@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.
Files changed (70) hide show
  1. package/custom-elements.json +8518 -6050
  2. package/dist/controllers/aria-forward-controller/aria-forward-controller.js +1 -1
  3. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +2 -2
  4. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +5 -4
  5. package/dist/controllers/machine-controller/machine-controller.d.ts +69 -0
  6. package/dist/controllers/machine-controller/machine-controller.js +78 -0
  7. package/dist/controllers/machine-controller/machine.d.ts +93 -0
  8. package/dist/controllers/machine-controller/machine.js +20 -0
  9. package/dist/controllers/reorder-controller/reorder-controller.d.ts +285 -0
  10. package/dist/controllers/reorder-controller/reorder-controller.js +497 -0
  11. package/dist/controllers/source-controller/source-controller.js +1 -1
  12. package/dist/controllers/virtualize-controller/heights.js +1 -1
  13. package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +117 -3
  14. package/dist/controllers/virtualize-controller/virtualize-controller.js +134 -32
  15. package/dist/events/before-reorder.d.ts +14 -0
  16. package/dist/events/before-reorder.js +11 -0
  17. package/dist/events/details.d.ts +28 -0
  18. package/dist/events/events.d.ts +4 -2
  19. package/dist/events/events.js +3 -1
  20. package/dist/events/names.js +1 -1
  21. package/dist/events/reorder.d.ts +18 -12
  22. package/dist/events/reordered.d.ts +4 -4
  23. package/dist/helix-element/helix-element.js +2 -1
  24. package/dist/helix-element/react-audit-off.d.ts +11 -0
  25. package/dist/helix-element/react-audit-off.js +1 -0
  26. package/dist/helix-element/react-audit.d.ts +20 -0
  27. package/dist/helix-element/react-audit.js +56 -0
  28. package/dist/helix-element/react-bridge.d.ts +2 -22
  29. package/dist/helix-element/react-bridge.js +1 -56
  30. package/dist/index.d.ts +10 -4
  31. package/dist/index.js +10 -4
  32. package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +2 -2
  33. package/dist/mixins/mixin-chart-source/mixin-chart-source.js +3 -0
  34. package/dist/mixins/mixin-collection/mixin-collection.js +4 -0
  35. package/dist/mixins/mixin-dismissible/mixin-dismissible.js +3 -0
  36. package/dist/mixins/mixin-field/mixin-field.js +1 -1
  37. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.d.ts +12 -0
  38. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +15 -2
  39. package/dist/mixins/mixin-tokens/mixin-tokens.d.ts +5 -0
  40. package/dist/mixins/mixin-tokens/mixin-tokens.js +13 -2
  41. package/dist/mixins/mixin-viewport/mixin-viewport.d.ts +17 -15
  42. package/dist/mixins/mixin-viewport/mixin-viewport.js +15 -34
  43. package/dist/utils/calendar/calendar.d.ts +27 -0
  44. package/dist/utils/calendar/calendar.js +17 -0
  45. package/dist/utils/count-label/count-label.d.ts +7 -4
  46. package/dist/utils/count-label/count-label.js +2 -5
  47. package/dist/utils/date-segments/date-segments.d.ts +2 -1
  48. package/dist/utils/date-segments/date-segments.js +10 -0
  49. package/dist/utils/locale-of/locale-of.d.ts +5 -0
  50. package/dist/utils/locale-of/locale-of.js +8 -2
  51. package/dist/utils/reorder/drag-preview.d.ts +46 -0
  52. package/dist/utils/reorder/drag-preview.js +58 -0
  53. package/dist/utils/reorder/reorder.d.ts +178 -0
  54. package/dist/utils/reorder/reorder.js +112 -0
  55. package/dist/utils/report-runtime/report-runtime.d.ts +7 -4
  56. package/dist/utils/slotted-words/slotted-words.d.ts +3 -2
  57. package/dist/utils/slotted-words/slotted-words.js +3 -1
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +1 -1
  60. package/dist/words/index.d.ts +3 -0
  61. package/dist/words/index.js +3 -0
  62. package/dist/words/message.d.ts +47 -0
  63. package/dist/words/message.js +152 -0
  64. package/dist/words/registry.d.ts +89 -0
  65. package/dist/words/registry.js +101 -0
  66. package/dist/words/words-locale.d.ts +34 -0
  67. package/dist/words/words-locale.js +30 -0
  68. package/dist/words/words.d.ts +52 -0
  69. package/dist/words/words.js +100 -0
  70. package/package.json +40 -25
@@ -1,4 +1,4 @@
1
- import { auditName } from '#audit-name';
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 is the
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
- const format = formatNumbers(this.host.locale ?? '');
159
- return fillTemplate(words, { count: format(shown.length), position: format(place + 1) });
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
+ }