@fusion.dev/helix-core 0.147.0 → 0.149.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 +16160 -12084
- package/dist/controllers/aria-forward-controller/aria-forward-controller.js +1 -1
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +2 -2
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +5 -4
- package/dist/controllers/children-controller/children-controller.d.ts +28 -0
- package/dist/controllers/children-controller/children-controller.js +18 -0
- package/dist/controllers/countdown-controller/countdown-controller.d.ts +15 -1
- package/dist/controllers/countdown-controller/countdown-controller.js +27 -2
- package/dist/controllers/floating-controller/floating-controller.d.ts +12 -1
- package/dist/controllers/floating-controller/floating-controller.js +2 -1
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +25 -0
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +8 -0
- package/dist/controllers/machine-controller/machine-controller.d.ts +69 -0
- package/dist/controllers/machine-controller/machine-controller.js +78 -0
- package/dist/controllers/machine-controller/machine.d.ts +93 -0
- package/dist/controllers/machine-controller/machine.js +20 -0
- package/dist/controllers/open-phase-controller/open-phase-controller.d.ts +10 -0
- package/dist/controllers/open-phase-controller/open-phase-controller.js +7 -4
- package/dist/controllers/option-window-controller/option-window-controller.d.ts +96 -0
- package/dist/controllers/option-window-controller/option-window-controller.js +81 -0
- package/dist/controllers/popover-controller/popover-controller.js +1 -1
- package/dist/controllers/reorder-controller/reorder-controller.d.ts +285 -0
- package/dist/controllers/reorder-controller/reorder-controller.js +497 -0
- package/dist/controllers/source-controller/source-controller.js +1 -1
- package/dist/controllers/virtualize-controller/heights.js +1 -1
- package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +117 -3
- package/dist/controllers/virtualize-controller/virtualize-controller.js +134 -32
- package/dist/events/before-reorder.d.ts +14 -0
- package/dist/events/before-reorder.js +11 -0
- package/dist/events/details.d.ts +28 -0
- package/dist/events/events.d.ts +4 -2
- package/dist/events/events.js +3 -1
- package/dist/events/names.js +1 -1
- package/dist/events/reorder.d.ts +18 -12
- package/dist/events/reordered.d.ts +4 -4
- package/dist/helix-element/helix-element.d.ts +14 -5
- package/dist/helix-element/helix-element.js +6 -3
- package/dist/helix-element/react-audit-off.d.ts +11 -0
- package/dist/helix-element/react-audit-off.js +1 -0
- package/dist/helix-element/react-audit.d.ts +20 -0
- package/dist/helix-element/react-audit.js +56 -0
- package/dist/helix-element/react-bridge.d.ts +2 -22
- package/dist/helix-element/react-bridge.js +1 -56
- package/dist/index.d.ts +34 -14
- package/dist/index.js +32 -12
- package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +7 -2
- package/dist/mixins/mixin-chart-source/mixin-chart-source.js +6 -0
- package/dist/mixins/mixin-collection/mixin-collection.js +4 -0
- package/dist/mixins/mixin-dismissible/mixin-dismissible.js +3 -0
- package/dist/mixins/mixin-field/mixin-field.js +1 -1
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.d.ts +12 -0
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +15 -2
- package/dist/mixins/mixin-tokens/mixin-tokens.d.ts +5 -0
- package/dist/mixins/mixin-tokens/mixin-tokens.js +13 -2
- package/dist/mixins/mixin-viewport/mixin-viewport.d.ts +17 -15
- package/dist/mixins/mixin-viewport/mixin-viewport.js +23 -41
- package/dist/utils/assign-slots/assign-slots.d.ts +18 -0
- package/dist/utils/assign-slots/assign-slots.js +14 -0
- package/dist/utils/autofill-select/autofill-select.d.ts +40 -0
- package/dist/utils/autofill-select/autofill-select.js +14 -0
- package/dist/utils/calendar/calendar.d.ts +27 -0
- package/dist/utils/calendar/calendar.js +17 -0
- package/dist/utils/center-in-view/center-in-view.d.ts +18 -0
- package/dist/utils/center-in-view/center-in-view.js +14 -0
- package/dist/utils/chord/key-names.d.ts +30 -0
- package/dist/utils/chord/key-names.js +52 -0
- package/dist/utils/column-step/column-step.d.ts +13 -0
- package/dist/utils/column-step/column-step.js +9 -0
- package/dist/utils/count-label/count-label.d.ts +7 -4
- package/dist/utils/count-label/count-label.js +2 -5
- package/dist/utils/data-options/data-options.d.ts +60 -0
- package/dist/utils/data-options/data-options.js +46 -0
- package/dist/utils/date-segments/date-segments.d.ts +2 -1
- package/dist/utils/date-segments/date-segments.js +10 -0
- package/dist/utils/draw-tooltip/draw-tooltip.d.ts +7 -2
- package/dist/utils/draw-tooltip/draw-tooltip.js +1 -1
- package/dist/utils/draw-tooltip/spoken-reading.d.ts +3 -2
- package/dist/utils/draw-tooltip/spoken-reading.js +3 -2
- package/dist/utils/export-parts/export-parts.d.ts +14 -0
- package/dist/utils/export-parts/export-parts.js +1 -0
- package/dist/utils/fill-template/fill-template.d.ts +9 -0
- package/dist/utils/fill-template/fill-template.js +3 -0
- package/dist/utils/filter-marks/filter-marks.d.ts +36 -0
- package/dist/utils/filter-marks/filter-marks.js +41 -0
- package/dist/utils/focus-target/focus-target.d.ts +12 -0
- package/dist/utils/focus-target/focus-target.js +9 -0
- package/dist/utils/focusable-elements/focusable-elements.d.ts +17 -0
- package/dist/utils/focusable-elements/focusable-elements.js +8 -0
- package/dist/utils/grid-move/grid-move.d.ts +56 -0
- package/dist/utils/grid-move/grid-move.js +28 -0
- package/dist/utils/locale-of/locale-of.d.ts +5 -0
- package/dist/utils/locale-of/locale-of.js +8 -2
- package/dist/utils/number-format/number-format.d.ts +7 -0
- package/dist/utils/number-format/number-format.js +1 -0
- package/dist/utils/reorder/drag-preview.d.ts +46 -0
- package/dist/utils/reorder/drag-preview.js +58 -0
- package/dist/utils/reorder/reorder.d.ts +178 -0
- package/dist/utils/reorder/reorder.js +112 -0
- package/dist/utils/report-runtime/report-runtime.d.ts +14 -5
- package/dist/utils/report-values/report-values.d.ts +16 -4
- package/dist/utils/report-values/report-values.js +2 -2
- package/dist/utils/request-change/request-change.d.ts +11 -0
- package/dist/utils/request-change/request-change.js +10 -0
- package/dist/utils/scroll-item-into-view/scroll-item-into-view.d.ts +17 -0
- package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +1 -0
- package/dist/utils/slot-filled/slot-filled.d.ts +8 -0
- package/dist/utils/slot-filled/slot-filled.js +1 -0
- package/dist/utils/slotted-words/slotted-words.d.ts +3 -2
- package/dist/utils/slotted-words/slotted-words.js +3 -1
- package/dist/utils/toolbar-around/toolbar-around.d.ts +18 -0
- package/dist/utils/toolbar-around/toolbar-around.js +5 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/words/index.d.ts +3 -0
- package/dist/words/index.js +3 -0
- package/dist/words/message.d.ts +47 -0
- package/dist/words/message.js +152 -0
- package/dist/words/registry.d.ts +89 -0
- package/dist/words/registry.js +101 -0
- package/dist/words/words-locale.d.ts +34 -0
- package/dist/words/words-locale.js +30 -0
- package/dist/words/words.d.ts +52 -0
- package/dist/words/words.js +100 -0
- package/package.json +40 -25
|
@@ -52,6 +52,11 @@ export declare class MixinTokensInterface {
|
|
|
52
52
|
* either way and this is what says what pressing it does.
|
|
53
53
|
*/
|
|
54
54
|
collapseLabel: string;
|
|
55
|
+
/**
|
|
56
|
+
* The count of the tokens past `max-tags`, as it is shown, with `{count}`
|
|
57
|
+
* for the number, written in the element's locale. `+{count}` by default.
|
|
58
|
+
*/
|
|
59
|
+
restText: string;
|
|
55
60
|
/**
|
|
56
61
|
* The cap in force right now, which is none while the reader has expanded it.
|
|
57
62
|
*
|
|
@@ -8,6 +8,7 @@ import { caretUp } from '@fusion.dev/helix-icons';
|
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { drawIcon } from '../../utils/draw-icon/draw-icon.js';
|
|
11
|
+
import { formatWords, words } from '../../words/words.js';
|
|
11
12
|
export const MixinTokens = (Base) => {
|
|
12
13
|
class TokensElement extends Base {
|
|
13
14
|
constructor() {
|
|
@@ -16,11 +17,13 @@ export const MixinTokens = (Base) => {
|
|
|
16
17
|
this.expandable = false;
|
|
17
18
|
this.expandLabel = 'Show all';
|
|
18
19
|
this.maxTags = 0;
|
|
20
|
+
this.restText = '+{count}';
|
|
19
21
|
this.expanded = false;
|
|
20
22
|
this.toggleExpanded = () => {
|
|
21
23
|
this.expanded = !this.expanded;
|
|
22
24
|
};
|
|
23
25
|
}
|
|
26
|
+
static { this.words = ''; }
|
|
24
27
|
get shownLimit() {
|
|
25
28
|
return this.expanded ? 0 : this.maxTags;
|
|
26
29
|
}
|
|
@@ -29,7 +32,9 @@ export const MixinTokens = (Base) => {
|
|
|
29
32
|
}
|
|
30
33
|
renderRest(over) {
|
|
31
34
|
if (!this.expandable) {
|
|
32
|
-
return over > 0
|
|
35
|
+
return over > 0
|
|
36
|
+
? html `<span part="rest">${formatWords(this, 'restText', { count: over })}</span>`
|
|
37
|
+
: nothing;
|
|
33
38
|
}
|
|
34
39
|
if (over < 1 && !this.expanded) {
|
|
35
40
|
return nothing;
|
|
@@ -39,7 +44,7 @@ export const MixinTokens = (Base) => {
|
|
|
39
44
|
type="button"
|
|
40
45
|
aria-label=${this.expanded ? this.collapseLabel : this.expandLabel}
|
|
41
46
|
@click=${this.toggleExpanded}
|
|
42
|
-
>${this.expanded ? drawIcon(caretUp) :
|
|
47
|
+
>${this.expanded ? drawIcon(caretUp) : formatWords(this, 'restText', { count: over })}</button
|
|
43
48
|
>`;
|
|
44
49
|
}
|
|
45
50
|
hideOverflow(slot) {
|
|
@@ -64,17 +69,23 @@ export const MixinTokens = (Base) => {
|
|
|
64
69
|
removeLastToken() { }
|
|
65
70
|
}
|
|
66
71
|
__decorate([
|
|
72
|
+
words,
|
|
67
73
|
property({ attribute: 'collapse-label' })
|
|
68
74
|
], TokensElement.prototype, "collapseLabel", void 0);
|
|
69
75
|
__decorate([
|
|
70
76
|
property({ type: Boolean })
|
|
71
77
|
], TokensElement.prototype, "expandable", void 0);
|
|
72
78
|
__decorate([
|
|
79
|
+
words,
|
|
73
80
|
property({ attribute: 'expand-label' })
|
|
74
81
|
], TokensElement.prototype, "expandLabel", void 0);
|
|
75
82
|
__decorate([
|
|
76
83
|
property({ attribute: 'max-tags', type: Number })
|
|
77
84
|
], TokensElement.prototype, "maxTags", void 0);
|
|
85
|
+
__decorate([
|
|
86
|
+
words,
|
|
87
|
+
property({ attribute: 'rest-text' })
|
|
88
|
+
], TokensElement.prototype, "restText", void 0);
|
|
78
89
|
__decorate([
|
|
79
90
|
state()
|
|
80
91
|
], TokensElement.prototype, "expanded", void 0);
|
|
@@ -15,7 +15,13 @@ export type ViewportGestures = 'activate' | 'always' | 'cooperative';
|
|
|
15
15
|
* the cooperative set, or none, while an `activate` surface waits to be pressed.
|
|
16
16
|
*/
|
|
17
17
|
export type ViewportGestureMode = 'cooperative' | 'free' | 'off';
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The words a surface says about its gestures.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Each family declares its gesture words as word properties,
|
|
22
|
+
* `activate-hint-label` and its three, which a page registers by locale.
|
|
23
|
+
* Removed in the next major version.
|
|
24
|
+
*/
|
|
19
25
|
export interface ViewportGestureLabels {
|
|
20
26
|
/** The hint while an `activate` surface waits to be pressed. */
|
|
21
27
|
activate: string;
|
|
@@ -38,18 +44,16 @@ export declare class ViewportElement {
|
|
|
38
44
|
fullscreenLabel: string;
|
|
39
45
|
/** Which gestures the surface takes from the page. Unset is the family's own. */
|
|
40
46
|
gestures?: ViewportGestures;
|
|
41
|
-
/** The hint while a surface with `gestures="activate"` waits to be pressed. */
|
|
42
|
-
activateHintLabel
|
|
43
|
-
/** The hint when one finger swipes over a surface with `gestures="cooperative"
|
|
44
|
-
twoFingerHintLabel
|
|
45
|
-
/** The line while a surface with `gestures="activate"` has the gestures. */
|
|
46
|
-
usingLabel
|
|
47
|
-
/** The hint when the wheel scrolls past a surface with `gestures="cooperative"`, with `{key}
|
|
48
|
-
wheelHintLabel
|
|
47
|
+
/** The hint while a surface with `gestures="activate"` waits to be pressed, a word property each family declares. */
|
|
48
|
+
activateHintLabel: string;
|
|
49
|
+
/** The hint when one finger swipes over a surface with `gestures="cooperative"`, a word property each family declares. */
|
|
50
|
+
twoFingerHintLabel: string;
|
|
51
|
+
/** The line while a surface with `gestures="activate"` has the gestures, a word property each family declares. */
|
|
52
|
+
usingLabel: string;
|
|
53
|
+
/** The hint when the wheel scrolls past a surface with `gestures="cooperative"`, with `{key}`, a word property each family declares. */
|
|
54
|
+
wheelHintLabel: string;
|
|
49
55
|
/** @internal Which gestures the thing drawing the surface takes right now. */
|
|
50
56
|
get gestureMode(): ViewportGestureMode;
|
|
51
|
-
/** What the surface says about its gestures where the page does not say it, which each family says for itself. */
|
|
52
|
-
protected get restingGestureLabels(): ViewportGestureLabels;
|
|
53
57
|
/** Whether an `activate` surface has been pressed, and has the gestures. */
|
|
54
58
|
protected gesturesTaken: boolean;
|
|
55
59
|
/** Whether a gesture that started with this event is the surface's to answer. */
|
|
@@ -92,10 +96,8 @@ export declare class ViewportElement {
|
|
|
92
96
|
protected readonly fullscreen: FullscreenController;
|
|
93
97
|
/** The key relay, bound by the family's own frame. */
|
|
94
98
|
protected handleKeydown: (event: KeyboardEvent) => void;
|
|
95
|
-
/** The name of the group of controls, read by screen readers. */
|
|
96
|
-
controlsLabel: string
|
|
97
|
-
/** What the group of controls is called where the page does not say, which each family says for itself. */
|
|
98
|
-
protected get restingControlsLabel(): string;
|
|
99
|
+
/** The name of the group of controls, read by screen readers, a word property each family declares. */
|
|
100
|
+
controlsLabel: string;
|
|
99
101
|
/** The pan event, built and not dispatched, for a family that names its own. */
|
|
100
102
|
protected panEvent(detail: ViewportPanDetail): Event;
|
|
101
103
|
/** The zoom event, built and not dispatched, for a family that names its own. */
|
|
@@ -8,9 +8,9 @@ import { html, nothing } from 'lit';
|
|
|
8
8
|
import { property, state } from 'lit/decorators.js';
|
|
9
9
|
import { FullscreenController } from '../../controllers/fullscreen-controller/fullscreen-controller.js';
|
|
10
10
|
import { IdleController } from '../../controllers/idle-controller/idle-controller.js';
|
|
11
|
-
import { fillTemplate } from '../../utils/fill-template/fill-template.js';
|
|
12
11
|
import { inlineStep } from '../../utils/inline-step/inline-step.js';
|
|
13
12
|
import { isRtl } from '../../utils/is-rtl/is-rtl.js';
|
|
13
|
+
import { formatWords, words } from '../../words/words.js';
|
|
14
14
|
const HINT_SHOWS = 1600;
|
|
15
15
|
export const MixinViewport = (Base) => {
|
|
16
16
|
class Viewport extends Base {
|
|
@@ -38,11 +38,10 @@ export const MixinViewport = (Base) => {
|
|
|
38
38
|
this.handleGestureWheel = (event) => {
|
|
39
39
|
if (this.gestures === 'cooperative' && !(event.ctrlKey || event.metaKey)) {
|
|
40
40
|
const mac = typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac');
|
|
41
|
-
|
|
42
|
-
this.showHint(fillTemplate(words, { key: mac ? '⌘' : 'Ctrl' }), event);
|
|
41
|
+
this.showHint(formatWords(this, 'wheelHintLabel', { key: mac ? '⌘' : 'Ctrl' }), event);
|
|
43
42
|
}
|
|
44
43
|
else if (this.gestures === 'activate' && !this.gesturesTaken) {
|
|
45
|
-
this.showHint(this.activateHintLabel
|
|
44
|
+
this.showHint(this.activateHintLabel, event);
|
|
46
45
|
}
|
|
47
46
|
};
|
|
48
47
|
this.handleGestureTouch = (event) => {
|
|
@@ -51,10 +50,10 @@ export const MixinViewport = (Base) => {
|
|
|
51
50
|
return;
|
|
52
51
|
}
|
|
53
52
|
if (this.gestures === 'cooperative') {
|
|
54
|
-
this.showHint(this.twoFingerHintLabel
|
|
53
|
+
this.showHint(this.twoFingerHintLabel, finger);
|
|
55
54
|
}
|
|
56
55
|
else if (this.gestures === 'activate' && !this.gesturesTaken) {
|
|
57
|
-
this.showHint(this.activateHintLabel
|
|
56
|
+
this.showHint(this.activateHintLabel, finger);
|
|
58
57
|
}
|
|
59
58
|
};
|
|
60
59
|
this.handleTake = (event) => {
|
|
@@ -133,17 +132,7 @@ export const MixinViewport = (Base) => {
|
|
|
133
132
|
}
|
|
134
133
|
};
|
|
135
134
|
}
|
|
136
|
-
|
|
137
|
-
return 'View controls';
|
|
138
|
-
}
|
|
139
|
-
get restingGestureLabels() {
|
|
140
|
-
return {
|
|
141
|
-
activate: 'Press to use it',
|
|
142
|
-
twoFinger: 'Use two fingers to move it',
|
|
143
|
-
using: 'In use. Press Escape to scroll the page again.',
|
|
144
|
-
wheel: 'Use {key} and scroll to zoom',
|
|
145
|
-
};
|
|
146
|
-
}
|
|
135
|
+
static { this.words = ''; }
|
|
147
136
|
get gestureMode() {
|
|
148
137
|
if (this.gestures === 'cooperative') {
|
|
149
138
|
return 'cooperative';
|
|
@@ -215,7 +204,7 @@ export const MixinViewport = (Base) => {
|
|
|
215
204
|
?hidden=${this.hint === ''}
|
|
216
205
|
style=${at ? `--_viewport-hint-x: ${(at.x * 100).toFixed(2)}%; --_viewport-hint-y: ${(at.y * 100).toFixed(2)}%` : nothing}
|
|
217
206
|
>${this.hint}</div>
|
|
218
|
-
<div part="gesture-status" aria-hidden="true" ?hidden=${!this.gesturesTaken}>${this.usingLabel
|
|
207
|
+
<div part="gesture-status" aria-hidden="true" ?hidden=${!this.gesturesTaken}>${this.usingLabel}</div>`;
|
|
219
208
|
}
|
|
220
209
|
panEvent(_detail) {
|
|
221
210
|
throw new Error(`<${this.localName}> composes MixinViewport and must implement panEvent(), the surface naming no event of its own.`);
|
|
@@ -286,27 +275,28 @@ export const MixinViewport = (Base) => {
|
|
|
286
275
|
if (!pan && !zoom && !fullscreen && more === nothing) {
|
|
287
276
|
return nothing;
|
|
288
277
|
}
|
|
289
|
-
|
|
278
|
+
const [up, start, end, down] = ['up', 'start', 'end', 'down'].map((way) => this.panGlyph(way));
|
|
279
|
+
return html `<div part="controls" role="group" aria-label=${this.controlsLabel}>
|
|
290
280
|
${pan
|
|
291
281
|
? html `<button part="pan-up" aria-label=${this.panLabel('up')} type="button" @click=${() => this.pan('up')}>
|
|
292
|
-
|
|
282
|
+
<slot name="pan-up-icon">${up}</slot>
|
|
293
283
|
</button>
|
|
294
284
|
<button part="pan-start" aria-label=${this.panLabel('start')} type="button" @click=${() => this.pan('start')}>
|
|
295
|
-
|
|
285
|
+
<slot name="pan-start-icon">${start}</slot>
|
|
296
286
|
</button>
|
|
297
287
|
<button part="pan-end" aria-label=${this.panLabel('end')} type="button" @click=${() => this.pan('end')}>
|
|
298
|
-
|
|
288
|
+
<slot name="pan-end-icon">${end}</slot>
|
|
299
289
|
</button>
|
|
300
290
|
<button part="pan-down" aria-label=${this.panLabel('down')} type="button" @click=${() => this.pan('down')}>
|
|
301
|
-
|
|
291
|
+
<slot name="pan-down-icon">${down}</slot>
|
|
302
292
|
</button>`
|
|
303
293
|
: nothing}
|
|
304
294
|
${zoom
|
|
305
295
|
? html `<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
|
|
306
|
-
|
|
296
|
+
<slot name="zoom-in-icon">+</slot>
|
|
307
297
|
</button>
|
|
308
298
|
<button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
|
|
309
|
-
|
|
299
|
+
<slot name="zoom-out-icon">−</slot>
|
|
310
300
|
</button>`
|
|
311
301
|
: nothing}
|
|
312
302
|
${more}
|
|
@@ -318,25 +308,20 @@ export const MixinViewport = (Base) => {
|
|
|
318
308
|
type="button"
|
|
319
309
|
@click=${this.toggleFullscreen}
|
|
320
310
|
>
|
|
321
|
-
|
|
311
|
+
<slot name="fullscreen-icon">⤢</slot>
|
|
322
312
|
</button>`
|
|
323
313
|
: nothing}
|
|
324
314
|
</div>`;
|
|
325
315
|
}
|
|
326
316
|
}
|
|
327
|
-
__decorate([
|
|
328
|
-
property({ attribute: 'activate-hint-label' })
|
|
329
|
-
], Viewport.prototype, "activateHintLabel", void 0);
|
|
330
317
|
__decorate([
|
|
331
318
|
property({ reflect: true })
|
|
332
319
|
], Viewport.prototype, "controls", void 0);
|
|
333
|
-
__decorate([
|
|
334
|
-
property({ attribute: 'controls-label' })
|
|
335
|
-
], Viewport.prototype, "controlsLabel", void 0);
|
|
336
320
|
__decorate([
|
|
337
321
|
property({ attribute: 'controls-placement', reflect: true })
|
|
338
322
|
], Viewport.prototype, "controlsPlacement", void 0);
|
|
339
323
|
__decorate([
|
|
324
|
+
words,
|
|
340
325
|
property({ attribute: 'fullscreen-label' })
|
|
341
326
|
], Viewport.prototype, "fullscreenLabel", void 0);
|
|
342
327
|
__decorate([
|
|
@@ -346,30 +331,26 @@ export const MixinViewport = (Base) => {
|
|
|
346
331
|
property({ attribute: 'idle-delay', type: Number })
|
|
347
332
|
], Viewport.prototype, "idleDelay", void 0);
|
|
348
333
|
__decorate([
|
|
334
|
+
words,
|
|
349
335
|
property({ attribute: 'pan-down-label' })
|
|
350
336
|
], Viewport.prototype, "panDownLabel", void 0);
|
|
351
337
|
__decorate([
|
|
338
|
+
words,
|
|
352
339
|
property({ attribute: 'pan-left-label' })
|
|
353
340
|
], Viewport.prototype, "panLeftLabel", void 0);
|
|
354
341
|
__decorate([
|
|
342
|
+
words,
|
|
355
343
|
property({ attribute: 'pan-right-label' })
|
|
356
344
|
], Viewport.prototype, "panRightLabel", void 0);
|
|
357
345
|
__decorate([
|
|
358
346
|
property({ attribute: 'pan-step', type: Number })
|
|
359
347
|
], Viewport.prototype, "panStep", void 0);
|
|
360
348
|
__decorate([
|
|
349
|
+
words,
|
|
361
350
|
property({ attribute: 'pan-up-label' })
|
|
362
351
|
], Viewport.prototype, "panUpLabel", void 0);
|
|
363
352
|
__decorate([
|
|
364
|
-
|
|
365
|
-
], Viewport.prototype, "twoFingerHintLabel", void 0);
|
|
366
|
-
__decorate([
|
|
367
|
-
property({ attribute: 'using-label' })
|
|
368
|
-
], Viewport.prototype, "usingLabel", void 0);
|
|
369
|
-
__decorate([
|
|
370
|
-
property({ attribute: 'wheel-hint-label' })
|
|
371
|
-
], Viewport.prototype, "wheelHintLabel", void 0);
|
|
372
|
-
__decorate([
|
|
353
|
+
words,
|
|
373
354
|
property({ attribute: 'zoom-in-label' })
|
|
374
355
|
], Viewport.prototype, "zoomInLabel", void 0);
|
|
375
356
|
__decorate([
|
|
@@ -388,6 +369,7 @@ export const MixinViewport = (Base) => {
|
|
|
388
369
|
state()
|
|
389
370
|
], Viewport.prototype, "hintAt", void 0);
|
|
390
371
|
__decorate([
|
|
372
|
+
words,
|
|
391
373
|
property({ attribute: 'zoom-out-label' })
|
|
392
374
|
], Viewport.prototype, "zoomOutLabel", void 0);
|
|
393
375
|
return Viewport;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sends each child to the slot it names, and every other child to the default
|
|
3
|
+
* slot, in a shadow root that assigns its slots by hand.
|
|
4
|
+
*
|
|
5
|
+
* **A root that assigns by hand routes nothing by itself**, its named slots
|
|
6
|
+
* included, so a header, a footer or an empty state slotted by name reaches
|
|
7
|
+
* nothing unless it is assigned here too. `place` says where a child goes when
|
|
8
|
+
* the host decides it, a row to its list or a card to the slot the layout drew
|
|
9
|
+
* for it, and a child it gives no slot to goes where its `slot` attribute says,
|
|
10
|
+
* as it would under the default assignment.
|
|
11
|
+
*
|
|
12
|
+
* **A slot already holding exactly what it would be given is left alone**, so
|
|
13
|
+
* calling this after every update fires no `slotchange` that nothing changed.
|
|
14
|
+
*
|
|
15
|
+
* Pair it with `ChildrenController`, which calls back when a child arrives
|
|
16
|
+
* after the first render, the case no `slotchange` reports.
|
|
17
|
+
*/
|
|
18
|
+
export declare const assignSlots: (root: ParentNode | null | undefined, children: Iterable<Element>, place?: (child: Element) => string | undefined) => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const assignSlots = (root, children, place = () => undefined) => {
|
|
2
|
+
const named = new Map();
|
|
3
|
+
for (const child of children) {
|
|
4
|
+
const name = place(child) ?? child.getAttribute('slot') ?? '';
|
|
5
|
+
named.set(name, [...(named.get(name) ?? []), child]);
|
|
6
|
+
}
|
|
7
|
+
for (const slot of root?.querySelectorAll?.('slot') ?? []) {
|
|
8
|
+
const wanted = named.get(slot.name) ?? [];
|
|
9
|
+
const had = slot.assignedNodes();
|
|
10
|
+
if (had.length !== wanted.length || had.some((one, at) => one !== wanted[at])) {
|
|
11
|
+
slot.assign?.(...wanted);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { nothing, type TemplateResult } from 'lit';
|
|
2
|
+
/** What the hidden native select offers a browser's autofill, and what it does with the answer. */
|
|
3
|
+
export interface DrawAutofillOptions {
|
|
4
|
+
/** The autofill token, such as `country` or `cc-exp-month`. Empty draws nothing. */
|
|
5
|
+
autocomplete: string;
|
|
6
|
+
/** Whether the select is disabled, which takes it out of autofill too. */
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
/** Whether more than one option can be chosen. */
|
|
9
|
+
multiple: boolean;
|
|
10
|
+
/** Takes what the browser filled in, as a value: several are joined by commas. */
|
|
11
|
+
onFill: (value: string) => void;
|
|
12
|
+
/** The options, each with its value and its words, in order. */
|
|
13
|
+
options: readonly {
|
|
14
|
+
text: string;
|
|
15
|
+
value: string;
|
|
16
|
+
}[];
|
|
17
|
+
/** The value now, several joined by commas. */
|
|
18
|
+
value: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A native `<select>` that a browser's autofill can fill, holding the same
|
|
22
|
+
* options as the custom select beside it. Select, Combobox and Listbox draw it
|
|
23
|
+
* under `autocomplete`.
|
|
24
|
+
*
|
|
25
|
+
* **A browser fills native fields only.** It reads `autocomplete`, picks an
|
|
26
|
+
* option by its value or its words, and sends `change`, which `onFill` turns
|
|
27
|
+
* into the custom select's value. Chromium fills a select inside a shadow root
|
|
28
|
+
* when its host is inside the form being filled.
|
|
29
|
+
*
|
|
30
|
+
* **The select's own `input` stops here.** It is composed, so it crossed the
|
|
31
|
+
* shadow root and reached the host before `change` did, with the host's value
|
|
32
|
+
* still the old one: measured in Chromium, a fill sent a page's `input`
|
|
33
|
+
* listener two events, the first carrying the old value. The host sends its
|
|
34
|
+
* own `input` and `change` once the value is taken.
|
|
35
|
+
*
|
|
36
|
+
* **Hidden from everyone but the browser**: clipped to a pixel, `aria-hidden`,
|
|
37
|
+
* and out of the tab order, with no `name`, so the form still receives the
|
|
38
|
+
* value once, from the custom select itself.
|
|
39
|
+
*/
|
|
40
|
+
export declare const drawAutofill: ({ autocomplete, disabled, multiple, onFill, options, value, }: DrawAutofillOptions) => TemplateResult | typeof nothing;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { html, nothing } from 'lit';
|
|
2
|
+
const HIDDEN = 'position:fixed;top:0;left:0;width:1px;height:1px;opacity:0;pointer-events:none';
|
|
3
|
+
export const drawAutofill = ({ autocomplete, disabled, multiple, onFill, options, value, }) => {
|
|
4
|
+
if (autocomplete === '') {
|
|
5
|
+
return nothing;
|
|
6
|
+
}
|
|
7
|
+
const chosen = value.split(',');
|
|
8
|
+
const fill = (event) => onFill([...event.currentTarget.selectedOptions]
|
|
9
|
+
.map((option) => option.value)
|
|
10
|
+
.filter(Boolean)
|
|
11
|
+
.join(','));
|
|
12
|
+
const stop = (event) => event.stopPropagation();
|
|
13
|
+
return html `<select aria-hidden="true" autocomplete=${autocomplete} style=${HIDDEN} tabindex="-1" ?disabled=${disabled} ?multiple=${multiple} @change=${fill} @input=${stop}><option value=""></option>${options.map((option) => html `<option value=${option.value} ?selected=${chosen.includes(option.value)}>${option.text}</option>`)}</select>`;
|
|
14
|
+
};
|
|
@@ -16,6 +16,33 @@ export declare const localToday: (now?: Date) => string;
|
|
|
16
16
|
* neither, as Firefox does not, or where the tag cannot be read.
|
|
17
17
|
*/
|
|
18
18
|
export declare const weekStartOf: (locale: string) => number;
|
|
19
|
+
/**
|
|
20
|
+
* The calendars a date family draws and writes: those whose months are the
|
|
21
|
+
* Gregorian months, so a grid of Gregorian days is one of their months.
|
|
22
|
+
*
|
|
23
|
+
* `buddhist` is Thailand's (2569 for 2026), `japanese` the Japanese eras
|
|
24
|
+
* (Reiwa 8), and `roc` Taiwan's Minguo years (115). They differ from
|
|
25
|
+
* `gregory` in the year alone, and `iso8601` in the order the parts are
|
|
26
|
+
* written.
|
|
27
|
+
*/
|
|
28
|
+
export type DateCalendar = 'buddhist' | 'gregory' | 'iso8601' | 'japanese' | 'roc';
|
|
29
|
+
/**
|
|
30
|
+
* The language tag a date family formats with: `locale`, with the calendar it
|
|
31
|
+
* writes dates in.
|
|
32
|
+
*
|
|
33
|
+
* That is `calendar` where it is one of the five `DateCalendar` names, then
|
|
34
|
+
* the locale's own calendar where its months are the Gregorian months, then
|
|
35
|
+
* `gregory`. **A calendar with months of its own, such as `persian` for `fa-IR`
|
|
36
|
+
* or `islamic-umalqura` for `ar-SA` in some engines, is written as `gregory`.**
|
|
37
|
+
* The arithmetic is Gregorian, so a heading in Mehr 1405 over the days of
|
|
38
|
+
* October 2026 named a month the grid did not show.
|
|
39
|
+
*
|
|
40
|
+
* `locale` unchanged where nothing moves, so a page in a Gregorian locale
|
|
41
|
+
* formats exactly as it did. Empty is the runtime's own locale. A tag `Intl`
|
|
42
|
+
* refuses throws, as every formatter given one does. Remembered per locale and
|
|
43
|
+
* calendar, since reading a locale's calendar builds a formatter.
|
|
44
|
+
*/
|
|
45
|
+
export declare const calendarLocale: (locale: string, calendar?: string) => string;
|
|
19
46
|
/** A month as `YYYY-MM`. */
|
|
20
47
|
export declare const monthOf: (date: Date) => string;
|
|
21
48
|
/** A date some days away, which may be negative, at midnight UTC. */
|
|
@@ -15,6 +15,23 @@ export const weekStartOf = (locale) => {
|
|
|
15
15
|
return 0;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
+
const DRAWN = ['buddhist', 'gregory', 'iso8601', 'japanese', 'roc'];
|
|
19
|
+
const tagged = new Map();
|
|
20
|
+
export const calendarLocale = (locale, calendar = '') => {
|
|
21
|
+
const key = `${locale} ${calendar}`;
|
|
22
|
+
let tag = tagged.get(key);
|
|
23
|
+
if (tag === undefined) {
|
|
24
|
+
const own = new Intl.DateTimeFormat(locale || undefined).resolvedOptions();
|
|
25
|
+
const wanted = DRAWN.includes(calendar)
|
|
26
|
+
? calendar
|
|
27
|
+
: DRAWN.includes(own.calendar)
|
|
28
|
+
? ''
|
|
29
|
+
: 'gregory';
|
|
30
|
+
tag = wanted ? `${new Intl.Locale(locale || own.locale, { calendar: wanted })}` : locale;
|
|
31
|
+
tagged.set(key, tag);
|
|
32
|
+
}
|
|
33
|
+
return tag;
|
|
34
|
+
};
|
|
18
35
|
export const monthOf = (date) => `${String(date.getUTCFullYear()).padStart(4, '0')}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`;
|
|
19
36
|
export const addDays = (date, days) => utcDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days);
|
|
20
37
|
export const sameMonth = (left, right) => left.getUTCFullYear() === right.getUTCFullYear() && left.getUTCMonth() === right.getUTCMonth();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrolls `box` to put `item`, one of the things it scrolls, in its middle.
|
|
3
|
+
*
|
|
4
|
+
* For a list read as a dial rather than scanned, as Time Picker's wheels read
|
|
5
|
+
* a Listbox. A delta from the two boxes rather than `offsetTop`: a slotted
|
|
6
|
+
* item's `offsetParent` is whatever is positioned above it, which is not the
|
|
7
|
+
* box and is not guaranteed to be anything.
|
|
8
|
+
*
|
|
9
|
+
* **Twice, and the second pass is not superstition.** The first delta is
|
|
10
|
+
* computed against whatever layout is current when this is called, and inside
|
|
11
|
+
* a panel that has just been revealed it is a frame behind: measured, one call
|
|
12
|
+
* landed a whole row short, 672 where 704 was wanted, and calling it again
|
|
13
|
+
* from a settled layout put it exactly on center. Reading a rect forces
|
|
14
|
+
* layout, so the second pass sees the result of the first and corrects the
|
|
15
|
+
* remainder. It stops as soon as there is nothing left to correct, and where
|
|
16
|
+
* either box has no height, as on a page not laid out.
|
|
17
|
+
*/
|
|
18
|
+
export declare const centerInView: (box: HTMLElement, item: Element) => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const centerInView = (box, item) => {
|
|
2
|
+
for (let pass = 0; pass < 2; pass += 1) {
|
|
3
|
+
const outer = box.getBoundingClientRect();
|
|
4
|
+
const inner = item.getBoundingClientRect();
|
|
5
|
+
if (outer.height === 0 || inner.height === 0) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const off = inner.top + inner.height / 2 - (outer.top + outer.height / 2);
|
|
9
|
+
if (Math.abs(off) < 1) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
box.scrollTop += off;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words and glyphs a chord is drawn with, per platform.
|
|
3
|
+
*
|
|
4
|
+
* In core beside `ariaChord`, which says a chord to a reader as this draws it
|
|
5
|
+
* for the eye: Kbd draws a chord with it, and Speed Dial draws an action's
|
|
6
|
+
* shortcut with it where nothing is slotted, without importing Kbd.
|
|
7
|
+
*/
|
|
8
|
+
/** A chord's keys as they are shown, and what is shown between two of them. */
|
|
9
|
+
export interface KeyNames {
|
|
10
|
+
/** Each key's label, in the order the chord names them. */
|
|
11
|
+
keys: string[];
|
|
12
|
+
/** What goes between two keys: `+`, a hyphen, or nothing. */
|
|
13
|
+
separator: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The labels of a chord's keys on a platform, with `own` labels in place of
|
|
17
|
+
* the platform's, and what goes between two keys.
|
|
18
|
+
*
|
|
19
|
+
* `parts` are the chord's names as `chordParts` splits them. A name `own`
|
|
20
|
+
* holds takes that label, a name the platform knows takes its glyph or word,
|
|
21
|
+
* and any other single character is shown in capitals.
|
|
22
|
+
*
|
|
23
|
+
* **On an Apple keyboard glyphs run together and words are joined with a
|
|
24
|
+
* hyphen**, as Apple writes `Command-K`. A label of more than one character
|
|
25
|
+
* from `own` is a word, so `{"mod": "Command"}` shows `Command-K` there, where
|
|
26
|
+
* nothing between the two ran them into `CommandK`. The platform's own `Esc`
|
|
27
|
+
* and `Space` keep running on from a glyph, as `⌘Esc` always has. Everywhere
|
|
28
|
+
* else keys are joined with `+`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const keyNames: (parts: readonly string[], apple: boolean, own?: Readonly<Record<string, string>>) => KeyNames;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const APPLE = {
|
|
2
|
+
alt: '⌥',
|
|
3
|
+
backspace: '⌫',
|
|
4
|
+
cmd: '⌘',
|
|
5
|
+
ctrl: '⌃',
|
|
6
|
+
del: '⌦',
|
|
7
|
+
down: '↓',
|
|
8
|
+
enter: '↵',
|
|
9
|
+
esc: 'Esc',
|
|
10
|
+
left: '←',
|
|
11
|
+
meta: '⌘',
|
|
12
|
+
mod: '⌘',
|
|
13
|
+
opt: '⌥',
|
|
14
|
+
right: '→',
|
|
15
|
+
shift: '⇧',
|
|
16
|
+
space: 'Space',
|
|
17
|
+
tab: '⇥',
|
|
18
|
+
up: '↑',
|
|
19
|
+
};
|
|
20
|
+
const ELSEWHERE = {
|
|
21
|
+
alt: 'Alt',
|
|
22
|
+
backspace: 'Backspace',
|
|
23
|
+
cmd: 'Win',
|
|
24
|
+
ctrl: 'Ctrl',
|
|
25
|
+
del: 'Del',
|
|
26
|
+
down: '↓',
|
|
27
|
+
enter: 'Enter',
|
|
28
|
+
esc: 'Esc',
|
|
29
|
+
left: '←',
|
|
30
|
+
meta: 'Win',
|
|
31
|
+
mod: 'Ctrl',
|
|
32
|
+
opt: 'Alt',
|
|
33
|
+
right: '→',
|
|
34
|
+
shift: 'Shift',
|
|
35
|
+
space: 'Space',
|
|
36
|
+
tab: 'Tab',
|
|
37
|
+
up: '↑',
|
|
38
|
+
};
|
|
39
|
+
export const keyNames = (parts, apple, own = {}) => {
|
|
40
|
+
const names = apple ? APPLE : ELSEWHERE;
|
|
41
|
+
let worded = false;
|
|
42
|
+
const keys = parts.map((part) => {
|
|
43
|
+
const name = part.toLowerCase();
|
|
44
|
+
const mine = own[name];
|
|
45
|
+
if (mine !== undefined) {
|
|
46
|
+
worded ||= [...mine].length > 1;
|
|
47
|
+
return mine;
|
|
48
|
+
}
|
|
49
|
+
return names[name] ?? (part.length === 1 ? part.toUpperCase() : part);
|
|
50
|
+
});
|
|
51
|
+
return { keys, separator: apple ? (worded ? '-' : '') : '+' };
|
|
52
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Up or Down moves in a list laid out in columns, as a grid of tiles or
|
|
3
|
+
* a wrapping row is: to the next item after `at` (with `by` of `1`) or the
|
|
4
|
+
* last one before it (`-1`) that starts at the same inline offset, which is
|
|
5
|
+
* the item above or below it. `at` itself where there is none, so the key
|
|
6
|
+
* stops at the edge, as React Aria's grid layout stops.
|
|
7
|
+
*
|
|
8
|
+
* Read from where the items are drawn rather than from a column count, so it
|
|
9
|
+
* holds for a grid of any width, a row that wraps, and a column cut short.
|
|
10
|
+
* `starts` are the items' inline offsets in the order of the list, such as
|
|
11
|
+
* each one's `getBoundingClientRect().left`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const columnStep: (starts: readonly number[], at: number, by: -1 | 1) => number;
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* **`Intl.PluralRules` picks the sentence**, because the line between "one"
|
|
6
6
|
* and "other" is the language's: French says "0 résultat" where English says
|
|
7
|
-
* "0 results".
|
|
8
|
-
*
|
|
7
|
+
* "0 results". Each sentence is a message, so `other` can hold every form a
|
|
8
|
+
* language has, `{count, plural, one {# wynik} few {# wyniki} many {# wyników}
|
|
9
|
+
* other {# wyniku}}`, and an empty `one` leaves the choice to it.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Kept for the families whose singular property is still read. A family on the
|
|
12
|
+
* words registry formats its one plural message with `formatWords`. Listbox
|
|
13
|
+
* says how many options a filter left this way, which Combobox and Command
|
|
14
|
+
* hand down to it.
|
|
12
15
|
*/
|
|
13
16
|
export declare const countLabel: (count: number, one: string, other: string, locale?: string) => string;
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export const countLabel = (count, one, other, locale = '') => fillTemplate(new Intl.PluralRules(locale || undefined).select(count) === 'one' ? one : other, {
|
|
4
|
-
count: formatNumbers(locale)(count),
|
|
5
|
-
});
|
|
1
|
+
import { formatMessage } from '../../words/message.js';
|
|
2
|
+
export const countLabel = (count, one, other, locale = '') => formatMessage(one && new Intl.PluralRules(locale || undefined).select(count) === 'one' ? one : other, { count }, locale);
|