@fusion.dev/helix-headless 0.165.0 → 0.167.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 (57) hide show
  1. package/custom-elements.json +3235 -534
  2. package/dist/callout/root/callout-root.d.ts +8 -2
  3. package/dist/callout/root/callout-root.js +14 -1
  4. package/dist/canvas/arrange.d.ts +32 -0
  5. package/dist/canvas/arrange.js +144 -0
  6. package/dist/canvas/paste.d.ts +25 -0
  7. package/dist/canvas/paste.js +58 -0
  8. package/dist/canvas/root/canvas-root.d.ts +60 -3
  9. package/dist/canvas/root/canvas-root.js +166 -2
  10. package/dist/chat/composer/chat-composer.js +5 -1
  11. package/dist/code-block/root/code-block-root.d.ts +63 -0
  12. package/dist/code-block/root/code-block-root.js +117 -6
  13. package/dist/combobox/root/combobox-root.d.ts +6 -1
  14. package/dist/combobox/root/combobox-root.js +2 -2
  15. package/dist/date-input/root/date-input-root.d.ts +1 -1
  16. package/dist/element-events.generated.js +17 -2
  17. package/dist/file-input/root/file-input-root.d.ts +1 -1
  18. package/dist/file-input/root/file-input-root.js +1 -1
  19. package/dist/filter-input/menu/filter-menu.d.ts +1 -0
  20. package/dist/filter-input/menu/filter-menu.js +1 -1
  21. package/dist/format-date/root/format-date-root.d.ts +10 -3
  22. package/dist/format-date/root/format-date-root.js +6 -1
  23. package/dist/listbox/root/listbox-root.d.ts +12 -1
  24. package/dist/listbox/root/listbox-root.js +15 -6
  25. package/dist/menu/item/menu-item.d.ts +20 -0
  26. package/dist/menu/item/menu-item.js +53 -20
  27. package/dist/menu/root/menu-root.d.ts +84 -1
  28. package/dist/menu/root/menu-root.js +187 -44
  29. package/dist/object-inspector/root/object-inspector-root.d.ts +5 -0
  30. package/dist/object-inspector/root/object-inspector-root.js +5 -0
  31. package/dist/select/root/select-root.js +1 -1
  32. package/dist/steps/root/steps-root.d.ts +7 -0
  33. package/dist/steps/root/steps-root.js +7 -0
  34. package/dist/table/grid-controller.d.ts +10 -0
  35. package/dist/table/grid-controller.js +7 -0
  36. package/dist/table/root/table-root.d.ts +71 -1
  37. package/dist/table/root/table-root.js +122 -7
  38. package/dist/table/row/table-row.d.ts +17 -0
  39. package/dist/table/row/table-row.js +23 -0
  40. package/dist/time-input/root/time-input-root.d.ts +2 -1
  41. package/dist/time-input/root/time-input-root.js +1 -1
  42. package/dist/time-picker/root/time-picker-root.d.ts +48 -1
  43. package/dist/time-picker/root/time-picker-root.js +79 -21
  44. package/dist/video/root/video-root.d.ts +2 -0
  45. package/dist/video/root/video-root.js +4 -2
  46. package/dist/video-playlist/menu/video-playlist-menu.d.ts +1 -0
  47. package/dist/video-playlist/menu/video-playlist-menu.js +1 -1
  48. package/dist/video-playlist/root/video-playlist-root.js +15 -1
  49. package/dist/virtual-list/root/virtual-list-root.d.ts +70 -2
  50. package/dist/virtual-list/root/virtual-list-root.js +216 -32
  51. package/dist/virtual-list/sections.d.ts +27 -0
  52. package/dist/virtual-list/sections.js +43 -0
  53. package/lint.json +1 -1
  54. package/package.json +5 -5
  55. package/types/jsx.d.ts +716 -96
  56. package/types/vue.d.ts +148 -12
  57. package/types/words.d.ts +45 -0
@@ -1,5 +1,5 @@
1
- import { HelixElement } from '@fusion.dev/helix-core';
2
- import { type PropertyValues, type TemplateResult } from 'lit';
1
+ import { type HelixDismissEvent, HelixElement } from '@fusion.dev/helix-core';
2
+ import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessCallout_base: (new (...args: any[]) => import("@fusion.dev/helix-core").DismissibleElement) & typeof HelixElement;
4
4
  /**
5
5
  * @summary A passage set apart as a note, information, a warning, or an error.
@@ -52,6 +52,7 @@ declare const HelixHeadlessCallout_base: (new (...args: any[]) => import("@fusio
52
52
  * @cssstate has-icon - An icon of your own is slotted into `icon`, in place of the tone's.
53
53
  */
54
54
  export declare class HelixHeadlessCallout extends HelixHeadlessCallout_base {
55
+ static styles: CSSResultGroup;
55
56
  /**
56
57
  * The key this family's words are registered under, its styled tag:
57
58
  * `registerWords('de', { 'helix-callout': { toneLabels: { danger: 'Fehler' } } })`.
@@ -141,6 +142,11 @@ export declare class HelixHeadlessCallout extends HelixHeadlessCallout_base {
141
142
  * heading.
142
143
  */
143
144
  private dismissName;
145
+ /**
146
+ * The event a dismissal sends, naming the note by its heading where it has
147
+ * one, the words its dismiss button is named by, and otherwise by its text.
148
+ */
149
+ protected dismissEvent(): HelixDismissEvent;
144
150
  protected firstUpdated(changed: PropertyValues): void;
145
151
  protected updated(changed: PropertyValues): void;
146
152
  /**
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { animationsSettled, customElement, drawDismiss, drawDismissGlyph, formatWords, HelixElement, hostAria, MixinDismissible, slottedWords, TONE_MARKS, toneMark, words, wordsConverter, } from '@fusion.dev/helix-core';
8
- import { html, nothing } from 'lit';
8
+ import { css, html, nothing, } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
11
11
  let HelixHeadlessCallout = class HelixHeadlessCallout extends MixinDismissible(HelixElement) {
@@ -32,6 +32,11 @@ let HelixHeadlessCallout = class HelixHeadlessCallout extends MixinDismissible(H
32
32
  this.toggleState('has-icon', filled('icon'));
33
33
  };
34
34
  }
35
+ static { this.styles = css `
36
+ :host {
37
+ display: block;
38
+ }
39
+ `; }
35
40
  static { this.words = 'helix-callout'; }
36
41
  get present() {
37
42
  return this.isConnected && !this.hasAttribute('hidden');
@@ -66,6 +71,14 @@ let HelixHeadlessCallout = class HelixHeadlessCallout extends MixinDismissible(H
66
71
  ? formatWords(this, 'dismissLabel', { label: heading || tone }).trim()
67
72
  : this.dismissLabel;
68
73
  }
74
+ dismissEvent() {
75
+ const event = super.dismissEvent();
76
+ const heading = slottedWords(this, ['heading']);
77
+ if (heading) {
78
+ event.detail.label = heading;
79
+ }
80
+ return event;
81
+ }
69
82
  firstUpdated(changed) {
70
83
  super.firstUpdated(changed);
71
84
  this.finishHydration();
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Where `arrange()` puts every card: the arithmetic, kept apart from the board
3
+ * that moves them there.
4
+ */
5
+ import { type CanvasEdge, type CanvasNode } from './root/canvas-document.js';
6
+ /** How a board is arranged. */
7
+ export interface CanvasArrangeOptions {
8
+ /**
9
+ * Which way the arrows run: `down` puts each card below the cards that point
10
+ * to it, and `right` beside them. `down` by default.
11
+ */
12
+ direction?: 'down' | 'right';
13
+ /** The space between two cards, in the document's own units. 64 by default. */
14
+ gap?: number;
15
+ }
16
+ /**
17
+ * Where each card goes, by id, so that no two cards overlap.
18
+ *
19
+ * **Layers where there are connections.** A card goes one layer past the
20
+ * furthest card that points to it, a connection that would close a loop is
21
+ * read as pointing back, and the cards in each layer are ordered by where
22
+ * the cards they connect to sit, so connections cross less. **A grid where
23
+ * there are none**, in reading order, about as many columns as rows.
24
+ *
25
+ * A group is placed as one box and carries the cards inside it, so a card
26
+ * stays in its group. What is arranged starts where the board's top left
27
+ * corner was, and every place lands on a multiple of `snap` where it is set.
28
+ */
29
+ export declare const arrangement: (nodes: readonly CanvasNode[], edges: readonly CanvasEdge[], options?: CanvasArrangeOptions, snap?: number) => Map<string, {
30
+ x: number;
31
+ y: number;
32
+ }>;
@@ -0,0 +1,144 @@
1
+ import { groupOf, reading } from './root/canvas-document.js';
2
+ import { snapTo } from './snap.js';
3
+ export const arrangement = (nodes, edges, options = {}, snap) => {
4
+ const gap = Math.max(0, options.gap ?? 64, snap ?? 0);
5
+ const across = options.direction === 'right';
6
+ const groups = nodes.filter((node) => node.type === 'group');
7
+ const top = (node) => {
8
+ const seen = new Set([node]);
9
+ let at = node;
10
+ for (let held = groupOf(at, groups); held && !seen.has(held); held = groupOf(at, groups)) {
11
+ seen.add(held);
12
+ at = held;
13
+ }
14
+ return at;
15
+ };
16
+ const holder = new Map(nodes.map((node) => [node.id, top(node)]));
17
+ const units = reading([...nodes], [], 'spatial').filter((node) => holder.get(node.id) === node);
18
+ const order = new Map(units.map((unit, index) => [unit.id, index]));
19
+ const into = new Map();
20
+ const out = new Map();
21
+ for (const edge of edges) {
22
+ const from = holder.get(edge.fromNode)?.id;
23
+ const to = holder.get(edge.toNode)?.id;
24
+ if (from !== undefined && to !== undefined && from !== to) {
25
+ out.set(from, (out.get(from) ?? new Set()).add(to));
26
+ into.set(to, (into.get(to) ?? new Set()).add(from));
27
+ }
28
+ }
29
+ const layer = new Map();
30
+ if (out.size === 0) {
31
+ const columns = Math.ceil(Math.sqrt(units.length));
32
+ for (const [index, unit] of units.entries()) {
33
+ layer.set(unit.id, Math.floor(index / Math.max(columns, 1)));
34
+ }
35
+ }
36
+ else {
37
+ const done = new Set();
38
+ const open = new Set();
39
+ const back = new Set();
40
+ const visit = (id) => {
41
+ open.add(id);
42
+ for (const next of out.get(id) ?? []) {
43
+ if (open.has(next)) {
44
+ back.add(`${id}>${next}`);
45
+ }
46
+ else if (!done.has(next)) {
47
+ visit(next);
48
+ }
49
+ }
50
+ open.delete(id);
51
+ done.add(id);
52
+ };
53
+ for (const unit of units) {
54
+ if (!done.has(unit.id) && !into.get(unit.id)?.size) {
55
+ visit(unit.id);
56
+ }
57
+ }
58
+ for (const unit of units) {
59
+ if (!done.has(unit.id)) {
60
+ visit(unit.id);
61
+ }
62
+ }
63
+ const depth = (id, seen) => {
64
+ const known = layer.get(id);
65
+ if (known !== undefined) {
66
+ return known;
67
+ }
68
+ seen.add(id);
69
+ let deepest = 0;
70
+ for (const from of into.get(id) ?? []) {
71
+ if (!back.has(`${from}>${id}`) && !seen.has(from)) {
72
+ deepest = Math.max(deepest, depth(from, seen) + 1);
73
+ }
74
+ }
75
+ layer.set(id, deepest);
76
+ return deepest;
77
+ };
78
+ for (const unit of units) {
79
+ depth(unit.id, new Set());
80
+ }
81
+ }
82
+ const layers = [];
83
+ for (const unit of units) {
84
+ const at = layer.get(unit.id) ?? 0;
85
+ layers[at] = [...(layers[at] ?? []), unit];
86
+ }
87
+ if (out.size > 0) {
88
+ const place = new Map();
89
+ const settle = (row, near) => {
90
+ const mean = (unit) => {
91
+ const known = [...(near.get(unit.id) ?? [])].filter((id) => place.has(id));
92
+ return known.length === 0
93
+ ? (order.get(unit.id) ?? 0) / Math.max(units.length, 1)
94
+ : known.reduce((sum, id) => sum + (place.get(id) ?? 0), 0) / known.length;
95
+ };
96
+ const means = new Map(row.map((unit) => [unit.id, mean(unit)]));
97
+ row.sort((a, b) => (means.get(a.id) ?? 0) - (means.get(b.id) ?? 0));
98
+ for (const [index, unit] of row.entries()) {
99
+ place.set(unit.id, (index + 0.5) / row.length);
100
+ }
101
+ };
102
+ for (const row of layers) {
103
+ settle(row ?? [], into);
104
+ }
105
+ for (const row of [...layers].reverse()) {
106
+ settle(row ?? [], out);
107
+ }
108
+ }
109
+ const main = (node) => (across ? node.width : node.height);
110
+ const cross = (node) => (across ? node.height : node.width);
111
+ const span = (row) => row.reduce((sum, unit) => sum + cross(unit), 0) + gap * Math.max(row.length - 1, 0);
112
+ const widest = Math.max(0, ...layers.map((row) => span(row ?? [])));
113
+ const start = {
114
+ x: Math.min(...units.map((unit) => unit.x)),
115
+ y: Math.min(...units.map((unit) => unit.y)),
116
+ };
117
+ const moved = new Map();
118
+ let along = 0;
119
+ for (const row of layers) {
120
+ if (!row) {
121
+ continue;
122
+ }
123
+ let at = out.size === 0 ? 0 : (widest - span(row)) / 2;
124
+ for (const unit of row) {
125
+ const x = snapTo(start.x + (across ? along : at), snap);
126
+ const y = snapTo(start.y + (across ? at : along), snap);
127
+ const dx = x - unit.x;
128
+ const dy = y - unit.y;
129
+ for (const node of nodes) {
130
+ if (holder.get(node.id) === unit) {
131
+ moved.set(node.id, { x: node.x + dx, y: node.y + dy });
132
+ }
133
+ }
134
+ at += cross(unit) + gap;
135
+ }
136
+ along += Math.max(...row.map(main)) + gap;
137
+ }
138
+ for (const node of nodes) {
139
+ if (!moved.has(node.id)) {
140
+ moved.set(node.id, { x: node.x, y: node.y });
141
+ }
142
+ }
143
+ return moved;
144
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * What a paste adds to a board: the arithmetic, kept apart from the board that
3
+ * adds it.
4
+ */
5
+ import type { CanvasDocument, CanvasNode } from './root/canvas-document.js';
6
+ /**
7
+ * A JSON Canvas document read from pasted text, or nothing where the text is
8
+ * not one: any text that does not parse, or a node without an id, a type and
9
+ * a box. An edge whose ends are not both among the nodes is left out.
10
+ */
11
+ export declare const parseCanvas: (text: string) => CanvasDocument | undefined;
12
+ /**
13
+ * The document a paste adds to a board that already holds `nodes` and the
14
+ * connections named in `taken`.
15
+ *
16
+ * **Every id is made new where the board has it**, by a count after it, and
17
+ * the connections follow their cards to the new ids. **The cards move clear
18
+ * of what they were copied from**: a step down and to the right, and another
19
+ * while any pasted card would still sit where a card already is, so a second
20
+ * paste lands beside the first. Cards from another board, where nothing sits,
21
+ * stay where they were.
22
+ *
23
+ * @param step How far each move is, in the document's own units.
24
+ */
25
+ export declare const pasteInto: (document: CanvasDocument, nodes: readonly CanvasNode[], taken: ReadonlySet<string>, step: number) => CanvasDocument;
@@ -0,0 +1,58 @@
1
+ const finite = (value) => typeof value === 'number' && Number.isFinite(value);
2
+ export const parseCanvas = (text) => {
3
+ let read;
4
+ try {
5
+ read = JSON.parse(text);
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ const { edges, nodes } = (read ?? {});
11
+ if (!Array.isArray(nodes) || nodes.length === 0) {
12
+ return undefined;
13
+ }
14
+ const valid = nodes.every((node) => typeof node?.id === 'string' &&
15
+ typeof node.type === 'string' &&
16
+ [node.x, node.y, node.width, node.height].every(finite));
17
+ if (!valid) {
18
+ return undefined;
19
+ }
20
+ const ids = new Set(nodes.map((node) => node.id));
21
+ return {
22
+ edges: (Array.isArray(edges) ? edges : []).filter((edge) => ids.has(edge?.fromNode) && ids.has(edge?.toNode)),
23
+ nodes: nodes,
24
+ };
25
+ };
26
+ export const pasteInto = (document, nodes, taken, step) => {
27
+ const used = new Set([...taken, ...nodes.map((node) => node.id)]);
28
+ const unique = (id) => {
29
+ let next = id;
30
+ for (let count = 2; used.has(next); count++) {
31
+ next = `${id}-${count}`;
32
+ }
33
+ used.add(next);
34
+ return next;
35
+ };
36
+ const corners = new Set(nodes.map((node) => `${Math.round(node.x)},${Math.round(node.y)}`));
37
+ const pasted = document.nodes ?? [];
38
+ let by = 0;
39
+ while (step > 0 &&
40
+ pasted.some((node) => corners.has(`${Math.round(node.x + by)},${Math.round(node.y + by)}`))) {
41
+ by += step;
42
+ }
43
+ const renamed = new Map();
44
+ const out = pasted.map((node) => {
45
+ const id = unique(node.id);
46
+ renamed.set(node.id, id);
47
+ return { ...node, id, x: node.x + by, y: node.y + by };
48
+ });
49
+ return {
50
+ edges: (document.edges ?? []).map((edge) => ({
51
+ ...edge,
52
+ fromNode: renamed.get(edge.fromNode) ?? edge.fromNode,
53
+ id: unique(edge.id || `${edge.fromNode}-${edge.toNode}`),
54
+ toNode: renamed.get(edge.toNode) ?? edge.toNode,
55
+ })),
56
+ nodes: out,
57
+ };
58
+ };
@@ -1,6 +1,8 @@
1
1
  import { type CanvasView, HelixElement, type ViewportPanDetail, type ViewportWay, type ViewportZoomDetail } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
+ import { type CanvasArrangeOptions } from '../arrange.js';
3
4
  import { type CanvasDocument, type CanvasRoute, type CanvasTone } from './canvas-document.js';
5
+ export type { CanvasArrangeOptions } from '../arrange.js';
4
6
  export type { CanvasDocument, CanvasEdge, CanvasEdgeProps, CanvasEnd, CanvasNode, CanvasNodeProps, CanvasPath, CanvasRoute, CanvasRouteEnds, CanvasSide, CanvasTone, } from './canvas-document.js';
5
7
  export { fromJsonCanvas } from './canvas-document.js';
6
8
  declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion.dev/helix-core").ViewportElement) & typeof HelixElement;
@@ -60,15 +62,24 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
60
62
  * card or connection says so when a reader arrives on it.
61
63
  * - Control or Command with C copies the selected cards, and the connections
62
64
  * between them, as a JSON Canvas document in text, which another board or
63
- * an app that reads the format takes. A paste is your page's: listen for
64
- * `paste` on the board, read the text with `fromJsonCanvas`, and add the
65
- * cards it holds.
65
+ * an app that reads the format takes.
66
+ * - Control or Command with V pastes a JSON Canvas document: the board adds
67
+ * its cards and connections, a step down and to the right of any card they
68
+ * would sit on, and selects them. It asks with `helix-before-paste` first.
69
+ * A page that renders its cards from its own state cancels it and adds the
70
+ * detail's document to that state, through `fromJsonCanvas`. `paste()` does
71
+ * the same from a script.
66
72
  * - Control or Command with Z undoes the last move or resize the board made,
67
73
  * and with Shift, or Control with Y, makes it again. `undo()` and `redo()`
68
74
  * do the same from a script. Each asks with `helix-before-move` and tells
69
75
  * with `helix-move`, as a move does, so a board that holds its positions in
70
76
  * your state is undone through your state.
71
77
  *
78
+ * **`arrange()` moves every card so that none overlaps another**, in layers
79
+ * that follow the arrows, or in a grid on a board with no connections. The
80
+ * cards glide for as long as the board's own transition, and `undo()` puts
81
+ * them back.
82
+ *
72
83
  * Every drag also works with clicks, as WCAG 2.5.7 requires for a pointer that
73
84
  * cannot hold a button down. Click a selected card's move handle, a corner, a
74
85
  * card's connection point, or the end of a selected connection to pick it up.
@@ -129,6 +140,7 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
129
140
  * @slot zoom-out-icon - Replaces the glyph inside the zoom-out button.
130
141
  *
131
142
  * @event {HelixBeforeMoveEvent} helix-before-move - Cards are about to move. Cancelable: cancel it to keep the positions in your own state.
143
+ * @event {HelixBeforePasteEvent} helix-before-paste - Cards and connections are about to be pasted. Cancelable: cancel it to add the detail's document to your own state.
132
144
  * @event {HelixBeforeReconnectEvent} helix-before-reconnect - A connection's end is about to move to another card or side. Cancelable: cancel it to keep connections in your own state.
133
145
  * @event {HelixBeforeRelabelEvent} helix-before-relabel - A connection's label or a group's name is about to change. Cancelable: cancel it to keep labels in your own state.
134
146
  * @event {HelixCanvasEditEvent} helix-canvas-edit - A card was double-clicked, or Enter or F2 was pressed on it. Open your own editor for the card.
@@ -137,6 +149,7 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
137
149
  * @event {HelixCanvasZoomEvent} helix-canvas-zoom - The board zoomed one step, from its controls or the keys. A wheel or a pinch sends `helix-canvas-view`.
138
150
  * @event {HelixConnectEvent} helix-connect - Two cards were chosen to be joined. Add a `helix-canvas-edge` to join them.
139
151
  * @event {HelixMoveEvent} helix-move - Cards moved and the move is finished: a drag was released, a click put a card down, or a key was pressed.
152
+ * @event {HelixPastedEvent} helix-pasted - Cards and connections were pasted, and the board holds them.
140
153
  * @event {HelixReconnectEvent} helix-reconnect - A connection's end moved, and the move is finished.
141
154
  * @event {HelixRelabelEvent} helix-relabel - A connection's label or a group's name changed.
142
155
  * @event {HelixRemoveEvent} helix-remove - Cards or connections were chosen for removal. Remove the elements it names.
@@ -198,6 +211,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
198
211
  * `gestures="activate"`, is scrolled or swiped over.
199
212
  */
200
213
  activateHintLabel: string;
214
+ /** What screen readers hear after `arrange()` moves the cards. */
215
+ arrangedLabel: string;
201
216
  /** The text read with a card to say where its connections come from, with `{cards}`. */
202
217
  comesFromLabel: string;
203
218
  /** The text announced when a connection is requested, with `{from}` and `{to}`. */
@@ -282,6 +297,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
282
297
  * that reflected would write a choice onto every host that no server sent.
283
298
  */
284
299
  order?: 'spatial' | 'edges';
300
+ /** What screen readers hear after a paste, with `{count}` for the cards pasted. */
301
+ pastedLabel: string;
285
302
  /**
286
303
  * The route every connection takes when it sets no `path` of its own:
287
304
  * `straight`, or `step` for right angles.
@@ -308,6 +325,12 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
308
325
  reconnectingLabel: string;
309
326
  /** What screen readers hear after a move or a resize is made again. */
310
327
  redoneLabel: string;
328
+ /**
329
+ * What screen readers hear when Delete asks to remove what is selected, with
330
+ * `{count}` for how many cards and connections, and `{name}` for the one
331
+ * where there is one.
332
+ */
333
+ removedLabel: string;
311
334
  /**
312
335
  * What screen readers hear after a key resizes a card, with `{name}` for the
313
336
  * card and `{width}` and `{height}` for its new size, in the document's
@@ -846,6 +869,40 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
846
869
  * holds, nor over text a reader selected, which are the platform's to copy.
847
870
  */
848
871
  private readonly handleCopy;
872
+ /**
873
+ * A paste on the board of a JSON Canvas document, the text a copy writes,
874
+ * adds its cards and connections. Not into a field a card holds, nor onto a
875
+ * `readonly` board, nor text that is not a board, which are the platform's.
876
+ */
877
+ private readonly handlePaste;
878
+ /**
879
+ * Adds the cards and connections of a JSON Canvas document, as a paste does,
880
+ * and selects the cards. Ids the board already holds are given a count after
881
+ * them, and the cards move a step down and to the right while they would sit
882
+ * on cards already there.
883
+ *
884
+ * Asks with `helix-before-paste` first: cancel it to add the detail's
885
+ * document to your own state. Returns whether the board added the cards:
886
+ * false on a `readonly` board, for text that is not a board, or when the
887
+ * request was refused.
888
+ */
889
+ paste(document: CanvasDocument | string): boolean;
890
+ /** The glide `arrange()` started, while it runs. */
891
+ private gliding;
892
+ /** Ends a glide where it was going. */
893
+ private settle;
894
+ /**
895
+ * Moves the cards so that none overlaps another: in layers that follow the
896
+ * connections, or in a grid where there are none. A group moves as one box
897
+ * with its cards. Each place lands on a multiple of `snap` where it is set.
898
+ *
899
+ * Asks with `helix-before-move` first and tells with `helix-move`, as a
900
+ * move does, so `undo()` puts every card back. The cards glide to their
901
+ * places for as long as the board's plane takes to glide, and land at once
902
+ * where it does not, such as under `prefers-reduced-motion`. Returns whether
903
+ * the cards moved.
904
+ */
905
+ arrange(options?: CanvasArrangeOptions): boolean;
849
906
  /**
850
907
  * Control or Command with Z undoes, and with Shift, or Control with Y,
851
908
  * redoes, from anywhere on the board but a field a card holds, where the