@fusion.dev/helix-headless 0.159.0 → 0.161.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 +2980 -189
- package/dist/canvas/root/canvas-root.d.ts +59 -2
- package/dist/canvas/root/canvas-root.js +123 -8
- package/dist/chat/message/chat-message.d.ts +8 -0
- package/dist/chat/message/chat-message.js +11 -0
- package/dist/chat/root/chat-root.d.ts +47 -1
- package/dist/chat/root/chat-root.js +130 -4
- package/dist/code-block/lines.d.ts +12 -0
- package/dist/code-block/lines.js +41 -0
- package/dist/code-block/root/code-block-root.d.ts +88 -5
- package/dist/code-block/root/code-block-root.js +154 -10
- package/dist/date-input/root/date-input-root.d.ts +108 -19
- package/dist/date-input/root/date-input-root.js +112 -13
- package/dist/date-picker/root/date-picker-root.d.ts +81 -16
- package/dist/date-picker/root/date-picker-root.js +140 -36
- package/dist/element-events.generated.js +6 -0
- package/dist/format-date/fields.js +1 -0
- package/dist/format-date/options.d.ts +3 -1
- package/dist/format-date/options.js +4 -1
- package/dist/format-date/root/format-date-root.d.ts +27 -11
- package/dist/format-date/root/format-date-root.js +6 -0
- package/dist/listbox/root/listbox-root.js +5 -0
- package/dist/notifications/notification/notification.d.ts +1 -0
- package/dist/notifications/notification/notification.js +2 -1
- package/dist/slider/root/slider-root.d.ts +54 -3
- package/dist/slider/root/slider-root.js +124 -2
- package/dist/splitter/root/splitter-root.d.ts +15 -0
- package/dist/splitter/root/splitter-root.js +16 -2
- package/dist/table/grid-controller.d.ts +7 -1
- package/dist/table/grid-controller.js +9 -1
- package/dist/table/root/table-root.d.ts +122 -0
- package/dist/table/root/table-root.js +293 -17
- package/dist/table/row/table-row.d.ts +41 -0
- package/dist/table/row/table-row.js +56 -2
- package/dist/time-input/root/time-input-root.d.ts +55 -7
- package/dist/time-input/root/time-input-root.js +70 -10
- package/dist/time-picker/root/time-picker-root.d.ts +27 -5
- package/dist/time-picker/root/time-picker-root.js +52 -13
- package/dist/timeline/item/timeline-item.d.ts +47 -10
- package/dist/timeline/item/timeline-item.js +36 -4
- package/dist/toggle/group/toggle-group.d.ts +18 -1
- package/dist/toggle/group/toggle-group.js +8 -2
- package/dist/toggle/root/toggle-root.d.ts +2 -2
- package/dist/toggle/root/toggle-root.js +2 -1
- package/dist/video-playlist/item/video-playlist-item.d.ts +11 -0
- package/dist/video-playlist/item/video-playlist-item.js +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +6 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +11 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +59 -5
- package/dist/video-playlist/root/video-playlist-root.js +82 -10
- package/dist/virtual-list/fill.d.ts +6 -1
- package/dist/virtual-list/fill.js +1 -1
- package/dist/virtual-list/keys.d.ts +8 -0
- package/dist/virtual-list/keys.js +20 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +98 -13
- package/dist/virtual-list/root/virtual-list-root.js +195 -20
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +1596 -224
- package/types/vue.d.ts +404 -49
- package/types/words.d.ts +151 -0
|
@@ -4,14 +4,14 @@ 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, formatWords, HelixElement, words } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, formatWords, HelixBeforeToggleEvent, HelixElement, HelixToggleEvent, requestChange, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
11
11
|
import { html } from 'lit/static-html.js';
|
|
12
12
|
import '../../copy-button/index.js';
|
|
13
13
|
import { highlightedLines } from '../highlight.js';
|
|
14
|
-
import { gutterNumbers, lineCount } from '../lines.js';
|
|
14
|
+
import { gutterNumbers, lineCount, lineRuns, lineSpans } from '../lines.js';
|
|
15
15
|
import { pairLines, parsePatch } from '../patch.js';
|
|
16
16
|
let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
17
17
|
constructor() {
|
|
@@ -28,12 +28,17 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
28
28
|
this.label = '';
|
|
29
29
|
this.language = '';
|
|
30
30
|
this.lineNumbers = false;
|
|
31
|
+
this.markLines = '';
|
|
31
32
|
this.noCopy = false;
|
|
33
|
+
this.wrap = false;
|
|
34
|
+
this.wrapLabel = 'Wrap lines';
|
|
35
|
+
this.wrappable = false;
|
|
32
36
|
this.parsed = { files: [], text: '' };
|
|
33
37
|
this.capped = false;
|
|
34
38
|
this.expanded = false;
|
|
35
39
|
this.measure = () => {
|
|
36
40
|
this.markScrollers();
|
|
41
|
+
this.placeLines();
|
|
37
42
|
if (!this.expanded) {
|
|
38
43
|
this.capped =
|
|
39
44
|
this.expandable &&
|
|
@@ -43,6 +48,20 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
43
48
|
};
|
|
44
49
|
}
|
|
45
50
|
static { this.words = 'helix-code-block'; }
|
|
51
|
+
toggleWrap() {
|
|
52
|
+
const next = !this.wrap;
|
|
53
|
+
const applied = requestChange({
|
|
54
|
+
apply: (checked) => {
|
|
55
|
+
this.wrap = checked;
|
|
56
|
+
},
|
|
57
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
58
|
+
host: this,
|
|
59
|
+
next,
|
|
60
|
+
});
|
|
61
|
+
if (applied) {
|
|
62
|
+
this.dispatchEvent(new HelixToggleEvent({ checked: next }));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
46
65
|
get files() {
|
|
47
66
|
if (!this.diff) {
|
|
48
67
|
return [];
|
|
@@ -85,6 +104,89 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
85
104
|
}
|
|
86
105
|
}
|
|
87
106
|
}
|
|
107
|
+
lineBoxes(code) {
|
|
108
|
+
const slot = code.querySelector('slot');
|
|
109
|
+
const roots = slot && !slot.hidden ? slot.assignedNodes({ flatten: true }) : [code];
|
|
110
|
+
const texts = [];
|
|
111
|
+
for (const root of roots) {
|
|
112
|
+
if (root.nodeType === Node.TEXT_NODE) {
|
|
113
|
+
texts.push(root);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const walker = (root.ownerDocument ?? document).createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
117
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
118
|
+
texts.push(node);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const starts = [];
|
|
122
|
+
let total = 0;
|
|
123
|
+
for (const text of texts) {
|
|
124
|
+
starts.push(total);
|
|
125
|
+
total += text.data.length;
|
|
126
|
+
}
|
|
127
|
+
const at = (offset) => {
|
|
128
|
+
for (let index = texts.length - 1; index >= 0; index -= 1) {
|
|
129
|
+
const start = starts[index] ?? 0;
|
|
130
|
+
if (offset >= start) {
|
|
131
|
+
const text = texts[index];
|
|
132
|
+
return [text, Math.min(offset - start, text.data.length)];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
};
|
|
137
|
+
const box = code.getBoundingClientRect();
|
|
138
|
+
const origin = box.top + code.clientTop - code.scrollTop;
|
|
139
|
+
const row = Number.parseFloat(getComputedStyle(code).lineHeight) || 0;
|
|
140
|
+
const boxes = [];
|
|
141
|
+
for (const [from, to] of lineSpans(texts.map((text) => text.data).join(''))) {
|
|
142
|
+
const start = at(from);
|
|
143
|
+
const end = at(to === from ? Math.min(to + 1, total) : to);
|
|
144
|
+
const previous = boxes.at(-1);
|
|
145
|
+
let top = previous ? previous.bottom : 0;
|
|
146
|
+
let bottom = top + row;
|
|
147
|
+
if (start && end) {
|
|
148
|
+
const range = (code.ownerDocument ?? document).createRange();
|
|
149
|
+
range.setStart(start[0], start[1]);
|
|
150
|
+
range.setEnd(end[0], end[1]);
|
|
151
|
+
const rects = [...range.getClientRects()].filter((rect) => rect.height > 0);
|
|
152
|
+
if (rects.length > 0) {
|
|
153
|
+
const half = Math.max(0, (row - (rects[0]?.height ?? row)) / 2);
|
|
154
|
+
top = Math.min(...rects.map((rect) => rect.top)) - origin - half;
|
|
155
|
+
bottom = Math.max(...rects.map((rect) => rect.bottom)) - origin + half;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
boxes.push({ bottom, top });
|
|
159
|
+
}
|
|
160
|
+
return boxes;
|
|
161
|
+
}
|
|
162
|
+
placeLines() {
|
|
163
|
+
const code = this.renderRoot.querySelector('[part="code"]');
|
|
164
|
+
const marks = [...this.renderRoot.querySelectorAll('[part="mark"]')];
|
|
165
|
+
const numbers = [
|
|
166
|
+
...this.renderRoot.querySelectorAll('[part="gutter"] > [part="number"]'),
|
|
167
|
+
];
|
|
168
|
+
if (!code || (marks.length === 0 && numbers.length === 0)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const boxes = this.lineBoxes(code);
|
|
172
|
+
for (const mark of marks) {
|
|
173
|
+
const [first, last] = (mark.dataset.lines ?? '').split('-').map(Number);
|
|
174
|
+
const top = boxes[(first ?? 0) - 1];
|
|
175
|
+
const bottom = boxes[Math.min(last ?? 0, boxes.length) - 1];
|
|
176
|
+
mark.hidden = !top || !bottom;
|
|
177
|
+
if (top && bottom) {
|
|
178
|
+
mark.style.setProperty('--code-block-mark-start', `${top.top}px`);
|
|
179
|
+
mark.style.setProperty('--code-block-mark-size', `${bottom.bottom - top.top}px`);
|
|
180
|
+
mark.style.setProperty('--code-block-mark-inline-size', `${code.scrollWidth}px`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
numbers.forEach((number, index) => {
|
|
184
|
+
const line = boxes[index];
|
|
185
|
+
if (line) {
|
|
186
|
+
number.style.setProperty('--code-block-line-size', `${line.bottom - line.top}px`);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
88
190
|
updated(changed) {
|
|
89
191
|
super.updated(changed);
|
|
90
192
|
if (typeof ResizeObserver !== 'undefined') {
|
|
@@ -126,21 +228,29 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
126
228
|
catch (error) {
|
|
127
229
|
globalThis.reportError?.(error);
|
|
128
230
|
}
|
|
231
|
+
const runs = this.childrenKnown ? lineRuns(this.markLines) : [];
|
|
232
|
+
const marks = runs.map(([first, last]) => html `<span part="mark" aria-hidden="true" data-lines="${first}-${last}"></span>`);
|
|
129
233
|
const code = highlighted === undefined
|
|
130
|
-
? html `<code part="code"
|
|
131
|
-
: html `<code part="code">${unsafeHTML(highlighted)}</code><slot
|
|
234
|
+
? html `<code part="code">${marks}<slot @slotchange=${() => this.requestUpdate()}></slot></code>`
|
|
235
|
+
: html `<code part="code">${marks}${unsafeHTML(highlighted)}</code><slot
|
|
132
236
|
hidden
|
|
133
237
|
@slotchange=${() => this.requestUpdate()}
|
|
134
238
|
></slot>`;
|
|
135
239
|
const lines = lineCount(text);
|
|
240
|
+
const numbers = lines === 0
|
|
241
|
+
? nothing
|
|
242
|
+
: this.wrap
|
|
243
|
+
? Array.from({ length: lines }, (_, index) => html `<span part="number">${index + 1}
|
|
244
|
+
</span>`)
|
|
245
|
+
: gutterNumbers(lines);
|
|
136
246
|
const gutter = this.lineNumbers
|
|
137
|
-
? html `<span part="gutter" aria-hidden="true">${
|
|
247
|
+
? html `<span part="gutter" aria-hidden="true">${numbers}</span>`
|
|
138
248
|
: nothing;
|
|
139
249
|
const name = this.label || this.language;
|
|
140
250
|
return html `${this.renderHeader(name)}
|
|
141
251
|
<div part="frame">
|
|
142
252
|
<pre id="block" part="block" translate="no">${gutter}${code}</pre>
|
|
143
|
-
${name ? nothing : this.renderCopy()}
|
|
253
|
+
${this.headed(name) ? nothing : this.renderCopy()}
|
|
144
254
|
</div>${this.renderExpand()}`;
|
|
145
255
|
}
|
|
146
256
|
renderExpand() {
|
|
@@ -160,11 +270,29 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
160
270
|
${this.expanded ? this.collapseLabel : this.expandLabel}
|
|
161
271
|
</button>`;
|
|
162
272
|
}
|
|
273
|
+
headed(name) {
|
|
274
|
+
return name !== '' || (this.wrappable && !this.diff) || this.slotted('actions');
|
|
275
|
+
}
|
|
163
276
|
renderHeader(name, value) {
|
|
164
|
-
|
|
165
|
-
|
|
277
|
+
const acting = this.slotted('actions');
|
|
278
|
+
return this.headed(name)
|
|
279
|
+
? html `<div part="header">${name ? html `<span part="label">${name}</span>` : nothing}${acting ? html `<span part="actions"><slot name="actions"></slot></span>` : nothing}${this.renderWrapToggle()}${this.renderCopy(value, name)}</div>`
|
|
166
280
|
: nothing;
|
|
167
281
|
}
|
|
282
|
+
renderWrapToggle() {
|
|
283
|
+
if (!this.wrappable || this.diff) {
|
|
284
|
+
return nothing;
|
|
285
|
+
}
|
|
286
|
+
return html `<button
|
|
287
|
+
part="wrap-toggle"
|
|
288
|
+
type="button"
|
|
289
|
+
aria-pressed=${this.wrap ? 'true' : 'false'}
|
|
290
|
+
@click=${() => this.toggleWrap()}
|
|
291
|
+
>${this.wrapLabel}</button>`;
|
|
292
|
+
}
|
|
293
|
+
slotted(name) {
|
|
294
|
+
return this.knownChildren.some((child) => child.getAttribute('slot') === name);
|
|
295
|
+
}
|
|
168
296
|
renderCopy(value, name) {
|
|
169
297
|
return this.noCopy ? nothing : this.renderCopyButton(value, name);
|
|
170
298
|
}
|
|
@@ -179,7 +307,10 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
179
307
|
copied-label=${this.copiedLabel}
|
|
180
308
|
label=${name ? formatWords(this, 'copyNameLabel', { copy: this.copyLabel, name }) : this.copyLabel}
|
|
181
309
|
.value=${value}
|
|
182
|
-
|
|
310
|
+
>${this.renderCopyIcons()}</${this.tag('copy-button')}>`;
|
|
311
|
+
}
|
|
312
|
+
renderCopyIcons() {
|
|
313
|
+
return html `${this.slotted('copy-icon') ? html `<slot name="copy-icon"></slot>` : nothing}${this.slotted('copied-icon') ? html `<slot name="copied-icon" slot="copied"></slot>` : nothing}`;
|
|
183
314
|
}
|
|
184
315
|
renderNumber(value, width) {
|
|
185
316
|
return html `<span part="number" aria-hidden="true">${String(value ?? '').padStart(width)} </span>`;
|
|
@@ -223,7 +354,7 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
223
354
|
${this.variant === 'split'
|
|
224
355
|
? this.renderSplit(file, width)
|
|
225
356
|
: html `<pre part="block" translate="no"><code part="code">${file.hunks.map((hunk) => html `${this.renderHunk(hunk)}${hunk.lines.map((line) => this.renderLine(line, width))}`)}</code></pre>`}
|
|
226
|
-
${name ? nothing : this.renderCopy(now)}
|
|
357
|
+
${this.headed(name) ? nothing : this.renderCopy(now)}
|
|
227
358
|
</div>
|
|
228
359
|
</div>`;
|
|
229
360
|
})}<slot hidden @slotchange=${() => this.requestUpdate()}></slot>`;
|
|
@@ -275,12 +406,25 @@ __decorate([
|
|
|
275
406
|
__decorate([
|
|
276
407
|
property({ attribute: 'line-numbers', reflect: true, type: Boolean })
|
|
277
408
|
], HelixHeadlessCodeBlock.prototype, "lineNumbers", void 0);
|
|
409
|
+
__decorate([
|
|
410
|
+
property({ attribute: 'mark-lines' })
|
|
411
|
+
], HelixHeadlessCodeBlock.prototype, "markLines", void 0);
|
|
278
412
|
__decorate([
|
|
279
413
|
property({ attribute: 'no-copy', reflect: true, type: Boolean })
|
|
280
414
|
], HelixHeadlessCodeBlock.prototype, "noCopy", void 0);
|
|
281
415
|
__decorate([
|
|
282
416
|
property({ reflect: true })
|
|
283
417
|
], HelixHeadlessCodeBlock.prototype, "variant", void 0);
|
|
418
|
+
__decorate([
|
|
419
|
+
property({ reflect: true, type: Boolean })
|
|
420
|
+
], HelixHeadlessCodeBlock.prototype, "wrap", void 0);
|
|
421
|
+
__decorate([
|
|
422
|
+
words,
|
|
423
|
+
property({ attribute: 'wrap-label' })
|
|
424
|
+
], HelixHeadlessCodeBlock.prototype, "wrapLabel", void 0);
|
|
425
|
+
__decorate([
|
|
426
|
+
property({ type: Boolean })
|
|
427
|
+
], HelixHeadlessCodeBlock.prototype, "wrappable", void 0);
|
|
284
428
|
__decorate([
|
|
285
429
|
state()
|
|
286
430
|
], HelixHeadlessCodeBlock.prototype, "capped", void 0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, type DateCalendar, HelixFormElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, type DateCalendar, HelixFormElement, type MonthCalendar, type MonthSystem } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../date-picker/index.js';
|
|
4
4
|
import '../../tag/index.js';
|
|
@@ -15,17 +15,24 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
15
15
|
* gives a picker and locale formatting but allows almost no styling, so the
|
|
16
16
|
* field is a text field. Typing sends `input` on each keystroke and `change`
|
|
17
17
|
* when you leave the field, as a text field does. A date picked from the
|
|
18
|
-
* calendar sends both.
|
|
18
|
+
* calendar sends both. The field reads ISO, `2026-08-04`, and a date written
|
|
19
|
+
* in the order, the digits, and the month names of `locale`, `8/4/2026` or
|
|
20
|
+
* `Aug 4, 2026` in `en-US` and `4.8.2026` in `de-DE`, which becomes the value
|
|
21
|
+
* as you leave the field.
|
|
19
22
|
*
|
|
20
23
|
* The trigger and ArrowDown open the calendar with focus on the selected day,
|
|
21
24
|
* Tab moves between the calendar's controls without leaving it, and Escape
|
|
22
25
|
* closes it and returns focus to the field. A press into the field opens the
|
|
23
26
|
* calendar too. Tab into the field opens nothing, and Tab out of the field
|
|
24
|
-
* closes the calendar.
|
|
27
|
+
* closes the calendar. The text field is a `combobox` with
|
|
28
|
+
* `aria-haspopup="dialog"`, `aria-expanded`, and `aria-controls`, as in the
|
|
29
|
+
* APG date picker combobox, since Down opens the calendar from it.
|
|
25
30
|
*
|
|
26
31
|
* With `segmented`, the field is a row of segments in place of the text: a
|
|
27
32
|
* month, a day and a year in the order the locale writes them, each set with
|
|
28
|
-
* digits or the arrow keys. Alt+Down opens the calendar from a segment.
|
|
33
|
+
* digits or the arrow keys. Alt+Down opens the calendar from a segment. A
|
|
34
|
+
* `range` is two rows with a dash between them, the start and the end, as
|
|
35
|
+
* React Aria's DateRangePicker draws them, and `multiple` keeps the text.
|
|
29
36
|
*
|
|
30
37
|
* Text that is not a date gives the form an empty value, as a native date
|
|
31
38
|
* field does, and `value` keeps the text so it can be corrected.
|
|
@@ -57,6 +64,7 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
57
64
|
* @aliases DatePicker, DateField, InputDate
|
|
58
65
|
* @documentation https://fusion.dev/helix/components/date-input
|
|
59
66
|
*
|
|
67
|
+
* @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
|
|
60
68
|
* @slot end - Content after the date, before the trigger, such as a clear button.
|
|
61
69
|
* @slot feedback - The error message under the field.
|
|
62
70
|
* @slot hint - The help text under the field.
|
|
@@ -72,9 +80,11 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
72
80
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before the date changes. Cancelable: call `preventDefault()` to keep the current date.
|
|
73
81
|
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before the calendar closes. Cancelable: call `preventDefault()` to keep it open.
|
|
74
82
|
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before the calendar opens. Cancelable: call `preventDefault()` to keep it closed.
|
|
83
|
+
* @event {HelixClearEvent} helix-clear - Fired after the clear button has emptied the field, after `input` and `change`.
|
|
75
84
|
* @event {Event} input - Fired after the value changes.
|
|
76
85
|
* @event {ToggleEvent} toggle - Fired when the calendar opens or closes, with `newState` and `oldState`.
|
|
77
86
|
*
|
|
87
|
+
* @csspart clear - The button that empties the field, under `clearable`, while it holds a date.
|
|
78
88
|
* @csspart control - The text input.
|
|
79
89
|
* @csspart date - One held date, as a tag, in `multiple`.
|
|
80
90
|
* @csspart date-cell - The tag's grid cell, which a tag draws only inside a tag group.
|
|
@@ -116,8 +126,10 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
116
126
|
* @csspart picker-periods - The grid of months or years.
|
|
117
127
|
* @csspart picker-previous - The control that moves to the previous month.
|
|
118
128
|
* @csspart picker-previous-mark - The icon on the previous month control.
|
|
129
|
+
* @csspart picker-selection - The chosen date or range in words, which screen readers hear when it changes. Drawn for screen readers only.
|
|
119
130
|
* @csspart picker-week - One row of days.
|
|
120
131
|
* @csspart picker-weekday - A column header naming a day of the week.
|
|
132
|
+
* @csspart range-separator - The dash between a range's two rows of segments, in `segmented`, beside `literal`.
|
|
121
133
|
* @csspart rest - The count of dates beyond the ones shown. It is a `<button>` with `expandable` and a `<span>` without it.
|
|
122
134
|
* @csspart segment - One part of the date, a year, a month or a day, in `segmented`.
|
|
123
135
|
* @csspart segment-placeholder - A segment with nothing in it yet. Applied with `segment`.
|
|
@@ -127,6 +139,7 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
127
139
|
* @csspart trigger - The control that opens the calendar.
|
|
128
140
|
* @csspart trigger-icon - The icon on the button that opens the calendar.
|
|
129
141
|
*
|
|
142
|
+
* @cssstate blank - The field holds no date.
|
|
130
143
|
* @cssstate invalid - The field has an error to show, from the browser's validation or from your `feedback`.
|
|
131
144
|
* @cssstate open - The calendar is open.
|
|
132
145
|
*/
|
|
@@ -138,28 +151,43 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
138
151
|
static words: string;
|
|
139
152
|
protected readonly aria: AriaForwardController;
|
|
140
153
|
/**
|
|
141
|
-
* What the browser may autofill here, as one of the platform's own tokens
|
|
154
|
+
* What the browser may autofill here, as one of the platform's own tokens,
|
|
155
|
+
* such as `bday`.
|
|
142
156
|
*
|
|
143
157
|
* Empty leaves the attribute off, which is the browser's default and is what
|
|
144
158
|
* lets autofill work at all: hardcoding `off` here means a birthday or a
|
|
145
|
-
* postal code can never be filled in for a reader.
|
|
159
|
+
* postal code can never be filled in for a reader. With `segmented`, a
|
|
160
|
+
* hidden native date input carries it, since no browser fills the segments.
|
|
146
161
|
*/
|
|
147
162
|
autocomplete: string;
|
|
148
163
|
/**
|
|
149
|
-
* The calendar the written date and the calendar's days are
|
|
150
|
-
* `buddhist`, `japanese`, `roc`, or `iso8601
|
|
164
|
+
* The calendar the written date, the segments, and the calendar's days are
|
|
165
|
+
* in: `gregory`, `buddhist`, `japanese`, `roc`, or `iso8601`, or a calendar
|
|
166
|
+
* with months of its own that Date Picker's `calendar` names, such as
|
|
167
|
+
* `persian`, `hebrew`, `islamic-umalqura`, `ethiopic`, or `chinese`.
|
|
151
168
|
*
|
|
152
|
-
* Absent is the locale's own where
|
|
153
|
-
* every other, as Date Picker's `calendar` is. The value is
|
|
154
|
-
* every calendar, and a focused field is ISO in every
|
|
155
|
-
* `segmented`, the segments are the
|
|
156
|
-
*
|
|
169
|
+
* Absent is the locale's own where its months are the Gregorian months, and
|
|
170
|
+
* `gregory` for every other, as Date Picker's `calendar` is. The value is
|
|
171
|
+
* `YYYY-MM-DD` in every calendar, and a focused text field is ISO in every
|
|
172
|
+
* calendar. In `segmented`, the segments are the day, month, and year as
|
|
173
|
+
* the calendar counts them, in the order the locale writes them: Mehr 14,
|
|
174
|
+
* 1405 is month 7 and day 14 of 1405 under `persian`. Under the five with
|
|
175
|
+
* Gregorian months they are the Gregorian day, month, and year, or ISO order
|
|
176
|
+
* for `iso8601`.
|
|
157
177
|
*/
|
|
158
|
-
calendar?: DateCalendar;
|
|
178
|
+
calendar?: DateCalendar | MonthCalendar;
|
|
159
179
|
/**
|
|
160
180
|
* The name of the calendar's grid of days, read by screen readers.
|
|
161
181
|
*/
|
|
162
182
|
calendarLabel: string;
|
|
183
|
+
/**
|
|
184
|
+
* Whether the field shows a button that empties it, as Input's `clearable`
|
|
185
|
+
* does. Shown only while the field holds something to clear and is neither
|
|
186
|
+
* disabled nor read-only.
|
|
187
|
+
*/
|
|
188
|
+
clearable: boolean;
|
|
189
|
+
/** The accessible name of the clear button, which shows only an icon. */
|
|
190
|
+
clearLabel: string;
|
|
163
191
|
/** Typed, so a keystroke is announced as `input` alone. See `announcesInput`. */
|
|
164
192
|
protected readonly announcesInput = true;
|
|
165
193
|
/**
|
|
@@ -168,8 +196,9 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
168
196
|
* **The field renders when it is idle and holds the value when it is being
|
|
169
197
|
* edited.** A written date is a rendering, and a document being edited must
|
|
170
198
|
* not be a rendering of something else: `Intl.DateTimeFormat` formats and does
|
|
171
|
-
* not parse, so
|
|
172
|
-
*
|
|
199
|
+
* not parse, so a rendering such as `Tuesday, August 4, 2026` is no text to
|
|
200
|
+
* edit. The field does read a date typed in the locale's order and digits as
|
|
201
|
+
* you leave it, which covers what a reader types.
|
|
173
202
|
*
|
|
174
203
|
* The way out is not to choose between the two but to separate them in time.
|
|
175
204
|
* Idle, the field shows `4 August 2026`, which is what a date is for reading.
|
|
@@ -348,6 +377,12 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
348
377
|
* removes rather than as "Remove" said once per date.
|
|
349
378
|
*/
|
|
350
379
|
removeLabel: string;
|
|
380
|
+
/**
|
|
381
|
+
* What a screen reader hears about the dates chosen in the calendar, with
|
|
382
|
+
* `{kind}`, `{start}`, `{end}` and `{count}` filled in as Date Picker's
|
|
383
|
+
* `selection-label` says.
|
|
384
|
+
*/
|
|
385
|
+
selectionLabel: string;
|
|
351
386
|
/**
|
|
352
387
|
* How far apart the selectable dates are, in days.
|
|
353
388
|
*
|
|
@@ -361,6 +396,12 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
361
396
|
* The message shown when a date is not on `step`.
|
|
362
397
|
*/
|
|
363
398
|
stepMismatchMessage: string;
|
|
399
|
+
/**
|
|
400
|
+
* The time zone today is read in, such as `America/New_York`, handed to the
|
|
401
|
+
* calendar: the day marked today, and the month an empty field opens on.
|
|
402
|
+
* Empty is the reader's own. Dates are plain `YYYY-MM-DD` and carry no zone.
|
|
403
|
+
*/
|
|
404
|
+
timeZone: string;
|
|
364
405
|
/**
|
|
365
406
|
* The name of the button that opens the calendar, read by screen readers.
|
|
366
407
|
*/
|
|
@@ -375,17 +416,23 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
375
416
|
*/
|
|
376
417
|
private get picked();
|
|
377
418
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
419
|
+
* A row of segments holds one date, and `range` takes two rows with a dash
|
|
420
|
+
* between them, as React Aria's range fields do. `multiple` keeps the line
|
|
421
|
+
* of text, whose tags are how it writes several.
|
|
380
422
|
*/
|
|
381
423
|
protected get segmentable(): boolean;
|
|
424
|
+
protected get segmentGroups(): number;
|
|
382
425
|
protected get segmentedKind(): 'date';
|
|
383
426
|
/**
|
|
384
427
|
* The segments are the Gregorian day, month and year, which is what they
|
|
385
428
|
* hold, in ISO order where the calendar is `iso8601`. A year shown as 2569
|
|
386
|
-
* or Reiwa 8 would be a year the segment does not hold.
|
|
429
|
+
* or Reiwa 8 would be a year the segment does not hold. Under a calendar
|
|
430
|
+
* with months of its own they hold that calendar's parts, so they are laid
|
|
431
|
+
* out and named in it.
|
|
387
432
|
*/
|
|
388
433
|
protected get segmentLocale(): string;
|
|
434
|
+
/** The calendar the segments count in, where it has months of its own. */
|
|
435
|
+
protected get segmentSystem(): MonthSystem | undefined;
|
|
389
436
|
/** One date, written the way `dateStyle` asks for. */
|
|
390
437
|
private written;
|
|
391
438
|
protected get display(): string;
|
|
@@ -401,6 +448,20 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
401
448
|
private draft;
|
|
402
449
|
/** Relayed under this element's name, so a consumer hears one control. */
|
|
403
450
|
private readonly handleInput;
|
|
451
|
+
/**
|
|
452
|
+
* A date as the reader wrote it, as `YYYY-MM-DD`: ISO as it is, and the
|
|
453
|
+
* order, the digits, and the month names of the field's locale and calendar
|
|
454
|
+
* read back, so `8/4/2026` in `en-US` is August 4, 2026. Empty where it is
|
|
455
|
+
* no date.
|
|
456
|
+
*/
|
|
457
|
+
private read;
|
|
458
|
+
/**
|
|
459
|
+
* The text the reader leaves, read in the field's locale: a date written as
|
|
460
|
+
* the locale writes one becomes the value, as ISO, when the field commits.
|
|
461
|
+
* Not on each key, where `8/4/202` is a date in the year 202 and taking it
|
|
462
|
+
* would move the caret mid-year.
|
|
463
|
+
*/
|
|
464
|
+
private readonly handleTextCommit;
|
|
404
465
|
/** Adds what was typed to the set, or takes the last one back out. */
|
|
405
466
|
private readonly handleDraftKey;
|
|
406
467
|
/** The dates that get a tag, which is all of them until the cap says not. */
|
|
@@ -423,6 +484,11 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
423
484
|
* The message shown when `disable-dates` or `disable-days` bars a date.
|
|
424
485
|
*/
|
|
425
486
|
unavailableMessage: string;
|
|
487
|
+
/**
|
|
488
|
+
* The message for text that is no date, where `bad-input-message` is not
|
|
489
|
+
* set. `{mode}` is `single`, `range`, or `multiple`.
|
|
490
|
+
*/
|
|
491
|
+
unreadableMessage: string;
|
|
426
492
|
/**
|
|
427
493
|
* The name of the calendar's heading where it shows a page of years, with
|
|
428
494
|
* `{heading}` filled in.
|
|
@@ -477,6 +543,29 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
477
543
|
* and no mark whatsoever.
|
|
478
544
|
*/
|
|
479
545
|
protected renderTrigger(): TemplateResult;
|
|
546
|
+
/**
|
|
547
|
+
* A native date input a browser's autofill can fill, where the field shows
|
|
548
|
+
* segments: a row of spans that no browser fills. React Aria's
|
|
549
|
+
* `HiddenDateInput` is the same answer for its segmented field.
|
|
550
|
+
*
|
|
551
|
+
* Drawn and never seen, a pixel and see-through, as Select's hidden select
|
|
552
|
+
* is, since Safari skips a field that is `display: none`. `aria-hidden` and
|
|
553
|
+
* out of the tab order, and in this shadow root, so the form still takes
|
|
554
|
+
* the value once, from the host. A fill is taken as a pick, with `input`
|
|
555
|
+
* and `change` from the host.
|
|
556
|
+
*/
|
|
557
|
+
private renderAutofill;
|
|
558
|
+
private readonly handleAutofill;
|
|
559
|
+
/** Whether there is a clear button on screen right now. */
|
|
560
|
+
private get showsClear();
|
|
561
|
+
/**
|
|
562
|
+
* Empties the field, through `requestValue` so a consumer who owns the
|
|
563
|
+
* value decides, then says `change` and `helix-clear` and puts focus back
|
|
564
|
+
* in the field, the button having gone.
|
|
565
|
+
*/
|
|
566
|
+
private readonly handleClear;
|
|
567
|
+
/** The cross on the clear button, behind a seam a tier can move. */
|
|
568
|
+
protected renderClearIcon(): TemplateResult;
|
|
480
569
|
/** The line of text the dates are typed into, where the field shows no segments. */
|
|
481
570
|
private renderControl;
|
|
482
571
|
protected render(): TemplateResult;
|