@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,435 @@
1
+ import { GridSnapshotValidationError } from "./GridSnapshot.js";
2
+ import { normalizeGridStackState } from "./GridStack.js";
3
+ const TRACK_PATTERN = /^(?:\d+(?:\.\d+)?|\.\d+)(?:fr|px)$/;
4
+ const isRecord = (value)=>"object" == typeof value && null !== value;
5
+ const validateKnownFields = (value, fields, path, issues)=>{
6
+ const knownFields = new Set(fields);
7
+ for (const field of Object.keys(value))if (!knownFields.has(field)) issues.push({
8
+ code: "UNEXPECTED_FIELD",
9
+ message: `unexpected field "${field}"`,
10
+ path: "$" === path ? field : `${path}.${field}`
11
+ });
12
+ };
13
+ const cloneTrack = ({ size })=>({
14
+ size
15
+ });
16
+ const cloneSpan = ({ span, start })=>({
17
+ span,
18
+ start
19
+ });
20
+ const cloneItem = ({ column, componentInstanceId, contentVisible, dropTarget, header, id, minHeight, minWidth, resizeable, row, title })=>({
21
+ column: cloneSpan(column),
22
+ componentInstanceId,
23
+ contentVisible,
24
+ dropTarget,
25
+ header,
26
+ id,
27
+ minHeight,
28
+ minWidth,
29
+ resizeable,
30
+ row: cloneSpan(row),
31
+ title
32
+ });
33
+ const cloneStack = ({ id, itemIds, selectedItemId })=>({
34
+ id,
35
+ itemIds: [
36
+ ...itemIds
37
+ ],
38
+ selectedItemId
39
+ });
40
+ const validateSpan = (span, trackCount, path, issues)=>{
41
+ if (!isRecord(span)) return void issues.push({
42
+ code: "INVALID_STRUCTURE",
43
+ message: "span must be an object",
44
+ path
45
+ });
46
+ validateKnownFields(span, [
47
+ "span",
48
+ "start"
49
+ ], path, issues);
50
+ const { span: length, start } = span;
51
+ if (!Number.isInteger(start) || !Number.isInteger(length) || "number" != typeof length || length <= 0) return void issues.push({
52
+ code: "INVALID_SPAN",
53
+ message: "start and span must be integers and span must be positive",
54
+ path
55
+ });
56
+ if ("number" == typeof start && (start <= 0 || start + length - 1 > trackCount)) issues.push({
57
+ code: "INVALID_TRACK_REFERENCE",
58
+ message: `range ${start}/${length} exceeds ${trackCount} tracks`,
59
+ path
60
+ });
61
+ };
62
+ const validateGridSnapshot = (value)=>{
63
+ const issues = [];
64
+ if (!isRecord(value)) return [
65
+ {
66
+ code: "INVALID_STRUCTURE",
67
+ message: "snapshot must be an object",
68
+ path: "$"
69
+ }
70
+ ];
71
+ const { columns, gridId, items, revision, rows, stacks } = value;
72
+ validateKnownFields(value, [
73
+ "columns",
74
+ "gridId",
75
+ "items",
76
+ "revision",
77
+ "rows",
78
+ "stacks"
79
+ ], "$", issues);
80
+ if ("string" != typeof gridId || !gridId) issues.push({
81
+ code: "EMPTY_ID",
82
+ message: "grid id must not be empty",
83
+ path: "gridId"
84
+ });
85
+ if ("number" != typeof revision || !Number.isInteger(revision) || revision < 0) issues.push({
86
+ code: "INVALID_REVISION",
87
+ message: "revision must be a non-negative integer",
88
+ path: "revision"
89
+ });
90
+ const validateTracks = (tracks, path)=>{
91
+ if (!Array.isArray(tracks)) {
92
+ issues.push({
93
+ code: "INVALID_STRUCTURE",
94
+ message: "tracks must be an array",
95
+ path
96
+ });
97
+ return [];
98
+ }
99
+ tracks.forEach((track, index)=>{
100
+ const size = isRecord(track) ? track.size : void 0;
101
+ if (isRecord(track)) validateKnownFields(track, [
102
+ "size"
103
+ ], `${path}[${index}]`, issues);
104
+ if ("string" != typeof size || !TRACK_PATTERN.test(size)) issues.push({
105
+ code: "MALFORMED_TRACK",
106
+ message: `unsupported track size "${String(size)}"`,
107
+ path: `${path}[${index}].size`
108
+ });
109
+ });
110
+ return tracks;
111
+ };
112
+ const validatedColumns = validateTracks(columns, "columns");
113
+ const validatedRows = validateTracks(rows, "rows");
114
+ const ids = new Map();
115
+ const addId = (id, path)=>{
116
+ if ("string" != typeof id || !id) return void issues.push({
117
+ code: "EMPTY_ID",
118
+ message: "id must not be empty",
119
+ path
120
+ });
121
+ const firstPath = ids.get(id);
122
+ if (firstPath) issues.push({
123
+ code: "DUPLICATE_ID",
124
+ message: `id "${id}" is already used at ${firstPath}`,
125
+ path
126
+ });
127
+ else ids.set(id, path);
128
+ };
129
+ const itemIds = new Set();
130
+ const itemById = new Map();
131
+ const validatedItems = Array.isArray(items) ? items : [];
132
+ if (!Array.isArray(items)) issues.push({
133
+ code: "INVALID_STRUCTURE",
134
+ message: "items must be an array",
135
+ path: "items"
136
+ });
137
+ validatedItems.forEach((item, index)=>{
138
+ const path = `items[${index}]`;
139
+ if (!isRecord(item)) return void issues.push({
140
+ code: "INVALID_STRUCTURE",
141
+ message: "item must be an object",
142
+ path
143
+ });
144
+ validateKnownFields(item, [
145
+ "column",
146
+ "componentInstanceId",
147
+ "contentVisible",
148
+ "dropTarget",
149
+ "header",
150
+ "id",
151
+ "minHeight",
152
+ "minWidth",
153
+ "resizeable",
154
+ "row",
155
+ "title"
156
+ ], path, issues);
157
+ addId(item.id, `${path}.id`);
158
+ if ("string" == typeof item.id) {
159
+ itemIds.add(item.id);
160
+ itemById.set(item.id, item);
161
+ }
162
+ validateSpan(item.column, validatedColumns.length, `${path}.column`, issues);
163
+ validateSpan(item.row, validatedRows.length, `${path}.row`, issues);
164
+ const optionalFields = [
165
+ [
166
+ "componentInstanceId",
167
+ (field)=>"string" == typeof field
168
+ ],
169
+ [
170
+ "contentVisible",
171
+ (field)=>"boolean" == typeof field
172
+ ],
173
+ [
174
+ "dropTarget",
175
+ (field)=>"boolean" == typeof field || "string" == typeof field
176
+ ],
177
+ [
178
+ "header",
179
+ (field)=>"boolean" == typeof field
180
+ ],
181
+ [
182
+ "minHeight",
183
+ (field)=>"number" == typeof field && Number.isFinite(field) && field >= 0
184
+ ],
185
+ [
186
+ "minWidth",
187
+ (field)=>"number" == typeof field && Number.isFinite(field) && field >= 0
188
+ ],
189
+ [
190
+ "resizeable",
191
+ (field)=>false === field || "h" === field || "v" === field || "hv" === field
192
+ ],
193
+ [
194
+ "title",
195
+ (field)=>"string" == typeof field
196
+ ]
197
+ ];
198
+ for (const [fieldName, isValid] of optionalFields){
199
+ const field = item[fieldName];
200
+ if (void 0 !== field && !isValid(field)) issues.push({
201
+ code: "INVALID_FIELD",
202
+ message: `invalid ${fieldName}`,
203
+ path: `${path}.${fieldName}`
204
+ });
205
+ }
206
+ });
207
+ const stackedItemIds = new Set();
208
+ const validatedStacks = Array.isArray(stacks) ? stacks : [];
209
+ if (!Array.isArray(stacks)) issues.push({
210
+ code: "INVALID_STRUCTURE",
211
+ message: "stacks must be an array",
212
+ path: "stacks"
213
+ });
214
+ validatedStacks.forEach((stack, stackIndex)=>{
215
+ const path = `stacks[${stackIndex}]`;
216
+ if (!isRecord(stack)) return void issues.push({
217
+ code: "INVALID_STRUCTURE",
218
+ message: "stack must be an object",
219
+ path
220
+ });
221
+ validateKnownFields(stack, [
222
+ "id",
223
+ "itemIds",
224
+ "selectedItemId"
225
+ ], path, issues);
226
+ addId(stack.id, `${path}.id`);
227
+ if (!Array.isArray(stack.itemIds)) return void issues.push({
228
+ code: "INVALID_STRUCTURE",
229
+ message: "stack item ids must be an array",
230
+ path: `${path}.itemIds`
231
+ });
232
+ if (stack.itemIds.length < 2) issues.push({
233
+ code: "INVALID_STACK_MEMBERSHIP",
234
+ message: "a stack must contain at least two items",
235
+ path: `${path}.itemIds`
236
+ });
237
+ const members = new Set();
238
+ stack.itemIds.forEach((itemId, itemIndex)=>{
239
+ const itemPath = `${path}.itemIds[${itemIndex}]`;
240
+ if ("string" != typeof itemId) issues.push({
241
+ code: "INVALID_STACK_MEMBERSHIP",
242
+ message: "stack item id must be a string",
243
+ path: itemPath
244
+ });
245
+ else if (!itemIds.has(itemId) || members.has(itemId) || stackedItemIds.has(itemId)) issues.push({
246
+ code: "INVALID_STACK_MEMBERSHIP",
247
+ message: `item "${itemId}" is missing, duplicated, or belongs to another stack`,
248
+ path: itemPath
249
+ });
250
+ if ("string" == typeof itemId) {
251
+ members.add(itemId);
252
+ stackedItemIds.add(itemId);
253
+ }
254
+ });
255
+ if ("string" != typeof stack.selectedItemId || !members.has(stack.selectedItemId)) issues.push({
256
+ code: "INVALID_STACK_SELECTION",
257
+ message: `selected item "${String(stack.selectedItemId)}" is not a stack member`,
258
+ path: `${path}.selectedItemId`
259
+ });
260
+ const [firstItemId, ...otherItemIds] = members;
261
+ const firstItem = itemById.get(firstItemId);
262
+ const hasSameSpan = (left, right)=>isRecord(left) && isRecord(right) && left.start === right.start && left.span === right.span;
263
+ if (firstItem && otherItemIds.some((itemId)=>{
264
+ const item = itemById.get(itemId);
265
+ return !item || !hasSameSpan(firstItem.column, item.column) || !hasSameSpan(firstItem.row, item.row);
266
+ })) issues.push({
267
+ code: "INVALID_STACK_POSITION",
268
+ message: "all stack members must occupy the same grid area",
269
+ path: `${path}.itemIds`
270
+ });
271
+ });
272
+ return issues;
273
+ };
274
+ const assertValidSnapshot = (snapshot)=>{
275
+ const issues = validateGridSnapshot(snapshot);
276
+ if (issues.length > 0) throw new GridSnapshotValidationError(issues);
277
+ };
278
+ const normalizeGridSnapshot = (snapshot)=>{
279
+ assertValidSnapshot(snapshot);
280
+ return {
281
+ columns: snapshot.columns.map(cloneTrack),
282
+ gridId: snapshot.gridId,
283
+ items: snapshot.items.map(cloneItem),
284
+ revision: snapshot.revision,
285
+ rows: snapshot.rows.map(cloneTrack),
286
+ stacks: snapshot.stacks.map(cloneStack)
287
+ };
288
+ };
289
+ const parseGridArea = (gridArea, path, issues)=>{
290
+ const lines = gridArea.split("/").map((value)=>Number(value));
291
+ if (4 !== lines.length || lines.some((value)=>!Number.isInteger(value))) {
292
+ issues.push({
293
+ code: "MALFORMED_GRID_AREA",
294
+ message: `grid area "${gridArea}" must contain four integer grid lines`,
295
+ path
296
+ });
297
+ return {
298
+ column: {
299
+ span: 0 / 0,
300
+ start: 0 / 0
301
+ },
302
+ row: {
303
+ span: 0 / 0,
304
+ start: 0 / 0
305
+ }
306
+ };
307
+ }
308
+ const [rowStart, columnStart, rowEnd, columnEnd] = lines;
309
+ return {
310
+ column: {
311
+ span: columnEnd - columnStart,
312
+ start: columnStart
313
+ },
314
+ row: {
315
+ span: rowEnd - rowStart,
316
+ start: rowStart
317
+ }
318
+ };
319
+ };
320
+ const gridLayoutDescriptorToSnapshot = (descriptor, { gridId, revision = 0 })=>{
321
+ const issues = [];
322
+ const stackMembers = new Map();
323
+ const items = Object.entries(descriptor.gridLayoutItems ?? {}).map(([id, item])=>{
324
+ const { componentId, gridArea, stackId, ...metadata } = item;
325
+ const snapshotItem = {
326
+ ...metadata,
327
+ componentInstanceId: componentId,
328
+ id,
329
+ ...parseGridArea(gridArea, `gridLayoutItems.${id}.gridArea`, issues)
330
+ };
331
+ if (stackId) {
332
+ const members = stackMembers.get(stackId) ?? [];
333
+ members.push(snapshotItem);
334
+ stackMembers.set(stackId, members);
335
+ }
336
+ return snapshotItem;
337
+ });
338
+ const stacks = [
339
+ ...stackMembers
340
+ ].map(([id, members])=>({
341
+ id,
342
+ itemIds: members.map(({ id: itemId })=>itemId),
343
+ selectedItemId: members.find(({ contentVisible })=>contentVisible)?.id ?? members[0]?.id ?? ""
344
+ }));
345
+ const stackedItemIds = new Set(stacks.flatMap(({ itemIds })=>itemIds));
346
+ const snapshot = {
347
+ columns: descriptor.cols.map((size)=>({
348
+ size
349
+ })),
350
+ gridId,
351
+ items: items.map((item)=>{
352
+ if (stackedItemIds.has(item.id)) {
353
+ const { contentVisible: _contentVisible, ...stackedItem } = item;
354
+ return stackedItem;
355
+ }
356
+ return item;
357
+ }),
358
+ revision,
359
+ rows: descriptor.rows.map((size)=>({
360
+ size
361
+ })),
362
+ stacks
363
+ };
364
+ issues.push(...validateGridSnapshot(snapshot));
365
+ if (issues.length > 0) throw new GridSnapshotValidationError(issues);
366
+ return normalizeGridSnapshot(snapshot);
367
+ };
368
+ const toDescriptorItem = (item, stack)=>({
369
+ ...void 0 === item.componentInstanceId ? {} : {
370
+ componentId: item.componentInstanceId
371
+ },
372
+ contentVisible: stack ? stack.selectedItemId === item.id : item.contentVisible,
373
+ dropTarget: item.dropTarget,
374
+ gridArea: `${item.row.start}/${item.column.start}/${item.row.start + item.row.span}/${item.column.start + item.column.span}`,
375
+ header: item.header,
376
+ minHeight: item.minHeight,
377
+ minWidth: item.minWidth,
378
+ resizeable: item.resizeable,
379
+ stackId: stack?.id,
380
+ title: item.title
381
+ });
382
+ const gridSnapshotToGridLayoutDescriptor = (snapshot)=>{
383
+ const normalized = normalizeGridSnapshot(snapshot);
384
+ const stackByItemId = new Map(normalized.stacks.flatMap((stack)=>stack.itemIds.map((itemId)=>[
385
+ itemId,
386
+ stack
387
+ ])));
388
+ return {
389
+ cols: normalized.columns.map(({ size })=>size),
390
+ gridLayoutItems: Object.fromEntries(normalized.items.map((item)=>[
391
+ item.id,
392
+ toDescriptorItem(item, stackByItemId.get(item.id))
393
+ ])),
394
+ rows: normalized.rows.map(({ size })=>size)
395
+ };
396
+ };
397
+ const gridSnapshotToGridStackStates = (snapshot)=>{
398
+ const normalized = normalizeGridSnapshot(snapshot);
399
+ const itemById = new Map(normalized.items.map((item)=>[
400
+ item.id,
401
+ item
402
+ ]));
403
+ return normalized.stacks.map((stack)=>{
404
+ const [firstItemId] = stack.itemIds;
405
+ const firstItem = itemById.get(firstItemId);
406
+ return normalizeGridStackState({
407
+ area: {
408
+ column: firstItem?.column ?? {
409
+ span: 1,
410
+ start: 1
411
+ },
412
+ row: firstItem?.row ?? {
413
+ span: 1,
414
+ start: 1
415
+ }
416
+ },
417
+ id: stack.id,
418
+ members: stack.itemIds.map((itemId)=>{
419
+ const item = itemById.get(itemId);
420
+ return {
421
+ id: itemId,
422
+ label: item?.title ?? itemId,
423
+ title: item?.title
424
+ };
425
+ }),
426
+ metadata: {
427
+ minHeight: firstItem?.minHeight,
428
+ minWidth: firstItem?.minWidth,
429
+ resizeable: firstItem?.resizeable
430
+ },
431
+ selectedItemId: stack.selectedItemId
432
+ });
433
+ });
434
+ };
435
+ export { gridLayoutDescriptorToSnapshot, gridSnapshotToGridLayoutDescriptor, gridSnapshotToGridStackStates, normalizeGridSnapshot, validateGridSnapshot };
package/src/index.js ADDED
@@ -0,0 +1,24 @@
1
+ import * as __rspack_external__GridLayoutLegacyCompatibility_js_8810c272 from "./GridLayoutLegacyCompatibility.js";
2
+ var createLegacyGridLayoutReader = __rspack_external__GridLayoutLegacyCompatibility_js_8810c272.createLegacyGridLayoutReader;
3
+ var decodeLegacySerializedGridLayout = __rspack_external__GridLayoutLegacyCompatibility_js_8810c272.decodeLegacySerializedGridLayout;
4
+ export { DragDropProviderNext, useOptionalDragContext } from "./drag-drop-next/DragDropProviderNext.js";
5
+ export { GridLayout } from "./GridLayout.js";
6
+ export { GridDragCoordinator, createGridDropPlan } from "./GridDragCoordinator.js";
7
+ export { GridController } from "./GridController.js";
8
+ export { GridCommandExecutionError, throwForGridCommandFailure } from "./GridCommand.js";
9
+ export { useGridController, useGridLayoutDispatch, useGridLayoutDragStartHandler, useGridModel, useGridSnapshot } from "./GridLayoutContext.js";
10
+ export { useGridControllerSnapshot } from "./useGridControllerSnapshot.js";
11
+ export { GridLayoutItem } from "./GridLayoutItem.js";
12
+ export { GridLayoutDocumentController, GridLayoutProvider } from "./GridLayoutProvider.js";
13
+ export { createSequentialGridLayoutIdAllocator, remapGridLayoutDocumentIds } from "./GridLayoutDocumentIds.js";
14
+ export { GridComponentRendererRegistry, GridComponentSettingsRegistry, GridLayoutContentRegistry } from "./GridComponentSettings.js";
15
+ export { GRID_LAYOUT_DOCUMENT_KIND, GRID_LAYOUT_DOCUMENT_VERSION, GridLayoutDocumentCodecError, decodeGridLayoutDocument, encodeGridLayoutDocument, immutableGridLayoutDocument } from "./GridLayoutDocument.js";
16
+ export { toJsonValue } from "./json-value.js";
17
+ export { GridLayoutStackedItem } from "./GridLayoutStackedtem.js";
18
+ export { gridLayoutDescriptorToSnapshot, gridSnapshotToGridLayoutDescriptor, gridSnapshotToGridStackStates, normalizeGridSnapshot, validateGridSnapshot } from "./grid-snapshot-adapters.js";
19
+ export { GridSnapshotValidationError } from "./GridSnapshot.js";
20
+ export { MIN_GRID_STACK_MEMBERS, addGridStackItem, assertValidGridStackState, cloneGridStackState, createGridStack, findGridStackMember, gridStackItemIds, gridStackMemberIndex, gridStackSelectedIndex, isSameGridStackState, normalizeGridStackState, removeGridStackItem, renameGridStackItem, reorderGridStackItem, selectGridStackItem, toGridStackSnapshot, validateGridStackState } from "./GridStack.js";
21
+ export { layoutFromJson } from "./layoutFromJson.js";
22
+ export { useDraggable } from "./useDraggable.js";
23
+ export { GridPlaceholder } from "./GridPlaceholder.js";
24
+ export { __rspack_external__GridLayoutLegacyCompatibility_js_8810c272 as GridLayoutLegacyCompatibility, createLegacyGridLayoutReader, decodeLegacySerializedGridLayout };
@@ -0,0 +1,56 @@
1
+ const error = (code, message, path)=>({
2
+ error: {
3
+ code,
4
+ message,
5
+ path
6
+ },
7
+ ok: false
8
+ });
9
+ const toJsonValue = (value, path = "$")=>{
10
+ const ancestors = new Set();
11
+ const visit = (candidate, candidatePath)=>{
12
+ if (null === candidate || "string" == typeof candidate || "boolean" == typeof candidate) return {
13
+ ok: true,
14
+ value: candidate
15
+ };
16
+ if ("number" == typeof candidate) return Number.isFinite(candidate) ? {
17
+ ok: true,
18
+ value: candidate
19
+ } : error("INVALID_NUMBER", "numbers must be finite", candidatePath);
20
+ if ("object" != typeof candidate) return error("UNSUPPORTED_VALUE", `${typeof candidate} values are not valid JSON`, candidatePath);
21
+ if (ancestors.has(candidate)) return error("CYCLE", "cyclic values are not valid JSON", candidatePath);
22
+ const prototype = Object.getPrototypeOf(candidate);
23
+ if (!Array.isArray(candidate) && prototype !== Object.prototype && null !== prototype) return error("NON_PLAIN_OBJECT", "only arrays and plain objects are valid JSON", candidatePath);
24
+ if (Object.getOwnPropertySymbols(candidate).length > 0) return error("UNSUPPORTED_VALUE", "symbol-keyed properties are not valid JSON", candidatePath);
25
+ ancestors.add(candidate);
26
+ if (Array.isArray(candidate)) {
27
+ const propertyNames = Object.getOwnPropertyNames(candidate);
28
+ const unexpectedProperty = propertyNames.find((key)=>"length" !== key && (!/^(?:0|[1-9]\d*)$/.test(key) || Number(key) >= candidate.length));
29
+ if (unexpectedProperty) return error("UNSUPPORTED_VALUE", `array property "${unexpectedProperty}" is not valid JSON`, `${candidatePath}.${unexpectedProperty}`);
30
+ const result = [];
31
+ for(let index = 0; index < candidate.length; index += 1){
32
+ const item = visit(candidate[index], `${candidatePath}[${index}]`);
33
+ if (!item.ok) return item;
34
+ result.push(item.value);
35
+ }
36
+ ancestors.delete(candidate);
37
+ return {
38
+ ok: true,
39
+ value: result
40
+ };
41
+ }
42
+ const result = {};
43
+ for (const key of Object.getOwnPropertyNames(candidate).sort()){
44
+ const item = visit(candidate[key], "$" === candidatePath ? `$.${key}` : `${candidatePath}.${key}`);
45
+ if (!item.ok) return item;
46
+ result[key] = item.value;
47
+ }
48
+ ancestors.delete(candidate);
49
+ return {
50
+ ok: true,
51
+ value: result
52
+ };
53
+ };
54
+ return visit(value, path);
55
+ };
56
+ export { toJsonValue };
@@ -0,0 +1,15 @@
1
+ import { getLayoutComponent, uuid } from "@vuu-ui/vuu-utils";
2
+ import react from "react";
3
+ const childFromJson = (child)=>"object" == typeof child ? layoutFromJson(child) : child;
4
+ function layoutFromJson({ active, id = uuid(), type, children, props }) {
5
+ const componentType = type.match(/^[a-z]/) ? type : getLayoutComponent(type);
6
+ if (void 0 === componentType) throw Error(`layoutUtils unable to create component from JSON, unknown type ${type}`);
7
+ const componentProps = {
8
+ active,
9
+ id,
10
+ ...props,
11
+ key: id
12
+ };
13
+ return children?.length ? react.createElement(componentType, componentProps, children.map(childFromJson)) : react.createElement(componentType, componentProps);
14
+ }
15
+ export { layoutFromJson };
@@ -0,0 +1,5 @@
1
+ import { componentToJson } from "./componentToJson.js";
2
+ function layoutToJSON(component) {
3
+ return componentToJson(component);
4
+ }
5
+ export { layoutToJSON };
@@ -0,0 +1,15 @@
1
+ const NO_PROPS = {};
2
+ const getProp = (component, propName)=>{
3
+ const props = getProps(component);
4
+ return props[propName] ?? props[`data-${propName}`];
5
+ };
6
+ const getProps = (component)=>component?.props || component || NO_PROPS;
7
+ const getChildProp = (container)=>{
8
+ const props = getProps(container);
9
+ if (props.children) {
10
+ const { children: [target, ...rest] } = props;
11
+ if (rest.length > 0) console.warn(`getChild expected a single child, found ${rest.length + 1}`);
12
+ return target;
13
+ }
14
+ };
15
+ export { getChildProp, getProp, getProps };
@@ -0,0 +1,15 @@
1
+ import react from "react";
2
+ const getGridItemChild = (gridItems, gridItemId)=>{
3
+ const targetGridItem = gridItems.find((gridItem)=>gridItem.props?.id === gridItemId);
4
+ if (targetGridItem) return targetGridItem;
5
+ throw Error(`getGridItemChild #${gridItemId} not found`);
6
+ };
7
+ const addChildToStackedGridItem = (stackElement, childElement)=>{
8
+ const stackProps = stackElement.props;
9
+ if (Array.isArray(stackProps.children)) console.log("children is an array");
10
+ const stackChildren = stackProps.children;
11
+ return react.cloneElement(stackElement, {
12
+ active: stackChildren.length
13
+ }, stackChildren.concat(childElement));
14
+ };
15
+ export { addChildToStackedGridItem, getGridItemChild };
package/src/typeOf.js ADDED
@@ -0,0 +1,15 @@
1
+ function typeOf(element) {
2
+ if (element) {
3
+ const type = element.type;
4
+ if ("function" == typeof type || "object" == typeof type) {
5
+ const elementName = type.displayName || type.name || type.type?.name;
6
+ if ("string" == typeof elementName) return elementName;
7
+ }
8
+ if ("string" == typeof element.type) return element.type;
9
+ if (element.constructor) return element.constructor.displayName;
10
+ throw Error("typeOf unable to determine type of element");
11
+ }
12
+ }
13
+ const isTypeOf = (element, type)=>typeOf(element) === type;
14
+ const isLayoutJSON = (layout)=>void 0 !== layout && "type" in layout;
15
+ export { isLayoutJSON, isTypeOf, typeOf };