efficient-easel 0.0.0 → 0.97.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 (119) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +818 -4
  3. package/dist/autosave/index.d.ts +101 -0
  4. package/dist/autosave/index.js +1 -0
  5. package/dist/blocks/index.d.ts +306 -0
  6. package/dist/blocks/index.js +0 -0
  7. package/dist/buckets-1vRlQceY.d.ts +13 -0
  8. package/dist/canvas/index.d.ts +194 -0
  9. package/dist/canvas/index.js +1 -0
  10. package/dist/chrome/chrome.css +570 -0
  11. package/dist/chrome/index.d.ts +219 -0
  12. package/dist/chrome/index.js +21 -0
  13. package/dist/chunk-2LUSK32B.js +1 -0
  14. package/dist/chunk-2OAZYSWJ.js +1 -0
  15. package/dist/chunk-67VZRQLG.js +13 -0
  16. package/dist/chunk-6OPSJGAI.js +1 -0
  17. package/dist/chunk-6PS6STGA.js +1 -0
  18. package/dist/chunk-6WY6ZXJG.js +1 -0
  19. package/dist/chunk-7A7O2JWQ.js +1 -0
  20. package/dist/chunk-BZ5ASXOL.js +1 -0
  21. package/dist/chunk-CERTFXCV.js +13 -0
  22. package/dist/chunk-D2BCHTQR.js +1 -0
  23. package/dist/chunk-FI23ALVJ.js +1 -0
  24. package/dist/chunk-GGTPNGFJ.js +1 -0
  25. package/dist/chunk-H4B72XCJ.js +1 -0
  26. package/dist/chunk-H6DDIBQ4.js +1 -0
  27. package/dist/chunk-KDIVA6WD.js +1 -0
  28. package/dist/chunk-KRXQM65X.js +1 -0
  29. package/dist/chunk-MCLBHENY.js +1 -0
  30. package/dist/chunk-MFIRYGHW.js +1 -0
  31. package/dist/chunk-NKB3KVAB.js +1 -0
  32. package/dist/chunk-O2NLQBFX.js +1 -0
  33. package/dist/chunk-OGZFDJ6G.js +1 -0
  34. package/dist/chunk-OWBO4WKA.js +0 -0
  35. package/dist/chunk-QB3BZIRA.js +5 -0
  36. package/dist/chunk-RE4LP46F.js +1 -0
  37. package/dist/chunk-STFMZJKU.js +14 -0
  38. package/dist/chunk-SUO5627P.js +1 -0
  39. package/dist/chunk-TDA4HH54.js +1 -0
  40. package/dist/chunk-WK3AFPXY.js +1 -0
  41. package/dist/chunk-YIMRTIBN.js +3 -0
  42. package/dist/chunk-YNZZYHA4.js +450 -0
  43. package/dist/chunk-YRLPFZW3.js +1 -0
  44. package/dist/chunk-ZAOM6PFH.js +1 -0
  45. package/dist/chunk-ZNCEOSXO.js +1 -0
  46. package/dist/copy/copy.css +282 -0
  47. package/dist/copy/index.d.ts +336 -0
  48. package/dist/copy/index.js +10 -0
  49. package/dist/data/index.d.ts +375 -0
  50. package/dist/data/index.js +1 -0
  51. package/dist/drag/drag.css +360 -0
  52. package/dist/drag/index.d.ts +379 -0
  53. package/dist/drag/index.js +18 -0
  54. package/dist/edit-lock/index.d.ts +354 -0
  55. package/dist/edit-lock/index.js +1 -0
  56. package/dist/editor/editor.css +58 -0
  57. package/dist/editor/index.d.ts +361 -0
  58. package/dist/editor/index.js +9 -0
  59. package/dist/fields/fields.css +207 -0
  60. package/dist/fields/index.d.ts +273 -0
  61. package/dist/fields/index.js +46 -0
  62. package/dist/gold/gold.css +196 -0
  63. package/dist/gold/index.d.ts +280 -0
  64. package/dist/gold/index.js +1 -0
  65. package/dist/icons/index.d.ts +474 -0
  66. package/dist/icons/index.js +1 -0
  67. package/dist/index.d.ts +6 -0
  68. package/dist/index.js +1 -0
  69. package/dist/markup/index.d.ts +452 -0
  70. package/dist/markup/index.js +1 -0
  71. package/dist/menu/index.d.ts +49 -0
  72. package/dist/menu/index.js +15 -0
  73. package/dist/menu/menu.css +254 -0
  74. package/dist/node-ops/index.d.ts +91 -0
  75. package/dist/node-ops/index.js +1 -0
  76. package/dist/panel/index.d.ts +1088 -0
  77. package/dist/panel/index.js +16 -0
  78. package/dist/panel/panel.css +1460 -0
  79. package/dist/pick/index.d.ts +153 -0
  80. package/dist/pick/index.js +14 -0
  81. package/dist/pick/pick.css +235 -0
  82. package/dist/plan-DChbUXdS.d.ts +88 -0
  83. package/dist/rail/index.d.ts +145 -0
  84. package/dist/rail/index.js +1 -0
  85. package/dist/rail/rail.css +175 -0
  86. package/dist/render/index.d.ts +117 -0
  87. package/dist/render/index.js +5 -0
  88. package/dist/resolve-D68pb3Bx.d.ts +57 -0
  89. package/dist/shell/index.d.ts +159 -0
  90. package/dist/shell/index.js +1 -0
  91. package/dist/shell/shell.css +122 -0
  92. package/dist/strings/catalogue.d.ts +141 -0
  93. package/dist/strings/catalogue.js +1 -0
  94. package/dist/strings/index.d.ts +56 -0
  95. package/dist/strings/index.js +2 -0
  96. package/dist/style-clipboard/index.d.ts +184 -0
  97. package/dist/style-clipboard/index.js +1 -0
  98. package/dist/tree/index.d.ts +173 -0
  99. package/dist/tree/index.js +1 -0
  100. package/dist/tree/tree.css +618 -0
  101. package/dist/types-41704JE4.d.ts +112 -0
  102. package/dist/types-CEqUFH2j.d.ts +129 -0
  103. package/dist/types-CuNiSnX6.d.ts +204 -0
  104. package/dist/types-DNrn_w4V.d.ts +88 -0
  105. package/dist/types-Dy6oR6Z2.d.ts +153 -0
  106. package/dist/types-pGBXevBU.d.ts +131 -0
  107. package/dist/useNodeOps-BF0fQsif.d.ts +68 -0
  108. package/dist/watch-DmasQA61.d.ts +60 -0
  109. package/dist/wordFit-9B9nqyf3.d.ts +35 -0
  110. package/dist/words-B2YLaKEr.d.ts +30 -0
  111. package/dist/words-B87GIFWH.d.ts +86 -0
  112. package/dist/words-BK-npta-.d.ts +27 -0
  113. package/dist/words-CD3WADyb.d.ts +51 -0
  114. package/dist/words-CsRWXkY4.d.ts +129 -0
  115. package/dist/words-D9ChvbNC.d.ts +52 -0
  116. package/dist/words-DOhF-4D4.d.ts +35 -0
  117. package/dist/words-DagJdwIA.d.ts +78 -0
  118. package/dist/words-DfxEp_RH.d.ts +142 -0
  119. package/package.json +202 -3
@@ -0,0 +1,379 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+ import { P as Place, S as SlotAddress } from '../types-41704JE4.js';
4
+ import { C as CanvasTarget$1 } from '../watch-DmasQA61.js';
5
+ import { D as DragWords } from '../words-D9ChvbNC.js';
6
+
7
+ /**
8
+ * The one drag in flight, shared by every surface of an editor — the Layers
9
+ * tree, the canvas and the Add list (blueprint step 3.2).
10
+ *
11
+ * Native drag-and-drop does not let a drop target read what is being dragged
12
+ * until the drop itself (the data is sealed during `dragover`), and a tree that
13
+ * only knows about drags it started cannot take a block from the Add list. So
14
+ * the surface that starts a drag writes it here and every surface reads it: a
15
+ * block picked up on the canvas can land in the tree, a tile from the Add list
16
+ * on either.
17
+ *
18
+ * `from` is where the thing sits now — absent for something new (an Add tile),
19
+ * which is also why a new thing can never be a no-op drop.
20
+ */
21
+
22
+ type DragHeld<I> = {
23
+ /** The identity `keyOf` gave it — which row or box is the one being dragged. */
24
+ key: string;
25
+ item: I;
26
+ /** Where it sits now. Absent: it is new, from the Add list. */
27
+ from?: Place;
28
+ };
29
+ type DragSession<I> = {
30
+ /** The drag in flight, current at once (for event handlers). */
31
+ get: () => DragHeld<I> | null;
32
+ /** The drag as last TOLD to subscribers (for rendering — see below). */
33
+ shown: () => DragHeld<I> | null;
34
+ start: (held: DragHeld<I>) => void;
35
+ end: () => void;
36
+ subscribe: (listener: () => void) => () => void;
37
+ };
38
+ /**
39
+ * `get()` is current the moment a drag starts — the drop targets read it on
40
+ * their first `dragover`. SUBSCRIBERS hear about a start one tick later: the
41
+ * browser takes the drag picture when the `dragstart` handlers return, and a
42
+ * render in between (a row dimming, the handle hiding) would be in the picture.
43
+ * An end is told at once.
44
+ */
45
+ declare function createDragSession<I>(): DragSession<I>;
46
+
47
+ /**
48
+ * Where a drop lands — the engine's one hit rule, as pure functions (blueprint
49
+ * step 3.1).
50
+ *
51
+ * The two editors had each written their own, and they disagreed in ways a
52
+ * merchant moving between them would feel: the campaign designer dragged the
53
+ * whole row and put an "into" drop at the START of a column; the website editor
54
+ * dragged a grip and put it at the END, and only in the middle of a container's
55
+ * row. There were five different drop lines between them. One rule now:
56
+ *
57
+ * - a SEAM (the gap between two rows) means "between" — its own place;
58
+ * - a CONTAINER's row means "into", the whole row — the host names the exact
59
+ * place (start or end is the host's call, per container);
60
+ * - an ORDINARY row splits in half: the top half drops before it, the bottom
61
+ * half after it;
62
+ * - a PINNED row (a header first, a footer last) never moves, and a drop on it
63
+ * lands on the side that keeps the band intact: after a pinned first row,
64
+ * before a pinned last one.
65
+ *
66
+ * Every place here is a GAP — the insert position in its list, counted as if
67
+ * the dragged row were still in it. `gapToMoveIndex` turns that into the index
68
+ * `efficient-easel/data`'s `move` wants.
69
+ */
70
+
71
+ type DropSide = 'before' | 'after' | 'into';
72
+ /** What the engine needs to know about one row to decide a drop on it. */
73
+ type DropRow = {
74
+ /** Where the row sits: its list, and its index in that list. */
75
+ place: Place;
76
+ /** Present: the row is a container and the whole row means "into", landing here. */
77
+ into?: Place;
78
+ /** A row fixed at the start or the end of its list. */
79
+ pinned?: 'first' | 'last';
80
+ };
81
+ type DropSpot = {
82
+ side: DropSide;
83
+ to: Place;
84
+ };
85
+ /** The spot a pointer at `y` means over a row drawn at `top` with `height`. */
86
+ declare function dropOnRow(row: DropRow, y: number, top: number, height: number): DropSpot;
87
+ /**
88
+ * A drop that would leave the row where it is: its own gap on either side. Such
89
+ * a drop draws no line — a line promises a move that is not coming.
90
+ */
91
+ declare function isNoOpDrop(from: Place, to: Place): boolean;
92
+ /**
93
+ * The gap a drop names → the index `move` wants. Within one list the row leaves
94
+ * its own slot first, so every gap after it is one less; into another list the
95
+ * gap is the index.
96
+ */
97
+ declare function gapToMoveIndex(from: Place, to: Place): number;
98
+ /** One step up or down its own list — what ⌥↑ / ⌥↓ ask for, as a gap. */
99
+ declare function stepGap(from: Place, dir: -1 | 1): Place;
100
+
101
+ /**
102
+ * Drag-and-drop for a Layers tree — ONE engine for both editors (blueprint step
103
+ * 3.1). The host keeps what is genuinely its own: whether a drop is allowed
104
+ * (`canDrop`) and what it writes (`onDrop`, `onStep`); the engine owns the
105
+ * gesture, the hit rule (./hit), the one drop line, auto-scroll (./autoScroll)
106
+ * and ⌥↑ / ⌥↓.
107
+ *
108
+ * Native HTML5 drag-and-drop, as both editors already used: the whole ROW is
109
+ * what you pick up (the campaign designer's way — the website editor's grip was
110
+ * a 9px target), and the picture that follows the pointer is the row itself,
111
+ * raised with a shadow.
112
+ *
113
+ * const drag = useTreeDrag({ keyOf, canDrop, onDrop, onStep, canStep, readOnly });
114
+ * <LayersTree rootProps={drag.rootProps()}>
115
+ * <TreeSeam {...drag.seam({ place: { ...list, index: 0 } })} onAdd={…} label="Add block here" />
116
+ * <TreeRow {...drag.row({ item, place, into, pinned }, { onClick })} icon={…} name={…} />
117
+ *
118
+ * A drop the host refuses draws nothing and cannot land; a drop that would leave
119
+ * the row where it was draws nothing either. Leaving the tree clears the line.
120
+ */
121
+
122
+ type TreeDragOptions<I> = {
123
+ /** The identity of an item — which row is the one being dragged. */
124
+ keyOf: (item: I) => string;
125
+ /** May `item` land at `to`? A refused spot draws no line and cannot be dropped on. */
126
+ canDrop: (item: I, to: Place) => boolean;
127
+ /** Land it. `to` is a gap (see ./hit `gapToMoveIndex` for `move`'s index). */
128
+ onDrop: (item: I, to: Place) => void;
129
+ /** ⌥↑ / ⌥↓ on a row: move it one step. Absent: the keys do nothing. */
130
+ onStep?: (item: I, dir: -1 | 1) => void;
131
+ /** May it step that way? Absent: the host's `onStep` decides. */
132
+ canStep?: (item: I, dir: -1 | 1) => boolean;
133
+ /** Nothing can be picked up, stepped or dropped. */
134
+ readOnly?: boolean;
135
+ /**
136
+ * The editor's shared drag (./session) — so a block picked up on the canvas or
137
+ * a tile from the Add list can land in the tree, and a row from the tree on
138
+ * the canvas. Absent: the tree keeps a drag of its own.
139
+ */
140
+ session?: DragSession<I>;
141
+ };
142
+ type TreeDragRowOptions<I> = DropRow & {
143
+ item: I;
144
+ /** False: the row is a place to drop, not a thing to pick up. Pinned rows never are. */
145
+ canDrag?: boolean;
146
+ };
147
+ type TreeDragSeamOptions = {
148
+ place: Place;
149
+ };
150
+ type DivProps = HTMLAttributes<HTMLDivElement> & Record<`data-${string}`, string | number | undefined>;
151
+ type TreeDragRowProps = {
152
+ draggable: boolean;
153
+ dragging: boolean;
154
+ drop?: DropSide;
155
+ rowProps: DivProps;
156
+ };
157
+ type TreeDragSeamProps = {
158
+ drop: boolean;
159
+ seamProps: DivProps;
160
+ };
161
+ type TreeDrag<I> = {
162
+ /** The item being dragged, or null. */
163
+ dragging: I | null;
164
+ row: (opts: TreeDragRowOptions<I>, host?: DivProps) => TreeDragRowProps;
165
+ seam: (opts: TreeDragSeamOptions, host?: DivProps) => TreeDragSeamProps;
166
+ /** For the tree's root: leaving it clears the line. */
167
+ rootProps: (host?: DivProps) => DivProps;
168
+ };
169
+ declare function useTreeDrag<I>(options: TreeDragOptions<I>): TreeDrag<I>;
170
+
171
+ /**
172
+ * Where a drop on the CANVAS lands — pure functions over measured boxes
173
+ * (blueprint step 3.2). The tree's rule (./hit) is about rows in a list; the
174
+ * canvas is boxes inside boxes, laid out down the page or across it, so it
175
+ * needs its own — the campaign designer's overlay, made general:
176
+ *
177
+ * - ONE HANDLE: the smallest box under the pointer wins, so hovering an image
178
+ * offers the image, not the section it sits in (their corners are a few
179
+ * pixels apart); a parent is picked up by hovering its own padding.
180
+ * - THE ZONE: the innermost list under the pointer that will take the drop. A
181
+ * refused inner zone falls through to the next one out — a section dragged
182
+ * over a column lands between sections, not nowhere.
183
+ * - THE GAP: along the zone's own axis — down a column, ACROSS a row of
184
+ * columns — counted against the children's midpoints; the line is drawn in
185
+ * the middle of that gap, horizontal or vertical to match.
186
+ *
187
+ * All boxes are in ONE coordinate space: the layer drawn over the canvas.
188
+ */
189
+
190
+ type Box = {
191
+ left: number;
192
+ top: number;
193
+ width: number;
194
+ height: number;
195
+ };
196
+ /** Something on the canvas that can be picked up. */
197
+ type CanvasSource<I> = {
198
+ key: string;
199
+ item: I;
200
+ box: Box;
201
+ /** What the handle calls it — "Image", "Section". */
202
+ label: string;
203
+ /** The handle's tooltip. Default "Drag to move this image". */
204
+ title?: string;
205
+ /** Where it sits now — a drop back there is a no-op. */
206
+ from?: Place;
207
+ };
208
+ /** A list on the canvas that takes drops: a slot, laid out one way. */
209
+ type CanvasZone = {
210
+ key: string;
211
+ list: SlotAddress;
212
+ box: Box;
213
+ /** 'y': children stack down; 'x': they sit across (columns). */
214
+ axis: 'x' | 'y';
215
+ /** The children, in order. */
216
+ children: Box[];
217
+ };
218
+ /** The gap between two sections, offered as a place to add one. */
219
+ type CanvasSeam = {
220
+ key: string;
221
+ place: Place;
222
+ box: Box;
223
+ };
224
+ declare const contains: (b: Box, x: number, y: number) => boolean;
225
+ /** The smallest source under the point — the innermost thing. */
226
+ declare function pickSource<I>(sources: readonly CanvasSource<I>[], x: number, y: number): CanvasSource<I> | null;
227
+ /** The gap the point means in a zone: children whose middle it has passed. */
228
+ declare function gapInZone(zone: CanvasZone, x: number, y: number): number;
229
+ /** The drop line for a gap: 2px, in the middle of the space between two children. */
230
+ declare function gapLine(zone: CanvasZone, gap: number): Box;
231
+ type CanvasTarget = {
232
+ zone: CanvasZone;
233
+ to: Place;
234
+ line: Box;
235
+ } | null;
236
+ /**
237
+ * Where a drop at the point lands: the innermost zone under it that takes it.
238
+ * `accept` answers for the place; a refused zone falls through to the one
239
+ * outside it. A drop that would leave the thing where it is lands NOWHERE — it
240
+ * does not fall through to an outer list, which would move it somewhere the
241
+ * pointer is not.
242
+ */
243
+ declare function canvasTarget(zones: readonly CanvasZone[], x: number, y: number, accept: (to: Place) => boolean, isNoOp?: (to: Place) => boolean): CanvasTarget;
244
+ /** The seams between a zone's children — where "+ Add section" goes. */
245
+ declare function seamsBetween(zone: CanvasZone, keyPrefix?: string): CanvasSeam[];
246
+
247
+ type MeasuredNode = {
248
+ id: string;
249
+ place: Place;
250
+ box: Box;
251
+ };
252
+ type MeasuredCanvas = {
253
+ nodes: MeasuredNode[];
254
+ zones: CanvasZone[];
255
+ };
256
+ declare const EMPTY_MEASURE: MeasuredCanvas;
257
+ declare function measureCanvas(canvas: CanvasTarget$1, layer: Element): MeasuredCanvas;
258
+
259
+ type CanvasDragModel<I> = {
260
+ /** What may be picked up. Leave out what cannot move — a pinned section, a block with nowhere to go. */
261
+ sources: CanvasSource<I>[];
262
+ /** The lists that take drops. */
263
+ zones: CanvasZone[];
264
+ /** The gaps offered as "+ Add section" (see `seamsBetween`). */
265
+ seams?: CanvasSeam[];
266
+ };
267
+ type CanvasDragLayerProps<I> = {
268
+ canvas: CanvasTarget$1 | null;
269
+ session: DragSession<I>;
270
+ /** Turn what was measured into what may be picked up and dropped on. */
271
+ model: (measured: MeasuredCanvas) => CanvasDragModel<I>;
272
+ canDrop: (item: I, to: Place) => boolean;
273
+ onDrop: (item: I, to: Place) => void;
274
+ /** The handle CLICKED, not dragged: select what it names. Absent: a click does nothing. */
275
+ onPick?: (item: I) => void;
276
+ /** "+ Add section" in a seam: open the Add panel at that place. */
277
+ onSeamAdd?: (place: Place) => void;
278
+ seamLabel?: string;
279
+ /** "+ Add block" in an empty slot: open the Add panel there. */
280
+ onZoneAdd?: (place: Place) => void;
281
+ zoneAddLabel?: string;
282
+ readOnly?: boolean;
283
+ /** Re-measure when this changes — the document's revision. Layout changes re-measure by themselves. */
284
+ revision?: unknown;
285
+ /** How the canvas is measured. Default: Puck's markers (./measure). */
286
+ measure?: (canvas: CanvasTarget$1, layer: Element) => MeasuredCanvas;
287
+ /**
288
+ * The layer's own words in the host's language:
289
+ * `useEditorStrings().drag.canvas` (0.95.0). Left out, English. `seamLabel`
290
+ * and `zoneAddLabel` above still win for their one word. A prop, not the
291
+ * strings provider: drag imports only its own lane.
292
+ */
293
+ words?: DragWords['canvas'];
294
+ };
295
+ /** How long the handle waits for the pointer on its way from the frame. */
296
+ declare const HANDLE_GRACE_MS = 140;
297
+ declare function CanvasDragLayer<I>(props: CanvasDragLayerProps<I>): react.JSX.Element;
298
+
299
+ type AddTile = {
300
+ /** The block's type — what `onInsert` and `itemFor` are given. */
301
+ type: string;
302
+ /** The tile's caption. */
303
+ label: string;
304
+ icon?: ReactNode;
305
+ /** More words search should find it by. */
306
+ keywords?: readonly string[];
307
+ /** The tooltip, when the caption is a shortening. */
308
+ title?: string;
309
+ /** A picture of what it adds — a section's thumbnail. Every tile of a group
310
+ * having one lays the group out as cards. */
311
+ cover?: ReactNode;
312
+ };
313
+ type AddGroup = {
314
+ title: string;
315
+ tiles: readonly AddTile[];
316
+ };
317
+ type AddPanelProps<I> = {
318
+ groups: readonly AddGroup[];
319
+ /** The editor's drag session — a dragged tile is a drag in it. */
320
+ session: DragSession<I>;
321
+ /** The drag item for a new block of `type`. */
322
+ itemFor: (type: string) => I;
323
+ /** A tile clicked: add one — at the place the panel was opened for, or the host's default. */
324
+ onInsert: (type: string) => void;
325
+ /** The panel was opened at a place — "Adding to Column 2" — and can stop being. */
326
+ at?: {
327
+ label: string;
328
+ onClear: () => void;
329
+ };
330
+ /** The line under the title. Default "Drag onto the page, or click to add." */
331
+ hint?: string;
332
+ /** The search field's name. Default "Search blocks". */
333
+ searchLabel?: string;
334
+ readOnly?: boolean;
335
+ /**
336
+ * The shell's own words in the host's language:
337
+ * `useEditorStrings().drag.add` (0.95.0). Left out, English. `hint` and
338
+ * `searchLabel` above still win for their one line. A prop, not the strings
339
+ * provider: drag imports only its own lane.
340
+ */
341
+ words?: DragWords['add'];
342
+ };
343
+ declare function AddPanel<I>({ groups, session, itemFor, onInsert, at, hint: ownHint, searchLabel: ownSearchLabel, readOnly, words, }: AddPanelProps<I>): react.JSX.Element;
344
+
345
+ /**
346
+ * Scroll the list while a drag is held near its top or bottom edge (blueprint
347
+ * step 3.1).
348
+ *
349
+ * From the campaign designer (efficient-admin-portal
350
+ * `src/components/email/dragAutoScroll.ts`), where it fixed the one drag a long
351
+ * tree could not do: a section at the bottom could not reach the top without
352
+ * dropping it halfway and going again. The website editor had none. The numbers
353
+ * are the designer's, which the owner has used since:
354
+ *
355
+ * - the last 56px of the box, top or bottom, scroll it;
356
+ * - up to 16px a frame, faster the closer the pointer is to the edge;
357
+ * - further than 56px OUTSIDE the box, nothing: the pointer has gone elsewhere.
358
+ *
359
+ * Nothing here reads a global at import; the document and the frame clock come
360
+ * from the element being scrolled.
361
+ */
362
+ declare const AUTO_SCROLL_EDGE = 56;
363
+ declare const AUTO_SCROLL_MAX_SPEED = 16;
364
+ /** Pixels a frame for a pointer `distance` px in from an edge (negative = outside). */
365
+ declare function autoScrollSpeed(distance: number): number;
366
+ /** The signed scroll for a pointer at `y` against a box from `top` to `bottom`. */
367
+ declare function autoScrollDelta(y: number, top: number, bottom: number): number;
368
+ /** The nearest ancestor that really scrolls — one whose content overflows it. */
369
+ declare function scrollParent(el: Element | null): HTMLElement | null;
370
+ /** `el` itself if it scrolls, else the nearest ancestor that does. */
371
+ declare function scrollBoxOf(el: HTMLElement | null): HTMLElement | null;
372
+ /**
373
+ * Scroll `box` while a drag is live. Reads the pointer from a capturing
374
+ * `dragover` on the box's document (a drag over the canvas frame never reaches
375
+ * it, which is right: the canvas scrolls itself). Returns the stop.
376
+ */
377
+ declare function startAutoScroll(box: HTMLElement): () => void;
378
+
379
+ export { AUTO_SCROLL_EDGE, AUTO_SCROLL_MAX_SPEED, type AddGroup, AddPanel, type AddPanelProps, type AddTile, type Box, CanvasDragLayer, type CanvasDragLayerProps, type CanvasDragModel, type CanvasTarget as CanvasDropTarget, type CanvasSeam, type CanvasSource, type CanvasZone, type DragHeld, type DragSession, DragWords, type DropRow, type DropSide, type DropSpot, EMPTY_MEASURE, HANDLE_GRACE_MS, type MeasuredCanvas, type MeasuredNode, type TreeDrag, type TreeDragOptions, type TreeDragRowOptions, type TreeDragRowProps, type TreeDragSeamOptions, type TreeDragSeamProps, autoScrollDelta, autoScrollSpeed, canvasTarget, contains, createDragSession, dropOnRow, gapInZone, gapLine, gapToMoveIndex, isNoOpDrop, measureCanvas, pickSource, scrollBoxOf, scrollParent, seamsBetween, startAutoScroll, stepGap, useTreeDrag };
@@ -0,0 +1,18 @@
1
+ import{DEFAULT_DRAG_WORDS as e}from"../chunk-O2NLQBFX.js";import{scrollBoxOf as t,startAutoScroll as n,isNoOpDrop as l}from"../chunk-6PS6STGA.js";export{AUTO_SCROLL_EDGE,AUTO_SCROLL_MAX_SPEED,autoScrollDelta,autoScrollSpeed,createDragSession,dropOnRow,gapToMoveIndex,isNoOpDrop,scrollBoxOf,scrollParent,startAutoScroll,stepGap,useTreeDrag}from"../chunk-6PS6STGA.js";import{useCanvasLayout as a,useCanvasEvent as r}from"../chunk-MCLBHENY.js";import{framePointToHost as o,elementScale as s,frameRectToLayer as i,clientPointToLayer as c}from"../chunk-ZNCEOSXO.js";import{CloseIcon as d,SearchIcon as u}from"../chunk-YNZZYHA4.js";import{parseZoneKey as h}from"../chunk-KRXQM65X.js";import"../chunk-NKB3KVAB.js";import{useRef as p,useEffect as m,useState as f,useCallback as g,useMemo as b,useSyncExternalStore as y,useId as v}from"react";import{jsxs as x,jsx as k}from"react/jsx-runtime";var w=(e,t,n)=>t>=e.left&&t<=e.left+e.width&&n>=e.top&&n<=e.top+e.height,N=e=>e.width*e.height;function D(e,t,n){let l=null;for(const a of e)w(a.box,t,n)&&(!l||N(a.box)<=N(l.box))&&(l=a);return l}function S(e,t,n){const l="x"===e.axis?t:n;let a=0;for(const t of e.children){l>("x"===e.axis?t.left+t.width/2:t.top+t.height/2)&&(a+=1)}return a}function A(e,t){const n=e.children;if("x"===e.axis){const l=n[t-1],a=n[t],r=l&&a?(l.left+l.width+a.left)/2:l?l.left+l.width:a?a.left:e.box.left,o=a??l??e.box;return{left:r-1,top:o.top,width:2,height:o.height}}const l=n[t-1],a=n[t],r=l&&a?(l.top+l.height+a.top)/2:l?l.top+l.height:a?a.top:e.box.top;return{left:e.box.left,top:r-1,width:e.box.width,height:2}}function T(e,t,n,l,a=()=>!1){const r=e.filter(e=>w(e.box,t,n)).sort((e,t)=>N(e.box)-N(t.box));for(const e of r){const r=S(e,t,n),o={...e.list,index:r};if(a(o))return null;if(l(o))return{zone:e,to:o,line:A(e,r)}}return null}function z(e,t=e.key){const n=[];for(let l=1;l<e.children.length;l++){const a=e.children[l-1],r=e.children[l],o=a.top+a.height;n.push({key:`${t}:${l}`,place:{...e.list,index:l},box:{left:e.box.left,top:o,width:e.box.width,height:Math.max(r.top-o,0)}})}return n}var C={nodes:[],zones:[]},E="data-puck-dropzone",L="data-puck-component";function O(e,t){if(e.length>=2){const[t,n]=e;return Math.abs(n.top-t.top)<Math.min(t.height,n.height)/2&&n.left>t.left?"x":"y"}const n=t.ownerDocument.defaultView?.getComputedStyle(t);return n&&n.display.includes("flex")&&n.flexDirection.startsWith("row")?"x":"y"}function j(e,t){const{frame:n,document:l}=e,a=e=>i(n,function(e){const t=e.getBoundingClientRect();return{left:t.left,top:t.top,width:t.width,height:t.height}}(e),t),r=[],o=[];for(const e of l.querySelectorAll(`[${E}]`)){const t=e.getAttribute(E)??"";let n;try{n=h(t)}catch{continue}const l=[...e.querySelectorAll(`[${L}]`)].filter(t=>t.parentElement?.closest(`[${E}]`)===e),s=l.map(a);o.push({key:t,list:n,box:a(e),axis:O(s,e),children:s}),l.forEach((e,t)=>{const l=e.getAttribute(L);l&&r.push({id:l,place:{...n,index:t},box:s[t]})})}return{nodes:r,zones:o}}var B=140,M=e=>({left:e.left,top:e.top,width:e.width,height:e.height});function K(i){const{canvas:d,session:u,readOnly:h,words:v=e.canvas}=i,w=p(i);m(()=>{w.current=i});const N=p(null),S=a(d),[A,z]=f(0),E=g(()=>z(e=>e+1),[]),[L,O]=f(C);m(()=>{const e=N.current;d&&e&&O((w.current.measure??j)(d,e))},[d,S,i.revision,A]);const B=i.model,K=b(()=>B(L),[B,L]),X=y(u.subscribe,u.shown,u.shown),[$,P]=f(null),[R,Y]=f(null),Z=p(null),_=()=>{Z.current&&clearTimeout(Z.current),Z.current=null},G=()=>{_(),Z.current=setTimeout(()=>{u.get()||P(null)},140)};m(()=>_,[]),r(d,"mousemove",e=>{const t=N.current;if(!d||!t||w.current.readOnly||u.get())return;_();const n=o(d.frame,e.clientX,e.clientY,t),l=s(t),a=D(K.sources,n.x/l,n.y/l);P(e=>e?.key===a?.key&&e?.box===a?.box?e:a)}),r(d,"mouseout",e=>{e.relatedTarget||G()}),r(d,"mouseover",e=>{e.relatedTarget||E()});const q=p(null),F=g(()=>{q.current?.(),q.current=null,Y(null)},[]);m(()=>u.subscribe(()=>{u.get()?E():F()}),[u,F,E]),m(()=>F,[F]);const H=e=>{const t=u.get(),n=N.current;if(!t||!n)return null;const a=c(n,e.clientX,e.clientY),r=T(K.zones,a.x,a.y,e=>w.current.canDrop(t.item,e),e=>!!t.from&&l(t.from,e));return r?{h:t,t:r}:null},I={onDragEnter:e=>{if(q.current)return;const l=t(e.currentTarget.parentElement?.parentElement??null);q.current=l?n(l):null},onDragOver:e=>{const t=H(e);if(!t)return void Y(null);e.preventDefault(),e.dataTransfer.dropEffect=/move|all|uninitialized/i.test(e.dataTransfer.effectAllowed)?"move":"copy";const n={zoneKey:t.t.zone.key,line:t.t.line,axis:t.t.zone.axis};Y(e=>e&&e.zoneKey===n.zoneKey&&e.line.left===n.line.left&&e.line.top===n.line.top?e:n)},onDragLeave:e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||Y(null)},onDrop:e=>{const t=H(e);t&&(e.preventDefault(),u.end(),F(),w.current.onDrop(t.h.item,t.t.to))}},Q={draggable:!h&&!!$,onMouseEnter:_,onMouseLeave:()=>!u.get()&&G(),onDragStart:e=>{if($&&!h){u.start({key:$.key,item:$.item,from:$.from}),e.dataTransfer.effectAllowed="move";try{e.dataTransfer.setData("text/plain",$.key)}catch{}}else e.preventDefault()},onDragEnd:()=>{u.end(),F()},onClick:()=>{$&&!h&&w.current.onPick?.($.item)}},{seams:U=[]}=K,V=K.zones.filter(e=>0===e.children.length);/* @__PURE__ */
2
+ return x("div",{ref:N,className:"es-canvas-layer",children:[X||!i.onSeamAdd||h?null:U.map(e=>/* @__PURE__ */k("div",{className:"es-canvas-seam",style:{left:e.box.left,top:e.box.top+e.box.height/2-8,width:e.box.width,height:16},children:/* @__PURE__ */k("button",{type:"button",className:"es-canvas-seam-add",onClick:()=>i.onSeamAdd?.(e.place),children:v.addButton({label:i.seamLabel??v.addSection})})},e.key)),i.onZoneAdd&&!h?V.map(e=>/* @__PURE__ */k("button",{type:"button",className:R?.zoneKey===e.key?"es-canvas-empty is-over":"es-canvas-empty",style:M(e.box),onClick:()=>i.onZoneAdd?.({...e.list,index:0}),children:v.addButton({label:i.zoneAddLabel??v.addBlock})},e.key)):null,X?/* @__PURE__ */k("div",{className:"es-canvas-catch",...I}):null,R&&!V.some(e=>e.key===R.zoneKey)?/* @__PURE__ */k("div",{className:`es-canvas-line is-${R.axis}`,style:M(R.line)}):null,
3
+ /* @__PURE__ */x("div",{className:["es-canvas-handle",$&&!h?"is-shown":"",X?"is-dragging":""].filter(Boolean).join(" "),style:$?{left:$.box.left+2,top:Math.max($.box.top-11,0)}:void 0,title:$?$.title??v.handle({label:$.label}):void 0,...Q,children:[
4
+ /* @__PURE__ */k("span",{className:"es-canvas-grip","aria-hidden":"true",children:"⋮⋮"}),$?.label]})]})}var X=e=>e.tiles.length>0&&e.tiles.every(e=>null!=e.cover);function $({groups:t,session:n,itemFor:l,onInsert:a,at:r,hint:o,searchLabel:s,readOnly:i,words:c=e.add}){const h=o??c.hint,p=s??c.search,[m,g]=f(""),b=v(),y=m.trim().toLowerCase(),w=t.map(e=>({...e,tiles:y?e.tiles.filter(e=>((e,t)=>e.label.toLowerCase().includes(t)||(e.keywords??[]).some(e=>e.toLowerCase().includes(t)))(e,y)):e.tiles})).filter(e=>e.tiles.length>0);/* @__PURE__ */
5
+ return x("div",{className:"es-add",children:[r?/* @__PURE__ */x("div",{className:"es-add-at",role:"status",children:[
6
+ /* @__PURE__ */k("span",{children:r.label}),
7
+ /* @__PURE__ */k("button",{type:"button",className:"es-add-at-clear","aria-label":c.stop,title:c.stop,onClick:r.onClear,children:/* @__PURE__ */k(d,{size:12,"aria-hidden":"true"})})]}):null,
8
+ /* @__PURE__ */k("p",{className:"es-add-hint",children:h}),
9
+ /* @__PURE__ */x("div",{className:"es-add-search",children:[
10
+ /* @__PURE__ */k(u,{size:16,"aria-hidden":"true"}),
11
+ /* @__PURE__ */k("input",{id:b,type:"search","aria-label":p,placeholder:c.searchPlaceholder({label:p}),value:m,onChange:e=>g(e.target.value)}),m?/* @__PURE__ */k("button",{type:"button",className:"es-add-search-clear","aria-label":c.clearSearch,onClick:()=>g(""),children:/* @__PURE__ */k(d,{size:12,"aria-hidden":"true"})}):null]}),0===w.length?/* @__PURE__ */x("div",{className:"es-add-empty",role:"status",children:[
12
+ /* @__PURE__ */k("div",{className:"es-add-empty-title",children:c.nothing({query:m.trim()})}),
13
+ /* @__PURE__ */k("div",{className:"es-add-empty-sub",children:c.tryAnother})]}):w.map(e=>/* @__PURE__ */x("section",{className:"es-add-group","aria-label":e.title,children:[
14
+ /* @__PURE__ */x("div",{className:"es-add-group-head",children:[
15
+ /* @__PURE__ */k("span",{className:"es-add-group-title",children:e.title}),
16
+ /* @__PURE__ */k("span",{className:"es-add-group-count",children:e.tiles.length})]}),
17
+ /* @__PURE__ */k("div",{className:X(e)?"es-add-grid is-cards":"es-add-grid",children:e.tiles.map(e=>{/* @__PURE__ */return x("button",{type:"button",className:null!=e.cover?"es-add-tile has-cover":"es-add-tile",draggable:!i,"aria-disabled":i||void 0,"aria-label":c.tile({label:e.label}),title:i?void 0:e.title??c.tile({label:e.label}),onDragStart:(t=e.type,e=>{if(i)e.preventDefault();else{n.start({key:`new:${t}`,item:l(t)}),e.dataTransfer.effectAllowed="copy";try{e.dataTransfer.setData("text/plain",t)}catch{}}}),onDragEnd:()=>n.end(),onClick:()=>!i&&a(e.type),children:[null!=e.cover?/* @__PURE__ */k("span",{className:"es-add-tile-cover","aria-hidden":"true",children:e.cover}):e.icon?/* @__PURE__ */k("span",{className:"es-add-tile-glyph","aria-hidden":"true",children:e.icon}):null,
18
+ /* @__PURE__ */k("span",{className:"es-add-tile-label",children:e.label})]},e.type);var t})})]},e.title))]})}export{$ as AddPanel,K as CanvasDragLayer,C as EMPTY_MEASURE,B as HANDLE_GRACE_MS,T as canvasTarget,w as contains,S as gapInZone,A as gapLine,j as measureCanvas,D as pickSource,z as seamsBetween};