@measured/puck-plugin-heading-analyzer 0.19.0-canary.84a836b → 0.19.0-canary.a281c342

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.
package/dist/index.mjs CHANGED
@@ -187,7 +187,7 @@ init_react_import();
187
187
 
188
188
  // src/HeadingAnalyzer.tsx
189
189
  init_react_import();
190
- import { useEffect as useEffect6, useState } from "react";
190
+ import { useEffect as useEffect5, useState } from "react";
191
191
 
192
192
  // css-module:/home/runner/work/puck/puck/packages/plugin-heading-analyzer/src/HeadingAnalyzer.module.css#css-module
193
193
  init_react_import();
@@ -356,28 +356,13 @@ init_react_import();
356
356
  // ../core/reducer/index.ts
357
357
  init_react_import();
358
358
 
359
- // ../core/reducer/data.ts
359
+ // ../core/reducer/reduce.ts
360
360
  init_react_import();
361
361
 
362
- // ../core/lib/reorder.ts
363
- init_react_import();
364
- var reorder = (list, startIndex, endIndex) => {
365
- const result = Array.from(list);
366
- const [removed] = result.splice(startIndex, 1);
367
- result.splice(endIndex, 0, removed);
368
- return result;
369
- };
370
-
371
- // ../core/lib/root-droppable-id.ts
372
- init_react_import();
373
- var rootAreaId = "root";
374
- var rootZone = "default-zone";
375
- var rootDroppableId = `${rootAreaId}:${rootZone}`;
376
-
377
362
  // ../core/lib/insert.ts
378
363
  init_react_import();
379
364
  var insert = (list, index, item) => {
380
- const result = Array.from(list);
365
+ const result = Array.from(list || []);
381
366
  result.splice(index, 0, item);
382
367
  return result;
383
368
  };
@@ -392,6 +377,14 @@ var remove = (list, index) => {
392
377
 
393
378
  // ../core/lib/setup-zone.ts
394
379
  init_react_import();
380
+
381
+ // ../core/lib/root-droppable-id.ts
382
+ init_react_import();
383
+ var rootAreaId = "root";
384
+ var rootZone = "default-zone";
385
+ var rootDroppableId = `${rootAreaId}:${rootZone}`;
386
+
387
+ // ../core/lib/setup-zone.ts
395
388
  var setupZone = (data, zoneKey) => {
396
389
  if (zoneKey === rootDroppableId) {
397
390
  return data;
@@ -403,29 +396,14 @@ var setupZone = (data, zoneKey) => {
403
396
  return newData;
404
397
  };
405
398
 
406
- // ../core/lib/replace.ts
407
- init_react_import();
408
- var replace = (list, index, newItem) => {
409
- const result = Array.from(list);
410
- result.splice(index, 1);
411
- result.splice(index, 0, newItem);
412
- return result;
413
- };
414
-
415
399
  // ../core/lib/get-item.ts
416
400
  init_react_import();
417
- function getItem(selector, data, dynamicProps = {}) {
418
- if (!selector.zone || selector.zone === rootDroppableId) {
419
- const item2 = data.content[selector.index];
420
- return (item2 == null ? void 0 : item2.props) ? __spreadProps(__spreadValues({}, item2), { props: dynamicProps[item2.props.id] || item2.props }) : void 0;
421
- }
422
- const item = setupZone(data, selector.zone).zones[selector.zone][selector.index];
423
- return (item == null ? void 0 : item.props) ? __spreadProps(__spreadValues({}, item), { props: dynamicProps[item.props.id] || item.props }) : void 0;
401
+ function getItem(selector, state) {
402
+ var _a, _b;
403
+ const zone = (_a = state.indexes.zones) == null ? void 0 : _a[selector.zone || rootDroppableId];
404
+ return zone ? (_b = state.indexes.nodes[zone.contentIds[selector.index]]) == null ? void 0 : _b.data : void 0;
424
405
  }
425
406
 
426
- // ../core/lib/reduce-related-zones.ts
427
- init_react_import();
428
-
429
407
  // ../core/lib/generate-id.ts
430
408
  init_react_import();
431
409
 
@@ -488,6 +466,49 @@ var v4_default = v4;
488
466
  // ../core/lib/generate-id.ts
489
467
  var generateId = (type) => type ? `${type}-${v4_default()}` : v4_default();
490
468
 
469
+ // ../core/lib/walk-tree.ts
470
+ init_react_import();
471
+
472
+ // ../core/lib/for-each-slot.ts
473
+ init_react_import();
474
+
475
+ // ../core/lib/is-slot.ts
476
+ init_react_import();
477
+ var isSlot = (prop) => {
478
+ var _a, _b;
479
+ return Array.isArray(prop) && typeof ((_a = prop[0]) == null ? void 0 : _a.type) === "string" && typeof ((_b = prop[0]) == null ? void 0 : _b.props) === "object";
480
+ };
481
+ var createIsSlotConfig = (config) => (itemType, propName, propValue) => {
482
+ var _a, _b;
483
+ const configForComponent = itemType === "root" ? config == null ? void 0 : config.root : config == null ? void 0 : config.components[itemType];
484
+ if (!configForComponent) return isSlot(propValue);
485
+ return ((_b = (_a = configForComponent.fields) == null ? void 0 : _a[propName]) == null ? void 0 : _b.type) === "slot";
486
+ };
487
+
488
+ // ../core/lib/for-each-slot.ts
489
+ var forEachSlot = (_0, _1, ..._2) => __async(void 0, [_0, _1, ..._2], function* (item, cb, recursive = false, isSlot2 = isSlot) {
490
+ const props = item.props || {};
491
+ const propKeys = Object.keys(props);
492
+ for (let i = 0; i < propKeys.length; i++) {
493
+ const propKey = propKeys[i];
494
+ const itemType = "type" in item ? item.type : "root";
495
+ if (isSlot2(itemType, propKey, props[propKey])) {
496
+ const content = props[propKey];
497
+ yield cb(props.id, propKey, content);
498
+ if (recursive) {
499
+ content.forEach(
500
+ (childItem) => __async(void 0, null, function* () {
501
+ return yield forEachSlot(childItem, cb, true, isSlot2);
502
+ })
503
+ );
504
+ }
505
+ }
506
+ }
507
+ });
508
+
509
+ // ../core/lib/for-related-zones.ts
510
+ init_react_import();
511
+
491
512
  // ../core/lib/get-zone-id.ts
492
513
  init_react_import();
493
514
  var getZoneId = (zoneCompound) => {
@@ -500,302 +521,497 @@ var getZoneId = (zoneCompound) => {
500
521
  return [rootDroppableId, zoneCompound];
501
522
  };
502
523
 
503
- // ../core/lib/reduce-related-zones.ts
504
- function reduceRelatedZones(item, data, fn) {
524
+ // ../core/lib/for-related-zones.ts
525
+ function forRelatedZones(item, data, cb, path = []) {
526
+ Object.entries(data.zones || {}).forEach(([zoneCompound, content]) => {
527
+ const [parentId] = getZoneId(zoneCompound);
528
+ if (parentId === item.props.id) {
529
+ const newPath = [...path, zoneCompound];
530
+ content.forEach((item2) => forRelatedZones(item2, data, cb, newPath));
531
+ cb(path, zoneCompound, content);
532
+ }
533
+ });
534
+ }
535
+
536
+ // ../core/lib/strip-slots.ts
537
+ init_react_import();
538
+ var stripSlots = (data) => {
505
539
  return __spreadProps(__spreadValues({}, data), {
506
- zones: Object.keys(data.zones || {}).reduce(
507
- (acc, key) => {
508
- const [parentId] = getZoneId(key);
509
- if (parentId === item.props.id) {
510
- const zones = data.zones;
511
- return fn(acc, key, zones[key]);
540
+ props: Object.entries(data.props).reduce(
541
+ (acc, [propKey, propVal]) => {
542
+ if (isSlot(propVal)) {
543
+ return acc;
512
544
  }
513
- return __spreadProps(__spreadValues({}, acc), { [key]: data.zones[key] });
545
+ return __spreadProps(__spreadValues({}, acc), { [propKey]: propVal });
514
546
  },
515
- {}
547
+ { id: data.props.id }
516
548
  )
517
549
  });
518
- }
519
- var findRelatedByZoneId = (zoneId, data) => {
520
- const [zoneParentId] = getZoneId(zoneId);
521
- return (data.zones[zoneId] || []).reduce(
522
- (acc, zoneItem) => {
523
- const related = findRelatedByItem(zoneItem, data);
524
- if (zoneItem.props.id === zoneParentId) {
525
- return __spreadProps(__spreadValues(__spreadValues({}, acc), related), { [zoneId]: zoneItem });
526
- }
527
- return __spreadValues(__spreadValues({}, acc), related);
528
- },
529
- {}
530
- );
531
550
  };
532
- var findRelatedByItem = (item, data) => {
533
- return Object.keys(data.zones || {}).reduce(
534
- (acc, zoneId) => {
535
- const [zoneParentId] = getZoneId(zoneId);
536
- if (item.props.id === zoneParentId) {
537
- const related = findRelatedByZoneId(zoneId, data);
538
- return __spreadProps(__spreadValues(__spreadValues({}, acc), related), {
539
- [zoneId]: data.zones[zoneId]
540
- });
541
- }
542
- return acc;
551
+
552
+ // ../core/lib/walk-tree.ts
553
+ function walkTree(state, config, mapContent = (content) => content, mapNodeOrSkip = (item) => item) {
554
+ var _a;
555
+ let newZones = {};
556
+ const newZoneIndex = {};
557
+ const newNodeIndex = {};
558
+ const processContent = (path, zoneCompound, content, zoneType, newId) => {
559
+ var _a2;
560
+ const [parentId] = zoneCompound.split(":");
561
+ const mappedContent = ((_a2 = mapContent(content, zoneCompound, zoneType)) != null ? _a2 : content) || [];
562
+ const [_2, zone] = zoneCompound.split(":");
563
+ const newZoneCompound = `${newId || parentId}:${zone}`;
564
+ const newContent2 = mappedContent.map(
565
+ (zoneChild, index) => processItem(zoneChild, [...path, newZoneCompound], index)
566
+ );
567
+ newZoneIndex[newZoneCompound] = {
568
+ contentIds: newContent2.map((item) => item.props.id),
569
+ type: zoneType
570
+ };
571
+ return [newZoneCompound, newContent2];
572
+ };
573
+ const processRelatedZones = (item, newId, initialPath) => {
574
+ forRelatedZones(
575
+ item,
576
+ state.data,
577
+ (relatedPath, relatedZoneCompound, relatedContent) => {
578
+ const [zoneCompound, newContent2] = processContent(
579
+ relatedPath,
580
+ relatedZoneCompound,
581
+ relatedContent,
582
+ "dropzone",
583
+ newId
584
+ );
585
+ newZones[zoneCompound] = newContent2;
586
+ },
587
+ initialPath
588
+ );
589
+ };
590
+ const processItem = (item, path, index) => {
591
+ const mappedItem = mapNodeOrSkip(item, path, index);
592
+ if (!mappedItem) return item;
593
+ const id = mappedItem.props.id;
594
+ processRelatedZones(item, id, path);
595
+ const newProps = __spreadValues({}, mappedItem.props);
596
+ forEachSlot(
597
+ mappedItem,
598
+ (parentId2, slotId, content) => {
599
+ const zoneCompound = `${parentId2}:${slotId}`;
600
+ const [_2, newContent2] = processContent(
601
+ path,
602
+ zoneCompound,
603
+ content,
604
+ "slot",
605
+ parentId2
606
+ );
607
+ newProps[slotId] = newContent2;
608
+ },
609
+ false,
610
+ createIsSlotConfig(config)
611
+ );
612
+ const newItem = __spreadProps(__spreadValues({}, item), { props: newProps });
613
+ const thisZoneCompound = path[path.length - 1];
614
+ const [parentId, zone] = thisZoneCompound ? thisZoneCompound.split(":") : [null, ""];
615
+ newNodeIndex[id] = {
616
+ data: newItem,
617
+ flatData: stripSlots(newItem),
618
+ path,
619
+ parentId,
620
+ zone
621
+ };
622
+ const finalData = __spreadProps(__spreadValues({}, newItem), { props: __spreadValues({}, newItem.props) });
623
+ if (newProps.id === "root") {
624
+ delete finalData["type"];
625
+ delete finalData.props["id"];
626
+ }
627
+ return finalData;
628
+ };
629
+ const zones = state.data.zones || {};
630
+ const [_, newContent] = processContent(
631
+ [],
632
+ rootDroppableId,
633
+ state.data.content,
634
+ "root"
635
+ );
636
+ const processedContent = newContent;
637
+ const zonesAlreadyProcessed = Object.keys(newZones);
638
+ Object.keys(zones || {}).forEach((zoneCompound) => {
639
+ const [parentId] = zoneCompound.split(":");
640
+ if (zonesAlreadyProcessed.includes(zoneCompound)) {
641
+ return;
642
+ }
643
+ const [_2, newContent2] = processContent(
644
+ [rootDroppableId],
645
+ zoneCompound,
646
+ zones[zoneCompound],
647
+ "dropzone",
648
+ parentId
649
+ );
650
+ newZones[zoneCompound] = newContent2;
651
+ }, newZones);
652
+ const processedRoot = processItem(
653
+ {
654
+ type: "root",
655
+ props: __spreadProps(__spreadValues({}, (_a = state.data.root.props) != null ? _a : state.data.root), { id: "root" })
543
656
  },
544
- {}
657
+ [],
658
+ -1
545
659
  );
546
- };
547
- var removeRelatedZones = (item, data) => {
548
- const newData = __spreadValues({}, data);
549
- const related = findRelatedByItem(item, data);
550
- Object.keys(related).forEach((key) => {
551
- delete newData.zones[key];
660
+ const root = __spreadProps(__spreadValues({}, state.data.root), {
661
+ props: processedRoot.props
552
662
  });
553
- return newData;
554
- };
555
- function duplicateRelatedZones(item, data, newId) {
556
- return reduceRelatedZones(item, data, (acc, key, zone) => {
557
- const dupedZone = zone.map((zoneItem) => __spreadProps(__spreadValues({}, zoneItem), {
558
- props: __spreadProps(__spreadValues({}, zoneItem.props), { id: generateId(zoneItem.type) })
559
- }));
560
- const dupeOfDupes = dupedZone.reduce(
561
- (dupeOfDupes2, item2, index) => __spreadValues(__spreadValues({}, dupeOfDupes2), duplicateRelatedZones(zone[index], data, item2.props.id).zones),
562
- acc
563
- );
564
- const [_, zoneId] = getZoneId(key);
565
- return __spreadProps(__spreadValues({}, dupeOfDupes), {
566
- [key]: zone,
567
- [`${newId}:${zoneId}`]: dupedZone
568
- });
663
+ return __spreadProps(__spreadValues({}, state), {
664
+ data: {
665
+ root,
666
+ // root: state.data.root, // TODO changing root causes it's entire subtree to re-render. Let's keep this disabled until the performance issues are resolved in #644.
667
+ content: processedContent,
668
+ zones: __spreadValues(__spreadValues({}, state.data.zones), newZones)
669
+ },
670
+ indexes: {
671
+ nodes: __spreadValues(__spreadValues({}, state.indexes.nodes), newNodeIndex),
672
+ zones: __spreadValues(__spreadValues({}, state.indexes.zones), newZoneIndex)
673
+ }
569
674
  });
570
675
  }
571
676
 
572
- // ../core/reducer/data.ts
677
+ // ../core/reducer/reduce.ts
573
678
  var zoneCache = {};
574
- var replaceAction = (data, action) => {
575
- if (action.destinationZone === rootDroppableId) {
576
- return __spreadProps(__spreadValues({}, data), {
577
- content: replace(data.content, action.destinationIndex, action.data)
578
- });
579
- }
580
- const newData = setupZone(data, action.destinationZone);
581
- return __spreadProps(__spreadValues({}, newData), {
582
- zones: __spreadProps(__spreadValues({}, newData.zones), {
583
- [action.destinationZone]: replace(
584
- newData.zones[action.destinationZone],
585
- action.destinationIndex,
586
- action.data
587
- )
588
- })
589
- });
679
+ var getIdsForParent = (zoneCompound, state) => {
680
+ const [parentId] = zoneCompound.split(":");
681
+ const node = state.indexes.nodes[parentId];
682
+ return ((node == null ? void 0 : node.path) || []).map((p) => p.split(":")[0]);
590
683
  };
591
- function insertAction(data, action, config) {
684
+ function insertAction(state, action, config) {
685
+ const id = action.id || generateId(action.componentType);
592
686
  const emptyComponentData = {
593
687
  type: action.componentType,
594
688
  props: __spreadProps(__spreadValues({}, config.components[action.componentType].defaultProps || {}), {
595
- id: action.id || generateId(action.componentType)
689
+ id
596
690
  })
597
691
  };
598
- if (action.destinationZone === rootDroppableId) {
599
- return __spreadProps(__spreadValues({}, data), {
600
- content: insert(
601
- data.content,
602
- action.destinationIndex,
603
- emptyComponentData
604
- )
605
- });
606
- }
607
- const newData = setupZone(data, action.destinationZone);
608
- return __spreadProps(__spreadValues({}, data), {
609
- zones: __spreadProps(__spreadValues({}, newData.zones), {
610
- [action.destinationZone]: insert(
611
- newData.zones[action.destinationZone],
612
- action.destinationIndex,
613
- emptyComponentData
614
- )
615
- })
616
- });
692
+ const [parentId] = action.destinationZone.split(":");
693
+ const idsInPath = getIdsForParent(action.destinationZone, state);
694
+ return walkTree(
695
+ state,
696
+ config,
697
+ (content, zoneCompound) => {
698
+ if (zoneCompound === action.destinationZone) {
699
+ return insert(
700
+ content || [],
701
+ action.destinationIndex,
702
+ emptyComponentData
703
+ );
704
+ }
705
+ return content;
706
+ },
707
+ (childItem, path) => {
708
+ if (childItem.props.id === id || childItem.props.id === parentId) {
709
+ return childItem;
710
+ } else if (idsInPath.includes(childItem.props.id)) {
711
+ return childItem;
712
+ } else if (path.includes(action.destinationZone)) {
713
+ return childItem;
714
+ }
715
+ return null;
716
+ }
717
+ );
617
718
  }
618
- var reorderAction = (data, action) => {
619
- if (action.destinationZone === rootDroppableId) {
620
- return __spreadProps(__spreadValues({}, data), {
621
- content: reorder(
622
- data.content,
623
- action.sourceIndex,
624
- action.destinationIndex
625
- )
626
- });
719
+ var moveAction = (state, action, appStore) => {
720
+ if (action.sourceZone === action.destinationZone && action.sourceIndex === action.destinationIndex) {
721
+ return state;
627
722
  }
628
- const newData = setupZone(data, action.destinationZone);
629
- return __spreadProps(__spreadValues({}, data), {
630
- zones: __spreadProps(__spreadValues({}, newData.zones), {
631
- [action.destinationZone]: reorder(
632
- newData.zones[action.destinationZone],
633
- action.sourceIndex,
634
- action.destinationIndex
635
- )
636
- })
723
+ const item = getItem(
724
+ { zone: action.sourceZone, index: action.sourceIndex },
725
+ state
726
+ );
727
+ if (!item) return state;
728
+ const idsInSourcePath = getIdsForParent(action.sourceZone, state);
729
+ const idsInDestinationPath = getIdsForParent(action.destinationZone, state);
730
+ return walkTree(
731
+ state,
732
+ appStore.config,
733
+ (content, zoneCompound) => {
734
+ if (zoneCompound === action.sourceZone && zoneCompound === action.destinationZone) {
735
+ return insert(
736
+ remove(content, action.sourceIndex),
737
+ action.destinationIndex,
738
+ item
739
+ );
740
+ } else if (zoneCompound === action.sourceZone) {
741
+ return remove(content, action.sourceIndex);
742
+ } else if (zoneCompound === action.destinationZone) {
743
+ return insert(content, action.destinationIndex, item);
744
+ }
745
+ return content;
746
+ },
747
+ (childItem, path) => {
748
+ const [sourceZoneParent] = action.sourceZone.split(":");
749
+ const [destinationZoneParent] = action.destinationZone.split(":");
750
+ const childId = childItem.props.id;
751
+ if (sourceZoneParent === childId || destinationZoneParent === childId || item.props.id === childId || idsInSourcePath.indexOf(childId) > -1 || idsInDestinationPath.indexOf(childId) > -1 || path.includes(action.destinationZone)) {
752
+ return childItem;
753
+ }
754
+ return null;
755
+ }
756
+ );
757
+ };
758
+ var replaceAction = (state, action, appStore) => {
759
+ const [parentId] = action.destinationZone.split(":");
760
+ const idsInPath = getIdsForParent(action.destinationZone, state);
761
+ const originalId = state.indexes.zones[action.destinationZone].contentIds[action.destinationIndex];
762
+ const idChanged = originalId !== action.data.props.id;
763
+ if (idChanged) {
764
+ throw new Error(
765
+ `Can't change the id during a replace action. Please us "remove" and "insert" to define a new node.`
766
+ );
767
+ }
768
+ return walkTree(
769
+ state,
770
+ appStore.config,
771
+ (content, zoneCompound) => {
772
+ const newContent = [...content];
773
+ if (zoneCompound === action.destinationZone) {
774
+ newContent[action.destinationIndex] = action.data;
775
+ }
776
+ return newContent;
777
+ },
778
+ (childItem, path) => {
779
+ const pathIds = path.map((p) => p.split(":")[0]);
780
+ if (childItem.props.id === action.data.props.id) {
781
+ return action.data;
782
+ } else if (childItem.props.id === parentId) {
783
+ return childItem;
784
+ } else if (idsInPath.indexOf(childItem.props.id) > -1) {
785
+ return childItem;
786
+ } else if (pathIds.indexOf(action.data.props.id) > -1) {
787
+ return childItem;
788
+ }
789
+ return null;
790
+ }
791
+ );
792
+ };
793
+ var setAction = (state, action, appStore) => {
794
+ if (typeof action.state === "object") {
795
+ const newState = __spreadValues(__spreadValues({}, state), action.state);
796
+ if (action.state.indexes) {
797
+ console.warn(
798
+ "`set` is expensive and may cause unnecessary re-renders. Consider using a more atomic action instead."
799
+ );
800
+ return newState;
801
+ }
802
+ return walkTree(newState, appStore.config);
803
+ }
804
+ return __spreadValues(__spreadValues({}, state), action.state(state));
805
+ };
806
+ var removeAction = (state, action, appStore) => {
807
+ const item = getItem({ index: action.index, zone: action.zone }, state);
808
+ const [parentId] = action.zone.split(":");
809
+ const nodesToDelete = Object.entries(state.indexes.nodes).reduce(
810
+ (acc, [nodeId, nodeData]) => {
811
+ const pathIds = nodeData.path.map((p) => p.split(":")[0]);
812
+ if (pathIds.includes(item.props.id)) {
813
+ return [...acc, nodeId];
814
+ }
815
+ return acc;
816
+ },
817
+ [item.props.id]
818
+ );
819
+ const newState = walkTree(
820
+ state,
821
+ appStore.config,
822
+ (content, zoneCompound) => {
823
+ if (zoneCompound === action.zone) {
824
+ return remove(content, action.index);
825
+ }
826
+ return content;
827
+ },
828
+ (childItem, path) => {
829
+ const parentIds = path.map((p) => p.split(":")[0]);
830
+ if (childItem.props.id === parentId || childItem.props.id === item.props.id || parentIds.indexOf(item.props.id) > -1) {
831
+ return childItem;
832
+ }
833
+ return null;
834
+ }
835
+ );
836
+ Object.keys(newState.data.zones || {}).forEach((zoneCompound) => {
837
+ const parentId2 = zoneCompound.split(":")[0];
838
+ if (nodesToDelete.includes(parentId2) && newState.data.zones) {
839
+ delete newState.data.zones[zoneCompound];
840
+ }
841
+ });
842
+ Object.keys(newState.indexes.zones).forEach((zoneCompound) => {
843
+ const parentId2 = zoneCompound.split(":")[0];
844
+ if (nodesToDelete.includes(parentId2)) {
845
+ delete newState.indexes.zones[zoneCompound];
846
+ }
847
+ });
848
+ nodesToDelete.forEach((id) => {
849
+ delete newState.indexes.nodes[id];
637
850
  });
851
+ return newState;
638
852
  };
639
- function reduceData(data, action, config) {
853
+ function reduce(state, action, appStore) {
854
+ if (action.type === "set") {
855
+ return setAction(state, action, appStore);
856
+ }
640
857
  if (action.type === "insert") {
641
- return insertAction(data, action, config);
858
+ return insertAction(state, action, appStore.config);
859
+ }
860
+ if (action.type === "replace") {
861
+ return replaceAction(state, action, appStore);
862
+ }
863
+ if (action.type === "replaceRoot") {
864
+ return walkTree(
865
+ state,
866
+ appStore.config,
867
+ (content) => content,
868
+ (childItem) => {
869
+ if (childItem.props.id === "root") {
870
+ return __spreadProps(__spreadValues({}, childItem), {
871
+ props: __spreadValues(__spreadValues({}, childItem.props), action.root.props),
872
+ readOnly: action.root.readOnly
873
+ });
874
+ }
875
+ return childItem;
876
+ }
877
+ );
642
878
  }
643
879
  if (action.type === "duplicate") {
644
880
  const item = getItem(
645
881
  { index: action.sourceIndex, zone: action.sourceZone },
646
- data
882
+ state
647
883
  );
884
+ const idsInPath = getIdsForParent(action.sourceZone, state);
648
885
  const newItem = __spreadProps(__spreadValues({}, item), {
649
886
  props: __spreadProps(__spreadValues({}, item.props), {
650
887
  id: generateId(item.type)
651
888
  })
652
889
  });
653
- const dataWithRelatedDuplicated = duplicateRelatedZones(
654
- item,
655
- data,
656
- newItem.props.id
890
+ const modified = walkTree(
891
+ state,
892
+ appStore.config,
893
+ (content, zoneCompound) => {
894
+ if (zoneCompound === action.sourceZone) {
895
+ return insert(content, action.sourceIndex + 1, item);
896
+ }
897
+ return content;
898
+ },
899
+ (childItem, path, index) => {
900
+ const zoneCompound = path[path.length - 1];
901
+ const parents = path.map((p) => p.split(":")[0]);
902
+ if (parents.indexOf(newItem.props.id) > -1) {
903
+ return __spreadProps(__spreadValues({}, childItem), {
904
+ props: __spreadProps(__spreadValues({}, childItem.props), {
905
+ id: generateId(childItem.type)
906
+ })
907
+ });
908
+ }
909
+ if (zoneCompound === action.sourceZone && index === action.sourceIndex + 1) {
910
+ return newItem;
911
+ }
912
+ const [sourceZoneParent] = action.sourceZone.split(":");
913
+ if (sourceZoneParent === childItem.props.id || idsInPath.indexOf(childItem.props.id) > -1) {
914
+ return childItem;
915
+ }
916
+ return null;
917
+ }
657
918
  );
658
- if (action.sourceZone === rootDroppableId) {
659
- return __spreadProps(__spreadValues({}, dataWithRelatedDuplicated), {
660
- content: insert(data.content, action.sourceIndex + 1, newItem)
661
- });
662
- }
663
- return __spreadProps(__spreadValues({}, dataWithRelatedDuplicated), {
664
- zones: __spreadProps(__spreadValues({}, dataWithRelatedDuplicated.zones), {
665
- [action.sourceZone]: insert(
666
- dataWithRelatedDuplicated.zones[action.sourceZone],
667
- action.sourceIndex + 1,
668
- newItem
669
- )
919
+ return __spreadProps(__spreadValues({}, modified), {
920
+ ui: __spreadProps(__spreadValues({}, modified.ui), {
921
+ itemSelector: {
922
+ index: action.sourceIndex + 1,
923
+ zone: action.sourceZone
924
+ }
670
925
  })
671
926
  });
672
927
  }
673
928
  if (action.type === "reorder") {
674
- return reorderAction(data, action);
675
- }
676
- if (action.type === "move") {
677
- if (action.sourceZone === action.destinationZone && action.sourceIndex === action.destinationIndex) {
678
- return data;
679
- }
680
- const newData = setupZone(
681
- setupZone(data, action.sourceZone),
682
- action.destinationZone
683
- );
684
- const item = getItem(
685
- { zone: action.sourceZone, index: action.sourceIndex },
686
- newData
929
+ return moveAction(
930
+ state,
931
+ {
932
+ type: "move",
933
+ sourceIndex: action.sourceIndex,
934
+ sourceZone: action.destinationZone,
935
+ destinationIndex: action.destinationIndex,
936
+ destinationZone: action.destinationZone
937
+ },
938
+ appStore
687
939
  );
688
- if (action.sourceZone === action.destinationZone) {
689
- return reorderAction(data, __spreadProps(__spreadValues({}, action), { type: "reorder" }));
690
- }
691
- if (action.sourceZone === rootDroppableId) {
692
- return __spreadProps(__spreadValues({}, newData), {
693
- content: remove(newData.content, action.sourceIndex),
694
- zones: __spreadProps(__spreadValues({}, newData.zones), {
695
- [action.destinationZone]: insert(
696
- newData.zones[action.destinationZone],
697
- action.destinationIndex,
698
- item
699
- )
700
- })
701
- });
702
- }
703
- if (action.destinationZone === rootDroppableId) {
704
- return __spreadProps(__spreadValues({}, newData), {
705
- content: insert(newData.content, action.destinationIndex, item),
706
- zones: __spreadProps(__spreadValues({}, newData.zones), {
707
- [action.sourceZone]: remove(
708
- newData.zones[action.sourceZone],
709
- action.sourceIndex
710
- )
711
- })
712
- });
713
- }
714
- return __spreadProps(__spreadValues({}, newData), {
715
- zones: __spreadProps(__spreadValues({}, newData.zones), {
716
- [action.sourceZone]: remove(
717
- newData.zones[action.sourceZone],
718
- action.sourceIndex
719
- ),
720
- [action.destinationZone]: insert(
721
- newData.zones[action.destinationZone],
722
- action.destinationIndex,
723
- item
724
- )
725
- })
726
- });
727
940
  }
728
- if (action.type === "replace") {
729
- return replaceAction(data, action);
941
+ if (action.type === "move") {
942
+ return moveAction(state, action, appStore);
730
943
  }
731
944
  if (action.type === "remove") {
732
- const item = getItem({ index: action.index, zone: action.zone }, data);
733
- const dataWithRelatedRemoved = setupZone(
734
- removeRelatedZones(item, data),
735
- action.zone
736
- );
737
- if (action.zone === rootDroppableId) {
738
- return __spreadProps(__spreadValues({}, dataWithRelatedRemoved), {
739
- content: remove(data.content, action.index)
740
- });
741
- }
742
- return __spreadProps(__spreadValues({}, dataWithRelatedRemoved), {
743
- zones: __spreadProps(__spreadValues({}, dataWithRelatedRemoved.zones), {
744
- [action.zone]: remove(
745
- dataWithRelatedRemoved.zones[action.zone],
746
- action.index
747
- )
748
- })
749
- });
945
+ return removeAction(state, action, appStore);
750
946
  }
751
947
  if (action.type === "registerZone") {
752
948
  if (zoneCache[action.zone]) {
753
- return __spreadProps(__spreadValues({}, data), {
754
- zones: __spreadProps(__spreadValues({}, data.zones), {
755
- [action.zone]: zoneCache[action.zone]
949
+ return __spreadProps(__spreadValues({}, state), {
950
+ data: __spreadProps(__spreadValues({}, state.data), {
951
+ zones: __spreadProps(__spreadValues({}, state.data.zones), {
952
+ [action.zone]: zoneCache[action.zone]
953
+ })
954
+ }),
955
+ indexes: __spreadProps(__spreadValues({}, state.indexes), {
956
+ zones: __spreadProps(__spreadValues({}, state.indexes.zones), {
957
+ [action.zone]: __spreadProps(__spreadValues({}, state.indexes.zones[action.zone]), {
958
+ contentIds: zoneCache[action.zone].map((item) => item.props.id),
959
+ type: "dropzone"
960
+ })
961
+ })
756
962
  })
757
963
  });
758
964
  }
759
- return setupZone(data, action.zone);
965
+ return __spreadProps(__spreadValues({}, state), { data: setupZone(state.data, action.zone) });
760
966
  }
761
967
  if (action.type === "unregisterZone") {
762
- const _zones = __spreadValues({}, data.zones || {});
968
+ const _zones = __spreadValues({}, state.data.zones || {});
969
+ const zoneIndex = __spreadValues({}, state.indexes.zones || {});
763
970
  if (_zones[action.zone]) {
764
971
  zoneCache[action.zone] = _zones[action.zone];
765
972
  delete _zones[action.zone];
766
973
  }
767
- return __spreadProps(__spreadValues({}, data), { zones: _zones });
974
+ delete zoneIndex[action.zone];
975
+ return __spreadProps(__spreadValues({}, state), {
976
+ data: __spreadProps(__spreadValues({}, state.data), {
977
+ zones: _zones
978
+ }),
979
+ indexes: __spreadProps(__spreadValues({}, state.indexes), {
980
+ zones: zoneIndex
981
+ })
982
+ });
768
983
  }
769
984
  if (action.type === "setData") {
770
985
  if (typeof action.data === "object") {
771
- return __spreadValues(__spreadValues({}, data), action.data);
986
+ console.warn(
987
+ "`setData` is expensive and may cause unnecessary re-renders. Consider using a more atomic action instead."
988
+ );
989
+ return walkTree(
990
+ __spreadProps(__spreadValues({}, state), {
991
+ data: __spreadValues(__spreadValues({}, state.data), action.data)
992
+ }),
993
+ appStore.config
994
+ );
772
995
  }
773
- return __spreadValues(__spreadValues({}, data), action.data(data));
996
+ return walkTree(
997
+ __spreadProps(__spreadValues({}, state), {
998
+ data: __spreadValues(__spreadValues({}, state.data), action.data(state.data))
999
+ }),
1000
+ appStore.config
1001
+ );
774
1002
  }
775
- return data;
776
- }
777
-
778
- // ../core/reducer/state.ts
779
- init_react_import();
780
- var reduceUi = (ui, action) => {
781
1003
  if (action.type === "setUi") {
782
1004
  if (typeof action.ui === "object") {
783
- return __spreadValues(__spreadValues({}, ui), action.ui);
1005
+ return __spreadProps(__spreadValues({}, state), {
1006
+ ui: __spreadValues(__spreadValues({}, state.ui), action.ui)
1007
+ });
784
1008
  }
785
- return __spreadValues(__spreadValues({}, ui), action.ui(ui));
786
- }
787
- if (action.type === "duplicate") {
788
- return __spreadProps(__spreadValues({}, ui), {
789
- itemSelector: { index: action.sourceIndex + 1, zone: action.sourceZone }
1009
+ return __spreadProps(__spreadValues({}, state), {
1010
+ ui: __spreadValues(__spreadValues({}, state.ui), action.ui(state.ui))
790
1011
  });
791
1012
  }
792
- if (action.type === "remove") {
793
- return __spreadProps(__spreadValues({}, ui), {
794
- itemSelector: null
795
- });
796
- }
797
- return ui;
798
- };
1013
+ return state;
1014
+ }
799
1015
 
800
1016
  // ../core/reducer/actions.tsx
801
1017
  init_react_import();
@@ -818,25 +1034,15 @@ function storeInterceptor(reducer, record, onAction) {
818
1034
  return newAppState;
819
1035
  };
820
1036
  }
821
- var setAction = (state, action) => {
822
- if (typeof action.state === "object") {
823
- return __spreadValues(__spreadValues({}, state), action.state);
824
- }
825
- return __spreadValues(__spreadValues({}, state), action.state(state));
826
- };
827
1037
  function createReducer({
828
- config,
829
1038
  record,
830
- onAction
1039
+ onAction,
1040
+ appStore
831
1041
  }) {
832
1042
  return storeInterceptor(
833
1043
  (state, action) => {
834
- const data = reduceData(state.data, action, config);
835
- const ui = reduceUi(state.ui, action);
836
- if (action.type === "set") {
837
- return setAction(state, action);
838
- }
839
- return { data, ui };
1044
+ const result = reduce(state, action, appStore);
1045
+ return result;
840
1046
  },
841
1047
  record,
842
1048
  onAction
@@ -856,11 +1062,11 @@ init_react_import();
856
1062
  var createStoreImpl = (createState) => {
857
1063
  let state;
858
1064
  const listeners = /* @__PURE__ */ new Set();
859
- const setState = (partial, replace2) => {
1065
+ const setState = (partial, replace) => {
860
1066
  const nextState = typeof partial === "function" ? partial(state) : partial;
861
1067
  if (!Object.is(nextState, state)) {
862
1068
  const previousState = state;
863
- state = (replace2 != null ? replace2 : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
1069
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
864
1070
  listeners.forEach((listener) => listener(state, previousState));
865
1071
  }
866
1072
  };
@@ -924,206 +1130,6 @@ var subscribeWithSelectorImpl = (fn) => (set, get, api) => {
924
1130
  };
925
1131
  var subscribeWithSelector = subscribeWithSelectorImpl;
926
1132
 
927
- // ../core/lib/resolve-data.ts
928
- init_react_import();
929
-
930
- // ../core/lib/resolve-component-data.ts
931
- init_react_import();
932
-
933
- // ../core/lib/get-changed.ts
934
- init_react_import();
935
- var getChanged = (newItem, oldItem) => {
936
- return newItem ? Object.keys(newItem.props || {}).reduce((acc, item) => {
937
- const newItemProps = (newItem == null ? void 0 : newItem.props) || {};
938
- const oldItemProps = (oldItem == null ? void 0 : oldItem.props) || {};
939
- return __spreadProps(__spreadValues({}, acc), {
940
- [item]: oldItemProps[item] !== newItemProps[item]
941
- });
942
- }, {}) : {};
943
- };
944
-
945
- // ../core/lib/resolve-component-data.ts
946
- var cache = { lastChange: {} };
947
- var resolveComponentData = (_0, _1, ..._2) => __async(void 0, [_0, _1, ..._2], function* (item, config, metadata = {}, onResolveStart, onResolveEnd) {
948
- const configForItem = config.components[item.type];
949
- if (configForItem.resolveData) {
950
- const { item: oldItem = null, resolved = {} } = cache.lastChange[item.props.id] || {};
951
- if (item && item === oldItem) {
952
- return resolved;
953
- }
954
- const changed = getChanged(item, oldItem);
955
- if (onResolveStart) {
956
- onResolveStart(item);
957
- }
958
- const { props: resolvedProps, readOnly = {} } = yield configForItem.resolveData(item, {
959
- changed,
960
- lastData: oldItem,
961
- metadata
962
- });
963
- const resolvedItem = __spreadProps(__spreadValues({}, item), {
964
- props: __spreadValues(__spreadValues({}, item.props), resolvedProps)
965
- });
966
- if (Object.keys(readOnly).length) {
967
- resolvedItem.readOnly = readOnly;
968
- }
969
- cache.lastChange[item.props.id] = {
970
- item,
971
- resolved: resolvedItem
972
- };
973
- if (onResolveEnd) {
974
- onResolveEnd(resolvedItem);
975
- }
976
- return resolvedItem;
977
- }
978
- return item;
979
- });
980
-
981
- // ../core/lib/apply-dynamic-props.ts
982
- init_react_import();
983
- var applyDynamicProps = (data, dynamicProps, rootData) => {
984
- return __spreadProps(__spreadValues({}, data), {
985
- root: rootData ? __spreadValues(__spreadValues({}, data.root), rootData ? rootData : {}) : data.root,
986
- content: data.content.map((item) => {
987
- return dynamicProps[item.props.id] ? __spreadValues(__spreadValues({}, item), dynamicProps[item.props.id]) : item;
988
- }),
989
- zones: Object.keys(data.zones || {}).reduce((acc, zoneKey) => {
990
- return __spreadProps(__spreadValues({}, acc), {
991
- [zoneKey]: data.zones[zoneKey].map((item) => {
992
- return dynamicProps[item.props.id] ? __spreadValues(__spreadValues({}, item), dynamicProps[item.props.id]) : item;
993
- })
994
- });
995
- }, {})
996
- });
997
- };
998
-
999
- // ../core/lib/resolve-root-data.ts
1000
- init_react_import();
1001
- var cache2 = {};
1002
- function resolveRootData(data, config, metadata) {
1003
- return __async(this, null, function* () {
1004
- var _a, _b, _c, _d, _e;
1005
- if (((_a = config.root) == null ? void 0 : _a.resolveData) && data.root.props) {
1006
- if (((_b = cache2.lastChange) == null ? void 0 : _b.original) === data.root) {
1007
- return cache2.lastChange.resolved;
1008
- }
1009
- const changed = getChanged(data.root, (_c = cache2.lastChange) == null ? void 0 : _c.original);
1010
- const rootWithProps = data.root;
1011
- const resolvedRoot = yield (_e = config.root) == null ? void 0 : _e.resolveData(rootWithProps, {
1012
- changed,
1013
- lastData: ((_d = cache2.lastChange) == null ? void 0 : _d.original) || {},
1014
- metadata: metadata || {}
1015
- });
1016
- cache2.lastChange = {
1017
- original: data.root,
1018
- resolved: resolvedRoot
1019
- };
1020
- return __spreadProps(__spreadValues(__spreadValues({}, data.root), resolvedRoot), {
1021
- props: __spreadValues(__spreadValues({}, data.root.props), resolvedRoot.props)
1022
- });
1023
- }
1024
- return data.root;
1025
- });
1026
- }
1027
-
1028
- // ../core/lib/flatten-data.ts
1029
- init_react_import();
1030
- var flattenData = (data) => {
1031
- return Object.keys(data.zones || {}).reduce(
1032
- (acc, zone) => [...acc, ...data.zones[zone]],
1033
- data.content
1034
- );
1035
- };
1036
-
1037
- // ../core/lib/resolve-data.ts
1038
- var import_fast_deep_equal = __toESM(require_fast_deep_equal());
1039
- var resolveData = (newAppState, appStoreData) => {
1040
- const {
1041
- state: appState,
1042
- config,
1043
- dispatch,
1044
- resolveDataRuns,
1045
- setComponentLoading,
1046
- unsetComponentLoading,
1047
- metadata,
1048
- permissions
1049
- } = appStoreData;
1050
- const deferredSetStates = {};
1051
- const _setComponentLoading = (id, loading, defer = 0) => {
1052
- if (deferredSetStates[id]) {
1053
- clearTimeout(deferredSetStates[id]);
1054
- delete deferredSetStates[id];
1055
- }
1056
- deferredSetStates[id] = setTimeout(() => {
1057
- if (loading) {
1058
- setComponentLoading(id);
1059
- } else {
1060
- unsetComponentLoading(id);
1061
- }
1062
- delete deferredSetStates[id];
1063
- }, defer);
1064
- };
1065
- const runResolvers = () => __async(void 0, null, function* () {
1066
- const newData = newAppState.data;
1067
- const flatContent = flattenData(newData).filter(
1068
- (item) => {
1069
- var _a;
1070
- return !!((_a = config.components[item.type]) == null ? void 0 : _a.resolveData);
1071
- }
1072
- );
1073
- const applyIfChange = (dynamicDataMap, dynamicRoot) => {
1074
- const processed = applyDynamicProps(
1075
- __spreadValues({}, appState.data),
1076
- dynamicDataMap,
1077
- dynamicRoot
1078
- );
1079
- const processedAppState = __spreadProps(__spreadValues({}, appState), { data: processed });
1080
- const containsChanges = !(0, import_fast_deep_equal.default)(appState, processedAppState);
1081
- if (containsChanges) {
1082
- dispatch({
1083
- type: "set",
1084
- state: (prev) => __spreadProps(__spreadValues({}, prev), {
1085
- data: applyDynamicProps(prev.data, dynamicDataMap, dynamicRoot),
1086
- ui: resolveDataRuns > 0 ? __spreadValues(__spreadValues({}, prev.ui), newAppState.ui) : prev.ui
1087
- }),
1088
- recordHistory: resolveDataRuns > 0
1089
- });
1090
- }
1091
- };
1092
- const promises = [];
1093
- promises.push(
1094
- (() => __async(void 0, null, function* () {
1095
- _setComponentLoading("puck-root", true, 50);
1096
- const dynamicRoot = yield resolveRootData(newData, config, metadata);
1097
- applyIfChange({}, dynamicRoot);
1098
- _setComponentLoading("puck-root", false);
1099
- }))()
1100
- );
1101
- flatContent.forEach((item) => {
1102
- promises.push(
1103
- (() => __async(void 0, null, function* () {
1104
- permissions.resolvePermissions({ item }, true);
1105
- const dynamicData = yield resolveComponentData(
1106
- item,
1107
- config,
1108
- metadata,
1109
- (item2) => {
1110
- _setComponentLoading(item2.props.id, true, 50);
1111
- },
1112
- (item2) => {
1113
- deferredSetStates[item2.props.id];
1114
- _setComponentLoading(item2.props.id, false);
1115
- }
1116
- );
1117
- const dynamicDataMap = { [item.props.id]: dynamicData };
1118
- applyIfChange(dynamicDataMap);
1119
- }))()
1120
- );
1121
- });
1122
- yield Promise.all(promises);
1123
- });
1124
- return runResolvers();
1125
- };
1126
-
1127
1133
  // ../core/store/index.ts
1128
1134
  import { createContext, useContext } from "react";
1129
1135
 
@@ -1241,31 +1247,14 @@ var createHistorySlice = (set, get) => {
1241
1247
 
1242
1248
  // ../core/store/slices/nodes.ts
1243
1249
  init_react_import();
1244
- var import_fast_deep_equal2 = __toESM(require_fast_deep_equal());
1245
- import { useEffect as useEffect3 } from "react";
1246
- var partialDeepEqual = (newItem, existingItem) => {
1247
- const filteredExistingItem = Object.keys(newItem).reduce(
1248
- (acc, key) => __spreadProps(__spreadValues({}, acc), { [key]: existingItem[key] }),
1249
- {}
1250
- );
1251
- return (0, import_fast_deep_equal2.default)(newItem, filteredExistingItem);
1252
- };
1253
1250
  var createNodesSlice = (set, get) => ({
1254
1251
  nodes: {},
1255
1252
  registerNode: (id, node) => {
1256
1253
  const s = get().nodes;
1257
- if (s.nodes[id] && partialDeepEqual(node, s.nodes[id])) {
1258
- return;
1259
- }
1260
1254
  const emptyNode = {
1261
1255
  id,
1262
1256
  methods: { sync: () => null },
1263
- data: { props: { id }, type: "unknown" },
1264
- parentId: "",
1265
- zone: "",
1266
- path: [],
1267
- element: null,
1268
- index: -1
1257
+ element: null
1269
1258
  };
1270
1259
  const existingNode = s.nodes[id];
1271
1260
  set({
@@ -1295,36 +1284,66 @@ var createNodesSlice = (set, get) => ({
1295
1284
 
1296
1285
  // ../core/store/slices/permissions.ts
1297
1286
  init_react_import();
1298
- import { useEffect as useEffect4 } from "react";
1287
+ import { useEffect as useEffect3 } from "react";
1288
+
1289
+ // ../core/lib/flatten-data.ts
1290
+ init_react_import();
1291
+ var flattenData = (state, config) => {
1292
+ const data = [];
1293
+ walkTree(
1294
+ state,
1295
+ config,
1296
+ (content) => content,
1297
+ (item) => {
1298
+ data.push(item);
1299
+ return null;
1300
+ }
1301
+ );
1302
+ return data;
1303
+ };
1304
+
1305
+ // ../core/lib/get-changed.ts
1306
+ init_react_import();
1307
+ var getChanged = (newItem, oldItem) => {
1308
+ return newItem ? Object.keys(newItem.props || {}).reduce((acc, item) => {
1309
+ const newItemProps = (newItem == null ? void 0 : newItem.props) || {};
1310
+ const oldItemProps = (oldItem == null ? void 0 : oldItem.props) || {};
1311
+ return __spreadProps(__spreadValues({}, acc), {
1312
+ [item]: oldItemProps[item] !== newItemProps[item]
1313
+ });
1314
+ }, {}) : {};
1315
+ };
1316
+
1317
+ // ../core/store/slices/permissions.ts
1299
1318
  var createPermissionsSlice = (set, get) => {
1300
1319
  const resolvePermissions = (..._0) => __async(void 0, [..._0], function* (params = {}, force) {
1301
- const { state, permissions } = get();
1302
- const { cache: cache3, globalPermissions } = permissions;
1320
+ const { state, permissions, config } = get();
1321
+ const { cache: cache2, globalPermissions } = permissions;
1303
1322
  const resolveDataForItem = (item2, force2 = false) => __async(void 0, null, function* () {
1304
1323
  var _a, _b, _c;
1305
1324
  const {
1306
- config,
1325
+ config: config2,
1307
1326
  state: appState,
1308
1327
  setComponentLoading,
1309
1328
  unsetComponentLoading
1310
1329
  } = get();
1311
- const componentConfig = item2.type === "root" ? config.root : config.components[item2.type];
1330
+ const componentConfig = item2.type === "root" ? config2.root : config2.components[item2.type];
1312
1331
  if (!componentConfig) {
1313
1332
  return;
1314
1333
  }
1315
1334
  const initialPermissions = __spreadValues(__spreadValues({}, globalPermissions), componentConfig.permissions);
1316
1335
  if (componentConfig.resolvePermissions) {
1317
- const changed = getChanged(item2, (_a = cache3[item2.props.id]) == null ? void 0 : _a.lastData);
1336
+ const changed = getChanged(item2, (_a = cache2[item2.props.id]) == null ? void 0 : _a.lastData);
1318
1337
  if (Object.values(changed).some((el) => el === true) || force2) {
1319
1338
  setComponentLoading(item2.props.id);
1320
1339
  const resolvedPermissions = yield componentConfig.resolvePermissions(
1321
1340
  item2,
1322
1341
  {
1323
1342
  changed,
1324
- lastPermissions: ((_b = cache3[item2.props.id]) == null ? void 0 : _b.lastPermissions) || null,
1343
+ lastPermissions: ((_b = cache2[item2.props.id]) == null ? void 0 : _b.lastPermissions) || null,
1325
1344
  permissions: initialPermissions,
1326
1345
  appState,
1327
- lastData: ((_c = cache3[item2.props.id]) == null ? void 0 : _c.lastData) || null
1346
+ lastData: ((_c = cache2[item2.props.id]) == null ? void 0 : _c.lastData) || null
1328
1347
  }
1329
1348
  );
1330
1349
  const latest = get().permissions;
@@ -1360,14 +1379,14 @@ var createPermissionsSlice = (set, get) => {
1360
1379
  if (item) {
1361
1380
  yield resolveDataForItem(item, force);
1362
1381
  } else if (type) {
1363
- flattenData(state.data).filter((item2) => item2.type === type).map((item2) => __async(void 0, null, function* () {
1382
+ flattenData(state, config).filter((item2) => item2.type === type).map((item2) => __async(void 0, null, function* () {
1364
1383
  yield resolveDataForItem(item2, force);
1365
1384
  }));
1366
1385
  } else if (root) {
1367
1386
  resolveDataForRoot(force);
1368
1387
  } else {
1369
1388
  resolveDataForRoot(force);
1370
- flattenData(state.data).map((item2) => __async(void 0, null, function* () {
1389
+ flattenData(state, config).map((item2) => __async(void 0, null, function* () {
1371
1390
  yield resolveDataForItem(item2, force);
1372
1391
  }));
1373
1392
  }
@@ -1409,8 +1428,8 @@ var createPermissionsSlice = (set, get) => {
1409
1428
 
1410
1429
  // ../core/store/slices/fields.ts
1411
1430
  init_react_import();
1412
- import { useCallback, useEffect as useEffect5 } from "react";
1413
- var createFieldsStore = (_set, _get) => {
1431
+ import { useCallback, useEffect as useEffect4 } from "react";
1432
+ var createFieldsSlice = (_set, _get) => {
1414
1433
  return {
1415
1434
  fields: {},
1416
1435
  loading: false,
@@ -1418,6 +1437,111 @@ var createFieldsStore = (_set, _get) => {
1418
1437
  };
1419
1438
  };
1420
1439
 
1440
+ // ../core/lib/resolve-component-data.ts
1441
+ init_react_import();
1442
+
1443
+ // ../core/lib/map-slots.ts
1444
+ init_react_import();
1445
+ function mapSlots(item, map, recursive = true, isSlot2) {
1446
+ return __async(this, null, function* () {
1447
+ const props = __spreadValues({}, item.props);
1448
+ yield forEachSlot(
1449
+ item,
1450
+ (_parentId, propName, content) => __async(this, null, function* () {
1451
+ const mappedContent = recursive ? yield Promise.all(
1452
+ content.map((item2) => __async(this, null, function* () {
1453
+ return yield mapSlots(item2, map, recursive, isSlot2);
1454
+ }))
1455
+ ) : content;
1456
+ props[propName] = yield map(mappedContent, propName);
1457
+ }),
1458
+ false,
1459
+ isSlot2
1460
+ );
1461
+ return __spreadProps(__spreadValues({}, item), { props });
1462
+ });
1463
+ }
1464
+
1465
+ // ../core/lib/resolve-component-data.ts
1466
+ var import_fast_deep_equal = __toESM(require_fast_deep_equal());
1467
+ var cache = { lastChange: {} };
1468
+ var resolveComponentData = (_0, _1, ..._2) => __async(void 0, [_0, _1, ..._2], function* (item, config, metadata = {}, onResolveStart, onResolveEnd, trigger = "replace", recursive = true) {
1469
+ const configForItem = "type" in item && item.type !== "root" ? config.components[item.type] : config.root;
1470
+ if ((configForItem == null ? void 0 : configForItem.resolveData) && item.props) {
1471
+ const id = "id" in item.props ? item.props.id : "root";
1472
+ const { item: oldItem = null, resolved = {} } = cache.lastChange[id] || {};
1473
+ if (item && (0, import_fast_deep_equal.default)(item, oldItem)) {
1474
+ return { node: resolved, didChange: false };
1475
+ }
1476
+ const changed = getChanged(item, oldItem);
1477
+ if (onResolveStart) {
1478
+ onResolveStart(item);
1479
+ }
1480
+ const { props: resolvedProps, readOnly = {} } = yield configForItem.resolveData(item, {
1481
+ changed,
1482
+ lastData: oldItem,
1483
+ metadata,
1484
+ trigger
1485
+ });
1486
+ let resolvedItem = __spreadProps(__spreadValues({}, item), {
1487
+ props: __spreadValues(__spreadValues({}, item.props), resolvedProps)
1488
+ });
1489
+ if (recursive) {
1490
+ resolvedItem = yield mapSlots(
1491
+ resolvedItem,
1492
+ (content) => __async(void 0, null, function* () {
1493
+ return Promise.all(
1494
+ content.map(
1495
+ (childItem) => __async(void 0, null, function* () {
1496
+ return (yield resolveComponentData(
1497
+ childItem,
1498
+ config,
1499
+ metadata,
1500
+ onResolveStart,
1501
+ onResolveEnd,
1502
+ trigger,
1503
+ false
1504
+ )).node;
1505
+ })
1506
+ )
1507
+ );
1508
+ }),
1509
+ false,
1510
+ createIsSlotConfig(config)
1511
+ );
1512
+ }
1513
+ if (Object.keys(readOnly).length) {
1514
+ resolvedItem.readOnly = readOnly;
1515
+ }
1516
+ cache.lastChange[id] = {
1517
+ item,
1518
+ resolved: resolvedItem
1519
+ };
1520
+ if (onResolveEnd) {
1521
+ onResolveEnd(resolvedItem);
1522
+ }
1523
+ return { node: resolvedItem, didChange: !(0, import_fast_deep_equal.default)(item, resolvedItem) };
1524
+ }
1525
+ return { node: item, didChange: false };
1526
+ });
1527
+
1528
+ // ../core/lib/to-root.ts
1529
+ init_react_import();
1530
+ var toRoot = (item) => {
1531
+ if ("type" in item && item.type !== "root") {
1532
+ throw new Error("Converting non-root item to root.");
1533
+ }
1534
+ const { readOnly } = item;
1535
+ if (item.props) {
1536
+ if ("id" in item.props) {
1537
+ const _a = item.props, { id } = _a, props = __objRest(_a, ["id"]);
1538
+ return { props, readOnly };
1539
+ }
1540
+ return { props: item.props, readOnly };
1541
+ }
1542
+ return { props: {}, readOnly };
1543
+ };
1544
+
1421
1545
  // ../core/store/index.ts
1422
1546
  var defaultAppState = {
1423
1547
  data: { content: [], root: {}, zones: {} },
@@ -1438,6 +1562,10 @@ var defaultAppState = {
1438
1562
  controlsVisible: true
1439
1563
  },
1440
1564
  field: { focus: null }
1565
+ },
1566
+ indexes: {
1567
+ nodes: {},
1568
+ zones: {}
1441
1569
  }
1442
1570
  };
1443
1571
  var defaultPageFields = {
@@ -1460,7 +1588,7 @@ var createAppStore = (initialAppStore) => create()(
1460
1588
  iframe: {},
1461
1589
  metadata: {}
1462
1590
  }, initialAppStore), {
1463
- fields: createFieldsStore(set, get),
1591
+ fields: createFieldsSlice(set, get),
1464
1592
  history: createHistorySlice(set, get),
1465
1593
  nodes: createNodesSlice(set, get),
1466
1594
  permissions: createPermissionsSlice(set, get),
@@ -1473,55 +1601,135 @@ var createAppStore = (initialAppStore) => create()(
1473
1601
  dispatch: (action) => set((s) => {
1474
1602
  var _a, _b;
1475
1603
  const { record } = get().history;
1476
- const dispatch = createReducer({ config: s.config, record });
1604
+ const dispatch = createReducer({
1605
+ record,
1606
+ appStore: s
1607
+ });
1477
1608
  const state = dispatch(s.state, action);
1478
- const selectedItem = state.ui.itemSelector ? getItem(state.ui.itemSelector, state.data) : null;
1609
+ const selectedItem = state.ui.itemSelector ? getItem(state.ui.itemSelector, state) : null;
1479
1610
  (_b = (_a = get()).onAction) == null ? void 0 : _b.call(_a, action, state, get().state);
1480
1611
  return __spreadProps(__spreadValues({}, s), { state, selectedItem });
1481
1612
  }),
1482
1613
  setZoomConfig: (zoomConfig) => set({ zoomConfig }),
1483
1614
  setStatus: (status) => set({ status }),
1484
1615
  setComponentState: (componentState) => set({ componentState }),
1485
- setComponentLoading: (id) => {
1486
- var _a;
1487
- const { setComponentState, componentState } = get();
1488
- setComponentState(__spreadProps(__spreadValues({}, componentState), {
1489
- [id]: __spreadProps(__spreadValues({}, componentState[id]), {
1490
- loadingCount: (((_a = componentState[id]) == null ? void 0 : _a.loadingCount) || 0) + 1
1616
+ pendingComponentLoads: {},
1617
+ setComponentLoading: (id, loading = true, defer = 0) => {
1618
+ const { setComponentState, pendingComponentLoads } = get();
1619
+ const thisPendingComponentLoads = __spreadValues({}, pendingComponentLoads);
1620
+ const setLoading = () => {
1621
+ var _a;
1622
+ const { componentState } = get();
1623
+ setComponentState(__spreadProps(__spreadValues({}, componentState), {
1624
+ [id]: __spreadProps(__spreadValues({}, componentState[id]), {
1625
+ loadingCount: (((_a = componentState[id]) == null ? void 0 : _a.loadingCount) || 0) + 1
1626
+ })
1627
+ }));
1628
+ };
1629
+ const unsetLoading = () => {
1630
+ var _a;
1631
+ const { componentState } = get();
1632
+ setComponentState(__spreadProps(__spreadValues({}, componentState), {
1633
+ [id]: __spreadProps(__spreadValues({}, componentState[id]), {
1634
+ loadingCount: Math.max(
1635
+ (((_a = componentState[id]) == null ? void 0 : _a.loadingCount) || 0) - 1,
1636
+ 0
1637
+ )
1638
+ })
1639
+ }));
1640
+ };
1641
+ if (thisPendingComponentLoads[id]) {
1642
+ clearTimeout(thisPendingComponentLoads[id]);
1643
+ delete thisPendingComponentLoads[id];
1644
+ set({ pendingComponentLoads: thisPendingComponentLoads });
1645
+ }
1646
+ const timeout = setTimeout(() => {
1647
+ if (loading) {
1648
+ setLoading();
1649
+ } else {
1650
+ unsetLoading();
1651
+ }
1652
+ delete thisPendingComponentLoads[id];
1653
+ set({ pendingComponentLoads: thisPendingComponentLoads });
1654
+ }, defer);
1655
+ set({
1656
+ pendingComponentLoads: __spreadProps(__spreadValues({}, thisPendingComponentLoads), {
1657
+ [id]: timeout
1491
1658
  })
1492
- }));
1659
+ });
1493
1660
  },
1494
1661
  unsetComponentLoading: (id) => {
1495
- var _a;
1496
- const { setComponentState, componentState } = get();
1497
- setComponentState(__spreadProps(__spreadValues({}, componentState), {
1498
- [id]: __spreadProps(__spreadValues({}, componentState[id]), {
1499
- loadingCount: Math.max(
1500
- (((_a = componentState[id]) == null ? void 0 : _a.loadingCount) || 0) - 1,
1501
- 0
1502
- )
1503
- })
1504
- }));
1662
+ const { setComponentLoading } = get();
1663
+ setComponentLoading(id, false);
1505
1664
  },
1506
1665
  // Helper
1507
1666
  setUi: (ui, recordHistory) => set((s) => {
1508
1667
  const dispatch = createReducer({
1509
- config: s.config,
1510
1668
  record: () => {
1511
- }
1669
+ },
1670
+ appStore: s
1512
1671
  });
1513
1672
  const state = dispatch(s.state, {
1514
1673
  type: "setUi",
1515
1674
  ui,
1516
1675
  recordHistory
1517
1676
  });
1518
- const selectedItem = state.ui.itemSelector ? getItem(state.ui.itemSelector, state.data) : null;
1677
+ const selectedItem = state.ui.itemSelector ? getItem(state.ui.itemSelector, state) : null;
1519
1678
  return __spreadProps(__spreadValues({}, s), { state, selectedItem });
1520
1679
  }),
1521
- resolveDataRuns: 0,
1522
- resolveData: (newAppState) => set((s) => {
1523
- resolveData(newAppState, get());
1524
- return __spreadProps(__spreadValues({}, s), { resolveDataRuns: s.resolveDataRuns + 1 });
1680
+ resolveComponentData: (componentData, trigger) => __async(void 0, null, function* () {
1681
+ const { config, metadata, setComponentLoading } = get();
1682
+ return yield resolveComponentData(
1683
+ componentData,
1684
+ config,
1685
+ metadata,
1686
+ (item) => setComponentLoading(
1687
+ "id" in item.props ? item.props.id : "root",
1688
+ true,
1689
+ 50
1690
+ ),
1691
+ (item) => setComponentLoading(
1692
+ "id" in item.props ? item.props.id : "root",
1693
+ false,
1694
+ 0
1695
+ ),
1696
+ trigger
1697
+ );
1698
+ }),
1699
+ resolveAndCommitData: () => __async(void 0, null, function* () {
1700
+ const { config, state, dispatch, resolveComponentData: resolveComponentData2 } = get();
1701
+ walkTree(
1702
+ state,
1703
+ config,
1704
+ (content) => content,
1705
+ (childItem) => {
1706
+ resolveComponentData2(childItem, "load").then((resolved) => {
1707
+ const { state: state2 } = get();
1708
+ const node = state2.indexes.nodes[resolved.node.props.id];
1709
+ if (node && resolved.didChange) {
1710
+ if (resolved.node.props.id === "root") {
1711
+ dispatch({
1712
+ type: "replaceRoot",
1713
+ root: toRoot(resolved.node)
1714
+ });
1715
+ } else {
1716
+ const zoneCompound = `${node.parentId}:${node.zone}`;
1717
+ const parentZone = state2.indexes.zones[zoneCompound];
1718
+ const index = parentZone.contentIds.indexOf(
1719
+ resolved.node.props.id
1720
+ );
1721
+ dispatch({
1722
+ type: "replace",
1723
+ data: resolved.node,
1724
+ destinationIndex: index,
1725
+ destinationZone: zoneCompound
1726
+ });
1727
+ }
1728
+ }
1729
+ });
1730
+ return childItem;
1731
+ }
1732
+ );
1525
1733
  })
1526
1734
  }))
1527
1735
  );
@@ -1543,12 +1751,12 @@ var useBreadcrumbs = (renderCount) => {
1543
1751
  const config = useAppStore((s) => s.config);
1544
1752
  const path = useAppStore((s) => {
1545
1753
  var _a;
1546
- return (_a = s.nodes.nodes[selectedId]) == null ? void 0 : _a.path;
1754
+ return (_a = s.state.indexes.nodes[selectedId]) == null ? void 0 : _a.path;
1547
1755
  });
1548
1756
  const appStore = useAppStoreApi();
1549
1757
  return useMemo(() => {
1550
1758
  const breadcrumbs = (path == null ? void 0 : path.map((zoneCompound) => {
1551
- var _a, _b;
1759
+ var _a, _b, _c;
1552
1760
  const [componentId] = zoneCompound.split(":");
1553
1761
  if (componentId === "root") {
1554
1762
  return {
@@ -1556,12 +1764,15 @@ var useBreadcrumbs = (renderCount) => {
1556
1764
  selector: null
1557
1765
  };
1558
1766
  }
1559
- const node = appStore.getState().nodes.nodes[componentId];
1560
- const label = node ? (_b = (_a = config.components[node.data.type]) == null ? void 0 : _a.label) != null ? _b : node.data.type : "Component";
1767
+ const node = appStore.getState().state.indexes.nodes[componentId];
1768
+ const parentId = node.path[node.path.length - 1];
1769
+ const contentIds = ((_a = appStore.getState().state.indexes.zones[parentId]) == null ? void 0 : _a.contentIds) || [];
1770
+ const index = contentIds.indexOf(componentId);
1771
+ const label = node ? (_c = (_b = config.components[node.data.type]) == null ? void 0 : _b.label) != null ? _c : node.data.type : "Component";
1561
1772
  return {
1562
1773
  label,
1563
1774
  selector: node ? {
1564
- index: node.index,
1775
+ index,
1565
1776
  zone: node.path[node.path.length - 1]
1566
1777
  } : null
1567
1778
  };
@@ -1582,6 +1793,12 @@ init_react_import();
1582
1793
  // ../core/lib/filter.ts
1583
1794
  init_react_import();
1584
1795
 
1796
+ // ../core/lib/reorder.ts
1797
+ init_react_import();
1798
+
1799
+ // ../core/lib/replace.ts
1800
+ init_react_import();
1801
+
1585
1802
  // css-module:/home/runner/work/puck/puck/packages/core/components/Loader/styles.module.css#css-module
1586
1803
  init_react_import();
1587
1804
  var styles_module_default3 = { "Loader": "_Loader_nacdm_13", "loader-animation": "_loader-animation_nacdm_1" };
@@ -1763,7 +1980,7 @@ var usePuck = createUsePuck();
1763
1980
  var HeadingAnalyzer = () => {
1764
1981
  const data = usePuck((s) => s.appState.data);
1765
1982
  const [hierarchy, setHierarchy] = useState([]);
1766
- useEffect6(() => {
1983
+ useEffect5(() => {
1767
1984
  const frame = getFrame();
1768
1985
  const entry = frame == null ? void 0 : frame.querySelector(`[data-puck-entry]`);
1769
1986
  if (!entry) return;