@nocobase/flow-engine 2.1.0-beta.23 → 2.1.0-beta.25

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.
@@ -44,7 +44,12 @@ __export(gridDragPlanner_exports, {
44
44
  MAX_SLOT_THICKNESS: () => MAX_SLOT_THICKNESS,
45
45
  MIN_SLOT_THICKNESS: () => MIN_SLOT_THICKNESS,
46
46
  buildLayoutSnapshot: () => buildLayoutSnapshot,
47
+ findModelUidLayoutPosition: () => findModelUidLayoutPosition,
47
48
  getSlotKey: () => getSlotKey,
49
+ isSameGridLayout: () => isSameGridLayout,
50
+ normalizeGridLayout: () => normalizeGridLayout,
51
+ projectLayoutToLegacyRows: () => projectLayoutToLegacyRows,
52
+ replaceUidInGridLayout: () => replaceUidInGridLayout,
48
53
  resolveDropIntent: () => resolveDropIntent,
49
54
  simulateLayoutForSlot: () => simulateLayoutForSlot
50
55
  });
@@ -165,12 +170,46 @@ const createColumnInsertRect = /* @__PURE__ */ __name((itemRect, position) => {
165
170
  height: thickness
166
171
  });
167
172
  }, "createColumnInsertRect");
173
+ const parseLayoutPath = /* @__PURE__ */ __name((value) => {
174
+ if (!value) {
175
+ return void 0;
176
+ }
177
+ try {
178
+ const parsed = JSON.parse(value);
179
+ if (!Array.isArray(parsed)) {
180
+ return void 0;
181
+ }
182
+ const path = parsed.map((entry) => {
183
+ if (!entry || typeof entry !== "object" || typeof entry.rowId !== "string") {
184
+ return null;
185
+ }
186
+ return {
187
+ rowId: entry.rowId,
188
+ ...typeof entry.cellId === "string" ? { cellId: entry.cellId } : {}
189
+ };
190
+ }).filter(Boolean);
191
+ return path.length ? path : void 0;
192
+ } catch (error) {
193
+ return void 0;
194
+ }
195
+ }, "parseLayoutPath");
196
+ const createLegacyCellPath = /* @__PURE__ */ __name((rowId, columnIndex) => [
197
+ {
198
+ rowId,
199
+ cellId: `${rowId}:cell:${columnIndex}`
200
+ }
201
+ ], "createLegacyCellPath");
168
202
  const expandColumnRect = /* @__PURE__ */ __name((columnRect) => ({
169
203
  top: columnRect.top,
170
204
  left: columnRect.left,
171
205
  width: columnRect.width,
172
206
  height: Math.max(columnRect.height, MIN_SLOT_THICKNESS)
173
207
  }), "expandColumnRect");
208
+ const hasDirectNestedRows = /* @__PURE__ */ __name((columnElement) => {
209
+ return Array.from(columnElement.querySelectorAll("[data-grid-row-id]")).some((rowElement) => {
210
+ return rowElement.closest("[data-grid-column-row-id][data-grid-column-index]") === columnElement;
211
+ });
212
+ }, "hasDirectNestedRows");
174
213
  const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
175
214
  if (!container) {
176
215
  return {
@@ -178,13 +217,19 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
178
217
  containerRect: { top: 0, left: 0, width: 0, height: 0 }
179
218
  };
180
219
  }
181
- const containerRect = toRect(container.getBoundingClientRect());
220
+ const scope = container.hasAttribute("data-grid-root") ? container : container.querySelector("[data-grid-root]");
221
+ const layoutContainer = scope || container;
222
+ const containerRect = toRect(layoutContainer.getBoundingClientRect());
182
223
  const slots = [];
183
- const allRowElements = Array.from(container.querySelectorAll("[data-grid-row-id]"));
224
+ const allRowElements = Array.from(layoutContainer.querySelectorAll("[data-grid-row-id]"));
225
+ const hasGridRootScope = layoutContainer.hasAttribute("data-grid-root");
184
226
  const rowElements = allRowElements.filter((el) => {
185
227
  const htmlEl = el;
228
+ if (hasGridRootScope) {
229
+ return htmlEl.closest("[data-grid-root]") === layoutContainer;
230
+ }
186
231
  let parent = htmlEl.parentElement;
187
- while (parent && parent !== container) {
232
+ while (parent && parent !== layoutContainer) {
188
233
  if (parent.hasAttribute("data-grid-row-id")) {
189
234
  return false;
190
235
  }
@@ -204,22 +249,39 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
204
249
  });
205
250
  return { slots, containerRect };
206
251
  }
207
- rowElements.forEach((rowElement, rowIndex) => {
252
+ const getRowScopeElement = /* @__PURE__ */ __name((rowElement) => {
253
+ const parent = rowElement.parentElement;
254
+ if (!parent || !layoutContainer.contains(parent)) {
255
+ return layoutContainer;
256
+ }
257
+ return parent;
258
+ }, "getRowScopeElement");
259
+ const rowElementsByScope = /* @__PURE__ */ new Map();
260
+ rowElements.forEach((rowElement) => {
261
+ const rowScopeElement = getRowScopeElement(rowElement);
262
+ rowElementsByScope.set(rowScopeElement, [...rowElementsByScope.get(rowScopeElement) || [], rowElement]);
263
+ });
264
+ rowElements.forEach((rowElement) => {
208
265
  const rowId = rowElement.dataset.gridRowId;
209
266
  if (!rowId) {
210
267
  return;
211
268
  }
212
269
  const rowRect = toRect(rowElement.getBoundingClientRect());
213
- if (rowIndex === 0) {
270
+ const rowPath = parseLayoutPath(rowElement.dataset.gridPath) || [{ rowId }];
271
+ const rowScopeElement = getRowScopeElement(rowElement);
272
+ const rowScopeRect = toRect(rowScopeElement.getBoundingClientRect());
273
+ const rowElementsInScope = rowElementsByScope.get(rowScopeElement) || [];
274
+ if (rowElementsInScope[0] === rowElement) {
214
275
  slots.push({
215
276
  type: "row-gap",
216
277
  targetRowId: rowId,
217
278
  position: "above",
218
- rect: createRowGapRect(rowRect, "above", containerRect)
279
+ rect: createRowGapRect(rowRect, "above", rowScopeRect),
280
+ path: rowPath
219
281
  });
220
282
  }
221
283
  const columnElements = Array.from(
222
- container.querySelectorAll(`[data-grid-column-row-id="${rowId}"][data-grid-column-index]`)
284
+ layoutContainer.querySelectorAll(`[data-grid-column-row-id="${rowId}"][data-grid-column-index]`)
223
285
  ).filter((el) => {
224
286
  return el.closest("[data-grid-row-id]") === rowElement;
225
287
  });
@@ -231,19 +293,22 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
231
293
  sortedColumns.forEach((columnElement) => {
232
294
  const columnIndex = Number(columnElement.dataset.gridColumnIndex || 0);
233
295
  const columnRect = toRect(columnElement.getBoundingClientRect());
296
+ const columnPath = parseLayoutPath(columnElement.dataset.gridPath) || createLegacyCellPath(rowId, columnIndex);
234
297
  slots.push({
235
298
  type: "column-edge",
236
299
  rowId,
237
300
  columnIndex,
238
301
  direction: "left",
239
- rect: createColumnEdgeRect(columnRect, "left")
302
+ rect: createColumnEdgeRect(columnRect, "left"),
303
+ path: columnPath
240
304
  });
241
305
  slots.push({
242
306
  type: "column-edge",
243
307
  rowId,
244
308
  columnIndex,
245
309
  direction: "right",
246
- rect: createColumnEdgeRect(columnRect, "right")
310
+ rect: createColumnEdgeRect(columnRect, "right"),
311
+ path: columnPath
247
312
  });
248
313
  const itemElements = Array.from(
249
314
  columnElement.querySelectorAll(`[data-grid-item-row-id="${rowId}"][data-grid-column-index="${columnIndex}"]`)
@@ -256,11 +321,15 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
256
321
  return indexA - indexB;
257
322
  });
258
323
  if (sortedItems.length === 0) {
324
+ if (hasDirectNestedRows(columnElement)) {
325
+ return;
326
+ }
259
327
  slots.push({
260
328
  type: "empty-column",
261
329
  rowId,
262
330
  columnIndex,
263
- rect: expandColumnRect(columnRect)
331
+ rect: expandColumnRect(columnRect),
332
+ path: columnPath
264
333
  });
265
334
  return;
266
335
  }
@@ -271,17 +340,41 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
271
340
  columnIndex,
272
341
  insertIndex: 0,
273
342
  position: "before",
274
- rect: createColumnInsertRect(firstItemRect, "before")
343
+ rect: createColumnInsertRect(firstItemRect, "before"),
344
+ path: columnPath
275
345
  });
276
346
  sortedItems.forEach((itemElement, itemIndex) => {
277
347
  const itemRect = toRect(itemElement.getBoundingClientRect());
348
+ const itemPath = parseLayoutPath(itemElement.dataset.gridPath) || columnPath;
349
+ const itemUid = itemElement.dataset.gridItemUid || "";
350
+ slots.push({
351
+ type: "item-edge",
352
+ rowId,
353
+ columnIndex,
354
+ itemIndex,
355
+ itemUid,
356
+ direction: "left",
357
+ rect: createColumnEdgeRect(itemRect, "left"),
358
+ path: itemPath
359
+ });
360
+ slots.push({
361
+ type: "item-edge",
362
+ rowId,
363
+ columnIndex,
364
+ itemIndex,
365
+ itemUid,
366
+ direction: "right",
367
+ rect: createColumnEdgeRect(itemRect, "right"),
368
+ path: itemPath
369
+ });
278
370
  slots.push({
279
371
  type: "column",
280
372
  rowId,
281
373
  columnIndex,
282
374
  insertIndex: itemIndex + 1,
283
375
  position: "after",
284
- rect: createColumnInsertRect(itemRect, "after")
376
+ rect: createColumnInsertRect(itemRect, "after"),
377
+ path: itemPath
285
378
  });
286
379
  });
287
380
  });
@@ -289,7 +382,8 @@ const buildLayoutSnapshot = /* @__PURE__ */ __name(({ container }) => {
289
382
  type: "row-gap",
290
383
  targetRowId: rowId,
291
384
  position: "below",
292
- rect: createRowGapRect(rowRect, "below", containerRect)
385
+ rect: createRowGapRect(rowRect, "below", rowScopeRect),
386
+ path: rowPath
293
387
  });
294
388
  });
295
389
  return {
@@ -309,6 +403,8 @@ const getSlotKey = /* @__PURE__ */ __name((slot) => {
309
403
  return `${slot.type}`;
310
404
  case "empty-column":
311
405
  return `${slot.type}:${slot.rowId}:${slot.columnIndex}`;
406
+ case "item-edge":
407
+ return `${slot.type}:${slot.rowId}:${slot.columnIndex}:${slot.itemUid}:${slot.direction}`;
312
408
  }
313
409
  }, "getSlotKey");
314
410
  const isPointInsideRect = /* @__PURE__ */ __name((point, rect) => {
@@ -319,19 +415,38 @@ const distanceToRect = /* @__PURE__ */ __name((point, rect) => {
319
415
  const dy = Math.max(rect.top - point.y, 0, point.y - (rect.top + rect.height));
320
416
  return Math.sqrt(dx * dx + dy * dy);
321
417
  }, "distanceToRect");
418
+ const slotPriority = {
419
+ "item-edge": 5,
420
+ "column-edge": 4,
421
+ column: 3,
422
+ "row-gap": 2,
423
+ "empty-column": 1,
424
+ "empty-row": 0
425
+ };
322
426
  const resolveDropIntent = /* @__PURE__ */ __name((point, slots) => {
323
427
  if (!slots.length) {
324
428
  return null;
325
429
  }
326
- const insideSlot = slots.find((slot) => isPointInsideRect(point, slot.rect));
327
- if (insideSlot) {
328
- return insideSlot;
430
+ let bestInsideSlot = null;
431
+ let bestInsidePriority = Number.NEGATIVE_INFINITY;
432
+ slots.forEach((slot) => {
433
+ if (!isPointInsideRect(point, slot.rect)) {
434
+ return;
435
+ }
436
+ const priority = slotPriority[slot.type];
437
+ if (priority > bestInsidePriority) {
438
+ bestInsidePriority = priority;
439
+ bestInsideSlot = slot;
440
+ }
441
+ });
442
+ if (bestInsideSlot) {
443
+ return bestInsideSlot;
329
444
  }
330
445
  let closest = null;
331
446
  let minDistance = Number.POSITIVE_INFINITY;
332
447
  slots.forEach((slot) => {
333
448
  const distance = distanceToRect(point, slot.rect);
334
- if (distance < minDistance) {
449
+ if (distance < minDistance || distance === minDistance && closest && slotPriority[slot.type] > slotPriority[closest.type]) {
335
450
  minDistance = distance;
336
451
  closest = slot;
337
452
  }
@@ -381,7 +496,10 @@ const toIntSizes = /* @__PURE__ */ __name((weights, count) => {
381
496
  if (count === 0) {
382
497
  return [];
383
498
  }
384
- const normalizedWeights = weights.map((weight) => Number.isFinite(weight) && weight > 0 ? weight : 1);
499
+ const normalizedWeights = Array.from({ length: count }, (_2, index) => {
500
+ const weight = weights[index];
501
+ return Number.isFinite(weight) && weight > 0 ? weight : 1;
502
+ });
385
503
  const total = normalizedWeights.reduce((sum, weight) => sum + weight, 0) || count;
386
504
  const ratios = normalizedWeights.map((weight) => weight / total);
387
505
  const raw = ratios.map((ratio) => ratio * DEFAULT_GRID_COLUMNS);
@@ -414,6 +532,234 @@ const toIntSizes = /* @__PURE__ */ __name((weights, count) => {
414
532
  }
415
533
  return floors;
416
534
  }, "toIntSizes");
535
+ const EMPTY_COLUMN_VALUE = "EMPTY_COLUMN";
536
+ const createTopLevelRow = /* @__PURE__ */ __name((itemUid, id) => ({
537
+ id,
538
+ cells: [
539
+ {
540
+ id: `${id}:cell:0`,
541
+ items: [itemUid]
542
+ }
543
+ ],
544
+ sizes: [DEFAULT_GRID_COLUMNS]
545
+ }), "createTopLevelRow");
546
+ const convertLegacyRowsToLayout = /* @__PURE__ */ __name((rows = {}, sizes = {}, rowOrder) => {
547
+ const order = deriveRowOrder(rows, rowOrder);
548
+ return {
549
+ version: 2,
550
+ rows: order.map((rowId) => {
551
+ const cells = (rows[rowId] || []).map((items, columnIndex) => ({
552
+ id: `${rowId}:cell:${columnIndex}`,
553
+ items: [...items]
554
+ }));
555
+ return {
556
+ id: rowId,
557
+ cells,
558
+ sizes: toIntSizes(sizes[rowId] || new Array(cells.length).fill(1), cells.length)
559
+ };
560
+ }).filter((row) => row.cells.length > 0)
561
+ };
562
+ }, "convertLegacyRowsToLayout");
563
+ const collectCellItems = /* @__PURE__ */ __name((cell) => {
564
+ if (Array.isArray(cell.items)) {
565
+ return cell.items;
566
+ }
567
+ return (cell.rows || []).flatMap((row) => row.cells.flatMap((childCell) => collectCellItems(childCell)));
568
+ }, "collectCellItems");
569
+ const projectLayoutToLegacyRows = /* @__PURE__ */ __name((layout) => {
570
+ const rows = {};
571
+ const sizes = {};
572
+ const rowOrder = [];
573
+ const appendRows = /* @__PURE__ */ __name((sourceRows, prefix = "") => {
574
+ sourceRows.forEach((row) => {
575
+ const rowId = prefix ? `${prefix}/${row.id}` : row.id;
576
+ const cells = row.cells.map((cell) => collectCellItems(cell)).filter((items) => items.length > 0);
577
+ if (cells.length > 0) {
578
+ rows[rowId] = cells;
579
+ sizes[rowId] = toIntSizes(row.sizes || new Array(cells.length).fill(1), cells.length);
580
+ rowOrder.push(rowId);
581
+ }
582
+ });
583
+ }, "appendRows");
584
+ appendRows(layout.rows || []);
585
+ return { rows, sizes, rowOrder, layout };
586
+ }, "projectLayoutToLegacyRows");
587
+ const normalizeGridRows = /* @__PURE__ */ __name((rows, options) => {
588
+ return (Array.isArray(rows) ? rows : []).map((row, rowIndex) => {
589
+ const rawCells = Array.isArray(row == null ? void 0 : row.cells) ? row.cells : [];
590
+ const rawSizes = Array.isArray(row == null ? void 0 : row.sizes) ? row.sizes : [];
591
+ const cellsWithSizes = rawCells.map((cell, cellIndex) => {
592
+ const id = typeof (cell == null ? void 0 : cell.id) === "string" && cell.id ? cell.id : `${(row == null ? void 0 : row.id) || `row:${rowIndex}`}:cell:${cellIndex}`;
593
+ const size = rawSizes[cellIndex];
594
+ if (Array.isArray(cell == null ? void 0 : cell.rows) && cell.rows.length > 0) {
595
+ const childRows = normalizeGridRows(cell.rows, options);
596
+ if (childRows.length > 0) {
597
+ return { cell: { id, rows: childRows }, size };
598
+ }
599
+ }
600
+ const rawItems = Array.isArray(cell == null ? void 0 : cell.items) ? cell.items : void 0;
601
+ const items = (rawItems || []).filter((itemUid) => typeof itemUid === "string" && itemUid).filter((itemUid) => !options.validUids || options.validUids.has(itemUid) || itemUid === EMPTY_COLUMN_VALUE).filter((itemUid) => {
602
+ if (itemUid === EMPTY_COLUMN_VALUE) {
603
+ return true;
604
+ }
605
+ if (options.seenUids.has(itemUid)) {
606
+ return false;
607
+ }
608
+ options.seenUids.add(itemUid);
609
+ return true;
610
+ });
611
+ if (rawItems && (items.length > 0 || rawItems.length === 0)) {
612
+ return { cell: { id, items }, size };
613
+ }
614
+ return null;
615
+ }).filter(Boolean);
616
+ const cells = cellsWithSizes.map((entry) => entry.cell);
617
+ if (cells.length === 0) {
618
+ return null;
619
+ }
620
+ return {
621
+ id: typeof (row == null ? void 0 : row.id) === "string" && row.id ? row.id : `row:${rowIndex}`,
622
+ cells,
623
+ sizes: toIntSizes(
624
+ cellsWithSizes.map((entry) => entry.size),
625
+ cells.length
626
+ )
627
+ };
628
+ }).filter(Boolean);
629
+ }, "normalizeGridRows");
630
+ const collapseCell = /* @__PURE__ */ __name((cell) => {
631
+ var _a;
632
+ if ((_a = cell.rows) == null ? void 0 : _a.length) {
633
+ const rows = collapseRows(cell.rows);
634
+ if (rows.length === 0) {
635
+ return null;
636
+ }
637
+ if (rows.length === 1 && rows[0].cells.length === 1 && rows[0].sizes[0] === DEFAULT_GRID_COLUMNS) {
638
+ return {
639
+ id: cell.id,
640
+ ...import_lodash.default.omit(rows[0].cells[0], ["id"])
641
+ };
642
+ }
643
+ return { id: cell.id, rows };
644
+ }
645
+ if (Array.isArray(cell.items)) {
646
+ return { id: cell.id, items: cell.items.filter(Boolean) };
647
+ }
648
+ return null;
649
+ }, "collapseCell");
650
+ const collapseRows = /* @__PURE__ */ __name((rows) => {
651
+ return rows.map((row) => {
652
+ const cellsWithSizes = row.cells.map((cell, index) => {
653
+ var _a;
654
+ const collapsed = collapseCell(cell);
655
+ return collapsed ? { cell: collapsed, size: (_a = row.sizes) == null ? void 0 : _a[index] } : null;
656
+ }).filter(Boolean);
657
+ const cells = cellsWithSizes.map((entry) => entry.cell);
658
+ if (cells.length === 0) {
659
+ return null;
660
+ }
661
+ return {
662
+ id: row.id,
663
+ cells,
664
+ sizes: toIntSizes(
665
+ cellsWithSizes.map((entry) => entry.size),
666
+ cells.length
667
+ )
668
+ };
669
+ }).filter(Boolean);
670
+ }, "collapseRows");
671
+ const normalizeGridLayout = /* @__PURE__ */ __name(({
672
+ layout,
673
+ rows,
674
+ sizes,
675
+ rowOrder,
676
+ itemUids,
677
+ generateId = import_shared.uid,
678
+ logger,
679
+ gridUid
680
+ }) => {
681
+ var _a;
682
+ const validUids = itemUids ? new Set(itemUids) : void 0;
683
+ if (validUids) {
684
+ validUids.add(EMPTY_COLUMN_VALUE);
685
+ }
686
+ try {
687
+ const source = (layout == null ? void 0 : layout.version) === 2 ? import_lodash.default.cloneDeep(layout) : convertLegacyRowsToLayout(rows || {}, sizes || {}, rowOrder || Object.keys(rows || {}));
688
+ const seenUids = /* @__PURE__ */ new Set();
689
+ const next = {
690
+ version: 2,
691
+ rows: collapseRows(
692
+ normalizeGridRows(source.rows || [], {
693
+ validUids,
694
+ seenUids
695
+ })
696
+ )
697
+ };
698
+ if (itemUids == null ? void 0 : itemUids.length) {
699
+ itemUids.forEach((itemUid) => {
700
+ if (itemUid === EMPTY_COLUMN_VALUE || seenUids.has(itemUid)) {
701
+ return;
702
+ }
703
+ const rowId = generateId();
704
+ next.rows.push(createTopLevelRow(itemUid, rowId));
705
+ seenUids.add(itemUid);
706
+ });
707
+ }
708
+ return next;
709
+ } catch (error) {
710
+ (_a = logger == null ? void 0 : logger.warn) == null ? void 0 : _a.call(logger, `[GridModel] Failed to normalize grid layout${gridUid ? ` (${gridUid})` : ""}.`, error);
711
+ return {
712
+ version: 2,
713
+ rows: (itemUids || []).filter((itemUid) => itemUid !== EMPTY_COLUMN_VALUE).map((itemUid) => createTopLevelRow(itemUid, generateId()))
714
+ };
715
+ }
716
+ }, "normalizeGridLayout");
717
+ const replaceUidInGridLayout = /* @__PURE__ */ __name((layout, fromUid, toUid) => {
718
+ const replaceRows = /* @__PURE__ */ __name((rows) => rows.map((row) => ({
719
+ ...row,
720
+ cells: row.cells.map((cell) => {
721
+ if (cell.rows) {
722
+ return { ...cell, rows: replaceRows(cell.rows) };
723
+ }
724
+ return {
725
+ ...cell,
726
+ items: (cell.items || []).map((itemUid) => itemUid === fromUid ? toUid : itemUid)
727
+ };
728
+ })
729
+ })), "replaceRows");
730
+ return { version: 2, rows: replaceRows(import_lodash.default.cloneDeep(layout.rows || [])) };
731
+ }, "replaceUidInGridLayout");
732
+ const findModelUidLayoutPosition = /* @__PURE__ */ __name((layout, uidValue) => {
733
+ const visitRows = /* @__PURE__ */ __name((rows, parentPath) => {
734
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
735
+ const row = rows[rowIndex];
736
+ for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex += 1) {
737
+ const cell = row.cells[cellIndex];
738
+ const path = [...parentPath, { rowId: row.id, cellId: cell.id }];
739
+ if (cell.items) {
740
+ const itemIndex = cell.items.indexOf(uidValue);
741
+ if (itemIndex !== -1) {
742
+ return {
743
+ path,
744
+ rowIndex,
745
+ cellIndex,
746
+ itemIndex,
747
+ itemUid: uidValue
748
+ };
749
+ }
750
+ }
751
+ if (cell.rows) {
752
+ const result = visitRows(cell.rows, path);
753
+ if (result) {
754
+ return result;
755
+ }
756
+ }
757
+ }
758
+ }
759
+ return null;
760
+ }, "visitRows");
761
+ return visitRows(layout.rows || [], []);
762
+ }, "findModelUidLayoutPosition");
417
763
  const normalizeRowSizes = /* @__PURE__ */ __name((rowId, layout) => {
418
764
  const columns = layout.rows[rowId];
419
765
  if (!columns || columns.length === 0) {
@@ -455,12 +801,237 @@ const distributeSizesWithNewColumn = /* @__PURE__ */ __name((sizes, insertIndex,
455
801
  weights.splice(insertIndex, 0, reference);
456
802
  return toIntSizes(weights, columnCount);
457
803
  }, "distributeSizesWithNewColumn");
804
+ const resolveCellPath = /* @__PURE__ */ __name((layout, slot) => {
805
+ var _a;
806
+ if ("path" in slot && ((_a = slot.path) == null ? void 0 : _a.length)) {
807
+ return slot.path;
808
+ }
809
+ if ("rowId" in slot && "columnIndex" in slot) {
810
+ return createLegacyCellPath(slot.rowId, slot.columnIndex);
811
+ }
812
+ return void 0;
813
+ }, "resolveCellPath");
814
+ const findRowListByPath = /* @__PURE__ */ __name((layout, path) => {
815
+ if (!path || path.length <= 1) {
816
+ return layout.rows;
817
+ }
818
+ let rows = layout.rows;
819
+ for (let i = 0; i < path.length - 1; i += 1) {
820
+ const entry = path[i];
821
+ const row = rows.find((candidate) => candidate.id === entry.rowId);
822
+ const cell = row == null ? void 0 : row.cells.find((candidate) => candidate.id === entry.cellId);
823
+ if (!(cell == null ? void 0 : cell.rows)) {
824
+ return rows;
825
+ }
826
+ rows = cell.rows;
827
+ }
828
+ return rows;
829
+ }, "findRowListByPath");
830
+ const findCellByPath = /* @__PURE__ */ __name((layout, path) => {
831
+ if (!(path == null ? void 0 : path.length)) {
832
+ return null;
833
+ }
834
+ let rows = layout.rows;
835
+ for (let i = 0; i < path.length; i += 1) {
836
+ const entry = path[i];
837
+ const rowIndex = rows.findIndex((candidate) => candidate.id === entry.rowId);
838
+ const row = rows[rowIndex];
839
+ if (!row || !entry.cellId) {
840
+ return null;
841
+ }
842
+ const cellIndex = row.cells.findIndex((candidate) => candidate.id === entry.cellId);
843
+ const cell = row.cells[cellIndex];
844
+ if (!cell) {
845
+ return null;
846
+ }
847
+ if (i === path.length - 1) {
848
+ return { rows, row, cell, rowIndex, cellIndex };
849
+ }
850
+ rows = cell.rows || [];
851
+ }
852
+ return null;
853
+ }, "findCellByPath");
854
+ const removeItemFromGridLayout = /* @__PURE__ */ __name((layout, sourceUid) => {
855
+ const removeFromRows = /* @__PURE__ */ __name((rows) => rows.map((row) => {
856
+ const cellsWithSizes = row.cells.map((cell, index) => {
857
+ var _a, _b;
858
+ if (cell.rows) {
859
+ const childRows = removeFromRows(cell.rows);
860
+ return childRows.length ? { cell: { ...cell, rows: childRows }, size: (_a = row.sizes) == null ? void 0 : _a[index] } : null;
861
+ }
862
+ const currentItems = cell.items || [];
863
+ const hadSourceUid = currentItems.includes(sourceUid);
864
+ const items = currentItems.filter((itemUid) => itemUid !== sourceUid);
865
+ if (hadSourceUid && !items.length) {
866
+ return null;
867
+ }
868
+ return { cell: { ...cell, items }, size: (_b = row.sizes) == null ? void 0 : _b[index] };
869
+ }).filter(Boolean);
870
+ const cells = cellsWithSizes.map((entry) => entry.cell);
871
+ return cells.length ? {
872
+ ...row,
873
+ cells,
874
+ sizes: toIntSizes(
875
+ cellsWithSizes.map((entry) => entry.size),
876
+ cells.length
877
+ )
878
+ } : null;
879
+ }).filter(Boolean), "removeFromRows");
880
+ layout.rows = collapseRows(removeFromRows(layout.rows));
881
+ }, "removeItemFromGridLayout");
882
+ const createSingleCellRow = /* @__PURE__ */ __name((itemUid, rowId, cellId) => ({
883
+ id: rowId,
884
+ cells: [{ id: cellId, items: [itemUid] }],
885
+ sizes: [DEFAULT_GRID_COLUMNS]
886
+ }), "createSingleCellRow");
887
+ const getGeneratedId = /* @__PURE__ */ __name((key, options) => {
888
+ var _a, _b, _c;
889
+ const existing = (_a = options == null ? void 0 : options.generatedIds) == null ? void 0 : _a.get(key);
890
+ if (existing) {
891
+ return existing;
892
+ }
893
+ const value = ((_b = options == null ? void 0 : options.generateId) == null ? void 0 : _b.call(options, key)) || (0, import_shared.uid)();
894
+ (_c = options == null ? void 0 : options.generatedIds) == null ? void 0 : _c.set(key, value);
895
+ return value;
896
+ }, "getGeneratedId");
897
+ const simulateGridLayoutForSlot = /* @__PURE__ */ __name(({
898
+ slot,
899
+ sourceUid,
900
+ layout,
901
+ generatedIds,
902
+ generateId
903
+ }) => {
904
+ const original = normalizeGridLayout({
905
+ layout: layout.layout,
906
+ rows: layout.rows,
907
+ sizes: layout.sizes,
908
+ rowOrder: layout.rowOrder
909
+ });
910
+ const cloned = import_lodash.default.cloneDeep(original);
911
+ const slotKey = getSlotKey(slot);
912
+ const sourcePosition = findModelUidLayoutPosition(cloned, sourceUid);
913
+ if (slot.type === "item-edge" && slot.itemUid === sourceUid) {
914
+ return cloned;
915
+ }
916
+ const targetPath = resolveCellPath(cloned, slot);
917
+ const targetItemUid = slot.type === "item-edge" ? slot.itemUid : void 0;
918
+ removeItemFromGridLayout(cloned, sourceUid);
919
+ switch (slot.type) {
920
+ case "column": {
921
+ const target = findCellByPath(cloned, targetPath);
922
+ if (!target) {
923
+ break;
924
+ }
925
+ if (target.cell.rows) {
926
+ target.cell.rows.push(
927
+ createTopLevelRow(sourceUid, getGeneratedId(`${slotKey}:row`, { generatedIds, generateId }))
928
+ );
929
+ break;
930
+ }
931
+ target.cell.items ||= [];
932
+ const insertIndex = Math.max(0, Math.min(slot.insertIndex, target.cell.items.length));
933
+ target.cell.items.splice(insertIndex, 0, sourceUid);
934
+ break;
935
+ }
936
+ case "empty-column": {
937
+ const target = findCellByPath(cloned, targetPath);
938
+ if (target) {
939
+ delete target.cell.rows;
940
+ target.cell.items = [sourceUid];
941
+ }
942
+ break;
943
+ }
944
+ case "column-edge": {
945
+ const target = findCellByPath(cloned, targetPath);
946
+ if (!target) {
947
+ break;
948
+ }
949
+ const insertIndex = slot.direction === "left" ? target.cellIndex : target.cellIndex + 1;
950
+ const cellId = getGeneratedId(`${slotKey}:cell`, { generatedIds, generateId });
951
+ target.row.cells.splice(insertIndex, 0, { id: cellId, items: [sourceUid] });
952
+ target.row.sizes = distributeSizesWithNewColumn(target.row.sizes, insertIndex, target.row.cells.length);
953
+ break;
954
+ }
955
+ case "row-gap": {
956
+ const rows = findRowListByPath(cloned, slot.path);
957
+ const targetIndex = rows.findIndex((row) => row.id === slot.targetRowId);
958
+ const insertIndex = targetIndex === -1 ? rows.length : slot.position === "above" ? targetIndex : targetIndex + 1;
959
+ const rowId = getGeneratedId(`${slotKey}:row`, { generatedIds, generateId });
960
+ rows.splice(insertIndex, 0, createSingleCellRow(sourceUid, rowId, `${rowId}:cell:0`));
961
+ break;
962
+ }
963
+ case "empty-row": {
964
+ const rowId = getGeneratedId(`${slotKey}:row`, { generatedIds, generateId });
965
+ cloned.rows.push(createSingleCellRow(sourceUid, rowId, `${rowId}:cell:0`));
966
+ break;
967
+ }
968
+ case "item-edge": {
969
+ if (!targetItemUid) {
970
+ break;
971
+ }
972
+ const target = findCellByPath(cloned, targetPath);
973
+ if (!(target == null ? void 0 : target.cell.items)) {
974
+ break;
975
+ }
976
+ const targetIndex = target.cell.items.indexOf(targetItemUid);
977
+ if (targetIndex === -1) {
978
+ break;
979
+ }
980
+ const rows = [];
981
+ target.cell.items.forEach((itemUid, index) => {
982
+ if (index === targetIndex) {
983
+ const rowId2 = getGeneratedId(`${slotKey}:target-row`, { generatedIds, generateId });
984
+ const leftItem = slot.direction === "left" ? sourceUid : itemUid;
985
+ const rightItem = slot.direction === "left" ? itemUid : sourceUid;
986
+ rows.push({
987
+ id: rowId2,
988
+ cells: [
989
+ { id: getGeneratedId(`${slotKey}:target-cell:0`, { generatedIds, generateId }), items: [leftItem] },
990
+ { id: getGeneratedId(`${slotKey}:target-cell:1`, { generatedIds, generateId }), items: [rightItem] }
991
+ ],
992
+ sizes: [12, 12]
993
+ });
994
+ return;
995
+ }
996
+ const rowId = getGeneratedId(`${slotKey}:row:${index}`, { generatedIds, generateId });
997
+ rows.push(createSingleCellRow(itemUid, rowId, `${rowId}:cell:0`));
998
+ });
999
+ delete target.cell.items;
1000
+ target.cell.rows = rows;
1001
+ break;
1002
+ }
1003
+ default:
1004
+ break;
1005
+ }
1006
+ const normalized = normalizeGridLayout({ layout: cloned });
1007
+ if (sourcePosition && isSameGridLayout(normalized, original)) {
1008
+ return original;
1009
+ }
1010
+ return normalized;
1011
+ }, "simulateGridLayoutForSlot");
1012
+ const isSameGridLayout = /* @__PURE__ */ __name((a, b) => {
1013
+ return JSON.stringify(a) === JSON.stringify(b);
1014
+ }, "isSameGridLayout");
458
1015
  const simulateLayoutForSlot = /* @__PURE__ */ __name(({
459
1016
  slot,
460
1017
  sourceUid,
461
1018
  layout,
462
- generateRowId
1019
+ generateRowId,
1020
+ generatedIds,
1021
+ generateId
463
1022
  }) => {
1023
+ var _a;
1024
+ if (layout.layout || slot.type === "item-edge" || "path" in slot && ((_a = slot.path) == null ? void 0 : _a.length)) {
1025
+ const nextLayout = simulateGridLayoutForSlot({
1026
+ slot,
1027
+ sourceUid,
1028
+ layout,
1029
+ generateRowId,
1030
+ generatedIds,
1031
+ generateId
1032
+ });
1033
+ return projectLayoutToLegacyRows(nextLayout);
1034
+ }
464
1035
  const cloned = {
465
1036
  rows: import_lodash.default.cloneDeep(layout.rows),
466
1037
  sizes: import_lodash.default.cloneDeep(layout.sizes),
@@ -547,7 +1118,12 @@ const simulateLayoutForSlot = /* @__PURE__ */ __name(({
547
1118
  MAX_SLOT_THICKNESS,
548
1119
  MIN_SLOT_THICKNESS,
549
1120
  buildLayoutSnapshot,
1121
+ findModelUidLayoutPosition,
550
1122
  getSlotKey,
1123
+ isSameGridLayout,
1124
+ normalizeGridLayout,
1125
+ projectLayoutToLegacyRows,
1126
+ replaceUidInGridLayout,
551
1127
  resolveDropIntent,
552
1128
  simulateLayoutForSlot
553
1129
  });