@fusion.dev/helix-headless 0.146.0 → 0.148.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 +9287 -1084
- package/dist/accordion/item/accordion-item.d.ts +43 -21
- package/dist/accordion/item/accordion-item.js +37 -11
- package/dist/accordion/root/accordion-root.d.ts +8 -2
- package/dist/accordion/root/accordion-root.js +6 -8
- package/dist/announcement/root/announcement-root.d.ts +66 -6
- package/dist/announcement/root/announcement-root.js +144 -13
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +14 -7
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/count.d.ts +14 -0
- package/dist/badge/count.js +20 -0
- package/dist/badge/root/badge-root.d.ts +57 -6
- package/dist/badge/root/badge-root.js +77 -8
- package/dist/bar-chart/root/bar-chart-root.js +11 -20
- package/dist/bar-chart/stack.d.ts +10 -0
- package/dist/bar-chart/stack.js +8 -0
- package/dist/blockquote/root/blockquote-root.d.ts +66 -8
- package/dist/blockquote/root/blockquote-root.js +85 -8
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
- package/dist/button/root/button-root.d.ts +24 -38
- package/dist/button/root/button-root.js +6 -37
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/arrows.d.ts +14 -0
- package/dist/button-group/arrows.js +10 -0
- package/dist/button-group/root/button-group-root.d.ts +141 -3
- package/dist/button-group/root/button-group-root.js +142 -2
- package/dist/canvas/edge-pan.d.ts +61 -0
- package/dist/canvas/edge-pan.js +63 -0
- package/dist/canvas/node/canvas-node.d.ts +12 -2
- package/dist/canvas/node/canvas-node.js +6 -2
- package/dist/canvas/root/canvas-document.d.ts +10 -0
- package/dist/canvas/root/canvas-document.js +1 -0
- package/dist/canvas/root/canvas-root.d.ts +107 -5
- package/dist/canvas/root/canvas-root.js +140 -36
- package/dist/canvas/snap.d.ts +42 -0
- package/dist/canvas/snap.js +32 -0
- package/dist/card/root/card-root.d.ts +12 -1
- package/dist/card/root/card-root.js +11 -4
- package/dist/carousel/root/carousel-root.d.ts +4 -3
- package/dist/carousel/root/carousel-root.js +2 -6
- package/dist/chat/root/chat-root.d.ts +28 -4
- package/dist/chat/root/chat-root.js +12 -7
- package/dist/checkbox/root/checkbox-root.js +5 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
- package/dist/checkbox-group/select-all.d.ts +9 -4
- package/dist/checkbox-group/select-all.js +1 -1
- package/dist/code-block/root/code-block-root.d.ts +41 -18
- package/dist/code-block/root/code-block-root.js +21 -6
- package/dist/color-input/root/color-input-root.d.ts +11 -0
- package/dist/color-input/root/color-input-root.js +12 -5
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +32 -24
- package/dist/color-picker/root/color-picker-root.js +99 -55
- package/dist/color-picker/wheel.d.ts +28 -0
- package/dist/color-picker/wheel.js +15 -0
- package/dist/combobox/root/combobox-root.d.ts +83 -11
- package/dist/combobox/root/combobox-root.js +81 -18
- package/dist/command/root/command-root.d.ts +7 -4
- package/dist/command/root/command-root.js +2 -19
- package/dist/copy-button/root/copy-button-root.d.ts +16 -1
- package/dist/copy-button/root/copy-button-root.js +7 -2
- package/dist/data-table/keys.d.ts +0 -18
- package/dist/data-table/keys.js +1 -11
- package/dist/data-table/root/data-table-root.js +29 -50
- package/dist/date-input/root/date-input-root.d.ts +8 -1
- package/dist/date-input/root/date-input-root.js +8 -5
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +21 -16
- package/dist/description-list/item/description-list-item.d.ts +22 -4
- package/dist/description-list/item/description-list-item.js +14 -4
- package/dist/divider/root/divider-root.d.ts +45 -16
- package/dist/divider/root/divider-root.js +28 -4
- package/dist/donut-chart/root/donut-chart-root.js +13 -6
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/root/drawer-root.d.ts +4 -2
- package/dist/drawer/root/drawer-root.js +15 -3
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +38 -4
- package/dist/drilldown/root/drilldown-root.js +3 -2
- package/dist/element-events.generated.js +5 -1
- package/dist/empty/root/empty-root.d.ts +46 -2
- package/dist/empty/root/empty-root.js +50 -5
- package/dist/file-input/root/file-input-root.d.ts +34 -6
- package/dist/file-input/root/file-input-root.js +55 -21
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +11 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +10 -2
- package/dist/filter-input/root/filter-input-root.d.ts +8 -0
- package/dist/filter-input/root/filter-input-root.js +17 -27
- package/dist/format-date/fields.d.ts +20 -0
- package/dist/format-date/fields.js +14 -0
- package/dist/format-date/options.d.ts +5 -5
- package/dist/format-date/options.js +10 -39
- package/dist/format-date/root/format-date-root.d.ts +53 -4
- package/dist/format-date/root/format-date-root.js +38 -50
- package/dist/graph/root/graph-root.d.ts +23 -5
- package/dist/graph/root/graph-root.js +17 -20
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +76 -3
- package/dist/heatmap/root/heatmap-root.js +105 -20
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +13 -0
- package/dist/icon/root/icon-root.js +23 -2
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/image/root/image-root.d.ts +20 -0
- package/dist/image/root/image-root.js +6 -1
- package/dist/input/root/input-root.d.ts +23 -2
- package/dist/input/root/input-root.js +12 -8
- package/dist/kbd/root/kbd-root.d.ts +20 -3
- package/dist/kbd/root/kbd-root.js +23 -50
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +25 -7
- package/dist/legend/root/legend-root.js +25 -26
- package/dist/lightbox/root/lightbox-root.d.ts +50 -5
- package/dist/lightbox/root/lightbox-root.js +76 -8
- package/dist/lightbox/zoom.d.ts +2 -0
- package/dist/lightbox/zoom.js +5 -3
- package/dist/line-chart/root/line-chart-root.d.ts +16 -0
- package/dist/line-chart/root/line-chart-root.js +10 -2
- package/dist/list/root/list-root.d.ts +10 -2
- package/dist/list/root/list-root.js +31 -24
- package/dist/list/selection.d.ts +17 -0
- package/dist/list/selection.js +16 -0
- package/dist/listbox/root/listbox-root.d.ts +125 -26
- package/dist/listbox/root/listbox-root.js +156 -166
- package/dist/map/marker/map-marker.d.ts +2 -1
- package/dist/map/root/map-root.d.ts +40 -2
- package/dist/map/root/map-root.js +64 -23
- package/dist/megamenu/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +38 -14
- package/dist/megamenu/root/megamenu-root.js +29 -50
- package/dist/menu/item/menu-item.js +4 -4
- package/dist/menu/root/menu-root.d.ts +5 -2
- package/dist/meter/root/meter-root.d.ts +42 -0
- package/dist/meter/root/meter-root.js +33 -7
- package/dist/navigation/root/navigation-root.js +5 -8
- package/dist/notifications/group/notification-group.d.ts +8 -1
- package/dist/notifications/group/notification-group.js +12 -6
- package/dist/notifications/notification/notification.d.ts +12 -1
- package/dist/notifications/notification/notification.js +3 -1
- package/dist/notifications/root/notifications-root.d.ts +48 -3
- package/dist/notifications/root/notifications-root.js +36 -6
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +17 -1
- package/dist/number-input/root/number-input-root.js +29 -18
- package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
- package/dist/object-inspector/root/object-inspector-root.js +31 -20
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +12 -0
- package/dist/outline/root/outline-root.js +5 -19
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +51 -1
- package/dist/pin-input/code.js +37 -0
- package/dist/pin-input/root/pin-input-root.d.ts +98 -121
- package/dist/pin-input/root/pin-input-root.js +151 -156
- package/dist/popover/hide-outside.js +2 -9
- package/dist/popover/root/popover-root.d.ts +7 -1
- package/dist/popover/root/popover-root.js +9 -1
- package/dist/progress/root/progress-root.d.ts +27 -0
- package/dist/progress/root/progress-root.js +25 -7
- package/dist/qr-code/export.d.ts +19 -0
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +31 -9
- package/dist/qr-code/root/qr-code-root.js +29 -17
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.js +2 -2
- package/dist/rating/root/rating-root.d.ts +22 -9
- package/dist/rating/root/rating-root.js +15 -39
- package/dist/scatter-chart/measures.d.ts +22 -0
- package/dist/scatter-chart/measures.js +11 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
- package/dist/scroll-area/scrollbar.d.ts +0 -8
- package/dist/scroll-area/scrollbar.js +1 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +115 -11
- package/dist/select/root/select-root.js +104 -20
- package/dist/slider/root/slider-root.d.ts +18 -1
- package/dist/slider/root/slider-root.js +22 -0
- package/dist/sparkline/readings.d.ts +30 -12
- package/dist/sparkline/readings.js +32 -15
- package/dist/sparkline/root/sparkline-root.d.ts +46 -3
- package/dist/sparkline/root/sparkline-root.js +60 -21
- package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
- package/dist/speed-dial/group/speed-dial-group.js +43 -0
- package/dist/speed-dial/index.d.ts +1 -0
- package/dist/speed-dial/index.js +1 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
- package/dist/speed-dial/item/speed-dial-item.js +43 -5
- package/dist/speed-dial/long-press.d.ts +50 -0
- package/dist/speed-dial/long-press.js +48 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
- package/dist/speed-dial/root/speed-dial-root.js +123 -6
- package/dist/splitter/root/splitter-root.d.ts +9 -2
- package/dist/splitter/root/splitter-root.js +18 -3
- package/dist/steps/root/steps-root.d.ts +8 -1
- package/dist/steps/root/steps-root.js +6 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/table/cell/table-cell.d.ts +8 -1
- package/dist/table/cell/table-cell.js +6 -2
- package/dist/table/column/table-column.d.ts +6 -0
- package/dist/table/column/table-column.js +5 -1
- package/dist/table/grid-controller.d.ts +117 -0
- package/dist/table/grid-controller.js +293 -0
- package/dist/table/root/table-root.d.ts +47 -3
- package/dist/table/root/table-root.js +93 -29
- package/dist/table/row/table-row.d.ts +36 -0
- package/dist/table/row/table-row.js +52 -2
- package/dist/tabs/root/tabs-root.d.ts +5 -3
- package/dist/tag/group/tag-group.d.ts +16 -4
- package/dist/tag/group/tag-group.js +23 -20
- package/dist/textarea/root/textarea-root.d.ts +14 -2
- package/dist/textarea/root/textarea-root.js +6 -7
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +10 -7
- package/dist/time-picker/root/time-picker-root.d.ts +12 -14
- package/dist/time-picker/root/time-picker-root.js +18 -23
- package/dist/toast/item/toast-item.d.ts +9 -6
- package/dist/toast/item/toast-item.js +1 -1
- package/dist/toast/root/toast-root.d.ts +40 -4
- package/dist/toast/root/toast-root.js +68 -16
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +29 -5
- package/dist/toggle/group/toggle-group.js +26 -43
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +52 -5
- package/dist/toolbar/root/toolbar-root.js +88 -13
- package/dist/tooltip/root/tooltip-root.d.ts +7 -1
- package/dist/tooltip/root/tooltip-root.js +10 -2
- package/dist/tour/root/tour-root.d.ts +15 -0
- package/dist/tour/root/tour-root.js +20 -1
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/root/tree-root.js +2 -2
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +41 -2
- package/dist/trend/root/trend-root.js +29 -3
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +16 -1
- package/dist/video/root/video-root.js +15 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -0
- package/dist/virtual-list/fill.js +9 -0
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +17 -1
- package/dist/virtual-list/plan.js +13 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
- package/dist/virtual-list/root/virtual-list-root.js +53 -41
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +4934 -954
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +946 -253
- package/dist/color-picker/swatches.d.ts +0 -12
- package/dist/color-picker/swatches.js +0 -26
- package/dist/rating/steps.d.ts +0 -7
- package/dist/rating/steps.js +0 -9
- package/dist/tooltip/focus-target.d.ts +0 -6
- package/dist/tooltip/focus-target.js +0 -9
|
@@ -4,33 +4,110 @@ 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, markRegion } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html, nothing } from 'lit';
|
|
7
|
+
import { customElement, HelixElement, markRegion, reportRuntime } from '@fusion.dev/helix-core';
|
|
8
|
+
import { css, html, nothing, } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { typedMarks } from '../../quote/marks.js';
|
|
10
11
|
let HelixHeadlessBlockquote = class HelixHeadlessBlockquote extends HelixElement {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
14
|
+
this.attribution = '';
|
|
13
15
|
this.cite = '';
|
|
16
|
+
this.marks = false;
|
|
17
|
+
this.warned = false;
|
|
18
|
+
this.citeWarned = false;
|
|
19
|
+
this.readPassage = () => {
|
|
20
|
+
if (!this.marks || this.warned) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const text = [...this.childNodes]
|
|
24
|
+
.filter((node) => !(node instanceof Element) || !node.slot)
|
|
25
|
+
.map((node) => node.textContent ?? '')
|
|
26
|
+
.join('')
|
|
27
|
+
.trim();
|
|
28
|
+
if (!typedMarks(text.charAt(0))) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.warned = true;
|
|
32
|
+
reportRuntime({
|
|
33
|
+
kind: 'typed-marks',
|
|
34
|
+
message: `<${this.localName} marks> starts with a typed quotation mark, and the element draws its own, so the mark shows twice. Take the typed mark out.`,
|
|
35
|
+
tag: this.localName,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
14
38
|
}
|
|
39
|
+
static { this.styles = css `
|
|
40
|
+
:host([marks]) [part='blockquote']::before {
|
|
41
|
+
content: open-quote / '';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:host([marks]) [part='blockquote']::after {
|
|
45
|
+
content: no-close-quote;
|
|
46
|
+
}
|
|
47
|
+
`; }
|
|
15
48
|
markEmpty() {
|
|
16
|
-
markRegion(this.renderRoot, 'attribution', ['attribution']
|
|
49
|
+
markRegion(this.renderRoot, 'attribution', ['attribution'], {
|
|
50
|
+
occupied: 'slot[name="attribution"] > *',
|
|
51
|
+
});
|
|
52
|
+
const named = !this.partNamed('attribution')?.hasAttribute('data-empty');
|
|
53
|
+
const figure = this.partNamed('figure');
|
|
54
|
+
if (named) {
|
|
55
|
+
figure?.setAttribute('role', 'figure');
|
|
56
|
+
figure?.setAttribute('aria-labelledby', 'attribution');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
figure?.removeAttribute('role');
|
|
60
|
+
figure?.removeAttribute('aria-labelledby');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
readCite() {
|
|
64
|
+
if (this.citeWarned || !/\S\s+\S/.test(this.cite || '')) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.citeWarned = true;
|
|
68
|
+
reportRuntime({
|
|
69
|
+
kind: 'cite-not-url',
|
|
70
|
+
message: `<${this.localName} cite="${this.cite}"> holds words, and \`cite\` takes the URL of the source. Put who said it in \`attribution\`.`,
|
|
71
|
+
tag: this.localName,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
firstUpdated(changed) {
|
|
75
|
+
super.firstUpdated(changed);
|
|
76
|
+
this.renderRoot.addEventListener('slotchange', this.readPassage);
|
|
17
77
|
}
|
|
18
78
|
updated(changed) {
|
|
19
79
|
super.updated(changed);
|
|
20
80
|
this.markEmpty();
|
|
81
|
+
if (changed.has('marks')) {
|
|
82
|
+
this.readPassage();
|
|
83
|
+
}
|
|
84
|
+
if (changed.has('cite')) {
|
|
85
|
+
this.readCite();
|
|
86
|
+
}
|
|
21
87
|
}
|
|
22
88
|
render() {
|
|
23
|
-
return html `<
|
|
89
|
+
return html `<div aria-labelledby="attribution" part="figure" role="figure">
|
|
24
90
|
<blockquote part="blockquote" cite=${this.cite || nothing}><slot></slot></blockquote>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
91
|
+
${this.renderAttribution()}
|
|
92
|
+
</div>`;
|
|
93
|
+
}
|
|
94
|
+
renderAttribution() {
|
|
95
|
+
return html `<div id="attribution" part="attribution"
|
|
96
|
+
><slot name="attribution" @slotchange=${() => this.markEmpty()}
|
|
97
|
+
>${this.attribution ? html `<span>${this.attribution}</span>` : nothing}</slot
|
|
98
|
+
></div
|
|
99
|
+
>`;
|
|
29
100
|
}
|
|
30
101
|
};
|
|
102
|
+
__decorate([
|
|
103
|
+
property()
|
|
104
|
+
], HelixHeadlessBlockquote.prototype, "attribution", void 0);
|
|
31
105
|
__decorate([
|
|
32
106
|
property()
|
|
33
107
|
], HelixHeadlessBlockquote.prototype, "cite", void 0);
|
|
108
|
+
__decorate([
|
|
109
|
+
property({ reflect: true, type: Boolean })
|
|
110
|
+
], HelixHeadlessBlockquote.prototype, "marks", void 0);
|
|
34
111
|
HelixHeadlessBlockquote = __decorate([
|
|
35
112
|
customElement('helix-headless-blockquote')
|
|
36
113
|
], HelixHeadlessBlockquote);
|
|
@@ -37,6 +37,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
37
37
|
* @csspart link - The crumb itself, which is an `<a>` where `href` is set.
|
|
38
38
|
* @csspart separator - The separator preceding the item.
|
|
39
39
|
* @csspart separator-mark - The chevron between crumbs, shown when no separator is slotted.
|
|
40
|
+
*
|
|
41
|
+
* @cssstate end - While the `end` slot holds something, so a stylesheet can join
|
|
42
|
+
* the label and what follows it into one control.
|
|
40
43
|
*/
|
|
41
44
|
export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
42
45
|
/**
|
|
@@ -74,6 +77,17 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
74
77
|
*/
|
|
75
78
|
target: string;
|
|
76
79
|
protected willUpdate(changed: PropertyValues): void;
|
|
80
|
+
protected updated(changed: PropertyValues): void;
|
|
81
|
+
/**
|
|
82
|
+
* Says whether anything sits after the label.
|
|
83
|
+
*
|
|
84
|
+
* A switcher's trigger in `end` makes the crumb a split control, and its
|
|
85
|
+
* label is drawn as the first half of it. No selector can ask a slot what was
|
|
86
|
+
* assigned to it, so this is script. Answered from a DOM, so the server
|
|
87
|
+
* writes the resting answer and the first client update corrects it.
|
|
88
|
+
*/
|
|
89
|
+
private markEnd;
|
|
90
|
+
private readonly handleEnd;
|
|
77
91
|
/**
|
|
78
92
|
* The mark between one crumb and the next.
|
|
79
93
|
*
|
|
@@ -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 } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, hostAria, slotFilled, slotNamed, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretRight } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -15,12 +15,22 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
15
15
|
this.current = false;
|
|
16
16
|
this.rel = '';
|
|
17
17
|
this.target = '';
|
|
18
|
+
this.handleEnd = () => {
|
|
19
|
+
this.markEnd();
|
|
20
|
+
};
|
|
18
21
|
}
|
|
19
22
|
willUpdate(changed) {
|
|
20
23
|
super.willUpdate(changed);
|
|
21
24
|
hostAria(this.internals, { role: 'listitem' });
|
|
22
25
|
this.internals.ariaCurrent = this.current ? 'page' : null;
|
|
23
26
|
}
|
|
27
|
+
updated(changed) {
|
|
28
|
+
super.updated(changed);
|
|
29
|
+
this.markEnd();
|
|
30
|
+
}
|
|
31
|
+
markEnd() {
|
|
32
|
+
this.toggleState('end', slotFilled(slotNamed(this.renderRoot, 'end')));
|
|
33
|
+
}
|
|
24
34
|
renderSeparator() {
|
|
25
35
|
return html `<slot name="separator"
|
|
26
36
|
><svg part="separator-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox}>
|
|
@@ -41,7 +51,7 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
41
51
|
rel=${this.rel || nothing}
|
|
42
52
|
>${label}</a
|
|
43
53
|
>`
|
|
44
|
-
: html `<span part="link">${label}</span>`}<slot name="end"></slot>`;
|
|
54
|
+
: html `<span part="link">${label}</span>`}<slot name="end" @slotchange=${this.handleEnd}></slot>`;
|
|
45
55
|
}
|
|
46
56
|
};
|
|
47
57
|
__decorate([
|
|
@@ -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 } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, fillTemplate, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { repeat } from 'lit/directives/repeat.js';
|
|
@@ -55,7 +55,7 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
55
55
|
><button
|
|
56
56
|
part="expand"
|
|
57
57
|
type="button"
|
|
58
|
-
aria-label=${this.expandLabel
|
|
58
|
+
aria-label=${fillTemplate(this.expandLabel, { count: String(folded) })}
|
|
59
59
|
@click=${this.expand}
|
|
60
60
|
>
|
|
61
61
|
…
|
|
@@ -18,13 +18,12 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
18
18
|
*
|
|
19
19
|
* The inner control is always `type="button"`, because a
|
|
20
20
|
* `<button type="submit">` inside a shadow root cannot submit a form outside
|
|
21
|
-
* it. To submit, the button
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* submit buttons apart.
|
|
21
|
+
* it. To submit, the button puts a hidden native submit button carrying its
|
|
22
|
+
* `name`, `value` and `form*` overrides into the form, calls
|
|
23
|
+
* `requestSubmit()` with it, which runs validation, unlike `submit()`, and
|
|
24
|
+
* takes it out again, as Shoelace and Web Awesome do. A `submit` listener
|
|
25
|
+
* reads that button as `event.submitter`, so `event.submitter.value` and
|
|
26
|
+
* `new FormData(form, event.submitter)` tell two submit buttons apart.
|
|
28
27
|
*
|
|
29
28
|
* As the first submit button in its form, it is the form's default button:
|
|
30
29
|
* Enter in a text field of the form presses it, as it presses a native one.
|
|
@@ -54,6 +53,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
54
53
|
*
|
|
55
54
|
* @csspart button - The inner control.
|
|
56
55
|
* @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.
|
|
56
|
+
* @csspart spinner - The ring a pending button turns, an empty element the styled button draws over the words. It is rendered only while the button is pending.
|
|
57
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.
|
|
58
58
|
*
|
|
59
59
|
* @cssstate pending - The button is pending: `pending` is set.
|
|
@@ -135,18 +135,13 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
135
135
|
/**
|
|
136
136
|
* Where this button's submission goes, overriding the form's own.
|
|
137
137
|
*
|
|
138
|
-
* **The five `form*` overrides
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* The whole submit algorithm runs synchronously inside `requestSubmit()`, so
|
|
147
|
-
* the window is one call and a `finally` closes it whether or not a listener
|
|
148
|
-
* refused. What a `submit` handler observes during that window is the form a
|
|
149
|
-
* native submitter would have given it, which is the point.
|
|
138
|
+
* **The five `form*` overrides ride on a native submit button that stands in
|
|
139
|
+
* for this one**, because `requestSubmit(submitter)` refuses the inner
|
|
140
|
+
* `<button>` twice over: it is `type="button"`, and it sits in this shadow
|
|
141
|
+
* root, so its form owner is not the consumer's form. The stand-in is a
|
|
142
|
+
* hidden `<button type="submit">` in the form for the one synchronous call,
|
|
143
|
+
* so the platform applies the overrides to that submission alone and leaves
|
|
144
|
+
* the form as it was. See `submitAs`.
|
|
150
145
|
*/
|
|
151
146
|
formAction: string;
|
|
152
147
|
/**
|
|
@@ -249,13 +244,10 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
249
244
|
* The value this button submits under its own `name`, as a native submit
|
|
250
245
|
* button does.
|
|
251
246
|
*
|
|
252
|
-
* **
|
|
247
|
+
* **Sent with exactly the submission this button starts and not otherwise.**
|
|
253
248
|
* A native submit button contributes `name=value` only when it is the one
|
|
254
|
-
* that submitted, and every other button on the form contributes nothing
|
|
255
|
-
*
|
|
256
|
-
* every submission whoever started it, which is a different feature wearing
|
|
257
|
-
* the same name, so `submit` below sets it, submits, and clears it inside one
|
|
258
|
-
* synchronous call.
|
|
249
|
+
* that submitted, and every other button on the form contributes nothing,
|
|
250
|
+
* which is what the native button standing in for this one at submit does.
|
|
259
251
|
*
|
|
260
252
|
* `CopyButton` has a `value` of its own meaning the text to put on the
|
|
261
253
|
* clipboard, which is not this and is why it is declared there rather than
|
|
@@ -263,19 +255,8 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
263
255
|
*/
|
|
264
256
|
value: string;
|
|
265
257
|
/**
|
|
266
|
-
* Submits the form as this button,
|
|
267
|
-
*
|
|
268
|
-
* Everything a native submitter carries is written onto the form, the
|
|
269
|
-
* submission is started, and everything is put back. See `formAction` for why
|
|
270
|
-
* `requestSubmit(submitter)` is not available to a control inside a shadow
|
|
271
|
-
* root.
|
|
272
|
-
*
|
|
273
|
-
* `novalidate` is in the same list rather than reached by `form.submit()`,
|
|
274
|
-
* which looks like the shortcut and is not: `submit()` skips the `submit`
|
|
275
|
-
* event as well as the validation, so a consumer's handler would stop running
|
|
276
|
-
* the moment somebody wrote `formnovalidate`. Turning the flag on and calling
|
|
277
|
-
* `requestSubmit()` skips the validation alone, which is what the attribute
|
|
278
|
-
* means.
|
|
258
|
+
* Submits the form as this button, through a native submit button carrying
|
|
259
|
+
* its name, value and overrides. See `formAction`.
|
|
279
260
|
*/
|
|
280
261
|
private submit;
|
|
281
262
|
/**
|
|
@@ -346,6 +327,11 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
346
327
|
/** Called by the browser when the button's form changes. */
|
|
347
328
|
formAssociatedCallback(form: HTMLFormElement | null): void;
|
|
348
329
|
protected render(): TemplateResult;
|
|
330
|
+
/**
|
|
331
|
+
* The ring a pending button turns, behind a seam a tier can move: an empty
|
|
332
|
+
* element, hidden from a screen reader, which hears `pending-label` instead.
|
|
333
|
+
*/
|
|
334
|
+
protected renderSpinner(): TemplateResult | typeof nothing;
|
|
349
335
|
}
|
|
350
336
|
declare global {
|
|
351
337
|
interface HTMLElementTagNameMap {
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
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
|
+
import { submitAs } from '../submitter.js';
|
|
10
11
|
let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
@@ -103,42 +104,7 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
submit(form) {
|
|
106
|
-
|
|
107
|
-
const override = (attribute, value) => {
|
|
108
|
-
if (value === null) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const had = form.getAttribute(attribute);
|
|
112
|
-
form.setAttribute(attribute, value);
|
|
113
|
-
undo.push(() => {
|
|
114
|
-
if (had === null) {
|
|
115
|
-
form.removeAttribute(attribute);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
form.setAttribute(attribute, had);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
override('action', this.formAction || null);
|
|
123
|
-
override('enctype', this.formEnctype || null);
|
|
124
|
-
override('method', this.formMethod || null);
|
|
125
|
-
override('novalidate', this.formNoValidate ? '' : null);
|
|
126
|
-
override('target', this.formTarget || null);
|
|
127
|
-
const reports = this.name !== '';
|
|
128
|
-
if (reports) {
|
|
129
|
-
this.internals.setFormValue(this.value);
|
|
130
|
-
}
|
|
131
|
-
try {
|
|
132
|
-
form.requestSubmit();
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
for (const put of undo) {
|
|
136
|
-
put();
|
|
137
|
-
}
|
|
138
|
-
if (reports) {
|
|
139
|
-
this.internals.setFormValue(null);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
107
|
+
submitAs(form, this);
|
|
142
108
|
}
|
|
143
109
|
get commandForElement() {
|
|
144
110
|
const button = this.renderRoot?.querySelector('button');
|
|
@@ -222,9 +188,12 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
222
188
|
@keydown=${this.notePress}
|
|
223
189
|
@pointerdown=${this.notePress}
|
|
224
190
|
>
|
|
225
|
-
${label}
|
|
191
|
+
${label}${this.renderSpinner()}
|
|
226
192
|
</button>${this.renderLive()}`;
|
|
227
193
|
}
|
|
194
|
+
renderSpinner() {
|
|
195
|
+
return this.pending ? html `<span part="spinner" aria-hidden="true"></span>` : nothing;
|
|
196
|
+
}
|
|
228
197
|
};
|
|
229
198
|
__decorate([
|
|
230
199
|
property()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Submitting a form through a native submit button that stands in for one in a
|
|
3
|
+
* shadow root.
|
|
4
|
+
*
|
|
5
|
+
* `requestSubmit(submitter)` takes only a native submit button whose form is
|
|
6
|
+
* the form, and a button inside a shadow root is neither. A hidden native
|
|
7
|
+
* `<button type="submit">` carrying the same name, value and `form*`
|
|
8
|
+
* overrides is put into the form for the one synchronous call, as Shoelace and
|
|
9
|
+
* Web Awesome do, so the platform does the rest: `event.submitter` is a
|
|
10
|
+
* button with the name and value, `new FormData(form, event.submitter)`
|
|
11
|
+
* includes them, and the overrides apply to that submission alone.
|
|
12
|
+
*/
|
|
13
|
+
/** What a submit button carries into the submission it starts. */
|
|
14
|
+
export interface Carried {
|
|
15
|
+
formAction: string;
|
|
16
|
+
formEnctype: string;
|
|
17
|
+
formMethod: string;
|
|
18
|
+
formNoValidate: boolean;
|
|
19
|
+
formTarget: string;
|
|
20
|
+
name: string;
|
|
21
|
+
value: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Submits `form` as a native submit button carrying `carried` would, and takes
|
|
25
|
+
* that button out again whether or not a listener refused the submission.
|
|
26
|
+
*/
|
|
27
|
+
export declare const submitAs: (form: HTMLFormElement, carried: Carried) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const submitAs = (form, carried) => {
|
|
2
|
+
const stand = form.ownerDocument.createElement('button');
|
|
3
|
+
stand.type = 'submit';
|
|
4
|
+
stand.hidden = true;
|
|
5
|
+
for (const [attribute, value] of [
|
|
6
|
+
['formaction', carried.formAction],
|
|
7
|
+
['formenctype', carried.formEnctype],
|
|
8
|
+
['formmethod', carried.formMethod],
|
|
9
|
+
['formtarget', carried.formTarget],
|
|
10
|
+
['name', carried.name],
|
|
11
|
+
]) {
|
|
12
|
+
if (value !== '') {
|
|
13
|
+
stand.setAttribute(attribute, value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
stand.value = carried.value;
|
|
17
|
+
stand.formNoValidate = carried.formNoValidate;
|
|
18
|
+
form.append(stand);
|
|
19
|
+
try {
|
|
20
|
+
form.requestSubmit(stand);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
stand.remove();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The index a key moves focus to, or `-1` for a key that moves nothing.
|
|
3
|
+
*
|
|
4
|
+
* Down and Up step forward and back, and Left and Right step by `step`, which
|
|
5
|
+
* core's `inlineStep` turns on a right-to-left page. Home and End go to the
|
|
6
|
+
* ends. A step wraps from the last button round to the first, as a toolbar's
|
|
7
|
+
* does.
|
|
8
|
+
*
|
|
9
|
+
* @param key The key pressed.
|
|
10
|
+
* @param step `1` or `-1` for Left and Right, from `inlineStep`, and `0` otherwise.
|
|
11
|
+
* @param from The index focus is on, or `-1` where it is on none of them.
|
|
12
|
+
* @param count How many buttons focus can move between.
|
|
13
|
+
*/
|
|
14
|
+
export declare const arrowTarget: (key: string, step: number, from: number, count: number) => number;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const arrowTarget = (key, step, from, count) => {
|
|
2
|
+
const by = key === 'ArrowDown' ? 1 : key === 'ArrowUp' ? -1 : step;
|
|
3
|
+
if (from < 0 || count === 0) {
|
|
4
|
+
return -1;
|
|
5
|
+
}
|
|
6
|
+
if (key === 'Home' || key === 'End') {
|
|
7
|
+
return key === 'Home' ? 0 : count - 1;
|
|
8
|
+
}
|
|
9
|
+
return by === 0 ? -1 : (from + by + count) % count;
|
|
10
|
+
};
|
|
@@ -9,19 +9,62 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
9
9
|
* controls, and a development build warns once with the kind `missing-name`.
|
|
10
10
|
*
|
|
11
11
|
* The group does not manage focus, so each button keeps its own tab stop. For
|
|
12
|
-
* one tab stop with arrow keys between
|
|
13
|
-
* use Toolbar.
|
|
12
|
+
* one tab stop with arrow keys between a mix of controls, the APG toolbar
|
|
13
|
+
* pattern, use Toolbar.
|
|
14
14
|
*
|
|
15
15
|
* Buttons are slotted, so they stay your own elements and keep their own
|
|
16
16
|
* appearance and size.
|
|
17
17
|
*
|
|
18
|
+
* **Buttons that stay pressed.** With `selection-mode`, each button with a
|
|
19
|
+
* `value` is a toggle button: a press presses or releases it, and it says so
|
|
20
|
+
* with `aria-pressed`. `single` keeps one pressed at a time, and a press on the
|
|
21
|
+
* pressed one releases it. `multiple` lets any number be pressed. `value` is
|
|
22
|
+
* the pressed values, comma separated. A press sends a cancelable
|
|
23
|
+
* `helix-before-change` with the value it would leave, then `change`.
|
|
24
|
+
*
|
|
25
|
+
* The pressed state is written on the control inside each button's shadow
|
|
26
|
+
* root, so the markup you rendered is never changed and a framework hydrating
|
|
27
|
+
* it sees what its server sent. That is also why only Helix buttons are
|
|
28
|
+
* toggles: a native `<button>` or a button without a `value` stays a plain
|
|
29
|
+
* action button in the group, and a native one without its own
|
|
30
|
+
* `aria-pressed` warns once, with the runtime kind `untold-toggle`. The inner
|
|
31
|
+
* control also carries
|
|
32
|
+
* `--button-group-pressed`, `1` or `0`, for a `::part(button)` rule of yours.
|
|
33
|
+
*
|
|
34
|
+
* Use Toggle Group instead for a choice that belongs in a form, or one where
|
|
35
|
+
* the arrow keys choose as they move: it is a `radiogroup` of options with a
|
|
36
|
+
* form value, `required` and validation. A Button Group in a selection mode is
|
|
37
|
+
* a set of actions that stay on, such as bold and italic, or a view that a
|
|
38
|
+
* press switches, and it submits nothing.
|
|
39
|
+
*
|
|
40
|
+
* **Keyboard.** In a selection mode the group is one tab stop: the button
|
|
41
|
+
* focus was last on, then the first pressed one, then the first one.
|
|
42
|
+
*
|
|
43
|
+
* | Key | What it does |
|
|
44
|
+
* |---|---|
|
|
45
|
+
* | Right, Down | Moves to the next button, from the last back to the first. |
|
|
46
|
+
* | Left, Up | Moves to the button before, from the first round to the last. |
|
|
47
|
+
* | Home, End | Moves to the first or the last button. |
|
|
48
|
+
* | Space, Enter | Presses or releases the focused button. |
|
|
49
|
+
*
|
|
50
|
+
* Left and Right swap on a right-to-left page, and a disabled button is
|
|
51
|
+
* passed over. In a selection mode the group is a `toolbar`, with
|
|
52
|
+
* `aria-orientation` under `orientation="vertical"`. Inside a toolbar it stays
|
|
53
|
+
* a named `group`, and the toolbar's own arrow keys walk its buttons, so a
|
|
54
|
+
* reader meets one toolbar.
|
|
55
|
+
*
|
|
18
56
|
* @since 0.1.0
|
|
19
57
|
* @status stable
|
|
20
58
|
* @category actions
|
|
21
|
-
* @aliases Segmented buttons, Split button
|
|
59
|
+
* @aliases Segmented buttons, Split button, Toggle buttons
|
|
22
60
|
* @documentation https://fusion.dev/helix/components/button-group
|
|
23
61
|
*
|
|
24
62
|
* @slot - The buttons in the group.
|
|
63
|
+
*
|
|
64
|
+
* @event {Event} change - Fired after a press changes `value`, in a selection mode.
|
|
65
|
+
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before a press changes `value`, with the value it would leave in `detail.value`. Cancelable: call `preventDefault()` to keep the buttons as they are.
|
|
66
|
+
*
|
|
67
|
+
* @cssproperty --button-group-pressed - Written on the control inside each toggle button of a group with `selection-mode`: `1` while it is pressed and `0` while it is not. Read it in a `::part(button)` rule to draw the pressed look.
|
|
25
68
|
*/
|
|
26
69
|
export declare class HelixHeadlessButtonGroup extends HelixElement {
|
|
27
70
|
/**
|
|
@@ -51,8 +94,103 @@ export declare class HelixHeadlessButtonGroup extends HelixElement {
|
|
|
51
94
|
* column.
|
|
52
95
|
*/
|
|
53
96
|
orientation?: 'horizontal' | 'vertical';
|
|
97
|
+
/**
|
|
98
|
+
* Whether the buttons stay pressed: `single` keeps one pressed at a time and
|
|
99
|
+
* `multiple` any number. Unset, they are action buttons, each its own tab
|
|
100
|
+
* stop, as before.
|
|
101
|
+
*
|
|
102
|
+
* Optional, so the attribute is absent until a consumer writes it.
|
|
103
|
+
*/
|
|
104
|
+
selectionMode?: 'multiple' | 'single';
|
|
105
|
+
/**
|
|
106
|
+
* The values of the pressed buttons, comma separated, in a selection mode.
|
|
107
|
+
* A button's own `value` names it, so a value holds no comma.
|
|
108
|
+
*
|
|
109
|
+
* The attribute is the seed, and a press changes the property, which does
|
|
110
|
+
* not reflect, as a native control's `value` does not.
|
|
111
|
+
*/
|
|
112
|
+
value: string;
|
|
113
|
+
/**
|
|
114
|
+
* The Helix buttons of a group in a selection mode, in the order they are
|
|
115
|
+
* written, and none otherwise. Empty on a server, which has no tree.
|
|
116
|
+
*/
|
|
117
|
+
private get buttons();
|
|
118
|
+
/**
|
|
119
|
+
* Whether the group holds the tab stop and the arrow keys: in a selection
|
|
120
|
+
* mode, and not inside a toolbar, whose own keys walk the buttons.
|
|
121
|
+
*/
|
|
122
|
+
private get roving();
|
|
123
|
+
/** Whether a button is pressed: its value is among the group's. */
|
|
124
|
+
private pressed;
|
|
125
|
+
/** The button focus was last on, which holds the tab stop. */
|
|
126
|
+
private lastFocused;
|
|
127
|
+
/**
|
|
128
|
+
* The buttons this group has told something, each with whether it moved
|
|
129
|
+
* their tab stop, so a button that leaves the group, or a group that leaves
|
|
130
|
+
* its selection mode, is put back as it was.
|
|
131
|
+
*/
|
|
132
|
+
private readonly told;
|
|
133
|
+
private watcher;
|
|
134
|
+
/**
|
|
135
|
+
* Tells every button whether it is pressed and whether it holds the stop,
|
|
136
|
+
* and puts back the ones that left.
|
|
137
|
+
*/
|
|
138
|
+
private sync;
|
|
139
|
+
/** Whether this group has said a native button in it cannot be a toggle, so it says so once. */
|
|
140
|
+
private warned;
|
|
141
|
+
/**
|
|
142
|
+
* Says once that a native `<button>` in a selection mode stays an action
|
|
143
|
+
* button, since its pressed state would be an attribute on the page's markup.
|
|
144
|
+
* One with its own `aria-pressed` is the page's to say, and is not reported.
|
|
145
|
+
*/
|
|
146
|
+
private warn;
|
|
147
|
+
/**
|
|
148
|
+
* Writes a button's pressed state onto its control, once the button has
|
|
149
|
+
* rendered it, and takes it off a button the group no longer holds.
|
|
150
|
+
*
|
|
151
|
+
* **On the control inside the button's shadow root, never on the button.**
|
|
152
|
+
* An attribute written on the consumer's element is a hydration mismatch a
|
|
153
|
+
* React consumer's hydration reports and does not patch up, which is why
|
|
154
|
+
* `tellDisclosure` hands a trigger `expanded` as a property. Inside the
|
|
155
|
+
* button's own shadow root no framework compares the attribute, and the
|
|
156
|
+
* reader is on that control. Read at the moment of the write, so the last
|
|
157
|
+
* press wins whatever order renders finish in.
|
|
158
|
+
*
|
|
159
|
+
* The control is the `<button>` a Helix button renders, which is where its
|
|
160
|
+
* `delegatesFocus` sends focus and what a reader is on.
|
|
161
|
+
*
|
|
162
|
+
* A button that carries `aria-pressed` itself is the consumer's to say, and
|
|
163
|
+
* its own forwarding carries that down instead.
|
|
164
|
+
*/
|
|
165
|
+
private mark;
|
|
166
|
+
/**
|
|
167
|
+
* Says on a button's control whether it is pressed, or that it is no toggle
|
|
168
|
+
* at all where `pressed` is undefined. A styled tier draws the look here.
|
|
169
|
+
*
|
|
170
|
+
* @param control The focusable control inside the button's shadow root.
|
|
171
|
+
* @param pressed Whether the button is pressed, or undefined where it is not a toggle.
|
|
172
|
+
*/
|
|
173
|
+
protected markPressed(control: HTMLElement, pressed: boolean | undefined): void;
|
|
174
|
+
/**
|
|
175
|
+
* Presses or releases the button a press acted on. `helix-press` rather than
|
|
176
|
+
* `click`, since a button sends it only for a press that acted: never while
|
|
177
|
+
* it is disabled or pending.
|
|
178
|
+
*/
|
|
179
|
+
private readonly handlePress;
|
|
180
|
+
/**
|
|
181
|
+
* Moves focus between the buttons without pressing them, a toolbar's
|
|
182
|
+
* reading: a press is its own act, on Space or Enter, which the button
|
|
183
|
+
* answers natively. Both axes, as every set here answers both, and the
|
|
184
|
+
* horizontal pair turns on a right-to-left page.
|
|
185
|
+
*/
|
|
186
|
+
private readonly handleKeydown;
|
|
187
|
+
/** Moves the tab stop to the button focus arrived on. */
|
|
188
|
+
private readonly noteFocus;
|
|
189
|
+
connectedCallback(): void;
|
|
190
|
+
disconnectedCallback(): void;
|
|
54
191
|
protected willUpdate(changed: PropertyValues): void;
|
|
55
192
|
protected firstUpdated(changed: PropertyValues): void;
|
|
193
|
+
protected updated(changed: PropertyValues): void;
|
|
56
194
|
protected render(): TemplateResult;
|
|
57
195
|
}
|
|
58
196
|
declare global {
|