@fusion.dev/helix-headless 0.142.1 → 0.144.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 +25381 -1202
- package/dist/accordion/item/accordion-item.d.ts +38 -2
- package/dist/accordion/item/accordion-item.js +38 -6
- package/dist/accordion/root/accordion-root.d.ts +23 -1
- package/dist/accordion/root/accordion-root.js +39 -3
- package/dist/announcement/root/announcement-root.d.ts +11 -7
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/app-header/root/app-header-root.d.ts +21 -0
- package/dist/app-header/root/app-header-root.js +31 -5
- package/dist/area-chart/root/area-chart-root.d.ts +12 -4
- package/dist/area-chart/root/area-chart-root.js +39 -11
- package/dist/avatar/group/avatar-group.d.ts +24 -3
- package/dist/avatar/group/avatar-group.js +34 -2
- package/dist/avatar/root/avatar-root.d.ts +17 -1
- package/dist/avatar/root/avatar-root.js +31 -10
- package/dist/badge/root/badge-root.d.ts +12 -0
- package/dist/badge/root/badge-root.js +1 -1
- package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
- package/dist/bar-chart/root/bar-chart-root.js +58 -21
- package/dist/blockquote/root/blockquote-root.d.ts +12 -7
- package/dist/blockquote/root/blockquote-root.js +6 -4
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
- package/dist/button/root/button-root.d.ts +84 -1
- package/dist/button/root/button-root.js +81 -3
- package/dist/callout/root/callout-root.d.ts +32 -6
- package/dist/callout/root/callout-root.js +26 -7
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- package/dist/card/root/card-root.d.ts +30 -1
- package/dist/card/root/card-root.js +38 -5
- package/dist/carousel/root/carousel-root.d.ts +47 -5
- package/dist/carousel/root/carousel-root.js +53 -21
- package/dist/chat/composer/chat-composer.d.ts +13 -11
- package/dist/chat/composer/chat-composer.js +6 -12
- package/dist/chat/message/chat-message.js +8 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +2 -1
- package/dist/checkbox/root/checkbox-root.d.ts +7 -0
- package/dist/checkbox/root/checkbox-root.js +9 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
- package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/lines.d.ts +13 -0
- package/dist/code-block/lines.js +2 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -0
- package/dist/code-block/root/code-block-root.js +44 -3
- package/dist/color-input/root/color-input-root.d.ts +60 -2
- package/dist/color-input/root/color-input-root.js +55 -7
- package/dist/color-picker/channels.d.ts +26 -0
- package/dist/color-picker/channels.js +84 -0
- package/dist/color-picker/root/color-picker-root.d.ts +118 -12
- package/dist/color-picker/root/color-picker-root.js +183 -13
- package/dist/combobox/root/combobox-root.d.ts +126 -3
- package/dist/combobox/root/combobox-root.js +224 -21
- package/dist/command/root/command-root.d.ts +47 -10
- package/dist/command/root/command-root.js +45 -4
- package/dist/copy-button/from.d.ts +22 -0
- package/dist/copy-button/from.js +28 -0
- package/dist/copy-button/root/copy-button-root.d.ts +48 -7
- package/dist/copy-button/root/copy-button-root.js +54 -8
- package/dist/data-table/root/data-table-root.d.ts +164 -10
- package/dist/data-table/root/data-table-root.js +488 -57
- package/dist/date-input/root/date-input-root.d.ts +123 -9
- package/dist/date-input/root/date-input-root.js +147 -45
- package/dist/date-picker/root/date-picker-root.d.ts +229 -18
- package/dist/date-picker/root/date-picker-root.js +342 -46
- package/dist/dialog/description.d.ts +9 -0
- package/dist/dialog/description.js +14 -0
- package/dist/dialog/root/dialog-root.d.ts +101 -10
- package/dist/dialog/root/dialog-root.js +83 -4
- package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
- package/dist/donut-chart/root/donut-chart-root.js +48 -13
- package/dist/drawer/root/drawer-root.d.ts +93 -7
- package/dist/drawer/root/drawer-root.js +126 -5
- package/dist/drawer/swipe-start.d.ts +9 -0
- package/dist/drawer/swipe-start.js +12 -0
- package/dist/drilldown/item/drilldown-item.d.ts +16 -13
- package/dist/drilldown/item/drilldown-item.js +6 -2
- package/dist/drilldown/root/drilldown-root.d.ts +21 -5
- package/dist/drilldown/root/drilldown-root.js +26 -10
- package/dist/element-events.generated.js +42 -13
- package/dist/empty/root/empty-root.d.ts +1 -1
- package/dist/file-input/root/file-input-root.d.ts +65 -1
- package/dist/file-input/root/file-input-root.js +76 -12
- package/dist/file-input/screen.d.ts +35 -0
- package/dist/file-input/screen.js +49 -0
- package/dist/filter-input/menu/filter-menu.d.ts +9 -0
- package/dist/filter-input/menu/filter-menu.js +8 -0
- package/dist/filter-input/root/filter-input-root.d.ts +43 -6
- package/dist/filter-input/root/filter-input-root.js +89 -10
- package/dist/filter-input/suggest.d.ts +17 -0
- package/dist/filter-input/suggest.js +23 -0
- package/dist/format-date/options.d.ts +33 -0
- package/dist/format-date/options.js +42 -0
- package/dist/format-date/root/format-date-root.d.ts +62 -3
- package/dist/format-date/root/format-date-root.js +78 -37
- package/dist/graph/root/graph-root.d.ts +24 -3
- package/dist/graph/root/graph-root.js +66 -12
- package/dist/heatmap/root/buckets.d.ts +2 -1
- package/dist/heatmap/root/buckets.js +5 -1
- package/dist/heatmap/root/heatmap-root.d.ts +47 -9
- package/dist/heatmap/root/heatmap-root.js +46 -18
- package/dist/icon/index.d.ts +2 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/registry.d.ts +37 -0
- package/dist/icon/registry.js +83 -0
- package/dist/icon/root/icon-root.d.ts +53 -6
- package/dist/icon/root/icon-root.js +72 -4
- package/dist/icon/root/index.d.ts +2 -0
- package/dist/icon/root/index.js +2 -0
- package/dist/icon/set.d.ts +1 -0
- package/dist/icon/set.js +3 -0
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +23 -2
- package/dist/image/root/image-root.js +23 -4
- package/dist/input/root/input-root.d.ts +62 -9
- package/dist/input/root/input-root.js +61 -5
- package/dist/kbd/root/kbd-root.d.ts +26 -11
- package/dist/kbd/root/kbd-root.js +35 -38
- package/dist/kbd/shortcut.d.ts +18 -0
- package/dist/kbd/shortcut.js +35 -0
- package/dist/legend/hidden-series.d.ts +8 -0
- package/dist/legend/hidden-series.js +13 -0
- package/dist/legend/root/legend-root.d.ts +63 -0
- package/dist/legend/root/legend-root.js +61 -7
- package/dist/lightbox/item/lightbox-item.d.ts +17 -1
- package/dist/lightbox/item/lightbox-item.js +10 -1
- package/dist/lightbox/root/lightbox-root.d.ts +77 -6
- package/dist/lightbox/root/lightbox-root.js +116 -5
- package/dist/line-chart/root/line-chart-root.d.ts +29 -4
- package/dist/line-chart/root/line-chart-root.js +58 -17
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/range.d.ts +17 -0
- package/dist/listbox/range.js +5 -0
- package/dist/listbox/root/listbox-root.d.ts +184 -4
- package/dist/listbox/root/listbox-root.js +229 -23
- package/dist/loader/busy.d.ts +17 -0
- package/dist/loader/busy.js +24 -0
- package/dist/loader/root/loader-root.d.ts +37 -0
- package/dist/loader/root/loader-root.js +52 -3
- package/dist/map/root/map-root.d.ts +19 -4
- package/dist/map/root/map-root.js +36 -7
- package/dist/megamenu/root/megamenu-root.d.ts +10 -1
- package/dist/megamenu/root/megamenu-root.js +10 -1
- package/dist/menu/item/menu-item.d.ts +41 -12
- package/dist/menu/item/menu-item.js +46 -3
- package/dist/menu/root/menu-root.d.ts +32 -2
- package/dist/menu/root/menu-root.js +48 -8
- package/dist/meter/root/meter-root.d.ts +13 -0
- package/dist/meter/root/meter-root.js +24 -5
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/feed-keys.d.ts +10 -0
- package/dist/notifications/feed-keys.js +14 -0
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +29 -0
- package/dist/notifications/notification/notification.js +51 -3
- package/dist/notifications/root/notifications-root.d.ts +49 -0
- package/dist/notifications/root/notifications-root.js +76 -2
- package/dist/number-input/root/number-input-root.d.ts +109 -7
- package/dist/number-input/root/number-input-root.js +109 -21
- package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
- package/dist/object-inspector/root/object-inspector-root.js +92 -12
- package/dist/option/root/option-root.d.ts +58 -6
- package/dist/option/root/option-root.js +35 -5
- package/dist/outline/root/outline-root.d.ts +13 -2
- package/dist/outline/root/outline-root.js +4 -2
- package/dist/pagination/root/pagination-root.d.ts +19 -1
- package/dist/pagination/root/pagination-root.js +49 -9
- package/dist/pagination/size/pagination-size.d.ts +13 -3
- package/dist/pagination/size/pagination-size.js +7 -0
- package/dist/pin-input/format.d.ts +7 -0
- package/dist/pin-input/format.js +16 -0
- package/dist/pin-input/root/pin-input-root.d.ts +37 -0
- package/dist/pin-input/root/pin-input-root.js +48 -7
- package/dist/popover/root/popover-root.d.ts +78 -3
- package/dist/popover/root/popover-root.js +74 -5
- package/dist/progress/root/progress-root.d.ts +23 -1
- package/dist/progress/root/progress-root.js +40 -10
- package/dist/qr-code/export.d.ts +31 -0
- package/dist/qr-code/export.js +10 -0
- package/dist/qr-code/root/qr-code-root.d.ts +45 -0
- package/dist/qr-code/root/qr-code-root.js +78 -3
- package/dist/radio/group/radio-group.d.ts +64 -0
- package/dist/radio/group/radio-group.js +66 -12
- package/dist/radio/root/radio-root.d.ts +8 -5
- package/dist/radio/root/radio-root.js +1 -2
- package/dist/rating/root/rating-root.d.ts +49 -1
- package/dist/rating/root/rating-root.js +69 -10
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
- package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
- package/dist/select/root/select-root.d.ts +93 -3
- package/dist/select/root/select-root.js +111 -13
- package/dist/skeleton/root/skeleton-root.d.ts +39 -3
- package/dist/skeleton/root/skeleton-root.js +33 -4
- package/dist/skip-link/root/skip-link-root.d.ts +10 -0
- package/dist/skip-link/root/skip-link-root.js +15 -1
- package/dist/slider/root/slider-root.d.ts +59 -2
- package/dist/slider/root/slider-root.js +82 -8
- package/dist/sparkline/root/sparkline-root.d.ts +9 -10
- package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
- package/dist/speed-dial/item/speed-dial-item.js +7 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
- package/dist/speed-dial/root/speed-dial-root.js +19 -5
- package/dist/splitter/root/splitter-root.d.ts +28 -6
- package/dist/splitter/root/splitter-root.js +35 -1
- package/dist/stat/root/stat-root.d.ts +9 -1
- package/dist/stat/root/stat-root.js +15 -2
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/switch/root/switch-root.d.ts +14 -2
- package/dist/switch/root/switch-root.js +7 -1
- package/dist/table/cell/table-cell.d.ts +24 -4
- package/dist/table/cell/table-cell.js +21 -1
- package/dist/table/column/table-column.d.ts +32 -6
- package/dist/table/column/table-column.js +36 -6
- package/dist/table/root/table-root.d.ts +94 -3
- package/dist/table/root/table-root.js +128 -5
- package/dist/table/row/table-row.d.ts +7 -0
- package/dist/table/row/table-row.js +9 -1
- package/dist/tabs/root/tabs-root.d.ts +6 -1
- package/dist/tabs/root/tabs-root.js +6 -2
- package/dist/tag/group/tag-group.d.ts +107 -0
- package/dist/tag/group/tag-group.js +157 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +83 -1
- package/dist/tag/root/tag-root.js +87 -17
- package/dist/tag/selection.d.ts +10 -0
- package/dist/tag/selection.js +12 -0
- package/dist/textarea/grow.d.ts +22 -0
- package/dist/textarea/grow.js +20 -0
- package/dist/textarea/root/textarea-root.d.ts +13 -0
- package/dist/textarea/root/textarea-root.js +10 -2
- package/dist/time-input/root/time-input-root.d.ts +71 -6
- package/dist/time-input/root/time-input-root.js +110 -44
- package/dist/time-picker/root/time-picker-root.d.ts +155 -26
- package/dist/time-picker/root/time-picker-root.js +192 -63
- package/dist/toast/hotkey.d.ts +22 -0
- package/dist/toast/hotkey.js +23 -0
- package/dist/toast/item/toast-item.d.ts +16 -1
- package/dist/toast/item/toast-item.js +41 -13
- package/dist/toast/root/toast-root.d.ts +105 -8
- package/dist/toast/root/toast-root.js +209 -4
- package/dist/toggle/group/toggle-group.d.ts +95 -16
- package/dist/toggle/group/toggle-group.js +99 -13
- package/dist/toggle/root/toggle-root.d.ts +26 -11
- package/dist/toggle/root/toggle-root.js +14 -6
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/focus-target.d.ts +6 -0
- package/dist/tooltip/focus-target.js +9 -0
- package/dist/tooltip/root/tooltip-root.d.ts +73 -15
- package/dist/tooltip/root/tooltip-root.js +96 -7
- package/dist/tour/naming.d.ts +30 -0
- package/dist/tour/naming.js +10 -0
- package/dist/tour/root/tour-root.d.ts +67 -3
- package/dist/tour/root/tour-root.js +105 -17
- package/dist/tour/stop/tour-stop.d.ts +65 -3
- package/dist/tour/stop/tour-stop.js +61 -11
- package/dist/tour/wait.d.ts +11 -0
- package/dist/tour/wait.js +19 -0
- package/dist/tree/item/tree-item.d.ts +21 -5
- package/dist/tree/item/tree-item.js +14 -4
- package/dist/tree/root/tree-root.d.ts +29 -5
- package/dist/tree/root/tree-root.js +64 -8
- package/dist/trend/root/trend-root.d.ts +36 -1
- package/dist/trend/root/trend-root.js +41 -15
- package/dist/video/root/keys.d.ts +5 -0
- package/dist/video/root/keys.js +13 -1
- package/dist/video/root/video-root.d.ts +19 -0
- package/dist/video/root/video-root.js +48 -4
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
- package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
- package/dist/video-playlist/root/video-playlist-root.js +6 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
- package/dist/virtual-list/root/virtual-list-root.js +103 -21
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +9140 -1149
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +2089 -267
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
|
|
4
4
|
/**
|
|
5
5
|
* @summary One collapsible section of an accordion.
|
|
@@ -8,6 +8,10 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
|
|
|
8
8
|
* Holds its own open state. Used alone, outside an accordion, it works as a
|
|
9
9
|
* disclosure.
|
|
10
10
|
*
|
|
11
|
+
* The trigger sits inside a heading, so a screen reader lists the section with
|
|
12
|
+
* the page's headings. The level is the item's `heading-level`, then the
|
|
13
|
+
* accordion's, then 3.
|
|
14
|
+
*
|
|
11
15
|
* Content stays mounted when the item is closed, so it can animate and its text
|
|
12
16
|
* is present in server-rendered HTML. Closed content has both `hidden` and
|
|
13
17
|
* `inert`. `hidden` collapses it when no stylesheet is loaded. `inert` keeps it
|
|
@@ -24,12 +28,13 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
|
|
|
24
28
|
*
|
|
25
29
|
* @event {HelixBeforeCloseEvent} helix-before-close - The section is about to close. Cancelable: cancel it to keep it open.
|
|
26
30
|
* @event {HelixBeforeOpenEvent} helix-before-open - The section is about to open. Cancelable: cancel it to keep it closed.
|
|
27
|
-
* @event {
|
|
31
|
+
* @event {ToggleEvent} toggle - The section opened or closed. The event carries `newState` and `oldState`.
|
|
28
32
|
*
|
|
29
33
|
* @csspart chevron - The open and close indicator.
|
|
30
34
|
* @csspart container - The outer wrapper.
|
|
31
35
|
* @csspart content - The region that holds the content.
|
|
32
36
|
* @csspart content-inner - The clipping box inside the animated region.
|
|
37
|
+
* @csspart heading - The heading that holds the trigger.
|
|
33
38
|
* @csspart trigger - The button that opens and closes the section, holding the summary.
|
|
34
39
|
*
|
|
35
40
|
* @cssstate open - While the item is open.
|
|
@@ -48,6 +53,24 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
48
53
|
chevronPlacement?: 'auto' | 'start' | 'end' | 'none';
|
|
49
54
|
/** The chevron, or nothing when suppressed. */
|
|
50
55
|
private renderChevron;
|
|
56
|
+
/**
|
|
57
|
+
* Whether the section is disabled, so its trigger cannot be pressed or
|
|
58
|
+
* reached with the arrow keys. A script can still open and close it.
|
|
59
|
+
*/
|
|
60
|
+
disabled: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* @internal The accordion's `heading-level`, written by the accordion. A
|
|
63
|
+
* property, because an attribute written onto your element after it upgrades
|
|
64
|
+
* causes a hydration mismatch.
|
|
65
|
+
*/
|
|
66
|
+
groupHeadingLevel: number | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* The level of the heading around the trigger, from 1 to 6.
|
|
69
|
+
*
|
|
70
|
+
* Unset takes the accordion's `heading-level`, and 3 where that is unset
|
|
71
|
+
* too.
|
|
72
|
+
*/
|
|
73
|
+
headingLevel?: number;
|
|
51
74
|
/**
|
|
52
75
|
* A group name. Opening an item closes the other items with the same name,
|
|
53
76
|
* as `<details name>` does.
|
|
@@ -69,6 +92,8 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
69
92
|
* absence. Caught by `hydration.dom.spec.ts`.
|
|
70
93
|
*/
|
|
71
94
|
name?: string;
|
|
95
|
+
/** Whether the item was open at the last update, and `undefined` before one. */
|
|
96
|
+
private wasOpen;
|
|
72
97
|
/**
|
|
73
98
|
* The nearest accordion above this item, if there is one.
|
|
74
99
|
*
|
|
@@ -95,6 +120,17 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
95
120
|
* set collapsed after a listener refused it.
|
|
96
121
|
*/
|
|
97
122
|
protected handleToggle: () => void;
|
|
123
|
+
/** Closes the other open items in this item's set, where it has one. */
|
|
124
|
+
private closePeers;
|
|
125
|
+
/**
|
|
126
|
+
* Closes the peers of an item opened any other way than its trigger: `open`
|
|
127
|
+
* set from a script, `requestOpen` or `toggleOpen`. The trigger already
|
|
128
|
+
* closed them, so for a press this finds nothing open.
|
|
129
|
+
*
|
|
130
|
+
* Not on the first update. What the markup opens is the accordion's to
|
|
131
|
+
* settle, once every item is there to compare.
|
|
132
|
+
*/
|
|
133
|
+
protected updated(changed: PropertyValues): void;
|
|
98
134
|
/**
|
|
99
135
|
* Moves focus to this item's trigger.
|
|
100
136
|
*
|
|
@@ -15,7 +15,13 @@ const TRIGGER_ID = 'trigger';
|
|
|
15
15
|
let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinControllerOpen(HelixElement) {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(...arguments);
|
|
18
|
+
this.disabled = false;
|
|
19
|
+
this.groupHeadingLevel = undefined;
|
|
20
|
+
this.wasOpen = undefined;
|
|
18
21
|
this.handleToggle = () => {
|
|
22
|
+
if (this.disabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
19
25
|
const next = !this.open;
|
|
20
26
|
const mode = this.accordion?.mode;
|
|
21
27
|
if (!next && mode === 'single') {
|
|
@@ -24,12 +30,8 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
24
30
|
if (!this.requestOpen(next)) {
|
|
25
31
|
return;
|
|
26
32
|
}
|
|
27
|
-
if (next
|
|
28
|
-
|
|
29
|
-
if (peer !== this && peer.open) {
|
|
30
|
-
peer.requestOpen(false);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
+
if (next) {
|
|
34
|
+
this.closePeers();
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
}
|
|
@@ -57,25 +59,46 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
57
59
|
}
|
|
58
60
|
return accordion.items;
|
|
59
61
|
}
|
|
62
|
+
closePeers() {
|
|
63
|
+
if (this.accordion?.mode === undefined && (this.name === undefined || this.name === '')) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const peer of this.peers) {
|
|
67
|
+
if (peer !== this && peer.open) {
|
|
68
|
+
peer.requestOpen(false);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
updated(changed) {
|
|
73
|
+
super.updated(changed);
|
|
74
|
+
if (this.wasOpen === false && this.open) {
|
|
75
|
+
this.closePeers();
|
|
76
|
+
}
|
|
77
|
+
this.wasOpen = this.open;
|
|
78
|
+
}
|
|
60
79
|
focusTrigger() {
|
|
61
80
|
this.renderRoot.querySelector(`#${TRIGGER_ID}`)?.focus();
|
|
62
81
|
}
|
|
63
82
|
render() {
|
|
64
83
|
const open = this.open;
|
|
84
|
+
const level = Math.min(6, Math.max(1, this.headingLevel ?? this.groupHeadingLevel ?? 3));
|
|
65
85
|
return html `
|
|
66
86
|
<div part="container">
|
|
87
|
+
<div part="heading" role="heading" aria-level=${level}>
|
|
67
88
|
<button
|
|
68
89
|
id=${TRIGGER_ID}
|
|
69
90
|
aria-controls=${CONTENT_ID}
|
|
70
91
|
aria-expanded=${open ? 'true' : 'false'}
|
|
71
92
|
part="trigger"
|
|
72
93
|
type="button"
|
|
94
|
+
?disabled=${this.disabled}
|
|
73
95
|
@click=${this.handleToggle}
|
|
74
96
|
>
|
|
75
97
|
${this.chevronPlacement === 'start' ? this.renderChevron() : nothing}
|
|
76
98
|
<slot name="summary"></slot>
|
|
77
99
|
${this.chevronPlacement === 'start' ? nothing : this.renderChevron()}
|
|
78
100
|
</button>
|
|
101
|
+
</div>
|
|
79
102
|
<div
|
|
80
103
|
id=${CONTENT_ID}
|
|
81
104
|
aria-labelledby=${TRIGGER_ID}
|
|
@@ -95,6 +118,15 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
95
118
|
__decorate([
|
|
96
119
|
property({ attribute: 'chevron-placement', reflect: true })
|
|
97
120
|
], HelixHeadlessAccordionItem.prototype, "chevronPlacement", void 0);
|
|
121
|
+
__decorate([
|
|
122
|
+
property({ reflect: true, type: Boolean })
|
|
123
|
+
], HelixHeadlessAccordionItem.prototype, "disabled", void 0);
|
|
124
|
+
__decorate([
|
|
125
|
+
property({ attribute: false })
|
|
126
|
+
], HelixHeadlessAccordionItem.prototype, "groupHeadingLevel", void 0);
|
|
127
|
+
__decorate([
|
|
128
|
+
property({ attribute: 'heading-level', type: Number })
|
|
129
|
+
], HelixHeadlessAccordionItem.prototype, "headingLevel", void 0);
|
|
98
130
|
__decorate([
|
|
99
131
|
property({ reflect: true })
|
|
100
132
|
], HelixHeadlessAccordionItem.prototype, "name", void 0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
4
4
|
/**
|
|
5
5
|
* @summary A group of collapsible sections.
|
|
@@ -20,6 +20,10 @@ import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
|
20
20
|
* The keyboard listener belongs to the controller and is attached on connect,
|
|
21
21
|
* so it does not run on the server.
|
|
22
22
|
*
|
|
23
|
+
* Each trigger sits inside a heading, level 3 unless `heading-level` says
|
|
24
|
+
* otherwise, so the sections are in a screen reader's list of headings. Set the
|
|
25
|
+
* level that fits the page's outline.
|
|
26
|
+
*
|
|
23
27
|
* @since 0.1.0
|
|
24
28
|
* @status stable
|
|
25
29
|
* @category layout
|
|
@@ -29,6 +33,12 @@ import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
|
29
33
|
* @slot - The accordion's items.
|
|
30
34
|
*/
|
|
31
35
|
export declare class HelixHeadlessAccordion extends HelixElement {
|
|
36
|
+
/**
|
|
37
|
+
* The level of the heading around each trigger, from 1 to 6.
|
|
38
|
+
*
|
|
39
|
+
* Unset is 3. An item's own `heading-level` wins over this.
|
|
40
|
+
*/
|
|
41
|
+
headingLevel?: number;
|
|
32
42
|
/**
|
|
33
43
|
* How many sections may be open at once.
|
|
34
44
|
*
|
|
@@ -36,6 +46,11 @@ export declare class HelixHeadlessAccordion extends HelixElement {
|
|
|
36
46
|
* no attribute on the host. `single` keeps exactly one open and refuses to
|
|
37
47
|
* close the last; `single-collapsible` keeps at most one and lets it close.
|
|
38
48
|
*
|
|
49
|
+
* Held however a section opens: a press, `open` set from a script,
|
|
50
|
+
* `toggleOpen()`, or `default-open` in the markup. Opening one closes the
|
|
51
|
+
* others, and on first render only the first section written open stays
|
|
52
|
+
* open. Under `single` the first section opens when none is written open.
|
|
53
|
+
*
|
|
39
54
|
* A union rather than a mode plus a `collapsible` boolean, which would make
|
|
40
55
|
* `collapsible` alongside `multiple` expressible and meaningless.
|
|
41
56
|
*/
|
|
@@ -43,6 +58,13 @@ export declare class HelixHeadlessAccordion extends HelixElement {
|
|
|
43
58
|
/** The accordion's own items, in the order they are written. Browser only. */
|
|
44
59
|
get items(): HelixHeadlessAccordionItem[];
|
|
45
60
|
protected readonly keys: KeyboardNavigationController;
|
|
61
|
+
/**
|
|
62
|
+
* Holds the mode over the sections as written, and passes the heading level
|
|
63
|
+
* down. A section opened later closes its peers itself.
|
|
64
|
+
*/
|
|
65
|
+
private settle;
|
|
66
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
67
|
+
protected updated(changed: PropertyValues): void;
|
|
46
68
|
protected render(): TemplateResult;
|
|
47
69
|
}
|
|
48
70
|
declare global {
|
|
@@ -4,13 +4,13 @@ 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, HelixElement, KeyboardNavigationController, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, KeyboardNavigationController, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
11
11
|
const navigable = (item) => ({
|
|
12
12
|
contains: (node) => node === item,
|
|
13
|
-
disabled:
|
|
13
|
+
disabled: item.disabled,
|
|
14
14
|
focusItem: () => item.focusTrigger(),
|
|
15
15
|
select: () => { },
|
|
16
16
|
selected: false,
|
|
@@ -27,10 +27,46 @@ let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
|
|
|
27
27
|
get items() {
|
|
28
28
|
return [...this.children].filter((child) => child instanceof HelixHeadlessAccordionItem);
|
|
29
29
|
}
|
|
30
|
+
settle() {
|
|
31
|
+
const items = this.items;
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
whenHydrated(item, () => {
|
|
34
|
+
item.groupHeadingLevel = this.headingLevel;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (this.mode === undefined) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const open = items.filter((item) => item.open);
|
|
41
|
+
for (const extra of open.slice(1)) {
|
|
42
|
+
whenHydrated(extra, () => {
|
|
43
|
+
extra.open = false;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const first = items[0];
|
|
47
|
+
if (this.mode === 'single' && open.length === 0 && first) {
|
|
48
|
+
whenHydrated(first, () => {
|
|
49
|
+
first.open = true;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
firstUpdated(changed) {
|
|
54
|
+
super.firstUpdated(changed);
|
|
55
|
+
this.settle();
|
|
56
|
+
}
|
|
57
|
+
updated(changed) {
|
|
58
|
+
super.updated(changed);
|
|
59
|
+
if (this.hasUpdated && (changed.has('mode') || changed.has('headingLevel'))) {
|
|
60
|
+
this.settle();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
30
63
|
render() {
|
|
31
|
-
return html `<slot></slot>`;
|
|
64
|
+
return html `<slot @slotchange=${() => this.settle()}></slot>`;
|
|
32
65
|
}
|
|
33
66
|
};
|
|
67
|
+
__decorate([
|
|
68
|
+
property({ attribute: 'heading-level', type: Number })
|
|
69
|
+
], HelixHeadlessAccordion.prototype, "headingLevel", void 0);
|
|
34
70
|
__decorate([
|
|
35
71
|
property({ reflect: true })
|
|
36
72
|
], HelixHeadlessAccordion.prototype, "mode", void 0);
|
|
@@ -16,12 +16,17 @@ declare const HelixHeadlessAnnouncement_base: (new (...args: any[]) => import("@
|
|
|
16
16
|
*
|
|
17
17
|
* The live region is its own part. When the announcement appears after the page
|
|
18
18
|
* has loaded, the message is written into the region one frame later, so screen
|
|
19
|
-
* readers read it reliably
|
|
20
|
-
*
|
|
19
|
+
* readers read it reliably, and the region is emptied seven seconds later, so
|
|
20
|
+
* the message is not in the page twice. When the announcement is in the served
|
|
21
|
+
* HTML, the region stays empty and nothing is read out.
|
|
21
22
|
*
|
|
22
23
|
* The dismiss button fires `helix-dismiss`, and the announcement stays in the
|
|
23
24
|
* document, so remove it in your listener. The event is cancelable, and
|
|
24
|
-
* `dismiss()` returns `false` when a listener calls `preventDefault()`.
|
|
25
|
+
* `dismiss()` returns `false` when a listener calls `preventDefault()`. When
|
|
26
|
+
* your listener removes an announcement whose dismiss button has focus, focus
|
|
27
|
+
* moves to the dismiss button of the announcement beside it. With no other
|
|
28
|
+
* announcement beside it, move focus yourself, for example to the page's main
|
|
29
|
+
* heading.
|
|
25
30
|
*
|
|
26
31
|
* @since 0.1.0
|
|
27
32
|
* @status stable
|
|
@@ -39,7 +44,7 @@ declare const HelixHeadlessAnnouncement_base: (new (...args: any[]) => import("@
|
|
|
39
44
|
* @csspart content - The region that holds the message.
|
|
40
45
|
* @csspart dismiss - The button that dismisses the announcement.
|
|
41
46
|
* @csspart dismiss-mark - The icon on the dismiss button, shown when the `icon` slot is empty.
|
|
42
|
-
* @csspart live - A copy of the message in a live region, read by screen readers when the announcement appears after the page has loaded. Visually hidden in the styled tier.
|
|
47
|
+
* @csspart live - A copy of the message in a live region, read by screen readers when the announcement appears after the page has loaded, and emptied seven seconds later. Visually hidden in the styled tier.
|
|
43
48
|
*/
|
|
44
49
|
export declare class HelixHeadlessAnnouncement extends HelixHeadlessAnnouncement_base {
|
|
45
50
|
/**
|
|
@@ -55,9 +60,8 @@ export declare class HelixHeadlessAnnouncement extends HelixHeadlessAnnouncement
|
|
|
55
60
|
* components saying what a thing means, in three vocabularies, one of which
|
|
56
61
|
* described itself as a fourth.
|
|
57
62
|
*
|
|
58
|
-
* `accent` is the second emphasis,
|
|
59
|
-
*
|
|
60
|
-
* is the seed itself.
|
|
63
|
+
* `accent` is the second emphasis, the second color a theme names, and the
|
|
64
|
+
* brand itself until one is named. `primary` is the brand.
|
|
61
65
|
*
|
|
62
66
|
* **`surface` was never a color and has moved to `separation`**, which is the
|
|
63
67
|
* axis that owns where a box sits relative to the page. It said the band rode
|
|
@@ -34,7 +34,7 @@ let HelixHeadlessAnnouncement = class HelixHeadlessAnnouncement extends MixinDis
|
|
|
34
34
|
render() {
|
|
35
35
|
return html `<div part="content"><slot @slotchange=${() => this.arrival.say()}></slot></div>
|
|
36
36
|
<span part="live" role="status">${this.arrival.said}</span>
|
|
37
|
-
<div part="actions"><slot name="actions"></slot></div>
|
|
37
|
+
<div part="actions"><slot name="actions" @slotchange=${() => this.markEmpty()}></slot></div>
|
|
38
38
|
${this.dismissible
|
|
39
39
|
? html `<button
|
|
40
40
|
part="dismiss"
|
|
@@ -16,6 +16,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
16
16
|
* `ElementInternals.states` is not in the DOM, so hydration has nothing to
|
|
17
17
|
* compare. Select the state with `:state(scrolled)`.
|
|
18
18
|
*
|
|
19
|
+
* The page is the window unless `scroller` names the element that scrolls, for
|
|
20
|
+
* an app shell whose content scrolls inside a container.
|
|
21
|
+
*
|
|
19
22
|
* @since 0.1.0
|
|
20
23
|
* @status stable
|
|
21
24
|
* @category navigation
|
|
@@ -56,7 +59,24 @@ export declare class HelixHeadlessAppHeader extends HelixElement {
|
|
|
56
59
|
* the property carries the part's name, `content`.
|
|
57
60
|
*/
|
|
58
61
|
contentAlign?: 'start';
|
|
62
|
+
/**
|
|
63
|
+
* The id of the element whose scrolling lifts the bar, for an app shell that
|
|
64
|
+
* scrolls a container instead of the window. Unset is the window.
|
|
65
|
+
*/
|
|
66
|
+
scroller?: string;
|
|
59
67
|
private scrolled;
|
|
68
|
+
/** What scroll is listened to now, so a change of `scroller` moves it. */
|
|
69
|
+
private source;
|
|
70
|
+
/** The element `scroller` names, or the window. */
|
|
71
|
+
private findSource;
|
|
72
|
+
/**
|
|
73
|
+
* Listens to the scroll source that `scroller` names now.
|
|
74
|
+
*
|
|
75
|
+
* A named element that is not in the document yet, such as a `<main>` the
|
|
76
|
+
* parser has not reached when the header connects, is looked for once more
|
|
77
|
+
* when the document has loaded.
|
|
78
|
+
*/
|
|
79
|
+
private listen;
|
|
60
80
|
/**
|
|
61
81
|
* A band rather than a line, so the fill cannot flicker at the boundary.
|
|
62
82
|
*
|
|
@@ -79,6 +99,7 @@ export declare class HelixHeadlessAppHeader extends HelixElement {
|
|
|
79
99
|
protected willUpdate(changed: PropertyValues): void;
|
|
80
100
|
connectedCallback(): void;
|
|
81
101
|
disconnectedCallback(): void;
|
|
102
|
+
protected updated(changed: PropertyValues): void;
|
|
82
103
|
protected render(): TemplateResult;
|
|
83
104
|
}
|
|
84
105
|
declare global {
|
|
@@ -4,7 +4,7 @@ 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, HelixElement, HelixScrolledEvent, hostAria } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, elementById, HelixElement, HelixScrolledEvent, hostAria, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
@@ -12,7 +12,8 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.scrolled = false;
|
|
14
14
|
this.handleScroll = () => {
|
|
15
|
-
const
|
|
15
|
+
const source = this.source ?? window;
|
|
16
|
+
const y = source instanceof Element ? source.scrollTop : window.scrollY;
|
|
16
17
|
const next = this.scrolled ? y > 2 : y > 8;
|
|
17
18
|
if (next === this.scrolled) {
|
|
18
19
|
return;
|
|
@@ -22,18 +23,40 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
22
23
|
this.dispatchEvent(new HelixScrolledEvent({ scrolled: next }));
|
|
23
24
|
};
|
|
24
25
|
}
|
|
26
|
+
findSource() {
|
|
27
|
+
return (this.scroller ? elementById(this, this.scroller) : null) ?? window;
|
|
28
|
+
}
|
|
29
|
+
listen() {
|
|
30
|
+
const next = this.findSource();
|
|
31
|
+
if (next === window && this.scroller && document.readyState === 'loading') {
|
|
32
|
+
document.addEventListener('DOMContentLoaded', () => this.listen(), { once: true });
|
|
33
|
+
}
|
|
34
|
+
if (next === this.source) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.source?.removeEventListener('scroll', this.handleScroll);
|
|
38
|
+
this.source = next;
|
|
39
|
+
next.addEventListener('scroll', this.handleScroll, { passive: true });
|
|
40
|
+
this.handleScroll();
|
|
41
|
+
}
|
|
25
42
|
willUpdate(changed) {
|
|
26
43
|
super.willUpdate(changed);
|
|
27
44
|
hostAria(this.internals, { role: 'banner' });
|
|
28
45
|
}
|
|
29
46
|
connectedCallback() {
|
|
30
47
|
super.connectedCallback();
|
|
31
|
-
|
|
32
|
-
this.handleScroll();
|
|
48
|
+
this.listen();
|
|
33
49
|
}
|
|
34
50
|
disconnectedCallback() {
|
|
35
51
|
super.disconnectedCallback();
|
|
36
|
-
|
|
52
|
+
this.source?.removeEventListener('scroll', this.handleScroll);
|
|
53
|
+
this.source = undefined;
|
|
54
|
+
}
|
|
55
|
+
updated(changed) {
|
|
56
|
+
super.updated(changed);
|
|
57
|
+
if (changed.has('scroller') && this.isConnected) {
|
|
58
|
+
this.listen();
|
|
59
|
+
}
|
|
37
60
|
}
|
|
38
61
|
render() {
|
|
39
62
|
return html `
|
|
@@ -48,6 +71,9 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
48
71
|
__decorate([
|
|
49
72
|
property({ attribute: 'content-align', reflect: true })
|
|
50
73
|
], HelixHeadlessAppHeader.prototype, "contentAlign", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
property()
|
|
76
|
+
], HelixHeadlessAppHeader.prototype, "scroller", void 0);
|
|
51
77
|
HelixHeadlessAppHeader = __decorate([
|
|
52
78
|
customElement('helix-headless-app-header')
|
|
53
79
|
], HelixHeadlessAppHeader);
|
|
@@ -44,9 +44,15 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
|
|
|
44
44
|
* bands show each part's share. Use it to see which part grew. The default
|
|
45
45
|
* shows whether the total grew.
|
|
46
46
|
*
|
|
47
|
-
* The drawing is
|
|
48
|
-
* total and each part's share of it, and the table beside the chart
|
|
49
|
-
* number.
|
|
47
|
+
* The drawing is hidden from screen readers. The text summary gives the latest
|
|
48
|
+
* reading's total and each part's share of it, and the table beside the chart
|
|
49
|
+
* has every number.
|
|
50
|
+
*
|
|
51
|
+
* **The plot is read by key.** It takes focus, named by `label` or the caption.
|
|
52
|
+
* The left and right arrows move from reading to reading, Home and End go to
|
|
53
|
+
* the first and the last, and the up and down arrows move among the series of
|
|
54
|
+
* a reading. The tooltip follows, the `live` part says the reading in words,
|
|
55
|
+
* and Escape puts the tooltip away.
|
|
50
56
|
*
|
|
51
57
|
* Every numeric column is a part, so leave a total column out of the table the
|
|
52
58
|
* chart reads, or it is counted twice. A negative reading is drawn as zero.
|
|
@@ -64,8 +70,9 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
|
|
|
64
70
|
* @csspart label - One reading's name.
|
|
65
71
|
* @csspart labels - The row of reading names.
|
|
66
72
|
* @csspart line - The top edge of one part's band.
|
|
73
|
+
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
67
74
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
68
|
-
* @csspart plot - The drawing.
|
|
75
|
+
* @csspart plot - The drawing, which takes focus to be read by key.
|
|
69
76
|
* @csspart summary - The total and each part's share at the latest reading, written as a sentence for screen readers.
|
|
70
77
|
* @csspart svg - The drawing surface the bands sit on.
|
|
71
78
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
@@ -77,6 +84,7 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
|
|
|
77
84
|
* @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
|
|
78
85
|
* @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
|
|
79
86
|
* @csspart tooltip-cell - One column's name and value inside the tooltip.
|
|
87
|
+
* @csspart tooltip-cell-current - The cell the up and down arrows rest on, while they rest there. Set alongside `tooltip-cell`.
|
|
80
88
|
* @csspart tooltip-label - The reading's own name inside the tooltip.
|
|
81
89
|
* @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
|
|
82
90
|
* @csspart tooltip-name - A column's name inside the tooltip.
|
|
@@ -8,7 +8,18 @@ import { CHART_PLOT, customElement, drawTooltip, formatNumbers, HelixElement, li
|
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import '../../tooltip/index.js';
|
|
11
|
-
const
|
|
11
|
+
const PERCENTS = new Map();
|
|
12
|
+
const percentIn = (locale) => {
|
|
13
|
+
let found = PERCENTS.get(locale);
|
|
14
|
+
if (!found) {
|
|
15
|
+
found = new Intl.NumberFormat(locale || undefined, {
|
|
16
|
+
maximumFractionDigits: 0,
|
|
17
|
+
style: 'percent',
|
|
18
|
+
});
|
|
19
|
+
PERCENTS.set(locale, found);
|
|
20
|
+
}
|
|
21
|
+
return found;
|
|
22
|
+
};
|
|
12
23
|
let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSource(HelixElement) {
|
|
13
24
|
constructor() {
|
|
14
25
|
super(...arguments);
|
|
@@ -25,7 +36,11 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
25
36
|
get stack() {
|
|
26
37
|
const rows = this.sourceRows;
|
|
27
38
|
const columns = this.plottedColumns;
|
|
28
|
-
const
|
|
39
|
+
const names = columns.map((column) => rows.find((row) => row.cells[column])?.cells[column]?.name ?? '');
|
|
40
|
+
const values = columns.map((column, depth) => rows.map((row) => {
|
|
41
|
+
if (!this.showsSeries(names[depth] ?? '')) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
29
44
|
const value = row.cells[column]?.value ?? 0;
|
|
30
45
|
if (value < 0) {
|
|
31
46
|
this.warnNegative();
|
|
@@ -48,7 +63,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
48
63
|
return {
|
|
49
64
|
columns,
|
|
50
65
|
layers,
|
|
51
|
-
names
|
|
66
|
+
names,
|
|
52
67
|
totals,
|
|
53
68
|
values,
|
|
54
69
|
};
|
|
@@ -83,8 +98,17 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
83
98
|
}
|
|
84
99
|
renderPlot(stack, count, x, y, domain) {
|
|
85
100
|
const order = stack.layers.map((_, depth) => depth).reverse();
|
|
86
|
-
return html `<div
|
|
101
|
+
return html `<div
|
|
102
|
+
aria-describedby=${this.named ? 'helix-chart-summary' : nothing}
|
|
103
|
+
aria-label=${this.named || nothing}
|
|
104
|
+
aria-labelledby=${this.named ? nothing : 'helix-chart-summary'}
|
|
105
|
+
id=${CHART_PLOT}
|
|
106
|
+
part="plot"
|
|
107
|
+
role="application"
|
|
108
|
+
tabindex="0"
|
|
109
|
+
>
|
|
87
110
|
<svg part="svg"
|
|
111
|
+
aria-hidden="true"
|
|
88
112
|
data-mirror
|
|
89
113
|
preserveAspectRatio="none"
|
|
90
114
|
viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
|
|
@@ -150,15 +174,19 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
150
174
|
renderSummary(stack, rows) {
|
|
151
175
|
const last = rows.length - 1;
|
|
152
176
|
const total = stack.totals[last] ?? 0;
|
|
153
|
-
const format = formatNumbers(
|
|
154
|
-
const shares = stack.names.
|
|
177
|
+
const format = formatNumbers(this.locale);
|
|
178
|
+
const shares = stack.names.flatMap((name, depth) => this.showsSeries(name)
|
|
179
|
+
? [
|
|
180
|
+
`${name} ${percentIn(this.locale).format(total > 0 ? (stack.values[depth]?.[last] ?? 0) / total : 0)}`,
|
|
181
|
+
]
|
|
182
|
+
: []);
|
|
155
183
|
const named = this.named ? `${this.named}, ` : '';
|
|
156
|
-
return html `<p part="summary">
|
|
184
|
+
return html `<p id="helix-chart-summary" part="summary">
|
|
157
185
|
${named}${rows[last]?.label ?? ''}: ${this.totalLabel} ${format(total)}; ${shares.join(', ')}.
|
|
158
186
|
</p>`;
|
|
159
187
|
}
|
|
160
188
|
tallied(rows, stack) {
|
|
161
|
-
const format = formatNumbers(
|
|
189
|
+
const format = formatNumbers(this.locale);
|
|
162
190
|
return rows.map((row, index) => {
|
|
163
191
|
const total = stack.totals[index] ?? 0;
|
|
164
192
|
return {
|
|
@@ -167,7 +195,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
167
195
|
...row.cells.map((cell, column) => this.share && cell.value !== undefined && stack.columns.includes(column) && total > 0
|
|
168
196
|
? {
|
|
169
197
|
...cell,
|
|
170
|
-
text: `${cell.text} (${
|
|
198
|
+
text: `${cell.text} (${percentIn(this.locale).format(Math.max(0, cell.value) / total)})`,
|
|
171
199
|
}
|
|
172
200
|
: cell),
|
|
173
201
|
{ name: this.totalLabel, text: format(total) },
|
|
@@ -179,14 +207,14 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
179
207
|
const at = this.pointer.at;
|
|
180
208
|
const rows = this.tallied(this.sourceRows, stack);
|
|
181
209
|
if (at < 0) {
|
|
182
|
-
return drawTooltip(rows, at, this.tag('tooltip'));
|
|
210
|
+
return drawTooltip(rows, at, this.tag('tooltip'), undefined, undefined, this.pointer);
|
|
183
211
|
}
|
|
184
212
|
const slot = 100 / rows.length;
|
|
185
213
|
return drawTooltip(rows, at, this.tag('tooltip'), {
|
|
186
214
|
placement: 'top',
|
|
187
215
|
x: `${at * slot + slot / 2}%`,
|
|
188
216
|
y: `${y(stack.layers.at(-1)?.[at] ?? 0)}%`,
|
|
189
|
-
}, (cell) => this.seriesOf(cell));
|
|
217
|
+
}, (cell) => this.seriesOf(cell), this.pointer);
|
|
190
218
|
}
|
|
191
219
|
};
|
|
192
220
|
__decorate([
|
|
@@ -20,8 +20,10 @@ export declare const FOLDS_UP_TO = 12;
|
|
|
20
20
|
* There is no slot for it, because the number has to match which avatars are
|
|
21
21
|
* hidden.
|
|
22
22
|
*
|
|
23
|
-
* Avatars past `max` stay in the DOM and are hidden.
|
|
24
|
-
*
|
|
23
|
+
* Avatars past `max` stay in the DOM and are hidden. The group writes `hidden`
|
|
24
|
+
* on each of them, so they are hidden on the headless tier as well, and the
|
|
25
|
+
* count is read out as `overflow-label`, such as "3 more", so a screen reader
|
|
26
|
+
* hears that there are more people than the ones it can reach.
|
|
25
27
|
*
|
|
26
28
|
* @since 0.1.0
|
|
27
29
|
* @status stable
|
|
@@ -30,7 +32,7 @@ export declare const FOLDS_UP_TO = 12;
|
|
|
30
32
|
*
|
|
31
33
|
* @slot - The avatars, in the order they should be read.
|
|
32
34
|
*
|
|
33
|
-
* @csspart overflow - The count of avatars past `max`.
|
|
35
|
+
* @csspart overflow - The count of avatars past `max`, an image named by `overflow-label`.
|
|
34
36
|
*/
|
|
35
37
|
export declare class HelixHeadlessAvatarGroup extends HelixElement {
|
|
36
38
|
/**
|
|
@@ -56,6 +58,15 @@ export declare class HelixHeadlessAvatarGroup extends HelixElement {
|
|
|
56
58
|
* never asked for a limit, including on the server.
|
|
57
59
|
*/
|
|
58
60
|
max?: number;
|
|
61
|
+
/**
|
|
62
|
+
* What a screen reader is told the count is, with `{count}` for the number.
|
|
63
|
+
*
|
|
64
|
+
* The count shows "+3", which reads as "plus three" and says nothing about
|
|
65
|
+
* what was counted.
|
|
66
|
+
*/
|
|
67
|
+
overflowLabel: string;
|
|
68
|
+
/** The avatars this group hid, so it unhides only those. */
|
|
69
|
+
private readonly folded;
|
|
59
70
|
/** The avatars, in light-DOM order. Empty on the server, which has no tree. */
|
|
60
71
|
get avatars(): HTMLElement[];
|
|
61
72
|
/**
|
|
@@ -72,6 +83,16 @@ export declare class HelixHeadlessAvatarGroup extends HelixElement {
|
|
|
72
83
|
protected willUpdate(changed: PropertyValues): void;
|
|
73
84
|
protected firstUpdated(changed: PropertyValues): void;
|
|
74
85
|
protected updated(changed: PropertyValues): void;
|
|
86
|
+
/**
|
|
87
|
+
* Hides the avatars past `max`, with the platform's own `hidden`.
|
|
88
|
+
*
|
|
89
|
+
* **State in markup, so the headless tier folds too.** The fold was a styled
|
|
90
|
+
* rule alone, and on the headless tier every avatar was drawn beside a "+3".
|
|
91
|
+
* The styled rule stays, because it is what folds a server's markup before
|
|
92
|
+
* this runs. Written through `whenHydrated`, so an avatar's hydrating render
|
|
93
|
+
* is the server's, and undone only on the avatars this group hid.
|
|
94
|
+
*/
|
|
95
|
+
private fold;
|
|
75
96
|
protected render(): TemplateResult;
|
|
76
97
|
}
|
|
77
98
|
declare global {
|