@f-ewald/components 1.15.0 → 1.16.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.
@@ -1 +1 @@
1
- {"version":3,"file":"photo-gallery.js","sourceRoot":"","sources":["../src/photo-gallery.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, queryAssignedElements, state } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport type { GalleryItemVariant } from \"./gallery-item-variant.js\";\nimport { GalleryItem } from \"./gallery-item.js\";\nimport { iconChevronLeft, iconChevronRight } from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\nexport type PhotoGalleryObjectFit = \"cover\" | \"contain\";\nexport type PhotoGalleryChangeReason =\n | \"autoplay\"\n | \"indicator\"\n | \"items\"\n | \"keyboard\"\n | \"next\"\n | \"previous\"\n | \"programmatic\"\n | \"swipe\";\n\nexport interface PhotoGallerySlideChangeDetail {\n previousIndex: number;\n currentIndex: number;\n item: GalleryItem;\n reason: PhotoGalleryChangeReason;\n}\n\nconst transitionDurationMs = 250;\nconst swipeThresholdPx = 40;\nconst booleanAttribute = {\n fromAttribute(value: string | null): boolean {\n return value !== null && value !== \"false\";\n },\n};\n\n/**\n * Responsive, accessible image carousel composed from declarative\n * `gallery-item` children.\n *\n * @element photo-gallery\n * @slot - `gallery-item` elements rendered as slides.\n * @fires slide-change - The active image changed.\n */\n@customElement(\"photo-gallery\")\nexport class PhotoGallery extends LitElement {\n /** Zero-based active image index. */\n @property({ type: Number, attribute: \"current-index\", reflect: true })\n currentIndex = 0;\n\n /** Autoplay interval in milliseconds. Set to zero to disable autoplay. */\n @property({ type: Number }) delay = 0;\n\n /** Whether previous and next buttons are shown. */\n @property({ attribute: \"show-controls\", converter: booleanAttribute })\n showControls = true;\n\n /** Whether a current/total counter is shown. */\n @property({ type: Boolean, attribute: \"show-counter\" })\n showCounter = false;\n\n /** Whether clickable slide indicators are shown. */\n @property({ type: Boolean, attribute: \"show-indicators\" })\n showIndicators = false;\n\n /** Whether autoplay includes a built-in pause/play control. */\n @property({ attribute: \"show-autoplay-control\", converter: booleanAttribute })\n showAutoplayControl = true;\n\n /** Whether autoplay is explicitly paused. */\n @property({ type: Boolean, reflect: true })\n paused = false;\n\n /** CSS aspect ratio used by the image viewport. */\n @property({ attribute: \"aspect-ratio\" })\n aspectRatio = \"16 / 9\";\n\n /** How images fit within the stable viewport. */\n @property({ attribute: \"object-fit\" })\n objectFit: PhotoGalleryObjectFit = \"cover\";\n\n @queryAssignedElements({ selector: \"gallery-item\" })\n private readonly _galleryItems!: GalleryItem[];\n\n @state()\n private _previousIndex: number | null = null;\n\n @state()\n private _itemsVersion = 0;\n\n private _autoplayTimer?: number;\n private _transitionTimer?: number;\n private _metadataObserver?: MutationObserver;\n private _hovered = false;\n private _focusWithin = false;\n private _nextChangeReason: PhotoGalleryChangeReason | null = null;\n private _pendingChange?: PhotoGallerySlideChangeDetail;\n private _pointerStart?: { id: number; x: number; y: number };\n private _itemsChanged = false;\n private _activeItem?: GalleryItem;\n private _renderedIndex = 0;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n color: var(--ui-text, #0f172a);\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size, 0.875rem);\n }\n .gallery {\n outline: none;\n }\n figure {\n margin: 0;\n }\n .viewport {\n position: relative;\n overflow: hidden;\n aspect-ratio: var(--photo-gallery-aspect-ratio, 16 / 9);\n border-radius: var(--ui-radius, 0.5rem);\n background: var(--ui-surface-muted, #f8fafc);\n touch-action: pan-y;\n user-select: none;\n }\n .gallery:focus-visible .viewport {\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .slides {\n display: grid;\n width: 100%;\n height: 100%;\n }\n picture {\n grid-area: 1 / 1;\n display: block;\n width: 100%;\n height: 100%;\n }\n picture img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: var(--photo-gallery-object-fit, cover);\n }\n .entering {\n z-index: 2;\n animation: gallery-fade-in 250ms ease both;\n }\n .leaving {\n z-index: 1;\n pointer-events: none;\n animation: gallery-fade-out 250ms ease both;\n }\n .arrow-controls {\n position: absolute;\n z-index: 3;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem;\n pointer-events: none;\n }\n button {\n border: 0;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n cursor: pointer;\n }\n button:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .arrow-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n color: var(--ui-on-accent, #ffffff);\n background: var(--ui-overlay, rgb(15 23 42 / 0.45));\n border-radius: 9999px;\n pointer-events: auto;\n }\n .arrow-button:hover {\n background: color-mix(in srgb, var(--ui-text, #0f172a) 70%, transparent);\n }\n figcaption {\n padding: 0.5rem 0.25rem 0;\n color: var(--ui-text-muted, #64748b);\n }\n .footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n min-height: 2rem;\n padding-top: 0.5rem;\n }\n .counter {\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n white-space: nowrap;\n }\n .indicators {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n }\n .indicator {\n position: relative;\n width: 2rem;\n height: 2rem;\n padding: 0;\n background: transparent;\n border-radius: 9999px;\n }\n .indicator::before {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 0.625rem;\n height: 0.625rem;\n background: var(--ui-border, #e2e8f0);\n border-radius: 9999px;\n content: \"\";\n transform: translate(-50%, -50%);\n }\n .indicator[aria-current=\"true\"]::before {\n background: var(--ui-primary, #4f46e5);\n }\n .autoplay-button {\n height: 2rem;\n box-sizing: border-box;\n padding: 0.25rem 0.5rem;\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface-muted, #f8fafc);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n white-space: nowrap;\n }\n .autoplay-button:hover {\n background: var(--ui-surface, #ffffff);\n }\n slot {\n display: none;\n }\n @keyframes gallery-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes gallery-fade-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .entering,\n .leaving {\n animation: none;\n }\n }\n `,\n ];\n\n /** Starts observers and autoplay integration when the element connects. */\n override connectedCallback(): void {\n super.connectedCallback();\n this._metadataObserver ??= new MutationObserver(() => this._handleMetadataChange());\n this._metadataObserver.observe(this, {\n attributes: true,\n attributeFilter: [\"alt\", \"caption\", \"media\", \"src\", \"srcset\"],\n childList: true,\n subtree: true,\n });\n document.addEventListener(\"visibilitychange\", this._handleVisibilityChange);\n }\n\n /** Releases timers and observers when the element disconnects. */\n override disconnectedCallback(): void {\n this._clearAutoplay();\n this._clearTransition();\n this._metadataObserver?.disconnect();\n document.removeEventListener(\"visibilitychange\", this._handleVisibilityChange);\n super.disconnectedCallback();\n }\n\n /** Normalizes external index changes before rendering. */\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (!changed.has(\"currentIndex\")) return;\n\n const normalized = this._normalizeIndex(this.currentIndex);\n if (normalized !== this.currentIndex) {\n this.currentIndex = normalized;\n }\n\n const previousValue = changed.get(\"currentIndex\");\n if (previousValue === undefined || this._galleryItems.length === 0) {\n this._nextChangeReason = null;\n return;\n }\n\n const previousIndex = this._normalizeIndex(Number(previousValue));\n if (previousIndex === normalized) {\n this._nextChangeReason = null;\n return;\n }\n\n const reason = this._nextChangeReason ?? \"programmatic\";\n this._previousIndex = reason === \"items\" ? null : previousIndex;\n this._pendingChange = {\n previousIndex,\n currentIndex: normalized,\n item: this._galleryItems[normalized],\n reason,\n };\n this._nextChangeReason = null;\n }\n\n /** Emits completed changes and keeps autoplay synchronized with properties. */\n protected override updated(changed: PropertyValues<this>): void {\n if (this._pendingChange) {\n this.dispatchEvent(\n new CustomEvent<PhotoGallerySlideChangeDetail>(\"slide-change\", {\n bubbles: true,\n composed: true,\n detail: this._pendingChange,\n }),\n );\n this._pendingChange = undefined;\n this._scheduleTransitionCleanup();\n }\n\n if (changed.has(\"currentIndex\") || changed.has(\"delay\") || changed.has(\"paused\") || this._itemsChanged) {\n this._itemsChanged = false;\n this._restartAutoplay();\n }\n this._activeItem = this._galleryItems[this.currentIndex];\n this._renderedIndex = this.currentIndex;\n }\n\n /** Wraps any requested index into the current item range. */\n private _normalizeIndex(index: number): number {\n const count = this._galleryItems.length;\n if (count === 0 || !Number.isFinite(index)) return 0;\n return ((Math.trunc(index) % count) + count) % count;\n }\n\n /** Returns responsive variants declared directly under an item. */\n private _variantsFor(item: GalleryItem): GalleryItemVariant[] {\n return Array.from(item.children).filter(\n (child): child is GalleryItemVariant => child.tagName.toLowerCase() === \"gallery-item-variant\",\n );\n }\n\n /** Changes slides through the shared state and event path. */\n private _goTo(index: number, reason: PhotoGalleryChangeReason): void {\n const normalized = this._normalizeIndex(index);\n if (this._galleryItems.length < 2 || normalized === this.currentIndex) {\n this._restartAutoplay();\n return;\n }\n\n this._nextChangeReason = reason;\n this.currentIndex = normalized;\n }\n\n /** Moves to the previous image. */\n private _showPrevious(reason: PhotoGalleryChangeReason = \"previous\"): void {\n this._goTo(this.currentIndex - 1, reason);\n }\n\n /** Moves to the next image. */\n private _showNext(reason: PhotoGalleryChangeReason = \"next\"): void {\n this._goTo(this.currentIndex + 1, reason);\n }\n\n /** Toggles explicit autoplay pause state. */\n private _togglePaused(): void {\n this.paused = !this.paused;\n }\n\n /** Clears and conditionally schedules the next autoplay advance. */\n private _restartAutoplay(): void {\n this._clearAutoplay();\n if (!this._canAutoplay()) return;\n\n this._autoplayTimer = window.setTimeout(() => {\n this._showNext(\"autoplay\");\n }, this.delay);\n }\n\n /** Reports whether autoplay may currently schedule a transition. */\n private _canAutoplay(): boolean {\n return (\n this.delay > 0 &&\n this._galleryItems.length > 1 &&\n !this.paused &&\n !this._hovered &&\n !this._focusWithin &&\n !document.hidden\n );\n }\n\n /** Clears the pending autoplay timeout. */\n private _clearAutoplay(): void {\n if (this._autoplayTimer === undefined) return;\n window.clearTimeout(this._autoplayTimer);\n this._autoplayTimer = undefined;\n }\n\n /** Removes the outgoing crossfade layer after the animation completes. */\n private _scheduleTransitionCleanup(): void {\n this._clearTransition();\n this._transitionTimer = window.setTimeout(() => {\n this._previousIndex = null;\n this._transitionTimer = undefined;\n }, transitionDurationMs);\n }\n\n /** Clears pending transition cleanup. */\n private _clearTransition(): void {\n if (this._transitionTimer === undefined) return;\n window.clearTimeout(this._transitionTimer);\n this._transitionTimer = undefined;\n }\n\n /** Refreshes item metadata and clamps the active index after light-DOM changes. */\n private _handleMetadataChange(): void {\n this._itemsChanged = true;\n this._itemsVersion += 1;\n const preserveActiveItem = this.currentIndex === this._renderedIndex;\n const preservedIndex =\n preserveActiveItem && this._activeItem ? this._galleryItems.indexOf(this._activeItem) : -1;\n const normalized = preservedIndex >= 0 ? preservedIndex : this._normalizeIndex(this.currentIndex);\n if (normalized === this.currentIndex) {\n const item = this._galleryItems[normalized];\n const activeItemRemoved = Boolean(this._activeItem && !this._galleryItems.includes(this._activeItem));\n if (item && activeItemRemoved) {\n this._previousIndex = null;\n this._pendingChange = {\n previousIndex: this._renderedIndex,\n currentIndex: normalized,\n item,\n reason: \"items\",\n };\n }\n return;\n }\n this._nextChangeReason = \"items\";\n this.currentIndex = normalized;\n }\n\n /** Refreshes item state after the default slot changes. */\n private _handleSlotChange(): void {\n this._handleMetadataChange();\n }\n\n /** Temporarily pauses autoplay while the pointer is over the gallery. */\n private _handleMouseEnter(): void {\n this._hovered = true;\n this._restartAutoplay();\n }\n\n /** Resumes autoplay with a fresh delay after hover ends. */\n private _handleMouseLeave(): void {\n this._hovered = false;\n this._restartAutoplay();\n }\n\n /** Temporarily pauses autoplay while focus is inside the gallery. */\n private _handleFocusIn(): void {\n this._focusWithin = true;\n this._restartAutoplay();\n }\n\n /** Resumes autoplay with a fresh delay after focus leaves the gallery. */\n private _handleFocusOut(): void {\n queueMicrotask(() => {\n this._focusWithin = this.matches(\":focus-within\");\n this._restartAutoplay();\n });\n }\n\n /** Pauses or resumes scheduling when page visibility changes. */\n private readonly _handleVisibilityChange = (): void => {\n this._restartAutoplay();\n };\n\n /** Handles Left and Right arrow keyboard navigation. */\n private _handleKeyDown(event: KeyboardEvent): void {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n this._showPrevious(\"keyboard\");\n return;\n }\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n this._showNext(\"keyboard\");\n }\n }\n\n /** Records the starting point of a primary pointer gesture. */\n private _handlePointerDown(event: PointerEvent): void {\n if (!event.isPrimary || event.button !== 0) return;\n if (event.composedPath().some((target) => target instanceof HTMLButtonElement)) return;\n this._pointerStart = { id: event.pointerId, x: event.clientX, y: event.clientY };\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n }\n\n /** Converts a sufficiently horizontal pointer gesture into navigation. */\n private _handlePointerUp(event: PointerEvent): void {\n const start = this._pointerStart;\n this._pointerStart = undefined;\n if (!start || start.id !== event.pointerId) return;\n\n const deltaX = event.clientX - start.x;\n const deltaY = event.clientY - start.y;\n if (Math.abs(deltaX) < swipeThresholdPx || Math.abs(deltaX) <= Math.abs(deltaY)) return;\n\n event.preventDefault();\n if (deltaX < 0) {\n this._showNext(\"swipe\");\n return;\n }\n this._showPrevious(\"swipe\");\n }\n\n /** Cancels an incomplete pointer gesture. */\n private _handlePointerCancel(): void {\n this._pointerStart = undefined;\n }\n\n /** Renders one responsive image layer for the crossfade stack. */\n private _renderPicture(index: number, state: \"current\" | \"previous\") {\n const item = this._galleryItems[index];\n if (!item) return nothing;\n\n const isPrevious = state === \"previous\";\n const transitionClass = this._previousIndex === null ? \"\" : isPrevious ? \"leaving\" : \"entering\";\n return html`\n <picture class=${transitionClass} aria-hidden=${isPrevious ? \"true\" : nothing}>\n ${this._variantsFor(item)\n .filter((variant) => variant.srcset)\n .map(\n (variant) =>\n html`<source media=${ifDefined(variant.media || undefined)} srcset=${variant.srcset} />`,\n )}\n <img src=${item.src} alt=${isPrevious ? \"\" : item.alt} draggable=\"false\" />\n </picture>\n `;\n }\n\n /** Renders enabled counter, indicator, and autoplay controls. */\n private _renderFooter(itemCount: number) {\n const showIndicators = this.showIndicators && itemCount > 1;\n const showAutoplay = this.showAutoplayControl && this.delay > 0 && itemCount > 1;\n if (!this.showCounter && !showIndicators && !showAutoplay) return nothing;\n\n return html`\n <div class=\"footer\">\n ${this.showCounter\n ? html`<span class=\"counter\">${this.currentIndex + 1} / ${itemCount}</span>`\n : nothing}\n ${showIndicators\n ? html`\n <div class=\"indicators\" role=\"group\" aria-label=\"Choose image\">\n ${this._galleryItems.map(\n (_item, index) => html`\n <button\n class=\"indicator\"\n type=\"button\"\n aria-label=\"Show image ${index + 1} of ${itemCount}\"\n aria-current=${String(index === this.currentIndex)}\n @click=${() => this._goTo(index, \"indicator\")}\n ></button>\n `,\n )}\n </div>\n `\n : nothing}\n ${showAutoplay\n ? html`\n <button\n class=\"autoplay-button\"\n type=\"button\"\n aria-label=${this.paused ? \"Resume slideshow\" : \"Pause slideshow\"}\n @click=${this._togglePaused}\n >\n ${this.paused ? \"Play\" : \"Pause\"}\n </button>\n `\n : nothing}\n </div>\n `;\n }\n\n /** Renders the active image, navigation, caption, and hidden metadata slot. */\n protected override render() {\n const itemCount = this._galleryItems.length;\n const currentItem = this._galleryItems[this.currentIndex];\n const objectFit: PhotoGalleryObjectFit = this.objectFit === \"contain\" ? \"contain\" : \"cover\";\n const viewportStyles = {\n \"--photo-gallery-aspect-ratio\": this.aspectRatio.trim() || \"16 / 9\",\n \"--photo-gallery-object-fit\": objectFit,\n };\n\n return html`\n <div\n class=\"gallery\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label=\"Photo gallery\"\n tabindex=\"0\"\n @keydown=${this._handleKeyDown}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n @focusin=${this._handleFocusIn}\n @focusout=${this._handleFocusOut}\n >\n ${currentItem\n ? html`\n <figure>\n <div\n class=\"viewport\"\n style=${styleMap(viewportStyles)}\n @pointerdown=${this._handlePointerDown}\n @pointerup=${this._handlePointerUp}\n @pointercancel=${this._handlePointerCancel}\n >\n <div class=\"slides\">\n ${this._previousIndex === null\n ? nothing\n : this._renderPicture(this._previousIndex, \"previous\")}\n ${this._renderPicture(this.currentIndex, \"current\")}\n </div>\n ${this.showControls && itemCount > 1\n ? html`\n <div class=\"arrow-controls\">\n <button\n class=\"arrow-button previous\"\n type=\"button\"\n aria-label=\"Previous image\"\n @click=${() => this._showPrevious()}\n >\n ${iconChevronLeft(18)}\n </button>\n <button\n class=\"arrow-button next\"\n type=\"button\"\n aria-label=\"Next image\"\n @click=${() => this._showNext()}\n >\n ${iconChevronRight(18)}\n </button>\n </div>\n `\n : nothing}\n </div>\n ${currentItem.caption ? html`<figcaption>${currentItem.caption}</figcaption>` : nothing}\n </figure>\n ${this._renderFooter(itemCount)}\n `\n : nothing}\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"photo-gallery\": PhotoGallery;\n }\n}\n"]}
1
+ {"version":3,"file":"photo-gallery.js","sourceRoot":"","sources":["../src/photo-gallery.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, queryAssignedElements, state } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport type { GalleryItemVariant } from \"./gallery-item-variant.js\";\nimport { GalleryItem } from \"./gallery-item.js\";\nimport { iconChevronLeft, iconChevronRight } from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\nexport type PhotoGalleryObjectFit = \"cover\" | \"contain\";\nexport type PhotoGalleryChangeReason =\n | \"autoplay\"\n | \"indicator\"\n | \"items\"\n | \"keyboard\"\n | \"next\"\n | \"previous\"\n | \"programmatic\"\n | \"swipe\";\n\nexport interface PhotoGallerySlideChangeDetail {\n previousIndex: number;\n currentIndex: number;\n item: GalleryItem;\n reason: PhotoGalleryChangeReason;\n}\n\nconst transitionDurationMs = 250;\nconst swipeThresholdPx = 40;\nconst booleanAttribute = {\n fromAttribute(value: string | null): boolean {\n return value !== null && value !== \"false\";\n },\n};\n\n/**\n * Responsive, accessible image carousel composed from declarative\n * `gallery-item` children.\n *\n * The image viewport keeps a fixed `aspect-ratio`, and the caption row is\n * reserved for every slide whenever any slide has a caption, so the carousel's\n * total height stays constant as it cycles — it never shifts the page below it.\n *\n * @element photo-gallery\n * @slot - `gallery-item` elements rendered as slides.\n * @fires slide-change - The active image changed.\n */\n@customElement(\"photo-gallery\")\nexport class PhotoGallery extends LitElement {\n /** Zero-based active image index. */\n @property({ type: Number, attribute: \"current-index\", reflect: true })\n currentIndex = 0;\n\n /** Autoplay interval in milliseconds. Set to zero to disable autoplay. */\n @property({ type: Number }) delay = 0;\n\n /** Whether previous and next buttons are shown. */\n @property({ attribute: \"show-controls\", converter: booleanAttribute })\n showControls = true;\n\n /** Whether a current/total counter is shown. */\n @property({ type: Boolean, attribute: \"show-counter\" })\n showCounter = false;\n\n /** Whether clickable slide indicators are shown. */\n @property({ type: Boolean, attribute: \"show-indicators\" })\n showIndicators = false;\n\n /** Whether autoplay includes a built-in pause/play control. */\n @property({ attribute: \"show-autoplay-control\", converter: booleanAttribute })\n showAutoplayControl = true;\n\n /** Whether autoplay is explicitly paused. */\n @property({ type: Boolean, reflect: true })\n paused = false;\n\n /** CSS aspect ratio used by the image viewport. */\n @property({ attribute: \"aspect-ratio\" })\n aspectRatio = \"16 / 9\";\n\n /** How images fit within the stable viewport. */\n @property({ attribute: \"object-fit\" })\n objectFit: PhotoGalleryObjectFit = \"cover\";\n\n @queryAssignedElements({ selector: \"gallery-item\" })\n private readonly _galleryItems!: GalleryItem[];\n\n @state()\n private _previousIndex: number | null = null;\n\n @state()\n private _itemsVersion = 0;\n\n private _autoplayTimer?: number;\n private _transitionTimer?: number;\n private _metadataObserver?: MutationObserver;\n private _hovered = false;\n private _focusWithin = false;\n private _nextChangeReason: PhotoGalleryChangeReason | null = null;\n private _pendingChange?: PhotoGallerySlideChangeDetail;\n private _pointerStart?: { id: number; x: number; y: number };\n private _itemsChanged = false;\n private _activeItem?: GalleryItem;\n private _renderedIndex = 0;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n color: var(--ui-text, #0f172a);\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size, 0.875rem);\n }\n .gallery {\n outline: none;\n }\n figure {\n margin: 0;\n }\n .viewport {\n position: relative;\n overflow: hidden;\n aspect-ratio: var(--photo-gallery-aspect-ratio, 16 / 9);\n border-radius: var(--ui-radius, 0.5rem);\n background: var(--ui-surface-muted, #f8fafc);\n touch-action: pan-y;\n user-select: none;\n }\n .gallery:focus-visible .viewport {\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .slides {\n display: grid;\n width: 100%;\n height: 100%;\n }\n picture {\n grid-area: 1 / 1;\n display: block;\n width: 100%;\n height: 100%;\n }\n picture img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: var(--photo-gallery-object-fit, cover);\n }\n .entering {\n z-index: 2;\n animation: gallery-fade-in 250ms ease both;\n }\n .leaving {\n z-index: 1;\n pointer-events: none;\n animation: gallery-fade-out 250ms ease both;\n }\n .arrow-controls {\n position: absolute;\n z-index: 3;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem;\n pointer-events: none;\n }\n button {\n border: 0;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n cursor: pointer;\n }\n button:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .arrow-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n color: var(--ui-on-accent, #ffffff);\n background: var(--ui-overlay, rgb(15 23 42 / 0.45));\n border-radius: 9999px;\n pointer-events: auto;\n }\n .arrow-button:hover {\n background: color-mix(in srgb, var(--ui-text, #0f172a) 70%, transparent);\n }\n figcaption {\n padding: 0.5rem 0.25rem 0;\n min-height: 1lh;\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-text-muted, #64748b);\n }\n .footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n min-height: 2rem;\n padding-top: 0.5rem;\n }\n .counter {\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n white-space: nowrap;\n }\n .indicators {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n }\n .indicator {\n position: relative;\n width: 2rem;\n height: 2rem;\n padding: 0;\n background: transparent;\n border-radius: 9999px;\n }\n .indicator::before {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 0.625rem;\n height: 0.625rem;\n background: var(--ui-border, #e2e8f0);\n border-radius: 9999px;\n content: \"\";\n transform: translate(-50%, -50%);\n }\n .indicator[aria-current=\"true\"]::before {\n background: var(--ui-primary, #4f46e5);\n }\n .autoplay-button {\n height: 2rem;\n box-sizing: border-box;\n padding: 0.25rem 0.5rem;\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface-muted, #f8fafc);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n white-space: nowrap;\n }\n .autoplay-button:hover {\n background: var(--ui-surface, #ffffff);\n }\n slot {\n display: none;\n }\n @keyframes gallery-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes gallery-fade-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .entering,\n .leaving {\n animation: none;\n }\n }\n `,\n ];\n\n /** Starts observers and autoplay integration when the element connects. */\n override connectedCallback(): void {\n super.connectedCallback();\n this._metadataObserver ??= new MutationObserver(() => this._handleMetadataChange());\n this._metadataObserver.observe(this, {\n attributes: true,\n attributeFilter: [\"alt\", \"caption\", \"media\", \"src\", \"srcset\"],\n childList: true,\n subtree: true,\n });\n document.addEventListener(\"visibilitychange\", this._handleVisibilityChange);\n }\n\n /** Releases timers and observers when the element disconnects. */\n override disconnectedCallback(): void {\n this._clearAutoplay();\n this._clearTransition();\n this._metadataObserver?.disconnect();\n document.removeEventListener(\"visibilitychange\", this._handleVisibilityChange);\n super.disconnectedCallback();\n }\n\n /** Normalizes external index changes before rendering. */\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (!changed.has(\"currentIndex\")) return;\n\n const normalized = this._normalizeIndex(this.currentIndex);\n if (normalized !== this.currentIndex) {\n this.currentIndex = normalized;\n }\n\n const previousValue = changed.get(\"currentIndex\");\n if (previousValue === undefined || this._galleryItems.length === 0) {\n this._nextChangeReason = null;\n return;\n }\n\n const previousIndex = this._normalizeIndex(Number(previousValue));\n if (previousIndex === normalized) {\n this._nextChangeReason = null;\n return;\n }\n\n const reason = this._nextChangeReason ?? \"programmatic\";\n this._previousIndex = reason === \"items\" ? null : previousIndex;\n this._pendingChange = {\n previousIndex,\n currentIndex: normalized,\n item: this._galleryItems[normalized],\n reason,\n };\n this._nextChangeReason = null;\n }\n\n /** Emits completed changes and keeps autoplay synchronized with properties. */\n protected override updated(changed: PropertyValues<this>): void {\n if (this._pendingChange) {\n this.dispatchEvent(\n new CustomEvent<PhotoGallerySlideChangeDetail>(\"slide-change\", {\n bubbles: true,\n composed: true,\n detail: this._pendingChange,\n }),\n );\n this._pendingChange = undefined;\n this._scheduleTransitionCleanup();\n }\n\n if (changed.has(\"currentIndex\") || changed.has(\"delay\") || changed.has(\"paused\") || this._itemsChanged) {\n this._itemsChanged = false;\n this._restartAutoplay();\n }\n this._activeItem = this._galleryItems[this.currentIndex];\n this._renderedIndex = this.currentIndex;\n }\n\n /** Wraps any requested index into the current item range. */\n private _normalizeIndex(index: number): number {\n const count = this._galleryItems.length;\n if (count === 0 || !Number.isFinite(index)) return 0;\n return ((Math.trunc(index) % count) + count) % count;\n }\n\n /** Returns responsive variants declared directly under an item. */\n private _variantsFor(item: GalleryItem): GalleryItemVariant[] {\n return Array.from(item.children).filter(\n (child): child is GalleryItemVariant => child.tagName.toLowerCase() === \"gallery-item-variant\",\n );\n }\n\n /** Changes slides through the shared state and event path. */\n private _goTo(index: number, reason: PhotoGalleryChangeReason): void {\n const normalized = this._normalizeIndex(index);\n if (this._galleryItems.length < 2 || normalized === this.currentIndex) {\n this._restartAutoplay();\n return;\n }\n\n this._nextChangeReason = reason;\n this.currentIndex = normalized;\n }\n\n /** Moves to the previous image. */\n private _showPrevious(reason: PhotoGalleryChangeReason = \"previous\"): void {\n this._goTo(this.currentIndex - 1, reason);\n }\n\n /** Moves to the next image. */\n private _showNext(reason: PhotoGalleryChangeReason = \"next\"): void {\n this._goTo(this.currentIndex + 1, reason);\n }\n\n /** Toggles explicit autoplay pause state. */\n private _togglePaused(): void {\n this.paused = !this.paused;\n }\n\n /** Clears and conditionally schedules the next autoplay advance. */\n private _restartAutoplay(): void {\n this._clearAutoplay();\n if (!this._canAutoplay()) return;\n\n this._autoplayTimer = window.setTimeout(() => {\n this._showNext(\"autoplay\");\n }, this.delay);\n }\n\n /** Reports whether autoplay may currently schedule a transition. */\n private _canAutoplay(): boolean {\n return (\n this.delay > 0 &&\n this._galleryItems.length > 1 &&\n !this.paused &&\n !this._hovered &&\n !this._focusWithin &&\n !document.hidden\n );\n }\n\n /** Clears the pending autoplay timeout. */\n private _clearAutoplay(): void {\n if (this._autoplayTimer === undefined) return;\n window.clearTimeout(this._autoplayTimer);\n this._autoplayTimer = undefined;\n }\n\n /** Removes the outgoing crossfade layer after the animation completes. */\n private _scheduleTransitionCleanup(): void {\n this._clearTransition();\n this._transitionTimer = window.setTimeout(() => {\n this._previousIndex = null;\n this._transitionTimer = undefined;\n }, transitionDurationMs);\n }\n\n /** Clears pending transition cleanup. */\n private _clearTransition(): void {\n if (this._transitionTimer === undefined) return;\n window.clearTimeout(this._transitionTimer);\n this._transitionTimer = undefined;\n }\n\n /** Refreshes item metadata and clamps the active index after light-DOM changes. */\n private _handleMetadataChange(): void {\n this._itemsChanged = true;\n this._itemsVersion += 1;\n const preserveActiveItem = this.currentIndex === this._renderedIndex;\n const preservedIndex =\n preserveActiveItem && this._activeItem ? this._galleryItems.indexOf(this._activeItem) : -1;\n const normalized = preservedIndex >= 0 ? preservedIndex : this._normalizeIndex(this.currentIndex);\n if (normalized === this.currentIndex) {\n const item = this._galleryItems[normalized];\n const activeItemRemoved = Boolean(this._activeItem && !this._galleryItems.includes(this._activeItem));\n if (item && activeItemRemoved) {\n this._previousIndex = null;\n this._pendingChange = {\n previousIndex: this._renderedIndex,\n currentIndex: normalized,\n item,\n reason: \"items\",\n };\n }\n return;\n }\n this._nextChangeReason = \"items\";\n this.currentIndex = normalized;\n }\n\n /** Refreshes item state after the default slot changes. */\n private _handleSlotChange(): void {\n this._handleMetadataChange();\n }\n\n /** Temporarily pauses autoplay while the pointer is over the gallery. */\n private _handleMouseEnter(): void {\n this._hovered = true;\n this._restartAutoplay();\n }\n\n /** Resumes autoplay with a fresh delay after hover ends. */\n private _handleMouseLeave(): void {\n this._hovered = false;\n this._restartAutoplay();\n }\n\n /** Temporarily pauses autoplay while focus is inside the gallery. */\n private _handleFocusIn(): void {\n this._focusWithin = true;\n this._restartAutoplay();\n }\n\n /** Resumes autoplay with a fresh delay after focus leaves the gallery. */\n private _handleFocusOut(): void {\n queueMicrotask(() => {\n this._focusWithin = this.matches(\":focus-within\");\n this._restartAutoplay();\n });\n }\n\n /** Pauses or resumes scheduling when page visibility changes. */\n private readonly _handleVisibilityChange = (): void => {\n this._restartAutoplay();\n };\n\n /** Handles Left and Right arrow keyboard navigation. */\n private _handleKeyDown(event: KeyboardEvent): void {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n this._showPrevious(\"keyboard\");\n return;\n }\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n this._showNext(\"keyboard\");\n }\n }\n\n /** Records the starting point of a primary pointer gesture. */\n private _handlePointerDown(event: PointerEvent): void {\n if (!event.isPrimary || event.button !== 0) return;\n if (event.composedPath().some((target) => target instanceof HTMLButtonElement)) return;\n this._pointerStart = { id: event.pointerId, x: event.clientX, y: event.clientY };\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n }\n\n /** Converts a sufficiently horizontal pointer gesture into navigation. */\n private _handlePointerUp(event: PointerEvent): void {\n const start = this._pointerStart;\n this._pointerStart = undefined;\n if (!start || start.id !== event.pointerId) return;\n\n const deltaX = event.clientX - start.x;\n const deltaY = event.clientY - start.y;\n if (Math.abs(deltaX) < swipeThresholdPx || Math.abs(deltaX) <= Math.abs(deltaY)) return;\n\n event.preventDefault();\n if (deltaX < 0) {\n this._showNext(\"swipe\");\n return;\n }\n this._showPrevious(\"swipe\");\n }\n\n /** Cancels an incomplete pointer gesture. */\n private _handlePointerCancel(): void {\n this._pointerStart = undefined;\n }\n\n /** Renders one responsive image layer for the crossfade stack. */\n private _renderPicture(index: number, state: \"current\" | \"previous\") {\n const item = this._galleryItems[index];\n if (!item) return nothing;\n\n const isPrevious = state === \"previous\";\n const transitionClass = this._previousIndex === null ? \"\" : isPrevious ? \"leaving\" : \"entering\";\n return html`\n <picture class=${transitionClass} aria-hidden=${isPrevious ? \"true\" : nothing}>\n ${this._variantsFor(item)\n .filter((variant) => variant.srcset)\n .map(\n (variant) =>\n html`<source media=${ifDefined(variant.media || undefined)} srcset=${variant.srcset} />`,\n )}\n <img src=${item.src} alt=${isPrevious ? \"\" : item.alt} draggable=\"false\" />\n </picture>\n `;\n }\n\n /** Renders enabled counter, indicator, and autoplay controls. */\n private _renderFooter(itemCount: number) {\n const showIndicators = this.showIndicators && itemCount > 1;\n const showAutoplay = this.showAutoplayControl && this.delay > 0 && itemCount > 1;\n if (!this.showCounter && !showIndicators && !showAutoplay) return nothing;\n\n return html`\n <div class=\"footer\">\n ${this.showCounter\n ? html`<span class=\"counter\">${this.currentIndex + 1} / ${itemCount}</span>`\n : nothing}\n ${showIndicators\n ? html`\n <div class=\"indicators\" role=\"group\" aria-label=\"Choose image\">\n ${this._galleryItems.map(\n (_item, index) => html`\n <button\n class=\"indicator\"\n type=\"button\"\n aria-label=\"Show image ${index + 1} of ${itemCount}\"\n aria-current=${String(index === this.currentIndex)}\n @click=${() => this._goTo(index, \"indicator\")}\n ></button>\n `,\n )}\n </div>\n `\n : nothing}\n ${showAutoplay\n ? html`\n <button\n class=\"autoplay-button\"\n type=\"button\"\n aria-label=${this.paused ? \"Resume slideshow\" : \"Pause slideshow\"}\n @click=${this._togglePaused}\n >\n ${this.paused ? \"Play\" : \"Pause\"}\n </button>\n `\n : nothing}\n </div>\n `;\n }\n\n /** Renders the active image, navigation, caption, and hidden metadata slot. */\n protected override render() {\n const itemCount = this._galleryItems.length;\n const currentItem = this._galleryItems[this.currentIndex];\n // Reserve the caption row for every slide as soon as any slide has a\n // caption, so the gallery's total height stays constant while it cycles\n // (a slide without a caption no longer collapses the box and shifts the\n // page below it).\n const hasCaptions = this._galleryItems.some((item) => item.caption);\n const objectFit: PhotoGalleryObjectFit = this.objectFit === \"contain\" ? \"contain\" : \"cover\";\n const viewportStyles = {\n \"--photo-gallery-aspect-ratio\": this.aspectRatio.trim() || \"16 / 9\",\n \"--photo-gallery-object-fit\": objectFit,\n };\n\n return html`\n <div\n class=\"gallery\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label=\"Photo gallery\"\n tabindex=\"0\"\n @keydown=${this._handleKeyDown}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n @focusin=${this._handleFocusIn}\n @focusout=${this._handleFocusOut}\n >\n ${currentItem\n ? html`\n <figure>\n <div\n class=\"viewport\"\n style=${styleMap(viewportStyles)}\n @pointerdown=${this._handlePointerDown}\n @pointerup=${this._handlePointerUp}\n @pointercancel=${this._handlePointerCancel}\n >\n <div class=\"slides\">\n ${this._previousIndex === null\n ? nothing\n : this._renderPicture(this._previousIndex, \"previous\")}\n ${this._renderPicture(this.currentIndex, \"current\")}\n </div>\n ${this.showControls && itemCount > 1\n ? html`\n <div class=\"arrow-controls\">\n <button\n class=\"arrow-button previous\"\n type=\"button\"\n aria-label=\"Previous image\"\n @click=${() => this._showPrevious()}\n >\n ${iconChevronLeft(18)}\n </button>\n <button\n class=\"arrow-button next\"\n type=\"button\"\n aria-label=\"Next image\"\n @click=${() => this._showNext()}\n >\n ${iconChevronRight(18)}\n </button>\n </div>\n `\n : nothing}\n </div>\n ${hasCaptions\n ? html`<figcaption>${currentItem.caption}</figcaption>`\n : nothing}\n </figure>\n ${this._renderFooter(itemCount)}\n `\n : nothing}\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"photo-gallery\": PhotoGallery;\n }\n}\n"]}
@@ -1,20 +1,30 @@
1
1
  import { LitElement, nothing } from "lit";
2
- export type ToastVariant = "error" | "info" | "success";
2
+ export type ToastVariant = "error" | "info" | "success" | "warning";
3
3
  interface ToastOptions {
4
4
  /** Visual style; also selects the accent color. Defaults to "info". */
5
5
  variant?: ToastVariant;
6
6
  /** Auto-dismiss delay in ms. Pass 0 to require a manual close. Defaults to 5000. */
7
7
  duration?: number;
8
+ /**
9
+ * Optional secondary line shown beneath the headline in smaller, non-bold
10
+ * type. Omit for a single-line toast.
11
+ */
12
+ description?: string;
8
13
  }
9
14
  /**
10
15
  * Fixed-position stack of dismissible notifications, anchored top-right
11
- * (top-full-width on mobile). Not wired to any app state yet — callers add
12
- * toasts imperatively via the `show()` method on a live element reference,
16
+ * (top-full-width on mobile). Every toast shares one fixed width so entries
17
+ * never appear narrower or wider than one another. Not wired to any app state
18
+ * yet — callers add toasts imperatively via the `show()` method on a live
19
+ * element reference,
13
20
  * e.g. `document.querySelector('toast-notification')?.show('Offline', { variant: 'error' })`,
14
21
  * or via the `notifySuccess`/`notifyError`/`notifyInfo` module-level helpers
15
- * exported from this file. Each toast auto-dismisses after `duration` ms and
16
- * can also be dismissed via its button. Appears/disappears instantly — no
17
- * slide/fade transitions.
22
+ * exported from this file. The first argument is the required bold headline; an
23
+ * optional `description` renders a smaller, non-bold second line. Each variant
24
+ * leads with a matching status icon (success → check, error → exclamation
25
+ * circle, info → information circle, warning → exclamation triangle). Each toast
26
+ * auto-dismisses after `duration` ms and can also be dismissed via its ✕
27
+ * button. Appears/disappears instantly — no slide/fade transitions.
18
28
  *
19
29
  * @element toast-notification
20
30
  */
@@ -36,6 +46,12 @@ export declare class ToastNotification extends LitElement {
36
46
  */
37
47
  dismiss(id: number): void;
38
48
  disconnectedCallback(): void;
49
+ /**
50
+ * Returns the decorative status icon for a variant, sized as a standalone
51
+ * 18px glyph to match the dismiss button.
52
+ * @param variant The toast variant.
53
+ */
54
+ private _variantIcon;
39
55
  render(): typeof nothing | import("lit-html").TemplateResult<1>;
40
56
  }
41
57
  declare global {
@@ -44,10 +60,12 @@ declare global {
44
60
  }
45
61
  }
46
62
  /** Shows an error toast. Use for connection/network failures, not validation errors. */
47
- export declare function notifyError(message: string): void;
63
+ export declare function notifyError(message: string, description?: string): void;
48
64
  /** Shows a success toast. */
49
- export declare function notifySuccess(message: string): void;
65
+ export declare function notifySuccess(message: string, description?: string): void;
50
66
  /** Shows an info toast. */
51
- export declare function notifyInfo(message: string): void;
67
+ export declare function notifyInfo(message: string, description?: string): void;
68
+ /** Shows a warning toast. */
69
+ export declare function notifyWarning(message: string, description?: string): void;
52
70
  export {};
53
71
  //# sourceMappingURL=toast-notification.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast-notification.d.ts","sourceRoot":"","sources":["../src/toast-notification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAE,MAAM,KAAK,CAAC;AAKrD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAExD,UAAU,YAAY;IACpB,uEAAuE;IACvE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAUD;;;;;;;;;;;GAWG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACtC,OAAO,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAoD;IAEnE,OAAgB,MAAM,4BAoGpB;IAEF;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAYxD;IAED;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,QAOjB;IAEQ,oBAAoB,SAI5B;IAEQ,MAAM,0DAkBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,iBAAiB,CAAC;KACzC;CACF;AAMD,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAE1C;AAED,6BAA6B;AAC7B,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,QAE5C;AAED,2BAA2B;AAC3B,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,QAEzC"}
1
+ {"version":3,"file":"toast-notification.d.ts","sourceRoot":"","sources":["../src/toast-notification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAE,MAAM,KAAK,CAAC;AAWrD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE,UAAU,YAAY;IACpB,uEAAuE;IACvE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACtC,OAAO,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAoD;IAEnE,OAAgB,MAAM,4BAyHpB;IAEF;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAYxD;IAED;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,QAOjB;IAEQ,oBAAoB,SAI5B;IAED;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAaX,MAAM,0DAsBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,iBAAiB,CAAC;KACzC;CACF;AAMD,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,QAEhE;AAED,6BAA6B;AAC7B,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,QAElE;AAED,2BAA2B;AAC3B,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,QAE/D;AAED,6BAA6B;AAC7B,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,QAElE"}
@@ -6,18 +6,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { LitElement, css, html, nothing } from "lit";
8
8
  import { customElement, state } from "lit/decorators.js";
9
- import { iconX } from "./icons.js";
9
+ import { iconCheckCircle, iconExclamationCircle, iconExclamationTriangle, iconInfo, iconX, } from "./icons.js";
10
10
  import { tokens } from "./tokens.js";
11
11
  const DEFAULT_DURATION_MS = 5000;
12
12
  /**
13
13
  * Fixed-position stack of dismissible notifications, anchored top-right
14
- * (top-full-width on mobile). Not wired to any app state yet — callers add
15
- * toasts imperatively via the `show()` method on a live element reference,
14
+ * (top-full-width on mobile). Every toast shares one fixed width so entries
15
+ * never appear narrower or wider than one another. Not wired to any app state
16
+ * yet — callers add toasts imperatively via the `show()` method on a live
17
+ * element reference,
16
18
  * e.g. `document.querySelector('toast-notification')?.show('Offline', { variant: 'error' })`,
17
19
  * or via the `notifySuccess`/`notifyError`/`notifyInfo` module-level helpers
18
- * exported from this file. Each toast auto-dismisses after `duration` ms and
19
- * can also be dismissed via its button. Appears/disappears instantly — no
20
- * slide/fade transitions.
20
+ * exported from this file. The first argument is the required bold headline; an
21
+ * optional `description` renders a smaller, non-bold second line. Each variant
22
+ * leads with a matching status icon (success → check, error → exclamation
23
+ * circle, info → information circle, warning → exclamation triangle). Each toast
24
+ * auto-dismisses after `duration` ms and can also be dismissed via its ✕
25
+ * button. Appears/disappears instantly — no slide/fade transitions.
21
26
  *
22
27
  * @element toast-notification
23
28
  */
@@ -39,7 +44,7 @@ let ToastNotification = class ToastNotification extends LitElement {
39
44
  display: flex;
40
45
  flex-direction: column;
41
46
  gap: 0.5rem;
42
- max-width: 22.5rem;
47
+ width: 22.5rem;
43
48
  pointer-events: none;
44
49
  }
45
50
  .toast {
@@ -78,8 +83,29 @@ let ToastNotification = class ToastNotification extends LitElement {
78
83
  .toast.info {
79
84
  background: var(--ui-info, #0ea5e9);
80
85
  }
81
- .message {
86
+ .toast.warning {
87
+ background: var(--ui-warning, #d97706);
88
+ }
89
+ .icon {
90
+ flex: 0 0 auto;
91
+ margin-top: 0.125rem;
92
+ line-height: var(--ui-line-height-glyph, 1);
93
+ }
94
+ .content {
82
95
  flex: 1 1 auto;
96
+ min-width: 0;
97
+ display: flex;
98
+ flex-direction: column;
99
+ gap: 0.25rem;
100
+ }
101
+ .message {
102
+ font-weight: var(--ui-font-weight-semibold, 600);
103
+ word-break: break-word;
104
+ }
105
+ .description {
106
+ font-size: var(--ui-font-size-sm, 0.75rem);
107
+ font-weight: var(--ui-font-weight-regular, 400);
108
+ line-height: var(--ui-line-height-normal, 1.5);
83
109
  word-break: break-word;
84
110
  }
85
111
  .close {
@@ -124,7 +150,7 @@ let ToastNotification = class ToastNotification extends LitElement {
124
150
  top: 0.75rem;
125
151
  right: 0.75rem;
126
152
  left: 0.75rem;
127
- max-width: none;
153
+ width: auto;
128
154
  }
129
155
  }
130
156
  `,
@@ -139,7 +165,7 @@ let ToastNotification = class ToastNotification extends LitElement {
139
165
  const id = this._nextId++;
140
166
  const variant = options.variant ?? "info";
141
167
  const duration = options.duration ?? DEFAULT_DURATION_MS;
142
- this._toasts = [...this._toasts, { id, message, variant }];
168
+ this._toasts = [...this._toasts, { id, message, variant, description: options.description }];
143
169
  if (duration > 0) {
144
170
  this._timers.set(id, setTimeout(() => this.dismiss(id), duration));
145
171
  }
@@ -163,6 +189,23 @@ let ToastNotification = class ToastNotification extends LitElement {
163
189
  clearTimeout(timer);
164
190
  this._timers.clear();
165
191
  }
192
+ /**
193
+ * Returns the decorative status icon for a variant, sized as a standalone
194
+ * 18px glyph to match the dismiss button.
195
+ * @param variant The toast variant.
196
+ */
197
+ _variantIcon(variant) {
198
+ switch (variant) {
199
+ case "success":
200
+ return iconCheckCircle(18);
201
+ case "error":
202
+ return iconExclamationCircle(18);
203
+ case "warning":
204
+ return iconExclamationTriangle(18);
205
+ default:
206
+ return iconInfo(18);
207
+ }
208
+ }
166
209
  render() {
167
210
  if (this._toasts.length === 0)
168
211
  return nothing;
@@ -173,7 +216,11 @@ let ToastNotification = class ToastNotification extends LitElement {
173
216
  role=${t.variant === "error" ? "alert" : "status"}
174
217
  aria-atomic="true"
175
218
  >
176
- <span class="message">${t.message}</span>
219
+ <span class="icon" aria-hidden="true">${this._variantIcon(t.variant)}</span>
220
+ <div class="content">
221
+ <span class="message">${t.message}</span>
222
+ ${t.description ? html `<span class="description">${t.description}</span>` : nothing}
223
+ </div>
177
224
  <button class="close" aria-label="Dismiss notification" @click=${() => this.dismiss(t.id)}>
178
225
  <span aria-hidden="true">${iconX(18)}</span>
179
226
  </button>
@@ -193,15 +240,19 @@ function getToast() {
193
240
  return document.querySelector("toast-notification");
194
241
  }
195
242
  /** Shows an error toast. Use for connection/network failures, not validation errors. */
196
- export function notifyError(message) {
197
- getToast()?.show(message, { variant: "error" });
243
+ export function notifyError(message, description) {
244
+ getToast()?.show(message, { variant: "error", description });
198
245
  }
199
246
  /** Shows a success toast. */
200
- export function notifySuccess(message) {
201
- getToast()?.show(message, { variant: "success" });
247
+ export function notifySuccess(message, description) {
248
+ getToast()?.show(message, { variant: "success", description });
202
249
  }
203
250
  /** Shows an info toast. */
204
- export function notifyInfo(message) {
205
- getToast()?.show(message, { variant: "info" });
251
+ export function notifyInfo(message, description) {
252
+ getToast()?.show(message, { variant: "info", description });
253
+ }
254
+ /** Shows a warning toast. */
255
+ export function notifyWarning(message, description) {
256
+ getToast()?.show(message, { variant: "warning", description });
206
257
  }
207
258
  //# sourceMappingURL=toast-notification.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast-notification.js","sourceRoot":"","sources":["../src/toast-notification.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\nimport { iconX } from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\nexport type ToastVariant = \"error\" | \"info\" | \"success\";\n\ninterface ToastOptions {\n /** Visual style; also selects the accent color. Defaults to \"info\". */\n variant?: ToastVariant;\n /** Auto-dismiss delay in ms. Pass 0 to require a manual close. Defaults to 5000. */\n duration?: number;\n}\n\ninterface Toast {\n id: number;\n message: string;\n variant: ToastVariant;\n}\n\nconst DEFAULT_DURATION_MS = 5000;\n\n/**\n * Fixed-position stack of dismissible notifications, anchored top-right\n * (top-full-width on mobile). Not wired to any app state yet — callers add\n * toasts imperatively via the `show()` method on a live element reference,\n * e.g. `document.querySelector('toast-notification')?.show('Offline', { variant: 'error' })`,\n * or via the `notifySuccess`/`notifyError`/`notifyInfo` module-level helpers\n * exported from this file. Each toast auto-dismisses after `duration` ms and\n * can also be dismissed via its ✕ button. Appears/disappears instantly — no\n * slide/fade transitions.\n *\n * @element toast-notification\n */\n@customElement(\"toast-notification\")\nexport class ToastNotification extends LitElement {\n @state() private _toasts: Toast[] = [];\n\n private _nextId = 0;\n private _timers = new Map<number, ReturnType<typeof setTimeout>>();\n\n static override styles = [\n tokens,\n css`\n :host {\n position: fixed;\n top: 1rem;\n right: 1rem;\n z-index: 200;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n max-width: 22.5rem;\n pointer-events: none;\n }\n .toast {\n pointer-events: auto;\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n border-radius: var(--ui-radius, 0.5rem);\n padding: 0.75rem;\n box-shadow: var(\n --ui-shadow-lg,\n 0 20px 25px -5px rgb(0 0 0 / 0.1),\n 0 8px 10px -6px rgb(0 0 0 / 0.1)\n );\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-on-accent, #ffffff);\n background: var(--ui-text, #0f172a);\n }\n .toast.error {\n background: var(--ui-danger, #dc2626);\n }\n .toast.success {\n background: var(--ui-success, #16a34a);\n }\n .toast.info {\n background: var(--ui-info, #0ea5e9);\n }\n .message {\n flex: 1 1 auto;\n word-break: break-word;\n }\n .close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background: none;\n border: none;\n padding: 0;\n margin: -0.25rem -0.25rem -0.25rem 0;\n color: inherit;\n opacity: 0.8;\n cursor: pointer;\n line-height: var(--ui-line-height-glyph, 1);\n border-radius: var(--ui-radius-sm, 0.25rem);\n }\n .close:hover {\n opacity: 1;\n background: var(--ui-hover-overlay, rgb(255 255 255 / 0.32));\n }\n .close:focus-visible {\n outline: none;\n opacity: 1;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n @media (forced-colors: active) {\n .toast {\n border: 1px solid CanvasText;\n forced-color-adjust: auto;\n }\n .close:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n }\n @media (max-width: 48rem) {\n :host {\n top: 0.75rem;\n right: 0.75rem;\n left: 0.75rem;\n max-width: none;\n }\n }\n `,\n ];\n\n /**\n * Queues a toast for display.\n * @param message Text to show.\n * @param options Variant + auto-dismiss duration (see {@link ToastOptions}).\n * @returns The toast's id — pass to `dismiss()` to remove it early.\n */\n show(message: string, options: ToastOptions = {}): number {\n const id = this._nextId++;\n const variant = options.variant ?? \"info\";\n const duration = options.duration ?? DEFAULT_DURATION_MS;\n this._toasts = [...this._toasts, { id, message, variant }];\n if (duration > 0) {\n this._timers.set(\n id,\n setTimeout(() => this.dismiss(id), duration),\n );\n }\n return id;\n }\n\n /**\n * Removes a toast immediately, cancelling its pending auto-dismiss timer if any.\n * @param id The id returned by `show()`.\n */\n dismiss(id: number) {\n const timer = this._timers.get(id);\n if (timer) {\n clearTimeout(timer);\n this._timers.delete(id);\n }\n this._toasts = this._toasts.filter((t) => t.id !== id);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n for (const timer of this._timers.values()) clearTimeout(timer);\n this._timers.clear();\n }\n\n override render() {\n if (this._toasts.length === 0) return nothing;\n return html`\n ${this._toasts.map(\n (t) => html`\n <div\n class=\"toast ${t.variant}\"\n role=${t.variant === \"error\" ? \"alert\" : \"status\"}\n aria-atomic=\"true\"\n >\n <span class=\"message\">${t.message}</span>\n <button class=\"close\" aria-label=\"Dismiss notification\" @click=${() => this.dismiss(t.id)}>\n <span aria-hidden=\"true\">${iconX(18)}</span>\n </button>\n </div>\n `,\n )}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"toast-notification\": ToastNotification;\n }\n}\n\nfunction getToast(): ToastNotification | null {\n return document.querySelector(\"toast-notification\");\n}\n\n/** Shows an error toast. Use for connection/network failures, not validation errors. */\nexport function notifyError(message: string) {\n getToast()?.show(message, { variant: \"error\" });\n}\n\n/** Shows a success toast. */\nexport function notifySuccess(message: string) {\n getToast()?.show(message, { variant: \"success\" });\n}\n\n/** Shows an info toast. */\nexport function notifyInfo(message: string) {\n getToast()?.show(message, { variant: \"info\" });\n}\n"]}
1
+ {"version":3,"file":"toast-notification.js","sourceRoot":"","sources":["../src/toast-notification.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\nimport {\n iconCheckCircle,\n iconExclamationCircle,\n iconExclamationTriangle,\n iconInfo,\n iconX,\n} from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\nexport type ToastVariant = \"error\" | \"info\" | \"success\" | \"warning\";\n\ninterface ToastOptions {\n /** Visual style; also selects the accent color. Defaults to \"info\". */\n variant?: ToastVariant;\n /** Auto-dismiss delay in ms. Pass 0 to require a manual close. Defaults to 5000. */\n duration?: number;\n /**\n * Optional secondary line shown beneath the headline in smaller, non-bold\n * type. Omit for a single-line toast.\n */\n description?: string;\n}\n\ninterface Toast {\n id: number;\n message: string;\n variant: ToastVariant;\n description?: string;\n}\n\nconst DEFAULT_DURATION_MS = 5000;\n\n/**\n * Fixed-position stack of dismissible notifications, anchored top-right\n * (top-full-width on mobile). Every toast shares one fixed width so entries\n * never appear narrower or wider than one another. Not wired to any app state\n * yet — callers add toasts imperatively via the `show()` method on a live\n * element reference,\n * e.g. `document.querySelector('toast-notification')?.show('Offline', { variant: 'error' })`,\n * or via the `notifySuccess`/`notifyError`/`notifyInfo` module-level helpers\n * exported from this file. The first argument is the required bold headline; an\n * optional `description` renders a smaller, non-bold second line. Each variant\n * leads with a matching status icon (success → check, error → exclamation\n * circle, info → information circle, warning → exclamation triangle). Each toast\n * auto-dismisses after `duration` ms and can also be dismissed via its ✕\n * button. Appears/disappears instantly — no slide/fade transitions.\n *\n * @element toast-notification\n */\n@customElement(\"toast-notification\")\nexport class ToastNotification extends LitElement {\n @state() private _toasts: Toast[] = [];\n\n private _nextId = 0;\n private _timers = new Map<number, ReturnType<typeof setTimeout>>();\n\n static override styles = [\n tokens,\n css`\n :host {\n position: fixed;\n top: 1rem;\n right: 1rem;\n z-index: 200;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n width: 22.5rem;\n pointer-events: none;\n }\n .toast {\n pointer-events: auto;\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n border-radius: var(--ui-radius, 0.5rem);\n padding: 0.75rem;\n box-shadow: var(\n --ui-shadow-lg,\n 0 20px 25px -5px rgb(0 0 0 / 0.1),\n 0 8px 10px -6px rgb(0 0 0 / 0.1)\n );\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-on-accent, #ffffff);\n background: var(--ui-text, #0f172a);\n }\n .toast.error {\n background: var(--ui-danger, #dc2626);\n }\n .toast.success {\n background: var(--ui-success, #16a34a);\n }\n .toast.info {\n background: var(--ui-info, #0ea5e9);\n }\n .toast.warning {\n background: var(--ui-warning, #d97706);\n }\n .icon {\n flex: 0 0 auto;\n margin-top: 0.125rem;\n line-height: var(--ui-line-height-glyph, 1);\n }\n .content {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n }\n .message {\n font-weight: var(--ui-font-weight-semibold, 600);\n word-break: break-word;\n }\n .description {\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: var(--ui-font-weight-regular, 400);\n line-height: var(--ui-line-height-normal, 1.5);\n word-break: break-word;\n }\n .close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background: none;\n border: none;\n padding: 0;\n margin: -0.25rem -0.25rem -0.25rem 0;\n color: inherit;\n opacity: 0.8;\n cursor: pointer;\n line-height: var(--ui-line-height-glyph, 1);\n border-radius: var(--ui-radius-sm, 0.25rem);\n }\n .close:hover {\n opacity: 1;\n background: var(--ui-hover-overlay, rgb(255 255 255 / 0.32));\n }\n .close:focus-visible {\n outline: none;\n opacity: 1;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n @media (forced-colors: active) {\n .toast {\n border: 1px solid CanvasText;\n forced-color-adjust: auto;\n }\n .close:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n }\n @media (max-width: 48rem) {\n :host {\n top: 0.75rem;\n right: 0.75rem;\n left: 0.75rem;\n width: auto;\n }\n }\n `,\n ];\n\n /**\n * Queues a toast for display.\n * @param message Text to show.\n * @param options Variant + auto-dismiss duration (see {@link ToastOptions}).\n * @returns The toast's id — pass to `dismiss()` to remove it early.\n */\n show(message: string, options: ToastOptions = {}): number {\n const id = this._nextId++;\n const variant = options.variant ?? \"info\";\n const duration = options.duration ?? DEFAULT_DURATION_MS;\n this._toasts = [...this._toasts, { id, message, variant, description: options.description }];\n if (duration > 0) {\n this._timers.set(\n id,\n setTimeout(() => this.dismiss(id), duration),\n );\n }\n return id;\n }\n\n /**\n * Removes a toast immediately, cancelling its pending auto-dismiss timer if any.\n * @param id The id returned by `show()`.\n */\n dismiss(id: number) {\n const timer = this._timers.get(id);\n if (timer) {\n clearTimeout(timer);\n this._timers.delete(id);\n }\n this._toasts = this._toasts.filter((t) => t.id !== id);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n for (const timer of this._timers.values()) clearTimeout(timer);\n this._timers.clear();\n }\n\n /**\n * Returns the decorative status icon for a variant, sized as a standalone\n * 18px glyph to match the dismiss button.\n * @param variant The toast variant.\n */\n private _variantIcon(variant: ToastVariant) {\n switch (variant) {\n case \"success\":\n return iconCheckCircle(18);\n case \"error\":\n return iconExclamationCircle(18);\n case \"warning\":\n return iconExclamationTriangle(18);\n default:\n return iconInfo(18);\n }\n }\n\n override render() {\n if (this._toasts.length === 0) return nothing;\n return html`\n ${this._toasts.map(\n (t) => html`\n <div\n class=\"toast ${t.variant}\"\n role=${t.variant === \"error\" ? \"alert\" : \"status\"}\n aria-atomic=\"true\"\n >\n <span class=\"icon\" aria-hidden=\"true\">${this._variantIcon(t.variant)}</span>\n <div class=\"content\">\n <span class=\"message\">${t.message}</span>\n ${t.description ? html`<span class=\"description\">${t.description}</span>` : nothing}\n </div>\n <button class=\"close\" aria-label=\"Dismiss notification\" @click=${() => this.dismiss(t.id)}>\n <span aria-hidden=\"true\">${iconX(18)}</span>\n </button>\n </div>\n `,\n )}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"toast-notification\": ToastNotification;\n }\n}\n\nfunction getToast(): ToastNotification | null {\n return document.querySelector(\"toast-notification\");\n}\n\n/** Shows an error toast. Use for connection/network failures, not validation errors. */\nexport function notifyError(message: string, description?: string) {\n getToast()?.show(message, { variant: \"error\", description });\n}\n\n/** Shows a success toast. */\nexport function notifySuccess(message: string, description?: string) {\n getToast()?.show(message, { variant: \"success\", description });\n}\n\n/** Shows an info toast. */\nexport function notifyInfo(message: string, description?: string) {\n getToast()?.show(message, { variant: \"info\", description });\n}\n\n/** Shows a warning toast. */\nexport function notifyWarning(message: string, description?: string) {\n getToast()?.show(message, { variant: \"warning\", description });\n}\n"]}
@@ -20,6 +20,10 @@ export interface TreeNode {
20
20
  * internally and untouched by later `nodes` updates, so a user's manual
21
21
  * toggles survive a data refresh.
22
22
  *
23
+ * Set the `lines` boolean to draw classic file-tree connector guides: a
24
+ * vertical line per continuing ancestor level and a branch elbow (`└`) or
25
+ * tee (`├`) linking each node to its parent. Off by default (indentation only).
26
+ *
23
27
  * @element tree-view
24
28
  * @fires node-click - A leaf row was activated; detail is `{ id, data }`.
25
29
  */
@@ -32,6 +36,11 @@ export declare class TreeView extends LitElement {
32
36
  renderNode: (node: TreeNode) => unknown;
33
37
  /** Start every folder expanded instead of the default all-collapsed. */
34
38
  defaultExpanded: boolean;
39
+ /**
40
+ * Draw classic file-tree connector guides (vertical ancestor lines plus a
41
+ * branch elbow/tee per row) instead of indentation alone. Off by default.
42
+ */
43
+ lines: boolean;
35
44
  private expanded;
36
45
  willUpdate(changed: Map<string, unknown>): void;
37
46
  render(): unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../src/tree-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2C,MAAM,KAAK,CAAC;AAM1E,oFAAoF;AACpF,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,QAAS,SAAQ,UAAU;;IACtC,OAAgB,MAAM,4BAsDpB;IAEF,iFAAiF;IACjD,KAAK,EAAE,QAAQ,EAAE,CAAM;IACvD,+EAA+E;IAC/C,UAAU,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAwB;IAC/F,wEAAwE;IACZ,eAAe,UAAS;IAE3E,OAAO,CAAC,QAAQ,CAAqB;IAGrC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAcvD;IAyEQ,MAAM,YAMd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
1
+ {"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../src/tree-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2C,MAAM,KAAK,CAAC;AAM1E,oFAAoF;AACpF,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,QAAS,SAAQ,UAAU;;IACtC,OAAgB,MAAM,4BA8FpB;IAEF,iFAAiF;IACjD,KAAK,EAAE,QAAQ,EAAE,CAAM;IACvD,+EAA+E;IAC/C,UAAU,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAwB;IAC/F,wEAAwE;IACZ,eAAe,UAAS;IACpF;;;OAGG;IACyC,KAAK,UAAS;IAEjD,OAAO,CAAC,QAAQ,CAAqB;IAGrC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAcvD;IA2FQ,MAAM,YAMd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
package/dist/tree-view.js CHANGED
@@ -23,6 +23,10 @@ import { tokens } from "./tokens.js";
23
23
  * internally and untouched by later `nodes` updates, so a user's manual
24
24
  * toggles survive a data refresh.
25
25
  *
26
+ * Set the `lines` boolean to draw classic file-tree connector guides: a
27
+ * vertical line per continuing ancestor level and a branch elbow (`└`) or
28
+ * tee (`├`) linking each node to its parent. Off by default (indentation only).
29
+ *
26
30
  * @element tree-view
27
31
  * @fires node-click - A leaf row was activated; detail is `{ id, data }`.
28
32
  */
@@ -35,6 +39,11 @@ let TreeView = class TreeView extends LitElement {
35
39
  this.renderNode = (node) => node.label;
36
40
  /** Start every folder expanded instead of the default all-collapsed. */
37
41
  this.defaultExpanded = false;
42
+ /**
43
+ * Draw classic file-tree connector guides (vertical ancestor lines plus a
44
+ * branch elbow/tee per row) instead of indentation alone. Off by default.
45
+ */
46
+ this.lines = false;
38
47
  this.expanded = new Set();
39
48
  this.#initializedExpansion = false;
40
49
  }
@@ -84,12 +93,52 @@ let TreeView = class TreeView extends LitElement {
84
93
  min-width: 0;
85
94
  flex: 1;
86
95
  }
96
+ :host([lines]) .row {
97
+ padding-top: 0;
98
+ padding-bottom: 0;
99
+ min-height: 1.5rem;
100
+ }
101
+ .guides {
102
+ display: flex;
103
+ align-self: stretch;
104
+ flex-shrink: 0;
105
+ }
106
+ .guide {
107
+ position: relative;
108
+ flex: 0 0 auto;
109
+ width: 1rem;
110
+ }
111
+ .guide.v::before,
112
+ .guide.connector::before {
113
+ content: "";
114
+ position: absolute;
115
+ left: 50%;
116
+ top: 0;
117
+ bottom: 0;
118
+ border-left: 1px solid var(--ui-border, #e2e8f0);
119
+ }
120
+ .guide.connector.last::before {
121
+ bottom: 50%;
122
+ }
123
+ .guide.connector::after {
124
+ content: "";
125
+ position: absolute;
126
+ left: 50%;
127
+ right: 0;
128
+ top: 50%;
129
+ border-top: 1px solid var(--ui-border, #e2e8f0);
130
+ }
87
131
  @media (forced-colors: active) {
88
132
  .row:focus-visible {
89
133
  outline: 2px solid CanvasText;
90
134
  outline-offset: -2px;
91
135
  box-shadow: none;
92
136
  }
137
+ .guide.v::before,
138
+ .guide.connector::before,
139
+ .guide.connector::after {
140
+ border-color: CanvasText;
141
+ }
93
142
  }
94
143
  `,
95
144
  ]; }
@@ -154,31 +203,41 @@ let TreeView = class TreeView extends LitElement {
154
203
  }
155
204
  return false;
156
205
  }
157
- #renderNode(node, depth) {
206
+ #renderNode(node, depth, isLast, ancestorHasNext) {
158
207
  const isFolder = !!node.children;
159
208
  const isOpen = isFolder && this.expanded.has(node.id);
209
+ const guides = this.lines
210
+ ? html `<span class="guides" aria-hidden="true">
211
+ ${ancestorHasNext.map((hasNext) => html `<span class="guide ${hasNext ? "v" : ""}"></span>`)}
212
+ <span class="guide connector ${isLast ? "last" : ""}"></span>
213
+ </span>`
214
+ : nothing;
160
215
  return html `
161
216
  <div
162
217
  class="row"
163
218
  role=${isFolder ? "button" : "link"}
164
219
  aria-expanded=${isFolder ? String(isOpen) : nothing}
165
220
  tabindex="0"
166
- style="padding-left: ${depth * 1.25}rem"
221
+ style=${this.lines ? nothing : `padding-left: ${depth * 1.25}rem`}
167
222
  @click=${(e) => this.#onRowClick(node, e)}
168
223
  @keydown=${(e) => this.#onKeydown(node, e)}
169
224
  >
225
+ ${guides}
170
226
  <span class="toggle" aria-hidden="true">
171
227
  ${isFolder ? (isOpen ? iconChevronDown(14) : iconChevronRight(14)) : nothing}
172
228
  </span>
173
229
  <span class="content">${this.renderNode(node)}</span>
174
230
  </div>
175
231
  ${isFolder && isOpen
176
- ? repeat(node.children, (child) => child.id, (child) => this.#renderNode(child, depth + 1))
232
+ ? repeat(node.children, (child) => child.id, (child, i) => this.#renderNode(child, depth + 1, i === node.children.length - 1, [
233
+ ...ancestorHasNext,
234
+ !isLast,
235
+ ]))
177
236
  : nothing}
178
237
  `;
179
238
  }
180
239
  render() {
181
- return repeat(this.nodes, (node) => node.id, (node) => this.#renderNode(node, 0));
240
+ return repeat(this.nodes, (node) => node.id, (node, i) => this.#renderNode(node, 0, i === this.nodes.length - 1, []));
182
241
  }
183
242
  };
184
243
  __decorate([
@@ -190,6 +249,9 @@ __decorate([
190
249
  __decorate([
191
250
  property({ type: Boolean, attribute: "default-expanded" })
192
251
  ], TreeView.prototype, "defaultExpanded", void 0);
252
+ __decorate([
253
+ property({ type: Boolean, reflect: true })
254
+ ], TreeView.prototype, "lines", void 0);
193
255
  __decorate([
194
256
  state()
195
257
  ], TreeView.prototype, "expanded", void 0);