@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
|
@@ -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, hostAria,
|
|
7
|
+
import { customElement, fillTemplate, HelixElement, hostAria, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
export const FOLDS_UP_TO = 12;
|
|
@@ -12,17 +12,15 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
|
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
14
14
|
this.label = '';
|
|
15
|
-
this.overflowLabel = '{count} more';
|
|
15
|
+
this.overflowLabel = '{count} more: {names}';
|
|
16
16
|
this.folded = new WeakSet();
|
|
17
|
-
this.warned = false;
|
|
18
17
|
}
|
|
19
18
|
get avatars() {
|
|
20
19
|
return this.knownChildren.filter((child) => child instanceof HTMLElement);
|
|
21
20
|
}
|
|
22
21
|
get overflow() {
|
|
23
22
|
const limit = this.max ?? 0;
|
|
24
|
-
|
|
25
|
-
return limited ? Math.max(this.avatars.length - limit, 0) : 0;
|
|
23
|
+
return limit > 0 ? Math.max(this.avatars.length - limit, 0) : 0;
|
|
26
24
|
}
|
|
27
25
|
willUpdate(changed) {
|
|
28
26
|
super.willUpdate(changed);
|
|
@@ -35,23 +33,11 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
|
|
|
35
33
|
updated(changed) {
|
|
36
34
|
super.updated(changed);
|
|
37
35
|
this.fold();
|
|
38
|
-
const limit = this.max ?? 0;
|
|
39
|
-
if (limit > FOLDS_UP_TO && this.avatars.length > limit && !this.warned) {
|
|
40
|
-
this.warned = true;
|
|
41
|
-
reportRuntime({
|
|
42
|
-
kind: 'max-past-fold',
|
|
43
|
-
message: `<${this.localName}> has max="${this.max}", past the ${FOLDS_UP_TO} the fold is written for, ` +
|
|
44
|
-
'so every avatar is shown and none are counted. Lower `max`, or hand the group the ' +
|
|
45
|
-
'avatars you want shown.',
|
|
46
|
-
tag: this.localName,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
36
|
}
|
|
50
37
|
fold() {
|
|
51
38
|
const limit = this.max ?? 0;
|
|
52
|
-
const limited = limit > 0 && limit <= FOLDS_UP_TO;
|
|
53
39
|
for (const [index, avatar] of this.avatars.entries()) {
|
|
54
|
-
const past =
|
|
40
|
+
const past = limit > 0 && index >= limit;
|
|
55
41
|
if (past && !avatar.hidden) {
|
|
56
42
|
this.folded.add(avatar);
|
|
57
43
|
whenHydrated(avatar, () => {
|
|
@@ -66,6 +52,15 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
|
|
|
66
52
|
}
|
|
67
53
|
}
|
|
68
54
|
}
|
|
55
|
+
foldedNames() {
|
|
56
|
+
const limit = this.max ?? 0;
|
|
57
|
+
return this.avatars
|
|
58
|
+
.slice(limit)
|
|
59
|
+
.map((avatar) => avatar.name ||
|
|
60
|
+
avatar.getAttribute('aria-label') ||
|
|
61
|
+
'')
|
|
62
|
+
.filter(Boolean);
|
|
63
|
+
}
|
|
69
64
|
render() {
|
|
70
65
|
const past = this.overflow;
|
|
71
66
|
return html `<slot @slotchange=${() => this.requestUpdate()}></slot>
|
|
@@ -73,7 +68,10 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
|
|
|
73
68
|
? html `<span
|
|
74
69
|
part="overflow"
|
|
75
70
|
role="img"
|
|
76
|
-
aria-label=${this.overflowLabel
|
|
71
|
+
aria-label=${fillTemplate(this.overflowLabel, {
|
|
72
|
+
count: String(past),
|
|
73
|
+
names: this.foldedNames().join(', '),
|
|
74
|
+
}).replace(/[\s:,]+$/, '')}
|
|
77
75
|
>+${past}</span
|
|
78
76
|
>`
|
|
79
77
|
: ''}`;
|
|
@@ -44,7 +44,9 @@ export declare class HelixHeadlessBadge extends HelixElement {
|
|
|
44
44
|
/**
|
|
45
45
|
* The badge's name, read by screen readers.
|
|
46
46
|
*
|
|
47
|
-
* Required for a dot, which has no text to read.
|
|
47
|
+
* Required for a dot, which has no text to read. `{count}` is replaced with
|
|
48
|
+
* what the badge shows, so `label="{count} unread"` reads "8 unread" and
|
|
49
|
+
* stays current as `value` changes, with no label of yours to keep in step.
|
|
48
50
|
*/
|
|
49
51
|
label: string;
|
|
50
52
|
/**
|
|
@@ -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 } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, fillTemplate, HelixElement } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessBadge = class HelixHeadlessBadge extends HelixElement {
|
|
@@ -36,7 +36,7 @@ let HelixHeadlessBadge = class HelixHeadlessBadge extends HelixElement {
|
|
|
36
36
|
data-blank=${blank ? '' : nothing}
|
|
37
37
|
data-single=${text.length <= 1 ? '' : nothing}
|
|
38
38
|
role="status"
|
|
39
|
-
aria-label=${announced ? this.label || text : nothing}
|
|
39
|
+
aria-label=${announced ? fillTemplate(this.label, { count: text }) || text : nothing}
|
|
40
40
|
>${blank ? html `<span aria-hidden="true">${text}</span>` : text}</span
|
|
41
41
|
>`;
|
|
42
42
|
}
|
|
@@ -176,6 +176,17 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
|
|
|
176
176
|
* of any scale question the picture raises.
|
|
177
177
|
*/
|
|
178
178
|
secondary?: string;
|
|
179
|
+
/**
|
|
180
|
+
* Stacks a category's columns into one, each series standing on the ones
|
|
181
|
+
* before it, so the column's height is the category's total.
|
|
182
|
+
*
|
|
183
|
+
* Absent stands them side by side, as it always did. A negative reading
|
|
184
|
+
* hangs below zero on the negatives before it, so neither direction hides
|
|
185
|
+
* the other. The scale fits the stacks. A series
|
|
186
|
+
* in `lines` is still a line, measured on its own reading; columns on the
|
|
187
|
+
* second scale stack among themselves.
|
|
188
|
+
*/
|
|
189
|
+
stacked: boolean;
|
|
179
190
|
/** The series names on the second scale, lowercased and trimmed. */
|
|
180
191
|
private get scaled();
|
|
181
192
|
/** The series names drawn as a line, lowercased and trimmed for matching. */
|
|
@@ -204,7 +215,8 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
|
|
|
204
215
|
*
|
|
205
216
|
* The highest, because which category leads is the question a bar chart is
|
|
206
217
|
* read for, and the table beside it has every other number. The reading is
|
|
207
|
-
* written the way the table writes it, such as `$128k` for `128000`.
|
|
218
|
+
* written the way the table writes it, such as `$128k` for `128000`. A
|
|
219
|
+
* series a legend hid is not drawn and is not said.
|
|
208
220
|
*/
|
|
209
221
|
protected renderSummary(series: Series[]): TemplateResult;
|
|
210
222
|
/**
|
|
@@ -214,6 +226,11 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
|
|
|
214
226
|
* and a screen reader hearing both hears the same numbers twice.
|
|
215
227
|
*/
|
|
216
228
|
protected renderPlot(series: Series[], categories: string[], y: (value: number) => number, domain: [number, number], floor: number, z?: (value: number) => number): TemplateResult;
|
|
229
|
+
/**
|
|
230
|
+
* One category's columns stacked into one, each on the ones before it on
|
|
231
|
+
* its own scale, through the pure `stackSpans`.
|
|
232
|
+
*/
|
|
233
|
+
private renderStack;
|
|
217
234
|
/**
|
|
218
235
|
* The numbers along one scale, drawn only where there are two of them.
|
|
219
236
|
*
|
|
@@ -7,11 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, ticks, unbroken, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { stackEnds, stackSpans } from '../stack.js';
|
|
10
11
|
import '../../tooltip/index.js';
|
|
11
12
|
let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
|
|
12
13
|
constructor() {
|
|
13
14
|
super(...arguments);
|
|
14
15
|
this.highestLabel = 'Highest';
|
|
16
|
+
this.stacked = false;
|
|
15
17
|
}
|
|
16
18
|
get scaled() {
|
|
17
19
|
return new Set(seriesNames(this.secondary));
|
|
@@ -39,8 +41,22 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
39
41
|
const own = (one) => scaled.has(one.name.trim().toLowerCase());
|
|
40
42
|
const shown = series.filter((one) => this.showsSeries(one.name));
|
|
41
43
|
const values = shown.flatMap((one) => one.points.map((point) => point.value));
|
|
44
|
+
const lined = this.lined;
|
|
45
|
+
const readingsOf = (group) => {
|
|
46
|
+
if (!this.stacked) {
|
|
47
|
+
return group.flatMap((one) => one.points.map((point) => point.value));
|
|
48
|
+
}
|
|
49
|
+
const columns = group.filter((one) => !lined.has(one.name.trim().toLowerCase()));
|
|
50
|
+
const slots = columns.map((one) => byRow(one, categories.length));
|
|
51
|
+
return [
|
|
52
|
+
...group
|
|
53
|
+
.filter((one) => lined.has(one.name.trim().toLowerCase()))
|
|
54
|
+
.flatMap((one) => one.points.map((point) => point.value)),
|
|
55
|
+
...stackEnds(categories.map((_, at) => slots.map((one) => one[at]?.value))),
|
|
56
|
+
];
|
|
57
|
+
};
|
|
42
58
|
const on = (which) => {
|
|
43
|
-
const found = shown.filter(which)
|
|
59
|
+
const found = readingsOf(shown.filter(which));
|
|
44
60
|
return found.length > 0 ? found : values.length > 0 ? values : [0];
|
|
45
61
|
};
|
|
46
62
|
const [low, high] = extent(scaled.size === 0 ? on(() => true) : on((one) => !own(one)));
|
|
@@ -66,7 +82,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
66
82
|
const columns = this.plottedColumns;
|
|
67
83
|
const highest = series.flatMap((one, depth) => {
|
|
68
84
|
const top = one.points.reduce((best, point) => (best === undefined || point.value > best.value ? point : best), undefined);
|
|
69
|
-
if (top === undefined) {
|
|
85
|
+
if (top === undefined || !this.showsSeries(one.name)) {
|
|
70
86
|
return [];
|
|
71
87
|
}
|
|
72
88
|
const text = rows[top.at]?.cells[columns[depth] ?? -1]?.text ?? String(top.value);
|
|
@@ -85,13 +101,15 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
85
101
|
const columns = series
|
|
86
102
|
.map((one, index) => ({ one, slots: byRow(one, categories.length), tone: index }))
|
|
87
103
|
.filter(({ one }) => !lined.has(one.name.trim().toLowerCase()) && this.showsSeries(one.name));
|
|
88
|
-
const
|
|
89
|
-
const
|
|
104
|
+
const abreast = this.stacked ? 1 : columns.length;
|
|
105
|
+
const stride = (slot * 0.72) / Math.max(abreast, 1);
|
|
106
|
+
const gap = abreast > 1 ? stride * 0.08 : 0;
|
|
90
107
|
const thickness = stride - gap;
|
|
91
|
-
const bar = (value, index, depth, tone, scale) => {
|
|
108
|
+
const bar = (value, index, depth, tone, scale, from) => {
|
|
92
109
|
const at = scale(value);
|
|
93
|
-
const
|
|
94
|
-
const
|
|
110
|
+
const base = from === undefined ? floor : scale(from);
|
|
111
|
+
const along = Math.min(base, at);
|
|
112
|
+
const size = Math.abs(base - at);
|
|
95
113
|
const across = index * slot + slot * 0.14 + depth * stride + gap / 2;
|
|
96
114
|
return sideways
|
|
97
115
|
? svg `<rect
|
|
@@ -151,12 +169,14 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
151
169
|
data-active=${this.pointer.at === index ? '' : nothing}
|
|
152
170
|
part="group${this.pointer.at === index ? ' group-active' : ''}"
|
|
153
171
|
>
|
|
154
|
-
${
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
${this.stacked
|
|
173
|
+
? this.renderStack(columns, index, against, bar)
|
|
174
|
+
: columns.map(({ slots, one, tone }, depth) => {
|
|
175
|
+
const point = slots[index];
|
|
176
|
+
return point === undefined
|
|
177
|
+
? nothing
|
|
178
|
+
: bar(point.value, index, depth, tone, against(one));
|
|
179
|
+
})}
|
|
160
180
|
</g>`)}
|
|
161
181
|
${series.map((one) => lined.has(one.name.trim().toLowerCase()) && this.showsSeries(one.name)
|
|
162
182
|
? this.renderLine(one, series.indexOf(one), slot, against(one), sideways)
|
|
@@ -165,6 +185,17 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
165
185
|
${this.renderTooltip()}
|
|
166
186
|
</div>`;
|
|
167
187
|
}
|
|
188
|
+
renderStack(columns, index, against, bar) {
|
|
189
|
+
const scales = [...new Set(columns.map(({ one }) => against(one)))];
|
|
190
|
+
return scales.flatMap((scale) => {
|
|
191
|
+
const mine = columns.filter(({ one }) => against(one) === scale);
|
|
192
|
+
const spans = stackSpans(mine.map(({ slots }) => slots[index]?.value));
|
|
193
|
+
return mine.flatMap(({ tone }, place) => {
|
|
194
|
+
const span = spans[place];
|
|
195
|
+
return span === undefined ? [] : [bar(span[1], index, 0, tone, scale, span[0])];
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
168
199
|
renderAxis(scale, domain, which, sideways, widest, tint) {
|
|
169
200
|
const sizing = sideways ? undefined : `--bar-chart-axis: ${widest}ch`;
|
|
170
201
|
return html `<div
|
|
@@ -234,10 +265,13 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
234
265
|
return drawTooltip(this.sourceRows, at, this.tag('tooltip'), undefined, undefined, this.pointer);
|
|
235
266
|
}
|
|
236
267
|
const shown = series.filter((one) => this.showsSeries(one.name));
|
|
237
|
-
const
|
|
268
|
+
const reached = shown
|
|
238
269
|
.map((one) => byRow(one, this.readings)[at]?.value)
|
|
239
270
|
.filter((one) => one !== undefined);
|
|
240
|
-
const
|
|
271
|
+
const values = this.stacked ? stackEnds([reached]) : reached;
|
|
272
|
+
const all = this.stacked
|
|
273
|
+
? stackEnds(Array.from({ length: this.readings }, (_, row) => shown.map((one) => byRow(one, this.readings)[row]?.value)))
|
|
274
|
+
: shown.flatMap((one) => one.points.map((point) => point.value));
|
|
241
275
|
const [low, high] = extent(all.length > 0 ? all : [0]);
|
|
242
276
|
const domain = [Math.min(0, low), Math.max(0, high)];
|
|
243
277
|
const sideways = this.orientation === 'horizontal';
|
|
@@ -268,6 +302,9 @@ __decorate([
|
|
|
268
302
|
__decorate([
|
|
269
303
|
property({ reflect: true })
|
|
270
304
|
], HelixHeadlessBarChart.prototype, "secondary", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
property({ reflect: true, type: Boolean })
|
|
307
|
+
], HelixHeadlessBarChart.prototype, "stacked", void 0);
|
|
271
308
|
HelixHeadlessBarChart = __decorate([
|
|
272
309
|
customElement('helix-headless-bar-chart')
|
|
273
310
|
], HelixHeadlessBarChart);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Where a column starts and ends along the measure, in the data's own units. */
|
|
2
|
+
export type Span = readonly [from: number, to: number];
|
|
3
|
+
/**
|
|
4
|
+
* Each column's span in one category, in the order given: a positive reading
|
|
5
|
+
* stacks up from zero on the positives before it, and a negative one down
|
|
6
|
+
* from zero on the negatives before it, so neither hides the other. A blank
|
|
7
|
+
* has no span.
|
|
8
|
+
*/
|
|
9
|
+
export declare const stackSpans: (values: readonly (number | undefined)[]) => (Span | undefined)[];
|
|
10
|
+
/**
|
|
11
|
+
* Every end a stack reaches across the categories, which is what its scale
|
|
12
|
+
* has to hold: the top of each stack of positives and the foot of each stack
|
|
13
|
+
* of negatives. `categories` holds each category's readings, one per column.
|
|
14
|
+
*/
|
|
15
|
+
export declare const stackEnds: (categories: readonly (readonly (number | undefined)[])[]) => number[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const stackSpans = (values) => {
|
|
2
|
+
let up = 0;
|
|
3
|
+
let down = 0;
|
|
4
|
+
return values.map((value) => {
|
|
5
|
+
if (value === undefined) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
const from = value >= 0 ? up : down;
|
|
9
|
+
const to = from + value;
|
|
10
|
+
if (value >= 0) {
|
|
11
|
+
up = to;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
down = to;
|
|
15
|
+
}
|
|
16
|
+
return [from, to];
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const stackEnds = (categories) => categories.flatMap((values) => stackSpans(values).flatMap((span) => (span === undefined ? [] : [span[1]])));
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
import '../breadcrumb/breadcrumb.js';
|
|
4
|
+
/** One step of a trail written as data, for `items`. */
|
|
5
|
+
export interface BreadcrumbItem {
|
|
6
|
+
/** The URL the step links to. The last step is the current page and takes none. */
|
|
7
|
+
href?: string;
|
|
8
|
+
/** The step's words. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** The link's `rel`. */
|
|
11
|
+
rel?: string;
|
|
12
|
+
/** Where the link opens. */
|
|
13
|
+
target?: string;
|
|
14
|
+
}
|
|
3
15
|
/**
|
|
4
16
|
* @summary Shows the path to the current page.
|
|
5
17
|
*
|
|
@@ -19,6 +31,16 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
19
31
|
* The trail does not measure itself, and you write its overflow in markup: put
|
|
20
32
|
* the crumb that holds the folded items where the gap should appear.
|
|
21
33
|
*
|
|
34
|
+
* A trail built from data, such as a router's matched routes, takes `items`: an
|
|
35
|
+
* array of `{ label, href }`, drawn as crumbs in order, the last one as the
|
|
36
|
+
* current page. Slotted crumbs follow them. Use one way or the other in a trail.
|
|
37
|
+
*
|
|
38
|
+
* With `max-items`, a trail drawn from `items` that is longer folds its middle
|
|
39
|
+
* into one crumb: the first crumb, a button, then the last `max-items` less one.
|
|
40
|
+
* The button is named by `expand-label` and shows the whole trail, moving focus
|
|
41
|
+
* to the first crumb it brought back. A new `items` folds again. Slotted crumbs
|
|
42
|
+
* do not fold; write the folded crumb where the gap should be.
|
|
43
|
+
*
|
|
22
44
|
* @since 0.1.0
|
|
23
45
|
* @status stable
|
|
24
46
|
* @category navigation
|
|
@@ -28,15 +50,49 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
28
50
|
* @slot - The trail's items, in order from the root to the current page. Put
|
|
29
51
|
* the crumb that holds the folded items where the gap should appear.
|
|
30
52
|
*
|
|
53
|
+
* @csspart crumb - Each crumb drawn from `items`.
|
|
54
|
+
* @csspart crumb-collapsed - The crumb that holds the folded middle of a trail longer than `max-items`.
|
|
55
|
+
* @csspart crumb-current - The crumb drawn from `items` for the current page.
|
|
56
|
+
* @csspart crumb-link - The link, or the current page's words, of a crumb drawn from `items`.
|
|
57
|
+
* @csspart crumb-separator - The separator before a crumb drawn from `items`.
|
|
58
|
+
* @csspart crumb-separator-mark - The chevron before a crumb drawn from `items`.
|
|
59
|
+
* @csspart expand - The button in the folded crumb that shows the whole trail.
|
|
31
60
|
* @csspart list - The ordered list.
|
|
32
61
|
*/
|
|
33
62
|
export declare class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
63
|
+
/**
|
|
64
|
+
* The name of the button that shows a folded trail's hidden crumbs. `{count}`
|
|
65
|
+
* is replaced by how many it shows. Translate it with the page.
|
|
66
|
+
*/
|
|
67
|
+
expandLabel: string;
|
|
68
|
+
/**
|
|
69
|
+
* The trail as data, drawn as crumbs before any you slot. The last item is the
|
|
70
|
+
* current page.
|
|
71
|
+
*
|
|
72
|
+
* React Aria's `items`. A property only: a trail is built by script, and an
|
|
73
|
+
* attribute would put the whole path into the markup twice.
|
|
74
|
+
*/
|
|
75
|
+
items: BreadcrumbItem[];
|
|
34
76
|
/**
|
|
35
77
|
* The landmark's name, read by screen readers. An `aria-label` on the host
|
|
36
78
|
* wins over it.
|
|
37
79
|
*/
|
|
38
80
|
label: string;
|
|
81
|
+
/**
|
|
82
|
+
* The most crumbs a trail drawn from `items` shows before it folds its middle
|
|
83
|
+
* into one, counting the first and the last. Unset, it never folds. At least
|
|
84
|
+
* 2, so the first crumb and the current page always show.
|
|
85
|
+
*/
|
|
86
|
+
maxItems?: number;
|
|
87
|
+
/** Whether a reader has asked to see the whole of a folded trail. */
|
|
88
|
+
private expanded;
|
|
89
|
+
/** Shows the whole trail and moves focus to the first crumb it brought back. */
|
|
90
|
+
private readonly expand;
|
|
39
91
|
protected willUpdate(changed: PropertyValues): void;
|
|
92
|
+
/** How many crumbs drawn from `items` are folded away, or 0. */
|
|
93
|
+
private get folded();
|
|
94
|
+
/** The crumbs `items` describes, each a crumb of this tier. */
|
|
95
|
+
protected renderItems(): TemplateResult | typeof nothing;
|
|
40
96
|
protected render(): TemplateResult;
|
|
41
97
|
}
|
|
42
98
|
declare global {
|
|
@@ -5,26 +5,96 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
|
-
import {
|
|
9
|
-
import { property } from 'lit/decorators.js';
|
|
8
|
+
import { nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
11
|
+
import { html } from 'lit/static-html.js';
|
|
12
|
+
import '../breadcrumb/breadcrumb.js';
|
|
10
13
|
let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
11
14
|
constructor() {
|
|
12
15
|
super(...arguments);
|
|
16
|
+
this.expandLabel = 'Show {count} more';
|
|
17
|
+
this.items = [];
|
|
13
18
|
this.label = 'Breadcrumb';
|
|
19
|
+
this.expanded = false;
|
|
20
|
+
this.expand = () => {
|
|
21
|
+
this.expanded = true;
|
|
22
|
+
this.updateComplete.then(() => {
|
|
23
|
+
const crumb = this.renderRoot.querySelectorAll('[part~="crumb"]')[1];
|
|
24
|
+
crumb?.shadowRoot?.querySelector('a, [part="link"]')?.focus();
|
|
25
|
+
});
|
|
26
|
+
};
|
|
14
27
|
}
|
|
15
28
|
willUpdate(changed) {
|
|
16
29
|
super.willUpdate(changed);
|
|
17
30
|
hostAria(this.internals, { label: this.label, role: 'navigation' });
|
|
31
|
+
if (changed.has('items') && changed.get('items') !== undefined) {
|
|
32
|
+
this.expanded = false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
get folded() {
|
|
36
|
+
const most = this.maxItems ?? 0;
|
|
37
|
+
const count = this.items.length;
|
|
38
|
+
return !this.expanded && most >= 2 && count > most ? count - most : 0;
|
|
39
|
+
}
|
|
40
|
+
renderItems() {
|
|
41
|
+
if (this.items.length === 0) {
|
|
42
|
+
return nothing;
|
|
43
|
+
}
|
|
44
|
+
const crumb = this.tag('breadcrumb');
|
|
45
|
+
const last = this.items.length - 1;
|
|
46
|
+
const folded = this.folded;
|
|
47
|
+
const shown = this.items
|
|
48
|
+
.map((item, index) => ({ index, item }))
|
|
49
|
+
.filter(({ index }) => folded === 0 || index === 0 || index > folded);
|
|
50
|
+
const fold = folded === 0
|
|
51
|
+
? nothing
|
|
52
|
+
: html `<${crumb}
|
|
53
|
+
part="crumb crumb-collapsed"
|
|
54
|
+
exportparts="link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
55
|
+
><button
|
|
56
|
+
part="expand"
|
|
57
|
+
type="button"
|
|
58
|
+
aria-label=${this.expandLabel.replace('{count}', String(folded))}
|
|
59
|
+
@click=${this.expand}
|
|
60
|
+
>
|
|
61
|
+
…
|
|
62
|
+
</button></${crumb}
|
|
63
|
+
>`;
|
|
64
|
+
const first = shown.slice(0, 1);
|
|
65
|
+
const rest = shown.slice(1);
|
|
66
|
+
const draw = ({ index, item }) => html `<${crumb}
|
|
67
|
+
part="crumb${index === last ? ' crumb-current' : ''}"
|
|
68
|
+
exportparts="link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
69
|
+
href=${index === last ? nothing : (item.href ?? nothing)}
|
|
70
|
+
rel=${item.rel ?? nothing}
|
|
71
|
+
target=${item.target ?? nothing}
|
|
72
|
+
?current=${index === last}
|
|
73
|
+
>${item.label}</${crumb}
|
|
74
|
+
>`;
|
|
75
|
+
return html `${repeat(first, ({ index }) => index, draw)}${fold}${repeat(rest, ({ index }) => index, draw)}`;
|
|
18
76
|
}
|
|
19
77
|
render() {
|
|
20
78
|
return html `<ol part="list" role="list">
|
|
21
|
-
<slot></slot>
|
|
79
|
+
${this.renderItems()}<slot></slot>
|
|
22
80
|
</ol>`;
|
|
23
81
|
}
|
|
24
82
|
};
|
|
83
|
+
__decorate([
|
|
84
|
+
property({ attribute: 'expand-label' })
|
|
85
|
+
], HelixHeadlessBreadcrumbs.prototype, "expandLabel", void 0);
|
|
86
|
+
__decorate([
|
|
87
|
+
property({ attribute: false })
|
|
88
|
+
], HelixHeadlessBreadcrumbs.prototype, "items", void 0);
|
|
25
89
|
__decorate([
|
|
26
90
|
property()
|
|
27
91
|
], HelixHeadlessBreadcrumbs.prototype, "label", void 0);
|
|
92
|
+
__decorate([
|
|
93
|
+
property({ attribute: 'max-items', type: Number })
|
|
94
|
+
], HelixHeadlessBreadcrumbs.prototype, "maxItems", void 0);
|
|
95
|
+
__decorate([
|
|
96
|
+
state()
|
|
97
|
+
], HelixHeadlessBreadcrumbs.prototype, "expanded", void 0);
|
|
28
98
|
HelixHeadlessBreadcrumbs = __decorate([
|
|
29
99
|
customElement('helix-headless-breadcrumbs')
|
|
30
100
|
], HelixHeadlessBreadcrumbs);
|
|
@@ -32,6 +32,15 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
32
32
|
* Set `pending` while the action a press started is still running. The button
|
|
33
33
|
* keeps focus and refuses presses, and a reader on it hears `pending-label`.
|
|
34
34
|
*
|
|
35
|
+
* Every press that acts sends `helix-press` with what pressed it in
|
|
36
|
+
* `detail.pointerType`: `mouse`, `pen`, `touch`, `keyboard`, or `virtual` for
|
|
37
|
+
* a screen reader's press or a script's `click()`, as React Aria's `onPress`
|
|
38
|
+
* does. It is sent once the press has done its own work, before `click`
|
|
39
|
+
* reaches listeners on the element, and never for a disabled or pending
|
|
40
|
+
* button.
|
|
41
|
+
*
|
|
42
|
+
* **Keyboard.** Enter and Space press the button, as on a native one.
|
|
43
|
+
*
|
|
35
44
|
* @since 0.1.0
|
|
36
45
|
* @status stable
|
|
37
46
|
* @category actions
|
|
@@ -41,6 +50,8 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
41
50
|
* @slot end - Content after the label.
|
|
42
51
|
* @slot start - Content before the label, usually an icon.
|
|
43
52
|
*
|
|
53
|
+
* @event {HelixPressEvent} helix-press - Fired when a press acts, with `detail.pointerType` saying what pressed the button.
|
|
54
|
+
*
|
|
44
55
|
* @csspart button - The inner control.
|
|
45
56
|
* @csspart live - The live region that says `pending-label` when the button becomes pending under focus. It is rendered from the first time the button is pending, and the styled button clips it out of view.
|
|
46
57
|
* @csspart text - The button's words, which the styled button trims to their capitals and baseline so the letters sit at the middle in any font.
|
|
@@ -214,7 +225,22 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
214
225
|
protected renderLive(): TemplateResult | typeof nothing;
|
|
215
226
|
/** Moves focus to the inner control, so the host is never the focus target. */
|
|
216
227
|
static shadowRootOptions: ShadowRootInit;
|
|
228
|
+
/** What the control saw before a click that the click may not carry. */
|
|
229
|
+
private recent;
|
|
230
|
+
/**
|
|
231
|
+
* @internal Records what starts a press, a pointer's kind or Enter or Space,
|
|
232
|
+
* for `helix-press`. Bound on the inner control by this render and by any
|
|
233
|
+
* subclass that draws its own.
|
|
234
|
+
*/
|
|
235
|
+
protected readonly notePress: (event: Event) => void;
|
|
236
|
+
/**
|
|
237
|
+
* @internal Sends `helix-press` for a click that acted, with what pressed it,
|
|
238
|
+
* and forgets what started it.
|
|
239
|
+
*/
|
|
240
|
+
protected announcePress(click: Event): void;
|
|
217
241
|
private readonly handleClick;
|
|
242
|
+
/** What a press does: sends the command, and submits or resets the form. */
|
|
243
|
+
private act;
|
|
218
244
|
/**
|
|
219
245
|
* What activating the button does to its form.
|
|
220
246
|
*/
|
|
@@ -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 { AriaForwardController, customElement, drawStatus, elementById, HelixFallbackCommandEvent, HelixFormElement, StatusController, supportsInvokers, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, defaultButton, drawStatus, elementById, HelixFallbackCommandEvent, HelixFormElement, HelixPressEvent, pressType, StatusController, submitsOnEnter, supportsInvokers, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
@@ -27,27 +27,23 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
27
27
|
this.pending = false;
|
|
28
28
|
this.pendingLabel = 'Loading';
|
|
29
29
|
this.status = new StatusController(this);
|
|
30
|
+
this.recent = {};
|
|
31
|
+
this.notePress = (event) => {
|
|
32
|
+
if (event.type === 'pointerdown') {
|
|
33
|
+
this.recent = { pointer: event.pointerType };
|
|
34
|
+
}
|
|
35
|
+
else if (event.key === 'Enter' || event.key === ' ') {
|
|
36
|
+
this.recent = { key: true };
|
|
37
|
+
}
|
|
38
|
+
};
|
|
30
39
|
this.handleClick = (event) => {
|
|
31
40
|
if (this.pending) {
|
|
32
41
|
event.preventDefault();
|
|
33
42
|
event.stopImmediatePropagation();
|
|
34
43
|
return;
|
|
35
44
|
}
|
|
36
|
-
this.
|
|
37
|
-
this.
|
|
38
|
-
if (this.type === 'button') {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const { form } = this;
|
|
42
|
-
if (!form) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (this.type === 'submit') {
|
|
46
|
-
this.submit(form);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
form.reset();
|
|
50
|
-
}
|
|
45
|
+
this.act();
|
|
46
|
+
this.announcePress(event);
|
|
51
47
|
};
|
|
52
48
|
this.type = 'button';
|
|
53
49
|
this.value = '';
|
|
@@ -57,8 +53,8 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
57
53
|
if (event.key !== 'Enter' ||
|
|
58
54
|
event.defaultPrevented ||
|
|
59
55
|
!form ||
|
|
60
|
-
!
|
|
61
|
-
|
|
56
|
+
!submitsOnEnter(event.composedPath()[0], form) ||
|
|
57
|
+
defaultButton(form) !== this) {
|
|
62
58
|
return;
|
|
63
59
|
}
|
|
64
60
|
event.preventDefault();
|
|
@@ -84,6 +80,28 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
84
80
|
...HelixFormElement.shadowRootOptions,
|
|
85
81
|
delegatesFocus: true,
|
|
86
82
|
}; }
|
|
83
|
+
announcePress(click) {
|
|
84
|
+
const pointerType = pressType(click, this.recent);
|
|
85
|
+
this.recent = {};
|
|
86
|
+
this.dispatchEvent(new HelixPressEvent({ pointerType }));
|
|
87
|
+
}
|
|
88
|
+
act() {
|
|
89
|
+
this.linkCommand();
|
|
90
|
+
this.sendCommand();
|
|
91
|
+
if (this.type === 'button') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { form } = this;
|
|
95
|
+
if (!form) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (this.type === 'submit') {
|
|
99
|
+
this.submit(form);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
form.reset();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
87
105
|
submit(form) {
|
|
88
106
|
const undo = [];
|
|
89
107
|
const override = (attribute, value) => {
|
|
@@ -201,6 +219,8 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
201
219
|
tabindex=${stop}
|
|
202
220
|
?disabled=${this.isDisabled}
|
|
203
221
|
@click=${this.handleClick}
|
|
222
|
+
@keydown=${this.notePress}
|
|
223
|
+
@pointerdown=${this.notePress}
|
|
204
224
|
>
|
|
205
225
|
${label}
|
|
206
226
|
</button>${this.renderLive()}`;
|