|
import { makeElement, effect, isBrowser, omit, overridable, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; |
|
import { writable } from 'svelte/store'; |
|
const defaults = { |
|
src: '', |
|
delayMs: 0, |
|
onLoadingStatusChange: undefined, |
|
}; |
|
export const createAvatar = (props) => { |
|
const withDefaults = { ...defaults, ...props }; |
|
const options = toWritableStores(omit(withDefaults, 'loadingStatus', 'onLoadingStatusChange')); |
|
const { src, delayMs } = options; |
|
const loadingStatusWritable = withDefaults.loadingStatus ?? writable('loading'); |
|
const loadingStatus = overridable(loadingStatusWritable, withDefaults?.onLoadingStatusChange); |
|
effect([src, delayMs], ([$src, $delayMs]) => { |
|
if (isBrowser) { |
|
const image = new Image(); |
|
image.src = $src; |
|
image.onload = () => { |
|
if (delayMs !== undefined) { |
|
const timerId = window.setTimeout(() => { |
|
loadingStatus.set('loaded'); |
|
}, $delayMs); |
|
return () => window.clearTimeout(timerId); |
|
} |
|
else { |
|
loadingStatus.set('loaded'); |
|
} |
|
}; |
|
image.onerror = () => { |
|
loadingStatus.set('error'); |
|
}; |
|
} |
|
}); |
|
const image = makeElement('avatar-image', { |
|
stores: [src, loadingStatus], |
|
returned: ([$src, $loadingStatus]) => { |
|
const imageStyles = styleToString({ |
|
display: $loadingStatus === 'loaded' ? 'block' : 'none', |
|
}); |
|
return { |
|
src: $src, |
|
style: imageStyles, |
|
}; |
|
}, |
|
}); |
|
const fallback = makeElement('avatar-fallback', { |
|
stores: [loadingStatus], |
|
returned: ([$loadingStatus]) => { |
|
return { |
|
style: $loadingStatus === 'loaded' |
|
? styleToString({ |
|
display: 'none', |
|
}) |
|
: undefined, |
|
hidden: $loadingStatus === 'loaded' ? true : undefined, |
|
}; |
|
}, |
|
}); |
|
return { |
|
elements: { |
|
image, |
|
fallback, |
|
}, |
|
states: { |
|
loadingStatus, |
|
}, |
|
options, |
|
}; |
|
}; |
|
|