@fusion.dev/helix-headless 0.144.0 → 0.146.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/custom-elements.json +15195 -4240
- package/dist/accordion/item/accordion-item.d.ts +62 -12
- package/dist/accordion/item/accordion-item.js +41 -10
- package/dist/accordion/root/accordion-root.d.ts +14 -5
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +24 -3
- package/dist/announcement/root/announcement-root.js +39 -2
- package/dist/app-header/root/app-header-root.d.ts +12 -0
- package/dist/app-header/root/app-header-root.js +13 -1
- package/dist/app-header/sectioning.d.ts +9 -0
- package/dist/app-header/sectioning.js +27 -0
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +57 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +73 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +123 -42
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +133 -4
- package/dist/carousel/root/carousel-root.js +174 -24
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/composer/chat-composer.d.ts +38 -6
- package/dist/chat/composer/chat-composer.js +42 -9
- package/dist/chat/message/chat-message.d.ts +32 -1
- package/dist/chat/message/chat-message.js +27 -10
- package/dist/chat/naming.d.ts +26 -0
- package/dist/chat/naming.js +14 -0
- package/dist/chat/root/chat-root.d.ts +58 -0
- package/dist/chat/root/chat-root.js +43 -3
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +57 -2
- package/dist/code-block/root/code-block-root.js +63 -8
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +26 -1
- package/dist/copy-button/root/copy-button-root.js +12 -5
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +170 -13
- package/dist/data-table/root/data-table-root.js +294 -52
- package/dist/data-table/tree.d.ts +55 -0
- package/dist/data-table/tree.js +54 -0
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/description-list/item/description-list-item.d.ts +17 -2
- package/dist/description-list/item/description-list-item.js +15 -2
- package/dist/description-list/root/description-list-root.d.ts +27 -1
- package/dist/description-list/root/description-list-root.js +26 -1
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.d.ts +11 -6
- package/dist/drilldown/item/drilldown-item.js +8 -5
- package/dist/drilldown/root/drilldown-root.d.ts +29 -0
- package/dist/drilldown/root/drilldown-root.js +28 -5
- package/dist/element-events.generated.js +83 -12
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +5 -0
- package/dist/filter-input/menu/filter-menu.js +16 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +10 -2
- package/dist/input/root/input-root.d.ts +13 -3
- package/dist/input/root/input-root.js +12 -3
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +70 -1
- package/dist/list/item/list-item.js +77 -6
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +155 -9
- package/dist/list/root/list-root.js +246 -4
- package/dist/list/selection.d.ts +49 -0
- package/dist/list/selection.js +30 -0
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -4
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/map/root/map-root.d.ts +6 -2
- package/dist/map/root/map-root.js +5 -2
- package/dist/megamenu/root/megamenu-root.d.ts +62 -0
- package/dist/megamenu/root/megamenu-root.js +90 -5
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +87 -11
- package/dist/menu/item/menu-item.js +78 -22
- package/dist/menu/root/menu-root.d.ts +39 -1
- package/dist/menu/root/menu-root.js +65 -8
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +18 -2
- package/dist/navigation/root/navigation-root.js +29 -3
- package/dist/notifications/root/notifications-root.d.ts +25 -0
- package/dist/notifications/root/notifications-root.js +33 -5
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +161 -32
- package/dist/object-inspector/root/object-inspector-root.js +264 -123
- package/dist/object-inspector/rows.d.ts +75 -0
- package/dist/object-inspector/rows.js +119 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +86 -3
- package/dist/outline/root/outline-root.js +95 -12
- package/dist/pagination/size/pagination-size.d.ts +12 -2
- package/dist/pagination/size/pagination-size.js +20 -5
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/group/radio-group.d.ts +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +10 -5
- package/dist/rating/root/rating-root.js +32 -8
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +84 -0
- package/dist/scroll-area/root/scroll-area-root.js +106 -7
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +92 -0
- package/dist/scroll-area/scrollbar.js +33 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +20 -12
- package/dist/splitter/root/splitter-root.js +226 -203
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +20 -0
- package/dist/steps/reach.js +15 -0
- package/dist/steps/root/steps-root.d.ts +76 -0
- package/dist/steps/root/steps-root.js +93 -1
- package/dist/steps/step/step.d.ts +45 -2
- package/dist/steps/step/step.js +33 -6
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +11 -10
- package/dist/table/column/table-column.js +8 -19
- package/dist/table/root/table-root.d.ts +126 -4
- package/dist/table/root/table-root.js +156 -6
- package/dist/table/row/table-row.d.ts +47 -1
- package/dist/table/row/table-row.js +39 -2
- package/dist/tabs/panel/tab-panel.d.ts +22 -5
- package/dist/tabs/panel/tab-panel.js +34 -6
- package/dist/tabs/root/tabs-root.d.ts +37 -1
- package/dist/tabs/root/tabs-root.js +22 -4
- package/dist/tabs/tab/tab.d.ts +41 -4
- package/dist/tabs/tab/tab.js +49 -3
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.d.ts +46 -0
- package/dist/timeline/group/timeline-group.js +37 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/timeline/root/timeline-root.d.ts +10 -3
- package/dist/toast/item/toast-item.d.ts +24 -18
- package/dist/toast/item/toast-item.js +36 -40
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +61 -4
- package/dist/tree/item/tree-item.js +92 -20
- package/dist/tree/root/tree-root.d.ts +58 -0
- package/dist/tree/root/tree-root.js +80 -16
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +13 -0
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +44 -0
- package/dist/video/media-events.js +35 -0
- package/dist/video/root/video-root.d.ts +117 -18
- package/dist/video/root/video-root.js +93 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
- package/dist/video-playlist/order.d.ts +41 -0
- package/dist/video-playlist/order.js +34 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +77 -3
- package/dist/video-playlist/root/video-playlist-root.js +60 -16
- package/dist/virtual-list/controls.d.ts +4 -0
- package/dist/virtual-list/controls.js +30 -0
- package/dist/virtual-list/fill.d.ts +22 -0
- package/dist/virtual-list/fill.js +23 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +259 -26
- package/dist/virtual-list/root/virtual-list-root.js +333 -49
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +8113 -1394
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +1678 -353
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -24,10 +24,39 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
24
24
|
* polite live region. While the carousel rotates the region is off, so a
|
|
25
25
|
* screen reader is not interrupted every few seconds.
|
|
26
26
|
*
|
|
27
|
-
* The indicators are one tab stop.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* **Keyboard.** The indicators are one tab stop.
|
|
28
|
+
*
|
|
29
|
+
* | Key | What it does |
|
|
30
|
+
* |---|---|
|
|
31
|
+
* | Tab | Moves through the rotation control, Previous, Next, the slides' own links and buttons, and the indicators, in that order. |
|
|
32
|
+
* | Enter, Space | Presses the control or the indicator that has focus. |
|
|
33
|
+
* | Right, Left | On an indicator, moves to the next or the previous slide and its indicator. Left moves on, on a right-to-left page. |
|
|
34
|
+
* | Down, Up | The same, on a vertical carousel. |
|
|
35
|
+
* | Home, End | On an indicator, moves to the first or the last slide. |
|
|
36
|
+
*
|
|
37
|
+
* Without `loop`, Previous on the first slide and Next on the last are marked
|
|
38
|
+
* `aria-disabled`, and keep focus.
|
|
39
|
+
*
|
|
40
|
+
* **What a screen reader hears.** The carousel is a group named by `label`,
|
|
41
|
+
* announced as `role-label` ("carousel"). Each slide is a group announced as
|
|
42
|
+
* `slide-role-label` ("slide") and named by `slide-label` ("2 of 5"). After a
|
|
43
|
+
* move by a control, an indicator, a key, or a drag, the `live` part says the
|
|
44
|
+
* slide's name politely. While the carousel rotates the region is off.
|
|
45
|
+
*
|
|
46
|
+
* **`slides-per-move` moves several slides at a time.** With `per-view="3"`
|
|
47
|
+
* and `slides-per-move="3"`, Next shows the next three, there is one
|
|
48
|
+
* indicator for each stop, and the track snaps only at the stops. The last
|
|
49
|
+
* stop is always the end of the run, so a run that does not divide evenly
|
|
50
|
+
* ends on its last slides. Unset moves one slide.
|
|
51
|
+
*
|
|
52
|
+
* **`mouse-drag` lets a mouse drag the track**, which otherwise only a touch
|
|
53
|
+
* screen, a trackpad, or the scroll wheel moves. The drag follows the pointer
|
|
54
|
+
* with snapping off and settles on the nearest slide when it is let go, and
|
|
55
|
+
* that move is announced and refusable like a press of Next. A link in a slide
|
|
56
|
+
* is not followed at the end of a drag.
|
|
57
|
+
*
|
|
58
|
+
* The glyphs on Previous and Next can be replaced by slotting an icon of your
|
|
59
|
+
* own into `previous-icon` and `next-icon`.
|
|
31
60
|
*
|
|
32
61
|
* @since 0.1.0
|
|
33
62
|
* @status stable
|
|
@@ -36,6 +65,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
36
65
|
* @documentation https://fusion.dev/helix/components/carousel
|
|
37
66
|
*
|
|
38
67
|
* @slot - The slides.
|
|
68
|
+
* @slot next-icon - The glyph on the control that moves to the next slide. Defaults to a caret.
|
|
69
|
+
* @slot previous-icon - The glyph on the control that moves to the previous slide. Defaults to a caret.
|
|
39
70
|
*
|
|
40
71
|
* @event {HelixActivateEvent} helix-activate - Fired after the slide in view changes, with the new index as a string in `detail.value`.
|
|
41
72
|
* @event {HelixSelectEvent} helix-select - Fired before the slide in view changes, with the requested index. Cancelable: cancel it to keep the current slide. Nothing moves, and a drag returns to the slide the index still holds. See `handleScroll`.
|
|
@@ -59,6 +90,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
59
90
|
* @cssproperty --carousel-per-view - How many slides go across. The component writes it onto the track, so your stylesheet divides the track by the same number the component counts positions from. Read this property to follow `per-view`, because attribute selectors cannot cover every possible count. Under `per-view="auto"` the component writes nothing and your stylesheet declares it, so the same name works in both modes. See `perView`.
|
|
60
91
|
* @cssproperty --carousel-run-end - How far short of a whole pixel the run ends, set on the last slide only. Your stylesheet applies it as `margin-inline-end`. See `runEnd`.
|
|
61
92
|
* @cssproperty --carousel-slide-min - The narrowest a slide may be. `per-view="auto"` uses it to fit slides into the track. It must be a length, because the stylesheet divides by it. When unset, it is the whole track, which shows one slide across.
|
|
93
|
+
*
|
|
94
|
+
* @cssstate dragging - While a mouse drags the track, under `mouse-drag`.
|
|
62
95
|
*/
|
|
63
96
|
export declare class HelixHeadlessCarousel extends HelixElement {
|
|
64
97
|
/**
|
|
@@ -154,6 +187,14 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
154
187
|
* Whether moving past either end wraps to the other.
|
|
155
188
|
*/
|
|
156
189
|
loop: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Whether a mouse can drag the track from slide to slide.
|
|
192
|
+
*
|
|
193
|
+
* Off unless asked for, because a press on a slide is then the start of a
|
|
194
|
+
* drag, and text in a slide can no longer be selected with the mouse. A drag
|
|
195
|
+
* of a few pixels or less is still a press.
|
|
196
|
+
*/
|
|
197
|
+
mouseDrag: boolean;
|
|
157
198
|
/**
|
|
158
199
|
* The name of the control that moves to the next slide.
|
|
159
200
|
*/
|
|
@@ -246,6 +287,12 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
246
287
|
* The name of the control that moves to the previous slide.
|
|
247
288
|
*/
|
|
248
289
|
previousLabel: string;
|
|
290
|
+
/**
|
|
291
|
+
* The word screen readers announce in place of the carousel's role, set as
|
|
292
|
+
* `aria-roledescription`. Translate it with the rest of your text, or empty
|
|
293
|
+
* it to leave the role as `group`.
|
|
294
|
+
*/
|
|
295
|
+
roleLabel: string;
|
|
249
296
|
/**
|
|
250
297
|
* The name of each slide, with `{index}` and `{count}` filled in.
|
|
251
298
|
*/
|
|
@@ -255,6 +302,12 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
255
302
|
* `aria-roledescription`. Translate it with the rest of your text.
|
|
256
303
|
*/
|
|
257
304
|
slideRoleLabel: string;
|
|
305
|
+
/**
|
|
306
|
+
* How many slides Previous, Next, the indicators, rotation, and a drag move
|
|
307
|
+
* at a time. Unset moves one. The track stops at every `slides-per-move`th
|
|
308
|
+
* position from the first, and at the last.
|
|
309
|
+
*/
|
|
310
|
+
slidesPerMove?: number;
|
|
258
311
|
/**
|
|
259
312
|
* The name of the rotation control while rotation is stopped.
|
|
260
313
|
*/
|
|
@@ -323,6 +376,8 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
323
376
|
* withheld rather than counted from it. See `across`.
|
|
324
377
|
*/
|
|
325
378
|
get positions(): number;
|
|
379
|
+
/** The positions the track stops at, `slides-per-move` apart, and the last. See `stopsOf`. */
|
|
380
|
+
private get stops();
|
|
326
381
|
/**
|
|
327
382
|
* How many slides the box turned out to hold, from the pane it laid out.
|
|
328
383
|
*
|
|
@@ -386,6 +441,25 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
386
441
|
* in exactly as the inline one did.
|
|
387
442
|
*/
|
|
388
443
|
private handed;
|
|
444
|
+
/**
|
|
445
|
+
* The track's inline style: the count above, and snapping off while a mouse
|
|
446
|
+
* drags it.
|
|
447
|
+
*
|
|
448
|
+
* **Inline, because the drag does not work without it.** A track that snaps
|
|
449
|
+
* puts every scroll the drag asks for back on the nearest slide, so the
|
|
450
|
+
* slides jump from one to the next under the pointer. A stylesheet cannot be
|
|
451
|
+
* relied on to turn snapping off, since the headless tier has none, so the
|
|
452
|
+
* component says it for the length of the drag and no longer.
|
|
453
|
+
*
|
|
454
|
+
* **And `!important`, because a document rule beats a shadow root's inline
|
|
455
|
+
* style.** The style attribute is in the shadow tree's context, and a
|
|
456
|
+
* consumer's `::part(track)` rule is in the document's, which wins every
|
|
457
|
+
* normal declaration. Measured in Chromium on a headless track snapping from
|
|
458
|
+
* the document: the inline `none` was there and the computed value stayed
|
|
459
|
+
* `x mandatory`, and the drag never moved the track. An important
|
|
460
|
+
* declaration sorts the other way, the inner context first.
|
|
461
|
+
*/
|
|
462
|
+
private trackStyle;
|
|
389
463
|
/** What the box resolved to, and `undefined` until it has been laid out. */
|
|
390
464
|
private fitted;
|
|
391
465
|
/** Watches the pane a fitted track laid out, while `auto` is what was asked. */
|
|
@@ -425,6 +499,8 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
425
499
|
private get panes();
|
|
426
500
|
/** The slides, in light-DOM order. Empty on the server, which has no tree. */
|
|
427
501
|
get slides(): HTMLElement[];
|
|
502
|
+
/** What a consumer slotted into one of the arrows' glyph slots. */
|
|
503
|
+
private iconsFor;
|
|
428
504
|
/**
|
|
429
505
|
* The arrows move between indicators, which is the tablist pattern.
|
|
430
506
|
*
|
|
@@ -446,6 +522,11 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
446
522
|
* sends neither, being a correction rather than a move anybody asked for.
|
|
447
523
|
*/
|
|
448
524
|
private applyIndex;
|
|
525
|
+
/**
|
|
526
|
+
* The position one stop forward or back lands on, wrapping where `loop`
|
|
527
|
+
* says so.
|
|
528
|
+
*/
|
|
529
|
+
private move;
|
|
449
530
|
/** Moves to a slide. It wraps past either end only when `loop` is set. */
|
|
450
531
|
goTo(index: number): void;
|
|
451
532
|
/**
|
|
@@ -509,6 +590,38 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
509
590
|
*/
|
|
510
591
|
private settling;
|
|
511
592
|
private readonly handleTake;
|
|
593
|
+
/** Whether a mouse is dragging the track. */
|
|
594
|
+
private dragging;
|
|
595
|
+
/** A mouse pressed on the track under `mouse-drag`, from where it pressed. */
|
|
596
|
+
private pull;
|
|
597
|
+
/** Takes the press, and under `mouse-drag` the start of a drag. */
|
|
598
|
+
private readonly handlePress;
|
|
599
|
+
/**
|
|
600
|
+
* Moves the track with the pointer.
|
|
601
|
+
*
|
|
602
|
+
* Not until the pointer has moved a few pixels, so a press on a link or a
|
|
603
|
+
* button in a slide stays a press. Instant scrolls, since a smooth one would
|
|
604
|
+
* trail the pointer.
|
|
605
|
+
*/
|
|
606
|
+
private readonly handlePull;
|
|
607
|
+
/**
|
|
608
|
+
* Lets go of the track, and settles on the slide nearest to where it was let
|
|
609
|
+
* go.
|
|
610
|
+
*
|
|
611
|
+
* Through the same request as a press of Next, so the move is refusable,
|
|
612
|
+
* sends `helix-activate`, and is announced. A refusal, or a drag that ends on
|
|
613
|
+
* the slide it began on, goes back to that slide once snapping is on again.
|
|
614
|
+
*/
|
|
615
|
+
private readonly handleLetGo;
|
|
616
|
+
/**
|
|
617
|
+
* Keeps the click that ends a drag from following a link in the slide.
|
|
618
|
+
*
|
|
619
|
+
* Once, in capture on the track, and given up a moment later where no click
|
|
620
|
+
* comes, which is a drag let go off the track.
|
|
621
|
+
*/
|
|
622
|
+
private swallowClick;
|
|
623
|
+
/** Keeps a mouse drag from picking up a link or an image under `mouse-drag`. */
|
|
624
|
+
private readonly handleDragStart;
|
|
512
625
|
/**
|
|
513
626
|
* Stops rotation for good.
|
|
514
627
|
*
|
|
@@ -705,6 +818,22 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
705
818
|
* server, which knows no slides and so no ends.
|
|
706
819
|
*/
|
|
707
820
|
private atEnd;
|
|
821
|
+
/**
|
|
822
|
+
* The glyph on Previous: the `previous-icon` slot, holding a caret until
|
|
823
|
+
* something is slotted. A tier above overrides this to draw its own caret.
|
|
824
|
+
*/
|
|
825
|
+
protected renderPreviousMark(): TemplateResult;
|
|
826
|
+
/**
|
|
827
|
+
* The glyph on Next: the `next-icon` slot, holding a caret until something
|
|
828
|
+
* is slotted. A tier above overrides this to draw its own caret.
|
|
829
|
+
*/
|
|
830
|
+
protected renderNextMark(): TemplateResult;
|
|
831
|
+
/**
|
|
832
|
+
* A pane's own declarations: the last pane's `runEnd`, and no snap point on
|
|
833
|
+
* a pane the track does not stop at under `slides-per-move`, so a swipe
|
|
834
|
+
* settles on a stop as the controls do.
|
|
835
|
+
*/
|
|
836
|
+
private paneStyle;
|
|
708
837
|
protected render(): TemplateResult;
|
|
709
838
|
}
|
|
710
839
|
declare global {
|
|
@@ -4,11 +4,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, fillTemplate, HelixActivateEvent, HelixElement, HelixSelectEvent, hostAria, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { capturePointer, customElement, fillTemplate, HelixActivateEvent, HelixElement, HelixSelectEvent, hostAria, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretLeft, caretRight, play, stop } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
import { stepStop, stopFor, stopsOf } from '../stops.js';
|
|
12
13
|
const COUNT_OR_AUTO = {
|
|
13
14
|
fromAttribute: (value) => {
|
|
14
15
|
if (value === null) {
|
|
@@ -18,6 +19,8 @@ const COUNT_OR_AUTO = {
|
|
|
18
19
|
},
|
|
19
20
|
toAttribute: (value) => value === undefined ? null : String(value),
|
|
20
21
|
};
|
|
22
|
+
const ICON_SLOTS = ['previous-icon', 'next-icon'];
|
|
23
|
+
const DRAG_SLOP = 4;
|
|
21
24
|
let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
22
25
|
constructor() {
|
|
23
26
|
super(...arguments);
|
|
@@ -31,9 +34,11 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
31
34
|
this.said = '';
|
|
32
35
|
this.label = 'Carousel';
|
|
33
36
|
this.loop = false;
|
|
37
|
+
this.mouseDrag = false;
|
|
34
38
|
this.nextLabel = 'Next slide';
|
|
35
39
|
this.rotating = false;
|
|
36
40
|
this.previousLabel = 'Previous slide';
|
|
41
|
+
this.roleLabel = 'carousel';
|
|
37
42
|
this.slideLabel = '{index} of {count}';
|
|
38
43
|
this.slideRoleLabel = 'slide';
|
|
39
44
|
this.startLabel = 'Start slide rotation';
|
|
@@ -55,7 +60,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
55
60
|
? -1
|
|
56
61
|
: 0
|
|
57
62
|
: inlineStep(this, event.key);
|
|
58
|
-
let to
|
|
63
|
+
let to;
|
|
59
64
|
if (event.key === 'Home') {
|
|
60
65
|
to = 0;
|
|
61
66
|
}
|
|
@@ -65,6 +70,9 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
65
70
|
else if (step === 0) {
|
|
66
71
|
return;
|
|
67
72
|
}
|
|
73
|
+
else {
|
|
74
|
+
to = this.move(step);
|
|
75
|
+
}
|
|
68
76
|
event.preventDefault();
|
|
69
77
|
this.goTo(to);
|
|
70
78
|
this.updateComplete.then(() => {
|
|
@@ -75,6 +83,68 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
75
83
|
this.handleTake = () => {
|
|
76
84
|
this.settling = false;
|
|
77
85
|
};
|
|
86
|
+
this.dragging = false;
|
|
87
|
+
this.handlePress = (event) => {
|
|
88
|
+
this.handleTake();
|
|
89
|
+
const track = this.partNamed('track');
|
|
90
|
+
if (!this.mouseDrag || event.pointerType !== 'mouse' || event.button !== 0 || !track) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.pull = { left: track.scrollLeft, top: track.scrollTop, x: event.clientX, y: event.clientY };
|
|
94
|
+
};
|
|
95
|
+
this.handlePull = (event) => {
|
|
96
|
+
const pull = this.pull;
|
|
97
|
+
const track = this.partNamed('track');
|
|
98
|
+
if (!pull || !track) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if ((event.buttons & 1) === 0) {
|
|
102
|
+
this.pull = undefined;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const across = event.clientX - pull.x;
|
|
106
|
+
const down = event.clientY - pull.y;
|
|
107
|
+
if (!this.dragging) {
|
|
108
|
+
if (Math.hypot(across, down) < DRAG_SLOP) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.dragging = true;
|
|
112
|
+
track.style.setProperty('scroll-snap-type', 'none', 'important');
|
|
113
|
+
capturePointer(track, event.pointerId);
|
|
114
|
+
}
|
|
115
|
+
track.scrollTo(this.orientation === 'vertical'
|
|
116
|
+
? { behavior: 'instant', top: pull.top - down }
|
|
117
|
+
: { behavior: 'instant', left: pull.left - across });
|
|
118
|
+
};
|
|
119
|
+
this.handleLetGo = () => {
|
|
120
|
+
if (!this.pull) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.pull = undefined;
|
|
124
|
+
if (!this.dragging) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
this.swallowClick();
|
|
128
|
+
const nearest = this.nearest();
|
|
129
|
+
this.dragging = false;
|
|
130
|
+
this.showing = undefined;
|
|
131
|
+
const moved = nearest !== undefined &&
|
|
132
|
+
nearest !== this.index &&
|
|
133
|
+
requestChange({
|
|
134
|
+
apply: (value) => this.applyIndex(value),
|
|
135
|
+
event: (value) => new HelixSelectEvent({ value: String(value) }),
|
|
136
|
+
host: this,
|
|
137
|
+
next: nearest,
|
|
138
|
+
});
|
|
139
|
+
if (!moved) {
|
|
140
|
+
this.updateComplete.then(() => this.scrollToIndex());
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
this.handleDragStart = (event) => {
|
|
144
|
+
if (this.mouseDrag) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
78
148
|
this.handleTrackScroll = () => {
|
|
79
149
|
if (this.settling || this.scrollFrame) {
|
|
80
150
|
return;
|
|
@@ -92,6 +162,9 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
92
162
|
this.settling = false;
|
|
93
163
|
return;
|
|
94
164
|
}
|
|
165
|
+
if (this.dragging) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
95
168
|
this.showing = undefined;
|
|
96
169
|
const nearest = this.nearest();
|
|
97
170
|
if (nearest === undefined) {
|
|
@@ -144,6 +217,9 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
144
217
|
get positions() {
|
|
145
218
|
return Math.max(1, this.slides.length - (this.across ?? 1) + 1);
|
|
146
219
|
}
|
|
220
|
+
get stops() {
|
|
221
|
+
return stopsOf(this.positions, this.slidesPerMove);
|
|
222
|
+
}
|
|
147
223
|
measure() {
|
|
148
224
|
const track = this.partNamed('track');
|
|
149
225
|
const pane = this.panes[0]?.getBoundingClientRect().width;
|
|
@@ -169,6 +245,14 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
169
245
|
handed() {
|
|
170
246
|
return this.fits ? nothing : `--carousel-per-view: ${this.clamped}`;
|
|
171
247
|
}
|
|
248
|
+
trackStyle() {
|
|
249
|
+
const handed = this.handed();
|
|
250
|
+
if (!this.dragging) {
|
|
251
|
+
return handed;
|
|
252
|
+
}
|
|
253
|
+
const off = 'scroll-snap-type: none !important';
|
|
254
|
+
return handed === nothing ? off : `${handed}; ${off}`;
|
|
255
|
+
}
|
|
172
256
|
watchPane() {
|
|
173
257
|
if (!this.fits || typeof ResizeObserver === 'undefined') {
|
|
174
258
|
this.sizes?.disconnect();
|
|
@@ -193,7 +277,10 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
193
277
|
return [...(this.renderRoot?.querySelectorAll?.('[part="slide"]') ?? [])];
|
|
194
278
|
}
|
|
195
279
|
get slides() {
|
|
196
|
-
return this.knownChildren.filter((child) => child instanceof HTMLElement);
|
|
280
|
+
return this.knownChildren.filter((child) => child instanceof HTMLElement && !ICON_SLOTS.includes(child.slot));
|
|
281
|
+
}
|
|
282
|
+
iconsFor(name) {
|
|
283
|
+
return this.knownChildren.filter((child) => child.slot === name);
|
|
197
284
|
}
|
|
198
285
|
applyIndex(value) {
|
|
199
286
|
const previous = this.index;
|
|
@@ -201,6 +288,9 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
201
288
|
this.requestUpdate('index', previous);
|
|
202
289
|
this.dispatchEvent(new HelixActivateEvent({ value: String(value) }));
|
|
203
290
|
}
|
|
291
|
+
move(step) {
|
|
292
|
+
return stepStop(this.stops, this.index, step < 0 ? -1 : 1, this.loop);
|
|
293
|
+
}
|
|
204
294
|
goTo(index) {
|
|
205
295
|
if (this.slides.length === 0) {
|
|
206
296
|
return;
|
|
@@ -251,6 +341,18 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
251
341
|
this.settling = true;
|
|
252
342
|
track.scrollTo({ behavior: still ? 'instant' : 'smooth', ...at });
|
|
253
343
|
}
|
|
344
|
+
swallowClick() {
|
|
345
|
+
const track = this.partNamed('track');
|
|
346
|
+
if (!track) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const swallow = (event) => {
|
|
350
|
+
event.preventDefault();
|
|
351
|
+
event.stopPropagation();
|
|
352
|
+
};
|
|
353
|
+
track.addEventListener('click', swallow, { capture: true, once: true });
|
|
354
|
+
setTimeout(() => track.removeEventListener('click', swallow, { capture: true }));
|
|
355
|
+
}
|
|
254
356
|
stop() {
|
|
255
357
|
this.stopped = true;
|
|
256
358
|
this.rotating = false;
|
|
@@ -265,7 +367,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
265
367
|
if (!this.rotating || this.slides.length < 2) {
|
|
266
368
|
return;
|
|
267
369
|
}
|
|
268
|
-
this.timer = setInterval(() => this.goTo(this.index >= this.positions - 1 ? 0 : this.
|
|
370
|
+
this.timer = setInterval(() => this.goTo(this.index >= this.positions - 1 ? 0 : this.move(1)), this.interval);
|
|
269
371
|
}
|
|
270
372
|
nearest() {
|
|
271
373
|
const track = this.partNamed('track');
|
|
@@ -274,8 +376,11 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
274
376
|
}
|
|
275
377
|
const bleed = this.bleed(track);
|
|
276
378
|
const at = this.orientation === 'vertical' ? track.scrollTop : track.scrollLeft;
|
|
277
|
-
return this.
|
|
278
|
-
const
|
|
379
|
+
return this.stops.reduce((best, index) => {
|
|
380
|
+
const slide = this.panes[index];
|
|
381
|
+
const distance = slide
|
|
382
|
+
? Math.abs(this.edgeOf(slide, track, bleed) - at)
|
|
383
|
+
: Number.POSITIVE_INFINITY;
|
|
279
384
|
return distance < best.distance ? { distance, index } : best;
|
|
280
385
|
}, { distance: Number.POSITIVE_INFINITY, index: this.index }).index;
|
|
281
386
|
}
|
|
@@ -324,7 +429,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
324
429
|
this.fitted = undefined;
|
|
325
430
|
}
|
|
326
431
|
hostAria(this.internals, { label: this.label, role: 'group' });
|
|
327
|
-
this.internals.ariaRoleDescription =
|
|
432
|
+
this.internals.ariaRoleDescription = this.roleLabel || null;
|
|
328
433
|
}
|
|
329
434
|
firstUpdated(changed) {
|
|
330
435
|
super.firstUpdated(changed);
|
|
@@ -342,6 +447,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
342
447
|
this.holdIndex();
|
|
343
448
|
this.watchPane();
|
|
344
449
|
this.assign();
|
|
450
|
+
this.toggleState('dragging', this.dragging);
|
|
345
451
|
}
|
|
346
452
|
assign() {
|
|
347
453
|
if (this.assignsByName) {
|
|
@@ -350,6 +456,11 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
350
456
|
});
|
|
351
457
|
return;
|
|
352
458
|
}
|
|
459
|
+
for (const name of ICON_SLOTS) {
|
|
460
|
+
this.renderRoot
|
|
461
|
+
?.querySelector?.(`slot[name="${name}"]`)
|
|
462
|
+
?.assign?.(...this.iconsFor(name));
|
|
463
|
+
}
|
|
353
464
|
const panes = this.renderRoot?.querySelectorAll?.('[part="slide"] slot');
|
|
354
465
|
if (!panes) {
|
|
355
466
|
return;
|
|
@@ -372,9 +483,35 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
372
483
|
}
|
|
373
484
|
return side === 'start' ? this.index <= 0 : this.index >= this.positions - 1;
|
|
374
485
|
}
|
|
486
|
+
renderPreviousMark() {
|
|
487
|
+
return html `<slot name="previous-icon"
|
|
488
|
+
><svg part="previous-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
489
|
+
${unsafeSVG(caretLeft.content)}
|
|
490
|
+
</svg></slot
|
|
491
|
+
>`;
|
|
492
|
+
}
|
|
493
|
+
renderNextMark() {
|
|
494
|
+
return html `<slot name="next-icon"
|
|
495
|
+
><svg part="next-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
496
|
+
${unsafeSVG(caretRight.content)}
|
|
497
|
+
</svg></slot
|
|
498
|
+
>`;
|
|
499
|
+
}
|
|
500
|
+
paneStyle(index, last, stops) {
|
|
501
|
+
const declared = [
|
|
502
|
+
index === last ? this.runEnd() : nothing,
|
|
503
|
+
(this.slidesPerMove ?? 1) > 1 && !stops.includes(index)
|
|
504
|
+
? 'scroll-snap-align: none !important'
|
|
505
|
+
: nothing,
|
|
506
|
+
].filter((one) => one !== nothing);
|
|
507
|
+
return declared.length > 0 ? declared.join('; ') : nothing;
|
|
508
|
+
}
|
|
375
509
|
render() {
|
|
376
510
|
const rotating = this.rotating;
|
|
377
511
|
const last = this.slides.length - 1;
|
|
512
|
+
const stops = this.stops;
|
|
513
|
+
const place = stopFor(stops, this.index);
|
|
514
|
+
const showing = stopFor(stops, this.showing ?? this.index);
|
|
378
515
|
return html `<div part="controls">
|
|
379
516
|
${this.autoplay
|
|
380
517
|
? html `<button
|
|
@@ -399,40 +536,41 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
399
536
|
type="button"
|
|
400
537
|
aria-label=${this.previousLabel}
|
|
401
538
|
aria-disabled=${this.atEnd('start') ? 'true' : nothing}
|
|
402
|
-
@click=${() => this.goTo(this.
|
|
539
|
+
@click=${() => this.goTo(this.move(-1))}
|
|
403
540
|
>
|
|
404
|
-
|
|
405
|
-
${unsafeSVG(caretLeft.content)}
|
|
406
|
-
</svg>
|
|
541
|
+
${this.renderPreviousMark()}
|
|
407
542
|
</button>
|
|
408
543
|
<button
|
|
409
544
|
part="next"
|
|
410
545
|
type="button"
|
|
411
546
|
aria-label=${this.nextLabel}
|
|
412
547
|
aria-disabled=${this.atEnd('end') ? 'true' : nothing}
|
|
413
|
-
@click=${() => this.goTo(this.
|
|
548
|
+
@click=${() => this.goTo(this.move(1))}
|
|
414
549
|
>
|
|
415
|
-
|
|
416
|
-
${unsafeSVG(caretRight.content)}
|
|
417
|
-
</svg>
|
|
550
|
+
${this.renderNextMark()}
|
|
418
551
|
</button>`}
|
|
419
552
|
</div>
|
|
420
553
|
<div
|
|
421
554
|
data-scroller
|
|
422
555
|
part="track"
|
|
423
|
-
style=${this.
|
|
556
|
+
style=${this.trackStyle()}
|
|
424
557
|
@scroll=${this.handleTrackScroll}
|
|
425
558
|
@scrollend=${this.handleScroll}
|
|
426
|
-
@pointerdown=${this.
|
|
559
|
+
@pointerdown=${this.handlePress}
|
|
560
|
+
@pointermove=${this.handlePull}
|
|
561
|
+
@pointerup=${this.handleLetGo}
|
|
562
|
+
@pointercancel=${this.handleLetGo}
|
|
563
|
+
@lostpointercapture=${this.handleLetGo}
|
|
564
|
+
@dragstart=${this.handleDragStart}
|
|
427
565
|
@touchstart=${this.handleTake}
|
|
428
566
|
@wheel=${this.handleTake}
|
|
429
567
|
>
|
|
430
568
|
${this.slides.map((_, index) => html `<div
|
|
431
569
|
part="slide"
|
|
432
570
|
role="group"
|
|
433
|
-
aria-roledescription=${this.slideRoleLabel}
|
|
571
|
+
aria-roledescription=${this.slideRoleLabel || nothing}
|
|
434
572
|
aria-label=${fillTemplate(this.slideLabel, { count: this.slides.length, index: index + 1 })}
|
|
435
|
-
style=${index
|
|
573
|
+
style=${this.paneStyle(index, last, stops)}
|
|
436
574
|
>
|
|
437
575
|
<slot
|
|
438
576
|
name=${this.assignsByName ? `slide-${index + 1}` : nothing}
|
|
@@ -444,17 +582,17 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
444
582
|
${this.slides.length > 1 && this.across !== undefined
|
|
445
583
|
? html `<div part="indicators" role="group" aria-label=${fillTemplate(this.indicatorsLabel, { label: this.label })}>
|
|
446
584
|
${''}
|
|
447
|
-
${
|
|
448
|
-
const current = at ===
|
|
585
|
+
${stops.map((stop, at) => {
|
|
586
|
+
const current = at === showing;
|
|
449
587
|
return html `<button
|
|
450
588
|
part="indicator${current ? ' indicator-current' : ''}"
|
|
451
589
|
type="button"
|
|
452
590
|
aria-label=${fillTemplate(this.indicatorLabel, { index: at + 1 })}
|
|
453
|
-
aria-current=${at ===
|
|
454
|
-
tabindex=${at ===
|
|
591
|
+
aria-current=${at === place ? 'true' : nothing}
|
|
592
|
+
tabindex=${at === place ? '0' : '-1'}
|
|
455
593
|
?data-current=${current}
|
|
456
594
|
@keydown=${this.handleIndicatorKeydown}
|
|
457
|
-
@click=${() => this.goTo(
|
|
595
|
+
@click=${() => this.goTo(stop)}
|
|
458
596
|
></button>`;
|
|
459
597
|
})}
|
|
460
598
|
</div>`
|
|
@@ -488,6 +626,9 @@ __decorate([
|
|
|
488
626
|
__decorate([
|
|
489
627
|
property({ type: Boolean })
|
|
490
628
|
], HelixHeadlessCarousel.prototype, "loop", void 0);
|
|
629
|
+
__decorate([
|
|
630
|
+
property({ attribute: 'mouse-drag', reflect: true, type: Boolean })
|
|
631
|
+
], HelixHeadlessCarousel.prototype, "mouseDrag", void 0);
|
|
491
632
|
__decorate([
|
|
492
633
|
property({ attribute: 'next-label' })
|
|
493
634
|
], HelixHeadlessCarousel.prototype, "nextLabel", void 0);
|
|
@@ -503,12 +644,18 @@ __decorate([
|
|
|
503
644
|
__decorate([
|
|
504
645
|
property({ attribute: 'previous-label' })
|
|
505
646
|
], HelixHeadlessCarousel.prototype, "previousLabel", void 0);
|
|
647
|
+
__decorate([
|
|
648
|
+
property({ attribute: 'role-label' })
|
|
649
|
+
], HelixHeadlessCarousel.prototype, "roleLabel", void 0);
|
|
506
650
|
__decorate([
|
|
507
651
|
property({ attribute: 'slide-label' })
|
|
508
652
|
], HelixHeadlessCarousel.prototype, "slideLabel", void 0);
|
|
509
653
|
__decorate([
|
|
510
654
|
property({ attribute: 'slide-role-label' })
|
|
511
655
|
], HelixHeadlessCarousel.prototype, "slideRoleLabel", void 0);
|
|
656
|
+
__decorate([
|
|
657
|
+
property({ attribute: 'slides-per-move', type: Number })
|
|
658
|
+
], HelixHeadlessCarousel.prototype, "slidesPerMove", void 0);
|
|
512
659
|
__decorate([
|
|
513
660
|
property({ attribute: 'start-label' })
|
|
514
661
|
], HelixHeadlessCarousel.prototype, "startLabel", void 0);
|
|
@@ -518,6 +665,9 @@ __decorate([
|
|
|
518
665
|
__decorate([
|
|
519
666
|
state()
|
|
520
667
|
], HelixHeadlessCarousel.prototype, "fitted", void 0);
|
|
668
|
+
__decorate([
|
|
669
|
+
state()
|
|
670
|
+
], HelixHeadlessCarousel.prototype, "dragging", void 0);
|
|
521
671
|
__decorate([
|
|
522
672
|
state()
|
|
523
673
|
], HelixHeadlessCarousel.prototype, "showing", void 0);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a carousel's track stops when it moves several slides at a time, as
|
|
3
|
+
* arithmetic over its positions.
|
|
4
|
+
*
|
|
5
|
+
* A position is a slide the track can start at: six slides four across have
|
|
6
|
+
* three, 0, 1 and 2. Moving `perMove` slides at a time stops at every
|
|
7
|
+
* `perMove`th of them from the first, and always at the last, so the end of
|
|
8
|
+
* the run is reachable whatever the count.
|
|
9
|
+
*/
|
|
10
|
+
/** The positions the track stops at, in order: every `perMove`th from 0, and the last. */
|
|
11
|
+
export declare const stopsOf: (positions: number, perMove?: number) => number[];
|
|
12
|
+
/** Which stop a position is at or past: the last stop at or before it, as an index into `stops`. */
|
|
13
|
+
export declare const stopFor: (stops: readonly number[], position: number) => number;
|
|
14
|
+
/**
|
|
15
|
+
* The position a move of one stop forward (`1`) or back (`-1`) lands on.
|
|
16
|
+
*
|
|
17
|
+
* From a position between two stops, back goes to the stop before it. Past
|
|
18
|
+
* either end it wraps where `loop` says so, and stays at the end otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export declare const stepStop: (stops: readonly number[], position: number, step: -1 | 1, loop: boolean) => number;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const stopsOf = (positions, perMove = 1) => {
|
|
2
|
+
const step = Number.isFinite(perMove) ? Math.max(1, Math.floor(perMove)) : 1;
|
|
3
|
+
const last = Math.max(0, positions - 1);
|
|
4
|
+
const stops = [];
|
|
5
|
+
for (let at = 0; at < last; at += step) {
|
|
6
|
+
stops.push(at);
|
|
7
|
+
}
|
|
8
|
+
stops.push(last);
|
|
9
|
+
return stops;
|
|
10
|
+
};
|
|
11
|
+
export const stopFor = (stops, position) => {
|
|
12
|
+
let found = 0;
|
|
13
|
+
stops.forEach((stop, at) => {
|
|
14
|
+
if (stop <= position) {
|
|
15
|
+
found = at;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return found;
|
|
19
|
+
};
|
|
20
|
+
export const stepStop = (stops, position, step, loop) => {
|
|
21
|
+
const at = stopFor(stops, position);
|
|
22
|
+
let next = step < 0 && stops[at] !== position ? at : at + step;
|
|
23
|
+
if (loop) {
|
|
24
|
+
next = (next + stops.length) % stops.length;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
next = Math.min(Math.max(next, 0), stops.length - 1);
|
|
28
|
+
}
|
|
29
|
+
return stops[next] ?? 0;
|
|
30
|
+
};
|