@fusion.dev/helix-core 0.148.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 +8518 -6050
- 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/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/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.js +2 -1
- 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 +10 -4
- package/dist/index.js +10 -4
- package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +2 -2
- package/dist/mixins/mixin-chart-source/mixin-chart-source.js +3 -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 +15 -34
- package/dist/utils/calendar/calendar.d.ts +27 -0
- package/dist/utils/calendar/calendar.js +17 -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/date-segments/date-segments.d.ts +2 -1
- package/dist/utils/date-segments/date-segments.js +10 -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/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 +7 -4
- package/dist/utils/slotted-words/slotted-words.d.ts +3 -2
- package/dist/utils/slotted-words/slotted-words.js +3 -1
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { auditName } from '
|
|
1
|
+
import { auditName } from '@fusion.dev/helix-core/audits/name';
|
|
2
2
|
import { elementById } from '../../utils/element-by-id/element-by-id.js';
|
|
3
3
|
import { nameText } from '../../utils/name-text/name-text.js';
|
|
4
4
|
const RELATIONSHIPS = [
|
|
@@ -61,8 +61,8 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
|
|
|
61
61
|
*/
|
|
62
62
|
readonly positionLabel?: string;
|
|
63
63
|
/**
|
|
64
|
-
* The locale the position's numbers are written in. Absent or empty
|
|
65
|
-
* runtime's own.
|
|
64
|
+
* The locale the position's numbers are written in. Absent or empty reads
|
|
65
|
+
* the nearest `lang`, then the runtime's own, as `wordsLocale` does.
|
|
66
66
|
*/
|
|
67
67
|
readonly locale?: string;
|
|
68
68
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { fillTemplate } from '../../utils/fill-template/fill-template.js';
|
|
2
|
-
import { formatNumbers } from '../../utils/format-numbers/format-numbers.js';
|
|
3
1
|
import { isRtl } from '../../utils/is-rtl/is-rtl.js';
|
|
2
|
+
import { formatWords } from '../../words/words.js';
|
|
4
3
|
import { stepReading } from './reading-step.js';
|
|
5
4
|
export const CHART_PLOT = 'helix-chart-plot';
|
|
6
5
|
export class ChartPointerController {
|
|
@@ -155,8 +154,10 @@ export class ChartPointerController {
|
|
|
155
154
|
if (words === '' || place < 0) {
|
|
156
155
|
return '';
|
|
157
156
|
}
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
return formatWords(this.host, 'positionLabel', {
|
|
158
|
+
count: shown.length,
|
|
159
|
+
position: place + 1,
|
|
160
|
+
});
|
|
160
161
|
}
|
|
161
162
|
columns() {
|
|
162
163
|
const host = this.host;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { type Machine, type MachineEvent } from './machine.js';
|
|
3
|
+
export * from './machine.js';
|
|
4
|
+
/** An effect a state runs: it may return a function that ends it. */
|
|
5
|
+
export type MachineEffect<E extends MachineEvent, C> = (context: C, by: E | undefined) => undefined | (() => void);
|
|
6
|
+
/** What a `MachineController` starts from and what it runs. */
|
|
7
|
+
export interface MachineOptions<S extends string, E extends MachineEvent, C, F extends string> {
|
|
8
|
+
/** The context the machine starts with. */
|
|
9
|
+
context: C;
|
|
10
|
+
/**
|
|
11
|
+
* Each effect a state names, by name. It runs after the host renders the
|
|
12
|
+
* state, with the event that entered it, and never on a server. The function
|
|
13
|
+
* it returns runs when the state is left and when the host is disconnected.
|
|
14
|
+
*/
|
|
15
|
+
effects: {
|
|
16
|
+
[K in F]: MachineEffect<E, C>;
|
|
17
|
+
};
|
|
18
|
+
/** The state the machine starts in, before the host's first `willUpdate`. */
|
|
19
|
+
initial: S;
|
|
20
|
+
/**
|
|
21
|
+
* Records a state on the host, or takes it off: the host's own
|
|
22
|
+
* `toggleState`, passed in because it is protected.
|
|
23
|
+
*/
|
|
24
|
+
mark?: (state: S, on: boolean) => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Runs a `Machine` on a host: holds the state and the context, moves them by
|
|
28
|
+
* `step`, and runs each state's effects with their clean-ups.
|
|
29
|
+
*
|
|
30
|
+
* The host turns its property writes into events in `willUpdate`, so a write
|
|
31
|
+
* moves the machine the way a press does, and the state a server prints comes
|
|
32
|
+
* from properties. Effects run in `hostUpdated`, which a server never calls,
|
|
33
|
+
* and none runs at the first update except a state's `atStart` effects: an
|
|
34
|
+
* element served in a state was not moved there by anybody.
|
|
35
|
+
*/
|
|
36
|
+
export declare class MachineController<S extends string, E extends MachineEvent, C, F extends string = string> implements ReactiveController {
|
|
37
|
+
/** The current state. */
|
|
38
|
+
state: S;
|
|
39
|
+
/** The current context. */
|
|
40
|
+
context: C;
|
|
41
|
+
private readonly host;
|
|
42
|
+
private readonly machine;
|
|
43
|
+
private readonly options;
|
|
44
|
+
/** The event that entered the current state, which its effects are told. */
|
|
45
|
+
private by;
|
|
46
|
+
/** The clean-ups of the effects that are running. */
|
|
47
|
+
private ends;
|
|
48
|
+
/** Whether the host has finished its first update. */
|
|
49
|
+
private live;
|
|
50
|
+
/** Whether the current state's effects have run. */
|
|
51
|
+
private ran;
|
|
52
|
+
constructor(host: ReactiveControllerHost & EventTarget, machine: Machine<S, E, C, F>, options: MachineOptions<S, E, C, F>);
|
|
53
|
+
/** Whether an event would move the machine, with nothing run or asked. */
|
|
54
|
+
can(event: E): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Moves the machine by an event, and returns whether it moved.
|
|
57
|
+
*
|
|
58
|
+
* A request is announced first and applies only where nobody refused it.
|
|
59
|
+
* Entering a state ends the effects of the state it leaves at once, and runs
|
|
60
|
+
* its own after the host's next update.
|
|
61
|
+
*/
|
|
62
|
+
send(event: E): boolean;
|
|
63
|
+
hostConnected(): void;
|
|
64
|
+
hostUpdated(): void;
|
|
65
|
+
hostDisconnected(): void;
|
|
66
|
+
/** Ends the running effects, so the next update runs the current state's. */
|
|
67
|
+
private end;
|
|
68
|
+
private mark;
|
|
69
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { requestChange } from '../../utils/request-change/request-change.js';
|
|
2
|
+
import { step } from './machine.js';
|
|
3
|
+
export * from './machine.js';
|
|
4
|
+
export class MachineController {
|
|
5
|
+
constructor(host, machine, options) {
|
|
6
|
+
this.by = undefined;
|
|
7
|
+
this.ends = [];
|
|
8
|
+
this.live = false;
|
|
9
|
+
this.ran = false;
|
|
10
|
+
this.host = host;
|
|
11
|
+
this.machine = machine;
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.state = options.initial;
|
|
14
|
+
this.context = options.context;
|
|
15
|
+
this.mark(this.state, true);
|
|
16
|
+
host.addController(this);
|
|
17
|
+
}
|
|
18
|
+
can(event) {
|
|
19
|
+
return step(this.machine, this.state, this.context, event).changed;
|
|
20
|
+
}
|
|
21
|
+
send(event) {
|
|
22
|
+
const next = step(this.machine, this.state, this.context, event);
|
|
23
|
+
if (!next.changed) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const apply = () => {
|
|
27
|
+
if (next.entered) {
|
|
28
|
+
this.end();
|
|
29
|
+
this.by = event;
|
|
30
|
+
}
|
|
31
|
+
this.mark(this.state, false);
|
|
32
|
+
this.state = next.state;
|
|
33
|
+
this.context = next.context;
|
|
34
|
+
this.mark(this.state, true);
|
|
35
|
+
this.host.requestUpdate();
|
|
36
|
+
};
|
|
37
|
+
if (next.ask) {
|
|
38
|
+
return requestChange({ apply, event: next.ask, host: this.host, next: 0 });
|
|
39
|
+
}
|
|
40
|
+
apply();
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
hostConnected() {
|
|
44
|
+
if (this.live) {
|
|
45
|
+
this.by = undefined;
|
|
46
|
+
this.hostUpdated();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
hostUpdated() {
|
|
50
|
+
const first = !this.live;
|
|
51
|
+
this.live = true;
|
|
52
|
+
if (this.ran) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.ran = true;
|
|
56
|
+
const state = this.machine.states[this.state];
|
|
57
|
+
for (const name of (first ? state.atStart : state.effects) ?? []) {
|
|
58
|
+
const end = this.options.effects[name](this.context, first ? undefined : this.by);
|
|
59
|
+
if (end) {
|
|
60
|
+
this.ends.push(end);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
hostDisconnected() {
|
|
65
|
+
this.end();
|
|
66
|
+
}
|
|
67
|
+
end() {
|
|
68
|
+
for (const end of this.ends.splice(0)) {
|
|
69
|
+
end();
|
|
70
|
+
}
|
|
71
|
+
this.ran = false;
|
|
72
|
+
}
|
|
73
|
+
mark(state, on) {
|
|
74
|
+
if (this.machine.states[state].mark) {
|
|
75
|
+
this.options.mark?.(state, on);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Something that happens to a machine, named by `type`, with whatever it carries. */
|
|
2
|
+
export interface MachineEvent {
|
|
3
|
+
/** The event's name, such as `NEXT`. */
|
|
4
|
+
type: string;
|
|
5
|
+
}
|
|
6
|
+
/** One way an event moves a machine. Every function on it is pure. */
|
|
7
|
+
export interface Transition<S extends string, E extends MachineEvent, C> {
|
|
8
|
+
/**
|
|
9
|
+
* The cancelable event announced before the move, which makes the move a
|
|
10
|
+
* request. It goes through `requestChange`, so a listener calling
|
|
11
|
+
* `preventDefault()` refuses it, and a refusal changes nothing, as a failed
|
|
12
|
+
* guard does.
|
|
13
|
+
*/
|
|
14
|
+
ask?: ((context: C, event: E) => Event) | undefined;
|
|
15
|
+
/** The context after the move. */
|
|
16
|
+
assign?: (context: C, event: E) => C;
|
|
17
|
+
/** Whether this way applies. The first way whose guard passes is taken. */
|
|
18
|
+
guard?: (context: C, event: E) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The state the move enters. Given, the state is entered again even where it
|
|
21
|
+
* is the same state, so its effects end and run again. Left out, the machine
|
|
22
|
+
* stays where it is and only `assign` applies.
|
|
23
|
+
*/
|
|
24
|
+
to?: S | ((context: C, event: E) => S) | undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What a state does with one event: one way, ways tried in order, or
|
|
28
|
+
* `'ignore'`, which says in the table that the state hears the event and does
|
|
29
|
+
* nothing with it.
|
|
30
|
+
*/
|
|
31
|
+
export type MachineAnswer<S extends string, E extends MachineEvent, C> = Transition<S, E, C> | readonly Transition<S, E, C>[] | 'ignore';
|
|
32
|
+
/** One state of a machine: its answers to events, and the effects it runs. */
|
|
33
|
+
export interface MachineState<S extends string, E extends MachineEvent, C, F extends string> {
|
|
34
|
+
/**
|
|
35
|
+
* The effects that also run when the element starts in this state, at its
|
|
36
|
+
* first update. They run with no event, because nobody moved the element
|
|
37
|
+
* there. Every other effect waits for a move.
|
|
38
|
+
*/
|
|
39
|
+
atStart?: readonly F[];
|
|
40
|
+
/** The effects that run while the element is in this state, by name. */
|
|
41
|
+
effects?: readonly F[];
|
|
42
|
+
/** Records the state on the host as `:state(<name>)` while it is current. */
|
|
43
|
+
mark?: boolean;
|
|
44
|
+
/** What each event does in this state. An event left out changes nothing. */
|
|
45
|
+
on?: {
|
|
46
|
+
[T in E['type']]?: MachineAnswer<S, E, C>;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A table of states. Each state lists the events it answers and the effects
|
|
51
|
+
* it runs. The effects are named here and written on the element, so the table
|
|
52
|
+
* stays pure and a spec can walk it.
|
|
53
|
+
*/
|
|
54
|
+
export interface Machine<S extends string, E extends MachineEvent, C, F extends string = string> {
|
|
55
|
+
/** Every state, by name. */
|
|
56
|
+
states: {
|
|
57
|
+
[K in S]: MachineState<S, E, C, F>;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The exhaustive form of a machine: every state answers every event, with a
|
|
62
|
+
* transition or with `'ignore'`. A table typed this way cannot leave a pair
|
|
63
|
+
* out by accident, so a reviewer reads every pair the machine ignores.
|
|
64
|
+
*/
|
|
65
|
+
export interface ExhaustiveMachine<S extends string, E extends MachineEvent, C, F extends string = string> extends Machine<S, E, C, F> {
|
|
66
|
+
states: {
|
|
67
|
+
[K in S]: MachineState<S, E, C, F> & {
|
|
68
|
+
on: {
|
|
69
|
+
[T in E['type']]: MachineAnswer<S, E, C>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** What one event does to a state and its context. */
|
|
75
|
+
export interface MachineStep<S extends string, C> {
|
|
76
|
+
/** Makes the event announced before the move, where the move is a request. */
|
|
77
|
+
ask?: (() => Event) | undefined;
|
|
78
|
+
/** Whether anything moves: the state, the context, or both. */
|
|
79
|
+
changed: boolean;
|
|
80
|
+
/** The context after the event. */
|
|
81
|
+
context: C;
|
|
82
|
+
/** Whether the event enters a state, so its effects end and run again. */
|
|
83
|
+
entered: boolean;
|
|
84
|
+
/** The state after the event. */
|
|
85
|
+
state: S;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* What an event does to a state and its context, with nothing run.
|
|
89
|
+
*
|
|
90
|
+
* Takes the first way whose guard passes. An event the state does not answer,
|
|
91
|
+
* an event it ignores, and an event whose guards all fail change nothing.
|
|
92
|
+
*/
|
|
93
|
+
export declare const step: <S extends string, E extends MachineEvent, C>(machine: Machine<S, E, C, string>, state: S, context: C, event: E) => MachineStep<S, C>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const step = (machine, state, context, event) => {
|
|
2
|
+
const answer = machine.states[state].on?.[event.type];
|
|
3
|
+
const ways = answer === undefined || answer === 'ignore' ? [] : [answer].flat();
|
|
4
|
+
for (const way of ways) {
|
|
5
|
+
if (way.guard?.(context, event) === false) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
const next = way.assign ? way.assign(context, event) : context;
|
|
9
|
+
const entered = way.to !== undefined;
|
|
10
|
+
const ask = way.ask;
|
|
11
|
+
return {
|
|
12
|
+
ask: ask && (() => ask(context, event)),
|
|
13
|
+
changed: entered || next !== context,
|
|
14
|
+
context: next,
|
|
15
|
+
entered,
|
|
16
|
+
state: typeof way.to === 'function' ? way.to(context, event) : (way.to ?? state),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return { changed: false, context, entered: false, state };
|
|
20
|
+
};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import type { nothing, ReactiveController, ReactiveControllerHost, TemplateResult } from 'lit';
|
|
2
|
+
import type { ReorderDetail } from '../../events/details.js';
|
|
3
|
+
import { type ReorderAxis, type ReorderHold } from '../../utils/reorder/reorder.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a screen reader hears as an item moves. `{name}` is the item's name,
|
|
6
|
+
* and `{position}` and `{count}` say where it would go.
|
|
7
|
+
*/
|
|
8
|
+
export interface ReorderWords {
|
|
9
|
+
/** Said when a key or a click puts the item back where it was. */
|
|
10
|
+
canceled: string;
|
|
11
|
+
/** Said when the item is let go. */
|
|
12
|
+
dropped: string;
|
|
13
|
+
/** Said each time a key moves the held item. */
|
|
14
|
+
moved: string;
|
|
15
|
+
/** Said when a key or a click takes hold of the item. */
|
|
16
|
+
pickedUp: string;
|
|
17
|
+
}
|
|
18
|
+
/** A move a drop asks for, counted from 0 in the order the items are drawn. */
|
|
19
|
+
export interface ReorderMove {
|
|
20
|
+
from: number;
|
|
21
|
+
key: string;
|
|
22
|
+
to: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ReorderOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Every key the item with that key moves among, the ones a filter hides
|
|
27
|
+
* included, for a drop the controller asks for itself. `keys` where this is
|
|
28
|
+
* not given.
|
|
29
|
+
*/
|
|
30
|
+
all?: (key: string) => readonly string[];
|
|
31
|
+
/** Which way the items run: rows down the block axis, or columns along the inline one. */
|
|
32
|
+
axis: ReorderAxis;
|
|
33
|
+
/** The box an item is drawn in, or nothing for one a window did not draw. */
|
|
34
|
+
box: (key: string) => DOMRect | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Called when an item is let go at a new place. Returns whether the move
|
|
37
|
+
* stood: `false` where a listener refused it.
|
|
38
|
+
*
|
|
39
|
+
* Where this is not given, the controller asks the page itself, from the
|
|
40
|
+
* host: `helix-before-reorder`, then `helix-reorder`, with `kind` and
|
|
41
|
+
* every key of `all` in the new order, joined by commas in `value`. A key a
|
|
42
|
+
* filter hides keeps its place, as `placeKey` says.
|
|
43
|
+
*/
|
|
44
|
+
drop?: (move: ReorderMove) => boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The key of the item a key pressed in the host stands for: the one with
|
|
47
|
+
* focus, or the one `aria-activedescendant` names. Alt with Up or Down then
|
|
48
|
+
* moves that item a place at once, and Alt with Home or End to either end,
|
|
49
|
+
* as the rearrangeable listbox of the APG does, with no grip and nothing
|
|
50
|
+
* held. Alt with an arrow moves nothing where this is not given.
|
|
51
|
+
*/
|
|
52
|
+
current?: (event: KeyboardEvent) => string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Whether an item may be moved now. Where this is not given, the host's own
|
|
55
|
+
* `reorderable` says, and every item may on a host without one.
|
|
56
|
+
*/
|
|
57
|
+
enabled?: () => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* The grip an event passed through, and the key of the item it moves, or
|
|
60
|
+
* nothing for an event that passed through none.
|
|
61
|
+
*/
|
|
62
|
+
grip: (event: Event) => {
|
|
63
|
+
element: HTMLElement;
|
|
64
|
+
key: string;
|
|
65
|
+
} | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Whether a key or a click holds the item for the arrow keys. `true` where
|
|
68
|
+
* this is not given. Data Table's columns move a place for each arrow on the
|
|
69
|
+
* grip and say `false`, so they are only dragged. A listbox's options say
|
|
70
|
+
* `false` too: the whole option is what a pointer drags, and a click on it
|
|
71
|
+
* still chooses it.
|
|
72
|
+
*/
|
|
73
|
+
holds?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The key of the item an event passed through, anywhere in it. A click there
|
|
76
|
+
* drops a held item at that place, which is the move a single pointer makes
|
|
77
|
+
* without a drag.
|
|
78
|
+
*/
|
|
79
|
+
item?: (event: Event) => string | undefined;
|
|
80
|
+
/** What a drop the controller asks for itself moves: `item`, the default, or `row`. */
|
|
81
|
+
kind?: ReorderDetail['kind'];
|
|
82
|
+
/**
|
|
83
|
+
* The keys of the items the item with that key moves among, in the order
|
|
84
|
+
* they are drawn: every item of a list, or the item's siblings in a tree.
|
|
85
|
+
*/
|
|
86
|
+
keys: (key: string) => readonly string[];
|
|
87
|
+
/** An item's name, for the words. */
|
|
88
|
+
name?: (key: string) => string;
|
|
89
|
+
/**
|
|
90
|
+
* The element a pointer drag copies for the drag preview: a copy of what it
|
|
91
|
+
* draws follows the pointer, raised over the page, until the item is let go
|
|
92
|
+
* or Escape puts it back. A move made with the keys draws none. No preview
|
|
93
|
+
* is drawn where this is not given.
|
|
94
|
+
*
|
|
95
|
+
* The copy is drawn in the host's `drag-preview` part, which the host's
|
|
96
|
+
* template draws with `drawDragPreview`: a manual popover in its shadow
|
|
97
|
+
* root, hidden from assistive technology, shown in the top layer so no
|
|
98
|
+
* scrolling box clips it. The host's stylesheet gives it its look. No
|
|
99
|
+
* preview is drawn where the host draws no such part.
|
|
100
|
+
*/
|
|
101
|
+
preview?: (key: string) => Element | null | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Gives focus back to the item with that key, called after a move made from
|
|
104
|
+
* the keyboard stood, once the page has moved the item and focus went to the
|
|
105
|
+
* body with it. Focus the page put anywhere else is left there. Focus is left
|
|
106
|
+
* alone where this is not given.
|
|
107
|
+
*/
|
|
108
|
+
refocus?: (key: string) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Speaks words in the host's live region. Where this is not given, the
|
|
111
|
+
* words go to the host's `announced`, the region a collection draws, where
|
|
112
|
+
* it has one, and nowhere otherwise.
|
|
113
|
+
*/
|
|
114
|
+
say?: (words: string) => void;
|
|
115
|
+
/**
|
|
116
|
+
* The box to scroll while a dragged item nears one of its edges, or `null`
|
|
117
|
+
* for the window. Where this is not given, rows down the block axis scroll
|
|
118
|
+
* the nearest box around the host's first child that scrolls that way and
|
|
119
|
+
* has more to show, or the window, and items along the inline axis scroll
|
|
120
|
+
* nothing.
|
|
121
|
+
*/
|
|
122
|
+
scroller?: () => HTMLElement | null;
|
|
123
|
+
/**
|
|
124
|
+
* The words a screen reader hears. Where this is not given, they are the
|
|
125
|
+
* host's own `canceledLabel`, `droppedLabel`, `movedLabel`, and
|
|
126
|
+
* `pickedUpLabel`, which is what a family declares them as.
|
|
127
|
+
*/
|
|
128
|
+
words?: () => ReorderWords;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Asks to move a row or an item and reports whether the move stood:
|
|
132
|
+
* `helix-before-reorder`, which can refuse it, and then `helix-reorder`, which
|
|
133
|
+
* is when you move your data.
|
|
134
|
+
*/
|
|
135
|
+
export declare const requestReorder: (host: HTMLElement, detail: ReorderDetail) => boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Moves one item of a collection to a new place, by pointer, by keyboard, and
|
|
138
|
+
* by a screen reader, and says each step in words.
|
|
139
|
+
*
|
|
140
|
+
* - **A pointer** drags an item by its grip. The page under it scrolls near an
|
|
141
|
+
* edge, and `mark` says where a drop indicator goes.
|
|
142
|
+
* - **A key or a click** on a grip holds the item. The arrows move it, Home
|
|
143
|
+
* and End move it to either end, Enter, Space, or a second click drops it,
|
|
144
|
+
* and Escape puts it back. A click on another item drops it there, so one
|
|
145
|
+
* pointer can move an item without dragging, as WCAG 2.5.7 asks.
|
|
146
|
+
* - **Alt with an arrow** moves the item focus is on a place at once, where
|
|
147
|
+
* the host says which item that is with `current`. A collection whose own
|
|
148
|
+
* keys are the arrows, Enter, and Space, such as a listbox or a tree, moves
|
|
149
|
+
* its items this way.
|
|
150
|
+
*
|
|
151
|
+
* **It moves nothing.** A drop calls `drop`, and the host asks its page,
|
|
152
|
+
* which owns the items, to move them. The host reads `held` and `mark` when
|
|
153
|
+
* it renders, and this asks it for an update at each change of state.
|
|
154
|
+
*
|
|
155
|
+
* Each change of state is worked out by `reorderStep`, a pure function, and
|
|
156
|
+
* what it calls for runs here: the words, the scrolling, and the drop.
|
|
157
|
+
*/
|
|
158
|
+
export declare class ReorderController implements ReactiveController {
|
|
159
|
+
private readonly host;
|
|
160
|
+
private readonly options;
|
|
161
|
+
/** The state of the move. */
|
|
162
|
+
private state;
|
|
163
|
+
/** The grip a key or a click took hold of, which has to keep focus. */
|
|
164
|
+
private holder;
|
|
165
|
+
/** Where the pointer was last, for the scrolling to place the item by. */
|
|
166
|
+
private pointer;
|
|
167
|
+
/** The frame the next scroll waits for. */
|
|
168
|
+
private frame;
|
|
169
|
+
/** The copy of the dragged item that follows the pointer, while one is drawn. */
|
|
170
|
+
private shown;
|
|
171
|
+
/** Where the pointer went down on the item the preview copies. */
|
|
172
|
+
private anchor;
|
|
173
|
+
constructor(host: ReactiveControllerHost & HTMLElement, options: ReorderOptions);
|
|
174
|
+
/** The item held and where it would go, or nothing while none is. */
|
|
175
|
+
get held(): {
|
|
176
|
+
by: ReorderHold;
|
|
177
|
+
from: number;
|
|
178
|
+
key: string;
|
|
179
|
+
to: number;
|
|
180
|
+
} | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Where the drop indicator goes: before or after the item with that key, or
|
|
183
|
+
* nothing while no item is held away from its place.
|
|
184
|
+
*/
|
|
185
|
+
get mark(): {
|
|
186
|
+
edge: 'after' | 'before';
|
|
187
|
+
key: string;
|
|
188
|
+
} | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* Where the item with that key stands in a move, for the host to mark it:
|
|
191
|
+
* the item held, the item the drop indicator is before or after, or nothing.
|
|
192
|
+
*/
|
|
193
|
+
moveOf(key: string): 'dragging' | 'drop-after' | 'drop-before' | undefined;
|
|
194
|
+
/**
|
|
195
|
+
* The `drag-preview` part, for the host's template: an empty manual popover
|
|
196
|
+
* while items may be moved, which a pointer drag fills and shows.
|
|
197
|
+
*/
|
|
198
|
+
drawDragPreview(): TemplateResult | typeof nothing;
|
|
199
|
+
hostConnected(): void;
|
|
200
|
+
hostDisconnected(): void;
|
|
201
|
+
/** Puts a held item back where it was, as Escape does. */
|
|
202
|
+
cancel(): void;
|
|
203
|
+
/** Moves the state on, and runs what the change calls for. */
|
|
204
|
+
private send;
|
|
205
|
+
/** What a change of state calls for. */
|
|
206
|
+
private enter;
|
|
207
|
+
/** Asks for a move: through `drop`, or of the page where the host gives none. */
|
|
208
|
+
private drop;
|
|
209
|
+
/** Says one of the words, with the item's name and place filled in. */
|
|
210
|
+
private speak;
|
|
211
|
+
/** The place among the others that the pointer is over, for the item with that key. */
|
|
212
|
+
private placeAt;
|
|
213
|
+
private enabled;
|
|
214
|
+
/** The page's own watch for the move it was asked for, while one is awaited. */
|
|
215
|
+
private awaiting;
|
|
216
|
+
/**
|
|
217
|
+
* Gives focus back to a moved item once the page has moved it, where moving
|
|
218
|
+
* it sent focus to the body. A page that moves the item as it hears
|
|
219
|
+
* `helix-reorder` has done so already; one that renders later changes the
|
|
220
|
+
* host's children first.
|
|
221
|
+
*/
|
|
222
|
+
private follow;
|
|
223
|
+
private readonly handleDown;
|
|
224
|
+
private readonly handleMove;
|
|
225
|
+
/**
|
|
226
|
+
* Draws the drag preview: a copy of the item, where it is, in the host's
|
|
227
|
+
* `drag-preview` part, shown in the top layer. Measured before the host
|
|
228
|
+
* draws the item as dragged, so the copy is the item as it was.
|
|
229
|
+
*/
|
|
230
|
+
private lift;
|
|
231
|
+
/** Moves the drag preview with the pointer. */
|
|
232
|
+
private glide;
|
|
233
|
+
/** Takes the drag preview away: hides the part and empties it. */
|
|
234
|
+
private lower;
|
|
235
|
+
/** Places the dragged item under the pointer's last reading. */
|
|
236
|
+
private drag;
|
|
237
|
+
private readonly handleUp;
|
|
238
|
+
private readonly handleCancel;
|
|
239
|
+
/**
|
|
240
|
+
* Escape while a pointer drags puts the item back. Heard on the window,
|
|
241
|
+
* since focus may be anywhere while a pointer drags, and kept from the page,
|
|
242
|
+
* so a dialog the list is in stays open.
|
|
243
|
+
*/
|
|
244
|
+
private readonly handleEscape;
|
|
245
|
+
/** Starts or stops hearing the pointer on the window, and the scrolling with it. */
|
|
246
|
+
private listen;
|
|
247
|
+
/** Scrolls the box while the dragged item is near one of its edges, a frame at a time. */
|
|
248
|
+
private scroll;
|
|
249
|
+
/**
|
|
250
|
+
* A click on a grip takes hold of its item, and a second one drops it. While
|
|
251
|
+
* one is held, a click on another item drops it there. Heard in the capture
|
|
252
|
+
* phase, so the click that drops an item does not also select a row.
|
|
253
|
+
*/
|
|
254
|
+
private readonly handleClick;
|
|
255
|
+
/** Takes hold of an item from its grip, which keeps focus while it is held. */
|
|
256
|
+
private take;
|
|
257
|
+
/**
|
|
258
|
+
* The keys while an item is held: the arrows, Home and End move it, Enter and
|
|
259
|
+
* Space drop it, and Escape puts it back. Heard in the capture phase and kept
|
|
260
|
+
* from everything else, so an arrow moves the item and not focus.
|
|
261
|
+
*
|
|
262
|
+
* A grip that is a native button answers Enter and Space with a click, which
|
|
263
|
+
* `handleClick` hears. Any other grip, such as a cell of a grid, is answered
|
|
264
|
+
* here.
|
|
265
|
+
*/
|
|
266
|
+
private readonly handleKey;
|
|
267
|
+
/**
|
|
268
|
+
* Alt with an arrow, Home, or End: moves the item the key stands for at
|
|
269
|
+
* once, with nothing held, and says where it went. A move the page refuses
|
|
270
|
+
* is said as canceled. At an end the key is kept and nothing moves.
|
|
271
|
+
*/
|
|
272
|
+
private nudge;
|
|
273
|
+
/**
|
|
274
|
+
* A pointer went down while a key or a click holds an item. Its click may
|
|
275
|
+
* drop the item on another one, so the focus it moves does not put the item
|
|
276
|
+
* back until that click has been heard.
|
|
277
|
+
*/
|
|
278
|
+
private press;
|
|
279
|
+
/** Whether a pointer is down while an item is held, for `press`. */
|
|
280
|
+
private pressing;
|
|
281
|
+
/** Focus leaving the grip that holds an item puts the item back. */
|
|
282
|
+
private readonly handleFocusOut;
|
|
283
|
+
/** Puts a held item back where focus has left its grip. */
|
|
284
|
+
private keepOrCancel;
|
|
285
|
+
}
|