@vielzeug/refine 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion-item.cjs +1 -1
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js +1 -1
- package/dist/accordion-item.js.map +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/chat-message.cjs +1 -1
- package/dist/chat-message.cjs.map +1 -1
- package/dist/chat-message.js +1 -1
- package/dist/chat-message.js.map +1 -1
- package/dist/combobox.cjs +9 -7
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +55 -48
- package/dist/combobox.js.map +1 -1
- package/dist/content/index.d.ts +2 -0
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/list/list-item.css.cjs +1 -1
- package/dist/content/list/list-item.css.cjs.map +1 -1
- package/dist/content/list/list-item.css.js +1 -1
- package/dist/content/list/list-item.css.js.map +1 -1
- package/dist/content/list/list-item.d.ts +9 -0
- package/dist/content/list/list-item.d.ts.map +1 -1
- package/dist/content/stats/stats.css.cjs +2 -0
- package/dist/content/stats/stats.css.cjs.map +1 -0
- package/dist/content/stats/stats.css.js +6 -0
- package/dist/content/stats/stats.css.js.map +1 -0
- package/dist/content/stats/stats.d.ts +72 -0
- package/dist/content/stats/stats.d.ts.map +1 -0
- package/dist/core/auto-resize.cjs +1 -1
- package/dist/core/auto-resize.cjs.map +1 -1
- package/dist/core/auto-resize.js +1 -1
- package/dist/core/auto-resize.js.map +1 -1
- package/dist/custom-elements.json +5087 -4791
- package/dist/datagrid.cjs +199 -179
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +435 -321
- package/dist/datagrid.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.cjs +1 -1
- package/dist/disclosure/tab-item/tab-item.css.cjs.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.js +1 -1
- package/dist/disclosure/tab-item/tab-item.css.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts +3 -0
- package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
- package/dist/disclosure/tabs/tabs.css.js +1 -1
- package/dist/disclosure/tabs/tabs.css.js.map +1 -1
- package/dist/disclosure/tabs/tabs.d.ts +4 -0
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/frameworks/elements.d.ts +2 -1
- package/dist/icon.cjs +1 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +1 -1
- package/dist/icon.js.map +1 -1
- package/dist/input.cjs +5 -4
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +14 -8
- package/dist/input.js.map +1 -1
- package/dist/inputs/combobox/combobox-options.cjs +1 -1
- package/dist/inputs/combobox/combobox-options.cjs.map +1 -1
- package/dist/inputs/combobox/combobox-options.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox-options.js +1 -0
- package/dist/inputs/combobox/combobox-options.js.map +1 -1
- package/dist/inputs/combobox/combobox.css.cjs +1 -1
- package/dist/inputs/combobox/combobox.css.cjs.map +1 -1
- package/dist/inputs/combobox/combobox.css.js +1 -1
- package/dist/inputs/combobox/combobox.css.js.map +1 -1
- package/dist/inputs/combobox/combobox.d.ts +1 -0
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox.types.d.ts +7 -0
- package/dist/inputs/combobox/combobox.types.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.d.ts +17 -3
- package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.js +93 -70
- package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.js +1 -1
- package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +54 -4
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/index.d.ts +1 -1
- package/dist/inputs/index.d.ts.map +1 -1
- package/dist/inputs/input/input.css.cjs +1 -1
- package/dist/inputs/input/input.css.cjs.map +1 -1
- package/dist/inputs/input/input.css.js +1 -1
- package/dist/inputs/input/input.css.js.map +1 -1
- package/dist/inputs/input/input.d.ts +3 -0
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/select/select.css.cjs +1 -1
- package/dist/inputs/select/select.css.cjs.map +1 -1
- package/dist/inputs/select/select.css.js +1 -1
- package/dist/inputs/select/select.css.js.map +1 -1
- package/dist/inputs/select/select.d.ts +5 -0
- package/dist/inputs/select/select.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.d.ts +2 -0
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs.map +1 -1
- package/dist/layout/sidebar/sidebar.css.js +1 -1
- package/dist/layout/sidebar/sidebar.css.js.map +1 -1
- package/dist/layout/sidebar/sidebar.d.ts +8 -0
- package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
- package/dist/list-item.cjs +6 -5
- package/dist/list-item.cjs.map +1 -1
- package/dist/list-item.js +23 -17
- package/dist/list-item.js.map +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.cjs.map +1 -1
- package/dist/list.js +1 -1
- package/dist/list.js.map +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +1 -1
- package/dist/menu.js.map +1 -1
- package/dist/navbar.cjs +2 -2
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +7 -5
- package/dist/navbar.js.map +1 -1
- package/dist/navigation-menu.cjs +1 -1
- package/dist/navigation-menu.cjs.map +1 -1
- package/dist/navigation-menu.js +1 -1
- package/dist/navigation-menu.js.map +1 -1
- package/dist/overlay/popover/popover.css.cjs +1 -1
- package/dist/overlay/popover/popover.css.cjs.map +1 -1
- package/dist/overlay/popover/popover.css.js +1 -1
- package/dist/overlay/popover/popover.css.js.map +1 -1
- package/dist/overlay/popover/popover.d.ts +1 -0
- package/dist/overlay/popover/popover.d.ts.map +1 -1
- package/dist/overlay/shared/use-dialog.cjs +1 -1
- package/dist/overlay/shared/use-dialog.cjs.map +1 -1
- package/dist/overlay/shared/use-dialog.js +1 -1
- package/dist/overlay/shared/use-dialog.js.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.js +1 -1
- package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
- package/dist/popover.cjs.map +1 -1
- package/dist/popover.js.map +1 -1
- package/dist/radio.cjs +1 -1
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +10 -8
- package/dist/radio.js.map +1 -1
- package/dist/rating.cjs +1 -1
- package/dist/rating.cjs.map +1 -1
- package/dist/rating.js +1 -1
- package/dist/rating.js.map +1 -1
- package/dist/refine.cjs +372 -323
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +372 -323
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +402 -353
- package/dist/refine.js.map +1 -1
- package/dist/select.cjs +16 -14
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +118 -112
- package/dist/select.js.map +1 -1
- package/dist/sidebar.cjs +28 -23
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +112 -77
- package/dist/sidebar.js.map +1 -1
- package/dist/slider.cjs +1 -1
- package/dist/slider.cjs.map +1 -1
- package/dist/slider.js +1 -1
- package/dist/slider.js.map +1 -1
- package/dist/stats.cjs +18 -0
- package/dist/stats.cjs.map +1 -0
- package/dist/stats.js +88 -0
- package/dist/stats.js.map +1 -0
- package/dist/stepper.cjs +1 -1
- package/dist/stepper.cjs.map +1 -1
- package/dist/stepper.js +1 -1
- package/dist/stepper.js.map +1 -1
- package/dist/styles/mixins/animation.css.cjs +2 -0
- package/dist/styles/mixins/animation.css.cjs.map +1 -1
- package/dist/styles/mixins/animation.css.d.ts.map +1 -1
- package/dist/styles/mixins/animation.css.js +2 -0
- package/dist/styles/mixins/animation.css.js.map +1 -1
- package/dist/tab-item.cjs +1 -1
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +3 -2
- package/dist/tab-item.js.map +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js +3 -1
- package/dist/tabs.js.map +1 -1
- package/dist/toast.cjs.map +1 -1
- package/dist/toast.js.map +1 -1
- package/package.json +64 -56
package/dist/toast.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.cjs","names":["#entries","#listeners","#eventListeners","#disposed","#max","#setEntries","#emit","#entry","#update","#scheduleTimer","#clearTimer"],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { createPanGesture, type PanGesture } from '@vielzeug/gesture';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout). */\n horizontal?: boolean;\n /** Auto-generated when omitted. */\n id?: string;\n message: string;\n /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n meta?: string;\n /** Called after the toast is fully dismissed and removed. */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n * default; all other toasts are polite.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n exitTimeoutId: ReturnType<typeof setTimeout> | null;\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\ntype ToastStoreEvent = {\n id: string;\n type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n readonly #entries = signal<ToastEntry[]>([]);\n readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n #disposed = false;\n #max = 5;\n\n add(item: ToastItem): string {\n if (this.#disposed) return item.id ?? uuid();\n\n const id = item.id ?? uuid();\n const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n const overflow = active.length - (this.#max - 1);\n\n if (overflow > 0) {\n for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n exitTimeoutId: null,\n id,\n phase: 'entering',\n timer: null,\n };\n\n this.#setEntries([...this.#entries.value, entry]);\n this.#emit({ id, type: 'add' });\n\n requestAnimationFrame(() => {\n if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n return id;\n }\n\n clear(): void {\n for (const entry of this.#entries.value) {\n if (entry.phase !== 'exiting') this.dismiss(entry.id);\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n\n this.#disposed = true;\n\n for (const entry of this.#entries.value) {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n }\n\n this.#setEntries([]);\n this.#listeners.clear();\n this.#eventListeners.clear();\n }\n\n dismiss(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n }\n\n finalize(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n entry.onDismiss?.();\n this.#emit({ id, type: 'dismiss' });\n }\n\n pauseTimers(): void {\n if (this.#disposed) return;\n\n this.#setEntries(\n this.#entries.value.map((entry) => {\n if (!entry.timer) return entry;\n\n clearTimeout(entry.timer.timeoutId);\n\n return {\n ...entry,\n timer: {\n ...entry.timer,\n remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n },\n };\n }),\n );\n }\n\n resumeTimers(): void {\n if (this.#disposed) return;\n\n for (const entry of this.#entries.value) {\n if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n this.#scheduleTimer(entry.id, entry.timer.remaining);\n }\n }\n }\n\n scheduleFinalization(id: string, delay: number): void {\n const entry = this.#entry(id);\n\n if (entry?.phase !== 'exiting' || this.#disposed) return;\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n this.#update(id, { exitTimeoutId });\n }\n\n setMax(max: number | undefined): void {\n if (max != null) this.#max = Math.max(1, max);\n }\n\n subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n listener(this.#entries.value);\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n this.#eventListeners.add(listener);\n\n return () => this.#eventListeners.delete(listener);\n }\n\n update(id: string, updates: Partial<ToastItem>): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n this.#update(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n }\n\n #clearTimer(entry: ToastEntry): ToastEntry {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n }\n\n #emit(event: ToastStoreEvent): void {\n for (const listener of this.#eventListeners) listener(event);\n }\n\n #entry(id: string): ToastEntry | undefined {\n return this.#entries.value.find((entry) => entry.id === id);\n }\n\n #scheduleTimer(id: string, remaining: number): void {\n if (remaining <= 0 || this.#disposed) return;\n\n const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n }\n\n #setEntries(entries: ToastEntry[]): void {\n this.#entries.value = entries;\n for (const listener of this.#listeners) listener(entries);\n }\n\n #update(id: string, patch: Partial<ToastEntry>): void {\n this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n }\n}\n\ntype ToastHostBinding = {\n bind: (store: ToastStore) => void;\n unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n hostStores.set(host, store);\n hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n dismiss();\n }}>\n ${action.label}\n </ore-button>\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup() {\n const el = getHost() as HTMLElement;\n const emit = useEmit<OreToastEvents>();\n const containerRef = ref<HTMLDivElement>();\n const entries = signal<ToastEntry[]>([]);\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n const swipeControls = new Map<string, { element: HTMLElement; gesture: PanGesture }>();\n const exiting = new Map<string, () => void>();\n const swiping = new Set<string>();\n let pendingSyncFrame: number | undefined;\n let store: ToastStore | null = null;\n let unsubscribeEntries = () => {};\n let unsubscribeEvents = () => {};\n\n const getInner = (wrapper: HTMLElement): HTMLElement | null => {\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n const clearExitListener = (id: string): void => {\n exiting.get(id)?.();\n exiting.delete(id);\n };\n\n const finalizeSwipe = (id: string): void => {\n swiping.delete(id);\n store?.finalize(id);\n };\n\n const createToastSwipe = (id: string, wrapper: HTMLElement): PanGesture => {\n const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n const reset = (): void => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n };\n\n return createPanGesture(wrapper, {\n axis: 'x',\n disabled: () => !isDismissible(),\n onEnd: ({ distance, reason }) => {\n if (reason !== 'release' || Math.abs(distance) < 48) {\n reset();\n\n return;\n }\n\n const inner = getInner(wrapper);\n\n if (!inner || !store) return;\n\n swiping.add(id);\n\n store.dismiss(id);\n\n const finish = () => finalizeSwipe(id);\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n const direction = distance >= 0 ? 1 : -1;\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${direction * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (transition: TransitionEvent) => {\n if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n };\n\n inner.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, 300);\n },\n onMove: ({ distance }) => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n pointerCapture: false,\n shouldStart: (event) =>\n !event\n .composedPath()\n .some((node) => node instanceof Element && node.matches('button, a, input, select, textarea, ore-button')),\n });\n };\n\n const beginExit = (id: string): void => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n requestAnimationFrame(() => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n if (!inner) {\n store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n return;\n }\n\n void inner.offsetHeight;\n\n const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n const onTransitionEnd = (event: TransitionEvent) => {\n const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n clearExitListener(id);\n store?.finalize(id);\n };\n const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n exiting.set(id, remove);\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, exitMs + 50);\n });\n };\n\n const syncControls = (): void => {\n const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n for (const [id, control] of swipeControls) {\n if (!currentIds.has(id)) {\n control.gesture.dispose();\n\n swipeControls.delete(id);\n clearExitListener(id);\n swiping.delete(id);\n }\n }\n\n for (const entry of entries.value) {\n const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${entry.id}\"]`);\n const control = swipeControls.get(entry.id);\n\n if (wrapper && control?.element !== wrapper) {\n control?.gesture.dispose();\n swipeControls.set(entry.id, { element: wrapper, gesture: createToastSwipe(entry.id, wrapper) });\n }\n\n if (entry.phase === 'exiting') beginExit(entry.id);\n }\n };\n\n const scheduleSyncControls = (): void => {\n syncControls();\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n pendingSyncFrame = requestAnimationFrame(() => {\n pendingSyncFrame = undefined;\n syncControls();\n });\n };\n\n watch(entries, scheduleSyncControls);\n watch(paused, (isPaused) => {\n if (isPaused) store?.pauseTimers();\n else store?.resumeTimers();\n });\n\n const bind = (nextStore: ToastStore): void => {\n if (store === nextStore) return;\n\n unsubscribeEntries();\n\n unsubscribeEvents();\n store = nextStore;\n unsubscribeEntries = store.subscribe((nextEntries) => {\n entries.value = nextEntries;\n });\n unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n if (paused.value) store.pauseTimers();\n };\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => store?.dismiss(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\">\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible}\n @dismiss=${dismiss}>\n ${\n entry.meta\n ? html`\n <span slot=\"meta\">${entry.meta}</span>\n `\n : ''\n }\n ${entry.message} ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n onMounted(() => {\n hostBindings.set(el, {\n bind,\n unbind() {\n unsubscribeEntries();\n unsubscribeEvents();\n store = null;\n entries.value = [];\n },\n });\n\n const boundStore = hostStores.get(el);\n\n if (boundStore) bind(boundStore);\n });\n\n onCleanup(() => {\n hostBindings.get(el)?.unbind();\n\n hostBindings.delete(el);\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n for (const control of swipeControls.values()) control.gesture.dispose();\n swipeControls.clear();\n for (const id of exiting.keys()) clearExitListener(id);\n });\n\n const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n add(item: ToastItem): string;\n clear(): void;\n configure(config: ToastServiceConfig): void;\n dismiss(id: string): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n error(message: string, opts?: Partial<ToastItem>): string;\n info(message: string, opts?: Partial<ToastItem>): string;\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n success(message: string, opts?: Partial<ToastItem>): string;\n update(id: string, updates: Partial<ToastItem>): void;\n warning(message: string, opts?: Partial<ToastItem>): string;\n [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n const existing = services.get(root);\n\n if (existing) return existing;\n\n const store = new ToastStore();\n const disposalController = new AbortController();\n let disposed = false;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n let host: HTMLElement | null = null;\n\n const assertActive = (): boolean => !disposed;\n const rootNode = root as Element | Document | ShadowRoot;\n const getHost = (): HTMLElement | null => {\n if (!assertActive()) return null;\n\n if (host?.isConnected) return host;\n\n host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n if (!host) {\n host = document.createElement(TOAST_TAG);\n\n if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n rootNode.appendChild(host);\n }\n\n if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n else {\n const max = Number(host.getAttribute('max'));\n\n if (Number.isFinite(max) && max > 0) store.setMax(max);\n }\n\n pendingConfig = null;\n configured = true;\n bindToastHost(host, store);\n\n return host;\n };\n const ensureHost = (): boolean => Boolean(getHost());\n\n const service: ToastService = {\n add(item) {\n if (!ensureHost()) return item.id ?? uuid();\n\n return store.add(item);\n },\n\n clear() {\n if (ensureHost()) store.clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n if (ensureHost()) store.dismiss(id);\n },\n\n get disposalSignal() {\n return disposalController.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n\n disposalController.abort();\n\n store.dispose();\n\n if (services.get(root) === service) services.delete(root);\n },\n\n get disposed() {\n return disposed;\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n [Symbol.dispose]() {\n service.dispose();\n },\n\n update(id, updates) {\n if (ensureHost()) store.update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n services.set(root, service);\n\n return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toast.cjs","names":[],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { createPanGesture, type PanGesture } from '@vielzeug/gesture';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout). */\n horizontal?: boolean;\n /** Auto-generated when omitted. */\n id?: string;\n message: string;\n /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n meta?: string;\n /** Called after the toast is fully dismissed and removed. */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n * default; all other toasts are polite.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n exitTimeoutId: ReturnType<typeof setTimeout> | null;\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\ntype ToastStoreEvent = {\n id: string;\n type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n readonly #entries = signal<ToastEntry[]>([]);\n readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n #disposed = false;\n #max = 5;\n\n add(item: ToastItem): string {\n if (this.#disposed) return item.id ?? uuid();\n\n const id = item.id ?? uuid();\n const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n const overflow = active.length - (this.#max - 1);\n\n if (overflow > 0) {\n for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n exitTimeoutId: null,\n id,\n phase: 'entering',\n timer: null,\n };\n\n this.#setEntries([...this.#entries.value, entry]);\n this.#emit({ id, type: 'add' });\n\n requestAnimationFrame(() => {\n if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n return id;\n }\n\n clear(): void {\n for (const entry of this.#entries.value) {\n if (entry.phase !== 'exiting') this.dismiss(entry.id);\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n\n this.#disposed = true;\n\n for (const entry of this.#entries.value) {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n }\n\n this.#setEntries([]);\n this.#listeners.clear();\n this.#eventListeners.clear();\n }\n\n dismiss(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n }\n\n finalize(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n entry.onDismiss?.();\n this.#emit({ id, type: 'dismiss' });\n }\n\n pauseTimers(): void {\n if (this.#disposed) return;\n\n this.#setEntries(\n this.#entries.value.map((entry) => {\n if (!entry.timer) return entry;\n\n clearTimeout(entry.timer.timeoutId);\n\n return {\n ...entry,\n timer: {\n ...entry.timer,\n remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n },\n };\n }),\n );\n }\n\n resumeTimers(): void {\n if (this.#disposed) return;\n\n for (const entry of this.#entries.value) {\n if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n this.#scheduleTimer(entry.id, entry.timer.remaining);\n }\n }\n }\n\n scheduleFinalization(id: string, delay: number): void {\n const entry = this.#entry(id);\n\n if (entry?.phase !== 'exiting' || this.#disposed) return;\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n this.#update(id, { exitTimeoutId });\n }\n\n setMax(max: number | undefined): void {\n if (max != null) this.#max = Math.max(1, max);\n }\n\n subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n listener(this.#entries.value);\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n this.#eventListeners.add(listener);\n\n return () => this.#eventListeners.delete(listener);\n }\n\n update(id: string, updates: Partial<ToastItem>): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n this.#update(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n }\n\n #clearTimer(entry: ToastEntry): ToastEntry {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n }\n\n #emit(event: ToastStoreEvent): void {\n for (const listener of this.#eventListeners) listener(event);\n }\n\n #entry(id: string): ToastEntry | undefined {\n return this.#entries.value.find((entry) => entry.id === id);\n }\n\n #scheduleTimer(id: string, remaining: number): void {\n if (remaining <= 0 || this.#disposed) return;\n\n const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n }\n\n #setEntries(entries: ToastEntry[]): void {\n this.#entries.value = entries;\n for (const listener of this.#listeners) listener(entries);\n }\n\n #update(id: string, patch: Partial<ToastEntry>): void {\n this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n }\n}\n\ntype ToastHostBinding = {\n bind: (store: ToastStore) => void;\n unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n hostStores.set(host, store);\n hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n dismiss();\n }}>\n ${action.label}\n </ore-button>\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup() {\n const el = getHost() as HTMLElement;\n const emit = useEmit<OreToastEvents>();\n const containerRef = ref<HTMLDivElement>();\n const entries = signal<ToastEntry[]>([]);\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n const swipeControls = new Map<string, { element: HTMLElement; gesture: PanGesture }>();\n const exiting = new Map<string, () => void>();\n const swiping = new Set<string>();\n let pendingSyncFrame: number | undefined;\n let store: ToastStore | null = null;\n let unsubscribeEntries = () => {};\n let unsubscribeEvents = () => {};\n\n const getInner = (wrapper: HTMLElement): HTMLElement | null => {\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n const clearExitListener = (id: string): void => {\n exiting.get(id)?.();\n exiting.delete(id);\n };\n\n const finalizeSwipe = (id: string): void => {\n swiping.delete(id);\n store?.finalize(id);\n };\n\n const createToastSwipe = (id: string, wrapper: HTMLElement): PanGesture => {\n const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n const reset = (): void => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n };\n\n return createPanGesture(wrapper, {\n axis: 'x',\n disabled: () => !isDismissible(),\n onEnd: ({ distance, reason }) => {\n if (reason !== 'release' || Math.abs(distance) < 48) {\n reset();\n\n return;\n }\n\n const inner = getInner(wrapper);\n\n if (!inner || !store) return;\n\n swiping.add(id);\n\n store.dismiss(id);\n\n const finish = () => finalizeSwipe(id);\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n const direction = distance >= 0 ? 1 : -1;\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${direction * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (transition: TransitionEvent) => {\n if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n };\n\n inner.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, 300);\n },\n onMove: ({ distance }) => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n pointerCapture: false,\n shouldStart: (event) =>\n !event\n .composedPath()\n .some((node) => node instanceof Element && node.matches('button, a, input, select, textarea, ore-button')),\n });\n };\n\n const beginExit = (id: string): void => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n requestAnimationFrame(() => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n if (!inner) {\n store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n return;\n }\n\n void inner.offsetHeight;\n\n const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n const onTransitionEnd = (event: TransitionEvent) => {\n const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n clearExitListener(id);\n store?.finalize(id);\n };\n const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n exiting.set(id, remove);\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, exitMs + 50);\n });\n };\n\n const syncControls = (): void => {\n const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n for (const [id, control] of swipeControls) {\n if (!currentIds.has(id)) {\n control.gesture.dispose();\n\n swipeControls.delete(id);\n clearExitListener(id);\n swiping.delete(id);\n }\n }\n\n for (const entry of entries.value) {\n const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${entry.id}\"]`);\n const control = swipeControls.get(entry.id);\n\n if (wrapper && control?.element !== wrapper) {\n control?.gesture.dispose();\n swipeControls.set(entry.id, { element: wrapper, gesture: createToastSwipe(entry.id, wrapper) });\n }\n\n if (entry.phase === 'exiting') beginExit(entry.id);\n }\n };\n\n const scheduleSyncControls = (): void => {\n syncControls();\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n pendingSyncFrame = requestAnimationFrame(() => {\n pendingSyncFrame = undefined;\n syncControls();\n });\n };\n\n watch(entries, scheduleSyncControls);\n watch(paused, (isPaused) => {\n if (isPaused) store?.pauseTimers();\n else store?.resumeTimers();\n });\n\n const bind = (nextStore: ToastStore): void => {\n if (store === nextStore) return;\n\n unsubscribeEntries();\n\n unsubscribeEvents();\n store = nextStore;\n unsubscribeEntries = store.subscribe((nextEntries) => {\n entries.value = nextEntries;\n });\n unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n if (paused.value) store.pauseTimers();\n };\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => store?.dismiss(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\">\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible}\n @dismiss=${dismiss}>\n ${\n entry.meta\n ? html`\n <span slot=\"meta\">${entry.meta}</span>\n `\n : ''\n }\n ${entry.message} ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n onMounted(() => {\n hostBindings.set(el, {\n bind,\n unbind() {\n unsubscribeEntries();\n unsubscribeEvents();\n store = null;\n entries.value = [];\n },\n });\n\n const boundStore = hostStores.get(el);\n\n if (boundStore) bind(boundStore);\n });\n\n onCleanup(() => {\n hostBindings.get(el)?.unbind();\n\n hostBindings.delete(el);\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n for (const control of swipeControls.values()) control.gesture.dispose();\n swipeControls.clear();\n for (const id of exiting.keys()) clearExitListener(id);\n });\n\n const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n add(item: ToastItem): string;\n clear(): void;\n configure(config: ToastServiceConfig): void;\n dismiss(id: string): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n error(message: string, opts?: Partial<ToastItem>): string;\n info(message: string, opts?: Partial<ToastItem>): string;\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n success(message: string, opts?: Partial<ToastItem>): string;\n update(id: string, updates: Partial<ToastItem>): void;\n warning(message: string, opts?: Partial<ToastItem>): string;\n [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n const existing = services.get(root);\n\n if (existing) return existing;\n\n const store = new ToastStore();\n const disposalController = new AbortController();\n let disposed = false;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n let host: HTMLElement | null = null;\n\n const assertActive = (): boolean => !disposed;\n const rootNode = root as Element | Document | ShadowRoot;\n const getHost = (): HTMLElement | null => {\n if (!assertActive()) return null;\n\n if (host?.isConnected) return host;\n\n host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n if (!host) {\n host = document.createElement(TOAST_TAG);\n\n if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n rootNode.appendChild(host);\n }\n\n if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n else {\n const max = Number(host.getAttribute('max'));\n\n if (Number.isFinite(max) && max > 0) store.setMax(max);\n }\n\n pendingConfig = null;\n configured = true;\n bindToastHost(host, store);\n\n return host;\n };\n const ensureHost = (): boolean => Boolean(getHost());\n\n const service: ToastService = {\n add(item) {\n if (!ensureHost()) return item.id ?? uuid();\n\n return store.add(item);\n },\n\n clear() {\n if (ensureHost()) store.clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n if (ensureHost()) store.dismiss(id);\n },\n\n get disposalSignal() {\n return disposalController.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n\n disposalController.abort();\n\n store.dispose();\n\n if (services.get(root) === service) services.delete(root);\n },\n\n get disposed() {\n return disposed;\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n [Symbol.dispose]() {\n service.dispose();\n },\n\n update(id, updates) {\n if (ensureHost()) store.update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n services.set(root, service);\n\n return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n"],"mappings":"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"}
|
package/dist/toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.js","names":["#entries","#listeners","#eventListeners","#disposed","#max","#setEntries","#emit","#entry","#update","#scheduleTimer","#clearTimer"],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { createPanGesture, type PanGesture } from '@vielzeug/gesture';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout). */\n horizontal?: boolean;\n /** Auto-generated when omitted. */\n id?: string;\n message: string;\n /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n meta?: string;\n /** Called after the toast is fully dismissed and removed. */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n * default; all other toasts are polite.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n exitTimeoutId: ReturnType<typeof setTimeout> | null;\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\ntype ToastStoreEvent = {\n id: string;\n type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n readonly #entries = signal<ToastEntry[]>([]);\n readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n #disposed = false;\n #max = 5;\n\n add(item: ToastItem): string {\n if (this.#disposed) return item.id ?? uuid();\n\n const id = item.id ?? uuid();\n const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n const overflow = active.length - (this.#max - 1);\n\n if (overflow > 0) {\n for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n exitTimeoutId: null,\n id,\n phase: 'entering',\n timer: null,\n };\n\n this.#setEntries([...this.#entries.value, entry]);\n this.#emit({ id, type: 'add' });\n\n requestAnimationFrame(() => {\n if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n return id;\n }\n\n clear(): void {\n for (const entry of this.#entries.value) {\n if (entry.phase !== 'exiting') this.dismiss(entry.id);\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n\n this.#disposed = true;\n\n for (const entry of this.#entries.value) {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n }\n\n this.#setEntries([]);\n this.#listeners.clear();\n this.#eventListeners.clear();\n }\n\n dismiss(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n }\n\n finalize(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n entry.onDismiss?.();\n this.#emit({ id, type: 'dismiss' });\n }\n\n pauseTimers(): void {\n if (this.#disposed) return;\n\n this.#setEntries(\n this.#entries.value.map((entry) => {\n if (!entry.timer) return entry;\n\n clearTimeout(entry.timer.timeoutId);\n\n return {\n ...entry,\n timer: {\n ...entry.timer,\n remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n },\n };\n }),\n );\n }\n\n resumeTimers(): void {\n if (this.#disposed) return;\n\n for (const entry of this.#entries.value) {\n if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n this.#scheduleTimer(entry.id, entry.timer.remaining);\n }\n }\n }\n\n scheduleFinalization(id: string, delay: number): void {\n const entry = this.#entry(id);\n\n if (entry?.phase !== 'exiting' || this.#disposed) return;\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n this.#update(id, { exitTimeoutId });\n }\n\n setMax(max: number | undefined): void {\n if (max != null) this.#max = Math.max(1, max);\n }\n\n subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n listener(this.#entries.value);\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n this.#eventListeners.add(listener);\n\n return () => this.#eventListeners.delete(listener);\n }\n\n update(id: string, updates: Partial<ToastItem>): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n this.#update(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n }\n\n #clearTimer(entry: ToastEntry): ToastEntry {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n }\n\n #emit(event: ToastStoreEvent): void {\n for (const listener of this.#eventListeners) listener(event);\n }\n\n #entry(id: string): ToastEntry | undefined {\n return this.#entries.value.find((entry) => entry.id === id);\n }\n\n #scheduleTimer(id: string, remaining: number): void {\n if (remaining <= 0 || this.#disposed) return;\n\n const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n }\n\n #setEntries(entries: ToastEntry[]): void {\n this.#entries.value = entries;\n for (const listener of this.#listeners) listener(entries);\n }\n\n #update(id: string, patch: Partial<ToastEntry>): void {\n this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n }\n}\n\ntype ToastHostBinding = {\n bind: (store: ToastStore) => void;\n unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n hostStores.set(host, store);\n hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n dismiss();\n }}>\n ${action.label}\n </ore-button>\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup() {\n const el = getHost() as HTMLElement;\n const emit = useEmit<OreToastEvents>();\n const containerRef = ref<HTMLDivElement>();\n const entries = signal<ToastEntry[]>([]);\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n const swipeControls = new Map<string, { element: HTMLElement; gesture: PanGesture }>();\n const exiting = new Map<string, () => void>();\n const swiping = new Set<string>();\n let pendingSyncFrame: number | undefined;\n let store: ToastStore | null = null;\n let unsubscribeEntries = () => {};\n let unsubscribeEvents = () => {};\n\n const getInner = (wrapper: HTMLElement): HTMLElement | null => {\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n const clearExitListener = (id: string): void => {\n exiting.get(id)?.();\n exiting.delete(id);\n };\n\n const finalizeSwipe = (id: string): void => {\n swiping.delete(id);\n store?.finalize(id);\n };\n\n const createToastSwipe = (id: string, wrapper: HTMLElement): PanGesture => {\n const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n const reset = (): void => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n };\n\n return createPanGesture(wrapper, {\n axis: 'x',\n disabled: () => !isDismissible(),\n onEnd: ({ distance, reason }) => {\n if (reason !== 'release' || Math.abs(distance) < 48) {\n reset();\n\n return;\n }\n\n const inner = getInner(wrapper);\n\n if (!inner || !store) return;\n\n swiping.add(id);\n\n store.dismiss(id);\n\n const finish = () => finalizeSwipe(id);\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n const direction = distance >= 0 ? 1 : -1;\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${direction * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (transition: TransitionEvent) => {\n if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n };\n\n inner.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, 300);\n },\n onMove: ({ distance }) => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n pointerCapture: false,\n shouldStart: (event) =>\n !event\n .composedPath()\n .some((node) => node instanceof Element && node.matches('button, a, input, select, textarea, ore-button')),\n });\n };\n\n const beginExit = (id: string): void => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n requestAnimationFrame(() => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n if (!inner) {\n store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n return;\n }\n\n void inner.offsetHeight;\n\n const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n const onTransitionEnd = (event: TransitionEvent) => {\n const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n clearExitListener(id);\n store?.finalize(id);\n };\n const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n exiting.set(id, remove);\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, exitMs + 50);\n });\n };\n\n const syncControls = (): void => {\n const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n for (const [id, control] of swipeControls) {\n if (!currentIds.has(id)) {\n control.gesture.dispose();\n\n swipeControls.delete(id);\n clearExitListener(id);\n swiping.delete(id);\n }\n }\n\n for (const entry of entries.value) {\n const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${entry.id}\"]`);\n const control = swipeControls.get(entry.id);\n\n if (wrapper && control?.element !== wrapper) {\n control?.gesture.dispose();\n swipeControls.set(entry.id, { element: wrapper, gesture: createToastSwipe(entry.id, wrapper) });\n }\n\n if (entry.phase === 'exiting') beginExit(entry.id);\n }\n };\n\n const scheduleSyncControls = (): void => {\n syncControls();\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n pendingSyncFrame = requestAnimationFrame(() => {\n pendingSyncFrame = undefined;\n syncControls();\n });\n };\n\n watch(entries, scheduleSyncControls);\n watch(paused, (isPaused) => {\n if (isPaused) store?.pauseTimers();\n else store?.resumeTimers();\n });\n\n const bind = (nextStore: ToastStore): void => {\n if (store === nextStore) return;\n\n unsubscribeEntries();\n\n unsubscribeEvents();\n store = nextStore;\n unsubscribeEntries = store.subscribe((nextEntries) => {\n entries.value = nextEntries;\n });\n unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n if (paused.value) store.pauseTimers();\n };\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => store?.dismiss(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\">\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible}\n @dismiss=${dismiss}>\n ${\n entry.meta\n ? html`\n <span slot=\"meta\">${entry.meta}</span>\n `\n : ''\n }\n ${entry.message} ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n onMounted(() => {\n hostBindings.set(el, {\n bind,\n unbind() {\n unsubscribeEntries();\n unsubscribeEvents();\n store = null;\n entries.value = [];\n },\n });\n\n const boundStore = hostStores.get(el);\n\n if (boundStore) bind(boundStore);\n });\n\n onCleanup(() => {\n hostBindings.get(el)?.unbind();\n\n hostBindings.delete(el);\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n for (const control of swipeControls.values()) control.gesture.dispose();\n swipeControls.clear();\n for (const id of exiting.keys()) clearExitListener(id);\n });\n\n const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n add(item: ToastItem): string;\n clear(): void;\n configure(config: ToastServiceConfig): void;\n dismiss(id: string): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n error(message: string, opts?: Partial<ToastItem>): string;\n info(message: string, opts?: Partial<ToastItem>): string;\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n success(message: string, opts?: Partial<ToastItem>): string;\n update(id: string, updates: Partial<ToastItem>): void;\n warning(message: string, opts?: Partial<ToastItem>): string;\n [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n const existing = services.get(root);\n\n if (existing) return existing;\n\n const store = new ToastStore();\n const disposalController = new AbortController();\n let disposed = false;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n let host: HTMLElement | null = null;\n\n const assertActive = (): boolean => !disposed;\n const rootNode = root as Element | Document | ShadowRoot;\n const getHost = (): HTMLElement | null => {\n if (!assertActive()) return null;\n\n if (host?.isConnected) return host;\n\n host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n if (!host) {\n host = document.createElement(TOAST_TAG);\n\n if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n rootNode.appendChild(host);\n }\n\n if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n else {\n const max = Number(host.getAttribute('max'));\n\n if (Number.isFinite(max) && max > 0) store.setMax(max);\n }\n\n pendingConfig = null;\n configured = true;\n bindToastHost(host, store);\n\n return host;\n };\n const ensureHost = (): boolean => Boolean(getHost());\n\n const service: ToastService = {\n add(item) {\n if (!ensureHost()) return item.id ?? uuid();\n\n return store.add(item);\n },\n\n clear() {\n if (ensureHost()) store.clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n if (ensureHost()) store.dismiss(id);\n },\n\n get disposalSignal() {\n return disposalController.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n\n disposalController.abort();\n\n store.dispose();\n\n if (services.get(root) === service) services.delete(root);\n },\n\n get disposed() {\n return disposed;\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n [Symbol.dispose]() {\n service.dispose();\n },\n\n update(id, updates) {\n if (ensureHost()) store.update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n services.set(root, service);\n\n return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n"],"mappings":";;;;;;;;AAWA,IAAM,IAAgB,KAqEhB,IAAN,MAAiB;CACf,KAAoB,EAAqB,CAAC,CAAC;CAC3C,qBAAsB,IAAI,IAAqC;CAC/D,qBAA2B,IAAI,IAAsC;CACrE,KAAY;CACZ,KAAO;CAEP,IAAI,GAAyB;EAC3B,IAAI,KAAKG,IAAW,OAAO,EAAK,MAAM,EAAK;EAE3C,IAAM,IAAK,EAAK,MAAM,EAAK,GACrB,IAAS,KAAKH,GAAS,MAAM,QAAQ,MAAU,EAAM,UAAU,SAAS,GACxE,IAAW,EAAO,UAAU,KAAKI,KAAO;EAE9C,IAAI,IAAW,GACb,KAAK,IAAM,KAAS,EAAO,MAAM,GAAG,CAAQ,GAAG,KAAK,QAAQ,EAAM,EAAE;EAGtE,IAAM,IAAoB;GACxB,aAAa;GACb,UAAU;GACV,GAAG;GACH,eAAe;GACf;GACA,OAAO;GACP,OAAO;EACT;EAWA,OATA,KAAKC,GAAY,CAAC,GAAG,KAAKL,GAAS,OAAO,CAAK,CAAC,GAChD,KAAKM,GAAM;GAAE;GAAI,MAAM;EAAM,CAAC,GAE9B,4BAA4B;GAC1B,AAAI,KAAKC,GAAO,CAAE,CAAC,EAAE,UAAU,cAAY,KAAKC,GAAQ,GAAI,EAAE,OAAO,SAAS,CAAC;EACjF,CAAC,GAEG,EAAM,WAAW,KAAG,KAAKC,GAAe,GAAI,EAAM,QAAQ,GAEvD;CACT;CAEA,QAAc;EACZ,KAAK,IAAM,KAAS,KAAKT,GAAS,OAChC,AAAI,EAAM,UAAU,aAAW,KAAK,QAAQ,EAAM,EAAE;CAExD;CAEA,UAAgB;EACV,UAAKG,IAET;QAAKA,KAAY;GAEjB,KAAK,IAAM,KAAS,KAAKH,GAAS,OAGhC,AAFI,EAAM,SAAO,aAAa,EAAM,MAAM,SAAS,GAE/C,EAAM,iBAAe,aAAa,EAAM,aAAa;GAK3D,AAFA,KAAKK,GAAY,CAAC,CAAC,GACnB,KAAKJ,GAAW,MAAM,GACtB,KAAKC,GAAgB,MAAM;EAVV;CAWnB;CAEA,QAAQ,GAAkB;EACxB,IAAM,IAAQ,KAAKK,GAAO,CAAE;EAExB,CAAC,KAAS,EAAM,UAAU,aAAa,KAAKJ,OAEhD,KAAKK,GAAQ,GAAI;GAAE,GAAG,KAAKE,GAAY,CAAK;GAAG,OAAO;EAAU,CAAC,GACjE,KAAK,qBAAqB,GAAI,GAAkB;CAClD;CAEA,SAAS,GAAkB;EACzB,IAAM,IAAQ,KAAKH,GAAO,CAAE;EAExB,CAAC,KAAS,KAAKJ,OAEf,EAAM,SAAO,aAAa,EAAM,MAAM,SAAS,GAE/C,EAAM,iBAAe,aAAa,EAAM,aAAa,GAEzD,KAAKE,GAAY,KAAKL,GAAS,MAAM,QAAQ,MAAc,EAAU,OAAO,CAAE,CAAC,GAC/E,EAAM,YAAY,GAClB,KAAKM,GAAM;GAAE;GAAI,MAAM;EAAU,CAAC;CACpC;CAEA,cAAoB;EACd,KAAKH,MAET,KAAKE,GACH,KAAKL,GAAS,MAAM,KAAK,MAClB,EAAM,SAEX,aAAa,EAAM,MAAM,SAAS,GAE3B;GACL,GAAG;GACH,OAAO;IACL,GAAG,EAAM;IACT,WAAW,KAAK,IAAI,GAAG,EAAM,MAAM,aAAa,KAAK,IAAI,IAAI,EAAM,MAAM,UAAU;GACrF;EACF,KAVyB,CAW1B,CACH;CACF;CAEA,eAAqB;EACf,UAAKG,IAET,KAAK,IAAM,KAAS,KAAKH,GAAS,OAChC,AAAI,EAAM,UAAU,YAAY,EAAM,SAAS,EAAM,MAAM,YAAY,KACrE,KAAKS,GAAe,EAAM,IAAI,EAAM,MAAM,SAAS;CAGzD;CAEA,qBAAqB,GAAY,GAAqB;EACpD,IAAM,IAAQ,KAAKF,GAAO,CAAE;EAE5B,IAAI,GAAO,UAAU,aAAa,KAAKJ,IAAW;EAElD,AAAI,EAAM,iBAAe,aAAa,EAAM,aAAa;EAEzD,IAAM,IAAgB,iBAAiB,KAAK,SAAS,CAAE,GAAG,CAAK;EAE/D,KAAKK,GAAQ,GAAI,EAAE,iBAAc,CAAC;CACpC;CAEA,OAAO,GAA+B;EACpC,AAAI,KAAO,SAAM,KAAKJ,KAAO,KAAK,IAAI,GAAG,CAAG;CAC9C;CAEA,UAAU,GAAuD;EAI/D,OAHA,EAAS,KAAKJ,GAAS,KAAK,GAC5B,KAAKC,GAAW,IAAI,CAAQ,SAEf,KAAKA,GAAW,OAAO,CAAQ;CAC9C;CAEA,gBAAgB,GAAwD;EAGtE,OAFA,KAAKC,GAAgB,IAAI,CAAQ,SAEpB,KAAKA,GAAgB,OAAO,CAAQ;CACnD;CAEA,OAAO,GAAY,GAAmC;EACpD,IAAM,IAAQ,KAAKK,GAAO,CAAE;EAE5B,IAAI,CAAC,KAAS,KAAKJ,IAAW;EAE9B,IAAM,IAAU,EAAQ,aAAa,KAAA,IAAsC,IAA1B,KAAKO,GAAY,CAAK;EAIvE,AAFA,KAAKF,GAAQ,GAAI;GAAE,GAAG;GAAS,GAAG;GAAS;EAAG,CAAC,GAE3C,EAAQ,aAAa,KAAA,KAAa,EAAQ,WAAW,KAAG,KAAKC,GAAe,GAAI,EAAQ,QAAQ;CACtG;CAEA,GAAY,GAA+B;EAGzC,OAFI,EAAM,SAAO,aAAa,EAAM,MAAM,SAAS,GAE5C;GAAE,GAAG;GAAO,OAAO;EAAK;CACjC;CAEA,GAAM,GAA8B;EAClC,KAAK,IAAM,KAAY,KAAKP,IAAiB,EAAS,CAAK;CAC7D;CAEA,GAAO,GAAoC;EACzC,OAAO,KAAKF,GAAS,MAAM,MAAM,MAAU,EAAM,OAAO,CAAE;CAC5D;CAEA,GAAe,GAAY,GAAyB;EAClD,IAAI,KAAa,KAAK,KAAKG,IAAW;EAEtC,IAAM,IAAY,iBAAiB,KAAK,QAAQ,CAAE,GAAG,CAAS;EAE9D,KAAKK,GAAQ,GAAI,EAAE,OAAO;GAAE;GAAW,WAAW,KAAK,IAAI;GAAG;EAAU,EAAE,CAAC;CAC7E;CAEA,GAAY,GAA6B;EACvC,KAAKR,GAAS,QAAQ;EACtB,KAAK,IAAM,KAAY,KAAKC,IAAY,EAAS,CAAO;CAC1D;CAEA,GAAQ,GAAY,GAAkC;EACpD,KAAKI,GAAY,KAAKL,GAAS,MAAM,KAAK,MAAW,EAAM,OAAO,IAAK;GAAE,GAAG;GAAO,GAAG;EAAM,IAAI,CAAM,CAAC;CACzG;AACF,GAOM,oBAAe,IAAI,QAAuC,GAC1D,oBAAa,IAAI,QAAiC,GAElD,KAAiB,GAAmB,MAA4B;CAEpE,AADA,EAAW,IAAI,GAAM,CAAK,GAC1B,EAAa,IAAI,CAAI,CAAC,EAAE,KAAK,CAAK;AACpC;AAGA,SAAS,EAAmB,GAAmB,GAAqB;CAGlE,OAFK,EAAM,SAAS,SAEb,CAAI;;QAEL,EAAM,QAAQ,KACb,MAAW,CAAI;;;oBAGJ,EAAO,SAAS,EAAM,SAAS,UAAU;sBACvC,EAAO,WAAW,QAAQ;2BACrB;EAEb,AADA,EAAO,UAAU,GACjB,EAAQ;CACV,EAAE;cACA,EAAO,MAAM;;SAGrB,EAAE;;MAjB6B;AAoBrC;AAEA,IAAa,IAAY;AAWzB,EAAsB,GAAW;CAC/B,OAAO;EACL,KAAK,EAAK,OAAO,CAAC;EAClB,UAAU,EAAK,MACb;GAAC;GAAY;GAAc;GAAa;GAAe;GAAiB;EAAc,GACtF,cACF;CACF;CACA,QAAQ;EACN,IAAM,IAAK,EAAQ,GACb,IAAO,EAAwB,GAC/B,IAAe,EAAoB,GACnC,IAAU,EAAqB,CAAC,CAAC,GACjC,IAAc,EAAO,EAAK,GAC1B,IAAc,EAAO,EAAK,GAC1B,IAAS,QAAe,EAAY,SAAS,EAAY,KAAK,GAC9D,oBAAgB,IAAI,IAA2D,GAC/E,oBAAU,IAAI,IAAwB,GACtC,oBAAU,IAAI,IAAY,GAC5B,GACA,IAA2B,MAC3B,UAA2B,CAAC,GAC5B,UAA0B,CAAC,GAEzB,KAAY,MACT,EAAQ,cAA2B,cAAc,GAGpD,KAAqB,MAAqB;GAE9C,AADA,EAAQ,IAAI,CAAE,CAAC,GAAG,GAClB,EAAQ,OAAO,CAAE;EACnB,GAEM,KAAiB,MAAqB;GAE1C,AADA,EAAQ,OAAO,CAAE,GACjB,GAAO,SAAS,CAAE;EACpB,GAEM,KAAoB,GAAY,MAAqC;GACzE,IAAM,UAA+B,EAAQ,MAAM,MAAM,MAAU,EAAM,OAAO,CAAE,CAAC,EAAE,eAAe,IAC9F,UAAoB;IACxB,IAAM,IAAQ,EAAS,CAAO;IAEzB,MAEL,EAAM,MAAM,aAAa,IACzB,EAAM,MAAM,YAAY,IACxB,EAAM,MAAM,UAAU;GACxB;GAEA,OAAO,EAAiB,GAAS;IAC/B,MAAM;IACN,gBAAgB,CAAC,EAAc;IAC/B,QAAQ,EAAE,aAAU,gBAAa;KAC/B,IAAI,MAAW,aAAa,KAAK,IAAI,CAAQ,IAAI,IAAI;MACnD,EAAM;MAEN;KACF;KAEA,IAAM,IAAQ,EAAS,CAAO;KAE9B,IAAI,CAAC,KAAS,CAAC,GAAO;KAItB,AAFA,EAAQ,IAAI,CAAE,GAEd,EAAM,QAAQ,CAAE;KAEhB,IAAM,UAAe,EAAc,CAAE;KAErC,IAAI,OAAO,WAAW,kCAAkC,CAAC,CAAC,SAAS;MAEjE,AADA,EAAM,MAAM,UAAU,KACtB,EAAO;MAEP;KACF;KAEA,IAAM,IAAY,KAAY,IAAI,IAAI;KAKtC,AAHA,EAAM,MAAM,aAAa,oDACzB,EAAW,aACX,EAAM,MAAM,YAAY,cAAc,IAAY,IAAI,KACtD,EAAM,MAAM,UAAU;KAEtB,IAAM,KAAmB,MAAgC;MACnD,EAAW,WAAW,KAAS,EAAW,iBAAiB,gBAE/D,EAAM,oBAAoB,iBAAiB,CAAe,GAC1D,EAAO;KACT;KAGA,AADA,EAAM,iBAAiB,iBAAiB,CAAe,GACvD,EAAM,qBAAqB,GAAI,GAAG;IACpC;IACA,SAAS,EAAE,kBAAe;KACxB,IAAM,IAAQ,EAAS,CAAO;KAEzB,MAEL,EAAM,MAAM,aAAa,QACzB,EAAM,MAAM,YAAY,cAAc,EAAS,MAC/C,EAAM,MAAM,UAAU,OAAO,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,CAAQ,IAAI,GAAG,CAAC;IACxE;IACA,gBAAgB;IAChB,cAAc,MACZ,CAAC,EACE,aAAa,CAAC,CACd,MAAM,MAAS,aAAgB,WAAW,EAAK,QAAQ,gDAAgD,CAAC;GAC/G,CAAC;EACH,GAEM,KAAa,MAAqB;GAClC,CAAC,KAAS,EAAQ,IAAI,CAAE,KAAK,EAAQ,IAAI,CAAE,KAE/C,4BAA4B;IAC1B,IAAI,CAAC,KAAS,EAAQ,IAAI,CAAE,KAAK,EAAQ,IAAI,CAAE,GAAG;IAElD,IAAM,IAAQ,EAAa,OAAO,cAA2B,mBAAmB,EAAG,gBAAgB;IAEnG,IAAI,CAAC,GAAO;KACV,EAAM,qBAAqB,GAAI,CAAa;KAE5C;IACF;IAEA,EAAW;IAEX,IAAM,IAAW,WAAW,iBAAiB,CAAK,CAAC,CAAC,kBAAkB,IAAI,KACpE,IAAS,OAAO,SAAS,CAAQ,KAAK,IAAW,IAAI,IAAW,GAChE,KAAmB,MAA2B;KACjC,EAAM,QAA+B,UAAU,mBAAmB,EAAG,GAAG,MAIzF,EAAkB,CAAE,GACpB,GAAO,SAAS,CAAE;IACpB;IAKA,AAFA,EAAQ,IAAI,SAFS,EAAa,OAAO,oBAAoB,iBAAiB,CAAe,CAEvE,GACtB,EAAa,OAAO,iBAAiB,iBAAiB,CAAe,GACrE,EAAM,qBAAqB,GAAI,IAAS,EAAE;GAC5C,CAAC;EACH,GAEM,UAA2B;GAC/B,IAAM,IAAa,IAAI,IAAI,EAAQ,MAAM,KAAK,MAAU,EAAM,EAAE,CAAC;GAEjE,KAAK,IAAM,CAAC,GAAI,MAAY,GAC1B,AAAK,EAAW,IAAI,CAAE,MACpB,EAAQ,QAAQ,QAAQ,GAExB,EAAc,OAAO,CAAE,GACvB,EAAkB,CAAE,GACpB,EAAQ,OAAO,CAAE;GAIrB,KAAK,IAAM,KAAS,EAAQ,OAAO;IACjC,IAAM,IAAU,EAAa,OAAO,cAA2B,mBAAmB,EAAM,GAAG,GAAG,GACxF,IAAU,EAAc,IAAI,EAAM,EAAE;IAO1C,AALI,KAAW,GAAS,YAAY,MAClC,GAAS,QAAQ,QAAQ,GACzB,EAAc,IAAI,EAAM,IAAI;KAAE,SAAS;KAAS,SAAS,EAAiB,EAAM,IAAI,CAAO;IAAE,CAAC,IAG5F,EAAM,UAAU,aAAW,EAAU,EAAM,EAAE;GACnD;EACF;EAcA,AADA,EAAM,SAXmC;GAKvC,AAJA,EAAa,GAET,MAAqB,KAAA,KAAW,qBAAqB,CAAgB,GAEzE,IAAmB,4BAA4B;IAE7C,AADA,IAAmB,KAAA,GACnB,EAAa;GACf,CAAC;EACH,CAEmC,GACnC,EAAM,IAAS,MAAa;GAC1B,AAAI,IAAU,GAAO,YAAY,IAC5B,GAAO,aAAa;EAC3B,CAAC;EAED,IAAM,KAAQ,MAAgC;GACxC,MAAU,MAEd,EAAmB,GAEnB,EAAkB,GAClB,IAAQ,GACR,IAAqB,EAAM,WAAW,MAAgB;IACpD,EAAQ,QAAQ;GAClB,CAAC,GACD,IAAoB,EAAM,iBAAiB,MAAU,EAAK,EAAM,MAAM,EAAE,IAAI,EAAM,GAAG,CAAC,CAAC,GAEnF,EAAO,SAAO,EAAM,YAAY;EACtC,GAEM,KAAe,MAAsB;GACzC,IAAM,UAAgB,GAAO,QAAQ,EAAM,EAAE;GAE7C,OAAO,CAAI;;;0BAGS,EAAM,GAAG;;8BAEL,cAAc,EAAM,UAAU,WAA+B,KAApB,IAAI,EAAM,UAAe;;sBAE1E,EAAM,UAAU,EAAM,YAAY,cAAc,UAAU,WAAW;wBACnE,EAAM,WAAW,QAAQ;qBAC5B,EAAM,QAAQ,KAAK;wBAChB,EAAM,WAAW,KAAK;4BAClB,EAAM,WAAW;wBACrB,EAAM,WAAW,GAAG;6BACf,EAAM,YAAY;yBACtB,EAAQ;gBAEjB,EAAM,OACF,CAAI;0CACkB,EAAM,KAAK;wBAEjC,GACL;gBACC,EAAM,QAAQ,GAAG,EAAmB,GAAO,CAAO,EAAE;;;;;EAKhE;EAkBA,AAhBA,QAAgB;GACd,EAAa,IAAI,GAAI;IACnB;IACA,SAAS;KAIP,AAHA,EAAmB,GACnB,EAAkB,GAClB,IAAQ,MACR,EAAQ,QAAQ,CAAC;IACnB;GACF,CAAC;GAED,IAAM,IAAa,EAAW,IAAI,CAAE;GAEpC,AAAI,KAAY,EAAK,CAAU;EACjC,CAAC,GAED,QAAgB;GAKd,AAJA,EAAa,IAAI,CAAE,CAAC,EAAE,OAAO,GAE7B,EAAa,OAAO,CAAE,GAElB,MAAqB,KAAA,KAAW,qBAAqB,CAAgB;GAEzE,KAAK,IAAM,KAAW,EAAc,OAAO,GAAG,EAAQ,QAAQ,QAAQ;GACtE,EAAc,MAAM;GACpB,KAAK,IAAM,KAAM,EAAQ,KAAK,GAAG,EAAkB,CAAE;EACvD,CAAC;EAED,IAAM,KAAa,MAAsB,EAAM,YAAY,EAAM,UAAU,UAAU,cAAc,WAC7F,IAAgB,QAAe,EAAQ,MAAM,QAAQ,MAAU,EAAU,CAAK,MAAM,QAAQ,CAAC,GAC7F,IAAmB,QAAe,EAAQ,MAAM,QAAQ,MAAU,EAAU,CAAK,MAAM,WAAW,CAAC;EAEzG,OAAO,CAAI;;;cAGD,EAAa;8BACG;GAEpB,AADA,EAAY,QAAQ,IACpB,EAAG,UAAU,IAAI,SAAS;EAC5B,EAAE;8BACoB;GAEpB,AADA,EAAY,QAAQ,IACpB,EAAG,UAAU,OAAO,SAAS;EAC/B,EAAE;yBACe;GACf,EAAY,QAAQ;EACtB,EAAE;0BACgB;GAChB,EAAY,QAAQ;EACtB,EAAE;;;;;;;;;kBASQ,EAAc,MAAM,IAAI,CAAW,EAAE;;;;;;;;;kBASrC,EAAiB,MAAM,IAAI,CAAW,EAAE;;;;;CAKxD;CACA,QAAQ,CAAC,GAAoB,CAAe;AAC9C,CAAC;AA4BD,IAAM,oBAAW,IAAI,QAAkC;AAOvD,SAAgB,EAAmB,IAAmB,SAAS,MAAoB;CACjF,IAAM,IAAW,EAAS,IAAI,CAAI;CAElC,IAAI,GAAU,OAAO;CAErB,IAAM,IAAQ,IAAI,EAAW,GACvB,IAAqB,IAAI,gBAAgB,GAC3C,IAAW,IACX,IAAa,IACb,IAA2C,MAC3C,IAA2B,MAEzB,UAA8B,CAAC,GAC/B,IAAW,GACX,UAAoC;EACxC,IAAI,CAAC,EAAa,GAAG,OAAO;EAE5B,IAAI,GAAM,aAAa,OAAO;EAc9B,IAZA,IAAO,EAAS,cAA2B,CAAS,GAE/C,MACH,IAAO,SAAS,cAAc,CAAS,GAEnC,GAAe,YAAU,EAAK,aAAa,YAAY,EAAc,QAAQ,GAE7E,GAAe,OAAO,QAAM,EAAK,aAAa,OAAO,OAAO,EAAc,GAAG,CAAC,GAElF,EAAS,YAAY,CAAI,IAGvB,GAAe,OAAO,MAAM,EAAM,OAAO,EAAc,GAAG;OACzD;GACH,IAAM,IAAM,OAAO,EAAK,aAAa,KAAK,CAAC;GAE3C,AAAI,OAAO,SAAS,CAAG,KAAK,IAAM,KAAG,EAAM,OAAO,CAAG;EACvD;EAMA,OAJA,IAAgB,MAChB,IAAa,IACb,EAAc,GAAM,CAAK,GAElB;CACT,GACM,UAA4B,EAAQ,EAAQ,GAE5C,IAAwB;EAC5B,IAAI,GAAM;GAGR,OAFK,EAAW,IAET,EAAM,IAAI,CAAI,IAFK,EAAK,MAAM,EAAK;EAG5C;EAEA,QAAQ;GACN,AAAI,EAAW,KAAG,EAAM,MAAM;EAChC;EAEA,UAAU,GAAQ;GACZ,MAMJ,IAAgB;IAAE,GAAG;IAAe,GAAG;GAAO;EAChD;EAEA,QAAQ,GAAI;GACV,AAAI,EAAW,KAAG,EAAM,QAAQ,CAAE;EACpC;EAEA,IAAI,iBAAiB;GACnB,OAAO,EAAmB;EAC5B;EAEA,UAAU;GACJ,MAEJ,IAAW,IAEX,EAAmB,MAAM,GAEzB,EAAM,QAAQ,GAEV,EAAS,IAAI,CAAI,MAAM,KAAS,EAAS,OAAO,CAAI;EAC1D;EAEA,IAAI,WAAW;GACb,OAAO;EACT;EAEA,MAAM,GAAS,GAAM;GACnB,OAAO,EAAQ,IAAI;IAAE,OAAO;IAAS,GAAG;IAAM;GAAQ,CAAC;EACzD;EAEA,KAAK,GAAS,GAAM;GAClB,OAAO,EAAQ,IAAI;IAAE,OAAO;IAAQ,GAAG;IAAM;GAAQ,CAAC;EACxD;EAEA,MAAM,QAAQ,GAAS,GAAU;GAC/B,IAAM,IAAK,EAAQ,IAAI;IAAE,OAAO;IAAW,aAAa;IAAO,UAAU;IAAG,SAAS,EAAS;GAAQ,CAAC;GAEvG,IAAI;IACF,IAAM,IAAO,MAAM;IASnB,OAPA,EAAQ,OAAO,GAAI;KACjB,OAAO;KACP,aAAa;KACb,UAAU;KACV,SAAS,OAAO,EAAS,WAAY,aAAa,EAAS,QAAQ,CAAI,IAAI,EAAS;IACtF,CAAC,GAEM;GACT,SAAS,GAAK;IAOZ,MANA,EAAQ,OAAO,GAAI;KACjB,OAAO;KACP,aAAa;KACb,UAAU;KACV,SAAS,OAAO,EAAS,SAAU,aAAa,EAAS,MAAM,CAAG,IAAI,EAAS;IACjF,CAAC,GACK;GACR;EACF;EAEA,QAAQ,GAAS,GAAM;GACrB,OAAO,EAAQ,IAAI;IAAE,OAAO;IAAW,GAAG;IAAM;GAAQ,CAAC;EAC3D;EAEA,CAAC,OAAO,WAAW;GACjB,EAAQ,QAAQ;EAClB;EAEA,OAAO,GAAI,GAAS;GAClB,AAAI,EAAW,KAAG,EAAM,OAAO,GAAI,CAAO;EAC5C;EAEA,QAAQ,GAAS,GAAM;GACrB,OAAO,EAAQ,IAAI;IAAE,OAAO;IAAW,GAAG;IAAM;GAAQ,CAAC;EAC3D;CACF;CAIA,OAFA,EAAS,IAAI,GAAM,CAAO,GAEnB;AACT;AAGA,IAAa,IAAsB,EAAmB"}
|
|
1
|
+
{"version":3,"file":"toast.js","names":[],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { createPanGesture, type PanGesture } from '@vielzeug/gesture';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout). */\n horizontal?: boolean;\n /** Auto-generated when omitted. */\n id?: string;\n message: string;\n /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n meta?: string;\n /** Called after the toast is fully dismissed and removed. */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n * default; all other toasts are polite.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n exitTimeoutId: ReturnType<typeof setTimeout> | null;\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\ntype ToastStoreEvent = {\n id: string;\n type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n readonly #entries = signal<ToastEntry[]>([]);\n readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n #disposed = false;\n #max = 5;\n\n add(item: ToastItem): string {\n if (this.#disposed) return item.id ?? uuid();\n\n const id = item.id ?? uuid();\n const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n const overflow = active.length - (this.#max - 1);\n\n if (overflow > 0) {\n for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n exitTimeoutId: null,\n id,\n phase: 'entering',\n timer: null,\n };\n\n this.#setEntries([...this.#entries.value, entry]);\n this.#emit({ id, type: 'add' });\n\n requestAnimationFrame(() => {\n if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n return id;\n }\n\n clear(): void {\n for (const entry of this.#entries.value) {\n if (entry.phase !== 'exiting') this.dismiss(entry.id);\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n\n this.#disposed = true;\n\n for (const entry of this.#entries.value) {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n }\n\n this.#setEntries([]);\n this.#listeners.clear();\n this.#eventListeners.clear();\n }\n\n dismiss(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n }\n\n finalize(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n entry.onDismiss?.();\n this.#emit({ id, type: 'dismiss' });\n }\n\n pauseTimers(): void {\n if (this.#disposed) return;\n\n this.#setEntries(\n this.#entries.value.map((entry) => {\n if (!entry.timer) return entry;\n\n clearTimeout(entry.timer.timeoutId);\n\n return {\n ...entry,\n timer: {\n ...entry.timer,\n remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n },\n };\n }),\n );\n }\n\n resumeTimers(): void {\n if (this.#disposed) return;\n\n for (const entry of this.#entries.value) {\n if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n this.#scheduleTimer(entry.id, entry.timer.remaining);\n }\n }\n }\n\n scheduleFinalization(id: string, delay: number): void {\n const entry = this.#entry(id);\n\n if (entry?.phase !== 'exiting' || this.#disposed) return;\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n this.#update(id, { exitTimeoutId });\n }\n\n setMax(max: number | undefined): void {\n if (max != null) this.#max = Math.max(1, max);\n }\n\n subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n listener(this.#entries.value);\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n this.#eventListeners.add(listener);\n\n return () => this.#eventListeners.delete(listener);\n }\n\n update(id: string, updates: Partial<ToastItem>): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n this.#update(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n }\n\n #clearTimer(entry: ToastEntry): ToastEntry {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n }\n\n #emit(event: ToastStoreEvent): void {\n for (const listener of this.#eventListeners) listener(event);\n }\n\n #entry(id: string): ToastEntry | undefined {\n return this.#entries.value.find((entry) => entry.id === id);\n }\n\n #scheduleTimer(id: string, remaining: number): void {\n if (remaining <= 0 || this.#disposed) return;\n\n const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n }\n\n #setEntries(entries: ToastEntry[]): void {\n this.#entries.value = entries;\n for (const listener of this.#listeners) listener(entries);\n }\n\n #update(id: string, patch: Partial<ToastEntry>): void {\n this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n }\n}\n\ntype ToastHostBinding = {\n bind: (store: ToastStore) => void;\n unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n hostStores.set(host, store);\n hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n dismiss();\n }}>\n ${action.label}\n </ore-button>\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup() {\n const el = getHost() as HTMLElement;\n const emit = useEmit<OreToastEvents>();\n const containerRef = ref<HTMLDivElement>();\n const entries = signal<ToastEntry[]>([]);\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n const swipeControls = new Map<string, { element: HTMLElement; gesture: PanGesture }>();\n const exiting = new Map<string, () => void>();\n const swiping = new Set<string>();\n let pendingSyncFrame: number | undefined;\n let store: ToastStore | null = null;\n let unsubscribeEntries = () => {};\n let unsubscribeEvents = () => {};\n\n const getInner = (wrapper: HTMLElement): HTMLElement | null => {\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n const clearExitListener = (id: string): void => {\n exiting.get(id)?.();\n exiting.delete(id);\n };\n\n const finalizeSwipe = (id: string): void => {\n swiping.delete(id);\n store?.finalize(id);\n };\n\n const createToastSwipe = (id: string, wrapper: HTMLElement): PanGesture => {\n const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n const reset = (): void => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n };\n\n return createPanGesture(wrapper, {\n axis: 'x',\n disabled: () => !isDismissible(),\n onEnd: ({ distance, reason }) => {\n if (reason !== 'release' || Math.abs(distance) < 48) {\n reset();\n\n return;\n }\n\n const inner = getInner(wrapper);\n\n if (!inner || !store) return;\n\n swiping.add(id);\n\n store.dismiss(id);\n\n const finish = () => finalizeSwipe(id);\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n const direction = distance >= 0 ? 1 : -1;\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${direction * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (transition: TransitionEvent) => {\n if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n };\n\n inner.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, 300);\n },\n onMove: ({ distance }) => {\n const inner = getInner(wrapper);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n pointerCapture: false,\n shouldStart: (event) =>\n !event\n .composedPath()\n .some((node) => node instanceof Element && node.matches('button, a, input, select, textarea, ore-button')),\n });\n };\n\n const beginExit = (id: string): void => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n requestAnimationFrame(() => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n if (!inner) {\n store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n return;\n }\n\n void inner.offsetHeight;\n\n const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n const onTransitionEnd = (event: TransitionEvent) => {\n const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n clearExitListener(id);\n store?.finalize(id);\n };\n const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n exiting.set(id, remove);\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, exitMs + 50);\n });\n };\n\n const syncControls = (): void => {\n const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n for (const [id, control] of swipeControls) {\n if (!currentIds.has(id)) {\n control.gesture.dispose();\n\n swipeControls.delete(id);\n clearExitListener(id);\n swiping.delete(id);\n }\n }\n\n for (const entry of entries.value) {\n const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${entry.id}\"]`);\n const control = swipeControls.get(entry.id);\n\n if (wrapper && control?.element !== wrapper) {\n control?.gesture.dispose();\n swipeControls.set(entry.id, { element: wrapper, gesture: createToastSwipe(entry.id, wrapper) });\n }\n\n if (entry.phase === 'exiting') beginExit(entry.id);\n }\n };\n\n const scheduleSyncControls = (): void => {\n syncControls();\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n pendingSyncFrame = requestAnimationFrame(() => {\n pendingSyncFrame = undefined;\n syncControls();\n });\n };\n\n watch(entries, scheduleSyncControls);\n watch(paused, (isPaused) => {\n if (isPaused) store?.pauseTimers();\n else store?.resumeTimers();\n });\n\n const bind = (nextStore: ToastStore): void => {\n if (store === nextStore) return;\n\n unsubscribeEntries();\n\n unsubscribeEvents();\n store = nextStore;\n unsubscribeEntries = store.subscribe((nextEntries) => {\n entries.value = nextEntries;\n });\n unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n if (paused.value) store.pauseTimers();\n };\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => store?.dismiss(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\">\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible}\n @dismiss=${dismiss}>\n ${\n entry.meta\n ? html`\n <span slot=\"meta\">${entry.meta}</span>\n `\n : ''\n }\n ${entry.message} ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n onMounted(() => {\n hostBindings.set(el, {\n bind,\n unbind() {\n unsubscribeEntries();\n unsubscribeEvents();\n store = null;\n entries.value = [];\n },\n });\n\n const boundStore = hostStores.get(el);\n\n if (boundStore) bind(boundStore);\n });\n\n onCleanup(() => {\n hostBindings.get(el)?.unbind();\n\n hostBindings.delete(el);\n\n if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n for (const control of swipeControls.values()) control.gesture.dispose();\n swipeControls.clear();\n for (const id of exiting.keys()) clearExitListener(id);\n });\n\n const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n add(item: ToastItem): string;\n clear(): void;\n configure(config: ToastServiceConfig): void;\n dismiss(id: string): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n error(message: string, opts?: Partial<ToastItem>): string;\n info(message: string, opts?: Partial<ToastItem>): string;\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n success(message: string, opts?: Partial<ToastItem>): string;\n update(id: string, updates: Partial<ToastItem>): void;\n warning(message: string, opts?: Partial<ToastItem>): string;\n [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n const existing = services.get(root);\n\n if (existing) return existing;\n\n const store = new ToastStore();\n const disposalController = new AbortController();\n let disposed = false;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n let host: HTMLElement | null = null;\n\n const assertActive = (): boolean => !disposed;\n const rootNode = root as Element | Document | ShadowRoot;\n const getHost = (): HTMLElement | null => {\n if (!assertActive()) return null;\n\n if (host?.isConnected) return host;\n\n host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n if (!host) {\n host = document.createElement(TOAST_TAG);\n\n if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n rootNode.appendChild(host);\n }\n\n if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n else {\n const max = Number(host.getAttribute('max'));\n\n if (Number.isFinite(max) && max > 0) store.setMax(max);\n }\n\n pendingConfig = null;\n configured = true;\n bindToastHost(host, store);\n\n return host;\n };\n const ensureHost = (): boolean => Boolean(getHost());\n\n const service: ToastService = {\n add(item) {\n if (!ensureHost()) return item.id ?? uuid();\n\n return store.add(item);\n },\n\n clear() {\n if (ensureHost()) store.clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n if (ensureHost()) store.dismiss(id);\n },\n\n get disposalSignal() {\n return disposalController.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n\n disposalController.abort();\n\n store.dispose();\n\n if (services.get(root) === service) services.delete(root);\n },\n\n get disposed() {\n return disposed;\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n [Symbol.dispose]() {\n service.dispose();\n },\n\n update(id, updates) {\n if (ensureHost()) store.update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n services.set(root, service);\n\n return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/refine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Accessible, themeable web components built on Ore custom element primitives",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -36,6 +36,39 @@
|
|
|
36
36
|
"require": "./dist/index.cjs",
|
|
37
37
|
"types": "./dist/index.d.ts"
|
|
38
38
|
},
|
|
39
|
+
"./styles/animation.css": {
|
|
40
|
+
"import": "./dist/styles/animation.css",
|
|
41
|
+
"default": "./dist/styles/animation.css"
|
|
42
|
+
},
|
|
43
|
+
"./styles/layers.css": {
|
|
44
|
+
"import": "./dist/styles/layer.css",
|
|
45
|
+
"default": "./dist/styles/layer.css"
|
|
46
|
+
},
|
|
47
|
+
"./styles/preflight.css": {
|
|
48
|
+
"import": "./dist/styles/preflight.css",
|
|
49
|
+
"default": "./dist/styles/preflight.css"
|
|
50
|
+
},
|
|
51
|
+
"./styles/theme.css": {
|
|
52
|
+
"import": "./dist/styles/theme.css",
|
|
53
|
+
"default": "./dist/styles/theme.css"
|
|
54
|
+
},
|
|
55
|
+
"./fouc.css": {
|
|
56
|
+
"import": "./dist/styles/fouc.css",
|
|
57
|
+
"default": "./dist/styles/fouc.css"
|
|
58
|
+
},
|
|
59
|
+
"./tokens.css": {
|
|
60
|
+
"import": "./dist/styles/tokens.css",
|
|
61
|
+
"default": "./dist/styles/tokens.css"
|
|
62
|
+
},
|
|
63
|
+
"./frameworks/elements": {
|
|
64
|
+
"types": "./dist/frameworks/elements.d.ts"
|
|
65
|
+
},
|
|
66
|
+
"./frameworks/react": {
|
|
67
|
+
"types": "./dist/frameworks/react.d.ts"
|
|
68
|
+
},
|
|
69
|
+
"./frameworks/vue": {
|
|
70
|
+
"types": "./dist/frameworks/vue.d.ts"
|
|
71
|
+
},
|
|
39
72
|
"./accordion": {
|
|
40
73
|
"import": "./dist/accordion.js",
|
|
41
74
|
"require": "./dist/accordion.cjs",
|
|
@@ -171,15 +204,6 @@
|
|
|
171
204
|
"require": "./dist/file-input.cjs",
|
|
172
205
|
"types": "./dist/inputs/file-input/file-input.d.ts"
|
|
173
206
|
},
|
|
174
|
-
"./frameworks/elements": {
|
|
175
|
-
"types": "./dist/frameworks/elements.d.ts"
|
|
176
|
-
},
|
|
177
|
-
"./frameworks/react": {
|
|
178
|
-
"types": "./dist/frameworks/react.d.ts"
|
|
179
|
-
},
|
|
180
|
-
"./frameworks/vue": {
|
|
181
|
-
"types": "./dist/frameworks/vue.d.ts"
|
|
182
|
-
},
|
|
183
207
|
"./grid": {
|
|
184
208
|
"import": "./dist/grid.js",
|
|
185
209
|
"require": "./dist/grid.cjs",
|
|
@@ -305,6 +329,11 @@
|
|
|
305
329
|
"require": "./dist/slider.cjs",
|
|
306
330
|
"types": "./dist/inputs/slider/slider.d.ts"
|
|
307
331
|
},
|
|
332
|
+
"./stats": {
|
|
333
|
+
"import": "./dist/stats.js",
|
|
334
|
+
"require": "./dist/stats.cjs",
|
|
335
|
+
"types": "./dist/content/stats/stats.d.ts"
|
|
336
|
+
},
|
|
308
337
|
"./step": {
|
|
309
338
|
"import": "./dist/step.js",
|
|
310
339
|
"require": "./dist/step.cjs",
|
|
@@ -315,26 +344,6 @@
|
|
|
315
344
|
"require": "./dist/stepper.cjs",
|
|
316
345
|
"types": "./dist/content/stepper/stepper.d.ts"
|
|
317
346
|
},
|
|
318
|
-
"./styles/animation.css": {
|
|
319
|
-
"default": "./dist/styles/animation.css",
|
|
320
|
-
"import": "./dist/styles/animation.css"
|
|
321
|
-
},
|
|
322
|
-
"./styles/layers.css": {
|
|
323
|
-
"default": "./dist/styles/layer.css",
|
|
324
|
-
"import": "./dist/styles/layer.css"
|
|
325
|
-
},
|
|
326
|
-
"./fouc.css": {
|
|
327
|
-
"default": "./dist/styles/fouc.css",
|
|
328
|
-
"import": "./dist/styles/fouc.css"
|
|
329
|
-
},
|
|
330
|
-
"./styles/preflight.css": {
|
|
331
|
-
"default": "./dist/styles/preflight.css",
|
|
332
|
-
"import": "./dist/styles/preflight.css"
|
|
333
|
-
},
|
|
334
|
-
"./styles/theme.css": {
|
|
335
|
-
"default": "./dist/styles/theme.css",
|
|
336
|
-
"import": "./dist/styles/theme.css"
|
|
337
|
-
},
|
|
338
347
|
"./switch": {
|
|
339
348
|
"import": "./dist/switch.js",
|
|
340
349
|
"require": "./dist/switch.cjs",
|
|
@@ -380,10 +389,6 @@
|
|
|
380
389
|
"require": "./dist/toast.cjs",
|
|
381
390
|
"types": "./dist/feedback/toast/toast.d.ts"
|
|
382
391
|
},
|
|
383
|
-
"./tokens.css": {
|
|
384
|
-
"default": "./dist/styles/tokens.css",
|
|
385
|
-
"import": "./dist/styles/tokens.css"
|
|
386
|
-
},
|
|
387
392
|
"./tooltip": {
|
|
388
393
|
"import": "./dist/tooltip.js",
|
|
389
394
|
"require": "./dist/tooltip.cjs",
|
|
@@ -397,6 +402,15 @@
|
|
|
397
402
|
},
|
|
398
403
|
"typesVersions": {
|
|
399
404
|
"*": {
|
|
405
|
+
"frameworks/elements": [
|
|
406
|
+
"dist/frameworks/elements.d.ts"
|
|
407
|
+
],
|
|
408
|
+
"frameworks/react": [
|
|
409
|
+
"dist/frameworks/react.d.ts"
|
|
410
|
+
],
|
|
411
|
+
"frameworks/vue": [
|
|
412
|
+
"dist/frameworks/vue.d.ts"
|
|
413
|
+
],
|
|
400
414
|
"accordion": [
|
|
401
415
|
"dist/disclosure/accordion/accordion.d.ts"
|
|
402
416
|
],
|
|
@@ -478,15 +492,6 @@
|
|
|
478
492
|
"file-input": [
|
|
479
493
|
"dist/inputs/file-input/file-input.d.ts"
|
|
480
494
|
],
|
|
481
|
-
"frameworks/elements": [
|
|
482
|
-
"dist/frameworks/elements.d.ts"
|
|
483
|
-
],
|
|
484
|
-
"frameworks/react": [
|
|
485
|
-
"dist/frameworks/react.d.ts"
|
|
486
|
-
],
|
|
487
|
-
"frameworks/vue": [
|
|
488
|
-
"dist/frameworks/vue.d.ts"
|
|
489
|
-
],
|
|
490
495
|
"grid": [
|
|
491
496
|
"dist/layout/grid/grid.d.ts"
|
|
492
497
|
],
|
|
@@ -562,6 +567,9 @@
|
|
|
562
567
|
"slider": [
|
|
563
568
|
"dist/inputs/slider/slider.d.ts"
|
|
564
569
|
],
|
|
570
|
+
"stats": [
|
|
571
|
+
"dist/content/stats/stats.d.ts"
|
|
572
|
+
],
|
|
565
573
|
"step": [
|
|
566
574
|
"dist/content/stepper/step.d.ts"
|
|
567
575
|
],
|
|
@@ -610,7 +618,7 @@
|
|
|
610
618
|
],
|
|
611
619
|
"scripts": {
|
|
612
620
|
"analyze": "custom-elements-manifest analyze --config scripts/refine-manifest.mjs",
|
|
613
|
-
"build": "pnpm run check:theme && pnpm run check:manifest && pnpm run check:css-contract && vite build && pnpm run build:bundle && cp -r src/styles/*.css dist/styles && pnpm run build:types && pnpm run analyze && pnpm run gen:framework-types",
|
|
621
|
+
"build": "pnpm --silent run check:theme && pnpm --silent run check:manifest && pnpm --silent run check:css-contract && vite build && pnpm --silent run build:bundle && cp -r src/styles/*.css dist/styles && pnpm --silent run build:types && pnpm --silent run analyze && pnpm --silent run gen:framework-types",
|
|
614
622
|
"build:bundle": "vite build --config vite.bundle.config.ts",
|
|
615
623
|
"build:bundle:watch": "vite build --watch --config vite.bundle.config.ts",
|
|
616
624
|
"build:types": "tsc -p tsconfig.declarations.json",
|
|
@@ -634,27 +642,27 @@
|
|
|
634
642
|
"@vielzeug/focus": "2.1.1",
|
|
635
643
|
"@vielzeug/gesture": "1.1.1",
|
|
636
644
|
"@vielzeug/keymap": "2.2.0",
|
|
637
|
-
"@vielzeug/orbit": "2.1.
|
|
638
|
-
"@vielzeug/ore": "2.
|
|
639
|
-
"@vielzeug/ripple": "2.
|
|
640
|
-
"@vielzeug/sentinel": "2.0.
|
|
641
|
-
"@vielzeug/tempo": "2.
|
|
642
|
-
"lucide": "^1.
|
|
645
|
+
"@vielzeug/orbit": "2.1.4",
|
|
646
|
+
"@vielzeug/ore": "2.2.0",
|
|
647
|
+
"@vielzeug/ripple": "2.3.0",
|
|
648
|
+
"@vielzeug/sentinel": "2.0.3",
|
|
649
|
+
"@vielzeug/tempo": "2.2.0",
|
|
650
|
+
"lucide": "^1.41.0"
|
|
643
651
|
},
|
|
644
652
|
"devDependencies": {
|
|
645
653
|
"@axe-core/playwright": "^4.13.0",
|
|
646
|
-
"@biomejs/biome": "2.5.
|
|
654
|
+
"@biomejs/biome": "^2.5.12",
|
|
647
655
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
648
|
-
"@playwright/test": "^1.
|
|
656
|
+
"@playwright/test": "^1.63.0",
|
|
649
657
|
"@types/culori": "^4.0.1",
|
|
650
|
-
"@types/node": "^26.
|
|
658
|
+
"@types/node": "^26.4.1",
|
|
651
659
|
"axe-core": "^4.13.0",
|
|
652
|
-
"browserslist": "^4.28.
|
|
660
|
+
"browserslist": "^4.28.9",
|
|
653
661
|
"culori": "^4.0.2",
|
|
654
662
|
"lightningcss": "^1.33.0",
|
|
655
663
|
"typescript": "^6.0.3",
|
|
656
|
-
"vite": "^8.2.
|
|
657
|
-
"vitest": "^
|
|
664
|
+
"vite": "^8.2.2",
|
|
665
|
+
"vitest": "^5.0.0"
|
|
658
666
|
},
|
|
659
667
|
"customElements": "dist/custom-elements.json"
|
|
660
668
|
}
|