luxen-ui 0.4.0 → 0.5.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/cdn/chunks/map.js +2 -0
- package/cdn/chunks/map.js.map +1 -0
- package/cdn/custom-elements.json +6522 -4081
- package/cdn/elements/avatar/avatar.d.ts +1 -1
- package/cdn/elements/avatar/avatar.d.ts.map +1 -1
- package/cdn/elements/avatar/avatar.js +2 -2
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/avatar/index.d.ts +2 -2
- package/cdn/elements/avatar/index.d.ts.map +1 -1
- package/cdn/elements/avatar/index.js +1 -1
- package/cdn/elements/avatar/index.js.map +1 -1
- package/cdn/elements/badge/badge.d.ts +1 -1
- package/cdn/elements/badge/badge.d.ts.map +1 -1
- package/cdn/elements/badge/badge.js +1 -1
- package/cdn/elements/badge/badge.js.map +1 -1
- package/cdn/elements/badge/index.d.ts +2 -2
- package/cdn/elements/badge/index.d.ts.map +1 -1
- package/cdn/elements/badge/index.js +1 -1
- package/cdn/elements/badge/index.js.map +1 -1
- package/cdn/elements/carousel/carousel.d.ts +9 -10
- package/cdn/elements/carousel/carousel.d.ts.map +1 -1
- package/cdn/elements/carousel/carousel.js +4 -4
- package/cdn/elements/carousel/carousel.js.map +1 -1
- package/cdn/elements/carousel/index.d.ts +2 -2
- package/cdn/elements/carousel/index.d.ts.map +1 -1
- package/cdn/elements/carousel/index.js +1 -1
- package/cdn/elements/carousel/index.js.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.d.ts +1 -1
- package/cdn/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.js +1 -1
- package/cdn/elements/carousel-item/carousel-item.js.map +1 -1
- package/cdn/elements/carousel-item/index.d.ts +2 -2
- package/cdn/elements/carousel-item/index.d.ts.map +1 -1
- package/cdn/elements/carousel-item/index.js +1 -1
- package/cdn/elements/carousel-item/index.js.map +1 -1
- package/cdn/elements/dialog/dialog.d.ts +1 -1
- package/cdn/elements/dialog/dialog.d.ts.map +1 -1
- package/cdn/elements/dialog/dialog.js +1 -1
- package/cdn/elements/dialog/dialog.js.map +1 -1
- package/cdn/elements/dialog/dialog.styles.js.map +1 -1
- package/cdn/elements/dialog/index.d.ts +2 -2
- package/cdn/elements/dialog/index.d.ts.map +1 -1
- package/cdn/elements/dialog/index.js +1 -1
- package/cdn/elements/dialog/index.js.map +1 -1
- package/cdn/elements/divider/divider.d.ts +1 -1
- package/cdn/elements/divider/divider.d.ts.map +1 -1
- package/cdn/elements/divider/divider.js +1 -1
- package/cdn/elements/divider/divider.js.map +1 -1
- package/cdn/elements/divider/index.d.ts +2 -2
- package/cdn/elements/divider/index.d.ts.map +1 -1
- package/cdn/elements/divider/index.js +1 -1
- package/cdn/elements/divider/index.js.map +1 -1
- package/cdn/elements/drawer/drawer.d.ts +2 -2
- package/cdn/elements/drawer/drawer.d.ts.map +1 -1
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/drawer/drawer.js.map +1 -1
- package/cdn/elements/drawer/index.d.ts +2 -2
- package/cdn/elements/drawer/index.d.ts.map +1 -1
- package/cdn/elements/drawer/index.js +1 -1
- package/cdn/elements/drawer/index.js.map +1 -1
- package/cdn/elements/dropdown/dropdown.d.ts +2 -2
- package/cdn/elements/dropdown/dropdown.d.ts.map +1 -1
- package/cdn/elements/dropdown/dropdown.js +1 -1
- package/cdn/elements/dropdown/dropdown.js.map +1 -1
- package/cdn/elements/dropdown/index.d.ts +2 -2
- package/cdn/elements/dropdown/index.d.ts.map +1 -1
- package/cdn/elements/dropdown/index.js +1 -1
- package/cdn/elements/dropdown/index.js.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.d.ts +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
- package/cdn/elements/dropdown-item/index.d.ts +2 -2
- package/cdn/elements/dropdown-item/index.d.ts.map +1 -1
- package/cdn/elements/dropdown-item/index.js +1 -1
- package/cdn/elements/dropdown-item/index.js.map +1 -1
- package/cdn/elements/icon/icon.d.ts +1 -1
- package/cdn/elements/icon/icon.d.ts.map +1 -1
- package/cdn/elements/icon/icon.js +1 -1
- package/cdn/elements/icon/icon.js.map +1 -1
- package/cdn/elements/icon/index.d.ts +2 -2
- package/cdn/elements/icon/index.d.ts.map +1 -1
- package/cdn/elements/icon/index.js +1 -1
- package/cdn/elements/icon/index.js.map +1 -1
- package/cdn/elements/input-otp/index.d.ts +2 -2
- package/cdn/elements/input-otp/index.d.ts.map +1 -1
- package/cdn/elements/input-otp/index.js +1 -1
- package/cdn/elements/input-otp/index.js.map +1 -1
- package/cdn/elements/input-otp/input-otp.d.ts +1 -1
- package/cdn/elements/input-otp/input-otp.d.ts.map +1 -1
- package/cdn/elements/input-otp/input-otp.js +1 -1
- package/cdn/elements/input-otp/input-otp.js.map +1 -1
- package/cdn/elements/input-stepper/index.d.ts +2 -2
- package/cdn/elements/input-stepper/index.d.ts.map +1 -1
- package/cdn/elements/input-stepper/index.js +1 -1
- package/cdn/elements/input-stepper/index.js.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.d.ts +1 -1
- package/cdn/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.js +1 -1
- package/cdn/elements/input-stepper/input-stepper.js.map +1 -1
- package/cdn/elements/popover/index.d.ts +2 -2
- package/cdn/elements/popover/index.d.ts.map +1 -1
- package/cdn/elements/popover/index.js +1 -1
- package/cdn/elements/popover/index.js.map +1 -1
- package/cdn/elements/popover/popover.d.ts +1 -1
- package/cdn/elements/popover/popover.d.ts.map +1 -1
- package/cdn/elements/popover/popover.js +1 -1
- package/cdn/elements/popover/popover.js.map +1 -1
- package/cdn/elements/rating/index.d.ts +2 -2
- package/cdn/elements/rating/index.d.ts.map +1 -1
- package/cdn/elements/rating/index.js +1 -1
- package/cdn/elements/rating/index.js.map +1 -1
- package/cdn/elements/rating/rating.d.ts +1 -1
- package/cdn/elements/rating/rating.d.ts.map +1 -1
- package/cdn/elements/rating/rating.js +2 -2
- package/cdn/elements/rating/rating.js.map +1 -1
- package/cdn/elements/skeleton/index.d.ts +2 -2
- package/cdn/elements/skeleton/index.d.ts.map +1 -1
- package/cdn/elements/skeleton/index.js +1 -1
- package/cdn/elements/skeleton/index.js.map +1 -1
- package/cdn/elements/skeleton/skeleton.d.ts +1 -1
- package/cdn/elements/skeleton/skeleton.d.ts.map +1 -1
- package/cdn/elements/skeleton/skeleton.js +1 -1
- package/cdn/elements/skeleton/skeleton.js.map +1 -1
- package/cdn/elements/spinner/index.d.ts +2 -2
- package/cdn/elements/spinner/index.d.ts.map +1 -1
- package/cdn/elements/spinner/index.js +1 -1
- package/cdn/elements/spinner/index.js.map +1 -1
- package/cdn/elements/spinner/spinner.d.ts +1 -1
- package/cdn/elements/spinner/spinner.d.ts.map +1 -1
- package/cdn/elements/spinner/spinner.js +1 -1
- package/cdn/elements/spinner/spinner.js.map +1 -1
- package/cdn/elements/sticky-bar/index.d.ts +8 -0
- package/cdn/elements/sticky-bar/index.d.ts.map +1 -0
- package/cdn/elements/sticky-bar/index.js +2 -0
- package/cdn/elements/sticky-bar/index.js.map +1 -0
- package/cdn/elements/sticky-bar/sticky-bar.d.ts +46 -0
- package/cdn/elements/sticky-bar/sticky-bar.d.ts.map +1 -0
- package/cdn/elements/sticky-bar/sticky-bar.js +2 -0
- package/cdn/elements/sticky-bar/sticky-bar.js.map +1 -0
- package/cdn/elements/stories/index.d.ts +8 -0
- package/cdn/elements/stories/index.d.ts.map +1 -0
- package/cdn/elements/stories/index.js +2 -0
- package/cdn/elements/stories/index.js.map +1 -0
- package/cdn/elements/stories/stories.d.ts +50 -0
- package/cdn/elements/stories/stories.d.ts.map +1 -0
- package/cdn/elements/stories/stories.js +2 -0
- package/cdn/elements/stories/stories.js.map +1 -0
- package/cdn/elements/stories-viewer/index.d.ts +8 -0
- package/cdn/elements/stories-viewer/index.d.ts.map +1 -0
- package/cdn/elements/stories-viewer/index.js +2 -0
- package/cdn/elements/stories-viewer/index.js.map +1 -0
- package/cdn/elements/stories-viewer/stories-viewer.d.ts +136 -0
- package/cdn/elements/stories-viewer/stories-viewer.d.ts.map +1 -0
- package/cdn/elements/stories-viewer/stories-viewer.js +160 -0
- package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -0
- package/cdn/elements/story/index.d.ts +8 -0
- package/cdn/elements/story/index.d.ts.map +1 -0
- package/cdn/elements/story/index.js +2 -0
- package/cdn/elements/story/index.js.map +1 -0
- package/cdn/elements/story/story.d.ts +48 -0
- package/cdn/elements/story/story.d.ts.map +1 -0
- package/cdn/elements/story/story.js +35 -0
- package/cdn/elements/story/story.js.map +1 -0
- package/cdn/elements/tabs/index.d.ts +2 -2
- package/cdn/elements/tabs/index.d.ts.map +1 -1
- package/cdn/elements/tabs/index.js +1 -1
- package/cdn/elements/tabs/index.js.map +1 -1
- package/cdn/elements/tabs/tabs.d.ts +1 -1
- package/cdn/elements/tabs/tabs.d.ts.map +1 -1
- package/cdn/elements/tabs/tabs.js +1 -1
- package/cdn/elements/tabs/tabs.js.map +1 -1
- package/cdn/elements/toast/index.d.ts +3 -3
- package/cdn/elements/toast/index.d.ts.map +1 -1
- package/cdn/elements/toast/index.js +1 -1
- package/cdn/elements/toast/index.js.map +1 -1
- package/cdn/elements/toast/toast.d.ts +2 -2
- package/cdn/elements/toast/toast.d.ts.map +1 -1
- package/cdn/elements/toast/toast.js +1 -1
- package/cdn/elements/toast/toast.js.map +1 -1
- package/cdn/elements/tooltip/index.d.ts +2 -2
- package/cdn/elements/tooltip/index.d.ts.map +1 -1
- package/cdn/elements/tooltip/index.js +1 -1
- package/cdn/elements/tooltip/index.js.map +1 -1
- package/cdn/elements/tooltip/tooltip.d.ts +1 -1
- package/cdn/elements/tooltip/tooltip.d.ts.map +1 -1
- package/cdn/elements/tooltip/tooltip.js +1 -1
- package/cdn/elements/tooltip/tooltip.js.map +1 -1
- package/cdn/elements/tree/index.d.ts +2 -2
- package/cdn/elements/tree/index.d.ts.map +1 -1
- package/cdn/elements/tree/index.js +1 -1
- package/cdn/elements/tree/index.js.map +1 -1
- package/cdn/elements/tree/tree.d.ts +5 -5
- package/cdn/elements/tree/tree.d.ts.map +1 -1
- package/cdn/elements/tree/tree.js +1 -1
- package/cdn/elements/tree/tree.js.map +1 -1
- package/cdn/elements/tree-item/index.d.ts +2 -2
- package/cdn/elements/tree-item/index.d.ts.map +1 -1
- package/cdn/elements/tree-item/index.js +1 -1
- package/cdn/elements/tree-item/index.js.map +1 -1
- package/cdn/elements/tree-item/tree-item.d.ts +2 -2
- package/cdn/elements/tree-item/tree-item.d.ts.map +1 -1
- package/cdn/elements/tree-item/tree-item.js +1 -1
- package/cdn/elements/tree-item/tree-item.js.map +1 -1
- package/cdn/registry.d.ts +1 -1
- package/cdn/registry.d.ts.map +1 -1
- package/cdn/registry.js.map +1 -1
- package/cdn/shared/controllers/popover.js.map +1 -1
- package/cdn/shared/styles/host.styles.js.map +1 -1
- package/cdn/styles/elements/stories.css +63 -0
- package/cdn/styles/elements/story.css +192 -0
- package/cdn/styles/index.css +3 -0
- package/dist/css/elements/stories.css +63 -0
- package/dist/css/elements/story.css +192 -0
- package/dist/css/index.css +3 -0
- package/dist/custom-elements.json +6522 -4081
- package/dist/elements/avatar/avatar.d.ts +1 -1
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +11 -11
- package/dist/elements/avatar/index.d.ts +2 -2
- package/dist/elements/avatar/index.d.ts.map +1 -1
- package/dist/elements/avatar/index.js +2 -2
- package/dist/elements/badge/badge.d.ts +1 -1
- package/dist/elements/badge/badge.d.ts.map +1 -1
- package/dist/elements/badge/badge.js +5 -5
- package/dist/elements/badge/index.d.ts +2 -2
- package/dist/elements/badge/index.d.ts.map +1 -1
- package/dist/elements/badge/index.js +2 -2
- package/dist/elements/carousel/carousel.d.ts +9 -10
- package/dist/elements/carousel/carousel.d.ts.map +1 -1
- package/dist/elements/carousel/carousel.js +132 -140
- package/dist/elements/carousel/index.d.ts +2 -2
- package/dist/elements/carousel/index.d.ts.map +1 -1
- package/dist/elements/carousel/index.js +2 -2
- package/dist/elements/carousel-item/carousel-item.d.ts +1 -1
- package/dist/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/dist/elements/carousel-item/carousel-item.js +2 -2
- package/dist/elements/carousel-item/index.d.ts +2 -2
- package/dist/elements/carousel-item/index.d.ts.map +1 -1
- package/dist/elements/carousel-item/index.js +2 -2
- package/dist/elements/dialog/dialog.d.ts +1 -1
- package/dist/elements/dialog/dialog.d.ts.map +1 -1
- package/dist/elements/dialog/dialog.js +9 -9
- package/dist/elements/dialog/index.d.ts +2 -2
- package/dist/elements/dialog/index.d.ts.map +1 -1
- package/dist/elements/dialog/index.js +2 -2
- package/dist/elements/divider/divider.d.ts +1 -1
- package/dist/elements/divider/divider.d.ts.map +1 -1
- package/dist/elements/divider/divider.js +3 -3
- package/dist/elements/divider/index.d.ts +2 -2
- package/dist/elements/divider/index.d.ts.map +1 -1
- package/dist/elements/divider/index.js +2 -2
- package/dist/elements/drawer/drawer.d.ts +2 -2
- package/dist/elements/drawer/drawer.d.ts.map +1 -1
- package/dist/elements/drawer/drawer.js +4 -4
- package/dist/elements/drawer/index.d.ts +2 -2
- package/dist/elements/drawer/index.d.ts.map +1 -1
- package/dist/elements/drawer/index.js +2 -2
- package/dist/elements/dropdown/dropdown.d.ts +2 -2
- package/dist/elements/dropdown/dropdown.d.ts.map +1 -1
- package/dist/elements/dropdown/dropdown.js +22 -22
- package/dist/elements/dropdown/index.d.ts +2 -2
- package/dist/elements/dropdown/index.d.ts.map +1 -1
- package/dist/elements/dropdown/index.js +2 -2
- package/dist/elements/dropdown-item/dropdown-item.d.ts +1 -1
- package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/dist/elements/dropdown-item/dropdown-item.js +20 -20
- package/dist/elements/dropdown-item/index.d.ts +2 -2
- package/dist/elements/dropdown-item/index.d.ts.map +1 -1
- package/dist/elements/dropdown-item/index.js +2 -2
- package/dist/elements/icon/icon.d.ts +1 -1
- package/dist/elements/icon/icon.d.ts.map +1 -1
- package/dist/elements/icon/icon.js +4 -4
- package/dist/elements/icon/index.d.ts +2 -2
- package/dist/elements/icon/index.d.ts.map +1 -1
- package/dist/elements/icon/index.js +2 -2
- package/dist/elements/input-otp/index.d.ts +2 -2
- package/dist/elements/input-otp/index.d.ts.map +1 -1
- package/dist/elements/input-otp/index.js +2 -2
- package/dist/elements/input-otp/input-otp.d.ts +1 -1
- package/dist/elements/input-otp/input-otp.d.ts.map +1 -1
- package/dist/elements/input-otp/input-otp.js +2 -2
- package/dist/elements/input-stepper/index.d.ts +2 -2
- package/dist/elements/input-stepper/index.d.ts.map +1 -1
- package/dist/elements/input-stepper/index.js +2 -2
- package/dist/elements/input-stepper/input-stepper.d.ts +1 -1
- package/dist/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/dist/elements/input-stepper/input-stepper.js +8 -8
- package/dist/elements/popover/index.d.ts +2 -2
- package/dist/elements/popover/index.d.ts.map +1 -1
- package/dist/elements/popover/index.js +2 -2
- package/dist/elements/popover/popover.d.ts +1 -1
- package/dist/elements/popover/popover.d.ts.map +1 -1
- package/dist/elements/popover/popover.js +33 -33
- package/dist/elements/rating/index.d.ts +2 -2
- package/dist/elements/rating/index.d.ts.map +1 -1
- package/dist/elements/rating/index.js +2 -2
- package/dist/elements/rating/rating.d.ts +1 -1
- package/dist/elements/rating/rating.d.ts.map +1 -1
- package/dist/elements/rating/rating.js +48 -48
- package/dist/elements/skeleton/index.d.ts +2 -2
- package/dist/elements/skeleton/index.d.ts.map +1 -1
- package/dist/elements/skeleton/index.js +2 -2
- package/dist/elements/skeleton/skeleton.d.ts +1 -1
- package/dist/elements/skeleton/skeleton.d.ts.map +1 -1
- package/dist/elements/skeleton/skeleton.js +1 -1
- package/dist/elements/spinner/index.d.ts +2 -2
- package/dist/elements/spinner/index.d.ts.map +1 -1
- package/dist/elements/spinner/index.js +2 -2
- package/dist/elements/spinner/spinner.d.ts +1 -1
- package/dist/elements/spinner/spinner.d.ts.map +1 -1
- package/dist/elements/spinner/spinner.js +2 -2
- package/dist/elements/sticky-bar/index.d.ts +8 -0
- package/dist/elements/sticky-bar/index.d.ts.map +1 -0
- package/dist/elements/sticky-bar/index.js +4 -0
- package/dist/elements/sticky-bar/sticky-bar.css +56 -0
- package/dist/elements/sticky-bar/sticky-bar.d.ts +46 -0
- package/dist/elements/sticky-bar/sticky-bar.d.ts.map +1 -0
- package/dist/elements/sticky-bar/sticky-bar.js +146 -0
- package/dist/elements/stories/index.d.ts +8 -0
- package/dist/elements/stories/index.d.ts.map +1 -0
- package/dist/elements/stories/index.js +4 -0
- package/dist/elements/stories/stories.d.ts +50 -0
- package/dist/elements/stories/stories.d.ts.map +1 -0
- package/dist/elements/stories/stories.js +113 -0
- package/dist/elements/stories-viewer/index.d.ts +8 -0
- package/dist/elements/stories-viewer/index.d.ts.map +1 -0
- package/dist/elements/stories-viewer/index.js +4 -0
- package/dist/elements/stories-viewer/stories-viewer.css +337 -0
- package/dist/elements/stories-viewer/stories-viewer.d.ts +136 -0
- package/dist/elements/stories-viewer/stories-viewer.d.ts.map +1 -0
- package/dist/elements/stories-viewer/stories-viewer.js +719 -0
- package/dist/elements/story/index.d.ts +8 -0
- package/dist/elements/story/index.d.ts.map +1 -0
- package/dist/elements/story/index.js +4 -0
- package/dist/elements/story/story.d.ts +48 -0
- package/dist/elements/story/story.d.ts.map +1 -0
- package/dist/elements/story/story.js +161 -0
- package/dist/elements/tabs/index.d.ts +2 -2
- package/dist/elements/tabs/index.d.ts.map +1 -1
- package/dist/elements/tabs/index.js +2 -2
- package/dist/elements/tabs/tabs.d.ts +1 -1
- package/dist/elements/tabs/tabs.d.ts.map +1 -1
- package/dist/elements/tabs/tabs.js +5 -5
- package/dist/elements/toast/index.d.ts +3 -3
- package/dist/elements/toast/index.d.ts.map +1 -1
- package/dist/elements/toast/index.js +3 -3
- package/dist/elements/toast/toast.d.ts +2 -2
- package/dist/elements/toast/toast.d.ts.map +1 -1
- package/dist/elements/toast/toast.js +5 -5
- package/dist/elements/tooltip/index.d.ts +2 -2
- package/dist/elements/tooltip/index.d.ts.map +1 -1
- package/dist/elements/tooltip/index.js +2 -2
- package/dist/elements/tooltip/tooltip.d.ts +1 -1
- package/dist/elements/tooltip/tooltip.d.ts.map +1 -1
- package/dist/elements/tooltip/tooltip.js +29 -29
- package/dist/elements/tree/index.d.ts +2 -2
- package/dist/elements/tree/index.d.ts.map +1 -1
- package/dist/elements/tree/index.js +2 -2
- package/dist/elements/tree/tree.d.ts +5 -5
- package/dist/elements/tree/tree.d.ts.map +1 -1
- package/dist/elements/tree/tree.js +14 -16
- package/dist/elements/tree-item/index.d.ts +2 -2
- package/dist/elements/tree-item/index.d.ts.map +1 -1
- package/dist/elements/tree-item/index.js +2 -2
- package/dist/elements/tree-item/tree-item.d.ts +2 -2
- package/dist/elements/tree-item/tree-item.d.ts.map +1 -1
- package/dist/elements/tree-item/tree-item.js +28 -28
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/skills/luxen-ui/SKILL.md +1 -0
- package/dist/skills/luxen-ui/references/sticky-bar.md +148 -0
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stories-viewer.js","names":[],"sources":["../../../src/html/elements/stories-viewer/stories-viewer.css?inline","../../../src/html/elements/stories-viewer/stories-viewer.ts"],"sourcesContent":[":host {\n --width: min(420px, 100vw);\n --aspect-ratio: 9 / 16;\n --progress-color: white;\n --progress-bg: rgb(255 255 255 / 35%);\n --progress-gap: 4px;\n --show-duration: 200ms;\n --hide-duration: 200ms;\n /* Semi-transparent backdrop so the underlying page (e.g. a product page) stays visible behind the player, but with enough darkness to focus attention on the frame. Override with `--backdrop: …` or set to `oklch(0% 0 0 / 90%)` for an opaque blackout. */\n --backdrop: var(--l-backdrop-strong);\n\n display: contents;\n}\n\ndialog {\n position: fixed;\n inset: 0;\n width: 100vw;\n height: 100dvh;\n max-width: none;\n max-height: none;\n margin: 0;\n padding: 0;\n border: 0;\n background: transparent;\n color: white;\n overflow: clip;\n\n /* Center the frame at all times. `place-items` is on the base rule so it survives the close transition (only `display` and `opacity` are transitioned with `allow-discrete`; non-transitioned properties revert immediately when `[open]` is removed and would un-center the frame to top-left for one frame). */\n place-items: center;\n\n /* EXIT STATE */\n opacity: 0;\n\n transition-property: opacity, display, overlay;\n transition-duration: var(--hide-duration);\n transition-behavior: allow-discrete;\n\n &::backdrop {\n background: var(--backdrop);\n }\n\n /* OPEN STATE */\n &[open] {\n display: grid;\n opacity: 1;\n transition-duration: var(--show-duration);\n }\n\n /* BEFORE-OPEN STATE */\n @starting-style {\n &[open] {\n opacity: 0;\n }\n }\n}\n\n.frame {\n position: relative;\n width: var(--width);\n max-width: 100vw;\n max-height: 100dvh;\n aspect-ratio: var(--aspect-ratio);\n background: black;\n border-radius: 0.75rem;\n overflow: clip;\n isolation: isolate;\n user-select: none;\n -webkit-user-select: none;\n touch-action: pan-y;\n}\n\n@media (max-width: 480px) {\n .frame {\n width: 100vw;\n height: 100dvh;\n aspect-ratio: auto;\n border-radius: 0;\n }\n}\n\n.video {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n background: black;\n}\n\n/* Loading spinner — centered over the video. Delayed fade-in so a fast buffer never visibly flashes the spinner. */\n.spinner {\n position: absolute;\n inset: 0;\n margin: auto;\n z-index: 1;\n width: 2rem;\n height: 2rem;\n color: white;\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease;\n}\n\n.spinner[data-state='loading'] {\n opacity: 1;\n /* Only paint the spinner if loading actually exceeds 200ms. */\n transition-delay: 200ms;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .spinner {\n transition: none;\n }\n}\n\n.progress {\n position: absolute;\n top: 0.5rem;\n left: 0.5rem;\n right: 0.5rem;\n z-index: 2;\n display: flex;\n gap: var(--progress-gap);\n pointer-events: none;\n}\n\n.progress-segment {\n flex: 1 1 0;\n height: 2.5px;\n border-radius: 999px;\n background: var(--progress-bg);\n overflow: clip;\n}\n\n.progress-fill {\n display: block;\n width: 100%;\n height: 100%;\n background: var(--progress-color);\n transform: scaleX(var(--p, 0));\n transform-origin: left;\n transition: transform 80ms linear;\n}\n\n.progress-segment[data-state='past'] .progress-fill {\n transform: scaleX(1);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .progress-fill {\n transition: none;\n }\n :host {\n --show-duration: 0ms;\n --hide-duration: 0ms;\n }\n}\n\n/* Top-left header — story thumbnail + label (slot fallback) or consumer-supplied content. */\n.header {\n position: absolute;\n top: 1.25rem;\n left: 0.75rem;\n right: 4rem; /* leave room for the right-side action stack */\n z-index: 2;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n min-width: 0;\n pointer-events: none;\n}\n\n.header > ::slotted(*) {\n pointer-events: auto;\n}\n\n.header-thumb {\n width: 2rem;\n height: 2rem;\n border-radius: 50%;\n object-fit: cover;\n flex-shrink: 0;\n pointer-events: auto;\n}\n\n.header-text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n pointer-events: auto;\n}\n\n.header-label {\n font-size: 0.875rem;\n font-weight: 600;\n line-height: 1.2;\n color: white;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Top-right vertical action stack — close, play/pause, mute. */\n.actions {\n position: absolute;\n top: 1.25rem;\n right: 0.75rem;\n z-index: 2;\n display: flex;\n flex-direction: column;\n /* 12px gap leaves room for the 6px hit-area extension on each adjacent button (see `.btn::before` below). */\n gap: 0.75rem;\n pointer-events: none;\n}\n\n.actions > ::slotted(*),\n.actions .btn {\n pointer-events: auto;\n}\n\n.btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n border: 0;\n border-radius: 999px;\n background: rgb(0 0 0 / 25%);\n color: white;\n font-size: 1rem;\n cursor: pointer;\n transition: background 150ms ease;\n\n &:hover {\n background: rgb(0 0 0 / 45%);\n }\n\n &:focus-visible {\n outline: 2px solid var(--progress-color);\n outline-offset: 2px;\n }\n\n /* WCAG 2.1 SC 2.5.5 / RGAA 13.4 — 44×44 hit area without changing the visible 32×32 disc. The pseudo carries no paint, only hit testing. */\n &::before {\n content: '';\n position: absolute;\n inset: -6px;\n }\n}\n\n.btn-nav {\n position: absolute;\n z-index: 2;\n width: 2.25rem;\n height: 2.25rem;\n font-size: 1.25rem;\n\n /* Chevrons start at 36×36 — 4px each side reaches 44. */\n &::before {\n inset: -4px;\n }\n}\n\n.btn-previous,\n.btn-next {\n top: 50%;\n transform: translateY(-50%);\n}\n\n/* Desktop ≥ 768px: chevrons sit outside the frame, on the dim backdrop. */\n@media (min-width: 768px) {\n .btn-previous {\n left: calc(50% - var(--width) / 2 - 3rem);\n }\n .btn-next {\n right: calc(50% - var(--width) / 2 - 3rem);\n }\n}\n\n/* Mobile < 768px: hide chevrons entirely — tap zones drive nav. */\n@media (max-width: 767px) {\n .btn-previous,\n .btn-next {\n display: none;\n }\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆃🅰🅿 zones (invisible click/tap targets — left = previous, rest = next)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n*/\n\n.tap-zone {\n position: absolute;\n top: 0;\n bottom: 0;\n z-index: 0;\n}\n\n.tap-previous {\n left: 0;\n width: 30%;\n}\n\n.tap-next {\n left: 30%;\n right: 0;\n}\n\n.overlay {\n position: absolute;\n inset: auto 0 0 0;\n z-index: 1;\n padding: 1rem;\n pointer-events: none;\n}\n\n.overlay > ::slotted(*) {\n pointer-events: auto;\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n","import { html, nothing, unsafeCSS, type CSSResultGroup, type PropertyValues } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { map } from 'lit/directives/map.js';\nimport { LuxenElement } from '../../shared/luxen-element';\nimport hostStyles from '../../shared/styles/host.styles';\nimport type { LuxenStories } from '../stories/stories';\nimport type { LuxenStory } from '../story/story';\nimport rawStyles from './stories-viewer.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nconst SCROLL_LOCK_SHEET = Symbol.for('luxen-stories-viewer-scroll-lock');\nif (typeof document !== 'undefined' && !(SCROLL_LOCK_SHEET in document)) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(\n `html:has(l-stories-viewer[data-modal]) { overflow: hidden; scrollbar-gutter: stable; }`,\n );\n document.adoptedStyleSheets.push(sheet);\n Object.defineProperty(document, SCROLL_LOCK_SHEET, { value: sheet });\n}\n\n/**\n * @summary Fullscreen modal that plays a sequence of `<l-story>` videos with an\n * Instagram-style segmented progress bar, previous/next navigation, mute toggle,\n * and auto-advance.\n *\n * Linked to one or more `<l-stories>` rows via matching `id` ↔ `for`. Open\n * programmatically via `open()` or by clicking a thumbnail in a linked row.\n *\n * @slot cta - Default CTA overlay (e.g. shoppable card). Per-story `slot=\"cta\"` inside `<l-story>` overrides this when that story is active.\n * @slot header - Default header overlay (e.g. avatar + author). Per-story override available the same way.\n * @slot close - Override the default close button.\n *\n * @csspart dialog - The native `<dialog>` element.\n * @csspart frame - The aspect-ratio video frame.\n * @csspart progress - The progress bar wrapper.\n * @csspart progress-segment - A single progress segment.\n * @csspart progress-fill - The fill element inside an active segment.\n * @csspart video - The `<video>` element.\n * @csspart overlay - The overlay wrapper that hosts CTA/header slots.\n * @csspart header - The top-left header area (story thumbnail + label fallback, or consumer-supplied content via the `header` slot).\n * @csspart header-label - The default story label inside the header.\n * @csspart actions - The top-right vertical button stack (close, play/pause, mute).\n * @csspart button-close - The close button.\n * @csspart button-pause - The play/pause toggle.\n * @csspart button-mute - The mute toggle.\n * @csspart button-previous - The previous story button.\n * @csspart button-next - The next story button.\n * @csspart spinner - The loading spinner shown while the current video is buffering.\n *\n * @cssproperty --width - Frame width. Default `min(420px, 100vw)`.\n * @cssproperty --progress-color - Active progress fill color. Default `white`.\n * @cssproperty --progress-bg - Inactive progress segment background. Default `rgb(255 255 255 / 35%)`.\n * @cssproperty --progress-gap - Gap between segments. Default `4px`.\n * @cssproperty --show-duration - Open transition duration. Default `200ms`.\n * @cssproperty --hide-duration - Close transition duration. Default `200ms`.\n * @cssproperty --backdrop - Backdrop color. Default `var(--l-backdrop-strong)` — darker than `--l-backdrop` to focus attention on the immersive frame, but still translucent so the page stays perceptible.\n *\n * @event show - Fired when the viewer opens.\n * @event after-show - Fired after the open transition completes.\n * @event hide - Fired when the viewer is about to close. Cancelable.\n * @event after-hide - Fired after the close transition completes.\n * @event story-change - Fired when the active story changes. Detail: `{ index: number, story: LuxenStory }`.\n * @event story-end - Fired when the active story finishes playback. Detail: `{ index: number }`.\n * @event chapter-change - Fired when the active chapter (within a story) changes. Detail: `{ chapter: number, story: LuxenStory }`.\n * @event mute-change - Fired when the mute state changes. Detail: `{ muted: boolean }`.\n *\n * @customElement l-stories-viewer\n */\nexport class LuxenStoriesViewer extends LuxenElement {\n static override styles: CSSResultGroup = [hostStyles, styles];\n\n /** Whether the viewer is open. */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /** Active story index (0-based). */\n @property({ type: Number, reflect: true })\n index = 0;\n\n /** Whether playback is muted. Defaults to `true` so autoplay always succeeds across browsers. The user can unmute via the dedicated button or the `m` keyboard shortcut. */\n @property({ type: Boolean, reflect: true })\n muted = true;\n\n /** Loop the active story instead of advancing. */\n @property({ type: Boolean, reflect: true })\n loop = false;\n\n /** Move to the next story when the current one ends; close after the last story. */\n @property({ type: Boolean, reflect: true, attribute: 'auto-advance' })\n autoAdvance = true;\n\n /** Close when the backdrop is clicked. */\n @property({ type: Boolean, reflect: true, attribute: 'light-dismiss' })\n lightDismiss = true;\n\n /** Active chapter index within the current story. Reflected. */\n @property({ type: Number, reflect: true })\n chapter = 0;\n\n /** Internal: the playlist set by the source `<l-stories>`. */\n stories: LuxenStory[] = [];\n\n /** Internal: the source `<l-stories>` element that opened the viewer. */\n source: LuxenStories | null = null;\n\n @query('dialog') private _dialog!: HTMLDialogElement;\n @query('video') private _video!: HTMLVideoElement;\n\n /** Tracks the underlying `<video>` paused state so the play/pause button stays in sync. */\n @state() private _paused = false;\n\n /** True while the video is buffering / waiting for data. Drives the loading spinner. */\n @state() private _loading = false;\n\n private _raf = 0;\n private _holdTimer = 0;\n private _pointerStart: { x: number; y: number; t: number } | null = null;\n private _segments: HTMLElement[] = [];\n private _chapterStarts: number[] = [0];\n /** Tracks the URL we've already injected a prefetch hint for so we don't duplicate. */\n private _prefetchedSrc: string | null = null;\n\n // --- Lifecycle ---\n\n override connectedCallback() {\n super.connectedCallback();\n this.addEventListener('keydown', this._onKeyDown);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._onKeyDown);\n cancelAnimationFrame(this._raf);\n clearTimeout(this._holdTimer);\n this._clearPrefetchHints();\n }\n\n override firstUpdated() {\n this._dialog.addEventListener('cancel', (e) => this._onCancel(e));\n this._dialog.addEventListener('close', () => this._onNativeClose());\n this._dialog.addEventListener('click', (e) => this._onDialogClick(e));\n this._video.addEventListener('ended', () => this._onEnded());\n this._video.addEventListener('loadedmetadata', () => this._tick());\n this._video.addEventListener('play', () => (this._paused = false));\n this._video.addEventListener('pause', () => (this._paused = true));\n // Loading spinner state — shown during initial buffer and any subsequent stalls,\n // hidden as soon as the video is actually painting frames.\n this._video.addEventListener('loadstart', () => (this._loading = true));\n this._video.addEventListener('waiting', () => (this._loading = true));\n this._video.addEventListener('playing', () => (this._loading = false));\n this._video.addEventListener('canplay', () => (this._loading = false));\n this._video.addEventListener('error', () => (this._loading = false));\n // Prefetch the next story's video once the current one is past 50% so the\n // transition feels instantaneous. Idempotent via `_prefetchedSrc`.\n this._video.addEventListener('timeupdate', () => this._maybePrefetchNext());\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('open')) {\n if (this.open && !this._dialog.open) {\n this.emit('show');\n this.toggleAttribute('data-modal', true);\n this._dialog.showModal();\n this._loadCurrent();\n void this._emitAfter('after-show');\n } else if (!this.open && this._dialog.open) {\n if (!this.emit('hide', { cancelable: true })) {\n this.open = true;\n return;\n }\n this._dialog.close();\n }\n }\n\n // Story change → reload current story (refreshes chapters, segments, slots, video).\n if (changed.has('index') && this.open) {\n this._loadCurrent();\n const story = this.stories[this.index];\n if (story) this.emit('story-change', { detail: { index: this.index, story } });\n }\n\n // Chapter change within the current story → seek + refresh segment fills.\n if (changed.has('chapter') && this.open && !changed.has('index')) {\n this._applyChapterSeek();\n }\n\n if (changed.has('muted') && this._video) {\n this._video.muted = this.muted;\n }\n }\n\n // --- Dialog event handlers ---\n\n private _onCancel(e: Event) {\n if (!this.emit('hide', { cancelable: true })) {\n e.preventDefault();\n }\n }\n\n private _onNativeClose() {\n cancelAnimationFrame(this._raf);\n this._video.pause();\n this._video.removeAttribute('src');\n this._video.load();\n this._clearPrefetchHints();\n // Mark all stories up to and including this.index as seen.\n for (let i = 0; i <= this.index && i < this.stories.length; i++) {\n this.stories[i].seen = true;\n }\n this._restoreFocus();\n this.open = false;\n this.removeAttribute('data-modal');\n void this._emitAfter('after-hide');\n }\n\n private _onDialogClick(e: MouseEvent) {\n if (!this.lightDismiss) return;\n // Backdrop click: target is the <dialog>, not a child.\n if (e.target === this._dialog) {\n this.open = false;\n }\n }\n\n // --- Keyboard ---\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (!this.open) return;\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n this.previous();\n break;\n case 'ArrowRight':\n e.preventDefault();\n this.next();\n break;\n case ' ':\n e.preventDefault();\n if (this._video.paused) this.play();\n else this.pause();\n break;\n case 'm':\n case 'M':\n e.preventDefault();\n this.muted = !this.muted;\n this.emit('mute-change', { detail: { muted: this.muted } });\n break;\n }\n };\n\n // --- Pointer / touch (long-press to pause, tap-to-advance, swipe to close) ---\n\n private _onFramePointerDown = (e: PointerEvent) => {\n // Skip buttons, links, and explicitly-marked no-gesture areas.\n if ((e.target as HTMLElement).closest('button, a, [data-no-gesture]')) return;\n this._pointerStart = { x: e.clientX, y: e.clientY, t: performance.now() };\n this._holdTimer = window.setTimeout(() => this.pause(), 200);\n };\n\n private _onFramePointerUp = (e: PointerEvent) => {\n clearTimeout(this._holdTimer);\n const start = this._pointerStart;\n this._pointerStart = null;\n if (!start) return;\n\n const dx = e.clientX - start.x;\n const dy = e.clientY - start.y;\n const elapsed = performance.now() - start.t;\n const isTap = elapsed < 200 && Math.abs(dx) < 10 && Math.abs(dy) < 10;\n const wasLongPress = elapsed >= 200 && Math.abs(dx) < 10 && Math.abs(dy) < 10;\n const SWIPE = 50;\n\n if (wasLongPress) {\n if (this._video.paused) this.play();\n return;\n }\n\n if (isTap) {\n // Tap zones: chapter-aware nav. Left ~30% = previous chapter (or previous\n // story at the chapter boundary), anywhere else = next chapter (or next\n // story at the last chapter). Chevron buttons remain story-to-story.\n const tap = (e.target as HTMLElement).closest<HTMLElement>('[data-tap]');\n if (tap?.dataset.tap === 'previous') this.previous();\n else this.next();\n return;\n }\n\n if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > SWIPE) {\n if (dx < 0) this.nextStory();\n else this.previousStory();\n } else if (dy > SWIPE) {\n this.close();\n }\n };\n\n // --- Segments / progress (chapter-based) ---\n\n private _refreshSegmentRefs() {\n this._segments = Array.from(\n this.shadowRoot!.querySelectorAll<HTMLElement>('[part~=\"progress-fill\"]'),\n );\n }\n\n private _resetSegmentFills() {\n this._refreshSegmentRefs();\n for (let i = 0; i < this._segments.length; i++) {\n const p = i < this.chapter ? 1 : 0;\n this._segments[i].style.setProperty('--p', String(p));\n }\n }\n\n private _loadCurrent() {\n const story = this.stories[this.index];\n if (!story) return;\n cancelAnimationFrame(this._raf);\n // Reset the prefetch tracker when the active story changes — the next\n // candidate has shifted and may need its own preload hint.\n this._prefetchedSrc = null;\n this._chapterStarts = story.getChapterStarts();\n this.chapter = 0;\n this._syncSlots(story);\n this._video.muted = this.muted;\n this._video.loop = this.loop;\n if (this._video.src !== story.src) {\n this._video.src = story.src;\n } else {\n this._video.currentTime = 0;\n }\n // Wait one frame for the new segment DOM to render before resetting fills.\n requestAnimationFrame(() => this._resetSegmentFills());\n this._video.play().catch(() => {\n // Autoplay-with-sound rejection: force muted, retry.\n this.muted = true;\n this._video.muted = true;\n this._video.play().catch(() => {});\n });\n }\n\n /**\n * Inject a `<link rel=\"preload\" as=\"video\">` for the next story once the\n * current video crosses 50% playback. Idempotent: tracked by `_prefetchedSrc`,\n * cleaned up on viewer close.\n */\n private _maybePrefetchNext() {\n const v = this._video;\n if (!v.duration || v.currentTime / v.duration < 0.5) return;\n const nextStory = this.stories[this.index + 1];\n if (!nextStory?.src) return;\n if (this._prefetchedSrc === nextStory.src) return;\n this._prefetchedSrc = nextStory.src;\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'video';\n link.href = nextStory.src;\n link.crossOrigin = 'anonymous';\n link.dataset.luxenStoriesPrefetch = '';\n document.head.appendChild(link);\n }\n\n /** Remove every prefetch hint we've injected. Called when the viewer closes. */\n private _clearPrefetchHints() {\n const links = document.head.querySelectorAll<HTMLLinkElement>(\n 'link[data-luxen-stories-prefetch]',\n );\n for (const link of links) link.remove();\n this._prefetchedSrc = null;\n }\n\n private _applyChapterSeek() {\n const target = this._chapterStarts[this.chapter] ?? 0;\n this._video.currentTime = target;\n this._resetSegmentFills();\n const story = this.stories[this.index];\n if (story) this.emit('chapter-change', { detail: { chapter: this.chapter, story } });\n }\n\n private get _lastChapter() {\n return Math.max(0, this._chapterStarts.length - 1);\n }\n\n // Clone the active story's slot-marked children (cta, header) into the\n // viewer's own light DOM so the shadow root's `<slot name=\"cta\">` and\n // `<slot name=\"header\">` project them. Originals stay attached to the\n // story (hidden via CSS) and are reused on every `index` change.\n private _syncSlots(story: LuxenStory) {\n for (const node of Array.from(this.children)) {\n if ((node as HTMLElement).dataset.storySlot !== undefined) node.remove();\n }\n for (const child of Array.from(story.children)) {\n const slotName = (child as HTMLElement).getAttribute?.('slot');\n if (!slotName) continue;\n const clone = child.cloneNode(true) as HTMLElement;\n clone.dataset.storySlot = '';\n this.appendChild(clone);\n }\n }\n\n private _tick = () => {\n if (!this.open) return;\n const v = this._video;\n const seg = this._segments[this.chapter];\n if (v && seg) {\n const start = this._chapterStarts[this.chapter] ?? 0;\n const end = this._chapterStarts[this.chapter + 1] ?? v.duration;\n const span = Math.max(0, end - start);\n const p = span ? Math.max(0, Math.min((v.currentTime - start) / span, 1)) : 0;\n seg.style.setProperty('--p', String(p));\n // Auto-advance chapter when its segment is full and there's a next chapter in this story.\n // (The video element's `ended` event handles the last chapter via `_onEnded`.)\n if (p >= 1 && this.chapter < this._lastChapter) {\n this._advance(1);\n }\n }\n this._raf = requestAnimationFrame(this._tick);\n };\n\n private _onEnded() {\n // Last chapter of the current story finished.\n const story = this.stories[this.index];\n if (story) this.emit('story-end', { detail: { index: this.index } });\n if (this.loop) {\n this._video.currentTime = this._chapterStarts[0] ?? 0;\n this.chapter = 0;\n this._video.play().catch(() => {});\n return;\n }\n if (!this.autoAdvance) return;\n if (this.index < this.stories.length - 1) {\n this.index = this.index + 1;\n } else {\n this.close();\n }\n }\n\n /** chapter-then-story navigation. */\n private _advance(direction: 1 | -1) {\n if (direction === 1) {\n if (this.chapter < this._lastChapter) {\n this.chapter = this.chapter + 1;\n } else if (this.index < this.stories.length - 1) {\n this.index = this.index + 1;\n } else {\n this.close();\n }\n return;\n }\n // direction === -1: Instagram pattern — restart the current chapter if past 1s in.\n const start = this._chapterStarts[this.chapter] ?? 0;\n if (this._video.currentTime > start + 1) {\n this._video.currentTime = start;\n this._resetSegmentFills();\n return;\n }\n if (this.chapter > 0) {\n this.chapter = this.chapter - 1;\n } else if (this.index > 0) {\n // Crossing into the previous story: load it, then jump to its last chapter.\n const previousStory = this.stories[this.index - 1];\n const previousLast = Math.max(0, previousStory.getChapterStarts().length - 1);\n this.index = this.index - 1;\n // After `index` updates, `_loadCurrent()` runs and resets `chapter` to 0.\n // Set `chapter` to the previous story's last chapter on the next microtask.\n queueMicrotask(() => {\n this.chapter = previousLast;\n });\n }\n }\n\n // --- Public API ---\n\n /** Open the viewer at the given index with an explicit playlist. */\n openAt(stories: LuxenStory[], index = 0, source: LuxenStories | null = null) {\n this.stories = stories;\n this.source = source;\n this.index = Math.max(0, Math.min(index, stories.length - 1));\n this.open = true;\n }\n\n close() {\n this.open = false;\n }\n\n /** Advance one chapter, or to the next story at the chapter boundary. */\n next() {\n this._advance(1);\n }\n\n /** Retreat one chapter, restart the current chapter past 1s in, or cross into the previous story. */\n previous() {\n this._advance(-1);\n }\n\n /** Jump to the next story, skipping any remaining chapters in the current story. */\n nextStory() {\n if (this.index < this.stories.length - 1) {\n this.index = this.index + 1;\n } else {\n this.close();\n }\n }\n\n /** Jump to the previous story regardless of current chapter. Lands on chapter 0 of the previous story. */\n previousStory() {\n if (this.index > 0) {\n this.index = this.index - 1;\n }\n }\n\n play() {\n this._video?.play().catch(() => {});\n this._raf = requestAnimationFrame(this._tick);\n }\n\n pause() {\n this._video?.pause();\n cancelAnimationFrame(this._raf);\n }\n\n // --- Helpers ---\n\n private async _emitAfter(name: 'after-show' | 'after-hide') {\n await new Promise((r) => requestAnimationFrame(() => r(null)));\n const anims = this._dialog.getAnimations({ subtree: false });\n await Promise.all(anims.map((a) => a.finished.catch(() => {})));\n if ((name === 'after-show') !== this.open) return;\n this.emit(name);\n if (name === 'after-show') {\n this._raf = requestAnimationFrame(this._tick);\n }\n }\n\n private _restoreFocus() {\n const stories = this.source?.stories() ?? this.stories;\n const story = stories[this.index];\n const trigger = story?.querySelector<HTMLButtonElement>('button[data-story-trigger]');\n trigger?.focus({ preventScroll: false });\n }\n\n override render() {\n const total = this.stories.length;\n const currentStory = this.stories[this.index];\n // Chevrons navigate story-to-story, so visibility depends on `index` only (not chapter).\n const isFirstStory = this.index === 0;\n const isLastStory = this.index >= total - 1;\n // Render one segment per chapter of the CURRENT story. Use `_chapterStarts` if present\n // (set after `_loadCurrent`), or fall back to the current story's parsed chapters.\n const chapterStarts = this._chapterStarts.length\n ? this._chapterStarts\n : (currentStory?.getChapterStarts() ?? [0]);\n\n return html`\n <dialog\n part=\"dialog\"\n aria-label=\"Stories\"\n >\n <div\n part=\"frame\"\n class=\"frame\"\n @pointerdown=${this._onFramePointerDown}\n @pointerup=${this._onFramePointerUp}\n @pointercancel=${this._onFramePointerUp}\n >\n <div\n part=\"progress\"\n class=\"progress\"\n role=\"progressbar\"\n aria-valuenow=${this.chapter + 1}\n aria-valuemin=\"1\"\n aria-valuemax=${chapterStarts.length || 1}\n >\n ${map(\n chapterStarts,\n (_, i) => html`\n <span\n part=\"progress-segment\"\n class=\"progress-segment\"\n data-state=${i < this.chapter ? 'past' : i === this.chapter ? 'active' : 'future'}\n >\n <span\n part=\"progress-fill\"\n class=\"progress-fill\"\n ></span>\n </span>\n `,\n )}\n </div>\n\n <header\n part=\"header\"\n class=\"header\"\n data-no-gesture\n >\n <slot name=\"header\">\n ${currentStory?.poster\n ? html`<img\n class=\"header-thumb\"\n src=${currentStory.poster}\n alt=\"\"\n />`\n : nothing}\n ${currentStory?.label\n ? html`<div class=\"header-text\">\n <div\n part=\"header-label\"\n class=\"header-label\"\n >\n ${currentStory.label}\n </div>\n </div>`\n : nothing}\n </slot>\n </header>\n\n <div\n part=\"actions\"\n class=\"actions\"\n data-no-gesture\n >\n <slot name=\"close\">\n <button\n type=\"button\"\n part=\"button-close\"\n class=\"btn btn-close\"\n aria-label=\"Close\"\n @click=${() => this.close()}\n >\n <l-icon name=\"mdi:close\"></l-icon>\n </button>\n </slot>\n <button\n type=\"button\"\n part=\"button-pause\"\n class=\"btn btn-pause\"\n aria-label=${this._paused ? 'Play' : 'Pause'}\n aria-pressed=${this._paused ? 'true' : 'false'}\n @click=${() => (this._paused ? this.play() : this.pause())}\n >\n <l-icon name=${this._paused ? 'mdi:play' : 'mdi:pause'}></l-icon>\n </button>\n <button\n type=\"button\"\n part=\"button-mute\"\n class=\"btn btn-mute\"\n aria-label=${this.muted ? 'Unmute' : 'Mute'}\n aria-pressed=${this.muted ? 'false' : 'true'}\n @click=${() => {\n this.muted = !this.muted;\n this.emit('mute-change', { detail: { muted: this.muted } });\n }}\n >\n <l-icon name=${this.muted ? 'mdi:volume-off' : 'mdi:volume-high'}></l-icon>\n </button>\n </div>\n\n <video\n part=\"video\"\n class=\"video\"\n playsinline\n preload=\"metadata\"\n ?muted=${this.muted}\n ></video>\n\n <l-spinner\n part=\"spinner\"\n class=\"spinner\"\n aria-label=\"Loading\"\n data-no-gesture\n data-state=${this._loading ? 'loading' : 'idle'}\n ></l-spinner>\n\n <!-- Tap zones: invisible overlays that translate clicks into previous/next.\n Sit BELOW header / overlay / chevron buttons in z-order, above the video. -->\n <div\n class=\"tap-zone tap-previous\"\n data-tap=\"previous\"\n aria-hidden=\"true\"\n ></div>\n <div\n class=\"tap-zone tap-next\"\n data-tap=\"next\"\n aria-hidden=\"true\"\n ></div>\n\n <div\n part=\"overlay\"\n class=\"overlay\"\n data-no-gesture\n >\n <slot name=\"cta\"></slot>\n </div>\n\n <div\n class=\"sr-only\"\n aria-live=\"polite\"\n >\n ${total\n ? `Story ${this.index + 1} of ${total}${\n this.stories[this.index]?.label ? ` — ${this.stories[this.index].label}` : ''\n }${chapterStarts.length > 1 ? ` — chapter ${this.chapter + 1} of ${chapterStarts.length}` : ''}`\n : ''}\n </div>\n </div>\n\n ${isFirstStory\n ? nothing\n : html`<button\n type=\"button\"\n part=\"button-previous\"\n class=\"btn btn-nav btn-previous\"\n aria-label=\"Previous story\"\n @click=${() => this.previousStory()}\n >\n <l-icon name=\"mdi:chevron-left\"></l-icon>\n </button>`}\n ${isLastStory\n ? nothing\n : html`<button\n type=\"button\"\n part=\"button-next\"\n class=\"btn btn-nav btn-next\"\n aria-label=\"Next story\"\n @click=${() => this.nextStory()}\n >\n <l-icon name=\"mdi:chevron-right\"></l-icon>\n </button>`}\n </dialog>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'l-stories-viewer': LuxenStoriesViewer;\n }\n}\n"],"mappings":"qQCSA,IAAM,EAAS,EAAU,msHAAU,CAE7B,EAAoB,OAAO,IAAI,mCAAmC,CACxE,GAAI,OAAO,SAAa,KAAe,EAAE,KAAqB,UAAW,CACvE,IAAM,EAAQ,IAAI,cAClB,EAAM,YACJ,yFACD,CACD,SAAS,mBAAmB,KAAK,EAAM,CACvC,OAAO,eAAe,SAAU,EAAmB,CAAE,MAAO,EAAO,CAAC,CAmDtE,IAAa,EAAb,cAAwC,CAAa,yCAK5C,cAIC,aAIA,aAID,oBAIO,qBAIC,gBAIL,eAGc,EAAE,aAGI,kBAMH,iBAGC,aAEb,kBACM,qBAC+C,oBACjC,EAAE,qBACF,CAAC,EAAE,qBAEE,qBAyGlB,GAAqB,CACpC,QAAK,KACV,OAAQ,EAAE,IAAV,CACE,IAAK,YACH,EAAE,gBAAgB,CAClB,KAAK,UAAU,CACf,MACF,IAAK,aACH,EAAE,gBAAgB,CAClB,KAAK,MAAM,CACX,MACF,IAAK,IACH,EAAE,gBAAgB,CACd,KAAK,OAAO,OAAQ,KAAK,MAAM,CAC9B,KAAK,OAAO,CACjB,MACF,IAAK,IACL,IAAK,IACH,EAAE,gBAAgB,CAClB,KAAK,MAAQ,CAAC,KAAK,MACnB,KAAK,KAAK,cAAe,CAAE,OAAQ,CAAE,MAAO,KAAK,MAAO,CAAE,CAAC,CAC3D,iCAMyB,GAAoB,CAE5C,EAAE,OAAuB,QAAQ,+BAA+B,GACrE,KAAK,cAAgB,CAAE,EAAG,EAAE,QAAS,EAAG,EAAE,QAAS,EAAG,YAAY,KAAK,CAAE,CACzE,KAAK,WAAa,OAAO,eAAiB,KAAK,OAAO,CAAE,IAAI,0BAGjC,GAAoB,CAC/C,aAAa,KAAK,WAAW,CAC7B,IAAM,EAAQ,KAAK,cAEnB,GADA,KAAK,cAAgB,KACjB,CAAC,EAAO,OAEZ,IAAM,EAAK,EAAE,QAAU,EAAM,EACvB,EAAK,EAAE,QAAU,EAAM,EACvB,EAAU,YAAY,KAAK,CAAG,EAAM,EACpC,EAAQ,EAAU,KAAO,KAAK,IAAI,EAAG,CAAG,IAAM,KAAK,IAAI,EAAG,CAAG,GAInE,GAHqB,GAAW,KAAO,KAAK,IAAI,EAAG,CAAG,IAAM,KAAK,IAAI,EAAG,CAAG,GAGzD,CACZ,KAAK,OAAO,QAAQ,KAAK,MAAM,CACnC,OAGF,GAAI,EAAO,CAII,EAAE,OAAuB,QAAqB,aACvD,EAAK,QAAQ,MAAQ,WAAY,KAAK,UAAU,CAC/C,KAAK,MAAM,CAChB,OAGE,KAAK,IAAI,EAAG,CAAG,KAAK,IAAI,EAAG,EAAI,KAAK,IAAI,EAAG,CAAG,GAC5C,EAAK,EAAG,KAAK,WAAW,CACvB,KAAK,eAAe,CAChB,EAAK,IACd,KAAK,OAAO,iBA2GM,CACpB,GAAI,CAAC,KAAK,KAAM,OAChB,IAAM,EAAI,KAAK,OACT,EAAM,KAAK,UAAU,KAAK,SAChC,GAAI,GAAK,EAAK,CACZ,IAAM,EAAQ,KAAK,eAAe,KAAK,UAAY,EAC7C,EAAM,KAAK,eAAe,KAAK,QAAU,IAAM,EAAE,SACjD,EAAO,KAAK,IAAI,EAAG,EAAM,EAAM,CAC/B,EAAI,EAAO,KAAK,IAAI,EAAG,KAAK,KAAK,EAAE,YAAc,GAAS,EAAM,EAAE,CAAC,CAAG,EAC5E,EAAI,MAAM,YAAY,MAAO,OAAO,EAAE,CAAC,CAGnC,GAAK,GAAK,KAAK,QAAU,KAAK,cAChC,KAAK,SAAS,EAAE,CAGpB,KAAK,KAAO,sBAAsB,KAAK,MAAM,qBAzVN,CAAC,EAAY,EAAO,CAuD7D,mBAA6B,CAC3B,MAAM,mBAAmB,CACzB,KAAK,iBAAiB,UAAW,KAAK,WAAW,CAGnD,sBAAgC,CAC9B,MAAM,sBAAsB,CAC5B,KAAK,oBAAoB,UAAW,KAAK,WAAW,CACpD,qBAAqB,KAAK,KAAK,CAC/B,aAAa,KAAK,WAAW,CAC7B,KAAK,qBAAqB,CAG5B,cAAwB,CACtB,KAAK,QAAQ,iBAAiB,SAAW,GAAM,KAAK,UAAU,EAAE,CAAC,CACjE,KAAK,QAAQ,iBAAiB,YAAe,KAAK,gBAAgB,CAAC,CACnE,KAAK,QAAQ,iBAAiB,QAAU,GAAM,KAAK,eAAe,EAAE,CAAC,CACrE,KAAK,OAAO,iBAAiB,YAAe,KAAK,UAAU,CAAC,CAC5D,KAAK,OAAO,iBAAiB,qBAAwB,KAAK,OAAO,CAAC,CAClE,KAAK,OAAO,iBAAiB,WAAe,KAAK,QAAU,GAAO,CAClE,KAAK,OAAO,iBAAiB,YAAgB,KAAK,QAAU,GAAM,CAGlE,KAAK,OAAO,iBAAiB,gBAAoB,KAAK,SAAW,GAAM,CACvE,KAAK,OAAO,iBAAiB,cAAkB,KAAK,SAAW,GAAM,CACrE,KAAK,OAAO,iBAAiB,cAAkB,KAAK,SAAW,GAAO,CACtE,KAAK,OAAO,iBAAiB,cAAkB,KAAK,SAAW,GAAO,CACtE,KAAK,OAAO,iBAAiB,YAAgB,KAAK,SAAW,GAAO,CAGpE,KAAK,OAAO,iBAAiB,iBAAoB,KAAK,oBAAoB,CAAC,CAG7E,QAAiB,EAA+B,CAC9C,GAAI,EAAQ,IAAI,OAAO,KACjB,KAAK,MAAQ,CAAC,KAAK,QAAQ,KAC7B,KAAK,KAAK,OAAO,CACjB,KAAK,gBAAgB,aAAc,GAAK,CACxC,KAAK,QAAQ,WAAW,CACxB,KAAK,cAAc,CACd,KAAK,WAAW,aAAa,SACzB,CAAC,KAAK,MAAQ,KAAK,QAAQ,KAAM,CAC1C,GAAI,CAAC,KAAK,KAAK,OAAQ,CAAE,WAAY,GAAM,CAAC,CAAE,CAC5C,KAAK,KAAO,GACZ,OAEF,KAAK,QAAQ,OAAO,EAKxB,GAAI,EAAQ,IAAI,QAAQ,EAAI,KAAK,KAAM,CACrC,KAAK,cAAc,CACnB,IAAM,EAAQ,KAAK,QAAQ,KAAK,OAC5B,GAAO,KAAK,KAAK,eAAgB,CAAE,OAAQ,CAAE,MAAO,KAAK,MAAO,QAAO,CAAE,CAAC,CAI5E,EAAQ,IAAI,UAAU,EAAI,KAAK,MAAQ,CAAC,EAAQ,IAAI,QAAQ,EAC9D,KAAK,mBAAmB,CAGtB,EAAQ,IAAI,QAAQ,EAAI,KAAK,SAC/B,KAAK,OAAO,MAAQ,KAAK,OAM7B,UAAkB,EAAU,CACrB,KAAK,KAAK,OAAQ,CAAE,WAAY,GAAM,CAAC,EAC1C,EAAE,gBAAgB,CAItB,gBAAyB,CACvB,qBAAqB,KAAK,KAAK,CAC/B,KAAK,OAAO,OAAO,CACnB,KAAK,OAAO,gBAAgB,MAAM,CAClC,KAAK,OAAO,MAAM,CAClB,KAAK,qBAAqB,CAE1B,IAAK,IAAI,EAAI,EAAG,GAAK,KAAK,OAAS,EAAI,KAAK,QAAQ,OAAQ,IAC1D,KAAK,QAAQ,GAAG,KAAO,GAEzB,KAAK,eAAe,CACpB,KAAK,KAAO,GACZ,KAAK,gBAAgB,aAAa,CAC7B,KAAK,WAAW,aAAa,CAGpC,eAAuB,EAAe,CAC/B,KAAK,cAEN,EAAE,SAAW,KAAK,UACpB,KAAK,KAAO,IA8EhB,qBAA8B,CAC5B,KAAK,UAAY,MAAM,KACrB,KAAK,WAAY,iBAA8B,0BAA0B,CAC1E,CAGH,oBAA6B,CAC3B,KAAK,qBAAqB,CAC1B,IAAK,IAAI,EAAI,EAAG,EAAI,KAAK,UAAU,OAAQ,IAAK,CAC9C,IAAM,EAAI,IAAI,KAAK,SACnB,KAAK,UAAU,GAAG,MAAM,YAAY,MAAO,OAAO,EAAE,CAAC,EAIzD,cAAuB,CACrB,IAAM,EAAQ,KAAK,QAAQ,KAAK,OAC3B,IACL,qBAAqB,KAAK,KAAK,CAG/B,KAAK,eAAiB,KACtB,KAAK,eAAiB,EAAM,kBAAkB,CAC9C,KAAK,QAAU,EACf,KAAK,WAAW,EAAM,CACtB,KAAK,OAAO,MAAQ,KAAK,MACzB,KAAK,OAAO,KAAO,KAAK,KACpB,KAAK,OAAO,MAAQ,EAAM,IAG5B,KAAK,OAAO,YAAc,EAF1B,KAAK,OAAO,IAAM,EAAM,IAK1B,0BAA4B,KAAK,oBAAoB,CAAC,CACtD,KAAK,OAAO,MAAM,CAAC,UAAY,CAE7B,KAAK,MAAQ,GACb,KAAK,OAAO,MAAQ,GACpB,KAAK,OAAO,MAAM,CAAC,UAAY,GAAG,EAClC,EAQJ,oBAA6B,CAC3B,IAAM,EAAI,KAAK,OACf,GAAI,CAAC,EAAE,UAAY,EAAE,YAAc,EAAE,SAAW,GAAK,OACrD,IAAM,EAAY,KAAK,QAAQ,KAAK,MAAQ,GAE5C,GADI,CAAC,GAAW,KACZ,KAAK,iBAAmB,EAAU,IAAK,OAC3C,KAAK,eAAiB,EAAU,IAEhC,IAAM,EAAO,SAAS,cAAc,OAAO,CAC3C,EAAK,IAAM,UACX,EAAK,GAAK,QACV,EAAK,KAAO,EAAU,IACtB,EAAK,YAAc,YACnB,EAAK,QAAQ,qBAAuB,GACpC,SAAS,KAAK,YAAY,EAAK,CAIjC,qBAA8B,CAC5B,IAAM,EAAQ,SAAS,KAAK,iBAC1B,oCACD,CACD,IAAK,IAAM,KAAQ,EAAO,EAAK,QAAQ,CACvC,KAAK,eAAiB,KAGxB,mBAA4B,CAC1B,IAAM,EAAS,KAAK,eAAe,KAAK,UAAY,EACpD,KAAK,OAAO,YAAc,EAC1B,KAAK,oBAAoB,CACzB,IAAM,EAAQ,KAAK,QAAQ,KAAK,OAC5B,GAAO,KAAK,KAAK,iBAAkB,CAAE,OAAQ,CAAE,QAAS,KAAK,QAAS,QAAO,CAAE,CAAC,CAGtF,IAAY,cAAe,CACzB,OAAO,KAAK,IAAI,EAAG,KAAK,eAAe,OAAS,EAAE,CAOpD,WAAmB,EAAmB,CACpC,IAAK,IAAM,KAAQ,MAAM,KAAK,KAAK,SAAS,CACrC,EAAqB,QAAQ,YAAc,IAAA,IAAW,EAAK,QAAQ,CAE1E,IAAK,IAAM,KAAS,MAAM,KAAK,EAAM,SAAS,CAAE,CAE9C,GAAI,CADc,EAAsB,eAAe,OAAO,CAC/C,SACf,IAAM,EAAQ,EAAM,UAAU,GAAK,CACnC,EAAM,QAAQ,UAAY,GAC1B,KAAK,YAAY,EAAM,EAuB3B,UAAmB,CAIjB,GAFc,KAAK,QAAQ,KAAK,QACrB,KAAK,KAAK,YAAa,CAAE,OAAQ,CAAE,MAAO,KAAK,MAAO,CAAE,CAAC,CAChE,KAAK,KAAM,CACb,KAAK,OAAO,YAAc,KAAK,eAAe,IAAM,EACpD,KAAK,QAAU,EACf,KAAK,OAAO,MAAM,CAAC,UAAY,GAAG,CAClC,OAEG,KAAK,cACN,KAAK,MAAQ,KAAK,QAAQ,OAAS,EACrC,KAAK,OAAqB,EAE1B,KAAK,OAAO,EAKhB,SAAiB,EAAmB,CAClC,GAAI,IAAc,EAAG,CACf,KAAK,QAAU,KAAK,aACtB,KAAK,SAAyB,EACrB,KAAK,MAAQ,KAAK,QAAQ,OAAS,EAC5C,KAAK,OAAqB,EAE1B,KAAK,OAAO,CAEd,OAGF,IAAM,EAAQ,KAAK,eAAe,KAAK,UAAY,EACnD,GAAI,KAAK,OAAO,YAAc,EAAQ,EAAG,CACvC,KAAK,OAAO,YAAc,EAC1B,KAAK,oBAAoB,CACzB,OAEF,GAAI,KAAK,QAAU,EACjB,OAAK,gBACI,KAAK,MAAQ,EAAG,CAEzB,IAAM,EAAgB,KAAK,QAAQ,KAAK,MAAQ,GAC1C,EAAe,KAAK,IAAI,EAAG,EAAc,kBAAkB,CAAC,OAAS,EAAE,CAC7E,OAAK,MAGL,mBAAqB,CACnB,KAAK,QAAU,GACf,EAON,OAAO,EAAuB,EAAQ,EAAG,EAA8B,KAAM,CAC3E,KAAK,QAAU,EACf,KAAK,OAAS,EACd,KAAK,MAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,EAAQ,OAAS,EAAE,CAAC,CAC7D,KAAK,KAAO,GAGd,OAAQ,CACN,KAAK,KAAO,GAId,MAAO,CACL,KAAK,SAAS,EAAE,CAIlB,UAAW,CACT,KAAK,SAAS,GAAG,CAInB,WAAY,CACN,KAAK,MAAQ,KAAK,QAAQ,OAAS,EACrC,KAAK,OAAqB,EAE1B,KAAK,OAAO,CAKhB,eAAgB,CACV,KAAK,MAAQ,GACf,OAAK,MAIT,MAAO,CACL,KAAK,QAAQ,MAAM,CAAC,UAAY,GAAG,CACnC,KAAK,KAAO,sBAAsB,KAAK,MAAM,CAG/C,OAAQ,CACN,KAAK,QAAQ,OAAO,CACpB,qBAAqB,KAAK,KAAK,CAKjC,MAAc,WAAW,EAAmC,CAC1D,MAAM,IAAI,QAAS,GAAM,0BAA4B,EAAE,KAAK,CAAC,CAAC,CAC9D,IAAM,EAAQ,KAAK,QAAQ,cAAc,CAAE,QAAS,GAAO,CAAC,CAC5D,MAAM,QAAQ,IAAI,EAAM,IAAK,GAAM,EAAE,SAAS,UAAY,GAAG,CAAC,CAAC,CAC1D,IAAS,eAAkB,KAAK,OACrC,KAAK,KAAK,EAAK,CACX,IAAS,eACX,KAAK,KAAO,sBAAsB,KAAK,MAAM,GAIjD,eAAwB,GACN,KAAK,QAAQ,SAAS,EAAI,KAAK,SACzB,KAAK,QACJ,cAAiC,6BAA6B,GAC5E,MAAM,CAAE,cAAe,GAAO,CAAC,CAG1C,QAAkB,CAChB,IAAM,EAAQ,KAAK,QAAQ,OACrB,EAAe,KAAK,QAAQ,KAAK,OAEjC,EAAe,KAAK,QAAU,EAC9B,EAAc,KAAK,OAAS,EAAQ,EAGpC,EAAgB,KAAK,eAAe,OACtC,KAAK,eACJ,GAAc,kBAAkB,EAAI,CAAC,EAAE,CAE5C,MAAO,EAAI;;;;;;;;yBAQU,KAAK,oBAAoB;uBAC3B,KAAK,kBAAkB;2BACnB,KAAK,kBAAkB;;;;;;4BAMtB,KAAK,QAAU,EAAE;;4BAEjB,EAAc,QAAU,EAAE;;cAExC,EACA,GACC,EAAG,IAAM,CAAI;;;;+BAIG,EAAI,KAAK,QAAU,OAAS,IAAM,KAAK,QAAU,SAAW,SAAS;;;;;;;gBAQvF,CAAC;;;;;;;;;gBASE,GAAc,OACZ,CAAI;;0BAEI,EAAa,OAAO;;sBAG5B,EAAQ;gBACV,GAAc,MACZ,CAAI;;;;;wBAKE,EAAa,MAAM;;0BAGzB,EAAQ;;;;;;;;;;;;;;;6BAeK,KAAK,OAAO,CAAC;;;;;;;;;2BASjB,KAAK,QAAU,OAAS,QAAQ;6BAC9B,KAAK,QAAU,OAAS,QAAQ;2BAC/B,KAAK,QAAU,KAAK,MAAM,CAAG,KAAK,OAAO,CAAE;;6BAE5C,KAAK,QAAU,WAAa,YAAY;;;;;;2BAM1C,KAAK,MAAQ,SAAW,OAAO;6BAC7B,KAAK,MAAQ,QAAU,OAAO;2BAC9B,CACb,KAAK,MAAQ,CAAC,KAAK,MACnB,KAAK,KAAK,cAAe,CAAE,OAAQ,CAAE,MAAO,KAAK,MAAO,CAAE,CAAC,EAC3D;;6BAEa,KAAK,MAAQ,iBAAmB,kBAAkB;;;;;;;;;qBAS1D,KAAK,MAAM;;;;;;;;yBAQP,KAAK,SAAW,UAAY,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4B9C,EACE,SAAS,KAAK,MAAQ,EAAE,MAAM,IAC5B,KAAK,QAAQ,KAAK,QAAQ,MAAQ,MAAM,KAAK,QAAQ,KAAK,OAAO,QAAU,KAC1E,EAAc,OAAS,EAAI,cAAc,KAAK,QAAU,EAAE,MAAM,EAAc,SAAW,KAC5F,GAAG;;;;UAIT,EACE,EACA,CAAI;;;;;2BAKa,KAAK,eAAe,CAAC;;;uBAG3B;UACb,EACE,EACA,CAAI;;;;;2BAKa,KAAK,WAAW,CAAC;;;uBAGvB;;WA7oBpB,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,OAAA,IAAA,GAAA,IAI1C,EAAS,CAAE,KAAM,OAAQ,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,QAAA,IAAA,GAAA,IAIzC,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,QAAA,IAAA,GAAA,IAI1C,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,OAAA,IAAA,GAAA,IAI1C,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,eAAgB,CAAC,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IAIrE,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,gBAAiB,CAAC,CAAA,CAAA,EAAA,UAAA,eAAA,IAAA,GAAA,IAItE,EAAS,CAAE,KAAM,OAAQ,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,UAAA,IAAA,GAAA,IASzC,EAAM,SAAS,CAAA,CAAA,EAAA,UAAA,UAAA,IAAA,GAAA,IACf,EAAM,QAAQ,CAAA,CAAA,EAAA,UAAA,SAAA,IAAA,GAAA,IAGd,GAAO,CAAA,CAAA,EAAA,UAAA,UAAA,IAAA,GAAA,IAGP,GAAO,CAAA,CAAA,EAAA,UAAA,WAAA,IAAA,GAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/story/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,cAAc,SAAS,CAAC;AAGxB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,UAAU,CAAC;KACvB;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/story/index.ts"],"sourcesContent":["import { define } from '../../define';\nimport { LuxenStory } from './story';\nexport * from './story';\ndefine('story', LuxenStory);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'l-story': LuxenStory;\n }\n}\n"],"mappings":"iFAGA,EAAO,QAAS,EAAW"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LuxenElement } from '../../shared/luxen-element';
|
|
2
|
+
/**
|
|
3
|
+
* @summary A single story declaration inside an `<l-stories>` row.
|
|
4
|
+
*
|
|
5
|
+
* Renders the clickable thumbnail (poster image + centered play overlay).
|
|
6
|
+
* The viewer reads `src`, `poster`, `label`, `handle`, `duration`, and
|
|
7
|
+
* `tracks` to play this story when opened.
|
|
8
|
+
*
|
|
9
|
+
* @slot cta - Overlay surfaced by the viewer when this story is active (e.g. product card, link).
|
|
10
|
+
* @slot header - Header overlay (e.g. avatar + author).
|
|
11
|
+
*
|
|
12
|
+
* @customElement l-story
|
|
13
|
+
*/
|
|
14
|
+
export declare class LuxenStory extends LuxenElement {
|
|
15
|
+
createRenderRoot(): this;
|
|
16
|
+
/** Video URL. */
|
|
17
|
+
src: string;
|
|
18
|
+
/** Thumbnail poster image. Falls back to the first video frame. */
|
|
19
|
+
poster: string;
|
|
20
|
+
/** Optional short looping preview video (URL of a small dedicated MP4, typically 2-3s, 480p, no audio). When set, the thumbnail renders this video muted+looped+autoplayed in place of `poster`. Gated by an `IntersectionObserver` so off-screen previews don't play. */
|
|
21
|
+
preview: string;
|
|
22
|
+
/** Caption shown below the thumbnail (or overlaid, depending on appearance) and used as the trigger `aria-label`. */
|
|
23
|
+
label: string;
|
|
24
|
+
/** Override the progress duration in seconds. Defaults to the video's metadata duration. */
|
|
25
|
+
duration: number;
|
|
26
|
+
/** Mark this story as already viewed (faded ring). Reflected. */
|
|
27
|
+
seen: boolean;
|
|
28
|
+
/** Pulse the thumbnail to draw attention (animated halo + subtle breathing scale). Reflected. */
|
|
29
|
+
pulse: boolean;
|
|
30
|
+
/** Chapter start times within the video, comma-separated seconds (e.g. `0,5,12,20`). `0` is implicit if omitted. Empty = single chapter spanning the full video. */
|
|
31
|
+
chapters: string;
|
|
32
|
+
/** Comma-separated VTT track URLs for captions. */
|
|
33
|
+
tracks: string;
|
|
34
|
+
/** Parsed chapter start times. Always begins with `0`, sorted, deduplicated. Empty `chapters` returns `[0]`. */
|
|
35
|
+
getChapterStarts(): number[];
|
|
36
|
+
private _previewVideo?;
|
|
37
|
+
private _io?;
|
|
38
|
+
connectedCallback(): void;
|
|
39
|
+
updated(changed: Map<string, unknown>): void;
|
|
40
|
+
disconnectedCallback(): void;
|
|
41
|
+
render(): import('lit').TemplateResult<1>;
|
|
42
|
+
}
|
|
43
|
+
declare global {
|
|
44
|
+
interface HTMLElementTagNameMap {
|
|
45
|
+
'l-story': LuxenStory;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=story.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../../src/html/elements/story/story.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,qBAAa,UAAW,SAAQ,YAAY;IACjC,gBAAgB;IAIzB,iBAAiB;IAEjB,GAAG,SAAM;IAET,mEAAmE;IAEnE,MAAM,SAAM;IAEZ,0QAA0Q;IAE1Q,OAAO,SAAM;IAEb,qHAAqH;IAErH,KAAK,SAAM;IAEX,4FAA4F;IAE5F,QAAQ,SAAK;IAEb,iEAAiE;IAEjE,IAAI,UAAS;IAEb,iGAAiG;IAEjG,KAAK,UAAS;IAEd,oKAAoK;IAEpK,QAAQ,SAAM;IAEd,mDAAmD;IAEnD,MAAM,SAAM;IAEZ,gHAAgH;IAChH,gBAAgB,IAAI,MAAM,EAAE;IAWE,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEvE,OAAO,CAAC,GAAG,CAAC,CAAuB;IAE1B,iBAAiB;IAOjB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAwBrC,oBAAoB;IAMpB,MAAM;CAwChB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,UAAU,CAAC;KACvB;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import{i as e,n as t}from"../../chunks/lit.js";import{LuxenElement as n}from"../../shared/luxen-element.js";import{i as r,n as i,t as a}from"../../chunks/decorate.js";var o=class extends n{constructor(...e){super(...e),this.src=``,this.poster=``,this.preview=``,this.label=``,this.duration=0,this.seen=!1,this.pulse=!1,this.chapters=``,this.tracks=``}createRenderRoot(){return this}getChapterStarts(){let e=this.chapters.split(`,`).map(e=>parseFloat(e.trim())).filter(e=>Number.isFinite(e)&&e>=0),t=new Set([0,...e]),n=Array.from(t);return n.sort((e,t)=>e-t),n}connectedCallback(){super.connectedCallback(),this.hasAttribute(`role`)||this.setAttribute(`role`,`listitem`)}updated(e){e.has(`preview`)&&(this._io?.disconnect(),this._io=void 0,this.preview&&this._previewVideo&&(this._io=new IntersectionObserver(e=>{for(let t of e){let e=t.target;t.isIntersecting?e.paused&&e.play().catch(()=>{}):e.paused||e.pause()}},{threshold:.1}),this._io.observe(this._previewVideo)))}disconnectedCallback(){super.disconnectedCallback(),this._io?.disconnect(),this._io=void 0}render(){return e`
|
|
2
|
+
<button
|
|
3
|
+
type="button"
|
|
4
|
+
class="l-story-trigger"
|
|
5
|
+
aria-label=${this.label||`Open story`}
|
|
6
|
+
data-story-trigger
|
|
7
|
+
>
|
|
8
|
+
<span class="l-story-thumb">
|
|
9
|
+
${this.preview?e`<video
|
|
10
|
+
data-preview
|
|
11
|
+
src=${this.preview}
|
|
12
|
+
poster=${this.poster||t}
|
|
13
|
+
muted
|
|
14
|
+
loop
|
|
15
|
+
playsinline
|
|
16
|
+
autoplay
|
|
17
|
+
preload="auto"
|
|
18
|
+
aria-hidden="true"
|
|
19
|
+
></video>`:this.poster?e`<img
|
|
20
|
+
src=${this.poster}
|
|
21
|
+
alt=""
|
|
22
|
+
loading="lazy"
|
|
23
|
+
decoding="async"
|
|
24
|
+
/>`:t}
|
|
25
|
+
<span
|
|
26
|
+
class="l-story-play"
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
>
|
|
29
|
+
<l-icon name="mdi:play"></l-icon>
|
|
30
|
+
</span>
|
|
31
|
+
</span>
|
|
32
|
+
${this.label?e`<span class="l-story-label">${this.label}</span>`:t}
|
|
33
|
+
</button>
|
|
34
|
+
`}};a([r({reflect:!0})],o.prototype,`src`,void 0),a([r({reflect:!0})],o.prototype,`poster`,void 0),a([r({reflect:!0})],o.prototype,`preview`,void 0),a([r({reflect:!0})],o.prototype,`label`,void 0),a([r({type:Number})],o.prototype,`duration`,void 0),a([r({type:Boolean,reflect:!0})],o.prototype,`seen`,void 0),a([r({type:Boolean,reflect:!0})],o.prototype,`pulse`,void 0),a([r()],o.prototype,`chapters`,void 0),a([r()],o.prototype,`tracks`,void 0),a([i(`video[data-preview]`)],o.prototype,`_previewVideo`,void 0);export{o as LuxenStory};
|
|
35
|
+
//# sourceMappingURL=story.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story.js","names":[],"sources":["../../../src/html/elements/story/story.ts"],"sourcesContent":["import { html, nothing } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element';\n\n/**\n * @summary A single story declaration inside an `<l-stories>` row.\n *\n * Renders the clickable thumbnail (poster image + centered play overlay).\n * The viewer reads `src`, `poster`, `label`, `handle`, `duration`, and\n * `tracks` to play this story when opened.\n *\n * @slot cta - Overlay surfaced by the viewer when this story is active (e.g. product card, link).\n * @slot header - Header overlay (e.g. avatar + author).\n *\n * @customElement l-story\n */\nexport class LuxenStory extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Video URL. */\n @property({ reflect: true })\n src = '';\n\n /** Thumbnail poster image. Falls back to the first video frame. */\n @property({ reflect: true })\n poster = '';\n\n /** Optional short looping preview video (URL of a small dedicated MP4, typically 2-3s, 480p, no audio). When set, the thumbnail renders this video muted+looped+autoplayed in place of `poster`. Gated by an `IntersectionObserver` so off-screen previews don't play. */\n @property({ reflect: true })\n preview = '';\n\n /** Caption shown below the thumbnail (or overlaid, depending on appearance) and used as the trigger `aria-label`. */\n @property({ reflect: true })\n label = '';\n\n /** Override the progress duration in seconds. Defaults to the video's metadata duration. */\n @property({ type: Number })\n duration = 0;\n\n /** Mark this story as already viewed (faded ring). Reflected. */\n @property({ type: Boolean, reflect: true })\n seen = false;\n\n /** Pulse the thumbnail to draw attention (animated halo + subtle breathing scale). Reflected. */\n @property({ type: Boolean, reflect: true })\n pulse = false;\n\n /** Chapter start times within the video, comma-separated seconds (e.g. `0,5,12,20`). `0` is implicit if omitted. Empty = single chapter spanning the full video. */\n @property()\n chapters = '';\n\n /** Comma-separated VTT track URLs for captions. */\n @property()\n tracks = '';\n\n /** Parsed chapter start times. Always begins with `0`, sorted, deduplicated. Empty `chapters` returns `[0]`. */\n getChapterStarts(): number[] {\n const raw = this.chapters\n .split(',')\n .map((s) => parseFloat(s.trim()))\n .filter((n) => Number.isFinite(n) && n >= 0);\n const set = new Set<number>([0, ...raw]);\n const list = Array.from(set);\n list.sort((a, b) => a - b);\n return list;\n }\n\n @query('video[data-preview]') private _previewVideo?: HTMLVideoElement;\n\n private _io?: IntersectionObserver;\n\n override connectedCallback() {\n super.connectedCallback();\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listitem');\n }\n }\n\n override updated(changed: Map<string, unknown>) {\n // Set up / tear down the IntersectionObserver when the preview URL toggles.\n if (changed.has('preview')) {\n this._io?.disconnect();\n this._io = undefined;\n if (this.preview && this._previewVideo) {\n this._io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const v = entry.target as HTMLVideoElement;\n if (entry.isIntersecting) {\n if (v.paused) v.play().catch(() => {});\n } else if (!v.paused) {\n v.pause();\n }\n }\n },\n { threshold: 0.1 },\n );\n this._io.observe(this._previewVideo);\n }\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._io?.disconnect();\n this._io = undefined;\n }\n\n override render() {\n return html`\n <button\n type=\"button\"\n class=\"l-story-trigger\"\n aria-label=${this.label || 'Open story'}\n data-story-trigger\n >\n <span class=\"l-story-thumb\">\n ${this.preview\n ? html`<video\n data-preview\n src=${this.preview}\n poster=${this.poster || nothing}\n muted\n loop\n playsinline\n autoplay\n preload=\"auto\"\n aria-hidden=\"true\"\n ></video>`\n : this.poster\n ? html`<img\n src=${this.poster}\n alt=\"\"\n loading=\"lazy\"\n decoding=\"async\"\n />`\n : nothing}\n <span\n class=\"l-story-play\"\n aria-hidden=\"true\"\n >\n <l-icon name=\"mdi:play\"></l-icon>\n </span>\n </span>\n ${this.label ? html`<span class=\"l-story-label\">${this.label}</span>` : nothing}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'l-story': LuxenStory;\n }\n}\n"],"mappings":"uKAgBA,IAAa,EAAb,cAAgC,CAAa,wCAOrC,eAIG,gBAIC,cAIF,iBAIG,YAIJ,cAIC,iBAIG,eAIF,GAtCT,kBAA4B,CAC1B,OAAO,KAwCT,kBAA6B,CAC3B,IAAM,EAAM,KAAK,SACd,MAAM,IAAI,CACV,IAAK,GAAM,WAAW,EAAE,MAAM,CAAC,CAAC,CAChC,OAAQ,GAAM,OAAO,SAAS,EAAE,EAAI,GAAK,EAAE,CACxC,EAAM,IAAI,IAAY,CAAC,EAAG,GAAG,EAAI,CAAC,CAClC,EAAO,MAAM,KAAK,EAAI,CAE5B,OADA,EAAK,MAAM,EAAG,IAAM,EAAI,EAAE,CACnB,EAOT,mBAA6B,CAC3B,MAAM,mBAAmB,CACpB,KAAK,aAAa,OAAO,EAC5B,KAAK,aAAa,OAAQ,WAAW,CAIzC,QAAiB,EAA+B,CAE1C,EAAQ,IAAI,UAAU,GACxB,KAAK,KAAK,YAAY,CACtB,KAAK,IAAM,IAAA,GACP,KAAK,SAAW,KAAK,gBACvB,KAAK,IAAM,IAAI,qBACZ,GAAY,CACX,IAAK,IAAM,KAAS,EAAS,CAC3B,IAAM,EAAI,EAAM,OACZ,EAAM,eACJ,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAY,GAAG,CAC5B,EAAE,QACZ,EAAE,OAAO,GAIf,CAAE,UAAW,GAAK,CACnB,CACD,KAAK,IAAI,QAAQ,KAAK,cAAc,GAK1C,sBAAgC,CAC9B,MAAM,sBAAsB,CAC5B,KAAK,KAAK,YAAY,CACtB,KAAK,IAAM,IAAA,GAGb,QAAkB,CAChB,MAAO,EAAI;;;;qBAIM,KAAK,OAAS,aAAa;;;;YAIpC,KAAK,QACH,CAAI;;sBAEI,KAAK,QAAQ;yBACV,KAAK,QAAU,EAAQ;;;;;;;yBAQlC,KAAK,OACH,CAAI;wBACI,KAAK,OAAO;;;;oBAKpB,EAAQ;;;;;;;;UAQd,KAAK,MAAQ,CAAI,+BAA+B,KAAK,MAAM,SAAW,EAAQ;;WA5HrF,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,MAAA,IAAA,GAAA,IAI3B,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,SAAA,IAAA,GAAA,IAI3B,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,UAAA,IAAA,GAAA,IAI3B,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,QAAA,IAAA,GAAA,IAI3B,EAAS,CAAE,KAAM,OAAQ,CAAC,CAAA,CAAA,EAAA,UAAA,WAAA,IAAA,GAAA,IAI1B,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,OAAA,IAAA,GAAA,IAI1C,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,QAAA,IAAA,GAAA,IAI1C,GAAU,CAAA,CAAA,EAAA,UAAA,WAAA,IAAA,GAAA,IAIV,GAAU,CAAA,CAAA,EAAA,UAAA,SAAA,IAAA,GAAA,IAeV,EAAM,sBAAsB,CAAA,CAAA,EAAA,UAAA,gBAAA,IAAA,GAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,cAAc,QAAQ,CAAC;AAGvB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,QAAQ,EAAE,IAAI,CAAC;KAChB;CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{define as e}from"../../define.js";import{
|
|
1
|
+
import{define as e}from"../../define.js";import{Tabs as t}from"./tabs.js";e(`tabs`,t);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/tabs/index.ts"],"sourcesContent":["import { define } from '../../define';\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/tabs/index.ts"],"sourcesContent":["import { define } from '../../define';\nimport { Tabs } from './tabs';\nexport * from './tabs';\ndefine('tabs', Tabs);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'l-tabs': Tabs;\n }\n}\n"],"mappings":"0EAGA,EAAO,OAAQ,EAAK"}
|
|
@@ -21,7 +21,7 @@ export type TabsOrientation = 'horizontal' | 'vertical';
|
|
|
21
21
|
*
|
|
22
22
|
* @customElement l-tabs
|
|
23
23
|
*/
|
|
24
|
-
export declare class
|
|
24
|
+
export declare class Tabs extends LuxenElement {
|
|
25
25
|
createRenderRoot(): this;
|
|
26
26
|
private _instanceId;
|
|
27
27
|
private _tablistEl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,IAAK,SAAQ,YAAY;IAC3B,gBAAgB;IAIzB,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAAqB;IAEpC,sBAAsB;IAEtB,OAAO,EAAE,WAAW,CAAU;IAE9B,yCAAyC;IAEzC,KAAK,SAAO;IAEZ,4CAA4C;IAE5C,SAAS,UAAS;IAElB,uBAAuB;IAEvB,WAAW,EAAE,eAAe,CAAgB;IAInC,iBAAiB;IAMjB,oBAAoB;IAKpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAW9C,OAAO,CAAC,MAAM;IAoDd,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,UAAU;IA2BlB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,QAAQ,CAQd;IAEF,OAAO,CAAC,UAAU,CAkChB;CACH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{uniqueId as e}from"../../registry.js";import{LuxenElement as t}from"../../shared/luxen-element.js";import{i as n,t as r}from"../../chunks/decorate.js";var i=class extends t{constructor(...t){super(...t),this._instanceId=e(`tabs`),this._tablistEl=null,this._tabs=[],this._panels=[],this.variant=`line`,this.value=`0`,this.fullWidth=!1,this.orientation=`horizontal`,this._onClick=e=>{let t=e.target.closest(`[role="tab"]`);if(!t)return;let n=this._tabs.indexOf(t);n>=0&&(this._selectTab(n),t.focus())},this._onKeyDown=e=>{let t=e.target;if(t.getAttribute(`role`)!==`tab`)return;let n=this.orientation===`horizontal`,r=n?`ArrowLeft`:`ArrowUp`,i=n?`ArrowRight`:`ArrowDown`,a=this._tabs.indexOf(t);switch(e.key){case i:e.preventDefault(),a=(a+1)%this._tabs.length,this._selectTab(a),this._tabs[a].focus();break;case r:e.preventDefault(),a=(a-1+this._tabs.length)%this._tabs.length,this._selectTab(a),this._tabs[a].focus();break;case`Home`:e.preventDefault(),this._selectTab(0),this._tabs[0].focus();break;case`End`:e.preventDefault(),this._selectTab(this._tabs.length-1),this._tabs[this._tabs.length-1].focus();break}}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._setup())}disconnectedCallback(){super.disconnectedCallback(),this._teardown()}updated(e){e.has(`value`)&&this._tabs.length&&this._selectTab(Number(this.value),!1),e.has(`orientation`)&&this._tablistEl&&this._tablistEl.setAttribute(`aria-orientation`,this.orientation)}_setup(){let e=Array.from(this.children);if(e.length<2)return;this._tablistEl=e[0],this._tablistEl.setAttribute(`role`,`tablist`),this._tablistEl.setAttribute(`aria-orientation`,this.orientation),this._tabs=Array.from(this._tablistEl.querySelectorAll(`button`)),this._panels=e.slice(1);let t=Number(this.value)||0;for(let e=0;e<this._tabs.length;e++){let n=this._tabs[e],r=this._panels[e],i=n.getAttribute(`name`)??String(e),a=`${this._instanceId}-tab-${i}`,o=`${this._instanceId}-panel-${i}`;n.setAttribute(`role`,`tab`),n.setAttribute(`id`,a),n.setAttribute(`aria-selected`,String(e===t)),n.setAttribute(`tabindex`,e===t?`0`:`-1`),r&&(n.setAttribute(`aria-controls`,o),r.setAttribute(`role`,`tabpanel`),r.setAttribute(`id`,o),r.setAttribute(`aria-labelledby`,a),r.setAttribute(`tabindex`,`0`),e===t?r.hidden=!1:r.hidden=!0)}this._tablistEl.addEventListener(`click`,this._onClick),this._tablistEl.addEventListener(`keydown`,this._onKeyDown),requestAnimationFrame(()=>this._updateIndicator())}_teardown(){this._tablistEl?.removeEventListener(`click`,this._onClick),this._tablistEl?.removeEventListener(`keydown`,this._onKeyDown)}_selectTab(e,t=!0){if(!(e<0||e>=this._tabs.length)){for(let t=0;t<this._tabs.length;t++){let n=this._tabs[t],r=this._panels[t],i=t===e;n.setAttribute(`aria-selected`,String(i)),n.setAttribute(`tabindex`,i?`0`:`-1`),r&&(r.hidden=!i)}if(this.value=String(e),this._updateIndicator(),t){let t=this._tabs[e]?.getAttribute(`name`)??null;this.emit(`change`,{detail:{index:e,name:t}})}}}_updateIndicator(){if(!this._tablistEl)return;let e=this._tabs[Number(this.value)];e&&(this.orientation===`vertical`?(this._tablistEl.style.setProperty(`--_indicator-top`,`${e.offsetTop}px`),this._tablistEl.style.setProperty(`--_indicator-height`,`${e.offsetHeight}px`)):(this._tablistEl.style.setProperty(`--_indicator-left`,`${e.offsetLeft}px`),this._tablistEl.style.setProperty(`--_indicator-width`,`${e.offsetWidth}px`)))}};r([n({reflect:!0})],i.prototype,`variant`,void 0),r([n({reflect:!0})],i.prototype,`value`,void 0),r([n({type:Boolean,reflect:!0,attribute:`full-width`})],i.prototype,`fullWidth`,void 0),r([n({reflect:!0})],i.prototype,`orientation`,void 0);export{i as
|
|
1
|
+
import{uniqueId as e}from"../../registry.js";import{LuxenElement as t}from"../../shared/luxen-element.js";import{i as n,t as r}from"../../chunks/decorate.js";var i=class extends t{constructor(...t){super(...t),this._instanceId=e(`tabs`),this._tablistEl=null,this._tabs=[],this._panels=[],this.variant=`line`,this.value=`0`,this.fullWidth=!1,this.orientation=`horizontal`,this._onClick=e=>{let t=e.target.closest(`[role="tab"]`);if(!t)return;let n=this._tabs.indexOf(t);n>=0&&(this._selectTab(n),t.focus())},this._onKeyDown=e=>{let t=e.target;if(t.getAttribute(`role`)!==`tab`)return;let n=this.orientation===`horizontal`,r=n?`ArrowLeft`:`ArrowUp`,i=n?`ArrowRight`:`ArrowDown`,a=this._tabs.indexOf(t);switch(e.key){case i:e.preventDefault(),a=(a+1)%this._tabs.length,this._selectTab(a),this._tabs[a].focus();break;case r:e.preventDefault(),a=(a-1+this._tabs.length)%this._tabs.length,this._selectTab(a),this._tabs[a].focus();break;case`Home`:e.preventDefault(),this._selectTab(0),this._tabs[0].focus();break;case`End`:e.preventDefault(),this._selectTab(this._tabs.length-1),this._tabs[this._tabs.length-1].focus();break}}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._setup())}disconnectedCallback(){super.disconnectedCallback(),this._teardown()}updated(e){e.has(`value`)&&this._tabs.length&&this._selectTab(Number(this.value),!1),e.has(`orientation`)&&this._tablistEl&&this._tablistEl.setAttribute(`aria-orientation`,this.orientation)}_setup(){let e=Array.from(this.children);if(e.length<2)return;this._tablistEl=e[0],this._tablistEl.setAttribute(`role`,`tablist`),this._tablistEl.setAttribute(`aria-orientation`,this.orientation),this._tabs=Array.from(this._tablistEl.querySelectorAll(`button`)),this._panels=e.slice(1);let t=Number(this.value)||0;for(let e=0;e<this._tabs.length;e++){let n=this._tabs[e],r=this._panels[e],i=n.getAttribute(`name`)??String(e),a=`${this._instanceId}-tab-${i}`,o=`${this._instanceId}-panel-${i}`;n.setAttribute(`role`,`tab`),n.setAttribute(`id`,a),n.setAttribute(`aria-selected`,String(e===t)),n.setAttribute(`tabindex`,e===t?`0`:`-1`),r&&(n.setAttribute(`aria-controls`,o),r.setAttribute(`role`,`tabpanel`),r.setAttribute(`id`,o),r.setAttribute(`aria-labelledby`,a),r.setAttribute(`tabindex`,`0`),e===t?r.hidden=!1:r.hidden=!0)}this._tablistEl.addEventListener(`click`,this._onClick),this._tablistEl.addEventListener(`keydown`,this._onKeyDown),requestAnimationFrame(()=>this._updateIndicator())}_teardown(){this._tablistEl?.removeEventListener(`click`,this._onClick),this._tablistEl?.removeEventListener(`keydown`,this._onKeyDown)}_selectTab(e,t=!0){if(!(e<0||e>=this._tabs.length)){for(let t=0;t<this._tabs.length;t++){let n=this._tabs[t],r=this._panels[t],i=t===e;n.setAttribute(`aria-selected`,String(i)),n.setAttribute(`tabindex`,i?`0`:`-1`),r&&(r.hidden=!i)}if(this.value=String(e),this._updateIndicator(),t){let t=this._tabs[e]?.getAttribute(`name`)??null;this.emit(`change`,{detail:{index:e,name:t}})}}}_updateIndicator(){if(!this._tablistEl)return;let e=this._tabs[Number(this.value)];e&&(this.orientation===`vertical`?(this._tablistEl.style.setProperty(`--_indicator-top`,`${e.offsetTop}px`),this._tablistEl.style.setProperty(`--_indicator-height`,`${e.offsetHeight}px`)):(this._tablistEl.style.setProperty(`--_indicator-left`,`${e.offsetLeft}px`),this._tablistEl.style.setProperty(`--_indicator-width`,`${e.offsetWidth}px`)))}};r([n({reflect:!0})],i.prototype,`variant`,void 0),r([n({reflect:!0})],i.prototype,`value`,void 0),r([n({type:Boolean,reflect:!0,attribute:`full-width`})],i.prototype,`fullWidth`,void 0),r([n({reflect:!0})],i.prototype,`orientation`,void 0);export{i as Tabs};
|
|
2
2
|
//# sourceMappingURL=tabs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":[],"sources":["../../../src/html/elements/tabs/tabs.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element';\nimport { uniqueId } from '../../registry';\n\nexport type TabsVariant = 'enclosed' | 'line';\nexport type TabsOrientation = 'horizontal' | 'vertical';\n\n/**\n * @summary A tabs component that progressively enhances light DOM markup\n * with ARIA roles, keyboard navigation, and animated indicators.\n *\n * @example\n * ```html\n * <l-tabs variant=\"enclosed\">\n * <div>\n * <button>Tab 1</button>\n * <button>Tab 2</button>\n * </div>\n * <div>Content 1</div>\n * <div>Content 2</div>\n * </l-tabs>\n * ```\n *\n * @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.\n *\n * @customElement l-tabs\n */\nexport class LuxenTabs extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n private _instanceId = uniqueId('tabs');\n private _tablistEl: HTMLElement | null = null;\n private _tabs: HTMLButtonElement[] = [];\n private _panels: HTMLElement[] = [];\n\n /** Visual variant. */\n @property({ reflect: true })\n variant: TabsVariant = 'line';\n\n /** Index of the active tab (0-based). */\n @property({ reflect: true })\n value = '0';\n\n /** Stretch tabs to fill container width. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n fullWidth = false;\n\n /** Tab orientation. */\n @property({ reflect: true })\n orientation: TabsOrientation = 'horizontal';\n\n // --- Lifecycle ---\n\n override connectedCallback() {\n super.connectedCallback();\n // Defer setup to let light DOM children parse\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') && this._tabs.length) {\n this._selectTab(Number(this.value), false);\n }\n if (changed.has('orientation') && this._tablistEl) {\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n }\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const children = Array.from(this.children) as HTMLElement[];\n if (children.length < 2) return;\n\n // First child is the tablist container\n this._tablistEl = children[0];\n this._tablistEl.setAttribute('role', 'tablist');\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n\n // Buttons inside tablist become tabs\n this._tabs = Array.from(this._tablistEl.querySelectorAll('button'));\n\n // Remaining children become panels\n this._panels = children.slice(1);\n\n const activeIndex = Number(this.value) || 0;\n\n // Enhance tabs\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const name = tab.getAttribute('name') ?? String(i);\n const tabId = `${this._instanceId}-tab-${name}`;\n const panelId = `${this._instanceId}-panel-${name}`;\n\n tab.setAttribute('role', 'tab');\n tab.setAttribute('id', tabId);\n tab.setAttribute('aria-selected', String(i === activeIndex));\n tab.setAttribute('tabindex', i === activeIndex ? '0' : '-1');\n\n if (panel) {\n tab.setAttribute('aria-controls', panelId);\n panel.setAttribute('role', 'tabpanel');\n panel.setAttribute('id', panelId);\n panel.setAttribute('aria-labelledby', tabId);\n panel.setAttribute('tabindex', '0');\n if (i !== activeIndex) {\n panel.hidden = true;\n } else {\n panel.hidden = false;\n }\n }\n }\n\n // Attach listeners\n this._tablistEl.addEventListener('click', this._onClick);\n this._tablistEl.addEventListener('keydown', this._onKeyDown);\n\n // Initial indicator position\n requestAnimationFrame(() => this._updateIndicator());\n }\n\n private _teardown() {\n this._tablistEl?.removeEventListener('click', this._onClick);\n this._tablistEl?.removeEventListener('keydown', this._onKeyDown);\n }\n\n // --- Tab selection ---\n\n private _selectTab(index: number, emitEvent = true) {\n if (index < 0 || index >= this._tabs.length) return;\n\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const isActive = i === index;\n\n tab.setAttribute('aria-selected', String(isActive));\n tab.setAttribute('tabindex', isActive ? '0' : '-1');\n\n if (panel) {\n panel.hidden = !isActive;\n }\n }\n\n this.value = String(index);\n this._updateIndicator();\n\n if (emitEvent) {\n const name = this._tabs[index]?.getAttribute('name') ?? null;\n this.emit('change', { detail: { index, name } });\n }\n }\n\n // --- Indicator ---\n\n private _updateIndicator() {\n if (!this._tablistEl) return;\n const activeTab = this._tabs[Number(this.value)];\n if (!activeTab) return;\n\n const isVertical = this.orientation === 'vertical';\n\n if (isVertical) {\n this._tablistEl.style.setProperty('--_indicator-top', `${activeTab.offsetTop}px`);\n this._tablistEl.style.setProperty('--_indicator-height', `${activeTab.offsetHeight}px`);\n } else {\n this._tablistEl.style.setProperty('--_indicator-left', `${activeTab.offsetLeft}px`);\n this._tablistEl.style.setProperty('--_indicator-width', `${activeTab.offsetWidth}px`);\n }\n }\n\n // --- Event handlers ---\n\n private _onClick = (e: Event) => {\n const tab = (e.target as HTMLElement).closest<HTMLButtonElement>('[role=\"tab\"]');\n if (!tab) return;\n const index = this._tabs.indexOf(tab);\n if (index >= 0) {\n this._selectTab(index);\n tab.focus();\n }\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.getAttribute('role') !== 'tab') return;\n\n const isHorizontal = this.orientation === 'horizontal';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n\n let index = this._tabs.indexOf(target as HTMLButtonElement);\n\n switch (e.key) {\n case nextKey:\n e.preventDefault();\n index = (index + 1) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case prevKey:\n e.preventDefault();\n index = (index - 1 + this._tabs.length) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case 'Home':\n e.preventDefault();\n this._selectTab(0);\n this._tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n this._selectTab(this._tabs.length - 1);\n this._tabs[this._tabs.length - 1].focus();\n break;\n }\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tabs.js","names":[],"sources":["../../../src/html/elements/tabs/tabs.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element';\nimport { uniqueId } from '../../registry';\n\nexport type TabsVariant = 'enclosed' | 'line';\nexport type TabsOrientation = 'horizontal' | 'vertical';\n\n/**\n * @summary A tabs component that progressively enhances light DOM markup\n * with ARIA roles, keyboard navigation, and animated indicators.\n *\n * @example\n * ```html\n * <l-tabs variant=\"enclosed\">\n * <div>\n * <button>Tab 1</button>\n * <button>Tab 2</button>\n * </div>\n * <div>Content 1</div>\n * <div>Content 2</div>\n * </l-tabs>\n * ```\n *\n * @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.\n *\n * @customElement l-tabs\n */\nexport class Tabs extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n private _instanceId = uniqueId('tabs');\n private _tablistEl: HTMLElement | null = null;\n private _tabs: HTMLButtonElement[] = [];\n private _panels: HTMLElement[] = [];\n\n /** Visual variant. */\n @property({ reflect: true })\n variant: TabsVariant = 'line';\n\n /** Index of the active tab (0-based). */\n @property({ reflect: true })\n value = '0';\n\n /** Stretch tabs to fill container width. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n fullWidth = false;\n\n /** Tab orientation. */\n @property({ reflect: true })\n orientation: TabsOrientation = 'horizontal';\n\n // --- Lifecycle ---\n\n override connectedCallback() {\n super.connectedCallback();\n // Defer setup to let light DOM children parse\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') && this._tabs.length) {\n this._selectTab(Number(this.value), false);\n }\n if (changed.has('orientation') && this._tablistEl) {\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n }\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const children = Array.from(this.children) as HTMLElement[];\n if (children.length < 2) return;\n\n // First child is the tablist container\n this._tablistEl = children[0];\n this._tablistEl.setAttribute('role', 'tablist');\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n\n // Buttons inside tablist become tabs\n this._tabs = Array.from(this._tablistEl.querySelectorAll('button'));\n\n // Remaining children become panels\n this._panels = children.slice(1);\n\n const activeIndex = Number(this.value) || 0;\n\n // Enhance tabs\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const name = tab.getAttribute('name') ?? String(i);\n const tabId = `${this._instanceId}-tab-${name}`;\n const panelId = `${this._instanceId}-panel-${name}`;\n\n tab.setAttribute('role', 'tab');\n tab.setAttribute('id', tabId);\n tab.setAttribute('aria-selected', String(i === activeIndex));\n tab.setAttribute('tabindex', i === activeIndex ? '0' : '-1');\n\n if (panel) {\n tab.setAttribute('aria-controls', panelId);\n panel.setAttribute('role', 'tabpanel');\n panel.setAttribute('id', panelId);\n panel.setAttribute('aria-labelledby', tabId);\n panel.setAttribute('tabindex', '0');\n if (i !== activeIndex) {\n panel.hidden = true;\n } else {\n panel.hidden = false;\n }\n }\n }\n\n // Attach listeners\n this._tablistEl.addEventListener('click', this._onClick);\n this._tablistEl.addEventListener('keydown', this._onKeyDown);\n\n // Initial indicator position\n requestAnimationFrame(() => this._updateIndicator());\n }\n\n private _teardown() {\n this._tablistEl?.removeEventListener('click', this._onClick);\n this._tablistEl?.removeEventListener('keydown', this._onKeyDown);\n }\n\n // --- Tab selection ---\n\n private _selectTab(index: number, emitEvent = true) {\n if (index < 0 || index >= this._tabs.length) return;\n\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const isActive = i === index;\n\n tab.setAttribute('aria-selected', String(isActive));\n tab.setAttribute('tabindex', isActive ? '0' : '-1');\n\n if (panel) {\n panel.hidden = !isActive;\n }\n }\n\n this.value = String(index);\n this._updateIndicator();\n\n if (emitEvent) {\n const name = this._tabs[index]?.getAttribute('name') ?? null;\n this.emit('change', { detail: { index, name } });\n }\n }\n\n // --- Indicator ---\n\n private _updateIndicator() {\n if (!this._tablistEl) return;\n const activeTab = this._tabs[Number(this.value)];\n if (!activeTab) return;\n\n const isVertical = this.orientation === 'vertical';\n\n if (isVertical) {\n this._tablistEl.style.setProperty('--_indicator-top', `${activeTab.offsetTop}px`);\n this._tablistEl.style.setProperty('--_indicator-height', `${activeTab.offsetHeight}px`);\n } else {\n this._tablistEl.style.setProperty('--_indicator-left', `${activeTab.offsetLeft}px`);\n this._tablistEl.style.setProperty('--_indicator-width', `${activeTab.offsetWidth}px`);\n }\n }\n\n // --- Event handlers ---\n\n private _onClick = (e: Event) => {\n const tab = (e.target as HTMLElement).closest<HTMLButtonElement>('[role=\"tab\"]');\n if (!tab) return;\n const index = this._tabs.indexOf(tab);\n if (index >= 0) {\n this._selectTab(index);\n tab.focus();\n }\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.getAttribute('role') !== 'tab') return;\n\n const isHorizontal = this.orientation === 'horizontal';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n\n let index = this._tabs.indexOf(target as HTMLButtonElement);\n\n switch (e.key) {\n case nextKey:\n e.preventDefault();\n index = (index + 1) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case prevKey:\n e.preventDefault();\n index = (index - 1 + this._tabs.length) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case 'Home':\n e.preventDefault();\n this._selectTab(0);\n this._tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n this._selectTab(this._tabs.length - 1);\n this._tabs[this._tabs.length - 1].focus();\n break;\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Toast, ToastItem } from './toast';
|
|
2
2
|
export * from './toast';
|
|
3
3
|
declare global {
|
|
4
4
|
interface HTMLElementTagNameMap {
|
|
5
|
-
'l-toast':
|
|
6
|
-
'l-toast-item':
|
|
5
|
+
'l-toast': Toast;
|
|
6
|
+
'l-toast-item': ToastItem;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/toast/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/toast/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC3C,cAAc,SAAS,CAAC;AAIxB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,KAAK,CAAC;QACjB,cAAc,EAAE,SAAS,CAAC;KAC3B;CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{define as e}from"../../define.js";import{
|
|
1
|
+
import{define as e}from"../../define.js";import{Toast as t,ToastItem as n}from"./toast.js";e(`toast`,t),e(`toast-item`,n);
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/toast/index.ts"],"sourcesContent":["import { define } from '../../define';\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/toast/index.ts"],"sourcesContent":["import { define } from '../../define';\nimport { Toast, ToastItem } from './toast';\nexport * from './toast';\ndefine('toast', Toast);\ndefine('toast-item', ToastItem);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'l-toast': Toast;\n 'l-toast-item': ToastItem;\n }\n}\n"],"mappings":"2FAGA,EAAO,QAAS,EAAM,CACtB,EAAO,aAAc,EAAU"}
|
|
@@ -6,7 +6,7 @@ declare global {
|
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
/** Minimal custom element for toast items — no render, no shadow DOM. */
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class ToastItem extends HTMLElement {
|
|
10
10
|
}
|
|
11
11
|
interface ToastOptionsBase {
|
|
12
12
|
/** Optional heading text displayed above the message. */
|
|
@@ -41,7 +41,7 @@ export type ToastOptions = (ToastOptionsBase & {
|
|
|
41
41
|
* @cssproperty --show-duration - Duration of the show animation.
|
|
42
42
|
* @cssproperty --hide-duration - Duration of the hide animation.
|
|
43
43
|
*/
|
|
44
|
-
export declare class
|
|
44
|
+
export declare class Toast extends LuxenElement {
|
|
45
45
|
/** Use light DOM — no Shadow DOM. */
|
|
46
46
|
createRenderRoot(): this;
|
|
47
47
|
/** Position of the toast stack on the screen. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../src/html/elements/toast/toast.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI1D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf,4EAA4E;QAC5E,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KACjE;CACF;AAED,yEAAyE;AACzE,qBAAa,
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../src/html/elements/toast/toast.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI1D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf,4EAA4E;QAC5E,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KACjE;CACF;AAED,yEAAyE;AACzE,qBAAa,SAAU,SAAQ,WAAW;CAAG;AAE7C,UAAU,gBAAgB;IACxB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB,CAAC,gBAAgB,GAAG;IAAsC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACvF,CAAC,gBAAgB,GAAG;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,sDAAsD,CAAC,IAAI,EAAE,MAAM,CAAC;CACrE,CAAC,CAAC;AASP;;;;;;;;;;;;;GAaG;AACH,qBAAa,KAAM,SAAQ,YAAY;IACrC,qCAAqC;IAC5B,gBAAgB;IAIzB,iDAAiD;IACpB,SAAS,EAClC,WAAW,GACX,YAAY,GACZ,SAAS,GACT,cAAc,GACd,eAAe,GACf,YAAY,CAAa;IAE7B,2EAA2E;IAChC,QAAQ,SAAQ;IAE3D,uEAAuE;IAC1C,OAAO,SAAM;IAE1C,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,eAAe,CAAS;IAEvB,iBAAiB;IAWjB,oBAAoB;IAM7B,4CAA4C;IAC5C,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAqLzC,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IAgDlB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,mBAAmB,CAQzB;IAIF,OAAO,CAAC,UAAU,CAShB;CACH;AAkBD,qFAAqF;AACrF,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAExD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{cls as e,tagName as t,uniqueId as n}from"../../registry.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";var o=class extends HTMLElement{},s=class extends r{constructor(...e){super(...e),this.placement=`top-end`,this.duration=5e3,this.variant=``,this._timers=new WeakMap,this._positionCache=new WeakMap,this._documentHidden=!1,this._onVisibilityChange=()=>{this._documentHidden=document.hidden;let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);if(document.hidden)for(let t of e)this._pauseTimer(t);else for(let t of e)this._resumeTimer(t)},this._onKeyDown=e=>{if(e.key!==`Escape`||!this.matches(`:popover-open`))return;let n=this.querySelector(`:scope > ${t(`toast-item`)}:last-of-type`);n&&(e.preventDefault(),this._hideToast(n))}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.popover=`manual`,this.setAttribute(`role`,`log`),this.setAttribute(`aria-live`,`polite`),this.setAttribute(`aria-relevant`,`additions`),document.addEventListener(`keydown`,this._onKeyDown),document.addEventListener(`visibilitychange`,this._onVisibilityChange)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`keydown`,this._onKeyDown),document.removeEventListener(`visibilitychange`,this._onVisibilityChange)}toast(r){let{heading:i,variant:a=this.variant,duration:o=this.duration}=r,s=n(`toast`),c=document.createElement(t(`toast-item`));if(a&&c.setAttribute(`variant`,a),c.setAttribute(`role`,a===`danger`?`alert`:`status`),c.setAttribute(`aria-atomic`,`true`),r.icon){let t=document.createElement(`iconify-icon`);t.setAttribute(`icon`,r.icon),t.setAttribute(`width`,`20`),t.setAttribute(`height`,`20`),t.setAttribute(`aria-hidden`,`true`),t.className=e(`toast-icon`),c.appendChild(t)}else{let t=document.createElement(`div`);t.className=e(`toast-accent`),t.setAttribute(`aria-hidden`,`true`),c.appendChild(t)}let l=document.createElement(`div`);l.className=e(`toast-content`);let u=document.createElement(`div`);if(i){let t=document.createElement(`div`);t.id=`${s}-heading`,t.className=`${e(`toast-heading`)} font-medium`,t.textContent=i,u.appendChild(t),c.setAttribute(`aria-labelledby`,`${s}-heading`)}let d=document.createElement(`div`);d.id=`${s}-message`,d.className=e(`toast-message`),`html`in r&&r.html?d.setHTML(r.html):d.textContent=r.text??``,u.appendChild(d),c.setAttribute(i?`aria-describedby`:`aria-labelledby`,`${s}-message`),l.appendChild(u),c.appendChild(l);let f=document.createElement(`button`);if(f.type=`button`,f.className=e(`close`),f.setAttribute(`data-appearance`,`ring`),f.setAttribute(`aria-label`,`Close`),f.addEventListener(`click`,()=>this._hideToast(c)),c.appendChild(f),r.timer&&o>0&&isFinite(o)){let t=document.createElement(`div`);t.className=e(`toast-timer`),t.setAttribute(`aria-hidden`,`true`),t.style.setProperty(`--_timer-duration`,`${o}ms`),c.appendChild(t)}if(this._capturePositions(),this.placement.includes(`bottom`)?this.appendChild(c):this.prepend(c),this.matches(`:popover-open`)||this.showPopover(),!this.emit(`show`,{cancelable:!0,detail:{toast:c}}))return c.remove(),c;requestAnimationFrame(()=>{c.setAttribute(`showing`,``),this._animatePositions();let e=t=>{t.target===c&&(c.removeEventListener(`transitionend`,e),this.emit(`after-show`,{detail:{toast:c}}))};c.addEventListener(`transitionend`,e)}),o>0&&isFinite(o)&&this._startTimer(c,o),c.addEventListener(`pointerenter`,()=>this._pauseTimer(c)),c.addEventListener(`pointerleave`,()=>this._resumeTimer(c)),c.addEventListener(`focusin`,()=>this._pauseTimer(c)),c.addEventListener(`focusout`,()=>this._resumeTimer(c));let p=null,m=!1;c.addEventListener(`pointerdown`,e=>{e.button===0&&(e.target.closest(`button, a, [role="button"]`)||(p={x:e.clientX,y:e.clientY},m=!1,c.setPointerCapture(e.pointerId),c.style.transition=`none`))});let h=e=>this.placement.endsWith(`-start`)?Math.min(e,0):this.placement.endsWith(`-end`)?Math.max(e,0):e;return c.addEventListener(`pointermove`,e=>{if(!p)return;let t=h(e.clientX-p.x),n=e.clientY-p.y,r=e.pointerType===`touch`?10:2;if(!(!m&&Math.abs(t)<r)){if(!m&&Math.abs(n)>Math.abs(t)){p=null;return}m=!0,this._pauseTimer(c),c.style.transform=`translateX(${t}px)`,c.style.opacity=`${1-Math.abs(t)/300}`}}),c.addEventListener(`pointerup`,e=>{if(!p)return;let t=h(e.clientX-p.x);if(p=null,c.style.transition=``,m&&Math.abs(t)>50){let e=t>0?1:-1;c.style.transform=`translateX(${e*120}%)`,c.style.opacity=`0`,c.addEventListener(`transitionend`,()=>this._hideToast(c),{once:!0})}else c.style.transform=``,c.style.opacity=``,m&&this._resumeTimer(c);m=!1}),c}_startTimer(e,t){let n=window.setTimeout(()=>this._hideToast(e),t);this._timers.set(e,{remaining:t,startTime:performance.now(),timeoutId:n,paused:!1})}_pauseTimer(t){let n=this._timers.get(t);if(!n||n.paused)return;clearTimeout(n.timeoutId),n.remaining-=performance.now()-n.startTime,n.paused=!0;let r=t.querySelector(`.${e(`toast-timer`)}`);if(r)for(let e of r.getAnimations())e.pause()}_resumeTimer(t){let n=this._timers.get(t);if(!n||!n.paused||n.remaining<=0||this._documentHidden)return;n.startTime=performance.now(),n.timeoutId=window.setTimeout(()=>this._hideToast(t),n.remaining),n.paused=!1;let r=t.querySelector(`.${e(`toast-timer`)}`);if(r)for(let e of r.getAnimations())e.play()}_hideToast(e){let n=this._timers.get(e);if(n&&(clearTimeout(n.timeoutId),this._timers.delete(e)),!e.hasAttribute(`showing`)||!this.emit(`hide`,{cancelable:!0,detail:{toast:e}}))return;this._capturePositions(),e.removeAttribute(`showing`);let r=()=>{e.remove(),this._animatePositions(),this.emit(`after-hide`,{detail:{toast:e}}),this.querySelectorAll(`:scope > ${t(`toast-item`)}`).length===0&&this.matches(`:popover-open`)&&this.hidePopover()};if(parseFloat(getComputedStyle(e).transitionDuration)===0)r();else{let t=n=>{n.target===e&&(e.removeEventListener(`transitionend`,t),r())};e.addEventListener(`transitionend`,t)}}_capturePositions(){let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);for(let t of e)this._positionCache.set(t,t.getBoundingClientRect())}_animatePositions(){if(window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);for(let t of e){let e=this._positionCache.get(t);if(!e)continue;let n=t.getBoundingClientRect(),r=e.top-n.top;Math.abs(r)<1||t.animate([{transform:`translateY(${r}px)`},{transform:`translateY(0)`}],{duration:200,easing:`cubic-bezier(0.2, 0, 0, 1)`})}}};a([i({reflect:!0})],s.prototype,`placement`,void 0),a([i({type:Number,reflect:!0})],s.prototype,`duration`,void 0),a([i({reflect:!0})],s.prototype,`variant`,void 0);export{s as
|
|
1
|
+
import{cls as e,tagName as t,uniqueId as n}from"../../registry.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";var o=class extends HTMLElement{},s=class extends r{constructor(...e){super(...e),this.placement=`top-end`,this.duration=5e3,this.variant=``,this._timers=new WeakMap,this._positionCache=new WeakMap,this._documentHidden=!1,this._onVisibilityChange=()=>{this._documentHidden=document.hidden;let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);if(document.hidden)for(let t of e)this._pauseTimer(t);else for(let t of e)this._resumeTimer(t)},this._onKeyDown=e=>{if(e.key!==`Escape`||!this.matches(`:popover-open`))return;let n=this.querySelector(`:scope > ${t(`toast-item`)}:last-of-type`);n&&(e.preventDefault(),this._hideToast(n))}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.popover=`manual`,this.setAttribute(`role`,`log`),this.setAttribute(`aria-live`,`polite`),this.setAttribute(`aria-relevant`,`additions`),document.addEventListener(`keydown`,this._onKeyDown),document.addEventListener(`visibilitychange`,this._onVisibilityChange)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`keydown`,this._onKeyDown),document.removeEventListener(`visibilitychange`,this._onVisibilityChange)}toast(r){let{heading:i,variant:a=this.variant,duration:o=this.duration}=r,s=n(`toast`),c=document.createElement(t(`toast-item`));if(a&&c.setAttribute(`variant`,a),c.setAttribute(`role`,a===`danger`?`alert`:`status`),c.setAttribute(`aria-atomic`,`true`),r.icon){let t=document.createElement(`iconify-icon`);t.setAttribute(`icon`,r.icon),t.setAttribute(`width`,`20`),t.setAttribute(`height`,`20`),t.setAttribute(`aria-hidden`,`true`),t.className=e(`toast-icon`),c.appendChild(t)}else{let t=document.createElement(`div`);t.className=e(`toast-accent`),t.setAttribute(`aria-hidden`,`true`),c.appendChild(t)}let l=document.createElement(`div`);l.className=e(`toast-content`);let u=document.createElement(`div`);if(i){let t=document.createElement(`div`);t.id=`${s}-heading`,t.className=`${e(`toast-heading`)} font-medium`,t.textContent=i,u.appendChild(t),c.setAttribute(`aria-labelledby`,`${s}-heading`)}let d=document.createElement(`div`);d.id=`${s}-message`,d.className=e(`toast-message`),`html`in r&&r.html?d.setHTML(r.html):d.textContent=r.text??``,u.appendChild(d),c.setAttribute(i?`aria-describedby`:`aria-labelledby`,`${s}-message`),l.appendChild(u),c.appendChild(l);let f=document.createElement(`button`);if(f.type=`button`,f.className=e(`close`),f.setAttribute(`data-appearance`,`ring`),f.setAttribute(`aria-label`,`Close`),f.addEventListener(`click`,()=>this._hideToast(c)),c.appendChild(f),r.timer&&o>0&&isFinite(o)){let t=document.createElement(`div`);t.className=e(`toast-timer`),t.setAttribute(`aria-hidden`,`true`),t.style.setProperty(`--_timer-duration`,`${o}ms`),c.appendChild(t)}if(this._capturePositions(),this.placement.includes(`bottom`)?this.appendChild(c):this.prepend(c),this.matches(`:popover-open`)||this.showPopover(),!this.emit(`show`,{cancelable:!0,detail:{toast:c}}))return c.remove(),c;requestAnimationFrame(()=>{c.setAttribute(`showing`,``),this._animatePositions();let e=t=>{t.target===c&&(c.removeEventListener(`transitionend`,e),this.emit(`after-show`,{detail:{toast:c}}))};c.addEventListener(`transitionend`,e)}),o>0&&isFinite(o)&&this._startTimer(c,o),c.addEventListener(`pointerenter`,()=>this._pauseTimer(c)),c.addEventListener(`pointerleave`,()=>this._resumeTimer(c)),c.addEventListener(`focusin`,()=>this._pauseTimer(c)),c.addEventListener(`focusout`,()=>this._resumeTimer(c));let p=null,m=!1;c.addEventListener(`pointerdown`,e=>{e.button===0&&(e.target.closest(`button, a, [role="button"]`)||(p={x:e.clientX,y:e.clientY},m=!1,c.setPointerCapture(e.pointerId),c.style.transition=`none`))});let h=e=>this.placement.endsWith(`-start`)?Math.min(e,0):this.placement.endsWith(`-end`)?Math.max(e,0):e;return c.addEventListener(`pointermove`,e=>{if(!p)return;let t=h(e.clientX-p.x),n=e.clientY-p.y,r=e.pointerType===`touch`?10:2;if(!(!m&&Math.abs(t)<r)){if(!m&&Math.abs(n)>Math.abs(t)){p=null;return}m=!0,this._pauseTimer(c),c.style.transform=`translateX(${t}px)`,c.style.opacity=`${1-Math.abs(t)/300}`}}),c.addEventListener(`pointerup`,e=>{if(!p)return;let t=h(e.clientX-p.x);if(p=null,c.style.transition=``,m&&Math.abs(t)>50){let e=t>0?1:-1;c.style.transform=`translateX(${e*120}%)`,c.style.opacity=`0`,c.addEventListener(`transitionend`,()=>this._hideToast(c),{once:!0})}else c.style.transform=``,c.style.opacity=``,m&&this._resumeTimer(c);m=!1}),c}_startTimer(e,t){let n=window.setTimeout(()=>this._hideToast(e),t);this._timers.set(e,{remaining:t,startTime:performance.now(),timeoutId:n,paused:!1})}_pauseTimer(t){let n=this._timers.get(t);if(!n||n.paused)return;clearTimeout(n.timeoutId),n.remaining-=performance.now()-n.startTime,n.paused=!0;let r=t.querySelector(`.${e(`toast-timer`)}`);if(r)for(let e of r.getAnimations())e.pause()}_resumeTimer(t){let n=this._timers.get(t);if(!n||!n.paused||n.remaining<=0||this._documentHidden)return;n.startTime=performance.now(),n.timeoutId=window.setTimeout(()=>this._hideToast(t),n.remaining),n.paused=!1;let r=t.querySelector(`.${e(`toast-timer`)}`);if(r)for(let e of r.getAnimations())e.play()}_hideToast(e){let n=this._timers.get(e);if(n&&(clearTimeout(n.timeoutId),this._timers.delete(e)),!e.hasAttribute(`showing`)||!this.emit(`hide`,{cancelable:!0,detail:{toast:e}}))return;this._capturePositions(),e.removeAttribute(`showing`);let r=()=>{e.remove(),this._animatePositions(),this.emit(`after-hide`,{detail:{toast:e}}),this.querySelectorAll(`:scope > ${t(`toast-item`)}`).length===0&&this.matches(`:popover-open`)&&this.hidePopover()};if(parseFloat(getComputedStyle(e).transitionDuration)===0)r();else{let t=n=>{n.target===e&&(e.removeEventListener(`transitionend`,t),r())};e.addEventListener(`transitionend`,t)}}_capturePositions(){let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);for(let t of e)this._positionCache.set(t,t.getBoundingClientRect())}_animatePositions(){if(window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;let e=this.querySelectorAll(`:scope > ${t(`toast-item`)}`);for(let t of e){let e=this._positionCache.get(t);if(!e)continue;let n=t.getBoundingClientRect(),r=e.top-n.top;Math.abs(r)<1||t.animate([{transform:`translateY(${r}px)`},{transform:`translateY(0)`}],{duration:200,easing:`cubic-bezier(0.2, 0, 0, 1)`})}}};a([i({reflect:!0})],s.prototype,`placement`,void 0),a([i({type:Number,reflect:!0})],s.prototype,`duration`,void 0),a([i({reflect:!0})],s.prototype,`variant`,void 0);export{s as Toast,o as ToastItem};
|
|
2
2
|
//# sourceMappingURL=toast.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.js","names":[],"sources":["../../../src/html/elements/toast/toast.ts"],"sourcesContent":["/* eslint-disable no-shadow -- the local `toast` HTMLElement intentionally\n shadows the module-level `toast()` export; renaming would touch ~50 lines\n without behavioral benefit. */\nimport { LuxenElement } from '../../shared/luxen-element';\nimport { property } from 'lit/decorators.js';\nimport { tagName, cls, uniqueId } from '../../registry';\n\ndeclare global {\n interface Element {\n /** @see https://developer.mozilla.org/en-US/docs/Web/API/Element/setHTML */\n setHTML(input: string, options?: Record<string, unknown>): void;\n }\n}\n\n/** Minimal custom element for toast items — no render, no shadow DOM. */\nexport class LuxenToastItem extends HTMLElement {}\n\ninterface ToastOptionsBase {\n /** Optional heading text displayed above the message. */\n heading?: string;\n /** Override the element's variant for this toast. */\n variant?: string;\n /** Override auto-dismiss duration (ms) for this toast. 0 = no auto-dismiss. */\n duration?: number;\n /** Iconify icon name (e.g. 'lucide:check'). Replaces the accent bar. */\n icon?: string;\n /** Show a countdown progress bar at the bottom. Default `false`. */\n timer?: boolean;\n}\n\nexport type ToastOptions =\n | (ToastOptionsBase & { /** The message text to display. */ text: string; html?: never })\n | (ToastOptionsBase & {\n text?: never;\n /** HTML content (sanitized via the Sanitizer API). */ html: string;\n });\n\ninterface TimerState {\n remaining: number;\n startTime: number;\n timeoutId: number;\n paused: boolean;\n}\n\n/**\n * @summary A toast notification container that generates toast items internally.\n * @customElement l-toast\n *\n * @event show - Emitted when a toast begins to show. Cancelable.\n * @event after-show - Emitted after the show animation completes.\n * @event hide - Emitted when a toast begins to hide. Cancelable.\n * @event after-hide - Emitted after the hide animation completes and toast is removed.\n *\n * @cssproperty --gap - Gap between stacked toast items.\n * @cssproperty --width - Width of the toast stack.\n * @cssproperty --show-duration - Duration of the show animation.\n * @cssproperty --hide-duration - Duration of the hide animation.\n */\nexport class LuxenToast extends LuxenElement {\n /** Use light DOM — no Shadow DOM. */\n override createRenderRoot() {\n return this;\n }\n\n /** Position of the toast stack on the screen. */\n @property({ reflect: true }) placement:\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end' = 'top-end';\n\n /** Default auto-dismiss delay in milliseconds. 0 disables auto-dismiss. */\n @property({ type: Number, reflect: true }) duration = 5000;\n\n /** Default variant for toast items: info, success, warning, danger. */\n @property({ reflect: true }) variant = '';\n\n private _timers = new WeakMap<HTMLElement, TimerState>();\n private _positionCache = new WeakMap<Element, DOMRect>();\n private _documentHidden = false;\n\n override connectedCallback() {\n super.connectedCallback();\n this.popover = 'manual';\n this.setAttribute('role', 'log');\n this.setAttribute('aria-live', 'polite');\n this.setAttribute('aria-relevant', 'additions');\n\n document.addEventListener('keydown', this._onKeyDown);\n document.addEventListener('visibilitychange', this._onVisibilityChange);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this._onKeyDown);\n document.removeEventListener('visibilitychange', this._onVisibilityChange);\n }\n\n /** Create and show a toast notification. */\n toast(options: ToastOptions): HTMLElement {\n const { heading, variant = this.variant, duration = this.duration } = options;\n\n // Build toast DOM\n const uid = uniqueId('toast');\n const toast = document.createElement(tagName('toast-item'));\n if (variant) toast.setAttribute('variant', variant);\n toast.setAttribute('role', variant === 'danger' ? 'alert' : 'status');\n toast.setAttribute('aria-atomic', 'true');\n\n if (options.icon) {\n const icon = document.createElement('iconify-icon');\n icon.setAttribute('icon', options.icon);\n icon.setAttribute('width', '20');\n icon.setAttribute('height', '20');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = cls('toast-icon');\n toast.appendChild(icon);\n } else {\n const accent = document.createElement('div');\n accent.className = cls('toast-accent');\n accent.setAttribute('aria-hidden', 'true');\n toast.appendChild(accent);\n }\n\n const content = document.createElement('div');\n content.className = cls('toast-content');\n\n const textWrap = document.createElement('div');\n\n if (heading) {\n const headingEl = document.createElement('div');\n headingEl.id = `${uid}-heading`;\n headingEl.className = `${cls('toast-heading')} font-medium`;\n headingEl.textContent = heading;\n textWrap.appendChild(headingEl);\n toast.setAttribute('aria-labelledby', `${uid}-heading`);\n }\n\n const messageEl = document.createElement('div');\n messageEl.id = `${uid}-message`;\n messageEl.className = cls('toast-message');\n if ('html' in options && options.html) {\n messageEl.setHTML(options.html);\n } else {\n messageEl.textContent = options.text ?? '';\n }\n textWrap.appendChild(messageEl);\n toast.setAttribute(heading ? 'aria-describedby' : 'aria-labelledby', `${uid}-message`);\n\n content.appendChild(textWrap);\n toast.appendChild(content);\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = cls('close');\n closeBtn.setAttribute('data-appearance', 'ring');\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.addEventListener('click', () => this._hideToast(toast));\n toast.appendChild(closeBtn);\n\n // Timer bar (opt-in)\n if (options.timer && duration > 0 && isFinite(duration)) {\n const timerBar = document.createElement('div');\n timerBar.className = cls('toast-timer');\n timerBar.setAttribute('aria-hidden', 'true');\n timerBar.style.setProperty('--_timer-duration', `${duration}ms`);\n toast.appendChild(timerBar);\n }\n\n // FLIP: capture existing positions\n this._capturePositions();\n\n // Insert into container\n if (this.placement.includes('bottom')) {\n this.appendChild(toast);\n } else {\n this.prepend(toast);\n }\n\n // Show popover if not already open\n if (!this.matches(':popover-open')) {\n this.showPopover();\n }\n\n // Dispatch show\n if (!this.emit('show', { cancelable: true, detail: { toast } })) {\n toast.remove();\n return toast;\n }\n\n // Trigger show animation on next frame\n requestAnimationFrame(() => {\n toast.setAttribute('showing', '');\n this._animatePositions();\n\n const onShown = (e: TransitionEvent) => {\n if (e.target !== toast) return;\n toast.removeEventListener('transitionend', onShown);\n this.emit('after-show', { detail: { toast } });\n };\n toast.addEventListener('transitionend', onShown);\n });\n\n // Auto-dismiss timer (0 or Infinity = persistent)\n if (duration > 0 && isFinite(duration)) {\n this._startTimer(toast, duration);\n }\n\n // Pause/resume timer on hover and focus\n toast.addEventListener('pointerenter', () => this._pauseTimer(toast));\n toast.addEventListener('pointerleave', () => this._resumeTimer(toast));\n toast.addEventListener('focusin', () => this._pauseTimer(toast));\n toast.addEventListener('focusout', () => this._resumeTimer(toast));\n\n // ── Swipe-to-dismiss ──────────────────────────────────────────────────────\n\n let swipeStart: { x: number; y: number } | null = null;\n let swiping = false;\n\n toast.addEventListener('pointerdown', (e: PointerEvent) => {\n if (e.button !== 0) return;\n if ((e.target as Element).closest('button, a, [role=\"button\"]')) return;\n swipeStart = { x: e.clientX, y: e.clientY };\n swiping = false;\n toast.setPointerCapture(e.pointerId);\n toast.style.transition = 'none';\n });\n\n // Only allow swiping away from the screen edge, never inward\n const clampDelta = (dx: number) =>\n this.placement.endsWith('-start')\n ? Math.min(dx, 0)\n : this.placement.endsWith('-end')\n ? Math.max(dx, 0)\n : dx;\n\n toast.addEventListener('pointermove', (e: PointerEvent) => {\n if (!swipeStart) return;\n const deltaX = clampDelta(e.clientX - swipeStart.x);\n const deltaY = e.clientY - swipeStart.y;\n\n const buffer = e.pointerType === 'touch' ? 10 : 2;\n if (!swiping && Math.abs(deltaX) < buffer) return;\n\n // If vertical movement dominates, cancel swipe tracking\n if (!swiping && Math.abs(deltaY) > Math.abs(deltaX)) {\n swipeStart = null;\n return;\n }\n\n swiping = true;\n this._pauseTimer(toast);\n toast.style.transform = `translateX(${deltaX}px)`;\n toast.style.opacity = `${1 - Math.abs(deltaX) / 300}`;\n });\n\n toast.addEventListener('pointerup', (e: PointerEvent) => {\n if (!swipeStart) return;\n const deltaX = clampDelta(e.clientX - swipeStart.x);\n swipeStart = null;\n toast.style.transition = '';\n\n if (swiping && Math.abs(deltaX) > 50) {\n const dir = deltaX > 0 ? 1 : -1;\n toast.style.transform = `translateX(${dir * 120}%)`;\n toast.style.opacity = '0';\n toast.addEventListener('transitionend', () => this._hideToast(toast), { once: true });\n } else {\n toast.style.transform = '';\n toast.style.opacity = '';\n if (swiping) this._resumeTimer(toast);\n }\n swiping = false;\n });\n\n return toast;\n }\n\n // ── Timer management ──────────────────────────────────────────────────────────\n\n private _startTimer(toast: HTMLElement, duration: number) {\n const timeoutId = window.setTimeout(() => this._hideToast(toast), duration);\n this._timers.set(toast, {\n remaining: duration,\n startTime: performance.now(),\n timeoutId,\n paused: false,\n });\n }\n\n private _pauseTimer(toast: HTMLElement) {\n const timer = this._timers.get(toast);\n if (!timer || timer.paused) return;\n clearTimeout(timer.timeoutId);\n timer.remaining -= performance.now() - timer.startTime;\n timer.paused = true;\n\n // Use the Web Animations API to pause the countdown bar. CSS `animation-play-state`\n // cannot be used here because browsers defer style recalculations while the tab is\n // hidden, so the animation runs to completion before the style change takes effect.\n const timerBar = toast.querySelector(`.${cls('toast-timer')}`);\n if (timerBar) for (const anim of timerBar.getAnimations()) anim.pause();\n }\n\n private _resumeTimer(toast: HTMLElement) {\n const timer = this._timers.get(toast);\n if (!timer || !timer.paused || timer.remaining <= 0 || this._documentHidden) return;\n timer.startTime = performance.now();\n timer.timeoutId = window.setTimeout(() => this._hideToast(toast), timer.remaining);\n timer.paused = false;\n\n const timerBar = toast.querySelector(`.${cls('toast-timer')}`);\n if (timerBar) for (const anim of timerBar.getAnimations()) anim.play();\n }\n\n // ── Hide a toast ──────────────────────────────────────────────────────────────\n\n private _hideToast(toast: HTMLElement) {\n // Clear timer\n const timer = this._timers.get(toast);\n if (timer) {\n clearTimeout(timer.timeoutId);\n this._timers.delete(toast);\n }\n\n // Prevent double-hide\n if (!toast.hasAttribute('showing')) return;\n\n // Dispatch hide\n if (!this.emit('hide', { cancelable: true, detail: { toast } })) return;\n\n this._capturePositions();\n\n // Remove showing class to trigger exit transition\n toast.removeAttribute('showing');\n\n const remove = () => {\n toast.remove();\n this._animatePositions();\n\n this.emit('after-hide', { detail: { toast } });\n\n // Close popover if no toasts remain\n const remaining = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n if (remaining.length === 0 && this.matches(':popover-open')) {\n this.hidePopover();\n }\n };\n\n // Handle zero-duration transitions (reduced motion)\n const duration = parseFloat(getComputedStyle(toast).transitionDuration);\n if (duration === 0) {\n remove();\n } else {\n const onEnd = (e: TransitionEvent) => {\n if (e.target !== toast) return;\n toast.removeEventListener('transitionend', onEnd);\n remove();\n };\n toast.addEventListener('transitionend', onEnd);\n }\n }\n\n // ── FLIP animation for reordering ─────────────────────────────────────────────\n\n private _capturePositions() {\n const items = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n for (const child of items) {\n this._positionCache.set(child, child.getBoundingClientRect());\n }\n }\n\n private _animatePositions() {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n\n const items = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n for (const child of items) {\n const oldRect = this._positionCache.get(child);\n if (!oldRect) continue;\n\n const newRect = child.getBoundingClientRect();\n const deltaY = oldRect.top - newRect.top;\n\n if (Math.abs(deltaY) < 1) continue;\n\n (child as HTMLElement).animate(\n [{ transform: `translateY(${deltaY}px)` }, { transform: 'translateY(0)' }],\n { duration: 200, easing: 'cubic-bezier(0.2, 0, 0, 1)' },\n );\n }\n }\n\n // ── Document visibility ──────────────────────────────────────────────────────\n\n private _onVisibilityChange = () => {\n this._documentHidden = document.hidden;\n const items = this.querySelectorAll<HTMLElement>(`:scope > ${tagName('toast-item')}`);\n if (document.hidden) {\n for (const item of items) this._pauseTimer(item);\n } else {\n for (const item of items) this._resumeTimer(item);\n }\n };\n\n // ── Keyboard ──────────────────────────────────────────────────────────────────\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (!this.matches(':popover-open')) return;\n\n const last = this.querySelector<HTMLElement>(`:scope > ${tagName('toast-item')}:last-of-type`);\n if (last) {\n e.preventDefault();\n this._hideToast(last);\n }\n };\n}\n\n// ── Standalone function ───────────────────────────────────────────────────────\n\nlet _defaultInstance: LuxenToast | null = null;\n\nfunction _getDefault(): LuxenToast {\n if (!_defaultInstance || !_defaultInstance.isConnected) {\n _defaultInstance =\n document.querySelector(tagName('toast')) ??\n (document.createElement(tagName('toast')) as LuxenToast);\n if (!_defaultInstance.isConnected) {\n document.body.appendChild(_defaultInstance);\n }\n }\n return _defaultInstance;\n}\n\n/** Show a toast notification. Auto-creates `<l-toast>` if none exists in the DOM. */\nexport function toast(options: ToastOptions): HTMLElement {\n return _getDefault().toast(options);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toast.js","names":[],"sources":["../../../src/html/elements/toast/toast.ts"],"sourcesContent":["/* eslint-disable no-shadow -- the local `toast` HTMLElement intentionally\n shadows the module-level `toast()` export; renaming would touch ~50 lines\n without behavioral benefit. */\nimport { LuxenElement } from '../../shared/luxen-element';\nimport { property } from 'lit/decorators.js';\nimport { tagName, cls, uniqueId } from '../../registry';\n\ndeclare global {\n interface Element {\n /** @see https://developer.mozilla.org/en-US/docs/Web/API/Element/setHTML */\n setHTML(input: string, options?: Record<string, unknown>): void;\n }\n}\n\n/** Minimal custom element for toast items — no render, no shadow DOM. */\nexport class ToastItem extends HTMLElement {}\n\ninterface ToastOptionsBase {\n /** Optional heading text displayed above the message. */\n heading?: string;\n /** Override the element's variant for this toast. */\n variant?: string;\n /** Override auto-dismiss duration (ms) for this toast. 0 = no auto-dismiss. */\n duration?: number;\n /** Iconify icon name (e.g. 'lucide:check'). Replaces the accent bar. */\n icon?: string;\n /** Show a countdown progress bar at the bottom. Default `false`. */\n timer?: boolean;\n}\n\nexport type ToastOptions =\n | (ToastOptionsBase & { /** The message text to display. */ text: string; html?: never })\n | (ToastOptionsBase & {\n text?: never;\n /** HTML content (sanitized via the Sanitizer API). */ html: string;\n });\n\ninterface TimerState {\n remaining: number;\n startTime: number;\n timeoutId: number;\n paused: boolean;\n}\n\n/**\n * @summary A toast notification container that generates toast items internally.\n * @customElement l-toast\n *\n * @event show - Emitted when a toast begins to show. Cancelable.\n * @event after-show - Emitted after the show animation completes.\n * @event hide - Emitted when a toast begins to hide. Cancelable.\n * @event after-hide - Emitted after the hide animation completes and toast is removed.\n *\n * @cssproperty --gap - Gap between stacked toast items.\n * @cssproperty --width - Width of the toast stack.\n * @cssproperty --show-duration - Duration of the show animation.\n * @cssproperty --hide-duration - Duration of the hide animation.\n */\nexport class Toast extends LuxenElement {\n /** Use light DOM — no Shadow DOM. */\n override createRenderRoot() {\n return this;\n }\n\n /** Position of the toast stack on the screen. */\n @property({ reflect: true }) placement:\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end' = 'top-end';\n\n /** Default auto-dismiss delay in milliseconds. 0 disables auto-dismiss. */\n @property({ type: Number, reflect: true }) duration = 5000;\n\n /** Default variant for toast items: info, success, warning, danger. */\n @property({ reflect: true }) variant = '';\n\n private _timers = new WeakMap<HTMLElement, TimerState>();\n private _positionCache = new WeakMap<Element, DOMRect>();\n private _documentHidden = false;\n\n override connectedCallback() {\n super.connectedCallback();\n this.popover = 'manual';\n this.setAttribute('role', 'log');\n this.setAttribute('aria-live', 'polite');\n this.setAttribute('aria-relevant', 'additions');\n\n document.addEventListener('keydown', this._onKeyDown);\n document.addEventListener('visibilitychange', this._onVisibilityChange);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this._onKeyDown);\n document.removeEventListener('visibilitychange', this._onVisibilityChange);\n }\n\n /** Create and show a toast notification. */\n toast(options: ToastOptions): HTMLElement {\n const { heading, variant = this.variant, duration = this.duration } = options;\n\n // Build toast DOM\n const uid = uniqueId('toast');\n const toast = document.createElement(tagName('toast-item'));\n if (variant) toast.setAttribute('variant', variant);\n toast.setAttribute('role', variant === 'danger' ? 'alert' : 'status');\n toast.setAttribute('aria-atomic', 'true');\n\n if (options.icon) {\n const icon = document.createElement('iconify-icon');\n icon.setAttribute('icon', options.icon);\n icon.setAttribute('width', '20');\n icon.setAttribute('height', '20');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = cls('toast-icon');\n toast.appendChild(icon);\n } else {\n const accent = document.createElement('div');\n accent.className = cls('toast-accent');\n accent.setAttribute('aria-hidden', 'true');\n toast.appendChild(accent);\n }\n\n const content = document.createElement('div');\n content.className = cls('toast-content');\n\n const textWrap = document.createElement('div');\n\n if (heading) {\n const headingEl = document.createElement('div');\n headingEl.id = `${uid}-heading`;\n headingEl.className = `${cls('toast-heading')} font-medium`;\n headingEl.textContent = heading;\n textWrap.appendChild(headingEl);\n toast.setAttribute('aria-labelledby', `${uid}-heading`);\n }\n\n const messageEl = document.createElement('div');\n messageEl.id = `${uid}-message`;\n messageEl.className = cls('toast-message');\n if ('html' in options && options.html) {\n messageEl.setHTML(options.html);\n } else {\n messageEl.textContent = options.text ?? '';\n }\n textWrap.appendChild(messageEl);\n toast.setAttribute(heading ? 'aria-describedby' : 'aria-labelledby', `${uid}-message`);\n\n content.appendChild(textWrap);\n toast.appendChild(content);\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = cls('close');\n closeBtn.setAttribute('data-appearance', 'ring');\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.addEventListener('click', () => this._hideToast(toast));\n toast.appendChild(closeBtn);\n\n // Timer bar (opt-in)\n if (options.timer && duration > 0 && isFinite(duration)) {\n const timerBar = document.createElement('div');\n timerBar.className = cls('toast-timer');\n timerBar.setAttribute('aria-hidden', 'true');\n timerBar.style.setProperty('--_timer-duration', `${duration}ms`);\n toast.appendChild(timerBar);\n }\n\n // FLIP: capture existing positions\n this._capturePositions();\n\n // Insert into container\n if (this.placement.includes('bottom')) {\n this.appendChild(toast);\n } else {\n this.prepend(toast);\n }\n\n // Show popover if not already open\n if (!this.matches(':popover-open')) {\n this.showPopover();\n }\n\n // Dispatch show\n if (!this.emit('show', { cancelable: true, detail: { toast } })) {\n toast.remove();\n return toast;\n }\n\n // Trigger show animation on next frame\n requestAnimationFrame(() => {\n toast.setAttribute('showing', '');\n this._animatePositions();\n\n const onShown = (e: TransitionEvent) => {\n if (e.target !== toast) return;\n toast.removeEventListener('transitionend', onShown);\n this.emit('after-show', { detail: { toast } });\n };\n toast.addEventListener('transitionend', onShown);\n });\n\n // Auto-dismiss timer (0 or Infinity = persistent)\n if (duration > 0 && isFinite(duration)) {\n this._startTimer(toast, duration);\n }\n\n // Pause/resume timer on hover and focus\n toast.addEventListener('pointerenter', () => this._pauseTimer(toast));\n toast.addEventListener('pointerleave', () => this._resumeTimer(toast));\n toast.addEventListener('focusin', () => this._pauseTimer(toast));\n toast.addEventListener('focusout', () => this._resumeTimer(toast));\n\n // ── Swipe-to-dismiss ──────────────────────────────────────────────────────\n\n let swipeStart: { x: number; y: number } | null = null;\n let swiping = false;\n\n toast.addEventListener('pointerdown', (e: PointerEvent) => {\n if (e.button !== 0) return;\n if ((e.target as Element).closest('button, a, [role=\"button\"]')) return;\n swipeStart = { x: e.clientX, y: e.clientY };\n swiping = false;\n toast.setPointerCapture(e.pointerId);\n toast.style.transition = 'none';\n });\n\n // Only allow swiping away from the screen edge, never inward\n const clampDelta = (dx: number) =>\n this.placement.endsWith('-start')\n ? Math.min(dx, 0)\n : this.placement.endsWith('-end')\n ? Math.max(dx, 0)\n : dx;\n\n toast.addEventListener('pointermove', (e: PointerEvent) => {\n if (!swipeStart) return;\n const deltaX = clampDelta(e.clientX - swipeStart.x);\n const deltaY = e.clientY - swipeStart.y;\n\n const buffer = e.pointerType === 'touch' ? 10 : 2;\n if (!swiping && Math.abs(deltaX) < buffer) return;\n\n // If vertical movement dominates, cancel swipe tracking\n if (!swiping && Math.abs(deltaY) > Math.abs(deltaX)) {\n swipeStart = null;\n return;\n }\n\n swiping = true;\n this._pauseTimer(toast);\n toast.style.transform = `translateX(${deltaX}px)`;\n toast.style.opacity = `${1 - Math.abs(deltaX) / 300}`;\n });\n\n toast.addEventListener('pointerup', (e: PointerEvent) => {\n if (!swipeStart) return;\n const deltaX = clampDelta(e.clientX - swipeStart.x);\n swipeStart = null;\n toast.style.transition = '';\n\n if (swiping && Math.abs(deltaX) > 50) {\n const dir = deltaX > 0 ? 1 : -1;\n toast.style.transform = `translateX(${dir * 120}%)`;\n toast.style.opacity = '0';\n toast.addEventListener('transitionend', () => this._hideToast(toast), { once: true });\n } else {\n toast.style.transform = '';\n toast.style.opacity = '';\n if (swiping) this._resumeTimer(toast);\n }\n swiping = false;\n });\n\n return toast;\n }\n\n // ── Timer management ──────────────────────────────────────────────────────────\n\n private _startTimer(toast: HTMLElement, duration: number) {\n const timeoutId = window.setTimeout(() => this._hideToast(toast), duration);\n this._timers.set(toast, {\n remaining: duration,\n startTime: performance.now(),\n timeoutId,\n paused: false,\n });\n }\n\n private _pauseTimer(toast: HTMLElement) {\n const timer = this._timers.get(toast);\n if (!timer || timer.paused) return;\n clearTimeout(timer.timeoutId);\n timer.remaining -= performance.now() - timer.startTime;\n timer.paused = true;\n\n // Use the Web Animations API to pause the countdown bar. CSS `animation-play-state`\n // cannot be used here because browsers defer style recalculations while the tab is\n // hidden, so the animation runs to completion before the style change takes effect.\n const timerBar = toast.querySelector(`.${cls('toast-timer')}`);\n if (timerBar) for (const anim of timerBar.getAnimations()) anim.pause();\n }\n\n private _resumeTimer(toast: HTMLElement) {\n const timer = this._timers.get(toast);\n if (!timer || !timer.paused || timer.remaining <= 0 || this._documentHidden) return;\n timer.startTime = performance.now();\n timer.timeoutId = window.setTimeout(() => this._hideToast(toast), timer.remaining);\n timer.paused = false;\n\n const timerBar = toast.querySelector(`.${cls('toast-timer')}`);\n if (timerBar) for (const anim of timerBar.getAnimations()) anim.play();\n }\n\n // ── Hide a toast ──────────────────────────────────────────────────────────────\n\n private _hideToast(toast: HTMLElement) {\n // Clear timer\n const timer = this._timers.get(toast);\n if (timer) {\n clearTimeout(timer.timeoutId);\n this._timers.delete(toast);\n }\n\n // Prevent double-hide\n if (!toast.hasAttribute('showing')) return;\n\n // Dispatch hide\n if (!this.emit('hide', { cancelable: true, detail: { toast } })) return;\n\n this._capturePositions();\n\n // Remove showing class to trigger exit transition\n toast.removeAttribute('showing');\n\n const remove = () => {\n toast.remove();\n this._animatePositions();\n\n this.emit('after-hide', { detail: { toast } });\n\n // Close popover if no toasts remain\n const remaining = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n if (remaining.length === 0 && this.matches(':popover-open')) {\n this.hidePopover();\n }\n };\n\n // Handle zero-duration transitions (reduced motion)\n const duration = parseFloat(getComputedStyle(toast).transitionDuration);\n if (duration === 0) {\n remove();\n } else {\n const onEnd = (e: TransitionEvent) => {\n if (e.target !== toast) return;\n toast.removeEventListener('transitionend', onEnd);\n remove();\n };\n toast.addEventListener('transitionend', onEnd);\n }\n }\n\n // ── FLIP animation for reordering ─────────────────────────────────────────────\n\n private _capturePositions() {\n const items = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n for (const child of items) {\n this._positionCache.set(child, child.getBoundingClientRect());\n }\n }\n\n private _animatePositions() {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n\n const items = this.querySelectorAll(`:scope > ${tagName('toast-item')}`);\n for (const child of items) {\n const oldRect = this._positionCache.get(child);\n if (!oldRect) continue;\n\n const newRect = child.getBoundingClientRect();\n const deltaY = oldRect.top - newRect.top;\n\n if (Math.abs(deltaY) < 1) continue;\n\n (child as HTMLElement).animate(\n [{ transform: `translateY(${deltaY}px)` }, { transform: 'translateY(0)' }],\n { duration: 200, easing: 'cubic-bezier(0.2, 0, 0, 1)' },\n );\n }\n }\n\n // ── Document visibility ──────────────────────────────────────────────────────\n\n private _onVisibilityChange = () => {\n this._documentHidden = document.hidden;\n const items = this.querySelectorAll<HTMLElement>(`:scope > ${tagName('toast-item')}`);\n if (document.hidden) {\n for (const item of items) this._pauseTimer(item);\n } else {\n for (const item of items) this._resumeTimer(item);\n }\n };\n\n // ── Keyboard ──────────────────────────────────────────────────────────────────\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (!this.matches(':popover-open')) return;\n\n const last = this.querySelector<HTMLElement>(`:scope > ${tagName('toast-item')}:last-of-type`);\n if (last) {\n e.preventDefault();\n this._hideToast(last);\n }\n };\n}\n\n// ── Standalone function ───────────────────────────────────────────────────────\n\nlet _defaultInstance: Toast | null = null;\n\nfunction _getDefault(): Toast {\n if (!_defaultInstance || !_defaultInstance.isConnected) {\n _defaultInstance =\n document.querySelector(tagName('toast')) ??\n (document.createElement(tagName('toast')) as Toast);\n if (!_defaultInstance.isConnected) {\n document.body.appendChild(_defaultInstance);\n }\n }\n return _defaultInstance;\n}\n\n/** Show a toast notification. Auto-creates `<l-toast>` if none exists in the DOM. */\nexport function toast(options: ToastOptions): HTMLElement {\n return _getDefault().toast(options);\n}\n"],"mappings":"+KAeA,IAAa,EAAb,cAA+B,WAAY,GA2C9B,EAAb,cAA2B,CAAa,8CAanB,wBAGmC,iBAGf,gBAErB,IAAI,4BACG,IAAI,6BACH,gCA2TU,CAClC,KAAK,gBAAkB,SAAS,OAChC,IAAM,EAAQ,KAAK,iBAA8B,YAAY,EAAQ,aAAa,GAAG,CACrF,GAAI,SAAS,OACX,IAAK,IAAM,KAAQ,EAAO,KAAK,YAAY,EAAK,MAEhD,IAAK,IAAM,KAAQ,EAAO,KAAK,aAAa,EAAK,kBAM/B,GAAqB,CAEzC,GADI,EAAE,MAAQ,UACV,CAAC,KAAK,QAAQ,gBAAgB,CAAE,OAEpC,IAAM,EAAO,KAAK,cAA2B,YAAY,EAAQ,aAAa,CAAC,eAAe,CAC1F,IACF,EAAE,gBAAgB,CAClB,KAAK,WAAW,EAAK,GAnWzB,kBAA4B,CAC1B,OAAO,KAsBT,mBAA6B,CAC3B,MAAM,mBAAmB,CACzB,KAAK,QAAU,SACf,KAAK,aAAa,OAAQ,MAAM,CAChC,KAAK,aAAa,YAAa,SAAS,CACxC,KAAK,aAAa,gBAAiB,YAAY,CAE/C,SAAS,iBAAiB,UAAW,KAAK,WAAW,CACrD,SAAS,iBAAiB,mBAAoB,KAAK,oBAAoB,CAGzE,sBAAgC,CAC9B,MAAM,sBAAsB,CAC5B,SAAS,oBAAoB,UAAW,KAAK,WAAW,CACxD,SAAS,oBAAoB,mBAAoB,KAAK,oBAAoB,CAI5E,MAAM,EAAoC,CACxC,GAAM,CAAE,UAAS,UAAU,KAAK,QAAS,WAAW,KAAK,UAAa,EAGhE,EAAM,EAAS,QAAQ,CACvB,EAAQ,SAAS,cAAc,EAAQ,aAAa,CAAC,CAK3D,GAJI,GAAS,EAAM,aAAa,UAAW,EAAQ,CACnD,EAAM,aAAa,OAAQ,IAAY,SAAW,QAAU,SAAS,CACrE,EAAM,aAAa,cAAe,OAAO,CAErC,EAAQ,KAAM,CAChB,IAAM,EAAO,SAAS,cAAc,eAAe,CACnD,EAAK,aAAa,OAAQ,EAAQ,KAAK,CACvC,EAAK,aAAa,QAAS,KAAK,CAChC,EAAK,aAAa,SAAU,KAAK,CACjC,EAAK,aAAa,cAAe,OAAO,CACxC,EAAK,UAAY,EAAI,aAAa,CAClC,EAAM,YAAY,EAAK,KAClB,CACL,IAAM,EAAS,SAAS,cAAc,MAAM,CAC5C,EAAO,UAAY,EAAI,eAAe,CACtC,EAAO,aAAa,cAAe,OAAO,CAC1C,EAAM,YAAY,EAAO,CAG3B,IAAM,EAAU,SAAS,cAAc,MAAM,CAC7C,EAAQ,UAAY,EAAI,gBAAgB,CAExC,IAAM,EAAW,SAAS,cAAc,MAAM,CAE9C,GAAI,EAAS,CACX,IAAM,EAAY,SAAS,cAAc,MAAM,CAC/C,EAAU,GAAK,GAAG,EAAI,UACtB,EAAU,UAAY,GAAG,EAAI,gBAAgB,CAAC,cAC9C,EAAU,YAAc,EACxB,EAAS,YAAY,EAAU,CAC/B,EAAM,aAAa,kBAAmB,GAAG,EAAI,UAAU,CAGzD,IAAM,EAAY,SAAS,cAAc,MAAM,CAC/C,EAAU,GAAK,GAAG,EAAI,UACtB,EAAU,UAAY,EAAI,gBAAgB,CACtC,SAAU,GAAW,EAAQ,KAC/B,EAAU,QAAQ,EAAQ,KAAK,CAE/B,EAAU,YAAc,EAAQ,MAAQ,GAE1C,EAAS,YAAY,EAAU,CAC/B,EAAM,aAAa,EAAU,mBAAqB,kBAAmB,GAAG,EAAI,UAAU,CAEtF,EAAQ,YAAY,EAAS,CAC7B,EAAM,YAAY,EAAQ,CAE1B,IAAM,EAAW,SAAS,cAAc,SAAS,CASjD,GARA,EAAS,KAAO,SAChB,EAAS,UAAY,EAAI,QAAQ,CACjC,EAAS,aAAa,kBAAmB,OAAO,CAChD,EAAS,aAAa,aAAc,QAAQ,CAC5C,EAAS,iBAAiB,YAAe,KAAK,WAAW,EAAM,CAAC,CAChE,EAAM,YAAY,EAAS,CAGvB,EAAQ,OAAS,EAAW,GAAK,SAAS,EAAS,CAAE,CACvD,IAAM,EAAW,SAAS,cAAc,MAAM,CAC9C,EAAS,UAAY,EAAI,cAAc,CACvC,EAAS,aAAa,cAAe,OAAO,CAC5C,EAAS,MAAM,YAAY,oBAAqB,GAAG,EAAS,IAAI,CAChE,EAAM,YAAY,EAAS,CAmB7B,GAfA,KAAK,mBAAmB,CAGpB,KAAK,UAAU,SAAS,SAAS,CACnC,KAAK,YAAY,EAAM,CAEvB,KAAK,QAAQ,EAAM,CAIhB,KAAK,QAAQ,gBAAgB,EAChC,KAAK,aAAa,CAIhB,CAAC,KAAK,KAAK,OAAQ,CAAE,WAAY,GAAM,OAAQ,CAAE,QAAO,CAAE,CAAC,CAE7D,OADA,EAAM,QAAQ,CACP,EAIT,0BAA4B,CAC1B,EAAM,aAAa,UAAW,GAAG,CACjC,KAAK,mBAAmB,CAExB,IAAM,EAAW,GAAuB,CAClC,EAAE,SAAW,IACjB,EAAM,oBAAoB,gBAAiB,EAAQ,CACnD,KAAK,KAAK,aAAc,CAAE,OAAQ,CAAE,QAAO,CAAE,CAAC,GAEhD,EAAM,iBAAiB,gBAAiB,EAAQ,EAChD,CAGE,EAAW,GAAK,SAAS,EAAS,EACpC,KAAK,YAAY,EAAO,EAAS,CAInC,EAAM,iBAAiB,mBAAsB,KAAK,YAAY,EAAM,CAAC,CACrE,EAAM,iBAAiB,mBAAsB,KAAK,aAAa,EAAM,CAAC,CACtE,EAAM,iBAAiB,cAAiB,KAAK,YAAY,EAAM,CAAC,CAChE,EAAM,iBAAiB,eAAkB,KAAK,aAAa,EAAM,CAAC,CAIlE,IAAI,EAA8C,KAC9C,EAAU,GAEd,EAAM,iBAAiB,cAAgB,GAAoB,CACrD,EAAE,SAAW,IACZ,EAAE,OAAmB,QAAQ,6BAA6B,GAC/D,EAAa,CAAE,EAAG,EAAE,QAAS,EAAG,EAAE,QAAS,CAC3C,EAAU,GACV,EAAM,kBAAkB,EAAE,UAAU,CACpC,EAAM,MAAM,WAAa,UACzB,CAGF,IAAM,EAAc,GAClB,KAAK,UAAU,SAAS,SAAS,CAC7B,KAAK,IAAI,EAAI,EAAE,CACf,KAAK,UAAU,SAAS,OAAO,CAC7B,KAAK,IAAI,EAAI,EAAE,CACf,EAyCR,OAvCA,EAAM,iBAAiB,cAAgB,GAAoB,CACzD,GAAI,CAAC,EAAY,OACjB,IAAM,EAAS,EAAW,EAAE,QAAU,EAAW,EAAE,CAC7C,EAAS,EAAE,QAAU,EAAW,EAEhC,EAAS,EAAE,cAAgB,QAAU,GAAK,EAC5C,MAAC,GAAW,KAAK,IAAI,EAAO,CAAG,GAGnC,IAAI,CAAC,GAAW,KAAK,IAAI,EAAO,CAAG,KAAK,IAAI,EAAO,CAAE,CACnD,EAAa,KACb,OAGF,EAAU,GACV,KAAK,YAAY,EAAM,CACvB,EAAM,MAAM,UAAY,cAAc,EAAO,KAC7C,EAAM,MAAM,QAAU,GAAG,EAAI,KAAK,IAAI,EAAO,CAAG,QAChD,CAEF,EAAM,iBAAiB,YAAc,GAAoB,CACvD,GAAI,CAAC,EAAY,OACjB,IAAM,EAAS,EAAW,EAAE,QAAU,EAAW,EAAE,CAInD,GAHA,EAAa,KACb,EAAM,MAAM,WAAa,GAErB,GAAW,KAAK,IAAI,EAAO,CAAG,GAAI,CACpC,IAAM,EAAM,EAAS,EAAI,EAAI,GAC7B,EAAM,MAAM,UAAY,cAAc,EAAM,IAAI,IAChD,EAAM,MAAM,QAAU,IACtB,EAAM,iBAAiB,oBAAuB,KAAK,WAAW,EAAM,CAAE,CAAE,KAAM,GAAM,CAAC,MAErF,EAAM,MAAM,UAAY,GACxB,EAAM,MAAM,QAAU,GAClB,GAAS,KAAK,aAAa,EAAM,CAEvC,EAAU,IACV,CAEK,EAKT,YAAoB,EAAoB,EAAkB,CACxD,IAAM,EAAY,OAAO,eAAiB,KAAK,WAAW,EAAM,CAAE,EAAS,CAC3E,KAAK,QAAQ,IAAI,EAAO,CACtB,UAAW,EACX,UAAW,YAAY,KAAK,CAC5B,YACA,OAAQ,GACT,CAAC,CAGJ,YAAoB,EAAoB,CACtC,IAAM,EAAQ,KAAK,QAAQ,IAAI,EAAM,CACrC,GAAI,CAAC,GAAS,EAAM,OAAQ,OAC5B,aAAa,EAAM,UAAU,CAC7B,EAAM,WAAa,YAAY,KAAK,CAAG,EAAM,UAC7C,EAAM,OAAS,GAKf,IAAM,EAAW,EAAM,cAAc,IAAI,EAAI,cAAc,GAAG,CAC9D,GAAI,EAAU,IAAK,IAAM,KAAQ,EAAS,eAAe,CAAE,EAAK,OAAO,CAGzE,aAAqB,EAAoB,CACvC,IAAM,EAAQ,KAAK,QAAQ,IAAI,EAAM,CACrC,GAAI,CAAC,GAAS,CAAC,EAAM,QAAU,EAAM,WAAa,GAAK,KAAK,gBAAiB,OAC7E,EAAM,UAAY,YAAY,KAAK,CACnC,EAAM,UAAY,OAAO,eAAiB,KAAK,WAAW,EAAM,CAAE,EAAM,UAAU,CAClF,EAAM,OAAS,GAEf,IAAM,EAAW,EAAM,cAAc,IAAI,EAAI,cAAc,GAAG,CAC9D,GAAI,EAAU,IAAK,IAAM,KAAQ,EAAS,eAAe,CAAE,EAAK,MAAM,CAKxE,WAAmB,EAAoB,CAErC,IAAM,EAAQ,KAAK,QAAQ,IAAI,EAAM,CAUrC,GATI,IACF,aAAa,EAAM,UAAU,CAC7B,KAAK,QAAQ,OAAO,EAAM,EAIxB,CAAC,EAAM,aAAa,UAAU,EAG9B,CAAC,KAAK,KAAK,OAAQ,CAAE,WAAY,GAAM,OAAQ,CAAE,QAAO,CAAE,CAAC,CAAE,OAEjE,KAAK,mBAAmB,CAGxB,EAAM,gBAAgB,UAAU,CAEhC,IAAM,MAAe,CACnB,EAAM,QAAQ,CACd,KAAK,mBAAmB,CAExB,KAAK,KAAK,aAAc,CAAE,OAAQ,CAAE,QAAO,CAAE,CAAC,CAG5B,KAAK,iBAAiB,YAAY,EAAQ,aAAa,GACrE,CAAU,SAAW,GAAK,KAAK,QAAQ,gBAAgB,EACzD,KAAK,aAAa,EAMtB,GADiB,WAAW,iBAAiB,EAAM,CAAC,mBAChD,GAAa,EACf,GAAQ,KACH,CACL,IAAM,EAAS,GAAuB,CAChC,EAAE,SAAW,IACjB,EAAM,oBAAoB,gBAAiB,EAAM,CACjD,GAAQ,GAEV,EAAM,iBAAiB,gBAAiB,EAAM,EAMlD,mBAA4B,CAC1B,IAAM,EAAQ,KAAK,iBAAiB,YAAY,EAAQ,aAAa,GAAG,CACxE,IAAK,IAAM,KAAS,EAClB,KAAK,eAAe,IAAI,EAAO,EAAM,uBAAuB,CAAC,CAIjE,mBAA4B,CAC1B,GAAI,OAAO,WAAW,mCAAmC,CAAC,QAAS,OAEnE,IAAM,EAAQ,KAAK,iBAAiB,YAAY,EAAQ,aAAa,GAAG,CACxE,IAAK,IAAM,KAAS,EAAO,CACzB,IAAM,EAAU,KAAK,eAAe,IAAI,EAAM,CAC9C,GAAI,CAAC,EAAS,SAEd,IAAM,EAAU,EAAM,uBAAuB,CACvC,EAAS,EAAQ,IAAM,EAAQ,IAEjC,KAAK,IAAI,EAAO,CAAG,GAEtB,EAAsB,QACrB,CAAC,CAAE,UAAW,cAAc,EAAO,KAAM,CAAE,CAAE,UAAW,gBAAiB,CAAC,CAC1E,CAAE,SAAU,IAAK,OAAQ,6BAA8B,CACxD,OArUJ,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,YAAA,IAAA,GAAA,IAS3B,EAAS,CAAE,KAAM,OAAQ,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,WAAA,IAAA,GAAA,IAGzC,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,UAAA,IAAA,GAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Tooltip } from './tooltip';
|
|
2
2
|
export * from './tooltip';
|
|
3
3
|
declare global {
|
|
4
4
|
interface HTMLElementTagNameMap {
|
|
5
|
-
'l-tooltip':
|
|
5
|
+
'l-tooltip': Tooltip;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|