@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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The state and the arithmetic of moving one item to a new place in its
|
|
3
|
+
* collection: rows of a list or a data table, or a table's columns.
|
|
4
|
+
*
|
|
5
|
+
* Pure, so every transition and every sum has a spec with no DOM.
|
|
6
|
+
* `ReorderController` holds the state, listens to the pointer and the keys, and
|
|
7
|
+
* runs the effects each change of state calls for.
|
|
8
|
+
*/
|
|
9
|
+
/** Which way a collection runs: rows down the block axis, columns along the inline one. */
|
|
10
|
+
export type ReorderAxis = 'block' | 'inline';
|
|
11
|
+
/** What holds the item: a key or a press on its grip, or a pointer dragging it. */
|
|
12
|
+
export type ReorderHold = 'keyboard' | 'pointer';
|
|
13
|
+
/**
|
|
14
|
+
* Where a move stands.
|
|
15
|
+
*
|
|
16
|
+
* - `idle`: nothing is held.
|
|
17
|
+
* - `pressed`: a pointer is down on a grip and has not traveled far enough to
|
|
18
|
+
* be a drag.
|
|
19
|
+
* - `held`: an item is held, and `to` is where it would go.
|
|
20
|
+
* - `dropped` and `canceled`: the move has ended, for one step, so the
|
|
21
|
+
* controller can run what each calls for before it settles to `idle`.
|
|
22
|
+
*
|
|
23
|
+
* `from` and `to` count from 0 in the order the items are drawn.
|
|
24
|
+
*/
|
|
25
|
+
export type ReorderState = {
|
|
26
|
+
phase: 'idle';
|
|
27
|
+
} | {
|
|
28
|
+
from: number;
|
|
29
|
+
key: string;
|
|
30
|
+
phase: 'pressed';
|
|
31
|
+
pointer: number;
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
} | {
|
|
35
|
+
by: ReorderHold;
|
|
36
|
+
from: number;
|
|
37
|
+
key: string;
|
|
38
|
+
phase: 'held';
|
|
39
|
+
to: number;
|
|
40
|
+
} | {
|
|
41
|
+
by: ReorderHold;
|
|
42
|
+
from: number;
|
|
43
|
+
key: string;
|
|
44
|
+
phase: 'dropped';
|
|
45
|
+
to: number;
|
|
46
|
+
} | {
|
|
47
|
+
by: ReorderHold;
|
|
48
|
+
key: string;
|
|
49
|
+
phase: 'canceled';
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* What can happen to a move.
|
|
53
|
+
*
|
|
54
|
+
* - `press`: a pointer went down on a grip.
|
|
55
|
+
* - `drag`: the pointer moved, and `to` is the place under it.
|
|
56
|
+
* - `release`: the pointer went up.
|
|
57
|
+
* - `pick`: a grip was pressed with a key or a click. It holds the item, or
|
|
58
|
+
* drops the item that grip already holds.
|
|
59
|
+
* - `step`: a key moved the held item to `to`.
|
|
60
|
+
* - `target`: a click on another item dropped the held one at `to`.
|
|
61
|
+
* - `drop` and `cancel`: Enter or Space, and Escape.
|
|
62
|
+
* - `settle`: the controller has run the effects of a drop or a cancel.
|
|
63
|
+
*/
|
|
64
|
+
export type ReorderInput = {
|
|
65
|
+
from: number;
|
|
66
|
+
key: string;
|
|
67
|
+
pointer: number;
|
|
68
|
+
type: 'press';
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
} | {
|
|
72
|
+
slop: number;
|
|
73
|
+
to: number;
|
|
74
|
+
type: 'drag';
|
|
75
|
+
x: number;
|
|
76
|
+
y: number;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'release';
|
|
79
|
+
} | {
|
|
80
|
+
from: number;
|
|
81
|
+
key: string;
|
|
82
|
+
type: 'pick';
|
|
83
|
+
} | {
|
|
84
|
+
to: number;
|
|
85
|
+
type: 'step';
|
|
86
|
+
} | {
|
|
87
|
+
to: number;
|
|
88
|
+
type: 'target';
|
|
89
|
+
} | {
|
|
90
|
+
type: 'cancel';
|
|
91
|
+
} | {
|
|
92
|
+
type: 'drop';
|
|
93
|
+
} | {
|
|
94
|
+
type: 'settle';
|
|
95
|
+
};
|
|
96
|
+
/** The state with nothing held. */
|
|
97
|
+
export declare const IDLE: ReorderState;
|
|
98
|
+
/**
|
|
99
|
+
* The state after an input, or `null` where the input changes nothing.
|
|
100
|
+
*
|
|
101
|
+
* A press becomes a drag only once the pointer has traveled `slop` pixels, so a
|
|
102
|
+
* click on a grip stays a click. A click on a grip holds the item for the
|
|
103
|
+
* keys, and a second click on the same grip drops it, which is the move a
|
|
104
|
+
* single pointer makes without dragging.
|
|
105
|
+
*/
|
|
106
|
+
export declare const reorderStep: (state: ReorderState, input: ReorderInput) => ReorderState | null;
|
|
107
|
+
/**
|
|
108
|
+
* How many of the other items the pointer has passed: the place the held item
|
|
109
|
+
* goes, among the others.
|
|
110
|
+
*
|
|
111
|
+
* `centers` are the middles of the other items along the axis, in the order
|
|
112
|
+
* drawn. `reversed` is a row laid out from the right, a right-to-left page,
|
|
113
|
+
* where passing an item means being left of its middle.
|
|
114
|
+
*/
|
|
115
|
+
export declare const passedCount: (centers: readonly number[], at: number, reversed?: boolean) => number;
|
|
116
|
+
/**
|
|
117
|
+
* The middles of the items along the axis, from their boxes, for
|
|
118
|
+
* `passedCount`.
|
|
119
|
+
*
|
|
120
|
+
* An item with no box is one a window did not draw. One before every drawn
|
|
121
|
+
* item counts as passed, one after them as not passed, and one between two
|
|
122
|
+
* drawn items as where the drawn one before it is. `reversed` is the same
|
|
123
|
+
* question on a row laid out from the right.
|
|
124
|
+
*/
|
|
125
|
+
export declare const centersOf: (spans: readonly ({
|
|
126
|
+
end: number;
|
|
127
|
+
start: number;
|
|
128
|
+
} | undefined)[], reversed?: boolean) => number[];
|
|
129
|
+
/**
|
|
130
|
+
* Where a key moves a held item, or `null` for a key that does not move one.
|
|
131
|
+
*
|
|
132
|
+
* The arrows along the axis move it one place, and Home and End move it to
|
|
133
|
+
* either end. Along the inline axis the arrows follow the writing direction,
|
|
134
|
+
* so on a right-to-left page the left arrow moves it forward. The answer is
|
|
135
|
+
* held to the collection, so an arrow at an end returns where it already is.
|
|
136
|
+
*/
|
|
137
|
+
export declare const reorderKey: (key: string, { axis, count, rtl, to }: {
|
|
138
|
+
axis: ReorderAxis;
|
|
139
|
+
count: number;
|
|
140
|
+
rtl: boolean;
|
|
141
|
+
to: number;
|
|
142
|
+
}) => number | null;
|
|
143
|
+
/**
|
|
144
|
+
* Where the drop indicator goes for a held item: before or after the item at
|
|
145
|
+
* an index of the order drawn, or nowhere while the item would stay where it
|
|
146
|
+
* is.
|
|
147
|
+
*
|
|
148
|
+
* Moving back, the item lands before the one now at `to`. Moving forward, it
|
|
149
|
+
* lands after it.
|
|
150
|
+
*/
|
|
151
|
+
export declare const dropMark: (from: number, to: number) => {
|
|
152
|
+
edge: 'after' | 'before';
|
|
153
|
+
index: number;
|
|
154
|
+
} | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* Every key in a new order: `key` taken out and put back at `to` among the
|
|
157
|
+
* shown ones.
|
|
158
|
+
*
|
|
159
|
+
* `all` is the whole order, which can hold keys that are not drawn: a hidden
|
|
160
|
+
* column, or a row a search left out. `shown` is the order drawn. The key goes
|
|
161
|
+
* after the shown one it now follows, or before the first shown one where it
|
|
162
|
+
* moves to the front, so a key that is not drawn keeps its place among the
|
|
163
|
+
* rest.
|
|
164
|
+
*/
|
|
165
|
+
export declare const placeKey: (all: readonly string[], shown: readonly string[], key: string, to: number) => string[];
|
|
166
|
+
/**
|
|
167
|
+
* How far to scroll a box in one frame while a held item is near one of its
|
|
168
|
+
* edges, in pixels: negative toward the start, positive toward the end, and 0
|
|
169
|
+
* away from both.
|
|
170
|
+
*
|
|
171
|
+
* `at` is the pointer along the axis, and `start` and `end` are the box's
|
|
172
|
+
* edges. The speed rises from nothing at `zone` pixels in to `most` at the
|
|
173
|
+
* edge and past it.
|
|
174
|
+
*/
|
|
175
|
+
export declare const edgeSpeed: (at: number, start: number, end: number, { most, zone }?: {
|
|
176
|
+
most?: number;
|
|
177
|
+
zone?: number;
|
|
178
|
+
}) => number;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export const IDLE = { phase: 'idle' };
|
|
2
|
+
export const reorderStep = (state, input) => {
|
|
3
|
+
switch (input.type) {
|
|
4
|
+
case 'press':
|
|
5
|
+
return state.phase === 'idle'
|
|
6
|
+
? {
|
|
7
|
+
from: input.from,
|
|
8
|
+
key: input.key,
|
|
9
|
+
phase: 'pressed',
|
|
10
|
+
pointer: input.pointer,
|
|
11
|
+
x: input.x,
|
|
12
|
+
y: input.y,
|
|
13
|
+
}
|
|
14
|
+
: null;
|
|
15
|
+
case 'drag':
|
|
16
|
+
if (state.phase === 'pressed') {
|
|
17
|
+
return Math.hypot(input.x - state.x, input.y - state.y) < input.slop
|
|
18
|
+
? null
|
|
19
|
+
: { by: 'pointer', from: state.from, key: state.key, phase: 'held', to: input.to };
|
|
20
|
+
}
|
|
21
|
+
return state.phase === 'held' && state.by === 'pointer' && state.to !== input.to
|
|
22
|
+
? { ...state, to: input.to }
|
|
23
|
+
: null;
|
|
24
|
+
case 'release':
|
|
25
|
+
if (state.phase === 'pressed') {
|
|
26
|
+
return IDLE;
|
|
27
|
+
}
|
|
28
|
+
return state.phase === 'held' && state.by === 'pointer'
|
|
29
|
+
? { ...state, phase: 'dropped' }
|
|
30
|
+
: null;
|
|
31
|
+
case 'pick':
|
|
32
|
+
if (state.phase === 'idle') {
|
|
33
|
+
return { by: 'keyboard', from: input.from, key: input.key, phase: 'held', to: input.from };
|
|
34
|
+
}
|
|
35
|
+
return state.phase === 'held' && state.by === 'keyboard' && state.key === input.key
|
|
36
|
+
? { ...state, phase: 'dropped' }
|
|
37
|
+
: null;
|
|
38
|
+
case 'step':
|
|
39
|
+
return state.phase === 'held' && state.by === 'keyboard' && state.to !== input.to
|
|
40
|
+
? { ...state, to: input.to }
|
|
41
|
+
: null;
|
|
42
|
+
case 'target':
|
|
43
|
+
return state.phase === 'held' && state.by === 'keyboard'
|
|
44
|
+
? { ...state, phase: 'dropped', to: input.to }
|
|
45
|
+
: null;
|
|
46
|
+
case 'drop':
|
|
47
|
+
return state.phase === 'held' ? { ...state, phase: 'dropped' } : null;
|
|
48
|
+
case 'cancel':
|
|
49
|
+
if (state.phase === 'pressed') {
|
|
50
|
+
return IDLE;
|
|
51
|
+
}
|
|
52
|
+
return state.phase === 'held' ? { by: state.by, key: state.key, phase: 'canceled' } : null;
|
|
53
|
+
case 'settle':
|
|
54
|
+
return state.phase === 'dropped' || state.phase === 'canceled' ? IDLE : null;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
export const passedCount = (centers, at, reversed = false) => centers.filter((center) => (reversed ? at < center : at > center)).length;
|
|
58
|
+
export const centersOf = (spans, reversed = false) => {
|
|
59
|
+
const drawn = spans.flatMap((span, index) => (span ? [index] : []));
|
|
60
|
+
const first = drawn[0] ?? spans.length;
|
|
61
|
+
const last = drawn[drawn.length - 1] ?? -1;
|
|
62
|
+
let before = reversed ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
|
|
63
|
+
return spans.map((span, index) => {
|
|
64
|
+
if (span) {
|
|
65
|
+
before = (span.start + span.end) / 2;
|
|
66
|
+
return before;
|
|
67
|
+
}
|
|
68
|
+
if (index < first) {
|
|
69
|
+
return reversed ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
|
|
70
|
+
}
|
|
71
|
+
return index > last ? (reversed ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY) : before;
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
export const reorderKey = (key, { axis, count, rtl, to }) => {
|
|
75
|
+
const last = Math.max(0, count - 1);
|
|
76
|
+
if (key === 'Home') {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
if (key === 'End') {
|
|
80
|
+
return last;
|
|
81
|
+
}
|
|
82
|
+
const back = axis === 'block' ? 'ArrowUp' : rtl ? 'ArrowRight' : 'ArrowLeft';
|
|
83
|
+
const forward = axis === 'block' ? 'ArrowDown' : rtl ? 'ArrowLeft' : 'ArrowRight';
|
|
84
|
+
if (key !== back && key !== forward) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return Math.min(last, Math.max(0, to + (key === forward ? 1 : -1)));
|
|
88
|
+
};
|
|
89
|
+
export const dropMark = (from, to) => to === from ? undefined : { edge: to < from ? 'before' : 'after', index: to };
|
|
90
|
+
export const placeKey = (all, shown, key, to) => {
|
|
91
|
+
const others = shown.filter((one) => one !== key);
|
|
92
|
+
const rest = all.filter((one) => one !== key);
|
|
93
|
+
const beside = others[to - 1] ?? others[0];
|
|
94
|
+
if (beside === undefined) {
|
|
95
|
+
return [...all];
|
|
96
|
+
}
|
|
97
|
+
rest.splice(rest.indexOf(beside) + (to > 0 ? 1 : 0), 0, key);
|
|
98
|
+
return rest;
|
|
99
|
+
};
|
|
100
|
+
export const edgeSpeed = (at, start, end, { most = 12, zone = 40 } = {}) => {
|
|
101
|
+
const reach = Math.min(zone, (end - start) / 2);
|
|
102
|
+
if (reach <= 0) {
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
if (at < start + reach) {
|
|
106
|
+
return -Math.round(most * Math.min(1, (start + reach - at) / reach)) || 0;
|
|
107
|
+
}
|
|
108
|
+
if (at > end - reach) {
|
|
109
|
+
return Math.round(most * Math.min(1, (at - (end - reach)) / reach));
|
|
110
|
+
}
|
|
111
|
+
return 0;
|
|
112
|
+
};
|
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
*/
|
|
19
19
|
/** What went wrong, stable across versions, so it can be counted. */
|
|
20
20
|
export type RuntimeKind =
|
|
21
|
+
/** A Blockquote's `cite` holds words, where it takes the source's URL. */
|
|
22
|
+
'cite-not-url'
|
|
21
23
|
/** A deprecated property, attribute or slot was used; the message names what replaces it. */
|
|
22
|
-
'deprecated'
|
|
24
|
+
| 'deprecated'
|
|
23
25
|
/** Another class asked for a tag that is already registered: two copies of Helix. */
|
|
24
26
|
| 'duplicate-registration'
|
|
25
27
|
/** The browser refused fullscreen, usually for a frame without the permission. */
|
|
@@ -28,7 +30,7 @@ export type RuntimeKind =
|
|
|
28
30
|
| 'min-out-of-range'
|
|
29
31
|
/** A Stat was given one of Trend's directions, `up`, `down` or `neutral`, which lay nothing out. */
|
|
30
32
|
| 'misread-direction'
|
|
31
|
-
/** A React handler prop names an event the element never dispatches itself. */
|
|
33
|
+
/** A React handler prop names an event the element never dispatches itself. Development builds only. */
|
|
32
34
|
| 'misplaced-handler'
|
|
33
35
|
/** An Image has no `alt`, so a screen reader announces its file name. */
|
|
34
36
|
| 'missing-alt'
|
|
@@ -57,9 +59,12 @@ export type RuntimeKind =
|
|
|
57
59
|
| 'picture-in-picture-refused'
|
|
58
60
|
/** A Grid's `min` is no length it can write, so the grid lays out by its column count. */
|
|
59
61
|
| 'refused-length'
|
|
60
|
-
/** A React handler prop is a removed callback, which never ran from JSX. */
|
|
62
|
+
/** A React handler prop is a removed callback, which never ran from JSX. Development builds only. */
|
|
61
63
|
| 'removed-callback'
|
|
62
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* A React handler prop uses Solid's `on:`, which React reads as another event's name.
|
|
66
|
+
* Development builds only.
|
|
67
|
+
*/
|
|
63
68
|
| 'solid-handler-syntax'
|
|
64
69
|
/** A stencil's regions went unused: no named parts, or parts too small. */
|
|
65
70
|
| 'stencil-regions-unused'
|
|
@@ -71,7 +76,7 @@ export type RuntimeKind =
|
|
|
71
76
|
| 'two-default-operators'
|
|
72
77
|
/** A Quote's text starts or ends with a quotation mark, so the browser's marks double it. */
|
|
73
78
|
| 'typed-marks'
|
|
74
|
-
/** A React handler prop names an event nothing dispatches. */
|
|
79
|
+
/** A React handler prop names an event nothing dispatches. Development builds only. */
|
|
75
80
|
| 'unknown-event'
|
|
76
81
|
/** An Icon's `name` is in no icon set it can read, so it draws nothing. */
|
|
77
82
|
| 'unknown-icon'
|
|
@@ -79,8 +84,12 @@ export type RuntimeKind =
|
|
|
79
84
|
| 'unlinked-trigger'
|
|
80
85
|
/** A Text is rendered as a label, a deprecated value whose shadow root reaches no control. */
|
|
81
86
|
| 'unreachable-label'
|
|
87
|
+
/** A QR code holds a logo at a correction level below `H`, so it may not scan. */
|
|
88
|
+
| 'unscannable-logo'
|
|
82
89
|
/** A virtualized list's box has no height of its own, so its window never settles. */
|
|
83
90
|
| 'unsettled-window'
|
|
91
|
+
/** A native button in a Button Group with `selection-mode`, which cannot be told it is pressed. */
|
|
92
|
+
| 'untold-toggle'
|
|
84
93
|
/** A slotted trigger is a plain element, which cannot be told it opens something. */
|
|
85
94
|
| 'untold-trigger'
|
|
86
95
|
/** A tooltip wraps its trigger, so its text reaches no screen reader. */
|
|
@@ -9,13 +9,25 @@
|
|
|
9
9
|
* sent the first and Date Picker the second, so what a server received for the
|
|
10
10
|
* same answer depended on which control asked for it.
|
|
11
11
|
*
|
|
12
|
-
* **The joined string is the state**, which is what the browser
|
|
13
|
-
* `formStateRestoreCallback` and what `value` holds, so a
|
|
14
|
-
* reads the shape it wrote.
|
|
12
|
+
* **The joined string is the state by default**, which is what the browser
|
|
13
|
+
* hands back to `formStateRestoreCallback` and what `value` holds, so a
|
|
14
|
+
* restored control reads the shape it wrote. A control whose answers can hold
|
|
15
|
+
* a comma asks for `state: 'entries'`, and the browser hands back the form
|
|
16
|
+
* data itself, one entry per answer, so `b,1` comes back as one answer and not
|
|
17
|
+
* two.
|
|
15
18
|
*
|
|
16
19
|
* **Nothing without a `name`.** A plain string is skipped by the form when its
|
|
17
20
|
* control has no name, but `FormData` carries its own names and its entries
|
|
18
21
|
* are appended whatever the element is called, so an unnamed control would
|
|
19
22
|
* submit empty-named values.
|
|
20
23
|
*/
|
|
21
|
-
|
|
24
|
+
/** How `reportValues` saves the state the browser restores. */
|
|
25
|
+
export interface ReportValuesOptions {
|
|
26
|
+
/**
|
|
27
|
+
* What the browser hands back to `formStateRestoreCallback`: `joined`, the
|
|
28
|
+
* answers joined with commas, or `entries`, the form data with one entry per
|
|
29
|
+
* answer. Defaults to `joined`.
|
|
30
|
+
*/
|
|
31
|
+
state?: 'entries' | 'joined';
|
|
32
|
+
}
|
|
33
|
+
export declare const reportValues: (internals: ElementInternals, name: string, values: readonly string[], { state }?: ReportValuesOptions) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const reportValues = (internals, name, values) => {
|
|
1
|
+
export const reportValues = (internals, name, values, { state = 'joined' } = {}) => {
|
|
2
2
|
if (name === '' || values.length === 0) {
|
|
3
3
|
internals.setFormValue(null);
|
|
4
4
|
return;
|
|
@@ -7,5 +7,5 @@ export const reportValues = (internals, name, values) => {
|
|
|
7
7
|
for (const value of values) {
|
|
8
8
|
data.append(name, value);
|
|
9
9
|
}
|
|
10
|
-
internals.setFormValue(data, values.join(','));
|
|
10
|
+
internals.setFormValue(data, state === 'entries' ? data : values.join(','));
|
|
11
11
|
};
|
|
@@ -35,3 +35,14 @@ export interface ChangeRequestOptions<T> {
|
|
|
35
35
|
next: T;
|
|
36
36
|
}
|
|
37
37
|
export declare const requestChange: <T>({ apply, event, host, next, }: ChangeRequestOptions<T>) => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Asks before a reader's press moves a value, then applies it and says so:
|
|
40
|
+
* `helix-before-change` with the value it would leave, which a listener may
|
|
41
|
+
* cancel, and `change` once it has moved.
|
|
42
|
+
*
|
|
43
|
+
* **The order every selectable set in the library keeps**, so a page reads the
|
|
44
|
+
* same pair from a list, a tag group, a heatmap or a legend: the cancelable
|
|
45
|
+
* question first, the platform's `change` after, bubbling and composed as a
|
|
46
|
+
* native control's does. Returns whether the value moved.
|
|
47
|
+
*/
|
|
48
|
+
export declare const requestValue: (host: EventTarget, next: string, apply: (value: string) => void) => boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HelixBeforeChangeEvent } from '../../events/before-change.js';
|
|
1
2
|
export const requestChange = ({ apply, event, host, next, }) => {
|
|
2
3
|
if (!host.dispatchEvent(event(next))) {
|
|
3
4
|
return false;
|
|
@@ -5,3 +6,12 @@ export const requestChange = ({ apply, event, host, next, }) => {
|
|
|
5
6
|
apply(next);
|
|
6
7
|
return true;
|
|
7
8
|
};
|
|
9
|
+
export const requestValue = (host, next, apply) => requestChange({
|
|
10
|
+
apply: (value) => {
|
|
11
|
+
apply(value);
|
|
12
|
+
host.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
13
|
+
},
|
|
14
|
+
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
15
|
+
host,
|
|
16
|
+
next,
|
|
17
|
+
});
|
|
@@ -27,6 +27,23 @@ export interface ScrollItemOptions {
|
|
|
27
27
|
* bar with it.
|
|
28
28
|
*/
|
|
29
29
|
export declare const scrollingAncestor: (item: HTMLElement, options?: ScrollerOptions) => HTMLElement | null;
|
|
30
|
+
/** What `scrollRoom` takes off a box that scrolls. */
|
|
31
|
+
export interface ScrollRoomOptions {
|
|
32
|
+
/**
|
|
33
|
+
* How much of the box its own content covers while it scrolls, a sticky row
|
|
34
|
+
* of headings, in pixels. Defaults to `0`.
|
|
35
|
+
*/
|
|
36
|
+
covered?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* How much of a list a reader sees at once, for Page Up and Page Down: the
|
|
40
|
+
* box's own height where it scrolls, less what covers it, and the window's
|
|
41
|
+
* where it does not and the page scrolls instead.
|
|
42
|
+
*
|
|
43
|
+
* **A pixel of slack**, since a box whose content rounds to one pixel more
|
|
44
|
+
* than its height does not scroll, and was paging by the window's height.
|
|
45
|
+
*/
|
|
46
|
+
export declare const scrollRoom: (box: Element | null | undefined, { covered }?: ScrollRoomOptions) => number;
|
|
30
47
|
/** Where `scrollingAncestor` looks, and what it takes for a scroller. */
|
|
31
48
|
export interface ScrollerOptions {
|
|
32
49
|
/** The axis whose overflow counts, or either where absent. */
|
|
@@ -15,6 +15,7 @@ export const scrollingAncestor = (item, options = {}) => {
|
|
|
15
15
|
}
|
|
16
16
|
return null;
|
|
17
17
|
};
|
|
18
|
+
export const scrollRoom = (box, { covered = 0 } = {}) => box && box.scrollHeight > box.clientHeight + 1 ? box.clientHeight - covered : window.innerHeight;
|
|
18
19
|
const overflows = (node, axis) => {
|
|
19
20
|
const tall = node.scrollHeight > node.clientHeight;
|
|
20
21
|
const wide = node.scrollWidth > node.clientWidth;
|
|
@@ -22,3 +22,11 @@
|
|
|
22
22
|
* anything", and a slot showing its fallback does render.
|
|
23
23
|
*/
|
|
24
24
|
export declare const slotFilled: (slot: HTMLSlotElement | null | undefined) => boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The slot of a name in a shadow root, or its default slot for `''`.
|
|
27
|
+
*
|
|
28
|
+
* `slot[name=""]` matches nothing, since the default slot has no `name`
|
|
29
|
+
* attribute at all, which is the one thing every hand-written lookup had to
|
|
30
|
+
* remember.
|
|
31
|
+
*/
|
|
32
|
+
export declare const slotNamed: (root: ParentNode | null | undefined, name: string) => HTMLSlotElement | null;
|
|
@@ -1 +1,2 @@
|
|
|
1
1
|
export const slotFilled = (slot) => (slot?.assignedNodes({ flatten: true }) ?? []).some((node) => node.nodeType === Node.ELEMENT_NODE || node.textContent?.trim() !== '');
|
|
2
|
+
export const slotNamed = (root, name) => root?.querySelector?.(name === '' ? 'slot:not([name])' : `slot[name="${name}"]`) ?? null;
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* For a component that says what the page put in it, which is the page's own
|
|
6
6
|
* text and not anything this library wrote: an empty state's heading and
|
|
7
7
|
* message, a banner's message. Text nodes count toward the default slot, as
|
|
8
|
-
* they are assigned to it
|
|
9
|
-
*
|
|
8
|
+
* they are assigned to it; comments, such as the markers a template writes
|
|
9
|
+
* around its text, are left out. Nothing on a server, whose element has no
|
|
10
|
+
* children to read.
|
|
10
11
|
*/
|
|
11
12
|
export declare const slottedWords: (host: Element, slots: readonly string[]) => string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const slottedWords = (host, slots) => [...(host.childNodes ?? [])]
|
|
2
|
-
.filter((node) =>
|
|
2
|
+
.filter((node) => node instanceof Element
|
|
3
|
+
? slots.includes(node.slot)
|
|
4
|
+
: node.nodeType === 3 && slots.includes(''))
|
|
3
5
|
.map((node) => node.textContent?.replace(/\s+/g, ' ').trim() ?? '')
|
|
4
6
|
.filter(Boolean)
|
|
5
7
|
.join(' ');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The toolbar an element sits in, or `null`.
|
|
3
|
+
*
|
|
4
|
+
* Read from the parent up, so a toolbar is never its own. One answer for every
|
|
5
|
+
* family that changes inside a toolbar: Toolbar becomes a group of the outer
|
|
6
|
+
* one, a multiple Toggle Group becomes a group, and Divider turns across the
|
|
7
|
+
* toolbar's axis. By tag and by role, since a family other than Toolbar cannot
|
|
8
|
+
* import Toolbar's class; Toolbar adds its own class for a third tag.
|
|
9
|
+
*
|
|
10
|
+
* `closest` stops at a shadow root, which is what a slotted child wants: its
|
|
11
|
+
* toolbar is its light-DOM parent or above.
|
|
12
|
+
*/
|
|
13
|
+
export declare const toolbarAround: (element: Element) => Element | null;
|
|
14
|
+
/**
|
|
15
|
+
* The axis a toolbar runs along: its own `orientation`, else the page's
|
|
16
|
+
* `aria-orientation`, else horizontal, which is the role's default.
|
|
17
|
+
*/
|
|
18
|
+
export declare const toolbarAxis: (toolbar: Element) => 'horizontal' | 'vertical';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const TOOLBAR = '[role="toolbar"], helix-toolbar, helix-headless-toolbar';
|
|
2
|
+
export const toolbarAround = (element) => element.parentElement?.closest(TOOLBAR) ?? null;
|
|
3
|
+
export const toolbarAxis = (toolbar) => (toolbar.getAttribute('orientation') ?? toolbar.getAttribute('aria-orientation')) === 'vertical'
|
|
4
|
+
? 'vertical'
|
|
5
|
+
: 'horizontal';
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.149.0';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { formatMessage, type Message, type MessageOptions, type MessageTable, type MessageValues, } from './message.js';
|
|
2
|
+
export { clearWords, type HelixWords, localeChain, refreshWords, registerWords, setDefaultWordsLocale, type Words, } from './registry.js';
|
|
3
|
+
export { handedLocale, wordsLocale } from './words-locale.js';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sentence a component says, written in a small subset of ICU
|
|
3
|
+
* MessageFormat, the syntax translation tools already read:
|
|
4
|
+
*
|
|
5
|
+
* - `{name}`, a value put in where the sentence says. A number is written in
|
|
6
|
+
* the element's locale.
|
|
7
|
+
* - `{n, number}`, `{n, number, percent}` and `{n, number, integer}`.
|
|
8
|
+
* - `{n, plural, =0 {...} one {# ...} other {...}}`, with `offset:`, and
|
|
9
|
+
* `{n, selectordinal, ...}` in the same shape. `#` is the number.
|
|
10
|
+
* - `{x, select, a {...} other {...}}`.
|
|
11
|
+
* - `''` for one apostrophe, and `'{'` for a brace written as text. A lone
|
|
12
|
+
* apostrophe is text, so "L'élément" needs no escaping.
|
|
13
|
+
*/
|
|
14
|
+
export type Message = string;
|
|
15
|
+
/** A word table, such as `color-words`. Its entries merge one by one. */
|
|
16
|
+
export type MessageTable = Readonly<Record<string, Message>>;
|
|
17
|
+
/** The values a message puts in, by name. */
|
|
18
|
+
export type MessageValues = Readonly<Record<string, string | number>>;
|
|
19
|
+
/** How a message is formatted. */
|
|
20
|
+
export interface MessageOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Wraps each value in Unicode isolates (U+2068 and U+2069), so a number or
|
|
23
|
+
* a Latin name keeps its order inside a right-to-left sentence.
|
|
24
|
+
*/
|
|
25
|
+
isolate?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The locale whose plural rules pick a form, where it is not the locale
|
|
28
|
+
* the numbers are written in. A message from the English fallback counts
|
|
29
|
+
* with English rules on a Polish page, because its forms are English.
|
|
30
|
+
*/
|
|
31
|
+
plurals?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A message with its values put in, its numbers written in `locale`, and its
|
|
35
|
+
* plural forms picked by the rules of `options.plurals`, or of `locale`.
|
|
36
|
+
*
|
|
37
|
+
* **A value that is missing leaves its placeholder as written**, so
|
|
38
|
+
* `{count}` shows on the page as the mistake it is. An unknown argument type
|
|
39
|
+
* writes the value as text, so a type added later changes only the messages
|
|
40
|
+
* that use it.
|
|
41
|
+
*
|
|
42
|
+
* ```js
|
|
43
|
+
* formatMessage('{count, plural, one {# wynik} few {# wyniki} many {# wyników} other {# wyniku}}', { count: 5 }, 'pl')
|
|
44
|
+
* // '5 wyników'
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare const formatMessage: (message: Message, values: MessageValues, locale: string, options?: MessageOptions) => string;
|