@vuu-ui/grid-layout 4.0.0-alpha.1

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 (142) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/package.json +40 -0
  4. package/src/GridCommand.js +395 -0
  5. package/src/GridComponentSettings.js +163 -0
  6. package/src/GridController.js +359 -0
  7. package/src/GridDragCoordinator.js +293 -0
  8. package/src/GridGeometry.js +1298 -0
  9. package/src/GridLayout.css.js +119 -0
  10. package/src/GridLayout.js +120 -0
  11. package/src/GridLayoutContext.js +58 -0
  12. package/src/GridLayoutDocument.js +307 -0
  13. package/src/GridLayoutDocumentIds.js +110 -0
  14. package/src/GridLayoutItem.css.js +46 -0
  15. package/src/GridLayoutItem.js +147 -0
  16. package/src/GridLayoutLegacyCompatibility.js +66 -0
  17. package/src/GridLayoutModel.js +138 -0
  18. package/src/GridLayoutProvider.js +263 -0
  19. package/src/GridLayoutStackedItem.css.js +26 -0
  20. package/src/GridLayoutStackedtem.js +140 -0
  21. package/src/GridModel.js +1289 -0
  22. package/src/GridPlaceholder.css.js +9 -0
  23. package/src/GridPlaceholder.js +24 -0
  24. package/src/GridSnapshot.js +11 -0
  25. package/src/GridSplitter.css.js +62 -0
  26. package/src/GridSplitter.js +26 -0
  27. package/src/GridStack.js +277 -0
  28. package/src/Icon.css.js +8 -0
  29. package/src/Icon.js +26 -0
  30. package/src/IconButton.css.js +9 -0
  31. package/src/IconButton.js +28 -0
  32. package/src/TabDialog.css.js +10 -0
  33. package/src/TabDialog.js +77 -0
  34. package/src/TabMenu.css.js +8 -0
  35. package/src/TabMenu.js +78 -0
  36. package/src/componentToJson.js +41 -0
  37. package/src/drag-drop-next/DragContextNext.js +173 -0
  38. package/src/drag-drop-next/DragDropProviderNext.css.js +72 -0
  39. package/src/drag-drop-next/DragDropProviderNext.js +91 -0
  40. package/src/drag-drop-next/SpaceMan.js +256 -0
  41. package/src/drag-drop-next/TemplateDragSession.js +36 -0
  42. package/src/drag-drop-next/tabstrip-drag-drop.js +251 -0
  43. package/src/grid-dom-utils.js +57 -0
  44. package/src/grid-layout-utils.js +39 -0
  45. package/src/grid-snapshot-adapters.js +435 -0
  46. package/src/index.js +24 -0
  47. package/src/json-value.js +56 -0
  48. package/src/layoutFromJson.js +15 -0
  49. package/src/layoutToJson.js +5 -0
  50. package/src/propUtils.js +15 -0
  51. package/src/react-element-utils.js +15 -0
  52. package/src/typeOf.js +15 -0
  53. package/src/useAsDropTarget.js +229 -0
  54. package/src/useDraggable.js +46 -0
  55. package/src/useEditTabName.js +70 -0
  56. package/src/useGridChildProps.js +47 -0
  57. package/src/useGridControllerSnapshot.js +21 -0
  58. package/src/useGridLayout.js +727 -0
  59. package/src/useGridSplitterResizing.js +262 -0
  60. package/src/useNotDropTarget.js +2 -0
  61. package/types/AddTabDialog.d.ts +5 -0
  62. package/types/GridCommand.d.ts +146 -0
  63. package/types/GridComponentSettings.d.ts +71 -0
  64. package/types/GridController.d.ts +50 -0
  65. package/types/GridDragCoordinator.d.ts +80 -0
  66. package/types/GridGeometry.d.ts +331 -0
  67. package/types/GridLayout.d.ts +20 -0
  68. package/types/GridLayoutContext.d.ts +141 -0
  69. package/types/GridLayoutDocument.d.ts +61 -0
  70. package/types/GridLayoutDocumentIds.d.ts +15 -0
  71. package/types/GridLayoutItem.d.ts +28 -0
  72. package/types/GridLayoutLegacyCompatibility.d.ts +57 -0
  73. package/types/GridLayoutModel.d.ts +72 -0
  74. package/types/GridLayoutProvider.d.ts +59 -0
  75. package/types/GridLayoutStackedtem.d.ts +10 -0
  76. package/types/GridModel.d.ts +504 -0
  77. package/types/GridPlaceholder.d.ts +5 -0
  78. package/types/GridSnapshot.d.ts +49 -0
  79. package/types/GridSplitter.d.ts +10 -0
  80. package/types/GridStack.d.ts +160 -0
  81. package/types/Icon.d.ts +6 -0
  82. package/types/IconButton.d.ts +6 -0
  83. package/types/TabDialog.d.ts +9 -0
  84. package/types/TabMenu.d.ts +7 -0
  85. package/types/componentToJson.d.ts +38 -0
  86. package/types/drag-drop-next/DragContextNext.d.ts +92 -0
  87. package/types/drag-drop-next/DragDropProviderNext.d.ts +23 -0
  88. package/types/drag-drop-next/SpaceMan.d.ts +35 -0
  89. package/types/drag-drop-next/TemplateDragSession.d.ts +21 -0
  90. package/types/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
  91. package/types/grid-dom-utils.d.ts +17 -0
  92. package/types/grid-layout-utils.d.ts +18 -0
  93. package/types/grid-matrix.d.ts +5 -0
  94. package/types/grid-snapshot-adapters.d.ts +22 -0
  95. package/types/index.d.ts +24 -0
  96. package/types/json-value.d.ts +23 -0
  97. package/types/layoutFromJson.d.ts +4 -0
  98. package/types/layoutToJson.d.ts +3 -0
  99. package/types/propUtils.d.ts +5 -0
  100. package/types/react-element-utils.d.ts +3 -0
  101. package/types/src/AddTabDialog.d.ts +5 -0
  102. package/types/src/GridLayout.d.ts +14 -0
  103. package/types/src/GridLayoutContext.d.ts +88 -0
  104. package/types/src/GridLayoutItem.d.ts +28 -0
  105. package/types/src/GridLayoutModel.d.ts +59 -0
  106. package/types/src/GridLayoutProvider.d.ts +37 -0
  107. package/types/src/GridLayoutStackedtem.d.ts +10 -0
  108. package/types/src/GridModel.d.ts +350 -0
  109. package/types/src/GridPlaceholder.d.ts +5 -0
  110. package/types/src/GridSplitter.d.ts +9 -0
  111. package/types/src/Icon.d.ts +6 -0
  112. package/types/src/IconButton.d.ts +6 -0
  113. package/types/src/TabMenu.d.ts +6 -0
  114. package/types/src/componentToJson.d.ts +32 -0
  115. package/types/src/drag-drop-next/DragContextNext.d.ts +73 -0
  116. package/types/src/drag-drop-next/DragDropProviderNext.d.ts +20 -0
  117. package/types/src/drag-drop-next/SpaceMan.d.ts +35 -0
  118. package/types/src/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
  119. package/types/src/grid-dom-utils.d.ts +17 -0
  120. package/types/src/grid-layout-utils.d.ts +80 -0
  121. package/types/src/grid-matrix.d.ts +5 -0
  122. package/types/src/index.d.ts +10 -0
  123. package/types/src/layoutFromJson.d.ts +3 -0
  124. package/types/src/layoutToJson.d.ts +2 -0
  125. package/types/src/propUtils.d.ts +5 -0
  126. package/types/src/react-element-utils.d.ts +3 -0
  127. package/types/src/typeOf.d.ts +6 -0
  128. package/types/src/useAsDropTarget.d.ts +7 -0
  129. package/types/src/useDraggable.d.ts +23 -0
  130. package/types/src/useGridChildProps.d.ts +13 -0
  131. package/types/src/useGridLayout.d.ts +43 -0
  132. package/types/src/useGridSplitterResizing.d.ts +12 -0
  133. package/types/src/useNotDropTarget.d.ts +1 -0
  134. package/types/typeOf.d.ts +6 -0
  135. package/types/useAsDropTarget.d.ts +7 -0
  136. package/types/useDraggable.d.ts +24 -0
  137. package/types/useEditTabName.d.ts +11 -0
  138. package/types/useGridChildProps.d.ts +13 -0
  139. package/types/useGridControllerSnapshot.d.ts +7 -0
  140. package/types/useGridLayout.d.ts +53 -0
  141. package/types/useGridSplitterResizing.d.ts +14 -0
  142. package/types/useNotDropTarget.d.ts +1 -0
@@ -0,0 +1,331 @@
1
+ import type { GridItemId, GridItemResizeable, GridTrackSize } from "./GridSnapshot";
2
+ /**
3
+ * Pure, immutable grid geometry.
4
+ *
5
+ * This module owns every geometry and track transition algorithm used by the
6
+ * grid layout. It is deliberately free of DOM, React, EventEmitter and mutable
7
+ * model dependencies; all browser/runtime measurement enters through the
8
+ * explicit, immutable {@link TrackMetrics} input.
9
+ *
10
+ * Callers read an immutable {@link GridGeometry} plus {@link TrackMetrics} from
11
+ * whatever runtime representation they own, invoke a transition, then hydrate
12
+ * the result back into that representation.
13
+ */
14
+ export type GridGeometryTrackType = "column" | "row";
15
+ export type GridGeometryItemType = "content" | "placeholder" | "splitter" | "stacked-content";
16
+ export type GridGeometrySplitDirection = "north" | "south" | "east" | "west";
17
+ export type GridGeometryResizeDirection = "horizontal" | "vertical";
18
+ export type GridGeometryAssignDirection = "bwd" | "fwd";
19
+ export type GridGeometryRemoveReason = "drag" | "close" | "placeholder" | "unstack";
20
+ export type GridGeometryTrackInsertPosition = "after" | "before";
21
+ export interface GridGeometrySpan {
22
+ readonly end: number;
23
+ readonly start: number;
24
+ }
25
+ export interface GridGeometryItem {
26
+ readonly column: GridGeometrySpan;
27
+ readonly dragging?: boolean;
28
+ readonly id: GridItemId;
29
+ readonly resizeable?: GridItemResizeable;
30
+ readonly row: GridGeometrySpan;
31
+ readonly stackId?: string;
32
+ readonly type: GridGeometryItemType;
33
+ }
34
+ export interface GridGeometry {
35
+ readonly columns: readonly GridTrackSize[];
36
+ readonly items: readonly GridGeometryItem[];
37
+ readonly rows: readonly GridTrackSize[];
38
+ }
39
+ /**
40
+ * Explicit measurement input. `measured[i]` is the measured pixel size of
41
+ * track `i`, or -1 when that track has not been measured. Geometry functions
42
+ * never measure; when a transition needs a measurement it does not have, it
43
+ * fails with MEASUREMENT_REQUIRED and the caller re-measures and retries.
44
+ */
45
+ export interface TrackMetrics {
46
+ readonly measured: readonly number[];
47
+ }
48
+ export declare const NO_TRACK_METRICS: TrackMetrics;
49
+ export declare const trackMetrics: (measured: readonly number[]) => TrackMetrics;
50
+ /** Measurement input for both track types. */
51
+ export interface GridMeasurements {
52
+ readonly column?: TrackMetrics;
53
+ readonly row?: TrackMetrics;
54
+ }
55
+ export declare const NO_MEASUREMENTS: GridMeasurements;
56
+ /**
57
+ * The immutable state of a single track: its css size, plus the measured
58
+ * pixel value carried alongside it (-1 when unmeasured).
59
+ */
60
+ export interface GridGeometryTrack {
61
+ readonly measured: number;
62
+ readonly size: GridTrackSize;
63
+ }
64
+ /**
65
+ * The result of a track transition. `sources[i]` is the index of the track in
66
+ * the previous track list that new track `i` derives from, or -1 for a track
67
+ * that did not previously exist.
68
+ */
69
+ export interface GridTrackTransition {
70
+ readonly sources: readonly number[];
71
+ readonly tracks: readonly GridGeometryTrack[];
72
+ }
73
+ export interface GridGeometryUpdate {
74
+ readonly column?: GridGeometrySpan;
75
+ readonly id: GridItemId;
76
+ readonly row?: GridGeometrySpan;
77
+ }
78
+ export interface GridGeometryRemoval {
79
+ readonly id: GridItemId;
80
+ readonly reason: GridGeometryRemoveReason;
81
+ }
82
+ export type GridGeometryErrorCode = "GEOMETRY_ERROR" | "INVALID_ITEM" | "INVALID_TARGET" | "ITEM_NOT_FOUND" | "MEASUREMENT_REQUIRED" | "NON_RESIZABLE" | "TRACK_NOT_FOUND";
83
+ export interface GridGeometryError {
84
+ readonly code: GridGeometryErrorCode;
85
+ readonly message: string;
86
+ readonly trackType?: GridGeometryTrackType;
87
+ }
88
+ export type GridGeometryResult<T> = {
89
+ readonly ok: true;
90
+ readonly value: T;
91
+ } | {
92
+ readonly error: GridGeometryError;
93
+ readonly ok: false;
94
+ };
95
+ export declare const isFractionTrackSize: (size: GridTrackSize) => boolean;
96
+ export declare const isPixelTrackSize: (size: GridTrackSize) => boolean;
97
+ export declare const readTracks: (sizes: readonly GridTrackSize[], metrics?: TrackMetrics) => readonly GridGeometryTrack[];
98
+ export declare const trackSizes: (tracks: readonly GridGeometryTrack[]) => GridTrackSize[];
99
+ export declare const geometryTracks: (geometry: GridGeometry, trackType: GridGeometryTrackType) => readonly GridTrackSize[];
100
+ /** Split a single track into two equally sized tracks. */
101
+ export declare const splitTrack: (tracks: readonly GridGeometryTrack[], trackIndex: number, trackType: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition>;
102
+ /**
103
+ * Find an existing grid line that exactly bisects the given track range,
104
+ * returning -1 when the range cannot be bisected by an existing line.
105
+ */
106
+ export declare const findBisectingTrack: (tracks: readonly GridGeometryTrack[], startIndex: number, endIndex: number, trackType: GridGeometryTrackType) => GridGeometryResult<number>;
107
+ export interface GridTrackBisection {
108
+ readonly newTrackIndex: number;
109
+ readonly transition: GridTrackTransition;
110
+ }
111
+ /**
112
+ * Create a new grid line that bisects the tracks between two grid lines.
113
+ */
114
+ export declare const bisectTracks: (tracks: readonly GridGeometryTrack[], fromTrackLine: number, toTrackLine: number, trackType: GridGeometryTrackType) => GridGeometryResult<GridTrackBisection>;
115
+ /**
116
+ * Insert a new pixel track, reducing the track it displaces by the same
117
+ * amount. The insertion is a no-op when there is no track to reduce.
118
+ */
119
+ export declare const insertTrack: (tracks: readonly GridGeometryTrack[], { index, position, }: {
120
+ index: number;
121
+ position: GridGeometryTrackInsertPosition;
122
+ }, size: number, trackType: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition | undefined>;
123
+ /**
124
+ * Remove a track, assigning its size to the adjacent (contra) track.
125
+ */
126
+ export declare const removeTrack: (tracks: readonly GridGeometryTrack[], index: number, assignDirection?: GridGeometryAssignDirection, trackType?: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition>;
127
+ /** Set an explicit size for a single track. */
128
+ export declare const resizeTrackTo: (tracks: readonly GridGeometryTrack[], trackIndex: number, size: GridTrackSize, trackType?: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition>;
129
+ /** Grow one track by `value`, shrinking its contra track by the same amount. */
130
+ export declare const resizeTracksAdjacent: (tracks: readonly GridGeometryTrack[], { contraTrackIndex, delta, resizedTrackIndex, }: {
131
+ contraTrackIndex: number;
132
+ delta: number;
133
+ resizedTrackIndex: number;
134
+ }, trackType: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition>;
135
+ export interface GridGeometryResizeConstraint {
136
+ readonly minimum: number;
137
+ readonly trackIndices: readonly number[];
138
+ }
139
+ export interface GridProportionalResize {
140
+ readonly afterConstraints?: readonly GridGeometryResizeConstraint[];
141
+ readonly afterTrackIndices: readonly number[];
142
+ readonly beforeConstraints?: readonly GridGeometryResizeConstraint[];
143
+ readonly beforeTrackIndices: readonly number[];
144
+ readonly delta: number;
145
+ readonly initialSizes?: readonly number[];
146
+ }
147
+ /**
148
+ * The total reduction that a group of tracks can absorb without violating
149
+ * its minimum size constraints.
150
+ */
151
+ export declare const getProportionalResizeAllowance: (tracks: readonly GridGeometryTrack[], trackIndices: readonly number[], constraints: readonly GridGeometryResizeConstraint[], trackType: GridGeometryTrackType) => GridGeometryResult<number>;
152
+ /**
153
+ * Move a boundary between two groups of tracks, distributing the change across
154
+ * each group in proportion to current track sizes and honouring the minimum
155
+ * size constraints declared for each group.
156
+ */
157
+ export declare const resizeTracksProportionally: (tracks: readonly GridGeometryTrack[], { afterConstraints, afterTrackIndices, beforeConstraints, beforeTrackIndices, delta, initialSizes, }: GridProportionalResize, trackType: GridGeometryTrackType) => GridGeometryResult<GridTrackTransition>;
158
+ export declare const findGeometryItem: (geometry: GridGeometry, itemId: GridItemId) => GridGeometryItem | undefined;
159
+ /**
160
+ * Apply position updates to a geometry, returning a new geometry. Updates
161
+ * applied to a stacked-content item are propagated to its stacked members,
162
+ * matching the way the legacy model applies child positions.
163
+ */
164
+ export declare const applyGeometryUpdates: (geometry: GridGeometry, updates: readonly GridGeometryUpdate[]) => GridGeometry;
165
+ export declare const isFixedHeightItem: ({ resizeable }: GridGeometryItem) => boolean;
166
+ export declare const isFixedWidthItem: ({ resizeable }: GridGeometryItem) => boolean;
167
+ export declare const canSplitGridItem: (item: GridGeometryItem, splitDirection: GridGeometrySplitDirection) => boolean;
168
+ export declare const gridResizeDirectionForSplit: (splitDirection: GridGeometrySplitDirection) => GridGeometryResizeDirection;
169
+ export declare const itemsFillColumn: (items: readonly GridGeometryItem[], pos: GridGeometrySpan) => boolean;
170
+ export declare const itemsFillRow: (items: readonly GridGeometryItem[], pos: GridGeometrySpan) => boolean;
171
+ /**
172
+ * Split a grid area in two along a grid line, returning the position of the
173
+ * dropped item followed by the position of the split target.
174
+ */
175
+ export declare const splitGridChildPosition: ({ column, row }: {
176
+ column: GridGeometrySpan;
177
+ row: GridGeometrySpan;
178
+ }, splitDirection: GridGeometrySplitDirection, splitTrackIndex: number) => [{
179
+ column: GridGeometrySpan;
180
+ row: GridGeometrySpan;
181
+ }, {
182
+ column: GridGeometrySpan;
183
+ row: GridGeometrySpan;
184
+ }];
185
+ export interface GridGeometryTransition {
186
+ readonly columns?: GridTrackTransition;
187
+ readonly rows?: GridTrackTransition;
188
+ /** updates applied to the model without notifying position listeners */
189
+ readonly silentUpdates: readonly GridGeometryUpdate[];
190
+ /** the geometry that results from applying this transition */
191
+ readonly geometry: GridGeometry;
192
+ /** updates applied to the model and broadcast to position listeners */
193
+ readonly updates: readonly GridGeometryUpdate[];
194
+ }
195
+ /**
196
+ * Shift items to accommodate a track that has been inserted at `trackIndex`.
197
+ */
198
+ export declare const shiftItemsForNewTrack: (items: readonly GridGeometryItem[], trackType: GridGeometryTrackType, trackIndex: number) => GridGeometryUpdate[];
199
+ export interface GridSplitItemRequest {
200
+ readonly droppedItemId: GridItemId;
201
+ readonly resizeDirection?: GridGeometryResizeDirection;
202
+ readonly splitDirection: GridGeometrySplitDirection;
203
+ readonly targetItemId: GridItemId;
204
+ }
205
+ /**
206
+ * A dragged item has been dropped on a (NESW) quadrant of a target item.
207
+ * Split the target, adding or reusing a grid line as required.
208
+ */
209
+ export declare const splitGridItem: (geometry: GridGeometry, { droppedItemId, resizeDirection, splitDirection, targetItemId, }: GridSplitItemRequest, measurements?: GridMeasurements) => GridGeometryResult<GridGeometryTransition>;
210
+ export interface GridReplaceItemRequest {
211
+ readonly droppedItemId: GridItemId;
212
+ readonly targetItemId: GridItemId;
213
+ }
214
+ export interface GridReplaceItemTransition extends GridGeometryTransition {
215
+ readonly removals: readonly GridGeometryRemoval[];
216
+ }
217
+ /**
218
+ * A dragged item has been dropped on the centre of a target item; the dropped
219
+ * item takes over the target's grid area and the target is removed.
220
+ */
221
+ export declare const replaceGridItem: (geometry: GridGeometry, { droppedItemId, targetItemId }: GridReplaceItemRequest) => GridGeometryResult<GridReplaceItemTransition>;
222
+ /**
223
+ * Identify grid lines that no longer serve as the start of one item and the
224
+ * end of another, and which can therefore be removed.
225
+ */
226
+ export declare const findUnusedGridLines: (geometry: GridGeometry) => readonly [number[], number[]];
227
+ /**
228
+ * Shift items to accommodate a track inserted at `index`. The insert position
229
+ * describes which of the two neighbouring tracks the new track overlaps.
230
+ */
231
+ export declare const shiftItemsForInsertedTrack: (items: readonly GridGeometryItem[], trackType: GridGeometryTrackType, index: number, position: GridGeometryTrackInsertPosition) => GridGeometryUpdate[];
232
+ /**
233
+ * When a grid line is removed, every item bound to a line beyond it must be
234
+ * rebound one line lower.
235
+ */
236
+ export declare const shiftItemsForRemovedTrack: (items: readonly GridGeometryItem[], trackType: GridGeometryTrackType, trackIndex: number) => GridGeometryUpdate[];
237
+ export interface GridRemoveItemRequest {
238
+ readonly itemId: GridItemId;
239
+ readonly reason: GridGeometryRemoveReason;
240
+ }
241
+ export interface GridRemoveItemTransition extends GridGeometryTransition {
242
+ /** true when listeners are notified of the position updates */
243
+ readonly notify: boolean;
244
+ readonly placeholders?: {
245
+ readonly added: readonly GridGeometryItem[];
246
+ readonly removedIds: readonly GridItemId[];
247
+ };
248
+ readonly removals: readonly GridGeometryRemoval[];
249
+ /** true when the removed item was a member of a stack */
250
+ readonly stackMember: boolean;
251
+ }
252
+ /**
253
+ * Remove an item, extending contra items to occupy the space it leaves,
254
+ * normalizing tracks that are no longer referenced and regenerating
255
+ * placeholders for any space that remains empty.
256
+ */
257
+ export declare const removeGridItem: (geometry: GridGeometry, { itemId, reason }: GridRemoveItemRequest, { createPlaceholderId, measurements, }: {
258
+ createPlaceholderId: () => string;
259
+ measurements?: GridMeasurements;
260
+ }) => GridGeometryResult<GridRemoveItemTransition>;
261
+ export interface GridPlaceholderTransition {
262
+ readonly added: readonly GridGeometryItem[];
263
+ readonly geometry: GridGeometry;
264
+ readonly removedIds: readonly GridItemId[];
265
+ }
266
+ /**
267
+ * Build the occupancy matrix for a set of items.
268
+ */
269
+ export declare const getGridMatrix: (items: readonly GridGeometryItem[], rowCount: number, colCount: number) => number[][];
270
+ /**
271
+ * Placeholders represent every empty area of the grid. They are regenerated
272
+ * from scratch, so existing placeholders are always replaced.
273
+ */
274
+ export declare const regeneratePlaceholders: (geometry: GridGeometry, createPlaceholderId: () => string) => GridPlaceholderTransition;
275
+ export interface GridGeometrySplitter {
276
+ readonly align: "start" | "end";
277
+ readonly ariaOrientation: "horizontal" | "vertical";
278
+ readonly column: GridGeometrySpan;
279
+ readonly controls: string;
280
+ readonly id: string;
281
+ readonly orientation: GridGeometryResizeDirection;
282
+ readonly resizedChildItems: {
283
+ readonly after: string[];
284
+ readonly before: string[];
285
+ };
286
+ readonly resizedGridTracks: [number, number];
287
+ readonly row: GridGeometrySpan;
288
+ }
289
+ export interface GridSplitterGeometry {
290
+ readonly horizontalSplitterItemIds: readonly GridItemId[];
291
+ readonly splitters: readonly GridGeometrySplitter[];
292
+ readonly verticalSplitterItemIds: readonly GridItemId[];
293
+ }
294
+ /**
295
+ * Compute the splitters for a grid, together with the items that carry a
296
+ * horizontal or vertical splitter.
297
+ */
298
+ export declare const computeSplitters: (geometry: GridGeometry) => GridSplitterGeometry;
299
+ /**
300
+ * Resize requires a new track if the splitter being used for the resize sits
301
+ * on the same track edge as another splitter.
302
+ */
303
+ export declare const doesResizeRequireNewTrack: (splitters: readonly GridGeometrySplitter[], splitter: GridGeometrySplitter) => boolean;
304
+ export interface GridInsertTrackRequest {
305
+ readonly contraItemIds: readonly GridItemId[];
306
+ readonly index: number;
307
+ readonly position: GridGeometryTrackInsertPosition;
308
+ readonly resizeItemIds: readonly GridItemId[];
309
+ readonly size: number;
310
+ readonly trackType: GridGeometryTrackType;
311
+ }
312
+ export interface GridInsertTrackTransition {
313
+ readonly anchorUpdates: readonly GridGeometryUpdate[];
314
+ readonly columns?: GridTrackTransition;
315
+ readonly geometry: GridGeometry;
316
+ readonly insertUpdates: readonly GridGeometryUpdate[];
317
+ readonly rows?: GridTrackTransition;
318
+ }
319
+ /**
320
+ * Insert a new grid line so that an item sharing a track edge with other items
321
+ * can be resized independently, and anchor the resized/contra items to it.
322
+ */
323
+ export declare const insertTrackForResize: (geometry: GridGeometry, { contraItemIds, index, position, resizeItemIds, size, trackType, }: GridInsertTrackRequest, measurements?: GridMeasurements) => GridGeometryResult<GridInsertTrackTransition>;
324
+ export interface GridRemoveTrackRequest {
325
+ readonly assignDirection?: GridGeometryAssignDirection;
326
+ readonly trackIndex: number;
327
+ readonly trackType: GridGeometryTrackType;
328
+ readonly updateItems?: boolean;
329
+ }
330
+ /** Remove a grid track, rebinding items bound to lines beyond it. */
331
+ export declare const removeGridTrack: (geometry: GridGeometry, { assignDirection, trackIndex, trackType, updateItems, }: GridRemoveTrackRequest, measurements?: GridMeasurements) => GridGeometryResult<GridGeometryTransition>;
@@ -0,0 +1,20 @@
1
+ import { type HTMLAttributes, type ReactElement, type ReactNode } from "react";
2
+ import type { GridLayoutItemProps } from "./GridLayoutItem";
3
+ import type { GridColumnsAndRows, GridLayoutChangeHandler } from "./GridModel";
4
+ export type GridResizeable = "h" | "v" | "hv";
5
+ export type GridResizeDistribution = "adjacent" | "proportional";
6
+ export interface GridLayoutProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
7
+ children?: ReactElement<GridLayoutItemProps> | ReactElement<GridLayoutItemProps>[];
8
+ "full-page"?: boolean;
9
+ colsAndRows?: GridColumnsAndRows;
10
+ /** @deprecated Use GridLayoutProvider onDocumentChange. */
11
+ onChange?: GridLayoutChangeHandler;
12
+ /** Content rendered inside canonical placeholders without obscuring their drop target. */
13
+ placeholderContent?: ReactNode;
14
+ /** Coupled boundaries with partial cross-group spans retain adjacent resizing. */
15
+ rowResizeDistribution?: GridResizeDistribution;
16
+ }
17
+ export declare function GridLayout({ id: idProp, children: childrenProp, className, "full-page": fullPage, colsAndRows, onClick, onChange, placeholderContent, rowResizeDistribution, style: styleProp, ...htmlAttributes }: GridLayoutProps): import("react").JSX.Element;
18
+ export declare namespace GridLayout {
19
+ var displayName: string;
20
+ }
@@ -0,0 +1,141 @@
1
+ import { type Dispatch, type DragEvent } from "react";
2
+ import type { GridLayoutDragEndHandler } from "./GridLayoutProvider";
3
+ import type { GridModel, TabStateTab, TrackSize } from "./GridModel";
4
+ import type { GridLayoutDragStartHandler } from "./useDraggable";
5
+ import type { GridLayoutModel } from "./GridLayoutModel";
6
+ import type { GridLayoutDropPosition } from "@vuu-ui/vuu-utils";
7
+ import type { GridController } from "./GridController";
8
+ import type { GridSnapshot } from "./GridSnapshot";
9
+ import type { JsonValue } from "./json-value";
10
+ export type GridLayoutActionType = "close";
11
+ export type GridLayoutCloseAction = {
12
+ type: "close";
13
+ id: string;
14
+ };
15
+ export type GridLayoutRenameTabAction = {
16
+ type: "rename-tab";
17
+ id: string;
18
+ title: string;
19
+ };
20
+ export type GridLayoutAddTabbedChildAction = {
21
+ title: string;
22
+ type: "add-tabbed-child";
23
+ componentTemplate: ComponentTemplate;
24
+ stackId: string;
25
+ };
26
+ export type GridLayoutSwitchTabAction = {
27
+ type: "switch-tab";
28
+ fromId: string;
29
+ toId: string;
30
+ };
31
+ export type GridLayoutSelectTabAction = {
32
+ type: "select-tab";
33
+ itemId: string;
34
+ stackId: string;
35
+ };
36
+ export type GridLayoutTrackAction = {
37
+ type: "resize-grid-column" | "resize-grid-row";
38
+ trackIndex: number;
39
+ value: TrackSize;
40
+ };
41
+ export type GridLayoutAction = GridLayoutCloseAction | GridLayoutAddTabbedChildAction | GridLayoutSwitchTabAction | GridLayoutSelectTabAction | GridLayoutTrackAction | GridLayoutRenameTabAction;
42
+ export type GridLayoutDispatch = Dispatch<GridLayoutAction>;
43
+ /**
44
+ * provides details of a dragged component within a stack
45
+ */
46
+ export interface TabbedComponentDragSource {
47
+ element: HTMLElement;
48
+ isSelectedTab: boolean;
49
+ label: string;
50
+ layoutId: string;
51
+ tab: TabStateTab;
52
+ /** deprecated */
53
+ tabIndex: number;
54
+ tabsId: string;
55
+ type: "tabbed-component";
56
+ }
57
+ /**
58
+ * provides details of a dragged component
59
+ */
60
+ export interface ComponentDragSource {
61
+ element: HTMLElement;
62
+ dragElement?: HTMLElement;
63
+ id: string;
64
+ label: string;
65
+ layoutId: string;
66
+ type: "component";
67
+ }
68
+ export interface TypedComponentTemplate {
69
+ readonly component: {
70
+ readonly settings: JsonValue;
71
+ readonly type: string;
72
+ readonly version: number;
73
+ };
74
+ /**
75
+ * Can the component act as a drop target. Note: false does not
76
+ * preclude children of the component from acting as drop targets.
77
+ */
78
+ readonly dropTarget?: boolean;
79
+ /** Primarily intended for display in a palette. */
80
+ readonly label: string;
81
+ }
82
+ /** @deprecated Use TypedComponentTemplate. */
83
+ export interface LegacyComponentTemplate {
84
+ /**
85
+ * Stringified JSON - the serialized layoutJSON from which
86
+ * component can be reconstituted
87
+ */
88
+ componentJson: string;
89
+ /**
90
+ * Can the component act as a drop target. Note: false does not
91
+ * preclude children of the component from acting as drop targets.
92
+ */
93
+ dropTarget?: boolean;
94
+ /**
95
+ * Primarily intended for display in Palette etc.
96
+ */
97
+ label: string;
98
+ }
99
+ export type ComponentTemplate = TypedComponentTemplate | LegacyComponentTemplate;
100
+ export type ComponentTemplateWithoutLabel = Omit<TypedComponentTemplate, "label"> | Omit<LegacyComponentTemplate, "label">;
101
+ export declare const isTypedComponentTemplate: (template: ComponentTemplate) => template is TypedComponentTemplate;
102
+ /**
103
+ * provides details of a template, to be used on drop to instantiate a new component
104
+ */
105
+ export type TemplateSource = ComponentTemplate & {
106
+ element: HTMLElement;
107
+ layoutId: string;
108
+ type: "template";
109
+ };
110
+ export type DragSourceProvider = (evt: DragEvent<Element>) => DragSource;
111
+ export type DragSource = ComponentDragSource | TemplateSource | TabbedComponentDragSource;
112
+ export declare const sourceIsComponent: (source: DragSource | undefined) => source is ComponentDragSource;
113
+ export declare const sourceIsTabbedComponent: (source: DragSource | undefined) => source is TabbedComponentDragSource;
114
+ export declare const sourceIsTemplate: (source: DragSource | undefined) => source is TemplateSource;
115
+ export type GridLayoutDropHandler = (targetId: string, dragSource: DragSource, position: GridLayoutDropPosition) => boolean;
116
+ export type GridLayoutDragLeaveHandler = () => void;
117
+ export interface GridLayoutContextProps {
118
+ dispatchGridLayoutAction: GridLayoutDispatch;
119
+ gridController?: GridController;
120
+ gridLayoutModel?: GridLayoutModel;
121
+ gridModel?: GridModel;
122
+ gridSnapshot?: GridSnapshot;
123
+ id: string;
124
+ onDragEnd?: GridLayoutDragEndHandler;
125
+ onDragLeave: GridLayoutDragLeaveHandler;
126
+ onDragPreview: GridLayoutDropHandler;
127
+ onDragStart: GridLayoutDragStartHandler;
128
+ onDrop: GridLayoutDropHandler;
129
+ }
130
+ export declare const GridLayoutContext: import("react").Context<GridLayoutContextProps>;
131
+ export declare const useGridLayoutDispatch: () => GridLayoutDispatch;
132
+ export declare const useGridLayoutDropHandler: () => GridLayoutDropHandler;
133
+ export declare const useGridLayoutDragPreviewHandler: () => GridLayoutDropHandler;
134
+ export declare const useGridLayoutDragLeaveHandler: () => GridLayoutDragLeaveHandler;
135
+ export declare const useGridLayoutDragEndHandler: () => GridLayoutDragEndHandler | undefined;
136
+ export declare const useGridLayoutDragStartHandler: () => GridLayoutDragStartHandler;
137
+ /** @deprecated Mutable GridModel is an internal compatibility engine. */
138
+ export declare const useGridModel: () => GridModel;
139
+ export declare const useGridController: () => GridController;
140
+ export declare const useGridSnapshot: () => GridSnapshot;
141
+ export declare const useGridLayoutId: () => string;
@@ -0,0 +1,61 @@
1
+ import type { DecodedGridComponentSettings, EncodedGridComponentSettings, GridComponentSettingsError, GridComponentSettingsInput, GridComponentSettingsRegistry } from "./GridComponentSettings";
2
+ import type { GridItemSnapshot, GridSnapshot, GridStackSnapshot } from "./GridSnapshot";
3
+ export declare const GRID_LAYOUT_DOCUMENT_KIND = "grid-layout";
4
+ export declare const GRID_LAYOUT_DOCUMENT_VERSION = 2;
5
+ export interface PersistedGridLayout {
6
+ readonly columns: readonly string[];
7
+ readonly id: string;
8
+ readonly items: readonly GridItemSnapshot[];
9
+ readonly placeholderIds: readonly string[];
10
+ readonly rows: readonly string[];
11
+ readonly stacks: readonly GridStackSnapshot[];
12
+ }
13
+ export interface GridLayoutDocument {
14
+ readonly components: readonly EncodedGridComponentSettings[];
15
+ readonly kind: typeof GRID_LAYOUT_DOCUMENT_KIND;
16
+ readonly layout: PersistedGridLayout;
17
+ readonly version: typeof GRID_LAYOUT_DOCUMENT_VERSION;
18
+ }
19
+ export declare const immutableGridLayoutDocument: (document: GridLayoutDocument) => GridLayoutDocument;
20
+ export interface GridLayoutDocumentV1 {
21
+ readonly components: readonly EncodedGridComponentSettings[];
22
+ readonly kind: typeof GRID_LAYOUT_DOCUMENT_KIND;
23
+ readonly layout: {
24
+ readonly columns: readonly string[];
25
+ readonly gridId: string;
26
+ readonly items: readonly GridItemSnapshot[];
27
+ readonly rows: readonly string[];
28
+ readonly stacks?: readonly GridStackSnapshot[];
29
+ };
30
+ readonly version: 1;
31
+ }
32
+ export interface DecodedGridLayoutDocument {
33
+ readonly components: readonly DecodedGridComponentSettings[];
34
+ readonly document: GridLayoutDocument;
35
+ readonly snapshot: GridSnapshot;
36
+ }
37
+ export type GridLayoutDocumentErrorCode = "COMPONENT_SETTINGS_ERROR" | "COMPONENT_RENDERER_ERROR" | "DOCUMENT_MIGRATION_FAILED" | "DUPLICATE_COMPONENT_ID" | "INVALID_DISCRIMINATOR" | "INVALID_DOCUMENT" | "MISSING_COMPONENT_SETTINGS" | "UNEXPECTED_COMPONENT_SETTINGS" | "UNSUPPORTED_DOCUMENT_VERSION";
38
+ export interface GridLayoutDocumentError {
39
+ readonly code: GridLayoutDocumentErrorCode;
40
+ readonly componentError?: GridComponentSettingsError;
41
+ readonly message: string;
42
+ readonly path: string;
43
+ readonly version?: number;
44
+ }
45
+ export declare class GridLayoutDocumentCodecError extends Error {
46
+ readonly issue: GridLayoutDocumentError;
47
+ constructor(issue: GridLayoutDocumentError);
48
+ }
49
+ export type GridLayoutDocumentResult<T> = {
50
+ readonly ok: true;
51
+ readonly value: T;
52
+ } | {
53
+ readonly error: GridLayoutDocumentError;
54
+ readonly ok: false;
55
+ };
56
+ export interface EncodeGridLayoutDocumentOptions {
57
+ readonly componentSettings: readonly GridComponentSettingsInput[];
58
+ readonly placeholderIds?: readonly string[];
59
+ }
60
+ export declare const encodeGridLayoutDocument: (snapshot: GridSnapshot, registry: GridComponentSettingsRegistry, { componentSettings, placeholderIds }: EncodeGridLayoutDocumentOptions) => GridLayoutDocumentResult<GridLayoutDocument>;
61
+ export declare const decodeGridLayoutDocument: (input: unknown, registry: GridComponentSettingsRegistry) => GridLayoutDocumentResult<DecodedGridLayoutDocument>;
@@ -0,0 +1,15 @@
1
+ import { type GridLayoutDocument } from "./GridLayoutDocument";
2
+ export type GridLayoutIdKind = "component" | "grid" | "item" | "stack";
3
+ export interface GridLayoutIdRemapping {
4
+ readonly kind: GridLayoutIdKind;
5
+ readonly newId: string;
6
+ readonly oldId: string;
7
+ readonly path: string;
8
+ }
9
+ export type GridLayoutIdAllocator = (kind: GridLayoutIdKind, oldId: string, path: string) => string;
10
+ export interface RemappedGridLayoutDocument {
11
+ readonly document: GridLayoutDocument;
12
+ readonly mappings: readonly GridLayoutIdRemapping[];
13
+ }
14
+ export declare const createSequentialGridLayoutIdAllocator: (prefix?: string) => GridLayoutIdAllocator;
15
+ export declare const remapGridLayoutDocumentIds: (source: GridLayoutDocument, allocate: GridLayoutIdAllocator) => RemappedGridLayoutDocument;
@@ -0,0 +1,28 @@
1
+ import { type HTMLAttributes, type ReactElement } from "react";
2
+ import { type LayoutJSON } from "./componentToJson";
3
+ import { type GridChildItemStyle, type GridModelChildItemProps } from "./GridModel";
4
+ export interface GridLayoutItemProps extends Omit<GridModelChildItemProps, "contentDetached" | "style" | "type">, Omit<HTMLAttributes<HTMLDivElement>, "id" | "onDragStart" | "onDrop" | "style"> {
5
+ "data-drop-target"?: boolean | string;
6
+ header?: boolean;
7
+ /**
8
+ * If provided, component is fixed height
9
+ */
10
+ height?: number;
11
+ label?: string;
12
+ /**
13
+ * style.gridArea is optional only if stackId is provided and a separate declaration
14
+ * of a GridLayoutStackedItem child is included within GridLayout
15
+ */
16
+ style?: GridChildItemStyle;
17
+ /**
18
+ * If provided, component is fixed width
19
+ */
20
+ width?: number;
21
+ }
22
+ export declare function GridLayoutItem({ children, className: classNameProp, contentVisible: contentVisibleProp, "data-drop-target": dataDropTarget, header: headerProp, height, id, minHeight, minWidth, stackId, resizeable, style: styleProp, title: titleProp, width, ...htmlAttributes }: GridLayoutItemProps): import("react").JSX.Element | null;
23
+ export declare namespace GridLayoutItem {
24
+ var toJSON: (element: ReactElement<GridLayoutItemProps, typeof GridLayoutItemType>) => LayoutJSON<object>;
25
+ }
26
+ declare const GridLayoutItemType: import("react").FunctionComponent<GridLayoutItemProps>;
27
+ export declare const isGridLayoutItem: (element: ReactElement) => boolean;
28
+ export {};
@@ -0,0 +1,57 @@
1
+ import type { ReactElement } from "react";
2
+ import type { LayoutJSON } from "./componentToJson";
3
+ import { type GridLayoutItemProps } from "./GridLayoutItem";
4
+ import type { GridLayoutDescriptor } from "./GridModel";
5
+ import type { GridSnapshot } from "./GridSnapshot";
6
+ export type LegacySerializedComponentMap = Record<string, LayoutJSON>;
7
+ /**
8
+ * Pre-v2 GridLayout persistence envelope.
9
+ *
10
+ * @deprecated Read existing data with this type, then save a GridLayoutDocument.
11
+ */
12
+ export type SerializedGridLayout = {
13
+ components: LegacySerializedComponentMap;
14
+ id: string;
15
+ layout: GridLayoutDescriptor;
16
+ };
17
+ export type LegacyDeserializedGridLayout = {
18
+ components: Record<string, ReactElement<GridLayoutItemProps>>;
19
+ id: string;
20
+ layout: GridLayoutDescriptor;
21
+ placeholderIds?: readonly string[];
22
+ };
23
+ export interface LegacyGridLayoutDocument {
24
+ readonly components: LegacySerializedComponentMap;
25
+ readonly snapshot: GridSnapshot;
26
+ }
27
+ export type LegacyGridLayoutDecodeResult = {
28
+ readonly ok: true;
29
+ readonly value: LegacyGridLayoutDocument;
30
+ } | {
31
+ readonly error: {
32
+ readonly code: "INVALID_LEGACY_GRID_LAYOUT";
33
+ readonly message: string;
34
+ readonly path: string;
35
+ readonly version: 1;
36
+ };
37
+ readonly ok: false;
38
+ };
39
+ /**
40
+ * Validates and adapts the descriptor portion of a pre-v2 persistence value.
41
+ * It deliberately does not produce a writable v2 document because legacy
42
+ * component props are not typed component settings.
43
+ *
44
+ * @deprecated Use decodeGridLayoutDocument for all new persistence.
45
+ */
46
+ export declare const decodeLegacySerializedGridLayout: (value: SerializedGridLayout) => LegacyGridLayoutDecodeResult;
47
+ export interface LegacyGridLayoutReader {
48
+ getSavedGrid(id: string): LegacyDeserializedGridLayout | undefined;
49
+ }
50
+ /**
51
+ * Creates the narrow, read-only React compatibility boundary used by the
52
+ * deprecated provider input. No mutations are written back to the legacy
53
+ * descriptor or generic React-prop component map.
54
+ */
55
+ export declare const createLegacyGridLayoutReader: (serializedLayout: SerializedGridLayout) => LegacyGridLayoutReader;
56
+ /** @deprecated Legacy component JSON may contain React-derived props. */
57
+ export type LegacyGridLayoutComponentJson = LayoutJSON;