UNPKG

melt

Version:

The next generation of Melt UI. Built for Svelte 5.

52 lines (51 loc) 1.72 kB
import { extract } from "../utils/extract"; import { createDataIds } from "../utils/identifiers"; import { styleAttr } from "../utils/attribute"; import { inBrowser } from "../utils/browser"; import { watch } from "runed"; const identifiers = createDataIds("avatar", ["image", "fallback"]); export class Avatar { /* Props */ #props; src = $derived(extract(this.#props.src, "")); delayMs = $derived(extract(this.#props.delayMs, 0)); /* State */ #loadingStatus = $state("loading"); constructor(props = {}) { $effect(() => { this.#props.onLoadingStatusChange?.(this.#loadingStatus); }); watch(() => this.src, () => { this.#loadingStatus = "loading"; }); this.#props = props; } get loadingStatus() { return this.#loadingStatus; } get image() { return { [identifiers.image]: "", src: this.src, style: styleAttr({ display: this.#loadingStatus === "loaded" ? "block" : "none" }), onload: () => { if (!inBrowser()) return; const timerId = window.setTimeout(() => { this.#loadingStatus = "loaded"; }, this.delayMs); return () => window.clearTimeout(timerId); }, onerror: () => { this.#loadingStatus = "error"; }, }; } get fallback() { return { [identifiers.fallback]: "", style: this.#loadingStatus === "loaded" ? styleAttr({ display: "none" }) : undefined, hidden: this.#loadingStatus === "loaded" ? true : undefined, }; } }