@superblocksteam/library 2.0.37-next.41 → 2.0.37-next.42

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
@@ -2061,6 +2061,7 @@ const InternalStack = observer(({ direction = "column", spacing: spacing$1, chil
2061
2061
  return /* @__PURE__ */ jsx("div", {
2062
2062
  className: combinedClassName,
2063
2063
  ...rest,
2064
+ ref: props.dropTargetRef,
2064
2065
  children
2065
2066
  });
2066
2067
  });
@@ -3242,10 +3243,13 @@ const getWidgetNode = (instanceId) => {
3242
3243
  const type = root_store_default.nameManager.getExistingIdentifier(instanceId)?.type;
3243
3244
  return document?.querySelector(`[data-sb-selector="${getEditWrapperIdWithType(instanceId, type)}"]`);
3244
3245
  };
3245
- const getIsComponentInInteractionLayer = (instanceId) => {
3246
+ const doesInteractionLayerContainInstance = (possibleParent, possibleChild) => {
3247
+ if (!possibleParent || !possibleChild) return false;
3246
3248
  const editStore = getEditStore();
3247
- const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
3248
- return !activeRootInstanceId || instanceId && (instanceId === activeRootInstanceId || editStore.runtimeEntitiesManager.isChildOf(instanceId, activeRootInstanceId));
3249
+ const parentMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(possibleParent);
3250
+ const childMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(possibleChild);
3251
+ if (editStore.interactionLayerManager.interactionLayerInstanceIds.has(possibleParent)) return possibleChild === possibleParent || childMeta?.interactionLayerInstanceId === possibleParent;
3252
+ return parentMeta?.interactionLayerInstanceId === childMeta?.interactionLayerInstanceId;
3249
3253
  };
3250
3254
 
3251
3255
  //#endregion
@@ -3267,7 +3271,29 @@ function rule(description, restriction) {
3267
3271
  restriction
3268
3272
  };
3269
3273
  }
3270
- const restrictions = [
3274
+ const instanceRestrictions = [
3275
+ rule("Drop target and dragged instance must be in the same interaction layer", ({ dropTargetInstanceId, draggedInstanceId, isDraggingNewComponent }) => {
3276
+ if (isDraggingNewComponent || !draggedInstanceId) return false;
3277
+ return !doesInteractionLayerContainInstance(dropTargetInstanceId, draggedInstanceId);
3278
+ }),
3279
+ rule("Dragged instance must not be a child of the drop target", ({ dropTargetInstanceId, draggedInstanceId }) => {
3280
+ if (!dropTargetInstanceId || !draggedInstanceId) return false;
3281
+ return getEditStore().runtimeEntitiesManager.isChildOf(dropTargetInstanceId, draggedInstanceId);
3282
+ }),
3283
+ rule("If the dragged instance has local bindings, it must share its root instance with the drop target", ({ dropTargetInstanceId, draggedInstanceId }) => {
3284
+ if (!dropTargetInstanceId || !draggedInstanceId) return false;
3285
+ const editStore = getEditStore();
3286
+ if (!(draggedInstanceId && editStore.runtimeEntitiesManager.doesEntityHaveLocalBindings(draggedInstanceId))) return false;
3287
+ const dropTargetMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(dropTargetInstanceId);
3288
+ const draggedMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedInstanceId);
3289
+ if (dropTargetMeta?.isRoot) return dropTargetMeta.instanceId !== draggedMeta?.rootInstanceId;
3290
+ else return dropTargetMeta?.rootInstanceId !== draggedMeta?.rootInstanceId;
3291
+ })
3292
+ ];
3293
+ const areDragAndDropInstancesValid = (params) => {
3294
+ return instanceRestrictions.find((restriction) => restriction.restriction(params)) == null;
3295
+ };
3296
+ const typeRestrictions = [
3271
3297
  rule("Draggable type must be draggable", ({ draggedType, isDraggingNewComponent }) => !isDraggingNewComponent && !isTypeDraggable(draggedType)),
3272
3298
  rule("Drop target type must be droppable", ({ dropTargetType }) => !isTypeDroppable(dropTargetType)),
3273
3299
  rule("Only containers can be dropped on non empty pages", ({ draggedType, dropTargetType, dropTargetEmpty }) => {
@@ -3275,7 +3301,7 @@ const restrictions = [
3275
3301
  })
3276
3302
  ];
3277
3303
  const isDragAndDropTypeValid = ({ draggedType, dropTargetType, dropTargetEmpty, isDraggingNewComponent }) => {
3278
- return restrictions.find((restriction) => restriction.restriction({
3304
+ return typeRestrictions.find((restriction) => restriction.restriction({
3279
3305
  draggedType,
3280
3306
  dropTargetType,
3281
3307
  dropTargetEmpty,
@@ -3298,23 +3324,6 @@ const isContentDraggable = (type) => {
3298
3324
  if (!isTypeDraggable(type)) return false;
3299
3325
  return root_store_default.componentRegistry.getEditorConfig(type)?.isContentDraggable !== false;
3300
3326
  };
3301
- /**
3302
- * TODO - should use the EditorConfig to determine if the created/dropped component should be wrapped.
3303
- * @param type - the type of the component being created
3304
- * @param parentType - the type of the parent component
3305
- * @returns
3306
- * - [false] if the component should not be wrapped
3307
- * - [true, wrapInType] if the component should be wrapped in the given type
3308
- */
3309
- function shouldWrapComponent(type, parentType) {
3310
- if (isComponentTypeDetached(type)) return [false];
3311
- if (!parentType) return [false];
3312
- if (parentType.includes("Modal") || parentType.includes("Slideout") || parentType.includes("Sheet") || parentType.includes("Dialog") || parentType === NATIVE_COMPONENT_TYPES.Page) {
3313
- if (root_store_default.componentRegistry.containerTypes.has(type)) return [false];
3314
- return [true, root_store_default.componentRegistry.defaultTagNames.container];
3315
- }
3316
- return [false];
3317
- }
3318
3327
  const filterSafeStackDimensionProperties = (existingProps) => {
3319
3328
  const { width, height, size: size$1 } = existingProps;
3320
3329
  const safeDimensions = {};
@@ -3368,13 +3377,13 @@ const DroppableWidget = observer((props) => {
3368
3377
  const widgetNode = useWidgetNodeRef(props.instanceId);
3369
3378
  useEffect(() => {
3370
3379
  let targetNode = null;
3371
- if (props.dropTargetRef?.current) targetNode = props.dropTargetRef.current;
3380
+ if (props.dropTargetElem) targetNode = props.dropTargetElem;
3372
3381
  else if (widgetNode) targetNode = widgetNode;
3373
3382
  if (targetNode) setDroppableNodeRef(targetNode);
3374
3383
  }, [
3375
3384
  widgetNode,
3376
3385
  setDroppableNodeRef,
3377
- props.dropTargetRef
3386
+ props.dropTargetElem
3378
3387
  ]);
3379
3388
  return /* @__PURE__ */ jsx(React.Fragment, { children: props.children });
3380
3389
  });
@@ -3442,6 +3451,28 @@ function ParentIdentifierProvider({ identifier, children }) {
3442
3451
  });
3443
3452
  }
3444
3453
 
3454
+ //#endregion
3455
+ //#region src/edit-mode/interaction-layer/interaction-context.tsx
3456
+ const defaultContext = { rootInstanceId: void 0 };
3457
+ const InteractionLayerContext = createContext(void 0);
3458
+ const useInteractionLayerContext = () => {
3459
+ return useContext(InteractionLayerContext) ?? defaultContext;
3460
+ };
3461
+ const InteractionLayerProvider = (props) => {
3462
+ const context$1 = useMemo(() => ({ rootInstanceId: props.instanceId }), [props.instanceId]);
3463
+ useEffect(() => {
3464
+ const editStore = getEditStore();
3465
+ editStore.interactionLayerManager.addInteractionLayerInstanceId(props.instanceId);
3466
+ return () => {
3467
+ editStore.interactionLayerManager.removeInteractionLayerInstanceId(props.instanceId);
3468
+ };
3469
+ }, [props.instanceId]);
3470
+ return /* @__PURE__ */ jsx(InteractionLayerContext.Provider, {
3471
+ value: context$1,
3472
+ children: props.children
3473
+ });
3474
+ };
3475
+
3445
3476
  //#endregion
3446
3477
  //#region src/lib/internal-details/lib/throttle.ts
3447
3478
  function throttle$1(func, delay) {
@@ -3475,413 +3506,6 @@ const CANVAS_ROOT_ID = "canvas-root";
3475
3506
  const PORTAL_ROOT_ID = "portal-root";
3476
3507
  const POPOVER_ROOT_ID = "sb-popover-root";
3477
3508
 
3478
- //#endregion
3479
- //#region src/edit-mode/dnd/is-nestable.ts
3480
- function isNestable(componentType, _parentType) {
3481
- if (componentType === PAGE_COMPONENT_TYPE) return false;
3482
- return true;
3483
- }
3484
-
3485
- //#endregion
3486
- //#region src/edit-mode/create-component.ts
3487
- function getParentInfo(parent) {
3488
- return { type: getEditStore().runtimeEntitiesManager.getAnyEditorWidgetMeta(parent.id)?.type };
3489
- }
3490
- const generateUniqueName = (componentType) => {
3491
- const baseName = componentType;
3492
- let counter = 1;
3493
- let name = `${baseName}${counter}`;
3494
- while (root_store_default.nameManager.hasEntityWithName(name)) {
3495
- counter++;
3496
- name = `${baseName}${counter}`;
3497
- }
3498
- return name;
3499
- };
3500
- function getBinding({ componentType, editorTemplateCreateRequest }) {
3501
- if (editorTemplateCreateRequest?.generateBinding === true) return Property$1.Static(generateUniqueName(componentType));
3502
- else if (typeof editorTemplateCreateRequest?.generateBinding === "string") return Property$1.Static(editorTemplateCreateRequest.generateBinding);
3503
- else return;
3504
- }
3505
- function getComponentBaseProperties(componentType, _parentInfo, editorTemplateCreateRequest) {
3506
- let properties = {};
3507
- const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
3508
- if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
3509
- if (editorTemplateCreateRequest?.properties) properties = {
3510
- ...properties,
3511
- ...editorTemplateCreateRequest.properties
3512
- };
3513
- const binding = getBinding({
3514
- componentType,
3515
- editorTemplateCreateRequest
3516
- });
3517
- if (binding) properties.name = binding;
3518
- const { width, height, size: size$1 } = properties;
3519
- const safeDimensions = filterSafeStackDimensionProperties({
3520
- width: width?.value,
3521
- height: height?.value,
3522
- size: size$1?.value
3523
- });
3524
- return {
3525
- properties: {
3526
- ...properties,
3527
- ...safeDimensions
3528
- },
3529
- children: editorTemplateCreateRequest?.children ?? []
3530
- };
3531
- }
3532
- function getCreateAtParentElement(relativeParent, createAt) {
3533
- if (createAt === "root") {
3534
- const parentInstanceId = getEditStore().runtimeEntitiesManager.widgets.getAnyInstanceIdForSourceId(relativeParent.id);
3535
- const pageComponent = getEditStore().runtimeEntitiesManager.getClosestAncestorByType(parentInstanceId, "Page");
3536
- if (!pageComponent) throw new Error(`Page component not found for parent: ${relativeParent.id}`);
3537
- return { source: { id: pageComponent.sourceId } };
3538
- } else return { source: relativeParent };
3539
- }
3540
- async function createComponent({ componentType, parent, scopeName, baseProperties = {}, skipSecondaryComponentsCreation, otherComponentsUpdates }) {
3541
- const parentInfo = getParentInfo(parent);
3542
- if (!isNestable(componentType, parentInfo.type)) {
3543
- console.error(`${componentType} cannot be nested under ${parentInfo.type}`);
3544
- return;
3545
- }
3546
- const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
3547
- if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
3548
- const context$1 = {
3549
- generateUniqueName,
3550
- parentInfo,
3551
- defaultTagNames: root_store_default.componentRegistry.defaultTagNames,
3552
- selfTagName: componentType
3553
- };
3554
- const editorTemplateCreateRequest = editorTemplates?.[0]?.create?.(context$1);
3555
- const primaryEditorTemplateCreateRequest = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest[0] : editorTemplateCreateRequest;
3556
- if (editorTemplateCreateRequest && primaryEditorTemplateCreateRequest?.type !== componentType) throw new Error(`When defining a ${Array.isArray(editorTemplateCreateRequest) ? "multiple" : "single"} component to be created on an EditorTemplate, the type must match with the component being created. got: ${primaryEditorTemplateCreateRequest?.type} when it should have been ${componentType}`);
3557
- const editorTemplateCreateRequests = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest : [editorTemplateCreateRequest];
3558
- const editStore = getEditStore();
3559
- function editorTemplateCreateRequestToInternalCreateRequest({ editorTemplateCreateRequest: editorTemplateCreateRequest$1, baseProperties: baseProperties$1 }) {
3560
- const type = editorTemplateCreateRequest$1?.type ?? componentType;
3561
- const [shouldWrap, wrapInType] = shouldWrapComponent(type, parentInfo.type);
3562
- const { properties: propertiesFromType, children } = getComponentBaseProperties(type, parentInfo, editorTemplateCreateRequest$1);
3563
- const properties = {
3564
- ...propertiesFromType,
3565
- ...baseProperties$1
3566
- };
3567
- let primaryComponent = {
3568
- parentElement: getCreateAtParentElement(parent, editorTemplateCreateRequest$1?.createAt),
3569
- tagName: type,
3570
- properties,
3571
- children,
3572
- scopeName,
3573
- id: editStore.operationManager.generateSourceId()
3574
- };
3575
- if (shouldWrap) primaryComponent = wrapComponentIfNecessary(primaryComponent, wrapInType);
3576
- return primaryComponent;
3577
- }
3578
- const createRequests = editorTemplateCreateRequests.map((editorTemplateCreateRequest$1, index) => editorTemplateCreateRequestToInternalCreateRequest({
3579
- editorTemplateCreateRequest: editorTemplateCreateRequest$1,
3580
- baseProperties: index === 0 ? baseProperties : {}
3581
- }));
3582
- const hasOtherComponentsUpdates = otherComponentsUpdates && Object.keys(otherComponentsUpdates).length > 0;
3583
- const hasMultipleCreateComponents = editorTemplateCreateRequests.length > 1 && !skipSecondaryComponentsCreation;
3584
- if (hasOtherComponentsUpdates || hasMultipleCreateComponents) {
3585
- const performOtherComponentsUpdates = (otherComponentsUpdates$1) => {
3586
- Object.entries(otherComponentsUpdates$1).forEach(([sourceId, updates]) => {
3587
- editStore.operationManager.setWidgetProperties({
3588
- sourceId,
3589
- properties: updates
3590
- });
3591
- });
3592
- };
3593
- editStore.operationManager.batchUpdate(() => {
3594
- if (skipSecondaryComponentsCreation) editStore.operationManager.createComponent(createRequests[0]);
3595
- else createRequests.forEach((createRequest) => {
3596
- editStore.operationManager.createComponent(createRequest);
3597
- });
3598
- if (hasOtherComponentsUpdates) performOtherComponentsUpdates(otherComponentsUpdates);
3599
- });
3600
- } else editStore.operationManager.createComponent(createRequests[0]);
3601
- /**
3602
- * Returns the single id, or the the last component if there are multiple.
3603
- * See EditorTemplate's definition to understand why.
3604
- */
3605
- return createRequests.at(-1).id;
3606
- }
3607
- function wrapComponentIfNecessary(primaryComponent, wrapInType) {
3608
- if (!wrapInType) return primaryComponent;
3609
- const { properties } = getComponentBaseProperties(wrapInType, { type: "Page" });
3610
- const [_$1, continueWrappingInType] = shouldWrapComponent(primaryComponent.tagName, wrapInType);
3611
- return {
3612
- parentElement: primaryComponent.parentElement,
3613
- tagName: wrapInType,
3614
- id: getEditStore().operationManager.generateSourceId(),
3615
- properties,
3616
- children: [wrapComponentIfNecessary(primaryComponent, continueWrappingInType)]
3617
- };
3618
- }
3619
-
3620
- //#endregion
3621
- //#region src/edit-mode/dnd/handle-stack-drop.ts
3622
- const mergeDroppedDimensions = (draggedType, draggedProps, activeDragRect) => {
3623
- const safeExistingDimensions = filterSafeStackDimensionProperties({
3624
- width: draggedProps?.width,
3625
- height: draggedProps?.height,
3626
- size: draggedProps?.size
3627
- });
3628
- const width = safeExistingDimensions.width;
3629
- const height = safeExistingDimensions.height;
3630
- if (draggedType === "Icon") return { size: safeExistingDimensions.size ?? (activeDragRect?.height ? Property$1.Dimension(Dim$1.px(activeDragRect.height)) : Property$1.Static("")) };
3631
- return {
3632
- width,
3633
- height
3634
- };
3635
- };
3636
- const handleStackDropWithinCanvas = (params) => {
3637
- const { dropInfo, draggedId, dropTargetId } = params;
3638
- const editStore = getEditStore();
3639
- const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
3640
- const draggedSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(draggedId);
3641
- if (!dropSourceId || !draggedSourceId) throw new Error(`Missing IDs: dragging ${draggedId} to ${dropTargetId}`);
3642
- console.log(`Dragged ${draggedSourceId} to ${dropSourceId}`, {
3643
- dropInfo,
3644
- index: dropInfo.insertionIndex
3645
- });
3646
- if (dropInfo.noopDrop) return;
3647
- const draggedType = editStore.runtimeEntitiesManager.getEditorWidgetType(draggedId);
3648
- const dropTargetType = editStore.runtimeEntitiesManager.getEditorWidgetType(dropTargetId);
3649
- if (!draggedType) throw new Error(`Missing dragged type: ${draggedId}`);
3650
- const [shouldWrap, wrapInType] = shouldWrapComponent(draggedType, dropTargetType);
3651
- const activeDragRect = editStore.ui.dnd.activeDragRect;
3652
- if (shouldWrap) dropComponentAndWrap({
3653
- draggedId,
3654
- draggedSourceId,
3655
- dropTargetId,
3656
- dropSourceId,
3657
- dropInfo,
3658
- dropTargetType,
3659
- activeDragRect,
3660
- wrapInType
3661
- });
3662
- else {
3663
- const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
3664
- editStore.operationManager.dropComponent({
3665
- from: { source: { id: draggedSourceId } },
3666
- to: { source: {
3667
- id: dropSourceId,
3668
- index: dropInfo.insertionIndex
3669
- } },
3670
- propsToChange: { ...mergeDroppedDimensions(draggedType, draggedProps, activeDragRect) }
3671
- });
3672
- }
3673
- };
3674
- const dropComponentAndWrap = async (params) => {
3675
- const { draggedId, draggedSourceId, dropSourceId, dropTargetId, dropInfo, dropTargetType, activeDragRect, wrapInType } = params;
3676
- const editStore = getEditStore();
3677
- const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
3678
- if (!dropScopeId) throw new Error(`Missing drop scope id: ${dropTargetId}`);
3679
- const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
3680
- const newComponentSourceId = await createComponent({
3681
- componentType: wrapInType,
3682
- parent: {
3683
- index: dropInfo.insertionIndex,
3684
- id: dropSourceId
3685
- },
3686
- scopeName
3687
- });
3688
- if (!newComponentSourceId) throw new Error("Missing new component source id");
3689
- const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
3690
- editStore.operationManager.dropComponent({
3691
- from: { source: { id: draggedSourceId } },
3692
- to: { source: {
3693
- id: newComponentSourceId,
3694
- index: 0
3695
- } },
3696
- propsToChange: { ...mergeDroppedDimensions(dropTargetType, draggedProps, activeDragRect) }
3697
- });
3698
- };
3699
- const handleStackDropForNewComponent = ({ componentType, dropInfo, dropTargetId }) => {
3700
- const editStore = getEditStore();
3701
- const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
3702
- const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
3703
- if (!dropSourceId || !dropScopeId) throw new Error("Missing drop source id");
3704
- const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
3705
- return createComponent({
3706
- componentType,
3707
- parent: {
3708
- index: dropInfo.insertionIndex,
3709
- id: dropSourceId
3710
- },
3711
- scopeName
3712
- });
3713
- };
3714
- const handleStackDrop = async ({ dropInfo, draggedId, dropTargetId, isDraggingNewComponent, newComponentType }) => {
3715
- if (dropInfo.insertionIndex == null) throw new Error("No insertion index found");
3716
- if (isDraggingNewComponent) {
3717
- if (!newComponentType) throw new Error("Missing componentType to create new component");
3718
- return handleStackDropForNewComponent({
3719
- componentType: newComponentType,
3720
- dropTargetId,
3721
- dropInfo
3722
- });
3723
- } else {
3724
- if (!draggedId) throw new Error("Missing dragged id");
3725
- handleStackDropWithinCanvas({
3726
- dropInfo,
3727
- draggedId,
3728
- dropTargetId
3729
- });
3730
- }
3731
- };
3732
-
3733
- //#endregion
3734
- //#region src/edit-mode/dnd/hooks/use-handle-dnd-events.ts
3735
- const measureRect = (id) => {
3736
- const rect = id ? getBoundingBoxForWidget(id) : null;
3737
- if (!rect) return null;
3738
- return {
3739
- left: rect.left,
3740
- top: rect.top,
3741
- right: rect.right,
3742
- bottom: rect.bottom,
3743
- width: rect.width,
3744
- height: rect.height
3745
- };
3746
- };
3747
- /**
3748
- * We have to follow a few rules while drag and dropping:
3749
- * 1. You can drag and drop within your own function component/scope
3750
- * 2. You can drag to another function component, but only if it doesn't break references to local variables in the current function component
3751
- * > a. If the reference is to some SB state, and you are in the same scope, you can drag to another function component and we will update the reference to the SB state
3752
- * @param overSourceId the widget ID we are currently dragging over
3753
- * @param overRootId the root ID (which could be the same as the widget ID) that we are dragging over, for example dragging over a container in another function component
3754
- * @returns true if the drop target is invalid
3755
- */
3756
- const isInvalidDropTarget = (overInstanceId, overRootInstanceId) => {
3757
- const activeRootInstanceIds = getEditStore().ui.dnd.validRootIds;
3758
- return Boolean(activeRootInstanceIds && !activeRootInstanceIds.includes(overInstanceId) && !activeRootInstanceIds.includes(overRootInstanceId)) || isDroppingOnAncestor(overInstanceId);
3759
- };
3760
- const isDroppingOnAncestor = (overInstanceId) => {
3761
- if (overInstanceId) {
3762
- const editStore = getEditStore();
3763
- const ancestorIds = /* @__PURE__ */ new Set();
3764
- let currentId = overInstanceId;
3765
- let iterations = 0;
3766
- const MAX_ITERATIONS$1 = 1e3;
3767
- while (currentId && iterations < MAX_ITERATIONS$1) {
3768
- const entity = editStore.runtimeEntitiesManager.getEditorWidgetMeta(currentId);
3769
- if (entity?.parentInstanceId) {
3770
- ancestorIds.add(entity.parentInstanceId);
3771
- currentId = entity.parentInstanceId;
3772
- } else break;
3773
- iterations++;
3774
- }
3775
- return Array.from(ancestorIds).some((id) => editStore.ui.isInstanceSelected(id));
3776
- }
3777
- return false;
3778
- };
3779
- const useHandleDnDEvents = () => {
3780
- const setActiveDragRect = useMemo(() => {
3781
- const editStore = getEditStore();
3782
- const throttled = throttle((rect) => {
3783
- editStore.ui.dnd.setActiveDragRect(rect);
3784
- }, 10, {
3785
- leading: true,
3786
- trailing: true
3787
- });
3788
- return (val) => {
3789
- throttled(val);
3790
- };
3791
- }, []);
3792
- const setActiveTargetInfo = useMemo(() => {
3793
- const editStore = getEditStore();
3794
- const throttled = throttle((id, rect) => {
3795
- editStore.ui.dnd.setDropTargetId(id);
3796
- editStore.ui.dnd.setActiveTargetRect(rect);
3797
- }, 10, {
3798
- leading: true,
3799
- trailing: true
3800
- });
3801
- return (id, val) => {
3802
- throttled(id, val);
3803
- };
3804
- }, []);
3805
- useDndMonitor({
3806
- onDragStart: useCallback((event) => {
3807
- const editStore = getEditStore();
3808
- const activeData = event.active?.data.current;
3809
- if (!activeData && !editStore.ui.dnd.isDraggingNewComponent) {
3810
- console.error("No active widget data");
3811
- return;
3812
- }
3813
- const activeRootInstanceId = (activeData?.instanceId && editStore.runtimeEntitiesManager.getEditorWidgetMeta(activeData?.instanceId))?.rootInstanceId;
3814
- const hasLocalBinding = activeData?.instanceId && editStore.runtimeEntitiesManager.doesEntityHaveLocalBindings(activeData?.instanceId);
3815
- if (activeRootInstanceId && hasLocalBinding) editStore.ui.dnd.setValidRootIds([activeRootInstanceId]);
3816
- editStore.ui.dnd.setDropTargetId(null);
3817
- editStore.ui.dnd.setIsDragging(true);
3818
- if (editStore.ui.dnd.isDraggingNewComponent) {
3819
- editStore.ui.selectWidget(null);
3820
- editStore.ui.dnd.resizePageIfNeeded();
3821
- } else editStore.ui.selectWidget(event.active?.id ? event.active.id : null, event.activatorEvent?.shiftKey);
3822
- }, []),
3823
- onDragMove: useCallback((event) => {
3824
- const editStore = getEditStore();
3825
- const overData = event.over?.data.current;
3826
- const overRootId = overData?.rootInstanceId ?? null;
3827
- const overInstanceId = overData?.instanceId ?? null;
3828
- editStore.ui.dnd.setInvalidDropTarget(isInvalidDropTarget(overInstanceId, overRootId));
3829
- setActiveTargetInfo(event.over?.id ?? null, event.over?.rect ?? null);
3830
- const collisionRect = event.collisions?.[0]?.data?.injectedCollisionRect;
3831
- if (collisionRect) setActiveDragRect(collisionRect);
3832
- else setActiveDragRect(null);
3833
- }, [setActiveDragRect, setActiveTargetInfo]),
3834
- onDragOver: useCallback((event) => {
3835
- const editStore = getEditStore();
3836
- const overData = event.over?.data.current;
3837
- const overRootId = overData?.rootInstanceId ?? null;
3838
- const overInstanceId = overData?.instanceId ?? null;
3839
- editStore.ui.dnd.setInvalidDropTarget(isInvalidDropTarget(overInstanceId, overRootId));
3840
- const overId = event.over?.id ? String(event.over?.id) : null;
3841
- setActiveTargetInfo(overId, measureRect(overId));
3842
- }, [setActiveTargetInfo]),
3843
- onDragCancel: useCallback((_event) => {
3844
- const editStore = getEditStore();
3845
- editStore.ui.dnd.setIsDragging(false);
3846
- editStore.ui.dnd.cancelNewComponentDrag();
3847
- }, []),
3848
- onDragEnd: useCallback(async (event) => {
3849
- const editStore = getEditStore();
3850
- let possibleNewComponentId;
3851
- try {
3852
- if (editStore.ui.dnd.invalidDropTarget) {
3853
- editorBridge.sendNotification("error", "You cannot drop a component here.");
3854
- return;
3855
- }
3856
- const dropTargetId = event.over?.id ? String(event.over.id) : null;
3857
- const draggedId = event.active?.id ? String(event.active?.id) : null;
3858
- const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
3859
- if (dropTargetId && activeRootInstanceId && !(editStore.runtimeEntitiesManager.isChildOf(dropTargetId, activeRootInstanceId) || dropTargetId === activeRootInstanceId)) return;
3860
- if (dropTargetId !== editStore.ui.dnd.dropTargetId) throw new Error("Drop target id and drag over id do not match");
3861
- if (!dropTargetId) throw new Error("No drop target id");
3862
- if (editStore.ui.dnd.isDropTargetStackLike) {
3863
- const dropInfo = editStore.ui.dnd.stack.refreshPositionsAndGetDropIndex();
3864
- possibleNewComponentId = await handleStackDrop({
3865
- dropInfo,
3866
- isDraggingNewComponent: editStore.ui.dnd.isDraggingNewComponent,
3867
- newComponentType: editStore.ui.dnd.dragToCanvasComponentType,
3868
- dropTargetId,
3869
- draggedId
3870
- });
3871
- } else throw new Error("Grid is no longer supported");
3872
- } catch (e) {
3873
- console.error("Error dropping item", e);
3874
- } finally {
3875
- runInAction(() => {
3876
- editStore.ui.dnd.setIsDragging(false);
3877
- editStore.ui.dnd.cancelNewComponentDrag();
3878
- if (possibleNewComponentId) editStore.ui.selectNewComponentBySourceId(possibleNewComponentId);
3879
- });
3880
- }
3881
- }, [])
3882
- });
3883
- };
3884
-
3885
3509
  //#endregion
3886
3510
  //#region src/edit-mode/dnd/stack-drop.tsx
3887
3511
  const StackDropPreview = observer(() => {
@@ -3898,7 +3522,7 @@ const StackDropPreview = observer(() => {
3898
3522
  bottom: "anchor(bottom)",
3899
3523
  positionAnchor: getWidgetDropAreaAnchorName(dropTargetId, dropTargetWidgetType)
3900
3524
  },
3901
- children: [!editStore.ui.dnd.invalidDropTarget && placeholders ? /* @__PURE__ */ jsx(Fragment, { children: placeholders.map((placeholder) => /* @__PURE__ */ jsx("div", {
3525
+ children: [editStore.ui.dnd.isProspectiveDropValid && placeholders ? /* @__PURE__ */ jsx(Fragment, { children: placeholders.map((placeholder) => /* @__PURE__ */ jsx("div", {
3902
3526
  className: "sb-edit-drop-placeholder",
3903
3527
  style: {
3904
3528
  top: placeholder.top,
@@ -3911,36 +3535,24 @@ const StackDropPreview = observer(() => {
3911
3535
  "data-is-valid-drop": true
3912
3536
  }, placeholder.top + placeholder.left)) }) : null, /* @__PURE__ */ jsx("div", {
3913
3537
  className: "sb-edit-drop-target-outline",
3914
- "data-invalid-target": editStore.ui.dnd.invalidDropTarget
3538
+ "data-invalid-target": !editStore.ui.dnd.isProspectiveDropValid
3915
3539
  })]
3916
3540
  });
3917
3541
  });
3918
3542
 
3919
3543
  //#endregion
3920
3544
  //#region src/edit-mode/dnd/drop-layer.tsx
3921
- const DropLayer = observer(() => {
3922
- useHandleDnDEvents();
3545
+ const DropLayer = observer((props) => {
3923
3546
  const editStore = getEditStore();
3924
3547
  const draggedWidgetType = editStore.ui.dnd.draggedWidgetType;
3925
3548
  const dropTargetWidgetType = editStore.ui.dnd.dropTargetWidgetType;
3926
3549
  const isDropTargetStackLike = editStore.ui.dnd.isDropTargetStackLike;
3927
3550
  const dropTargetId = editStore.ui.dnd.dropTargetId;
3928
- const isDropTargetInInteractionLayer = getIsComponentInInteractionLayer(dropTargetId);
3929
- const isDragging = editStore.ui.dnd.isDragging;
3930
- const validStackDrop = isDropTargetInInteractionLayer && isDragging && Boolean(draggedWidgetType && dropTargetWidgetType) && isDropTargetStackLike;
3931
- const isValidDrop = validStackDrop;
3932
- return /* @__PURE__ */ jsxs(Fragment, { children: [validStackDrop && /* @__PURE__ */ jsx(StackDropPreview, {}), /* @__PURE__ */ jsx(DragOverlay, {
3551
+ const isDropTargetInInteractionLayer = doesInteractionLayerContainInstance(props.rootInstanceId, dropTargetId);
3552
+ const possibleStackDrop = editStore.ui.dnd.isDragging && isDropTargetInInteractionLayer && Boolean(draggedWidgetType && dropTargetWidgetType) && isDropTargetStackLike;
3553
+ return /* @__PURE__ */ jsxs(Fragment, { children: [possibleStackDrop && /* @__PURE__ */ jsx(StackDropPreview, {}), /* @__PURE__ */ jsx(DragOverlay, {
3933
3554
  modifiers: [snapCenterToCursor],
3934
- dropAnimation: null,
3935
- children: editStore.ui.dnd.isDraggingNewComponent && /* @__PURE__ */ jsx("div", {
3936
- className: "sb-edit-drag-preview",
3937
- "data-is-valid-drop": isValidDrop,
3938
- style: {
3939
- visibility: "visible",
3940
- height: `${editStore.ui.dnd.draggingWidgetSize.height * 12}px`,
3941
- width: `${editStore.ui.dnd.draggingWidgetSize.width * 12}px`
3942
- }
3943
- })
3555
+ dropAnimation: null
3944
3556
  })] });
3945
3557
  });
3946
3558
  var drop_layer_default = DropLayer;
@@ -4393,18 +4005,18 @@ const useWidgetErrors = (params) => {
4393
4005
  ]);
4394
4006
  };
4395
4007
  const useSelectionElements = (params) => {
4396
- const { focusedInstanceId, selectedInstanceIds, targetedSourceIds, aiContextMode } = params;
4008
+ const { focusedInstanceId, selectedInstanceIds, targetedSourceIds, aiContextMode, rootId } = params;
4397
4009
  const allTargetedComponents = useMemo(() => {
4398
4010
  const components = [];
4399
4011
  targetedSourceIds.forEach((sourceId) => {
4400
4012
  const sourceInstanceIds = getEditStore().runtimeEntitiesManager.widgets.getAllInstanceIdsForSourceId(sourceId);
4401
- components.push(...sourceInstanceIds.map((instanceId) => ({
4013
+ components.push(...sourceInstanceIds.filter((instanceId) => doesInteractionLayerContainInstance(rootId, instanceId)).map((instanceId) => ({
4402
4014
  instanceId,
4403
4015
  sourceId
4404
4016
  })));
4405
4017
  });
4406
4018
  return components;
4407
- }, [targetedSourceIds]);
4019
+ }, [targetedSourceIds, rootId]);
4408
4020
  const visibleTargetedComponents = useViewportIntersection(allTargetedComponents);
4409
4021
  return useObserverMemo(() => {
4410
4022
  const selectedRects = [];
@@ -4419,7 +4031,7 @@ const useSelectionElements = (params) => {
4419
4031
  isVisible
4420
4032
  });
4421
4033
  });
4422
- selectedInstanceIds.forEach((instanceId) => {
4034
+ selectedInstanceIds.filter((instanceId) => doesInteractionLayerContainInstance(rootId, instanceId)).forEach((instanceId) => {
4423
4035
  const { type, displayName, sourceId, isVisible } = selectDisplayNameAndVisibility(instanceId);
4424
4036
  if (sourceId && !targetedSourceIds.includes(sourceId)) selectedRects.push({
4425
4037
  instanceId,
@@ -4430,7 +4042,7 @@ const useSelectionElements = (params) => {
4430
4042
  isVisible
4431
4043
  });
4432
4044
  });
4433
- if (focusedInstanceId && (aiContextMode === AiContextMode.AUTO_SELECT || !selectedInstanceIds.includes(focusedInstanceId))) {
4045
+ if (focusedInstanceId && doesInteractionLayerContainInstance(rootId, focusedInstanceId) && (aiContextMode === AiContextMode.AUTO_SELECT || !selectedInstanceIds.includes(focusedInstanceId))) {
4434
4046
  const { type, displayName, sourceId, isVisible } = selectDisplayNameAndVisibility(focusedInstanceId);
4435
4047
  if (sourceId) selectedRects.push({
4436
4048
  instanceId: focusedInstanceId,
@@ -4447,7 +4059,8 @@ const useSelectionElements = (params) => {
4447
4059
  selectedInstanceIds,
4448
4060
  targetedSourceIds,
4449
4061
  aiContextMode,
4450
- visibleTargetedComponents
4062
+ visibleTargetedComponents,
4063
+ rootId
4451
4064
  ]);
4452
4065
  };
4453
4066
  const InteractionRectTargetBorder = ({ instanceId }) => {
@@ -4679,7 +4292,7 @@ const InteractionLayer = observer((props) => {
4679
4292
  displayName: props.rootName ?? "Unknown",
4680
4293
  hideRectBorder: false
4681
4294
  }, props.rootInstanceId) : null;
4682
- return /* @__PURE__ */ jsxs("div", {
4295
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", {
4683
4296
  className: "sb-interaction-layer-wrapper",
4684
4297
  children: [
4685
4298
  interactionRectsForSelectedElements,
@@ -4690,9 +4303,9 @@ const InteractionLayer = observer((props) => {
4690
4303
  displayName: name,
4691
4304
  instanceId: id
4692
4305
  }, id)),
4693
- props.rootType !== "App" && /* @__PURE__ */ jsx(drop_layer_default, {})
4306
+ /* @__PURE__ */ jsx(drop_layer_default, { rootInstanceId: props.rootInstanceId })
4694
4307
  ]
4695
- });
4308
+ }) });
4696
4309
  });
4697
4310
  var interaction_layer_default = InteractionLayer;
4698
4311
 
@@ -4787,7 +4400,7 @@ const stableEffectOptions$1 = {
4787
4400
  cold: true
4788
4401
  };
4789
4402
  function useRuntimeEditTracking(props) {
4790
- const { parentInstanceId, directParentInstanceId, identifier, type, children, widgetProps, rootInstanceId, indexWithinParent, isRoot, isInsideRoot } = props;
4403
+ const { parentInstanceId, directParentInstanceId, identifier, type, children, widgetProps, rootInstanceId, interactionLayerInstanceId, indexWithinParent, isRoot, isInsideRoot } = props;
4791
4404
  const { children: _children,...rest } = widgetProps;
4792
4405
  use_stable_effect_default(() => {
4793
4406
  const widgetMeta = {
@@ -4802,6 +4415,7 @@ function useRuntimeEditTracking(props) {
4802
4415
  directParentInstanceId,
4803
4416
  sourceId: identifier.sourceId,
4804
4417
  rootInstanceId,
4418
+ interactionLayerInstanceId,
4805
4419
  isRoot,
4806
4420
  isInsideRoot
4807
4421
  };
@@ -4814,6 +4428,7 @@ function useRuntimeEditTracking(props) {
4814
4428
  parentInstanceId,
4815
4429
  directParentInstanceId,
4816
4430
  rootInstanceId,
4431
+ interactionLayerInstanceId,
4817
4432
  type,
4818
4433
  rest
4819
4434
  }, stableEffectOptions$1);
@@ -4913,6 +4528,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
4913
4528
  const rootInstanceId = editorRootContext?.instanceId;
4914
4529
  const parentIdentifier = useParentIdentifier();
4915
4530
  const isRoot = ROOT_WIDGET_ATTRIBUTE in props.widgetProps;
4531
+ const { rootInstanceId: interactionLayerInstanceId } = useInteractionLayerContext();
4916
4532
  const children = useRuntimeEditTracking({
4917
4533
  parentInstanceId: parentIdentifier?.instanceId,
4918
4534
  directParentInstanceId: props.directParentInstanceId,
@@ -4921,6 +4537,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
4921
4537
  children: props.children,
4922
4538
  widgetProps: props.widgetProps,
4923
4539
  rootInstanceId,
4540
+ interactionLayerInstanceId,
4924
4541
  indexWithinParent: props.indexWithinParent,
4925
4542
  isRoot,
4926
4543
  isInsideRoot
@@ -4963,7 +4580,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
4963
4580
  editStore$1.ui.selectWidget(props.identifier.instanceId, ev.shiftKey === true);
4964
4581
  stopPropagation();
4965
4582
  }, [props.identifier.sourceId, props.identifier.instanceId]);
4966
- const dropTargetRef = useRef(null);
4583
+ const [dropTargetElem, setDropTargetElem] = useState(null);
4967
4584
  const handleRef = useCallback((el) => {
4968
4585
  setDraggableNodeRef(el);
4969
4586
  }, [setDraggableNodeRef]);
@@ -5001,7 +4618,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5001
4618
  identifier,
5002
4619
  widgetProps: props.widgetProps,
5003
4620
  editorProps,
5004
- dropTargetRef,
4621
+ dropTargetRef: setDropTargetElem,
5005
4622
  showErrors: true,
5006
4623
  children: [showVisibilityBackground && /* @__PURE__ */ jsx("div", {
5007
4624
  className: VisibilityOverlayClass,
@@ -5020,10 +4637,13 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5020
4637
  }) : node;
5021
4638
  if (isDroppable) content = /* @__PURE__ */ jsx(droppable_widget_default, {
5022
4639
  instanceId: props.identifier.instanceId,
5023
- dropTargetRef,
4640
+ dropTargetElem,
5024
4641
  children: content
5025
4642
  });
5026
- if (props.type === "App" || props.type === "Page") return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(interaction_layer_default, {
4643
+ if (props.type === "App" || props.type === "Page") return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(InteractionLayerProvider, {
4644
+ instanceId: props.identifier.instanceId,
4645
+ children: content
4646
+ }), /* @__PURE__ */ jsx(interaction_layer_default, {
5027
4647
  rootType: props.type,
5028
4648
  rootInstanceId: props.identifier.instanceId,
5029
4649
  rootName: identifier.name.value
@@ -6537,7 +6157,6 @@ const registerComponentInternal = (type, config, Component$1) => {
6537
6157
  widgetProps,
6538
6158
  component: Component$1,
6539
6159
  identifier: identifier.current,
6540
- isDroppable,
6541
6160
  directParentInstanceId: props[WIDGET_PARENT_INSTANCE_ID_ATTRIBUTE],
6542
6161
  indexWithinParent: props[WIDGET_INDEX_WITHIN_PARENT],
6543
6162
  children: props.children
@@ -6993,10 +6612,137 @@ const FullPageSpinner = () => {
6993
6612
  function useGetCurrentUserQuery() {
6994
6613
  return useMemo(() => {
6995
6614
  return {
6996
- isLoading: false,
6997
- data: { user: { name: "Test User" } }
6615
+ isLoading: false,
6616
+ data: { user: { name: "Test User" } }
6617
+ };
6618
+ }, []);
6619
+ }
6620
+
6621
+ //#endregion
6622
+ //#region src/edit-mode/dnd/is-nestable.ts
6623
+ function isNestable(componentType, _parentType) {
6624
+ if (componentType === PAGE_COMPONENT_TYPE) return false;
6625
+ return true;
6626
+ }
6627
+
6628
+ //#endregion
6629
+ //#region src/edit-mode/create-component.ts
6630
+ function getParentInfo(parent) {
6631
+ return { type: getEditStore().runtimeEntitiesManager.getAnyEditorWidgetMeta(parent.id)?.type };
6632
+ }
6633
+ const generateUniqueName = (componentType) => {
6634
+ const baseName = componentType;
6635
+ let counter = 1;
6636
+ let name = `${baseName}${counter}`;
6637
+ while (root_store_default.nameManager.hasEntityWithName(name)) {
6638
+ counter++;
6639
+ name = `${baseName}${counter}`;
6640
+ }
6641
+ return name;
6642
+ };
6643
+ function getBinding({ componentType, editorTemplateCreateRequest }) {
6644
+ if (editorTemplateCreateRequest?.generateBinding === true) return Property$1.Static(generateUniqueName(componentType));
6645
+ else if (typeof editorTemplateCreateRequest?.generateBinding === "string") return Property$1.Static(editorTemplateCreateRequest.generateBinding);
6646
+ else return;
6647
+ }
6648
+ function getComponentBaseProperties(componentType, _parentInfo, editorTemplateCreateRequest) {
6649
+ let properties = {};
6650
+ const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
6651
+ if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
6652
+ if (editorTemplateCreateRequest?.properties) properties = {
6653
+ ...properties,
6654
+ ...editorTemplateCreateRequest.properties
6655
+ };
6656
+ const binding = getBinding({
6657
+ componentType,
6658
+ editorTemplateCreateRequest
6659
+ });
6660
+ if (binding) properties.name = binding;
6661
+ const { width, height, size: size$1 } = properties;
6662
+ const safeDimensions = filterSafeStackDimensionProperties({
6663
+ width: width?.value,
6664
+ height: height?.value,
6665
+ size: size$1?.value
6666
+ });
6667
+ return {
6668
+ properties: {
6669
+ ...properties,
6670
+ ...safeDimensions
6671
+ },
6672
+ children: editorTemplateCreateRequest?.children ?? []
6673
+ };
6674
+ }
6675
+ function getCreateAtParentElement(relativeParent, createAt) {
6676
+ if (createAt === "root") {
6677
+ const parentInstanceId = getEditStore().runtimeEntitiesManager.widgets.getAnyInstanceIdForSourceId(relativeParent.id);
6678
+ const pageComponent = getEditStore().runtimeEntitiesManager.getClosestAncestorByType(parentInstanceId, "Page");
6679
+ if (!pageComponent) throw new Error(`Page component not found for parent: ${relativeParent.id}`);
6680
+ return { source: { id: pageComponent.sourceId } };
6681
+ } else return { source: relativeParent };
6682
+ }
6683
+ async function createComponent({ componentType, parent, scopeName, baseProperties = {}, skipSecondaryComponentsCreation, otherComponentsUpdates }) {
6684
+ const parentInfo = getParentInfo(parent);
6685
+ if (!isNestable(componentType, parentInfo.type)) {
6686
+ console.error(`${componentType} cannot be nested under ${parentInfo.type}`);
6687
+ return;
6688
+ }
6689
+ const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
6690
+ if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
6691
+ const context$1 = {
6692
+ generateUniqueName,
6693
+ parentInfo,
6694
+ defaultTagNames: root_store_default.componentRegistry.defaultTagNames,
6695
+ selfTagName: componentType
6696
+ };
6697
+ const editorTemplateCreateRequest = editorTemplates?.[0]?.create?.(context$1);
6698
+ const primaryEditorTemplateCreateRequest = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest[0] : editorTemplateCreateRequest;
6699
+ if (editorTemplateCreateRequest && primaryEditorTemplateCreateRequest?.type !== componentType) throw new Error(`When defining a ${Array.isArray(editorTemplateCreateRequest) ? "multiple" : "single"} component to be created on an EditorTemplate, the type must match with the component being created. got: ${primaryEditorTemplateCreateRequest?.type} when it should have been ${componentType}`);
6700
+ const editorTemplateCreateRequests = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest : [editorTemplateCreateRequest];
6701
+ const editStore = getEditStore();
6702
+ function editorTemplateCreateRequestToInternalCreateRequest({ editorTemplateCreateRequest: editorTemplateCreateRequest$1, baseProperties: baseProperties$1 }) {
6703
+ const type = editorTemplateCreateRequest$1?.type ?? componentType;
6704
+ const { properties: propertiesFromType, children } = getComponentBaseProperties(type, parentInfo, editorTemplateCreateRequest$1);
6705
+ const properties = {
6706
+ ...propertiesFromType,
6707
+ ...baseProperties$1
6708
+ };
6709
+ return {
6710
+ parentElement: getCreateAtParentElement(parent, editorTemplateCreateRequest$1?.createAt),
6711
+ tagName: type,
6712
+ properties,
6713
+ children,
6714
+ scopeName,
6715
+ id: editStore.operationManager.generateSourceId()
6998
6716
  };
6999
- }, []);
6717
+ }
6718
+ const createRequests = editorTemplateCreateRequests.map((editorTemplateCreateRequest$1, index) => editorTemplateCreateRequestToInternalCreateRequest({
6719
+ editorTemplateCreateRequest: editorTemplateCreateRequest$1,
6720
+ baseProperties: index === 0 ? baseProperties : {}
6721
+ }));
6722
+ const hasOtherComponentsUpdates = otherComponentsUpdates && Object.keys(otherComponentsUpdates).length > 0;
6723
+ const hasMultipleCreateComponents = editorTemplateCreateRequests.length > 1 && !skipSecondaryComponentsCreation;
6724
+ if (hasOtherComponentsUpdates || hasMultipleCreateComponents) {
6725
+ const performOtherComponentsUpdates = (otherComponentsUpdates$1) => {
6726
+ Object.entries(otherComponentsUpdates$1).forEach(([sourceId, updates]) => {
6727
+ editStore.operationManager.setWidgetProperties({
6728
+ sourceId,
6729
+ properties: updates
6730
+ });
6731
+ });
6732
+ };
6733
+ editStore.operationManager.batchUpdate(() => {
6734
+ if (skipSecondaryComponentsCreation) editStore.operationManager.createComponent(createRequests[0]);
6735
+ else createRequests.forEach((createRequest) => {
6736
+ editStore.operationManager.createComponent(createRequest);
6737
+ });
6738
+ if (hasOtherComponentsUpdates) performOtherComponentsUpdates(otherComponentsUpdates);
6739
+ });
6740
+ } else editStore.operationManager.createComponent(createRequests[0]);
6741
+ /**
6742
+ * Returns the single id, or the the last component if there are multiple.
6743
+ * See EditorTemplate's definition to understand why.
6744
+ */
6745
+ return createRequests.at(-1).id;
7000
6746
  }
7001
6747
 
7002
6748
  //#endregion
@@ -7020,7 +6766,7 @@ const fixCursorSnapOffset = (args) => {
7020
6766
  const sortedCollisions = rectIntersection(updated).filter((collision) => {
7021
6767
  const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
7022
6768
  if (!activeRootInstanceId) return true;
7023
- return collision.id === activeRootInstanceId || editStore.runtimeEntitiesManager.isChildOf(collision.id, activeRootInstanceId);
6769
+ return collision.id === activeRootInstanceId || doesInteractionLayerContainInstance(activeRootInstanceId, collision.id);
7024
6770
  }).map((collision) => {
7025
6771
  const rect = collision.data?.droppableContainer?.rect.current;
7026
6772
  const pointerInside = rect && x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
@@ -7075,6 +6821,184 @@ const bubblingToParentIfFar = (args) => {
7075
6821
  };
7076
6822
  var collision_detection_default = fixCursorSnapOffset;
7077
6823
 
6824
+ //#endregion
6825
+ //#region src/edit-mode/dnd/handle-stack-drop.ts
6826
+ const mergeDroppedDimensions = (draggedType, draggedProps, activeDragRect) => {
6827
+ const safeExistingDimensions = filterSafeStackDimensionProperties({
6828
+ width: draggedProps?.width,
6829
+ height: draggedProps?.height,
6830
+ size: draggedProps?.size
6831
+ });
6832
+ const width = safeExistingDimensions.width;
6833
+ const height = safeExistingDimensions.height;
6834
+ if (draggedType === "Icon") return { size: safeExistingDimensions.size ?? (activeDragRect?.height ? Property$1.Dimension(Dim$1.px(activeDragRect.height)) : Property$1.Static("")) };
6835
+ return {
6836
+ width,
6837
+ height
6838
+ };
6839
+ };
6840
+ const handleStackDropWithinCanvas = (params) => {
6841
+ const { dropInfo, draggedId, dropTargetId } = params;
6842
+ const editStore = getEditStore();
6843
+ const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
6844
+ const draggedSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(draggedId);
6845
+ if (!dropSourceId || !draggedSourceId) throw new Error(`Missing IDs: dragging ${draggedId} to ${dropTargetId}`);
6846
+ console.log(`Dragged ${draggedSourceId} to ${dropSourceId}`, {
6847
+ dropInfo,
6848
+ index: dropInfo.insertionIndex
6849
+ });
6850
+ if (dropInfo.noopDrop) return;
6851
+ const draggedType = editStore.runtimeEntitiesManager.getEditorWidgetType(draggedId);
6852
+ if (!draggedType) throw new Error(`Missing dragged type: ${draggedId}`);
6853
+ const activeDragRect = editStore.ui.dnd.activeDragRect;
6854
+ const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
6855
+ editStore.operationManager.dropComponent({
6856
+ from: { source: { id: draggedSourceId } },
6857
+ to: { source: {
6858
+ id: dropSourceId,
6859
+ index: dropInfo.insertionIndex
6860
+ } },
6861
+ propsToChange: { ...mergeDroppedDimensions(draggedType, draggedProps, activeDragRect) }
6862
+ });
6863
+ };
6864
+ const handleStackDropForNewComponent = ({ componentType, dropInfo, dropTargetId }) => {
6865
+ const editStore = getEditStore();
6866
+ const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
6867
+ const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
6868
+ if (!dropSourceId || !dropScopeId) throw new Error("Missing drop source id");
6869
+ const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
6870
+ return createComponent({
6871
+ componentType,
6872
+ parent: {
6873
+ index: dropInfo.insertionIndex,
6874
+ id: dropSourceId
6875
+ },
6876
+ scopeName
6877
+ });
6878
+ };
6879
+ const handleStackDrop = async ({ dropInfo, draggedId, dropTargetId, isDraggingNewComponent, newComponentType }) => {
6880
+ if (dropInfo.insertionIndex == null) throw new Error("No insertion index found");
6881
+ if (isDraggingNewComponent) {
6882
+ if (!newComponentType) throw new Error("Missing componentType to create new component");
6883
+ return handleStackDropForNewComponent({
6884
+ componentType: newComponentType,
6885
+ dropTargetId,
6886
+ dropInfo
6887
+ });
6888
+ } else {
6889
+ if (!draggedId) throw new Error("Missing dragged id");
6890
+ handleStackDropWithinCanvas({
6891
+ dropInfo,
6892
+ draggedId,
6893
+ dropTargetId
6894
+ });
6895
+ }
6896
+ };
6897
+
6898
+ //#endregion
6899
+ //#region src/edit-mode/dnd/hooks/use-handle-dnd-events.ts
6900
+ const measureRect = (id) => {
6901
+ const rect = id ? getBoundingBoxForWidget(id) : null;
6902
+ if (!rect) return null;
6903
+ return {
6904
+ left: rect.left,
6905
+ top: rect.top,
6906
+ right: rect.right,
6907
+ bottom: rect.bottom,
6908
+ width: rect.width,
6909
+ height: rect.height
6910
+ };
6911
+ };
6912
+ const useHandleDnDEvents = () => {
6913
+ const setActiveDragRect = useMemo(() => {
6914
+ const editStore = getEditStore();
6915
+ const throttled = throttle((rect) => {
6916
+ editStore.ui.dnd.setActiveDragRect(rect);
6917
+ }, 10, {
6918
+ leading: true,
6919
+ trailing: true
6920
+ });
6921
+ return (val) => {
6922
+ throttled(val);
6923
+ };
6924
+ }, []);
6925
+ const setActiveTargetInfo = useMemo(() => {
6926
+ const editStore = getEditStore();
6927
+ const throttled = throttle((id, rect) => {
6928
+ editStore.ui.dnd.setDropTargetId(id);
6929
+ editStore.ui.dnd.setActiveTargetRect(rect);
6930
+ }, 10, {
6931
+ leading: true,
6932
+ trailing: true
6933
+ });
6934
+ return (id, val) => {
6935
+ throttled(id, val);
6936
+ };
6937
+ }, []);
6938
+ useDndMonitor({
6939
+ onDragStart: useCallback((event) => {
6940
+ const editStore = getEditStore();
6941
+ if (!event.active?.data.current && !editStore.ui.dnd.isDraggingNewComponent) {
6942
+ console.error("No active widget data");
6943
+ return;
6944
+ }
6945
+ editStore.ui.dnd.setDropTargetId(null);
6946
+ editStore.ui.dnd.setIsDragging(true);
6947
+ if (editStore.ui.dnd.isDraggingNewComponent) {
6948
+ editStore.ui.selectWidget(null);
6949
+ editStore.ui.dnd.resizePageIfNeeded();
6950
+ } else editStore.ui.selectWidget(event.active?.id ? event.active.id : null, event.activatorEvent?.shiftKey);
6951
+ }, []),
6952
+ onDragMove: useCallback((event) => {
6953
+ setActiveTargetInfo(event.over?.id ?? null, event.over?.rect ?? null);
6954
+ const collisionRect = event.collisions?.[0]?.data?.injectedCollisionRect;
6955
+ if (collisionRect) setActiveDragRect(collisionRect);
6956
+ else setActiveDragRect(null);
6957
+ }, [setActiveDragRect, setActiveTargetInfo]),
6958
+ onDragOver: useCallback((event) => {
6959
+ const overId = event.over?.id ? String(event.over?.id) : null;
6960
+ setActiveTargetInfo(overId, measureRect(overId));
6961
+ }, [setActiveTargetInfo]),
6962
+ onDragCancel: useCallback((_event) => {
6963
+ const editStore = getEditStore();
6964
+ editStore.ui.dnd.setIsDragging(false);
6965
+ editStore.ui.dnd.cancelNewComponentDrag();
6966
+ }, []),
6967
+ onDragEnd: useCallback(async (event) => {
6968
+ const editStore = getEditStore();
6969
+ let possibleNewComponentId;
6970
+ try {
6971
+ if (!editStore.ui.dnd.isProspectiveDropValid) {
6972
+ editorBridge.sendNotification("error", "You cannot drop a component here.");
6973
+ return;
6974
+ }
6975
+ const dropTargetId = event.over?.id ? String(event.over.id) : null;
6976
+ const draggedId = event.active?.id ? String(event.active?.id) : null;
6977
+ if (dropTargetId !== editStore.ui.dnd.dropTargetId) throw new Error("Drop target id and drag over id do not match");
6978
+ if (!dropTargetId) throw new Error("No drop target id");
6979
+ if (editStore.ui.dnd.isDropTargetStackLike) {
6980
+ const dropInfo = editStore.ui.dnd.stack.refreshPositionsAndGetDropIndex();
6981
+ possibleNewComponentId = await handleStackDrop({
6982
+ dropInfo,
6983
+ isDraggingNewComponent: editStore.ui.dnd.isDraggingNewComponent,
6984
+ newComponentType: editStore.ui.dnd.dragToCanvasComponentType,
6985
+ dropTargetId,
6986
+ draggedId
6987
+ });
6988
+ } else throw new Error("Grid is no longer supported");
6989
+ } catch (e) {
6990
+ console.error("Error dropping item", e);
6991
+ } finally {
6992
+ runInAction(() => {
6993
+ editStore.ui.dnd.setIsDragging(false);
6994
+ editStore.ui.dnd.cancelNewComponentDrag();
6995
+ if (possibleNewComponentId) editStore.ui.selectNewComponentBySourceId(possibleNewComponentId);
6996
+ });
6997
+ }
6998
+ }, [])
6999
+ });
7000
+ };
7001
+
7078
7002
  //#endregion
7079
7003
  //#region src/edit-mode/dnd/dnd-provider.tsx
7080
7004
  const pointerConfig = { activationConstraint: { distance: 10 } };
@@ -7089,14 +7013,18 @@ var CustomPointerSensor = class extends PointerSensor {
7089
7013
  }
7090
7014
  }];
7091
7015
  };
7016
+ const DragHandlerComponent = () => {
7017
+ useHandleDnDEvents();
7018
+ return null;
7019
+ };
7092
7020
  const DnDProvider = (props) => {
7093
7021
  const pointerSensor = useSensor(PointerSensor, pointerConfig);
7094
7022
  const customPointerSensor = useSensor(CustomPointerSensor);
7095
7023
  const sensors = useSensors(pointerSensor, customPointerSensor);
7096
- return /* @__PURE__ */ jsx(DndContext, {
7024
+ return /* @__PURE__ */ jsxs(DndContext, {
7097
7025
  sensors,
7098
7026
  collisionDetection: collision_detection_default,
7099
- children: props.children
7027
+ children: [props.children, /* @__PURE__ */ jsx(DragHandlerComponent, {})]
7100
7028
  });
7101
7029
  };
7102
7030
 
@@ -7238,9 +7166,16 @@ var InteractionLayerManager = class {
7238
7166
  * if set to the detached component id, the interaction layer will be disabled on the page
7239
7167
  */
7240
7168
  activeRootInstanceId = void 0;
7169
+ interactionLayerInstanceIds = /* @__PURE__ */ new Set();
7241
7170
  constructor() {
7242
7171
  makeAutoObservable(this);
7243
7172
  }
7173
+ @action addInteractionLayerInstanceId(instanceId) {
7174
+ this.interactionLayerInstanceIds.add(instanceId);
7175
+ }
7176
+ @action removeInteractionLayerInstanceId(instanceId) {
7177
+ this.interactionLayerInstanceIds.delete(instanceId);
7178
+ }
7244
7179
  @action setActiveRootInstanceId(rootInstanceId) {
7245
7180
  this.activeRootInstanceId = rootInstanceId;
7246
7181
  }
@@ -8131,7 +8066,8 @@ var RuntimeEntitiesManager = class {
8131
8066
  this.entitiesWithLocalBindings = new Set(entities);
8132
8067
  }
8133
8068
  doesEntityHaveLocalBindings(entity) {
8134
- return this.entitiesWithLocalBindings.has(entity);
8069
+ const entitySourceId = this.getEditorWidgetSourceId(entity);
8070
+ return entitySourceId && this.entitiesWithLocalBindings.has(entitySourceId);
8135
8071
  }
8136
8072
  getOptimisticWidgetChildrenIds(instanceId) {
8137
8073
  return this.getChildrenWithOptimisticUpdates(instanceId).reduce((acc, child) => {
@@ -8613,14 +8549,36 @@ var DragAndDropManager = class {
8613
8549
  const draggedInstanceId = this.root.editStore.ui.getSelectedInstanceIds()[0];
8614
8550
  return draggedInstanceId ? getEditStore().runtimeEntitiesManager.getEditorWidgetType(draggedInstanceId) : void 0;
8615
8551
  }
8552
+ get draggedWidgetInstanceId() {
8553
+ if (this.isDraggingNewComponent) return;
8554
+ return this.root.editStore.ui.getSelectedInstanceIds()[0];
8555
+ }
8616
8556
  get dragToCanvasComponentType() {
8617
8557
  return this._dragToCanvasComponentType;
8618
8558
  }
8619
8559
  get validRootIds() {
8620
8560
  return this._validRootIds;
8621
8561
  }
8622
- get invalidDropTarget() {
8623
- return this._invalidDropTarget;
8562
+ get isProspectiveDropValid() {
8563
+ const dropTargetInstanceId = this.dropTargetId;
8564
+ const draggedInstanceId = this.draggedWidgetInstanceId;
8565
+ if (!dropTargetInstanceId) return false;
8566
+ const isDraggingNewComponent = this.isDraggingNewComponent;
8567
+ if (!areDragAndDropInstancesValid({
8568
+ dropTargetInstanceId,
8569
+ draggedInstanceId,
8570
+ isDraggingNewComponent
8571
+ })) return false;
8572
+ const draggedType = this.draggedWidgetType;
8573
+ const dropTargetType = this.dropTargetWidgetType;
8574
+ if (!draggedType || !dropTargetType) return false;
8575
+ const dropTargetEmpty = (dropTargetInstanceId && getEditStore().runtimeEntitiesManager.getEditorWidgetMeta(dropTargetInstanceId)?.children?.length === 0) ?? true;
8576
+ return isDragAndDropTypeValid({
8577
+ draggedType,
8578
+ dropTargetType,
8579
+ isDraggingNewComponent,
8580
+ dropTargetEmpty
8581
+ });
8624
8582
  }
8625
8583
  canDragWidget(instanceId) {
8626
8584
  const editStore = getEditStore();
@@ -8649,7 +8607,6 @@ var DragAndDropManager = class {
8649
8607
  this._activeDragRect = null;
8650
8608
  this._activeTargetRect = null;
8651
8609
  this._validRootIds = null;
8652
- this._invalidDropTarget = false;
8653
8610
  }
8654
8611
  }
8655
8612
  /**
@@ -8692,9 +8649,6 @@ var DragAndDropManager = class {
8692
8649
  @action setValidRootIds(ids) {
8693
8650
  this._validRootIds = ids;
8694
8651
  }
8695
- @action setInvalidDropTarget(invalid) {
8696
- this._invalidDropTarget = invalid;
8697
- }
8698
8652
  @action setDropTargetId(id) {
8699
8653
  this._dropTargetInstanceId = id;
8700
8654
  if (id == null) this._activeTargetRect = null;
@@ -10288,7 +10242,7 @@ function useDialogEditing(props) {
10288
10242
  const selectedInstanceId = features.selectWidget.value;
10289
10243
  useEffect(() => {
10290
10244
  if (isEditing && instanceId) if (isOpen) {
10291
- if (!selectedInstanceId || selectedInstanceId !== instanceId && !getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId))
10245
+ if (!selectedInstanceId || selectedInstanceId !== instanceId && !doesInteractionLayerContainInstance(instanceId, selectedInstanceId))
10292
10246
  /**
10293
10247
  * If the dialog is open and the dialog or its children are not selected, then select it.
10294
10248
  * This happens when an event handler changes the open state of the dialog.
@@ -10304,10 +10258,10 @@ function useDialogEditing(props) {
10304
10258
  if (isEditing && instanceId) {
10305
10259
  if (prevIsOpenRef.current !== isOpen && !(prevIsOpenRef.current === void 0 && isOpen === false)) return;
10306
10260
  if (isOpen) {
10307
- if (selectedInstanceId && selectedInstanceId !== instanceId && !getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId)) update((entity) => {
10261
+ if (selectedInstanceId && selectedInstanceId !== instanceId && !doesInteractionLayerContainInstance(instanceId, selectedInstanceId)) update((entity) => {
10308
10262
  set(entity, isOpenPropertyName, false);
10309
10263
  });
10310
- } else if (selectedInstanceId === instanceId || selectedInstanceId && getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId)) update((entity) => {
10264
+ } else if (selectedInstanceId === instanceId || selectedInstanceId && doesInteractionLayerContainInstance(instanceId, selectedInstanceId)) update((entity) => {
10311
10265
  set(entity, isOpenPropertyName, true);
10312
10266
  });
10313
10267
  }
@@ -11330,7 +11284,10 @@ function DroppableContainer({ name, componentType, isOpen, children, layout, cla
11330
11284
  ref: dropTargetRef,
11331
11285
  id: getEditWrapperIdWithType(instanceId, componentType),
11332
11286
  style: EXPANDED,
11333
- children: [internalContainer, isOpen && /* @__PURE__ */ jsx(interaction_layer_default, {
11287
+ children: [/* @__PURE__ */ jsx(InteractionLayerProvider, {
11288
+ instanceId,
11289
+ children: internalContainer
11290
+ }), isOpen && /* @__PURE__ */ jsx(interaction_layer_default, {
11334
11291
  rootType: componentType,
11335
11292
  rootInstanceId: instanceId,
11336
11293
  rootName: name