@fusion.dev/helix-headless 0.53.0 → 0.53.2
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 +141 -141
- package/dist/accordion/item/accordion-item.d.ts +13 -13
- package/dist/accordion/root/accordion-root.d.ts +1 -1
- package/dist/area-chart/root/area-chart-root.js +1 -1
- package/dist/avatar/group/avatar-group.d.ts +11 -11
- package/dist/bar-chart/root/bar-chart-root.d.ts +1 -1
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +6 -6
- package/dist/button/root/button-root.d.ts +1 -1
- package/dist/card/root/card-root.d.ts +1 -1
- package/dist/carousel/root/carousel-root.d.ts +14 -14
- package/dist/chat/composer/chat-composer.d.ts +6 -6
- package/dist/chat/root/chat-root.d.ts +9 -9
- package/dist/checkbox/root/checkbox-root.d.ts +2 -2
- package/dist/checkbox/root/checkbox-root.js +1 -1
- package/dist/code-block/root/code-block-root.d.ts +5 -5
- package/dist/color-input/root/color-input-root.d.ts +3 -3
- package/dist/color-picker/root/color-picker-root.d.ts +14 -14
- package/dist/combobox/root/combobox-root.d.ts +25 -5
- package/dist/combobox/root/combobox-root.js +6 -4
- package/dist/command/root/command-root.d.ts +6 -7
- package/dist/data-table/root/data-table-root.d.ts +61 -38
- package/dist/data-table/root/data-table-root.js +8 -3
- package/dist/data-table/root/order.d.ts +3 -3
- package/dist/date-input/root/date-input-root.d.ts +12 -11
- package/dist/dialog/root/dialog-root.d.ts +4 -4
- package/dist/drawer/root/drawer-root.d.ts +5 -5
- package/dist/filter-input/menu/filter-menu.d.ts +7 -1
- package/dist/filter-input/menu/filter-menu.js +2 -1
- package/dist/filter-input/root/filter-input-root.d.ts +6 -6
- package/dist/format-date/root/format-date-root.d.ts +6 -5
- package/dist/heatmap/root/heatmap-root.d.ts +11 -16
- package/dist/image/root/image-root.d.ts +4 -4
- package/dist/input/root/input-root.d.ts +7 -7
- package/dist/line-chart/root/line-chart-root.d.ts +1 -2
- package/dist/list/item/list-item.d.ts +6 -7
- package/dist/list/root/list-root.d.ts +4 -4
- package/dist/megamenu/root/megamenu-root.d.ts +4 -4
- package/dist/notifications/notification/notification.d.ts +10 -10
- package/dist/notifications/root/notifications-root.d.ts +1 -1
- package/dist/option/root/option-root.d.ts +3 -3
- package/dist/pagination/root/pagination-root.d.ts +2 -2
- package/dist/pin-input/root/pin-input-root.d.ts +4 -4
- package/dist/popover/root/popover-root.d.ts +7 -6
- package/dist/radio/root/radio-root.d.ts +12 -2
- package/dist/radio/root/radio-root.js +5 -1
- package/dist/select/root/select-root.d.ts +24 -0
- package/dist/select/root/select-root.js +4 -1
- package/dist/speed-dial/root/speed-dial-root.d.ts +8 -9
- package/dist/stat/root/stat-root.d.ts +3 -3
- package/dist/steps/root/steps-root.d.ts +1 -1
- package/dist/steps/step/step.d.ts +5 -5
- package/dist/switch/root/switch-root.js +1 -1
- package/dist/table/column/table-column.d.ts +28 -28
- package/dist/table/root/table-root.d.ts +14 -17
- package/dist/table/row/table-row.d.ts +4 -4
- package/dist/tabs/panel/tab-panel.d.ts +2 -2
- package/dist/tabs/root/tabs-root.js +11 -4
- package/dist/tabs/tab/tab.d.ts +11 -1
- package/dist/tabs/tab/tab.js +5 -1
- package/dist/time-input/root/time-input-root.d.ts +13 -13
- package/dist/time-picker/root/time-picker-root.d.ts +8 -8
- package/dist/toast/root/toast-root.d.ts +2 -2
- package/dist/toggle/root/toggle-root.d.ts +16 -6
- package/dist/toggle/root/toggle-root.js +5 -1
- package/dist/tooltip/root/tooltip-root.d.ts +2 -2
- package/dist/tour/stop/tour-stop.d.ts +3 -3
- package/dist/tree/item/tree-item.d.ts +2 -2
- package/dist/tree/item/tree-item.js +4 -3
- package/dist/tree/root/tree-root.d.ts +8 -7
- package/dist/tree/root/tree-root.js +9 -5
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +7 -1
- package/dist/video-playlist/menu/video-playlist-menu.js +4 -2
- package/dist/video-playlist/root/video-playlist-root.d.ts +5 -5
- package/dist/video-playlist/root/video-playlist-root.js +2 -3
- package/package.json +5 -5
- package/types/jsx.d.ts +754 -780
- package/types/vue.d.ts +172 -185
|
@@ -111,25 +111,25 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
|
|
|
111
111
|
* pixel of it on the screen, so a consumer taking this tier gets sections of
|
|
112
112
|
* text permanently open under a trigger saying `aria-expanded="false"`, and a
|
|
113
113
|
* sighted reader sees content a screen reader is told is not there. Leaving
|
|
114
|
-
* the collapse to
|
|
115
|
-
*
|
|
114
|
+
* the collapse to a `grid-template-rows: 0fr` puts the state in a stylesheet,
|
|
115
|
+
* where only the consumers who load that sheet have it.
|
|
116
116
|
*
|
|
117
|
-
* **`hidden` costs
|
|
118
|
-
* cheap fix rather than a trade. The UA sheet hides `[hidden]`
|
|
119
|
-
* origin,
|
|
120
|
-
*
|
|
121
|
-
*
|
|
117
|
+
* **`hidden` costs a sheet that animates this region nothing**, which is what
|
|
118
|
+
* makes this the cheap fix rather than a trade. The UA sheet hides `[hidden]`
|
|
119
|
+
* from the UA origin, so any author rule already setting `display` on this
|
|
120
|
+
* part outranks it and the transition runs exactly as before. Measured on
|
|
121
|
+
* both tiers.
|
|
122
122
|
*
|
|
123
123
|
* **Not `hidden="until-found"`**, which would be the better accordion and is
|
|
124
124
|
* a different piece of work. It hides through `content-visibility` rather
|
|
125
|
-
* than `display`,
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
125
|
+
* than `display`, which an author `display` does not override, so a collapsed
|
|
126
|
+
* section a sheet animates would open to nothing. It also needs a
|
|
127
|
+
* `beforematch` handler to set `open`, or find-in-page reveals text while the
|
|
128
|
+
* trigger still reports collapsed.
|
|
129
129
|
*
|
|
130
130
|
* `inert` stays. `hidden` answers the reader who can see and `inert` answers
|
|
131
|
-
* the one tabbing through, and
|
|
132
|
-
*
|
|
131
|
+
* the one tabbing through, and wherever a sheet overrides `display`, `inert`
|
|
132
|
+
* is the only one of the two still in force.
|
|
133
133
|
*/
|
|
134
134
|
protected render(): TemplateResult;
|
|
135
135
|
}
|
|
@@ -18,7 +18,7 @@ import { HelixHeadlessAccordionItem } from '../item/accordion-item.js';
|
|
|
18
18
|
* item added a second after render coordinates on its first click.
|
|
19
19
|
*
|
|
20
20
|
* Items are matched with `instanceof HelixHeadlessAccordionItem`, never by tag
|
|
21
|
-
* name
|
|
21
|
+
* name, so this tier does not learn about the styled one.
|
|
22
22
|
*
|
|
23
23
|
* The keyboard listener is the controller's and is attached on connect, so
|
|
24
24
|
* none of it runs on the server, where there is no tree to walk and no events
|
|
@@ -61,7 +61,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
61
61
|
console.warn(`<${this.localName}> read a negative number and drew it as none. Its bands are parts of a ` +
|
|
62
62
|
'total, and a part cannot be less than nothing: a band drawn below its neighbor would say ' +
|
|
63
63
|
'the part took some of the one beneath it away. A series that crosses zero is a line, so ' +
|
|
64
|
-
'reach for
|
|
64
|
+
'reach for the line chart in this tier instead.');
|
|
65
65
|
}
|
|
66
66
|
render() {
|
|
67
67
|
const rows = this.sourceRows;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
|
-
* The largest `max`
|
|
4
|
+
* The largest `max` a stylesheet can hide past.
|
|
5
5
|
*
|
|
6
6
|
* The fold is `:host([max="N"]) ::slotted(:nth-child(n + N+1))`, one selector
|
|
7
7
|
* per value, because `An+B` takes a literal and no custom property can be read
|
|
8
|
-
* into it. So the range is finite and
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* into it. So the range is finite, and it is written down beside the count that
|
|
9
|
+
* has to agree with it: a count that folds and a stylesheet that does not would
|
|
10
|
+
* put a "+5" beside five avatars that are still on screen.
|
|
11
11
|
*/
|
|
12
12
|
export declare const FOLDS_UP_TO = 12;
|
|
13
13
|
/**
|
|
@@ -45,13 +45,13 @@ export declare class HelixHeadlessAvatarGroup extends HelixElement {
|
|
|
45
45
|
* Unset shows all of them, which is what no limit means and is more useful
|
|
46
46
|
* than refusing to render.
|
|
47
47
|
*
|
|
48
|
-
* **Reflected, because the fold is a stylesheet rule and nothing else.**
|
|
49
|
-
*
|
|
50
|
-
* so the attribute *is* the mechanism: a `max` that reaches this
|
|
51
|
-
* never reaches the host matches no rule, and every avatar is
|
|
52
|
-
* count claiming some are hidden. Markup is the safe path and
|
|
53
|
-
* a script is the broken one, and React takes it for
|
|
54
|
-
* matching property rather than an attribute.
|
|
48
|
+
* **Reflected, because the fold is a stylesheet rule and nothing else.** A
|
|
49
|
+
* sheet hides past the limit one selector per value, as `FOLDS_UP_TO`
|
|
50
|
+
* describes, so the attribute *is* the mechanism: a `max` that reaches this
|
|
51
|
+
* property and never reaches the host matches no rule, and every avatar is
|
|
52
|
+
* drawn beside a count claiming some are hidden. Markup is the safe path and
|
|
53
|
+
* hides the fault; a script is the broken one, and React takes it for
|
|
54
|
+
* everyone, assigning a matching property rather than an attribute.
|
|
55
55
|
*
|
|
56
56
|
* **Optional rather than defaulted, per the rule that a reflected property
|
|
57
57
|
* takes no default**: `max = 0` would stamp `max="0"` onto every host that
|
|
@@ -66,7 +66,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
|
|
|
66
66
|
* @csspart tooltip-value - A column's value inside the tooltip.
|
|
67
67
|
*
|
|
68
68
|
* @cssproperty --bar-chart-axis - How wide an axis column is drawn, in `ch`, from the widest number on it. Written on the axis itself, and only where the categories run along the bottom: turned sideways an axis is a row and takes a line's height instead.
|
|
69
|
-
* @cssproperty --bar-chart-secondary - The color of the secondary axis
|
|
69
|
+
* @cssproperty --bar-chart-secondary - The color of the secondary axis, where one series owns it. Written by the component from that series' `--chart-series-*`, so it promises the series color and nothing more: whatever that hook resolves to is what the axis is drawn in.
|
|
70
70
|
* @cssproperty --chart-bar-wash - The gradient a bar would take, named per bar so the
|
|
71
71
|
* styled tier can point `fill` at it. Drawn whatever the treatment and used only where
|
|
72
72
|
* `wash="gradient"` asks for it.
|
|
@@ -55,12 +55,12 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
55
55
|
/**
|
|
56
56
|
* Where the crumb goes, and nothing where it is the current page.
|
|
57
57
|
*
|
|
58
|
-
* **Optional and reflected, because a stylesheet does select on it.**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* the
|
|
63
|
-
*
|
|
58
|
+
* **Optional and reflected, because a stylesheet does select on it.** A sheet
|
|
59
|
+
* writes `:host(:not([href])) [part="link"]` to take the block padding off a
|
|
60
|
+
* crumb that is not a link, so the attribute is what decides how tall a crumb
|
|
61
|
+
* is. Unreflected, an `href` set from script reached the property, rendered
|
|
62
|
+
* the anchor, and left the host looking unlinked: the crumb drew at 20px
|
|
63
|
+
* where a markup twin drew at 28.
|
|
64
64
|
*
|
|
65
65
|
* Optional rather than defaulted, which is the general rule that a reflected
|
|
66
66
|
* property takes no default: an `href` written onto every host would be a link
|
|
@@ -47,7 +47,7 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
47
47
|
* the same way `label` becomes `aria-label` in there.
|
|
48
48
|
*
|
|
49
49
|
* ```html
|
|
50
|
-
* <helix-button commandfor="confirm" command="--show">Delete…</helix-button>
|
|
50
|
+
* <helix-headless-button commandfor="confirm" command="--show">Delete…</helix-headless-button>
|
|
51
51
|
* ```
|
|
52
52
|
*
|
|
53
53
|
* `commandFor` spells its attribute out, because Lit lowercases a property
|
|
@@ -11,7 +11,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
11
11
|
*
|
|
12
12
|
* The host is the surface. A wrapper `<div part="container">` would be a second
|
|
13
13
|
* box doing nothing the host cannot: the element itself takes the border, the
|
|
14
|
-
* radius, and the grid, and a consumer styles `
|
|
14
|
+
* radius, and the grid, and a consumer styles `Card` rather than reaching
|
|
15
15
|
* through `::part`. One node instead of two, on every card on the page.
|
|
16
16
|
*
|
|
17
17
|
* Name the card with `aria-label` or `aria-labelledby`. That is the only
|
|
@@ -166,13 +166,13 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
166
166
|
* **The number is published to the styles rather than enumerated by them**,
|
|
167
167
|
* as `--carousel-per-view` on the track, which is what keeps a width and a
|
|
168
168
|
* count from disagreeing. A sheet can only name a value it wrote a rule for,
|
|
169
|
-
* so
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* three dots, a pane taking the whole track and five slides
|
|
173
|
-
* dragging.
|
|
174
|
-
*
|
|
175
|
-
*
|
|
169
|
+
* so a sheet enumerating `per-view="2"` through `5` is a ceiling of five, and
|
|
170
|
+
* above it the pane falls back to one across while this file goes on counting
|
|
171
|
+
* positions. Measured in Chromium over eight slides against such a sheet, six
|
|
172
|
+
* across gave three dots, a pane taking the whole track and five slides
|
|
173
|
+
* reachable only by dragging. Published from here there is no ceiling to
|
|
174
|
+
* exceed, and every sheet reads the same declaration. `runEnd` publishes its
|
|
175
|
+
* correction the same way and for the same reason.
|
|
176
176
|
*
|
|
177
177
|
* **On the track and not on the host.** A custom property on the host is a
|
|
178
178
|
* reflected attribute by another name: it would arrive on upgrade, and a
|
|
@@ -197,8 +197,8 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
197
197
|
* `auto` track is handed nothing. A count stays for the design that calls for
|
|
198
198
|
* exactly three.
|
|
199
199
|
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
200
|
+
* A sheet says how it divides, and the `auto` example here carries the same
|
|
201
|
+
* three lines for a consumer writing their own.
|
|
202
202
|
*
|
|
203
203
|
* **A value rather than the resting behavior**, which is what the
|
|
204
204
|
* responsiveness policy asks of every axis that a box decides: a splitter
|
|
@@ -599,11 +599,11 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
599
599
|
* The arithmetic wants how many slides there are, and CSS can only ask
|
|
600
600
|
* `sibling-count()`, which is Chromium-only, evaluates to 0 through
|
|
601
601
|
* `::part()`, and needs a `:last-child` that `::part()` cannot carry either.
|
|
602
|
-
* So the
|
|
603
|
-
* several-across sheet could not: measured in
|
|
604
|
-
*
|
|
605
|
-
* one number both ways. Published from here,
|
|
606
|
-
*
|
|
602
|
+
* So a sheet shipped beside the component could correct its own run and a
|
|
603
|
+
* consumer writing their own several-across sheet could not: measured in
|
|
604
|
+
* Chromium at three across, an uncorrected track rested at 451 against -450
|
|
605
|
+
* where a corrected one rested on one number both ways. Published from here,
|
|
606
|
+
* one declaration reading this gets every sheet to the same place.
|
|
607
607
|
*
|
|
608
608
|
* **WebKit takes the margin and does not need it**, which is the reason a
|
|
609
609
|
* correction written in CSS looked like enough. It has no `sibling-count()`
|
|
@@ -133,12 +133,12 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
133
133
|
/**
|
|
134
134
|
* Records the draft, and stops the textarea speaking in this element's name.
|
|
135
135
|
*
|
|
136
|
-
* **The stop is not incidental.** `input` is composed by specification, so
|
|
137
|
-
* `<textarea>` in this shadow root sent its own past this host and on
|
|
138
|
-
* whatever `<helix-chat>` it is slotted into, and neither
|
|
139
|
-
* `input`: a consumer binding one on either received an
|
|
140
|
-
* target was a control they cannot reach. What a
|
|
141
|
-
* `helix-send`, once, when the reader is done.
|
|
136
|
+
* **The stop is not incidental.** `input` is composed by specification, so
|
|
137
|
+
* the `<textarea>` in this shadow root sent its own past this host and on
|
|
138
|
+
* through whatever `<helix-headless-chat>` it is slotted into, and neither
|
|
139
|
+
* element declares an `input`: a consumer binding one on either received an
|
|
140
|
+
* undeclared event whose target was a control they cannot reach. What a
|
|
141
|
+
* composer offers is `helix-send`, once, when the reader is done.
|
|
142
142
|
*/
|
|
143
143
|
private readonly handleInput;
|
|
144
144
|
private readonly handleSend;
|
|
@@ -15,7 +15,7 @@ export interface ChatTurn {
|
|
|
15
15
|
* response: history then loads under the reader rather than above them.
|
|
16
16
|
*/
|
|
17
17
|
key?: string;
|
|
18
|
-
/** What has happened to it, as on `
|
|
18
|
+
/** What has happened to it, as on `ChatMessage`. */
|
|
19
19
|
state?: 'failed' | 'sending' | 'sent' | 'streaming';
|
|
20
20
|
/** What was said, as text. */
|
|
21
21
|
text: string;
|
|
@@ -74,7 +74,7 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
74
74
|
* @aliases Conversation, Transcript, Thread, Messages
|
|
75
75
|
* @documentation https://fusion.dev/helix/components/chat
|
|
76
76
|
*
|
|
77
|
-
* @slot - The turns
|
|
77
|
+
* @slot - The turns.
|
|
78
78
|
* @slot actions - Beside the header: what can be done to the conversation itself.
|
|
79
79
|
* @slot composer - Below the transcript, where the reader writes.
|
|
80
80
|
* @slot header - Above the transcript: what this conversation is.
|
|
@@ -163,13 +163,13 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
|
|
|
163
163
|
*
|
|
164
164
|
* **Not reflected, and the default is why.** A reflected property that
|
|
165
165
|
* defaults to true writes its attribute on upgrade whether or not the
|
|
166
|
-
* consumer wrote one, so the server serves `<helix-chat label="x">`
|
|
167
|
-
* client turns it into `<helix-chat label="x" pinned>`: a
|
|
168
|
-
* React consumer reports and does not patch up. Nothing
|
|
169
|
-
* either, because the one thing that changes with the pin
|
|
170
|
-
* that is a part inside the shadow tree where a
|
|
171
|
-
* it. Measured rather than assumed: `label,
|
|
172
|
-
* `label` from the server.
|
|
166
|
+
* consumer wrote one, so the server serves `<helix-headless-chat label="x">`
|
|
167
|
+
* and the client turns it into `<helix-headless-chat label="x" pinned>`: a
|
|
168
|
+
* hydration mismatch a React consumer reports and does not patch up. Nothing
|
|
169
|
+
* needs the attribute either, because the one thing that changes with the pin
|
|
170
|
+
* is the way back, and that is a part inside the shadow tree where a
|
|
171
|
+
* stylesheet can already reach it. Measured rather than assumed: `label,
|
|
172
|
+
* pinned` after upgrade against `label` from the server.
|
|
173
173
|
*/
|
|
174
174
|
get pinned(): boolean;
|
|
175
175
|
set pinned(next: boolean);
|
|
@@ -78,8 +78,8 @@ export declare class HelixHeadlessCheckbox extends HelixHeadlessCheckbox_base {
|
|
|
78
78
|
* pixels of nothing after it. The input answers this by not rendering the
|
|
79
79
|
* element, which cannot work here, because a checkbox is named by its own
|
|
80
80
|
* content and the property is only that slot's fallback. Gating on the
|
|
81
|
-
* property would unlabel every
|
|
82
|
-
* written.
|
|
81
|
+
* property would unlabel every
|
|
82
|
+
* `<helix-headless-checkbox>Text</helix-headless-checkbox>` ever written.
|
|
83
83
|
*
|
|
84
84
|
* So the slot is asked instead, the same way `Tooltip` asks its own: with
|
|
85
85
|
* `flatten`, because here the fallback counts, being where the property
|
|
@@ -61,7 +61,7 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
|
|
|
61
61
|
<input
|
|
62
62
|
part="control"
|
|
63
63
|
type="checkbox"
|
|
64
|
-
.checked=${this.checked}
|
|
64
|
+
.checked=${this.checked || nothing}
|
|
65
65
|
.indeterminate=${this.indeterminate}
|
|
66
66
|
?disabled=${this.isDisabled}
|
|
67
67
|
?required=${this.required}
|
|
@@ -105,11 +105,11 @@ export declare class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
105
105
|
* round. The platform already writes booleans like this for the same reason,
|
|
106
106
|
* `novalidate` and `nomodule` and `noreferrer` among them.
|
|
107
107
|
*
|
|
108
|
-
* **Reflected, because the gutter is a stylesheet rule.**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
108
|
+
* **Reflected, because the gutter is a stylesheet rule.** A sheet reserves
|
|
109
|
+
* the copy button's width with `:host(:not([no-copy]))`, so the attribute is
|
|
110
|
+
* what decides whether the block pays for a control. Unreflected, setting it
|
|
111
|
+
* from script takes the button away (`render` reads the property) and leaves
|
|
112
|
+
* the 40px it stood in reserved.
|
|
113
113
|
*
|
|
114
114
|
* A false boolean reflects as the attribute's absence, so this costs no
|
|
115
115
|
* `no-copy=""` on hosts that never asked for one, and the rule about a
|
|
@@ -7,11 +7,11 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
|
|
|
7
7
|
* @summary A color, typed in any syntax or picked from a panel.
|
|
8
8
|
*
|
|
9
9
|
* @description
|
|
10
|
-
* **The picker is `
|
|
10
|
+
* **The picker is `ColorPicker`, not a second one written here.** It owns the
|
|
11
11
|
* square, the ramps, the eyedropper and the syntax toggle, and it is worth
|
|
12
12
|
* having on its own: a settings pane wants a picker flat on the page with
|
|
13
13
|
* nothing to open. This element is the field, the overlay, and the form.
|
|
14
|
-
* Exactly the arrangement Date Input has with `
|
|
14
|
+
* Exactly the arrangement Date Input has with `DatePicker`.
|
|
15
15
|
*
|
|
16
16
|
* **Typed as well as picked, and the typing is the reason this is not
|
|
17
17
|
* `<input type="color">`.** The native control gives a free picker and takes
|
|
@@ -190,7 +190,7 @@ export declare class HelixHeadlessColorInput extends HelixHeadlessColorInput_bas
|
|
|
190
190
|
* The picker is about to take the pointer over, so the panel gets out of the
|
|
191
191
|
* way and comes back after.
|
|
192
192
|
*
|
|
193
|
-
* `
|
|
193
|
+
* `ColorPicker` says what it is doing rather than reaching for a panel it
|
|
194
194
|
* cannot know it is in. A floating panel left up during an eyedropper is one
|
|
195
195
|
* the reader cannot dismiss and may well be trying to sample from underneath.
|
|
196
196
|
*/
|
|
@@ -160,10 +160,10 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
160
160
|
*
|
|
161
161
|
* **A color is exactly as requirable as a date**, which is the comparison
|
|
162
162
|
* that settles it: this element extends `HelixFormElement`, carries `name`
|
|
163
|
-
* and reports its value, so a consumer writing
|
|
164
|
-
*
|
|
165
|
-
* to
|
|
166
|
-
*
|
|
163
|
+
* and reports its value, so a consumer writing `<helix-headless-color-picker
|
|
164
|
+
* name="brand" required>` inside a form has every reason to expect the form
|
|
165
|
+
* to refuse an empty one. Its two siblings in the same composition position,
|
|
166
|
+
* Date Picker and Time Picker, both check it.
|
|
167
167
|
*
|
|
168
168
|
* Written out rather than taken from `MixinField`, for the reason those two
|
|
169
169
|
* record: the mixin brings a label, a hint and a feedback region, and this is
|
|
@@ -283,11 +283,11 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
283
283
|
* **The one thing a form-associated element owes, and this element owed it
|
|
284
284
|
* from the start without paying.** It extends `HelixFormElement`, takes
|
|
285
285
|
* `MixinControllerValue` and carries `name`, so a consumer writing
|
|
286
|
-
* `<helix-color-picker name="brand">` inside a form has every reason
|
|
287
|
-
* expect an entry, and the form carried none: no error, nothing in the
|
|
286
|
+
* `<helix-headless-color-picker name="brand">` inside a form has every reason
|
|
287
|
+
* to expect an entry, and the form carried none: no error, nothing in the
|
|
288
288
|
* markup to look at, and a field silently missing from the submission. Its
|
|
289
|
-
* two siblings in the same composition position, Color Input and Slider,
|
|
290
|
-
*
|
|
289
|
+
* two siblings in the same composition position, Color Input and Slider, both
|
|
290
|
+
* report.
|
|
291
291
|
*
|
|
292
292
|
* `null` rather than an empty string where there is no color, which is the
|
|
293
293
|
* difference between a control that submits nothing and one that submits a
|
|
@@ -352,12 +352,12 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
352
352
|
* ends. Listening only for the commit leaves the picker deaf while a handle
|
|
353
353
|
* moves, and the hue and alpha handles do not move at all.
|
|
354
354
|
*
|
|
355
|
-
* **Read off the target rather than out of a detail.** Do not bind
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
355
|
+
* **Read off the target rather than out of a detail.** Do not bind `Input`
|
|
356
|
+
* and `helix-change` and take the proposed value out of the event: those are
|
|
357
|
+
* requests, announcing what the slider is *about* to do, before anything has
|
|
358
|
+
* moved and while a listener may still refuse it. The native pair fires after
|
|
359
|
+
* the slider applied, so the value is on the element and cannot disagree with
|
|
360
|
+
* it.
|
|
361
361
|
*
|
|
362
362
|
* Idempotent, so taking both costs nothing: the same value applied twice is
|
|
363
363
|
* the same color.
|
|
@@ -7,10 +7,10 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
|
|
|
7
7
|
* @summary A field that filters a list as it is typed into.
|
|
8
8
|
*
|
|
9
9
|
* @description
|
|
10
|
-
* **The list is `
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* the
|
|
10
|
+
* **The list is `Listbox`, and the filtering is its own.** It owns narrowing,
|
|
11
|
+
* the empty state, the highlight, `aria-activedescendant` and scrolling an
|
|
12
|
+
* option into view. What is left for this element is the field, the panel and
|
|
13
|
+
* the traffic between them.
|
|
14
14
|
*
|
|
15
15
|
* **The text and the value are two things.** What a reader types is a filter:
|
|
16
16
|
* it narrows the list and is thrown away. The value is whichever option they
|
|
@@ -39,7 +39,7 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
|
|
|
39
39
|
* @aliases Autocomplete, Typeahead, Search select
|
|
40
40
|
* @documentation https://fusion.dev/helix/components/combobox
|
|
41
41
|
*
|
|
42
|
-
* @slot - The options
|
|
42
|
+
* @slot - The options.
|
|
43
43
|
* @slot end - After it, for a unit or a clear button.
|
|
44
44
|
* @slot indicator - Replaces the caret saying the field opens.
|
|
45
45
|
* @slot start - Before the text, for an icon.
|
|
@@ -208,6 +208,22 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
208
208
|
* so a tag does not move out from under the pointer about to remove it.
|
|
209
209
|
*/
|
|
210
210
|
private get chosen();
|
|
211
|
+
/**
|
|
212
|
+
* Whether a value is declared and this render cannot say what it is.
|
|
213
|
+
*
|
|
214
|
+
* **A placeholder is a statement, so a render that cannot read the words does
|
|
215
|
+
* not make it.** `value` is an attribute and a server has it; the words are
|
|
216
|
+
* the options' and the options are light-DOM children a server has none of.
|
|
217
|
+
* The field then came out empty with "Search owners" over it, which says
|
|
218
|
+
* nothing is chosen where the consumer had already said what is. Blank, it
|
|
219
|
+
* says nothing, keeps its box, and is filled in by the render after
|
|
220
|
+
* hydration, which is the answer `Select.Root.display` reaches for in the same
|
|
221
|
+
* position and for the same reason.
|
|
222
|
+
*
|
|
223
|
+
* The placeholder still stands where there is genuinely no value, which is
|
|
224
|
+
* what it is for and the one case a server can be sure of.
|
|
225
|
+
*/
|
|
226
|
+
private get unresolved();
|
|
211
227
|
/**
|
|
212
228
|
* Whether the filter has left anything to choose.
|
|
213
229
|
*
|
|
@@ -291,6 +307,10 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
291
307
|
* It only ever opens. Closing is Escape, a choice, or leaving, which is what
|
|
292
308
|
* the input already did and what a text field wants: a control that closed
|
|
293
309
|
* when you clicked into the middle of your own typing would be unusable.
|
|
310
|
+
*
|
|
311
|
+
* The tag is found by identity rather than by tag name. A name matches one
|
|
312
|
+
* tier's element and leaves the other's press falling through to the open,
|
|
313
|
+
* and a subclass under a third name is missed by both.
|
|
294
314
|
*/
|
|
295
315
|
private readonly handleFieldClick;
|
|
296
316
|
/**
|
|
@@ -11,6 +11,7 @@ import { property, state } from 'lit/decorators.js';
|
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { html } from 'lit/static-html.js';
|
|
13
13
|
import { optionsAmong } from '../../option/root/option-root.js';
|
|
14
|
+
import { HelixHeadlessTag } from '../../tag/root/tag-root.js';
|
|
14
15
|
import '../../listbox/index.js';
|
|
15
16
|
import '../../tag/index.js';
|
|
16
17
|
const isInsertion = (event) => !event.inputType?.startsWith('delete');
|
|
@@ -105,9 +106,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
105
106
|
if (this.isDisabled) {
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
|
-
if (event
|
|
109
|
-
.composedPath()
|
|
110
|
-
.some((node) => node instanceof HTMLElement && node.localName === 'helix-tag')) {
|
|
109
|
+
if (event.composedPath().some((node) => node instanceof HelixHeadlessTag)) {
|
|
111
110
|
return;
|
|
112
111
|
}
|
|
113
112
|
this.partNamed('control')?.focus();
|
|
@@ -147,6 +146,9 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
147
146
|
.filter((value) => known || words.has(value))
|
|
148
147
|
.map((value) => ({ text: words.get(value) ?? value, value }));
|
|
149
148
|
}
|
|
149
|
+
get unresolved() {
|
|
150
|
+
return this.values.length > 0 && !this.childrenKnown;
|
|
151
|
+
}
|
|
150
152
|
get showing() {
|
|
151
153
|
return (this.listbox?.options ?? []).some((option) => !option.hidden);
|
|
152
154
|
}
|
|
@@ -304,7 +306,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
304
306
|
aria-autocomplete=${this.suggest ? 'both' : 'list'}
|
|
305
307
|
aria-expanded=${this.open ? 'true' : 'false'}
|
|
306
308
|
aria-describedby=${this.describedBy ?? nothing}
|
|
307
|
-
placeholder=${(this.chosen.length > 0 ? '' : this.placeholder) || nothing}
|
|
309
|
+
placeholder=${(this.chosen.length > 0 || this.unresolved ? '' : this.placeholder) || nothing}
|
|
308
310
|
?disabled=${this.isDisabled}
|
|
309
311
|
.value=${this.multiple || this.open ? this.suggestion || this.typed : this.word}
|
|
310
312
|
@input=${this.handleInput}
|
|
@@ -7,12 +7,11 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
7
7
|
* @summary A list of commands, opened from anywhere and filtered by typing.
|
|
8
8
|
*
|
|
9
9
|
* @description
|
|
10
|
-
* **The list is `
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* and a key that summons it.
|
|
10
|
+
* **The list is `Listbox`, filtering and all.** Listbox already owns narrowing,
|
|
11
|
+
* the empty state, the highlight over what matched, `aria-activedescendant`,
|
|
12
|
+
* scrolling an option into view and the keyboard that moves between them. Its
|
|
13
|
+
* own note says a command palette is that list again with something different
|
|
14
|
+
* opening it, and this is that something: a dialog, and a key that summons it.
|
|
16
15
|
*
|
|
17
16
|
* **The value is not kept.** A palette runs a command and forgets it: nothing
|
|
18
17
|
* here is a form control and nothing is submitted, so what it reports is that
|
|
@@ -36,7 +35,7 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
36
35
|
* @aliases Command palette, Quick open, Spotlight
|
|
37
36
|
* @documentation https://fusion.dev/helix/components/command
|
|
38
37
|
*
|
|
39
|
-
* @slot - The commands,
|
|
38
|
+
* @slot - The commands, and any groups of them.
|
|
40
39
|
* @slot footer - Under the list, for the keys a reader can press.
|
|
41
40
|
*
|
|
42
41
|
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before it closes. Cancelable: refusing it takes the decision and nothing moves.
|