@fusion.dev/helix-headless 0.154.0 → 0.156.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 +3213 -179
- package/dist/accordion/item/accordion-item.d.ts +15 -0
- package/dist/accordion/item/accordion-item.js +12 -1
- package/dist/accordion/root/accordion-root.d.ts +2 -1
- package/dist/accordion/root/accordion-root.js +1 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +36 -3
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +42 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +15 -5
- package/dist/breadcrumbs/root/breadcrumbs-root.js +29 -4
- package/dist/button-group/root/button-group-root.d.ts +2 -0
- package/dist/button-group/root/button-group-root.js +1 -0
- package/dist/canvas/node/canvas-node.js +1 -1
- package/dist/canvas/root/canvas-root.d.ts +17 -2
- package/dist/canvas/root/canvas-root.js +23 -6
- package/dist/chat/composer/chat-composer.js +1 -1
- package/dist/chat/root/chat-root.d.ts +14 -1
- package/dist/chat/root/chat-root.js +14 -4
- package/dist/color-input/root/color-input-root.d.ts +9 -3
- package/dist/color-input/root/color-input-root.js +3 -1
- package/dist/color-picker/channels.d.ts +5 -3
- package/dist/color-picker/channels.js +79 -21
- package/dist/color-picker/root/color-picker-root.d.ts +58 -5
- package/dist/color-picker/root/color-picker-root.js +75 -13
- package/dist/combobox/root/combobox-root.d.ts +10 -0
- package/dist/combobox/root/combobox-root.js +18 -3
- package/dist/command/root/command-root.d.ts +116 -1
- package/dist/command/root/command-root.js +124 -15
- package/dist/data-table/root/data-table-root.d.ts +25 -0
- package/dist/data-table/root/data-table-root.js +13 -3
- package/dist/date-input/root/date-input-root.d.ts +33 -1
- package/dist/date-input/root/date-input-root.js +9 -2
- package/dist/date-picker/root/date-picker-root.d.ts +43 -13
- package/dist/date-picker/root/date-picker-root.js +54 -31
- package/dist/element-events.generated.js +3 -1
- package/dist/graph/root/graph-root.d.ts +13 -0
- package/dist/graph/root/graph-root.js +16 -0
- package/dist/list/root/list-root.d.ts +74 -1
- package/dist/list/root/list-root.js +92 -4
- package/dist/list/selection.js +3 -3
- package/dist/map/root/map-root.d.ts +6 -0
- package/dist/map/root/map-root.js +8 -1
- package/dist/navigation/root/navigation-root.d.ts +26 -0
- package/dist/navigation/root/navigation-root.js +58 -1
- package/dist/number-input/root/number-input-root.d.ts +63 -6
- package/dist/number-input/root/number-input-root.js +96 -11
- package/dist/object-inspector/root/object-inspector-root.d.ts +36 -1
- package/dist/object-inspector/root/object-inspector-root.js +26 -2
- package/dist/option/root/option-root.d.ts +32 -0
- package/dist/option/root/option-root.js +44 -5
- package/dist/outline/root/outline-root.d.ts +6 -2
- package/dist/outline/root/outline-root.js +7 -3
- package/dist/select/root/select-root.d.ts +29 -3
- package/dist/select/root/select-root.js +34 -9
- package/dist/slider/root/slider-root.d.ts +71 -9
- package/dist/slider/root/slider-root.js +129 -42
- package/dist/speed-dial/item/speed-dial-item.d.ts +29 -1
- package/dist/speed-dial/item/speed-dial-item.js +48 -7
- package/dist/speed-dial/root/speed-dial-root.d.ts +32 -6
- package/dist/speed-dial/root/speed-dial-root.js +50 -5
- package/dist/splitter/root/splitter-root.d.ts +22 -0
- package/dist/splitter/root/splitter-root.js +36 -7
- package/dist/steps/reach.d.ts +5 -1
- package/dist/steps/reach.js +2 -2
- package/dist/steps/root/steps-root.d.ts +37 -2
- package/dist/steps/root/steps-root.js +49 -7
- package/dist/steps/step/step.d.ts +6 -0
- package/dist/steps/step/step.js +4 -0
- package/dist/table/root/table-root.d.ts +20 -0
- package/dist/table/root/table-root.js +13 -3
- package/dist/tabs/root/tabs-root.d.ts +37 -0
- package/dist/tabs/root/tabs-root.js +92 -2
- package/dist/tabs/tab/tab.d.ts +38 -2
- package/dist/tabs/tab/tab.js +45 -4
- package/dist/tag/group/tag-group.d.ts +29 -3
- package/dist/tag/group/tag-group.js +42 -11
- package/dist/time-input/root/time-input-root.d.ts +32 -1
- package/dist/time-input/root/time-input-root.js +9 -2
- package/dist/time-picker/root/time-picker-root.d.ts +63 -1
- package/dist/time-picker/root/time-picker-root.js +58 -7
- package/dist/timeline/item/timeline-item.d.ts +25 -0
- package/dist/timeline/item/timeline-item.js +27 -2
- package/dist/toggle/root/toggle-root.d.ts +2 -0
- package/dist/toggle/root/toggle-root.js +1 -1
- package/dist/tree/item/tree-item.d.ts +10 -0
- package/dist/tree/item/tree-item.js +12 -0
- package/dist/tree/root/tree-root.d.ts +40 -1
- package/dist/tree/root/tree-root.js +120 -4
- package/dist/tree/selection.d.ts +6 -0
- package/dist/tree/selection.js +11 -0
- package/dist/video/root/keys.d.ts +6 -2
- package/dist/video/root/keys.js +18 -1
- package/dist/video/root/video-root.d.ts +60 -1
- package/dist/video/root/video-root.js +70 -2
- package/dist/video-playlist/item/video-playlist-item.d.ts +15 -1
- package/dist/video-playlist/item/video-playlist-item.js +7 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +43 -4
- package/dist/video-playlist/root/video-playlist-root.js +69 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +8 -0
- package/dist/virtual-list/root/virtual-list-root.js +3 -0
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +3885 -383
- package/types/vue.d.ts +1045 -107
- package/types/words.d.ts +146 -1
|
@@ -25,6 +25,10 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
|
|
|
25
25
|
* and a closed section is `hidden` and `inert` instead, and find in page skips
|
|
26
26
|
* it.
|
|
27
27
|
*
|
|
28
|
+
* A section whose trigger has no words, with nothing in its `summary` slot,
|
|
29
|
+
* is announced as a bare button, and a development build warns once with the
|
|
30
|
+
* kind `missing-name`.
|
|
31
|
+
*
|
|
28
32
|
* While it is open, the content part carries the content's height as
|
|
29
33
|
* `--accordion-content-height`, as Radix's accordion does, for a stylesheet
|
|
30
34
|
* that animates the section open with keyframes of its own.
|
|
@@ -51,6 +55,7 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
|
|
|
51
55
|
*
|
|
52
56
|
* @cssproperty --accordion-content-height - The height of the content, in pixels, written on the `content` part while the section is open.
|
|
53
57
|
*
|
|
58
|
+
* @cssstate closing - While the item has closed and its content is still drawn, until the content part's animations end.
|
|
54
59
|
* @cssstate open - While the item is open.
|
|
55
60
|
*/
|
|
56
61
|
export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionItem_base {
|
|
@@ -88,6 +93,11 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
88
93
|
* for the reason `groupHeadingLevel` is a property.
|
|
89
94
|
*/
|
|
90
95
|
groupHiddenUntilFound: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* @internal The accordion's `mode`, written by the accordion, so the trigger
|
|
98
|
+
* of the open section says it cannot close under `single`.
|
|
99
|
+
*/
|
|
100
|
+
groupMode: 'single' | 'single-collapsible' | undefined;
|
|
91
101
|
/**
|
|
92
102
|
* The level of the heading around the trigger, from 1 to 6.
|
|
93
103
|
*
|
|
@@ -155,6 +165,7 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
155
165
|
* and runs before the next paint or key press.
|
|
156
166
|
*/
|
|
157
167
|
private readonly handleBeforeMatch;
|
|
168
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
158
169
|
/** Whether the item was open at the last update, and `undefined` before one. */
|
|
159
170
|
private wasOpen;
|
|
160
171
|
/**
|
|
@@ -239,6 +250,10 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
239
250
|
* the accessibility tree by itself, and an inert region is never searched.
|
|
240
251
|
* It leaves the region's own box in the tree, so a closed findable section
|
|
241
252
|
* drops `role="region"` and its name until it opens.
|
|
253
|
+
*
|
|
254
|
+
* Under `mode="single"` the open section's trigger is `aria-disabled`, as in
|
|
255
|
+
* Radix, because a press cannot close the last open section. It stays
|
|
256
|
+
* focusable, so the arrow keys still reach it.
|
|
242
257
|
*/
|
|
243
258
|
protected render(): TemplateResult;
|
|
244
259
|
}
|
|
@@ -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 { animationsFinished, closestInstance, customElement, HelixElement, headingLevel, MixinControllerOpen, onUnlessFalse, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { animationsFinished, auditName, closestInstance, customElement, HelixElement, headingLevel, MixinControllerOpen, onUnlessFalse, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretDown } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -18,6 +18,7 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
18
18
|
this.disabled = false;
|
|
19
19
|
this.groupHeadingLevel = undefined;
|
|
20
20
|
this.groupHiddenUntilFound = true;
|
|
21
|
+
this.groupMode = undefined;
|
|
21
22
|
this.closing = false;
|
|
22
23
|
this.handleBeforeMatch = (event) => {
|
|
23
24
|
if (this.open || this.requestOpen(true)) {
|
|
@@ -76,6 +77,7 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
76
77
|
if (changed.has('open')) {
|
|
77
78
|
this.closing = !this.open && changed.get('open') === true && this.findable;
|
|
78
79
|
}
|
|
80
|
+
this.toggleState('closing', this.closing);
|
|
79
81
|
}
|
|
80
82
|
finishClosing() {
|
|
81
83
|
void animationsFinished(this.partNamed('content')).then(() => {
|
|
@@ -84,6 +86,10 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
84
86
|
}
|
|
85
87
|
});
|
|
86
88
|
}
|
|
89
|
+
firstUpdated(changed) {
|
|
90
|
+
super.firstUpdated(changed);
|
|
91
|
+
auditName(this, () => this.renderRoot.querySelector(`#${TRIGGER_ID}`), 'Write its title in the `summary` slot.');
|
|
92
|
+
}
|
|
87
93
|
get accordion() {
|
|
88
94
|
return closestInstance(this, HelixHeadlessAccordion);
|
|
89
95
|
}
|
|
@@ -129,12 +135,14 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
129
135
|
const shown = open || this.closing;
|
|
130
136
|
const landmark = shown || !this.findable;
|
|
131
137
|
const level = headingLevel(this.headingLevel ?? this.groupHeadingLevel);
|
|
138
|
+
const locked = open && this.groupMode === 'single';
|
|
132
139
|
return html `
|
|
133
140
|
<div part="container">
|
|
134
141
|
<div part="heading" role="heading" aria-level=${level}>
|
|
135
142
|
<button
|
|
136
143
|
id=${TRIGGER_ID}
|
|
137
144
|
aria-controls=${CONTENT_ID}
|
|
145
|
+
aria-disabled=${locked ? 'true' : nothing}
|
|
138
146
|
aria-expanded=${open ? 'true' : 'false'}
|
|
139
147
|
part="trigger"
|
|
140
148
|
type="button"
|
|
@@ -175,6 +183,9 @@ __decorate([
|
|
|
175
183
|
__decorate([
|
|
176
184
|
property({ attribute: false })
|
|
177
185
|
], HelixHeadlessAccordionItem.prototype, "groupHiddenUntilFound", void 0);
|
|
186
|
+
__decorate([
|
|
187
|
+
property({ attribute: false })
|
|
188
|
+
], HelixHeadlessAccordionItem.prototype, "groupMode", void 0);
|
|
178
189
|
__decorate([
|
|
179
190
|
property({ attribute: 'heading-level', type: Number })
|
|
180
191
|
], HelixHeadlessAccordionItem.prototype, "headingLevel", void 0);
|
|
@@ -20,7 +20,8 @@ import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
|
20
20
|
* Keys, on a trigger: Up and Down Arrow move to the previous and the next
|
|
21
21
|
* trigger, and so do Left and Right, wrapping at the ends; Home and End go to
|
|
22
22
|
* the first and the last. Enter and Space open and close the section. Disabled
|
|
23
|
-
* sections are passed over.
|
|
23
|
+
* sections are passed over. Under `single` the open section's trigger is
|
|
24
|
+
* `aria-disabled`, because a press cannot close it.
|
|
24
25
|
*
|
|
25
26
|
* Each trigger is a button with `aria-expanded` and `aria-controls`, inside a
|
|
26
27
|
* heading, level 3 unless `heading-level` says otherwise, so the sections are
|
|
@@ -32,6 +32,7 @@ let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
|
|
|
32
32
|
whenHydrated(item, () => {
|
|
33
33
|
item.groupHeadingLevel = this.headingLevel;
|
|
34
34
|
item.groupHiddenUntilFound = this.hiddenUntilFound;
|
|
35
|
+
item.groupMode = this.mode;
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
38
|
if (this.mode === undefined) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { type CSSResultGroup, nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary One step in a breadcrumb trail.
|
|
5
5
|
*
|
|
@@ -11,8 +11,11 @@ import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'l
|
|
|
11
11
|
* Set `href` to make the whole crumb an anchor, which works with Enter, middle
|
|
12
12
|
* click, and the status bar, and before any JavaScript runs. A router cannot
|
|
13
13
|
* reach an anchor inside a shadow root, so intercept the click for client-side
|
|
14
|
-
* navigation, as with `Tree.Item` and `List.Item
|
|
15
|
-
*
|
|
14
|
+
* navigation, as with `Tree.Item` and `List.Item`: a plain press on the link
|
|
15
|
+
* sends `helix-select` with the `href` as its value first, and canceling it
|
|
16
|
+
* keeps the browser from following, so a client-side router follows it
|
|
17
|
+
* instead, as React Aria's `onAction` lets a router do. A press with a
|
|
18
|
+
* modifier opens the link where the browser opens it and sends nothing.
|
|
16
19
|
*
|
|
17
20
|
* Without `href`, the crumb renders a plain `<span>` around what you slot,
|
|
18
21
|
* including your own anchor.
|
|
@@ -37,12 +40,18 @@ import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'l
|
|
|
37
40
|
* @slot separator - Replaces the chevron shown before this item.
|
|
38
41
|
* @slot start - Content before the label, such as an icon.
|
|
39
42
|
*
|
|
43
|
+
* @event {HelixSelectEvent} helix-select - A plain press on the crumb's link, with its `href` as the value, before the browser follows it. Cancelable: cancel it to keep the browser from following, as a client-side router does.
|
|
44
|
+
*
|
|
45
|
+
* @csspart expand - The button after the first crumb of a folded slotted trail, which shows the folded crumbs.
|
|
46
|
+
* @csspart fold-separator - The chevron before that button.
|
|
40
47
|
* @csspart link - The crumb itself, which is an `<a>` where `href` is set.
|
|
41
48
|
* @csspart separator - The separator preceding the item.
|
|
42
49
|
* @csspart separator-mark - The chevron between crumbs, shown when no separator is slotted.
|
|
43
50
|
*
|
|
51
|
+
* @cssstate current - While the crumb is the current page, marked `current` or the last of a trail with none marked.
|
|
44
52
|
* @cssstate end - While the `end` slot holds something, so a stylesheet can join
|
|
45
53
|
* the label and what follows it into one control.
|
|
54
|
+
* @cssstate folded - While a trail longer than its `max-items` has folded the crumb away. It takes no room.
|
|
46
55
|
*/
|
|
47
56
|
export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
48
57
|
static styles: CSSResultGroup;
|
|
@@ -50,6 +59,18 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
50
59
|
* Marks this item as the page you are on.
|
|
51
60
|
*/
|
|
52
61
|
current: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* @internal Set by the trail: how many crumbs after this one a slotted trail
|
|
64
|
+
* longer than its `max-items` has folded, so this crumb draws the button
|
|
65
|
+
* that shows them. 0 draws none.
|
|
66
|
+
*/
|
|
67
|
+
fold: number;
|
|
68
|
+
/**
|
|
69
|
+
* @internal Set by the trail: whether this crumb is folded away.
|
|
70
|
+
*/
|
|
71
|
+
folded: boolean;
|
|
72
|
+
/** @internal Set by the trail: the name of the button that shows the folded crumbs. */
|
|
73
|
+
foldLabel: string;
|
|
53
74
|
/**
|
|
54
75
|
* The URL the crumb links to. The current page has none.
|
|
55
76
|
*
|
|
@@ -74,6 +95,8 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
74
95
|
* `current`, so this one is said to be the current page.
|
|
75
96
|
*/
|
|
76
97
|
implied: boolean;
|
|
98
|
+
/** @internal Set by the trail: what a press on the fold's button does. */
|
|
99
|
+
onFold: (() => void) | undefined;
|
|
77
100
|
/**
|
|
78
101
|
* The link's `rel` value, which describes how the linked page relates to this
|
|
79
102
|
* one.
|
|
@@ -86,6 +109,16 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
86
109
|
*/
|
|
87
110
|
target: string;
|
|
88
111
|
protected willUpdate(changed: PropertyValues): void;
|
|
112
|
+
/**
|
|
113
|
+
* Sends `helix-select` for a plain press on the link, and keeps the browser
|
|
114
|
+
* from following where it was canceled.
|
|
115
|
+
*/
|
|
116
|
+
private readonly handleLinkClick;
|
|
117
|
+
/**
|
|
118
|
+
* The button that shows the crumbs a slotted trail folded after this one,
|
|
119
|
+
* with a chevron before it, drawn after the crumb's own label.
|
|
120
|
+
*/
|
|
121
|
+
protected renderFold(): TemplateResult | typeof nothing;
|
|
89
122
|
protected updated(changed: PropertyValues): void;
|
|
90
123
|
/**
|
|
91
124
|
* Says whether anything sits after the label.
|
|
@@ -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, slotFilled, slotNamed, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, HelixSelectEvent, hostAria, plainClick, slotFilled, slotNamed, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretRight } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { css, html, nothing, } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -13,9 +13,21 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.current = false;
|
|
16
|
+
this.fold = 0;
|
|
17
|
+
this.folded = false;
|
|
18
|
+
this.foldLabel = '';
|
|
16
19
|
this.implied = false;
|
|
20
|
+
this.onFold = undefined;
|
|
17
21
|
this.rel = '';
|
|
18
22
|
this.target = '';
|
|
23
|
+
this.handleLinkClick = (event) => {
|
|
24
|
+
if (!plainClick(event)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!this.dispatchEvent(new HelixSelectEvent({ value: this.href ?? '' }))) {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
19
31
|
this.handleEnd = () => {
|
|
20
32
|
this.markEnd();
|
|
21
33
|
};
|
|
@@ -24,11 +36,29 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
24
36
|
:host(:first-child) [part='separator'] {
|
|
25
37
|
display: none;
|
|
26
38
|
}
|
|
39
|
+
|
|
40
|
+
:host(:state(folded)) {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
27
43
|
`; }
|
|
28
44
|
willUpdate(changed) {
|
|
29
45
|
super.willUpdate(changed);
|
|
30
46
|
hostAria(this.internals, { role: 'listitem' });
|
|
31
47
|
this.internals.ariaCurrent = this.current || this.implied ? 'page' : null;
|
|
48
|
+
this.toggleState('current', this.current || this.implied);
|
|
49
|
+
this.toggleState('folded', this.folded);
|
|
50
|
+
}
|
|
51
|
+
renderFold() {
|
|
52
|
+
if (this.fold === 0) {
|
|
53
|
+
return nothing;
|
|
54
|
+
}
|
|
55
|
+
return html `<span part="fold-separator" aria-hidden="true"
|
|
56
|
+
><svg data-mirror fill="currentColor" viewBox=${caretRight.viewBox}>
|
|
57
|
+
${unsafeSVG(caretRight.content)}
|
|
58
|
+
</svg></span
|
|
59
|
+
><button part="expand" type="button" aria-label=${this.foldLabel} @click=${() => this.onFold?.()}>
|
|
60
|
+
…
|
|
61
|
+
</button>`;
|
|
32
62
|
}
|
|
33
63
|
updated(changed) {
|
|
34
64
|
super.updated(changed);
|
|
@@ -55,14 +85,24 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
55
85
|
href=${this.href ?? ''}
|
|
56
86
|
target=${this.target || nothing}
|
|
57
87
|
rel=${this.rel || nothing}
|
|
88
|
+
@click=${this.handleLinkClick}
|
|
58
89
|
>${label}</a
|
|
59
90
|
>`
|
|
60
|
-
: html `<span part="link">${label}</span>`}<slot name="end" @slotchange=${this.handleEnd}></slot
|
|
91
|
+
: html `<span part="link">${label}</span>`}<slot name="end" @slotchange=${this.handleEnd}></slot>${this.renderFold()}`;
|
|
61
92
|
}
|
|
62
93
|
};
|
|
63
94
|
__decorate([
|
|
64
95
|
property({ reflect: true, type: Boolean })
|
|
65
96
|
], HelixHeadlessBreadcrumb.prototype, "current", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
property({ attribute: false })
|
|
99
|
+
], HelixHeadlessBreadcrumb.prototype, "fold", void 0);
|
|
100
|
+
__decorate([
|
|
101
|
+
property({ attribute: false })
|
|
102
|
+
], HelixHeadlessBreadcrumb.prototype, "folded", void 0);
|
|
103
|
+
__decorate([
|
|
104
|
+
property({ attribute: false })
|
|
105
|
+
], HelixHeadlessBreadcrumb.prototype, "foldLabel", void 0);
|
|
66
106
|
__decorate([
|
|
67
107
|
property({ reflect: true })
|
|
68
108
|
], HelixHeadlessBreadcrumb.prototype, "href", void 0);
|
|
@@ -35,11 +35,13 @@ export interface BreadcrumbItem {
|
|
|
35
35
|
* array of `{ label, href }`, drawn as crumbs in order, the last one as the
|
|
36
36
|
* current page. Slotted crumbs follow them. Use one way or the other in a trail.
|
|
37
37
|
*
|
|
38
|
-
* With `max-items`, a trail
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
38
|
+
* With `max-items`, a trail that is longer folds its middle into one place:
|
|
39
|
+
* the first crumb, a button, then the last `max-items` less one. The button is
|
|
40
|
+
* named by `expand-label` and shows the whole trail, moving focus to the first
|
|
41
|
+
* crumb it brought back. A trail drawn from `items` draws the button as a
|
|
42
|
+
* crumb of its own, and a new `items` folds again. A slotted trail hides the
|
|
43
|
+
* crumbs it folds, which take no room, and its first crumb draws the button
|
|
44
|
+
* after its link; a change to the crumbs folds again.
|
|
43
45
|
*
|
|
44
46
|
* **Keyboard.** Each crumb with an `href` is a link and one tab stop, and
|
|
45
47
|
* Enter follows it. The current page and the separators are not in the tab
|
|
@@ -58,6 +60,8 @@ export interface BreadcrumbItem {
|
|
|
58
60
|
* @csspart crumb - Each crumb drawn from `items`.
|
|
59
61
|
* @csspart crumb-collapsed - The crumb that holds the folded middle of a trail longer than `max-items`.
|
|
60
62
|
* @csspart crumb-current - The crumb drawn from `items` for the current page.
|
|
63
|
+
* @csspart crumb-expand - The fold button a crumb draws after the first crumb of a folded slotted trail. A trail drawn from `items` draws its fold as a crumb of its own, `crumb-collapsed`, so this one is never drawn there.
|
|
64
|
+
* @csspart crumb-fold-separator - The chevron before that button.
|
|
61
65
|
* @csspart crumb-link - The link, or the current page's words, of a crumb drawn from `items`.
|
|
62
66
|
* @csspart crumb-separator - The separator before a crumb drawn from `items`.
|
|
63
67
|
* @csspart crumb-separator-mark - The chevron before a crumb drawn from `items`.
|
|
@@ -98,6 +102,10 @@ export declare class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
|
98
102
|
maxItems?: number;
|
|
99
103
|
/** Whether a reader has asked to see the whole of a folded trail. */
|
|
100
104
|
private expanded;
|
|
105
|
+
/** The crumbs slotted into the trail, in order. */
|
|
106
|
+
private get slotted();
|
|
107
|
+
/** Shows the whole of a folded slotted trail and moves focus to the first crumb it brought back. */
|
|
108
|
+
private readonly unfold;
|
|
101
109
|
/** Shows the whole trail and moves focus to the first crumb it brought back. */
|
|
102
110
|
private readonly expand;
|
|
103
111
|
protected willUpdate(changed: PropertyValues): void;
|
|
@@ -110,6 +118,8 @@ export declare class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
|
110
118
|
* not reflect, so nothing is written onto your markup.
|
|
111
119
|
*/
|
|
112
120
|
private readonly markLast;
|
|
121
|
+
/** New crumbs fold again, as a new `items` does. */
|
|
122
|
+
private readonly handleSlotChange;
|
|
113
123
|
/** The crumbs `items` describes, each a crumb of this tier. */
|
|
114
124
|
protected renderItems(): TemplateResult | typeof nothing;
|
|
115
125
|
protected render(): TemplateResult;
|
|
@@ -17,6 +17,15 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
17
17
|
this.items = [];
|
|
18
18
|
this.label = 'Breadcrumb';
|
|
19
19
|
this.expanded = false;
|
|
20
|
+
this.unfold = () => {
|
|
21
|
+
this.expanded = true;
|
|
22
|
+
this.updateComplete.then(() => {
|
|
23
|
+
const crumb = this.slotted[1];
|
|
24
|
+
const link = crumb?.shadowRoot?.querySelector('a[part="link"]') ??
|
|
25
|
+
crumb?.querySelector('a[href]');
|
|
26
|
+
link?.focus();
|
|
27
|
+
});
|
|
28
|
+
};
|
|
20
29
|
this.expand = () => {
|
|
21
30
|
this.expanded = true;
|
|
22
31
|
this.updateComplete.then(() => {
|
|
@@ -25,16 +34,32 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
25
34
|
});
|
|
26
35
|
};
|
|
27
36
|
this.markLast = () => {
|
|
28
|
-
const crumbs =
|
|
37
|
+
const crumbs = this.slotted;
|
|
29
38
|
const marked = crumbs.some((one) => one.current);
|
|
39
|
+
const most = this.maxItems ?? 0;
|
|
40
|
+
const fold = !this.expanded && this.items.length === 0 && most >= 2 && crumbs.length > most
|
|
41
|
+
? crumbs.length - most
|
|
42
|
+
: 0;
|
|
43
|
+
const label = fold > 0 ? formatWords(this, 'expandLabel', { count: fold }) : '';
|
|
30
44
|
crumbs.forEach((crumb, index) => {
|
|
31
45
|
whenHydrated(crumb, () => {
|
|
32
46
|
crumb.implied = !marked && this.items.length === 0 && index === crumbs.length - 1;
|
|
47
|
+
crumb.folded = index > 0 && index <= fold;
|
|
48
|
+
crumb.fold = index === 0 ? fold : 0;
|
|
49
|
+
crumb.foldLabel = index === 0 ? label : '';
|
|
50
|
+
crumb.onFold = index === 0 && fold > 0 ? this.unfold : undefined;
|
|
33
51
|
});
|
|
34
52
|
});
|
|
35
53
|
};
|
|
54
|
+
this.handleSlotChange = () => {
|
|
55
|
+
this.expanded = false;
|
|
56
|
+
this.markLast();
|
|
57
|
+
};
|
|
36
58
|
}
|
|
37
59
|
static { this.words = 'helix-breadcrumbs'; }
|
|
60
|
+
get slotted() {
|
|
61
|
+
return (this.renderRoot?.querySelector('slot:not([name])')?.assignedElements() ?? []).filter((one) => one instanceof HelixHeadlessBreadcrumb);
|
|
62
|
+
}
|
|
38
63
|
willUpdate(changed) {
|
|
39
64
|
super.willUpdate(changed);
|
|
40
65
|
hostAria(this.internals, { label: this.label, role: 'navigation' });
|
|
@@ -65,7 +90,7 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
65
90
|
? nothing
|
|
66
91
|
: html `<${crumb}
|
|
67
92
|
part="crumb crumb-collapsed"
|
|
68
|
-
exportparts="link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
93
|
+
exportparts="expand: crumb-expand, fold-separator: crumb-fold-separator, link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
69
94
|
><button
|
|
70
95
|
part="expand"
|
|
71
96
|
type="button"
|
|
@@ -79,7 +104,7 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
79
104
|
const rest = shown.slice(1);
|
|
80
105
|
const draw = ({ index, item }) => html `<${crumb}
|
|
81
106
|
part="crumb${index === last ? ' crumb-current' : ''}"
|
|
82
|
-
exportparts="link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
107
|
+
exportparts="expand: crumb-expand, fold-separator: crumb-fold-separator, link: crumb-link, separator: crumb-separator, separator-mark: crumb-separator-mark"
|
|
83
108
|
href=${index === last ? nothing : (item.href ?? nothing)}
|
|
84
109
|
rel=${item.rel ?? nothing}
|
|
85
110
|
target=${item.target ?? nothing}
|
|
@@ -90,7 +115,7 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
90
115
|
}
|
|
91
116
|
render() {
|
|
92
117
|
return html `<ol part="list" role="list">
|
|
93
|
-
${this.renderItems()}<slot @slotchange=${this.
|
|
118
|
+
${this.renderItems()}<slot @slotchange=${this.handleSlotChange}></slot>
|
|
94
119
|
</ol>`;
|
|
95
120
|
}
|
|
96
121
|
};
|
|
@@ -65,6 +65,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
65
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
66
|
*
|
|
67
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.
|
|
68
|
+
*
|
|
69
|
+
* @cssstate pressed - While a group with `selection-mode` has a button pressed.
|
|
68
70
|
*/
|
|
69
71
|
export declare class HelixHeadlessButtonGroup extends HelixElement {
|
|
70
72
|
/**
|
|
@@ -145,6 +145,7 @@ let HelixHeadlessButtonGroup = class HelixHeadlessButtonGroup extends HelixEleme
|
|
|
145
145
|
const toolbar = this.roving;
|
|
146
146
|
hostAria(this.internals, { label: this.label, role: toolbar ? 'toolbar' : 'group' });
|
|
147
147
|
this.internals.ariaOrientation = toolbar ? (this.orientation ?? null) : null;
|
|
148
|
+
this.toggleState('pressed', Boolean(this.selectionMode) && commaList(this.value).length > 0);
|
|
148
149
|
}
|
|
149
150
|
firstUpdated(changed) {
|
|
150
151
|
super.firstUpdated(changed);
|
|
@@ -77,7 +77,7 @@ let HelixHeadlessCanvasNode = class HelixHeadlessCanvasNode extends HelixElement
|
|
|
77
77
|
aria-describedby=${this.status || this.meaning || this.links ? 'about' : nothing}
|
|
78
78
|
aria-label=${this.label || nothing}
|
|
79
79
|
aria-labelledby=${this.label || this.group ? nothing : 'content'}
|
|
80
|
-
aria-keyshortcuts=${this.connectable ? 'Enter F2 Space Shift+ArrowRight Shift+ArrowDown Alt+ArrowRight Alt+ArrowDown C Delete' : nothing}
|
|
80
|
+
aria-keyshortcuts=${this.connectable ? 'Enter F2 Space Control+ArrowDown Control+ArrowUp Shift+ArrowRight Shift+ArrowDown Alt+ArrowRight Alt+ArrowDown C Delete' : nothing}
|
|
81
81
|
role=${this.group ? 'group' : 'article'}
|
|
82
82
|
tabindex=${this.current ? '0' : '-1'}
|
|
83
83
|
>
|
|
@@ -46,6 +46,10 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
|
|
|
46
46
|
* - One card holds the board's tab stop.
|
|
47
47
|
* - The arrow keys move through the cards in reading order. The card you land
|
|
48
48
|
* on scrolls into view, and its connections are announced with it.
|
|
49
|
+
* - The card you land on is selected. Control or Command with an arrow key,
|
|
50
|
+
* Home, or End moves without changing the selection, and Space adds the card
|
|
51
|
+
* to the selection or takes it out, so you can select cards that are not
|
|
52
|
+
* next to each other.
|
|
49
53
|
* - Shift with an arrow key moves the card: by 16 units, or to the next
|
|
50
54
|
* multiple of `snap` where it is set. Alt with an arrow key resizes it from
|
|
51
55
|
* its bottom right corner the same way.
|
|
@@ -143,6 +147,8 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
|
|
|
143
147
|
* @csspart zoom-in - The button that zooms in.
|
|
144
148
|
* @csspart zoom-out - The button that zooms out.
|
|
145
149
|
*
|
|
150
|
+
* @cssproperty --canvas-zoom - The board's zoom, which the board writes: 1 at the document's own size, 0.5 at half. The cards inherit it, so a card's stylesheet can draw less when the board is far out, such as a border that stays one pixel wide at `calc(1px / var(--canvas-zoom))`.
|
|
151
|
+
*
|
|
146
152
|
* @cssstate connecting - While you draw a connection.
|
|
147
153
|
* @cssstate direct - The board moves without easing, while you drag it or while it settles into its box.
|
|
148
154
|
* @cssstate empty - While the document has no nodes.
|
|
@@ -271,14 +277,21 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
|
|
|
271
277
|
* units.
|
|
272
278
|
*/
|
|
273
279
|
resizedLabel: string;
|
|
280
|
+
/**
|
|
281
|
+
* What a screen reader calls the board in place of its role, after its
|
|
282
|
+
* name: "Release plan, canvas". Said only where the board has a name of its
|
|
283
|
+
* own, since the fallback name is the same word. Empty leaves the role.
|
|
284
|
+
*/
|
|
285
|
+
roleLabel: string;
|
|
274
286
|
/**
|
|
275
287
|
* The names of the selected cards and connections, comma separated. Empty
|
|
276
288
|
* when nothing is selected.
|
|
277
289
|
*
|
|
278
290
|
* **Comma separated, the way `Listbox` writes a multiple value**, so a page
|
|
279
291
|
* reads one selection the same way wherever it comes from. A click, or a key
|
|
280
|
-
* that lands on one, selects it alone;
|
|
281
|
-
*
|
|
292
|
+
* that lands on one, selects it alone; Command or Control with an arrow key
|
|
293
|
+
* moves without selecting; Shift, Command or Control with a click adds or
|
|
294
|
+
* takes one away, and so does Space; Command or Control with A
|
|
282
295
|
* selects everything; Shift and a drag across the empty board selects the
|
|
283
296
|
* cards the box touches. A click on the empty board, or Escape, selects
|
|
284
297
|
* nothing. Dragging, Shift with an arrow, and Delete act on the whole
|
|
@@ -882,6 +895,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
|
|
|
882
895
|
* asks for it and Escape stops.
|
|
883
896
|
*/
|
|
884
897
|
private readonly handleStopKeydown;
|
|
898
|
+
/** Whether the stop focus is moving to keeps the selection as it is. */
|
|
899
|
+
private walkingApart;
|
|
885
900
|
/**
|
|
886
901
|
* A stop a reader landed on becomes the tab stop, and a card comes into view.
|
|
887
902
|
*
|
|
@@ -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 { assignSlots, capturePointer, customElement, formatPercent, formatWords, HelixBeforeMoveEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixConnectEvent, HelixElement, HelixMoveEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixSelectEvent, hostAria, inlineStep, isRtl, MixinViewport, words, wordsConverter, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { assignSlots, auditName, capturePointer, customElement, formatPercent, formatWords, HelixBeforeMoveEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixConnectEvent, HelixElement, HelixMoveEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixSelectEvent, hostAria, inlineStep, isRtl, MixinViewport, words, wordsConverter, wordsLocale, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { descriptionOf } from '../describe.js';
|
|
@@ -57,6 +57,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
57
57
|
this.readOnly = false;
|
|
58
58
|
this.reconnectingLabel = 'Moving the end of the connection from {from} to {to}. Move to a card and press Enter, or Escape to stop.';
|
|
59
59
|
this.resizedLabel = '{name} resized to {width} by {height}';
|
|
60
|
+
this.roleLabel = 'canvas';
|
|
60
61
|
this.selected = '';
|
|
61
62
|
this.selectedLabel = 'selected';
|
|
62
63
|
this.selectionLabel = '{count} selected';
|
|
@@ -592,8 +593,15 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
592
593
|
return;
|
|
593
594
|
}
|
|
594
595
|
event.preventDefault();
|
|
595
|
-
this.
|
|
596
|
+
this.walkingApart = event.ctrlKey || event.metaKey;
|
|
597
|
+
try {
|
|
598
|
+
this.focusStop(walk[to]?.key);
|
|
599
|
+
}
|
|
600
|
+
finally {
|
|
601
|
+
this.walkingApart = false;
|
|
602
|
+
}
|
|
596
603
|
};
|
|
604
|
+
this.walkingApart = false;
|
|
597
605
|
this.handleFocusIn = (event) => {
|
|
598
606
|
const edge = this.edgeOf(event);
|
|
599
607
|
const card = edge === undefined ? this.cardOf(event) : undefined;
|
|
@@ -603,7 +611,10 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
603
611
|
this.refocus = undefined;
|
|
604
612
|
this.focusedCard = card;
|
|
605
613
|
this.stop = edge ?? card?.name;
|
|
606
|
-
if (!this.pointing &&
|
|
614
|
+
if (!this.pointing &&
|
|
615
|
+
!this.walkingApart &&
|
|
616
|
+
this.stop !== undefined &&
|
|
617
|
+
!this.picked.includes(this.stop)) {
|
|
607
618
|
this.choose(this.stop);
|
|
608
619
|
}
|
|
609
620
|
if (card) {
|
|
@@ -1650,6 +1661,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
1650
1661
|
firstUpdated(changed) {
|
|
1651
1662
|
super.firstUpdated(changed);
|
|
1652
1663
|
this.finishHydration();
|
|
1664
|
+
auditName(this, () => null, 'Give it a `label` that says what the board holds, such as "Release plan".', () => this.label !== '');
|
|
1653
1665
|
if (this.waiting) {
|
|
1654
1666
|
this.measured = this.box;
|
|
1655
1667
|
this.view = this.waiting;
|
|
@@ -1941,7 +1953,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
1941
1953
|
d=${drawn.d}
|
|
1942
1954
|
data-edge=${key}
|
|
1943
1955
|
fill="none"
|
|
1944
|
-
aria-keyshortcuts="Enter F2 C Delete"
|
|
1956
|
+
aria-keyshortcuts="Enter F2 Space Control+ArrowDown Control+ArrowUp C Delete"
|
|
1945
1957
|
role="button"
|
|
1946
1958
|
tabindex=${key === stop ? '0' : '-1'}
|
|
1947
1959
|
/>
|
|
@@ -2050,7 +2062,8 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
2050
2062
|
return html `<div
|
|
2051
2063
|
part="region"
|
|
2052
2064
|
role="group"
|
|
2053
|
-
aria-label=${this.label || this.fallbackLabel}
|
|
2065
|
+
aria-label=${this.label || this.getAttribute?.('aria-label') || this.fallbackLabel}
|
|
2066
|
+
aria-roledescription=${(this.label || this.getAttribute?.('aria-label')) && this.roleLabel ? this.roleLabel : nothing}
|
|
2054
2067
|
aria-keyshortcuts="ArrowUp ArrowDown ArrowLeft ArrowRight Plus Minus"
|
|
2055
2068
|
tabindex="0"
|
|
2056
2069
|
@focusin=${this.idle.stir}
|
|
@@ -2063,7 +2076,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
2063
2076
|
</div>
|
|
2064
2077
|
<div
|
|
2065
2078
|
part="viewport"
|
|
2066
|
-
style=${`--_canvas-x: ${this.at.x}px; --_canvas-y: ${this.at.y}px; --_canvas-zoom: ${this.at.zoom}; --_canvas-rule-x: ${this.at.x - origin.x * this.at.zoom}px; --_canvas-rule-y: ${this.at.y - origin.y * this.at.zoom}px; --_canvas-rule-zoom: ${ruling(this.at.zoom)}`}
|
|
2079
|
+
style=${`--_canvas-x: ${this.at.x}px; --_canvas-y: ${this.at.y}px; --_canvas-zoom: ${this.at.zoom}; --canvas-zoom: ${this.at.zoom}; --_canvas-rule-x: ${this.at.x - origin.x * this.at.zoom}px; --_canvas-rule-y: ${this.at.y - origin.y * this.at.zoom}px; --_canvas-rule-zoom: ${ruling(this.at.zoom)}`}
|
|
2067
2080
|
@wheel=${this.handleWheel}
|
|
2068
2081
|
>
|
|
2069
2082
|
<!-- **One shape, whatever the board holds**, which is what hydration
|
|
@@ -2175,6 +2188,10 @@ __decorate([
|
|
|
2175
2188
|
words,
|
|
2176
2189
|
property({ attribute: 'resized-label' })
|
|
2177
2190
|
], HelixHeadlessCanvas.prototype, "resizedLabel", void 0);
|
|
2191
|
+
__decorate([
|
|
2192
|
+
words,
|
|
2193
|
+
property({ attribute: 'role-label' })
|
|
2194
|
+
], HelixHeadlessCanvas.prototype, "roleLabel", void 0);
|
|
2178
2195
|
__decorate([
|
|
2179
2196
|
property()
|
|
2180
2197
|
], HelixHeadlessCanvas.prototype, "selected", void 0);
|
|
@@ -105,7 +105,7 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixFor
|
|
|
105
105
|
super.updated(changed);
|
|
106
106
|
this.markEmpty();
|
|
107
107
|
if (changed.has('value')) {
|
|
108
|
-
this.internals.setFormValue(this.value === '' ? null : this.value);
|
|
108
|
+
this.internals.setFormValue(this.value === '' ? null : this.value, this.value);
|
|
109
109
|
}
|
|
110
110
|
const field = this.partNamed('field');
|
|
111
111
|
if (field?.validity) {
|
|
@@ -40,7 +40,8 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
40
40
|
* The log is `aria-live="off"`. A separate status region announces each new
|
|
41
41
|
* turn once, when it has finished arriving. It skips the user's own turns
|
|
42
42
|
* unless they failed to send, turns loaded as history, and the turns already
|
|
43
|
-
* there when the transcript opened.
|
|
43
|
+
* there when the transcript opened. A turn is said with its author first, such
|
|
44
|
+
* as "Ada: It ships today" (`arrival-label`), where its author can be named.
|
|
44
45
|
*
|
|
45
46
|
* Pass the turns as children or as `turns` data. Do not use both. Children
|
|
46
47
|
* render from the server and suit most conversations. `turns` draws a long
|
|
@@ -145,6 +146,13 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
145
146
|
static shadowRootOptions: ShadowRootInit;
|
|
146
147
|
/** How tall a turn is assumed to be before it has been drawn, in pixels. */
|
|
147
148
|
static readonly ESTIMATE = 72;
|
|
149
|
+
/**
|
|
150
|
+
* What a screen reader hears when a turn arrives. `{author}` is who wrote
|
|
151
|
+
* it, as its name says it, and `{text}` its words. A turn with no author a
|
|
152
|
+
* reader can be told, a turn by `them` with no `author-label`, says its
|
|
153
|
+
* words alone.
|
|
154
|
+
*/
|
|
155
|
+
arrivalLabel: string;
|
|
148
156
|
/**
|
|
149
157
|
* Declarations for the turns from `turns` by each author, keyed by `author`,
|
|
150
158
|
* as JSON in the attribute: `{"ada": "--chat-message-background-color: …"}`.
|
|
@@ -430,6 +438,11 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
430
438
|
private announce;
|
|
431
439
|
/** The turns after the newest one already accounted for, by the rules above. */
|
|
432
440
|
private arrived;
|
|
441
|
+
/**
|
|
442
|
+
* What is said for a turn: a failed one with `failed-turn-label`, and
|
|
443
|
+
* another with `arrival-label` where its author can be named, so a reader
|
|
444
|
+
* in a conversation of several knows who spoke.
|
|
445
|
+
*/
|
|
433
446
|
private phrase;
|
|
434
447
|
/** Watches what is drawn for size, re-observing only when that changed. */
|
|
435
448
|
private watchSizes;
|