@measured/puck-plugin-heading-analyzer 0.19.0-canary.cc5dc01 → 0.19.0-canary.d9be813b

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