@superblocksteam/library 2.0.37-next.9 → 2.0.37

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
@@ -1,5 +1,5 @@
1
1
  import { early_console_buffer_default } from "./early-console-buffer-DWTLgla0.js";
2
- import { CLASS_NAMES, DEFAULT_ANONYMOUS_SOURCE_ID, DevTools, EventFlow, GLOBAL_SCOPE_ID, LazyFunction, NavigationEvent, Prop, PropsPanelCategory, RecordProp, Section, VALIDATORS, addNewPromise, colors, createInternalPropsList, createManagedPropsList, createPropertiesPanelDefinition, editorBridge, generateId, getEditStore, getName, iframeMessageHandler, isEditMode, isEmbeddedBySuperblocksFirstParty, isLocalLink, isName, isNameEqual, navigation, rejectById, resolveById, root_store_default, run_event_handlers_default, sendNotification, startEditorSync, system_error_default } from "./root-store-2o7fAW9E.js";
2
+ import { CLASS_NAMES, DEFAULT_ANONYMOUS_SOURCE_ID, DevTools, EventFlow, GLOBAL_SCOPE_ID, LazyFunction, NavigationEvent, Prop, PropsPanelCategory, RecordProp, Section, VALIDATORS, addNewPromise, colors, createInternalPropsList, createManagedPropsList, createPropertiesPanelDefinition, editorBridge, generateId, getEditStore, getName, iframeMessageHandler, isEditMode, isEmbeddedBySuperblocksFirstParty, isLocalLink, isName, isNameEqual, navigation, rejectById, resolveById, root_store_default, run_event_handlers_default, sendNotification, startEditorSync, system_error_default } from "./root-store-D7IuNpKE.js";
3
3
  import "./utils-CCBWAYIM.js";
4
4
  import { AiContextMode, AiGenerationState, BindingMetaSymbol, SbEntityType, StateVarPersistence, StateVarPersistence as StateVarPersistence$1, ThemeMode, TriggerStepType, ViteMessageKind, isValidStepDef, sbEntitySymbol } from "@superblocksteam/library-shared/types";
5
5
  import _, { get, isEmpty, isEqual, isNumber, isObject, merge, set, throttle } from "lodash";
@@ -1241,20 +1241,6 @@ const createMemoizedClassGenerator = (generator) => {
1241
1241
  function getDefaultTypographies(themeVersion) {
1242
1242
  return DEFAULT_TYPOGRAPHIES_BY_VERSION[themeVersion || 2];
1243
1243
  }
1244
- function dimToCSS(dim, dimension, primary = true) {
1245
- switch (dim.mode) {
1246
- case "fit": return { [dimension]: "fit-content" };
1247
- case "fill":
1248
- if (!primary) return {
1249
- alignSelf: "stretch",
1250
- [dimension]: "unset"
1251
- };
1252
- return { flex: dim.value ?? 1 };
1253
- case "px": return { [dimension]: `${dim.value}px` };
1254
- case "%": return { [dimension]: `${dim.value}%` };
1255
- default: return {};
1256
- }
1257
- }
1258
1244
  const Classes = {
1259
1245
  minHeightZero: styleWithPrefix("sb-min-height-zero")`
1260
1246
  @layer components {
@@ -1281,7 +1267,13 @@ const Classes = {
1281
1267
  height: -webkit-fill-available;
1282
1268
  }
1283
1269
  `,
1284
- fitPrimary: styleWithPrefix("sb-fit-primary")`
1270
+ fitPrimaryHeight: styleWithPrefix("sb-fit-primary-height")`
1271
+ @layer components {
1272
+ flex-basis: auto;
1273
+ flex-shrink: 0;
1274
+ }
1275
+ `,
1276
+ fitPrimaryWidth: styleWithPrefix("sb-fit-primary-width")`
1285
1277
  @layer components {
1286
1278
  flex-basis: auto;
1287
1279
  }
@@ -1410,7 +1402,8 @@ const getWidthHeightInfo = (dim, dimension, instanceId) => {
1410
1402
  if (dimension === "width") return { classnames: [Classes.fitWidth] };
1411
1403
  return { classnames: [Classes.fitHeight] };
1412
1404
  }
1413
- if (primaryDimension) return { classnames: [Classes.fitPrimary] };
1405
+ if (primaryDimension) if (dimension === "height") return { classnames: [Classes.fitPrimaryHeight] };
1406
+ else return { classnames: [Classes.fitPrimaryWidth] };
1414
1407
  if (dimension === "width") return { classnames: [Classes.fitSecondaryWidth] };
1415
1408
  return { classnames: [Classes.fitSecondaryHeight] };
1416
1409
  case "fill":
@@ -1440,9 +1433,6 @@ const getWidthHeightInfo = (dim, dimension, instanceId) => {
1440
1433
  default: return { classnames: [] };
1441
1434
  }
1442
1435
  };
1443
- const getMinMaxCss = (dim, dimension) => {
1444
- return dim ? dim.mode === "fill" ? { [dimension]: "100%" } : dimToCSS(dim, dimension) : {};
1445
- };
1446
1436
 
1447
1437
  //#endregion
1448
1438
  //#region src/lib/user-facing/properties-panel/mixins/appearance-properties.ts
@@ -1518,74 +1508,11 @@ const borderRadius = (propertiesPanelConfig = {}) => {
1518
1508
 
1519
1509
  //#endregion
1520
1510
  //#region src/lib/user-facing/properties-panel/mixins/layout-section.ts
1521
- const getSizeProp = ({ label, controlType, defaultValue, defaultOnAdd, isVisible }) => {
1522
- let sizeProp = Prop.dimension().readAndWrite().propertiesPanel({
1523
- label,
1524
- controlType
1525
- });
1526
- if (defaultValue !== void 0 || defaultOnAdd !== void 0) {
1527
- sizeProp = sizeProp.propertiesPanel({
1528
- label,
1529
- controlType,
1530
- isRemovable: true,
1531
- visibility: "SHOW_NAME",
1532
- defaultOnAdd,
1533
- isVisible
1534
- });
1535
- if (defaultValue) sizeProp = sizeProp.default(defaultValue);
1536
- }
1537
- return sizeProp.docs({ description: `Controls the ${label.toLowerCase()} dimension of the component` });
1538
- };
1539
1511
  /**
1540
1512
  * Sets width default to `fill` if no default width config provided.
1541
1513
  * Sets height default to `fit` if no default height config provided.
1542
1514
  */
1543
- const size = ({ defaults, defaultsOnAdd = {
1544
- minWidth: Dim$1.px(0),
1545
- minHeight: Dim$1.px(0),
1546
- maxWidth: Dim$1.px(200),
1547
- maxHeight: Dim$1.px(120)
1548
- }, hasMinWidth = true, hasMaxWidth = true, hasMinHeight = true, hasMaxHeight = true, showMinWidth, showMinHeight, showMaxWidth, showMaxHeight, showWidth, showHeight } = {}) => {
1549
- const minWidthProperty = getSizeProp({
1550
- label: "Min width",
1551
- controlType: "WIDTH_DROPDOWN",
1552
- defaultValue: defaults?.minWidth,
1553
- defaultOnAdd: defaultsOnAdd?.minWidth,
1554
- isVisible: function(s) {
1555
- const hideWidth = this?.width?.mode === "px";
1556
- return Boolean((showMinWidth ? showMinWidth?.call(this, s) : true) && !hideWidth);
1557
- }
1558
- });
1559
- const maxWidthProperty = getSizeProp({
1560
- label: "Max width",
1561
- controlType: "WIDTH_DROPDOWN",
1562
- defaultValue: defaults?.maxWidth,
1563
- defaultOnAdd: defaultsOnAdd?.maxWidth,
1564
- isVisible: function(s) {
1565
- const hideWidth = this?.width?.mode === "px";
1566
- return Boolean((showMaxWidth ? showMaxWidth?.call(this, s) : true) && !hideWidth);
1567
- }
1568
- });
1569
- const minHeightProperty = getSizeProp({
1570
- label: "Min height",
1571
- controlType: "HEIGHT_DROPDOWN",
1572
- defaultValue: defaults?.minHeight,
1573
- defaultOnAdd: defaultsOnAdd?.minHeight,
1574
- isVisible: function(s) {
1575
- const hideHeight = this?.height?.mode === "px";
1576
- return Boolean((showMinHeight ? showMinHeight?.call(this, s) : true) && !hideHeight);
1577
- }
1578
- });
1579
- const maxHeightProperty = getSizeProp({
1580
- label: "Max height",
1581
- controlType: "HEIGHT_DROPDOWN",
1582
- defaultValue: defaults?.maxHeight,
1583
- defaultOnAdd: defaultsOnAdd?.maxHeight,
1584
- isVisible: function(s) {
1585
- const hideHeight = this?.height?.mode === "px";
1586
- return Boolean((showMaxHeight ? showMaxHeight?.call(this, s) : true) && !hideHeight);
1587
- }
1588
- });
1515
+ const size = ({ defaults, showWidth, showHeight } = {}) => {
1589
1516
  let heightProperty = Prop.dimension().readAndWrite().propertiesPanel({
1590
1517
  label: "Height",
1591
1518
  controlType: "HEIGHT_DROPDOWN",
@@ -1604,11 +1531,7 @@ const size = ({ defaults, defaultsOnAdd = {
1604
1531
  widthProperty = widthProperty.docs({ description: "Sets the width of the component" });
1605
1532
  return {
1606
1533
  width: widthProperty,
1607
- height: heightProperty,
1608
- ...hasMinWidth ? { minWidth: minWidthProperty } : {},
1609
- ...hasMaxWidth ? { maxWidth: maxWidthProperty } : {},
1610
- ...hasMinHeight ? { minHeight: minHeightProperty } : {},
1611
- ...hasMaxHeight ? { maxHeight: maxHeightProperty } : {}
1534
+ height: heightProperty
1612
1535
  };
1613
1536
  };
1614
1537
  /** @deprecated Using it will override the defaults values defined in size() for width */
@@ -1824,69 +1747,69 @@ const loading = () => Prop.boolean().default(void 0).readAndWrite().propertiesPa
1824
1747
  //#endregion
1825
1748
  //#region src/lib/user-facing/components/stack/stack-classes.ts
1826
1749
  const STACK_CLASSES = {
1827
- base: styleAsClass`
1750
+ base: styleWithPrefix("sb-stack-base")`
1828
1751
  @layer components {
1829
1752
  display: flex;
1830
1753
  position: relative;
1831
1754
  box-sizing: border-box;
1832
1755
  }
1833
1756
  `,
1834
- directionColumn: styleAsClass`
1757
+ directionColumn: styleWithPrefix("sb-direction-column")`
1835
1758
  @layer components {
1836
1759
  flex-direction: column;
1837
1760
  }
1838
1761
  `,
1839
- directionRow: styleAsClass`
1762
+ directionRow: styleWithPrefix("sb-direction-row")`
1840
1763
  @layer components {
1841
1764
  flex-direction: row;
1842
1765
  }
1843
1766
  `,
1844
- justifyStart: styleAsClass`
1767
+ justifyStart: styleWithPrefix("sb-justify-start")`
1845
1768
  @layer components {
1846
1769
  justify-content: flex-start;
1847
1770
  }
1848
1771
  `,
1849
- justifyCenter: styleAsClass`
1772
+ justifyCenter: styleWithPrefix("sb-justify-center")`
1850
1773
  @layer components {
1851
1774
  justify-content: center;
1852
1775
  }
1853
1776
  `,
1854
- justifyEnd: styleAsClass`
1777
+ justifyEnd: styleWithPrefix("sb-justify-end")`
1855
1778
  @layer components {
1856
1779
  justify-content: flex-end;
1857
1780
  }
1858
1781
  `,
1859
- justifySpaceBetween: styleAsClass`
1782
+ justifySpaceBetween: styleWithPrefix("sb-justify-space-between")`
1860
1783
  @layer components {
1861
1784
  justify-content: space-between;
1862
1785
  }
1863
1786
  `,
1864
- justifySpaceAround: styleAsClass`
1787
+ justifySpaceAround: styleWithPrefix("sb-justify-space-around")`
1865
1788
  @layer components {
1866
1789
  justify-content: space-around;
1867
1790
  }
1868
1791
  `,
1869
- alignStart: styleAsClass`
1792
+ alignStart: styleWithPrefix("sb-align-start")`
1870
1793
  @layer components {
1871
1794
  align-items: flex-start;
1872
1795
  }
1873
1796
  `,
1874
- alignCenter: styleAsClass`
1797
+ alignCenter: styleWithPrefix("sb-align-center")`
1875
1798
  @layer components {
1876
1799
  align-items: center;
1877
1800
  }
1878
1801
  `,
1879
- alignEnd: styleAsClass`
1802
+ alignEnd: styleWithPrefix("sb-align-end")`
1880
1803
  @layer components {
1881
1804
  align-items: flex-end;
1882
1805
  }
1883
1806
  `,
1884
- alignStretch: styleAsClass`
1807
+ alignStretch: styleWithPrefix("sb-align-stretch")`
1885
1808
  @layer components {
1886
1809
  align-items: stretch;
1887
1810
  }
1888
1811
  `,
1889
- overflowAuto: styleAsClass`
1812
+ overflowAuto: styleWithPrefix("sb-overflow-auto")`
1890
1813
  @layer components {
1891
1814
  overflow: auto;
1892
1815
  }
@@ -2145,11 +2068,12 @@ const InternalStack = observer(({ direction = "column", spacing: spacing$1, chil
2145
2068
  return /* @__PURE__ */ jsx("div", {
2146
2069
  className: combinedClassName,
2147
2070
  ...rest,
2071
+ ref: props.dropTargetRef,
2148
2072
  children
2149
2073
  });
2150
2074
  });
2151
2075
  const InternalVStack = (props) => {
2152
- const { verticalAlign, horizontalAlign,...rest } = props;
2076
+ const { verticalAlign,...rest } = props;
2153
2077
  return /* @__PURE__ */ jsx(InternalStack, {
2154
2078
  direction: "column",
2155
2079
  ...rest,
@@ -2236,7 +2160,7 @@ const InternalContainer = (props) => {
2236
2160
  height: "100%",
2237
2161
  width: "100%"
2238
2162
  }), [alignmentStyles]);
2239
- const shouldApplyEmptyContainerMinHeight = isEditing && props.height?.mode !== "px" && props.minHeight?.mode !== "px" && props.maxHeight?.mode !== "px" && isEmpty(props.children);
2163
+ const shouldApplyEmptyContainerMinHeight = isEditing && props.height?.mode !== "px" && isEmpty(props.children);
2240
2164
  const containerStyle = useMemo(() => ({
2241
2165
  display: "grid",
2242
2166
  gridTemplate: "minmax(0px, 1fr) / minmax(0px, 1fr)",
@@ -3119,26 +3043,12 @@ const useStyleWithSize = (props, instanceId) => {
3119
3043
  use_stable_effect_default(() => {
3120
3044
  const widthInfo = props.width ? getWidthHeightInfo(props.width, "width", instanceId) : { classnames: [] };
3121
3045
  const heightInfo = props.height ? getWidthHeightInfo(props.height, "height", instanceId) : { classnames: [] };
3122
- const minWidthCss = getMinMaxCss(props.minWidth, "minWidth");
3123
- const maxWidthCss = getMinMaxCss(props.maxWidth, "maxWidth");
3124
- const minHeightCss = getMinMaxCss(props.minHeight, "minHeight");
3125
- const maxHeightCss = getMinMaxCss(props.maxHeight, "maxHeight");
3126
- setStyle({
3127
- ...minWidthCss,
3128
- ...maxWidthCss,
3129
- ...minHeightCss,
3130
- ...maxHeightCss,
3131
- ...props.style
3132
- });
3046
+ if (props.style) setStyle(props.style);
3133
3047
  setClassNames([...widthInfo.classnames, ...heightInfo.classnames]);
3134
3048
  }, {
3135
3049
  instanceId,
3136
3050
  width: props.width,
3137
3051
  height: props.height,
3138
- minHeight: props.minHeight,
3139
- minWidth: props.minWidth,
3140
- maxHeight: props.maxHeight,
3141
- maxWidth: props.maxWidth,
3142
3052
  style: props.style
3143
3053
  }, {
3144
3054
  cold: true,
@@ -3196,8 +3106,12 @@ const ReactiveComponent = observer(function Component$1({ Component: Component$2
3196
3106
  const editorClickHandler = editorProps?.onClick;
3197
3107
  const handleClick = useCallback(async (e, ...rest) => {
3198
3108
  if (typeof realClickHandler === "function") realClickHandler(e, ...rest);
3199
- const extraClickHandler = editorClickHandler;
3200
- if (typeof extraClickHandler === "function") extraClickHandler(e);
3109
+ try {
3110
+ const extraClickHandler = editorClickHandler;
3111
+ if (typeof extraClickHandler === "function") extraClickHandler(e);
3112
+ } catch (error) {
3113
+ console.error("Editor click handler error", error);
3114
+ }
3201
3115
  }, [editorClickHandler, realClickHandler]);
3202
3116
  const hide = shouldHideComponent(reactiveProps?.isVisible);
3203
3117
  const fallbackPassthroughProps = useMemo(() => {
@@ -3336,10 +3250,13 @@ const getWidgetNode = (instanceId) => {
3336
3250
  const type = root_store_default.nameManager.getExistingIdentifier(instanceId)?.type;
3337
3251
  return document?.querySelector(`[data-sb-selector="${getEditWrapperIdWithType(instanceId, type)}"]`);
3338
3252
  };
3339
- const getIsComponentInInteractionLayer = (instanceId) => {
3253
+ const doesInteractionLayerContainInstance = (possibleParent, possibleChild) => {
3254
+ if (!possibleParent || !possibleChild) return false;
3340
3255
  const editStore = getEditStore();
3341
- const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
3342
- return !activeRootInstanceId || instanceId && (instanceId === activeRootInstanceId || editStore.runtimeEntitiesManager.isChildOf(instanceId, activeRootInstanceId));
3256
+ const parentMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(possibleParent);
3257
+ const childMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(possibleChild);
3258
+ if (editStore.interactionLayerManager.interactionLayerInstanceIds.has(possibleParent)) return possibleChild === possibleParent || childMeta?.interactionLayerInstanceId === possibleParent;
3259
+ return parentMeta?.interactionLayerInstanceId === childMeta?.interactionLayerInstanceId;
3343
3260
  };
3344
3261
 
3345
3262
  //#endregion
@@ -3361,7 +3278,29 @@ function rule(description, restriction) {
3361
3278
  restriction
3362
3279
  };
3363
3280
  }
3364
- const restrictions = [
3281
+ const instanceRestrictions = [
3282
+ rule("Drop target and dragged instance must be in the same interaction layer", ({ dropTargetInstanceId, draggedInstanceId, isDraggingNewComponent }) => {
3283
+ if (isDraggingNewComponent || !draggedInstanceId) return false;
3284
+ return !doesInteractionLayerContainInstance(dropTargetInstanceId, draggedInstanceId);
3285
+ }),
3286
+ rule("Dragged instance must not be a child of the drop target", ({ dropTargetInstanceId, draggedInstanceId }) => {
3287
+ if (!dropTargetInstanceId || !draggedInstanceId) return false;
3288
+ return getEditStore().runtimeEntitiesManager.isChildOf(dropTargetInstanceId, draggedInstanceId);
3289
+ }),
3290
+ rule("If the dragged instance has local bindings, it must share its root instance with the drop target", ({ dropTargetInstanceId, draggedInstanceId }) => {
3291
+ if (!dropTargetInstanceId || !draggedInstanceId) return false;
3292
+ const editStore = getEditStore();
3293
+ if (!(draggedInstanceId && editStore.runtimeEntitiesManager.doesEntityHaveLocalBindings(draggedInstanceId))) return false;
3294
+ const dropTargetMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(dropTargetInstanceId);
3295
+ const draggedMeta = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedInstanceId);
3296
+ if (dropTargetMeta?.isRoot) return dropTargetMeta.instanceId !== draggedMeta?.rootInstanceId;
3297
+ else return dropTargetMeta?.rootInstanceId !== draggedMeta?.rootInstanceId;
3298
+ })
3299
+ ];
3300
+ const areDragAndDropInstancesValid = (params) => {
3301
+ return instanceRestrictions.find((restriction) => restriction.restriction(params)) == null;
3302
+ };
3303
+ const typeRestrictions = [
3365
3304
  rule("Draggable type must be draggable", ({ draggedType, isDraggingNewComponent }) => !isDraggingNewComponent && !isTypeDraggable(draggedType)),
3366
3305
  rule("Drop target type must be droppable", ({ dropTargetType }) => !isTypeDroppable(dropTargetType)),
3367
3306
  rule("Only containers can be dropped on non empty pages", ({ draggedType, dropTargetType, dropTargetEmpty }) => {
@@ -3369,7 +3308,7 @@ const restrictions = [
3369
3308
  })
3370
3309
  ];
3371
3310
  const isDragAndDropTypeValid = ({ draggedType, dropTargetType, dropTargetEmpty, isDraggingNewComponent }) => {
3372
- return restrictions.find((restriction) => restriction.restriction({
3311
+ return typeRestrictions.find((restriction) => restriction.restriction({
3373
3312
  draggedType,
3374
3313
  dropTargetType,
3375
3314
  dropTargetEmpty,
@@ -3392,23 +3331,6 @@ const isContentDraggable = (type) => {
3392
3331
  if (!isTypeDraggable(type)) return false;
3393
3332
  return root_store_default.componentRegistry.getEditorConfig(type)?.isContentDraggable !== false;
3394
3333
  };
3395
- /**
3396
- * TODO - should use the EditorConfig to determine if the created/dropped component should be wrapped.
3397
- * @param type - the type of the component being created
3398
- * @param parentType - the type of the parent component
3399
- * @returns
3400
- * - [false] if the component should not be wrapped
3401
- * - [true, wrapInType] if the component should be wrapped in the given type
3402
- */
3403
- function shouldWrapComponent(type, parentType) {
3404
- if (isComponentTypeDetached(type)) return [false];
3405
- if (!parentType) return [false];
3406
- if (parentType.includes("Modal") || parentType.includes("Slideout") || parentType.includes("Sheet") || parentType.includes("Dialog") || parentType === NATIVE_COMPONENT_TYPES.Page) {
3407
- if (root_store_default.componentRegistry.containerTypes.has(type)) return [false];
3408
- return [true, root_store_default.componentRegistry.defaultTagNames.container];
3409
- }
3410
- return [false];
3411
- }
3412
3334
  const filterSafeStackDimensionProperties = (existingProps) => {
3413
3335
  const { width, height, size: size$1 } = existingProps;
3414
3336
  const safeDimensions = {};
@@ -3462,13 +3384,13 @@ const DroppableWidget = observer((props) => {
3462
3384
  const widgetNode = useWidgetNodeRef(props.instanceId);
3463
3385
  useEffect(() => {
3464
3386
  let targetNode = null;
3465
- if (props.dropTargetRef?.current) targetNode = props.dropTargetRef.current;
3387
+ if (props.dropTargetElem) targetNode = props.dropTargetElem;
3466
3388
  else if (widgetNode) targetNode = widgetNode;
3467
3389
  if (targetNode) setDroppableNodeRef(targetNode);
3468
3390
  }, [
3469
3391
  widgetNode,
3470
3392
  setDroppableNodeRef,
3471
- props.dropTargetRef
3393
+ props.dropTargetElem
3472
3394
  ]);
3473
3395
  return /* @__PURE__ */ jsx(React.Fragment, { children: props.children });
3474
3396
  });
@@ -3536,6 +3458,28 @@ function ParentIdentifierProvider({ identifier, children }) {
3536
3458
  });
3537
3459
  }
3538
3460
 
3461
+ //#endregion
3462
+ //#region src/edit-mode/interaction-layer/interaction-context.tsx
3463
+ const defaultContext = { rootInstanceId: void 0 };
3464
+ const InteractionLayerContext = createContext(void 0);
3465
+ const useInteractionLayerContext = () => {
3466
+ return useContext(InteractionLayerContext) ?? defaultContext;
3467
+ };
3468
+ const InteractionLayerProvider = (props) => {
3469
+ const context$1 = useMemo(() => ({ rootInstanceId: props.instanceId }), [props.instanceId]);
3470
+ useEffect(() => {
3471
+ const editStore = getEditStore();
3472
+ editStore.interactionLayerManager.addInteractionLayerInstanceId(props.instanceId);
3473
+ return () => {
3474
+ editStore.interactionLayerManager.removeInteractionLayerInstanceId(props.instanceId);
3475
+ };
3476
+ }, [props.instanceId]);
3477
+ return /* @__PURE__ */ jsx(InteractionLayerContext.Provider, {
3478
+ value: context$1,
3479
+ children: props.children
3480
+ });
3481
+ };
3482
+
3539
3483
  //#endregion
3540
3484
  //#region src/lib/internal-details/lib/throttle.ts
3541
3485
  function throttle$1(func, delay) {
@@ -3569,413 +3513,6 @@ const CANVAS_ROOT_ID = "canvas-root";
3569
3513
  const PORTAL_ROOT_ID = "portal-root";
3570
3514
  const POPOVER_ROOT_ID = "sb-popover-root";
3571
3515
 
3572
- //#endregion
3573
- //#region src/edit-mode/dnd/is-nestable.ts
3574
- function isNestable(componentType, _parentType) {
3575
- if (componentType === PAGE_COMPONENT_TYPE) return false;
3576
- return true;
3577
- }
3578
-
3579
- //#endregion
3580
- //#region src/edit-mode/create-component.ts
3581
- function getParentInfo(parent) {
3582
- return { type: getEditStore().runtimeEntitiesManager.getAnyEditorWidgetMeta(parent.id)?.type };
3583
- }
3584
- const generateUniqueName = (componentType) => {
3585
- const baseName = componentType;
3586
- let counter = 1;
3587
- let name = `${baseName}${counter}`;
3588
- while (root_store_default.nameManager.hasEntityWithName(name)) {
3589
- counter++;
3590
- name = `${baseName}${counter}`;
3591
- }
3592
- return name;
3593
- };
3594
- function getBinding({ componentType, editorTemplateCreateRequest }) {
3595
- if (editorTemplateCreateRequest?.generateBinding === true) return Property$1.Static(generateUniqueName(componentType));
3596
- else if (typeof editorTemplateCreateRequest?.generateBinding === "string") return Property$1.Static(editorTemplateCreateRequest.generateBinding);
3597
- else return;
3598
- }
3599
- function getComponentBaseProperties(componentType, _parentInfo, editorTemplateCreateRequest) {
3600
- let properties = {};
3601
- const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
3602
- if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
3603
- if (editorTemplateCreateRequest?.properties) properties = {
3604
- ...properties,
3605
- ...editorTemplateCreateRequest.properties
3606
- };
3607
- const binding = getBinding({
3608
- componentType,
3609
- editorTemplateCreateRequest
3610
- });
3611
- if (binding) properties.name = binding;
3612
- const { width, height, size: size$1 } = properties;
3613
- const safeDimensions = filterSafeStackDimensionProperties({
3614
- width: width?.value,
3615
- height: height?.value,
3616
- size: size$1?.value
3617
- });
3618
- return {
3619
- properties: {
3620
- ...properties,
3621
- ...safeDimensions
3622
- },
3623
- children: editorTemplateCreateRequest?.children ?? []
3624
- };
3625
- }
3626
- function getCreateAtParentElement(relativeParent, createAt) {
3627
- if (createAt === "root") {
3628
- const parentInstanceId = getEditStore().runtimeEntitiesManager.widgets.getAnyInstanceIdForSourceId(relativeParent.id);
3629
- const pageComponent = getEditStore().runtimeEntitiesManager.getClosestAncestorByType(parentInstanceId, "Page");
3630
- if (!pageComponent) throw new Error(`Page component not found for parent: ${relativeParent.id}`);
3631
- return { source: { id: pageComponent.sourceId } };
3632
- } else return { source: relativeParent };
3633
- }
3634
- async function createComponent({ componentType, parent, scopeName, baseProperties = {}, skipSecondaryComponentsCreation, otherComponentsUpdates }) {
3635
- const parentInfo = getParentInfo(parent);
3636
- if (!isNestable(componentType, parentInfo.type)) {
3637
- console.error(`${componentType} cannot be nested under ${parentInfo.type}`);
3638
- return;
3639
- }
3640
- const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
3641
- if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
3642
- const context$1 = {
3643
- generateUniqueName,
3644
- parentInfo,
3645
- defaultTagNames: root_store_default.componentRegistry.defaultTagNames,
3646
- selfTagName: componentType
3647
- };
3648
- const editorTemplateCreateRequest = editorTemplates?.[0]?.create?.(context$1);
3649
- const primaryEditorTemplateCreateRequest = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest[0] : editorTemplateCreateRequest;
3650
- 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}`);
3651
- const editorTemplateCreateRequests = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest : [editorTemplateCreateRequest];
3652
- const editStore = getEditStore();
3653
- function editorTemplateCreateRequestToInternalCreateRequest({ editorTemplateCreateRequest: editorTemplateCreateRequest$1, baseProperties: baseProperties$1 }) {
3654
- const type = editorTemplateCreateRequest$1?.type ?? componentType;
3655
- const [shouldWrap, wrapInType] = shouldWrapComponent(type, parentInfo.type);
3656
- const { properties: propertiesFromType, children } = getComponentBaseProperties(type, parentInfo, editorTemplateCreateRequest$1);
3657
- const properties = {
3658
- ...propertiesFromType,
3659
- ...baseProperties$1
3660
- };
3661
- let primaryComponent = {
3662
- parentElement: getCreateAtParentElement(parent, editorTemplateCreateRequest$1?.createAt),
3663
- tagName: type,
3664
- properties,
3665
- children,
3666
- scopeName,
3667
- id: editStore.operationManager.generateSourceId()
3668
- };
3669
- if (shouldWrap) primaryComponent = wrapComponentIfNecessary(primaryComponent, wrapInType);
3670
- return primaryComponent;
3671
- }
3672
- const createRequests = editorTemplateCreateRequests.map((editorTemplateCreateRequest$1, index) => editorTemplateCreateRequestToInternalCreateRequest({
3673
- editorTemplateCreateRequest: editorTemplateCreateRequest$1,
3674
- baseProperties: index === 0 ? baseProperties : {}
3675
- }));
3676
- const hasOtherComponentsUpdates = otherComponentsUpdates && Object.keys(otherComponentsUpdates).length > 0;
3677
- const hasMultipleCreateComponents = editorTemplateCreateRequests.length > 1 && !skipSecondaryComponentsCreation;
3678
- if (hasOtherComponentsUpdates || hasMultipleCreateComponents) {
3679
- const performOtherComponentsUpdates = (otherComponentsUpdates$1) => {
3680
- Object.entries(otherComponentsUpdates$1).forEach(([sourceId, updates]) => {
3681
- editStore.operationManager.setWidgetProperties({
3682
- sourceId,
3683
- properties: updates
3684
- });
3685
- });
3686
- };
3687
- editStore.operationManager.batchUpdate(() => {
3688
- if (skipSecondaryComponentsCreation) editStore.operationManager.createComponent(createRequests[0]);
3689
- else createRequests.forEach((createRequest) => {
3690
- editStore.operationManager.createComponent(createRequest);
3691
- });
3692
- if (hasOtherComponentsUpdates) performOtherComponentsUpdates(otherComponentsUpdates);
3693
- });
3694
- } else editStore.operationManager.createComponent(createRequests[0]);
3695
- /**
3696
- * Returns the single id, or the the last component if there are multiple.
3697
- * See EditorTemplate's definition to understand why.
3698
- */
3699
- return createRequests.at(-1).id;
3700
- }
3701
- function wrapComponentIfNecessary(primaryComponent, wrapInType) {
3702
- if (!wrapInType) return primaryComponent;
3703
- const { properties } = getComponentBaseProperties(wrapInType, { type: "Page" });
3704
- const [_$1, continueWrappingInType] = shouldWrapComponent(primaryComponent.tagName, wrapInType);
3705
- return {
3706
- parentElement: primaryComponent.parentElement,
3707
- tagName: wrapInType,
3708
- id: getEditStore().operationManager.generateSourceId(),
3709
- properties,
3710
- children: [wrapComponentIfNecessary(primaryComponent, continueWrappingInType)]
3711
- };
3712
- }
3713
-
3714
- //#endregion
3715
- //#region src/edit-mode/dnd/handle-stack-drop.ts
3716
- const mergeDroppedDimensions = (draggedType, draggedProps, activeDragRect) => {
3717
- const safeExistingDimensions = filterSafeStackDimensionProperties({
3718
- width: draggedProps?.width,
3719
- height: draggedProps?.height,
3720
- size: draggedProps?.size
3721
- });
3722
- const width = safeExistingDimensions.width;
3723
- const height = safeExistingDimensions.height;
3724
- if (draggedType === "Icon") return { size: safeExistingDimensions.size ?? (activeDragRect?.height ? Property$1.Dimension(Dim$1.px(activeDragRect.height)) : Property$1.Static("")) };
3725
- return {
3726
- width,
3727
- height
3728
- };
3729
- };
3730
- const handleStackDropWithinCanvas = (params) => {
3731
- const { dropInfo, draggedId, dropTargetId } = params;
3732
- const editStore = getEditStore();
3733
- const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
3734
- const draggedSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(draggedId);
3735
- if (!dropSourceId || !draggedSourceId) throw new Error(`Missing IDs: dragging ${draggedId} to ${dropTargetId}`);
3736
- console.log(`Dragged ${draggedSourceId} to ${dropSourceId}`, {
3737
- dropInfo,
3738
- index: dropInfo.insertionIndex
3739
- });
3740
- if (dropInfo.noopDrop) return;
3741
- const draggedType = editStore.runtimeEntitiesManager.getEditorWidgetType(draggedId);
3742
- const dropTargetType = editStore.runtimeEntitiesManager.getEditorWidgetType(dropTargetId);
3743
- if (!draggedType) throw new Error(`Missing dragged type: ${draggedId}`);
3744
- const [shouldWrap, wrapInType] = shouldWrapComponent(draggedType, dropTargetType);
3745
- const activeDragRect = editStore.ui.dnd.activeDragRect;
3746
- if (shouldWrap) dropComponentAndWrap({
3747
- draggedId,
3748
- draggedSourceId,
3749
- dropTargetId,
3750
- dropSourceId,
3751
- dropInfo,
3752
- dropTargetType,
3753
- activeDragRect,
3754
- wrapInType
3755
- });
3756
- else {
3757
- const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
3758
- editStore.operationManager.dropComponent({
3759
- from: { source: { id: draggedSourceId } },
3760
- to: { source: {
3761
- id: dropSourceId,
3762
- index: dropInfo.insertionIndex
3763
- } },
3764
- propsToChange: { ...mergeDroppedDimensions(draggedType, draggedProps, activeDragRect) }
3765
- });
3766
- }
3767
- };
3768
- const dropComponentAndWrap = async (params) => {
3769
- const { draggedId, draggedSourceId, dropSourceId, dropTargetId, dropInfo, dropTargetType, activeDragRect, wrapInType } = params;
3770
- const editStore = getEditStore();
3771
- const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
3772
- if (!dropScopeId) throw new Error(`Missing drop scope id: ${dropTargetId}`);
3773
- const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
3774
- const newComponentSourceId = await createComponent({
3775
- componentType: wrapInType,
3776
- parent: {
3777
- index: dropInfo.insertionIndex,
3778
- id: dropSourceId
3779
- },
3780
- scopeName
3781
- });
3782
- if (!newComponentSourceId) throw new Error("Missing new component source id");
3783
- const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
3784
- editStore.operationManager.dropComponent({
3785
- from: { source: { id: draggedSourceId } },
3786
- to: { source: {
3787
- id: newComponentSourceId,
3788
- index: 0
3789
- } },
3790
- propsToChange: { ...mergeDroppedDimensions(dropTargetType, draggedProps, activeDragRect) }
3791
- });
3792
- };
3793
- const handleStackDropForNewComponent = ({ componentType, dropInfo, dropTargetId }) => {
3794
- const editStore = getEditStore();
3795
- const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
3796
- const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
3797
- if (!dropSourceId || !dropScopeId) throw new Error("Missing drop source id");
3798
- const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
3799
- return createComponent({
3800
- componentType,
3801
- parent: {
3802
- index: dropInfo.insertionIndex,
3803
- id: dropSourceId
3804
- },
3805
- scopeName
3806
- });
3807
- };
3808
- const handleStackDrop = async ({ dropInfo, draggedId, dropTargetId, isDraggingNewComponent, newComponentType }) => {
3809
- if (dropInfo.insertionIndex == null) throw new Error("No insertion index found");
3810
- if (isDraggingNewComponent) {
3811
- if (!newComponentType) throw new Error("Missing componentType to create new component");
3812
- return handleStackDropForNewComponent({
3813
- componentType: newComponentType,
3814
- dropTargetId,
3815
- dropInfo
3816
- });
3817
- } else {
3818
- if (!draggedId) throw new Error("Missing dragged id");
3819
- handleStackDropWithinCanvas({
3820
- dropInfo,
3821
- draggedId,
3822
- dropTargetId
3823
- });
3824
- }
3825
- };
3826
-
3827
- //#endregion
3828
- //#region src/edit-mode/dnd/hooks/use-handle-dnd-events.ts
3829
- const measureRect = (id) => {
3830
- const rect = id ? getBoundingBoxForWidget(id) : null;
3831
- if (!rect) return null;
3832
- return {
3833
- left: rect.left,
3834
- top: rect.top,
3835
- right: rect.right,
3836
- bottom: rect.bottom,
3837
- width: rect.width,
3838
- height: rect.height
3839
- };
3840
- };
3841
- /**
3842
- * We have to follow a few rules while drag and dropping:
3843
- * 1. You can drag and drop within your own function component/scope
3844
- * 2. You can drag to another function component, but only if it doesn't break references to local variables in the current function component
3845
- * > 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
3846
- * @param overSourceId the widget ID we are currently dragging over
3847
- * @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
3848
- * @returns true if the drop target is invalid
3849
- */
3850
- const isInvalidDropTarget = (overInstanceId, overRootInstanceId) => {
3851
- const activeRootInstanceIds = getEditStore().ui.dnd.validRootIds;
3852
- return Boolean(activeRootInstanceIds && !activeRootInstanceIds.includes(overInstanceId) && !activeRootInstanceIds.includes(overRootInstanceId)) || isDroppingOnAncestor(overInstanceId);
3853
- };
3854
- const isDroppingOnAncestor = (overInstanceId) => {
3855
- if (overInstanceId) {
3856
- const editStore = getEditStore();
3857
- const ancestorIds = /* @__PURE__ */ new Set();
3858
- let currentId = overInstanceId;
3859
- let iterations = 0;
3860
- const MAX_ITERATIONS$1 = 1e3;
3861
- while (currentId && iterations < MAX_ITERATIONS$1) {
3862
- const entity = editStore.runtimeEntitiesManager.getEditorWidgetMeta(currentId);
3863
- if (entity?.parentInstanceId) {
3864
- ancestorIds.add(entity.parentInstanceId);
3865
- currentId = entity.parentInstanceId;
3866
- } else break;
3867
- iterations++;
3868
- }
3869
- return Array.from(ancestorIds).some((id) => editStore.ui.isInstanceSelected(id));
3870
- }
3871
- return false;
3872
- };
3873
- const useHandleDnDEvents = () => {
3874
- const setActiveDragRect = useMemo(() => {
3875
- const editStore = getEditStore();
3876
- const throttled = throttle((rect) => {
3877
- editStore.ui.dnd.setActiveDragRect(rect);
3878
- }, 10, {
3879
- leading: true,
3880
- trailing: true
3881
- });
3882
- return (val) => {
3883
- throttled(val);
3884
- };
3885
- }, []);
3886
- const setActiveTargetInfo = useMemo(() => {
3887
- const editStore = getEditStore();
3888
- const throttled = throttle((id, rect) => {
3889
- editStore.ui.dnd.setDropTargetId(id);
3890
- editStore.ui.dnd.setActiveTargetRect(rect);
3891
- }, 10, {
3892
- leading: true,
3893
- trailing: true
3894
- });
3895
- return (id, val) => {
3896
- throttled(id, val);
3897
- };
3898
- }, []);
3899
- useDndMonitor({
3900
- onDragStart: useCallback((event) => {
3901
- const editStore = getEditStore();
3902
- const activeData = event.active?.data.current;
3903
- if (!activeData && !editStore.ui.dnd.isDraggingNewComponent) {
3904
- console.error("No active widget data");
3905
- return;
3906
- }
3907
- const activeRootInstanceId = (activeData?.instanceId && editStore.runtimeEntitiesManager.getEditorWidgetMeta(activeData?.instanceId))?.rootInstanceId;
3908
- const hasLocalBinding = activeData?.instanceId && editStore.runtimeEntitiesManager.doesEntityHaveLocalBindings(activeData?.instanceId);
3909
- if (activeRootInstanceId && hasLocalBinding) editStore.ui.dnd.setValidRootIds([activeRootInstanceId]);
3910
- editStore.ui.dnd.setDropTargetId(null);
3911
- editStore.ui.dnd.setIsDragging(true);
3912
- if (editStore.ui.dnd.isDraggingNewComponent) {
3913
- editStore.ui.selectWidget(null);
3914
- editStore.ui.dnd.resizePageIfNeeded();
3915
- } else editStore.ui.selectWidget(event.active?.id ? event.active.id : null, event.activatorEvent?.shiftKey);
3916
- }, []),
3917
- onDragMove: useCallback((event) => {
3918
- const editStore = getEditStore();
3919
- const overData = event.over?.data.current;
3920
- const overRootId = overData?.rootInstanceId ?? null;
3921
- const overInstanceId = overData?.instanceId ?? null;
3922
- editStore.ui.dnd.setInvalidDropTarget(isInvalidDropTarget(overInstanceId, overRootId));
3923
- setActiveTargetInfo(event.over?.id ?? null, event.over?.rect ?? null);
3924
- const collisionRect = event.collisions?.[0]?.data?.injectedCollisionRect;
3925
- if (collisionRect) setActiveDragRect(collisionRect);
3926
- else setActiveDragRect(null);
3927
- }, [setActiveDragRect, setActiveTargetInfo]),
3928
- onDragOver: useCallback((event) => {
3929
- const editStore = getEditStore();
3930
- const overData = event.over?.data.current;
3931
- const overRootId = overData?.rootInstanceId ?? null;
3932
- const overInstanceId = overData?.instanceId ?? null;
3933
- editStore.ui.dnd.setInvalidDropTarget(isInvalidDropTarget(overInstanceId, overRootId));
3934
- const overId = event.over?.id ? String(event.over?.id) : null;
3935
- setActiveTargetInfo(overId, measureRect(overId));
3936
- }, [setActiveTargetInfo]),
3937
- onDragCancel: useCallback((_event) => {
3938
- const editStore = getEditStore();
3939
- editStore.ui.dnd.setIsDragging(false);
3940
- editStore.ui.dnd.cancelNewComponentDrag();
3941
- }, []),
3942
- onDragEnd: useCallback(async (event) => {
3943
- const editStore = getEditStore();
3944
- let possibleNewComponentId;
3945
- try {
3946
- if (editStore.ui.dnd.invalidDropTarget) {
3947
- editorBridge.sendNotification("error", "You cannot drop a component here.");
3948
- return;
3949
- }
3950
- const dropTargetId = event.over?.id ? String(event.over.id) : null;
3951
- const draggedId = event.active?.id ? String(event.active?.id) : null;
3952
- const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
3953
- if (dropTargetId && activeRootInstanceId && !(editStore.runtimeEntitiesManager.isChildOf(dropTargetId, activeRootInstanceId) || dropTargetId === activeRootInstanceId)) return;
3954
- if (dropTargetId !== editStore.ui.dnd.dropTargetId) throw new Error("Drop target id and drag over id do not match");
3955
- if (!dropTargetId) throw new Error("No drop target id");
3956
- if (editStore.ui.dnd.isDropTargetStackLike) {
3957
- const dropInfo = editStore.ui.dnd.stack.refreshPositionsAndGetDropIndex();
3958
- possibleNewComponentId = await handleStackDrop({
3959
- dropInfo,
3960
- isDraggingNewComponent: editStore.ui.dnd.isDraggingNewComponent,
3961
- newComponentType: editStore.ui.dnd.dragToCanvasComponentType,
3962
- dropTargetId,
3963
- draggedId
3964
- });
3965
- } else throw new Error("Grid is no longer supported");
3966
- } catch (e) {
3967
- console.error("Error dropping item", e);
3968
- } finally {
3969
- runInAction(() => {
3970
- editStore.ui.dnd.setIsDragging(false);
3971
- editStore.ui.dnd.cancelNewComponentDrag();
3972
- if (possibleNewComponentId) editStore.ui.selectNewComponentBySourceId(possibleNewComponentId);
3973
- });
3974
- }
3975
- }, [])
3976
- });
3977
- };
3978
-
3979
3516
  //#endregion
3980
3517
  //#region src/edit-mode/dnd/stack-drop.tsx
3981
3518
  const StackDropPreview = observer(() => {
@@ -3992,7 +3529,7 @@ const StackDropPreview = observer(() => {
3992
3529
  bottom: "anchor(bottom)",
3993
3530
  positionAnchor: getWidgetDropAreaAnchorName(dropTargetId, dropTargetWidgetType)
3994
3531
  },
3995
- children: [!editStore.ui.dnd.invalidDropTarget && placeholders ? /* @__PURE__ */ jsx(Fragment, { children: placeholders.map((placeholder) => /* @__PURE__ */ jsx("div", {
3532
+ children: [editStore.ui.dnd.isProspectiveDropValid && placeholders ? /* @__PURE__ */ jsx(Fragment, { children: placeholders.map((placeholder) => /* @__PURE__ */ jsx("div", {
3996
3533
  className: "sb-edit-drop-placeholder",
3997
3534
  style: {
3998
3535
  top: placeholder.top,
@@ -4005,36 +3542,24 @@ const StackDropPreview = observer(() => {
4005
3542
  "data-is-valid-drop": true
4006
3543
  }, placeholder.top + placeholder.left)) }) : null, /* @__PURE__ */ jsx("div", {
4007
3544
  className: "sb-edit-drop-target-outline",
4008
- "data-invalid-target": editStore.ui.dnd.invalidDropTarget
3545
+ "data-invalid-target": !editStore.ui.dnd.isProspectiveDropValid
4009
3546
  })]
4010
3547
  });
4011
3548
  });
4012
3549
 
4013
3550
  //#endregion
4014
3551
  //#region src/edit-mode/dnd/drop-layer.tsx
4015
- const DropLayer = observer(() => {
4016
- useHandleDnDEvents();
3552
+ const DropLayer = observer((props) => {
4017
3553
  const editStore = getEditStore();
4018
3554
  const draggedWidgetType = editStore.ui.dnd.draggedWidgetType;
4019
3555
  const dropTargetWidgetType = editStore.ui.dnd.dropTargetWidgetType;
4020
3556
  const isDropTargetStackLike = editStore.ui.dnd.isDropTargetStackLike;
4021
3557
  const dropTargetId = editStore.ui.dnd.dropTargetId;
4022
- const isDropTargetInInteractionLayer = getIsComponentInInteractionLayer(dropTargetId);
4023
- const isDragging = editStore.ui.dnd.isDragging;
4024
- const validStackDrop = isDropTargetInInteractionLayer && isDragging && Boolean(draggedWidgetType && dropTargetWidgetType) && isDropTargetStackLike;
4025
- const isValidDrop = validStackDrop;
4026
- return /* @__PURE__ */ jsxs(Fragment, { children: [validStackDrop && /* @__PURE__ */ jsx(StackDropPreview, {}), /* @__PURE__ */ jsx(DragOverlay, {
3558
+ const isDropTargetInInteractionLayer = doesInteractionLayerContainInstance(props.rootInstanceId, dropTargetId);
3559
+ const possibleStackDrop = editStore.ui.dnd.isDragging && isDropTargetInInteractionLayer && Boolean(draggedWidgetType && dropTargetWidgetType) && isDropTargetStackLike;
3560
+ return /* @__PURE__ */ jsxs(Fragment, { children: [possibleStackDrop && /* @__PURE__ */ jsx(StackDropPreview, {}), /* @__PURE__ */ jsx(DragOverlay, {
4027
3561
  modifiers: [snapCenterToCursor],
4028
- dropAnimation: null,
4029
- children: editStore.ui.dnd.isDraggingNewComponent && /* @__PURE__ */ jsx("div", {
4030
- className: "sb-edit-drag-preview",
4031
- "data-is-valid-drop": isValidDrop,
4032
- style: {
4033
- visibility: "visible",
4034
- height: `${editStore.ui.dnd.draggingWidgetSize.height * 12}px`,
4035
- width: `${editStore.ui.dnd.draggingWidgetSize.width * 12}px`
4036
- }
4037
- })
3562
+ dropAnimation: null
4038
3563
  })] });
4039
3564
  });
4040
3565
  var drop_layer_default = DropLayer;
@@ -4487,18 +4012,18 @@ const useWidgetErrors = (params) => {
4487
4012
  ]);
4488
4013
  };
4489
4014
  const useSelectionElements = (params) => {
4490
- const { focusedInstanceId, selectedInstanceIds, targetedSourceIds, aiContextMode } = params;
4015
+ const { focusedInstanceId, selectedInstanceIds, targetedSourceIds, aiContextMode, rootId } = params;
4491
4016
  const allTargetedComponents = useMemo(() => {
4492
4017
  const components = [];
4493
4018
  targetedSourceIds.forEach((sourceId) => {
4494
4019
  const sourceInstanceIds = getEditStore().runtimeEntitiesManager.widgets.getAllInstanceIdsForSourceId(sourceId);
4495
- components.push(...sourceInstanceIds.map((instanceId) => ({
4020
+ components.push(...sourceInstanceIds.filter((instanceId) => doesInteractionLayerContainInstance(rootId, instanceId)).map((instanceId) => ({
4496
4021
  instanceId,
4497
4022
  sourceId
4498
4023
  })));
4499
4024
  });
4500
4025
  return components;
4501
- }, [targetedSourceIds]);
4026
+ }, [targetedSourceIds, rootId]);
4502
4027
  const visibleTargetedComponents = useViewportIntersection(allTargetedComponents);
4503
4028
  return useObserverMemo(() => {
4504
4029
  const selectedRects = [];
@@ -4513,7 +4038,7 @@ const useSelectionElements = (params) => {
4513
4038
  isVisible
4514
4039
  });
4515
4040
  });
4516
- selectedInstanceIds.forEach((instanceId) => {
4041
+ selectedInstanceIds.filter((instanceId) => doesInteractionLayerContainInstance(rootId, instanceId)).forEach((instanceId) => {
4517
4042
  const { type, displayName, sourceId, isVisible } = selectDisplayNameAndVisibility(instanceId);
4518
4043
  if (sourceId && !targetedSourceIds.includes(sourceId)) selectedRects.push({
4519
4044
  instanceId,
@@ -4524,7 +4049,7 @@ const useSelectionElements = (params) => {
4524
4049
  isVisible
4525
4050
  });
4526
4051
  });
4527
- if (focusedInstanceId && (aiContextMode === AiContextMode.AUTO_SELECT || !selectedInstanceIds.includes(focusedInstanceId))) {
4052
+ if (focusedInstanceId && doesInteractionLayerContainInstance(rootId, focusedInstanceId) && (aiContextMode === AiContextMode.AUTO_SELECT || !selectedInstanceIds.includes(focusedInstanceId))) {
4528
4053
  const { type, displayName, sourceId, isVisible } = selectDisplayNameAndVisibility(focusedInstanceId);
4529
4054
  if (sourceId) selectedRects.push({
4530
4055
  instanceId: focusedInstanceId,
@@ -4541,7 +4066,8 @@ const useSelectionElements = (params) => {
4541
4066
  selectedInstanceIds,
4542
4067
  targetedSourceIds,
4543
4068
  aiContextMode,
4544
- visibleTargetedComponents
4069
+ visibleTargetedComponents,
4070
+ rootId
4545
4071
  ]);
4546
4072
  };
4547
4073
  const InteractionRectTargetBorder = ({ instanceId }) => {
@@ -4773,7 +4299,7 @@ const InteractionLayer = observer((props) => {
4773
4299
  displayName: props.rootName ?? "Unknown",
4774
4300
  hideRectBorder: false
4775
4301
  }, props.rootInstanceId) : null;
4776
- return /* @__PURE__ */ jsxs("div", {
4302
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", {
4777
4303
  className: "sb-interaction-layer-wrapper",
4778
4304
  children: [
4779
4305
  interactionRectsForSelectedElements,
@@ -4784,9 +4310,9 @@ const InteractionLayer = observer((props) => {
4784
4310
  displayName: name,
4785
4311
  instanceId: id
4786
4312
  }, id)),
4787
- props.rootType !== "App" && /* @__PURE__ */ jsx(drop_layer_default, {})
4313
+ /* @__PURE__ */ jsx(drop_layer_default, { rootInstanceId: props.rootInstanceId })
4788
4314
  ]
4789
- });
4315
+ }) });
4790
4316
  });
4791
4317
  var interaction_layer_default = InteractionLayer;
4792
4318
 
@@ -4881,7 +4407,7 @@ const stableEffectOptions$1 = {
4881
4407
  cold: true
4882
4408
  };
4883
4409
  function useRuntimeEditTracking(props) {
4884
- const { parentInstanceId, directParentInstanceId, identifier, type, children, widgetProps, rootInstanceId, indexWithinParent, isRoot, isInsideRoot } = props;
4410
+ const { parentInstanceId, directParentInstanceId, identifier, type, children, widgetProps, rootInstanceId, interactionLayerInstanceId, indexWithinParent, isRoot, isInsideRoot } = props;
4885
4411
  const { children: _children,...rest } = widgetProps;
4886
4412
  use_stable_effect_default(() => {
4887
4413
  const widgetMeta = {
@@ -4896,6 +4422,7 @@ function useRuntimeEditTracking(props) {
4896
4422
  directParentInstanceId,
4897
4423
  sourceId: identifier.sourceId,
4898
4424
  rootInstanceId,
4425
+ interactionLayerInstanceId,
4899
4426
  isRoot,
4900
4427
  isInsideRoot
4901
4428
  };
@@ -4908,6 +4435,7 @@ function useRuntimeEditTracking(props) {
4908
4435
  parentInstanceId,
4909
4436
  directParentInstanceId,
4910
4437
  rootInstanceId,
4438
+ interactionLayerInstanceId,
4911
4439
  type,
4912
4440
  rest
4913
4441
  }, stableEffectOptions$1);
@@ -5007,6 +4535,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5007
4535
  const rootInstanceId = editorRootContext?.instanceId;
5008
4536
  const parentIdentifier = useParentIdentifier();
5009
4537
  const isRoot = ROOT_WIDGET_ATTRIBUTE in props.widgetProps;
4538
+ const { rootInstanceId: interactionLayerInstanceId } = useInteractionLayerContext();
5010
4539
  const children = useRuntimeEditTracking({
5011
4540
  parentInstanceId: parentIdentifier?.instanceId,
5012
4541
  directParentInstanceId: props.directParentInstanceId,
@@ -5015,6 +4544,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5015
4544
  children: props.children,
5016
4545
  widgetProps: props.widgetProps,
5017
4546
  rootInstanceId,
4547
+ interactionLayerInstanceId,
5018
4548
  indexWithinParent: props.indexWithinParent,
5019
4549
  isRoot,
5020
4550
  isInsideRoot
@@ -5043,18 +4573,21 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5043
4573
  const { onContextMenu } = useRightClickMenu({ sourceId: props.identifier.sourceId });
5044
4574
  const showVisibilityBackground = props.widgetProps.isVisible === false && !editStore.ui.getSelectedSourceIds().includes(props.identifier.sourceId);
5045
4575
  const handleClick = useCallback((ev) => {
4576
+ const stopPropagation = () => {
4577
+ if (ev.stopPropagation) ev.stopPropagation();
4578
+ };
5046
4579
  const editStore$1 = getEditStore();
5047
4580
  if (ev.altKey || editStore$1.ai.getIsTaggingEnabled() && editStore$1.ai.shouldToggleComponentInAiContext()) {
5048
4581
  const sourceId = props.identifier.sourceId;
5049
4582
  const instanceId = props.identifier.instanceId;
5050
4583
  editorBridge.toggleComponentInAiContext(sourceId, instanceId);
5051
- ev.stopPropagation();
4584
+ stopPropagation();
5052
4585
  return;
5053
4586
  }
5054
4587
  editStore$1.ui.selectWidget(props.identifier.instanceId, ev.shiftKey === true);
5055
- ev.stopPropagation();
4588
+ stopPropagation();
5056
4589
  }, [props.identifier.sourceId, props.identifier.instanceId]);
5057
- const dropTargetRef = useRef(null);
4590
+ const [dropTargetElem, setDropTargetElem] = useState(null);
5058
4591
  const handleRef = useCallback((el) => {
5059
4592
  setDraggableNodeRef(el);
5060
4593
  }, [setDraggableNodeRef]);
@@ -5092,7 +4625,7 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5092
4625
  identifier,
5093
4626
  widgetProps: props.widgetProps,
5094
4627
  editorProps,
5095
- dropTargetRef,
4628
+ dropTargetRef: setDropTargetElem,
5096
4629
  showErrors: true,
5097
4630
  children: [showVisibilityBackground && /* @__PURE__ */ jsx("div", {
5098
4631
  className: VisibilityOverlayClass,
@@ -5111,10 +4644,13 @@ const EditWrapper = observer(function EditWrapper$1(props) {
5111
4644
  }) : node;
5112
4645
  if (isDroppable) content = /* @__PURE__ */ jsx(droppable_widget_default, {
5113
4646
  instanceId: props.identifier.instanceId,
5114
- dropTargetRef,
4647
+ dropTargetElem,
5115
4648
  children: content
5116
4649
  });
5117
- if (props.type === "App" || props.type === "Page") return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(interaction_layer_default, {
4650
+ if (props.type === "App" || props.type === "Page") return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(InteractionLayerProvider, {
4651
+ instanceId: props.identifier.instanceId,
4652
+ children: content
4653
+ }), /* @__PURE__ */ jsx(interaction_layer_default, {
5118
4654
  rootType: props.type,
5119
4655
  rootInstanceId: props.identifier.instanceId,
5120
4656
  rootName: identifier.name.value
@@ -6385,6 +5921,9 @@ async function connectSocket(serverUrl, { peerId, userId, applicationId, onClose
6385
5921
  removeRegisteredComponent: [async (payload) => {
6386
5922
  root_store_default.componentRegistry.deleteCustomComponent(payload.name);
6387
5923
  }],
5924
+ loadComponents: [async (payload) => {
5925
+ import(payload.componentFilePath);
5926
+ }],
6388
5927
  deleteEntities: [async (payload) => {
6389
5928
  payload.forEach((entity) => {
6390
5929
  if (entity.entityName) root_store_default.entityManager.deleteEntity({
@@ -6628,7 +6167,6 @@ const registerComponentInternal = (type, config, Component$1) => {
6628
6167
  widgetProps,
6629
6168
  component: Component$1,
6630
6169
  identifier: identifier.current,
6631
- isDroppable,
6632
6170
  directParentInstanceId: props[WIDGET_PARENT_INSTANCE_ID_ATTRIBUTE],
6633
6171
  indexWithinParent: props[WIDGET_INDEX_WITHIN_PARENT],
6634
6172
  children: props.children
@@ -6705,10 +6243,7 @@ const propertiesDefinition$4 = {
6705
6243
  height: Dim$1.fill()
6706
6244
  },
6707
6245
  showWidth: () => false,
6708
- hasMinWidth: false,
6709
- hasMinHeight: false,
6710
- hasMaxWidth: false,
6711
- hasMaxHeight: false
6246
+ showHeight: () => false
6712
6247
  })),
6713
6248
  appearance: Section.category(PropsPanelCategory.Appearance).children({ loading: loading() }),
6714
6249
  events: Section.category(PropsPanelCategory.EventHandlers).children({ onLoad: Prop.event().propertiesPanel({ label: "onPageLoad" }) })
@@ -7087,10 +6622,137 @@ const FullPageSpinner = () => {
7087
6622
  function useGetCurrentUserQuery() {
7088
6623
  return useMemo(() => {
7089
6624
  return {
7090
- isLoading: false,
7091
- data: { user: { name: "Test User" } }
6625
+ isLoading: false,
6626
+ data: { user: { name: "Test User" } }
6627
+ };
6628
+ }, []);
6629
+ }
6630
+
6631
+ //#endregion
6632
+ //#region src/edit-mode/dnd/is-nestable.ts
6633
+ function isNestable(componentType, _parentType) {
6634
+ if (componentType === PAGE_COMPONENT_TYPE) return false;
6635
+ return true;
6636
+ }
6637
+
6638
+ //#endregion
6639
+ //#region src/edit-mode/create-component.ts
6640
+ function getParentInfo(parent) {
6641
+ return { type: getEditStore().runtimeEntitiesManager.getAnyEditorWidgetMeta(parent.id)?.type };
6642
+ }
6643
+ const generateUniqueName = (componentType) => {
6644
+ const baseName = componentType;
6645
+ let counter = 1;
6646
+ let name = `${baseName}${counter}`;
6647
+ while (root_store_default.nameManager.hasEntityWithName(name)) {
6648
+ counter++;
6649
+ name = `${baseName}${counter}`;
6650
+ }
6651
+ return name;
6652
+ };
6653
+ function getBinding({ componentType, editorTemplateCreateRequest }) {
6654
+ if (editorTemplateCreateRequest?.generateBinding === true) return Property$1.Static(generateUniqueName(componentType));
6655
+ else if (typeof editorTemplateCreateRequest?.generateBinding === "string") return Property$1.Static(editorTemplateCreateRequest.generateBinding);
6656
+ else return;
6657
+ }
6658
+ function getComponentBaseProperties(componentType, _parentInfo, editorTemplateCreateRequest) {
6659
+ let properties = {};
6660
+ const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
6661
+ if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
6662
+ if (editorTemplateCreateRequest?.properties) properties = {
6663
+ ...properties,
6664
+ ...editorTemplateCreateRequest.properties
6665
+ };
6666
+ const binding = getBinding({
6667
+ componentType,
6668
+ editorTemplateCreateRequest
6669
+ });
6670
+ if (binding) properties.name = binding;
6671
+ const { width, height, size: size$1 } = properties;
6672
+ const safeDimensions = filterSafeStackDimensionProperties({
6673
+ width: width?.value,
6674
+ height: height?.value,
6675
+ size: size$1?.value
6676
+ });
6677
+ return {
6678
+ properties: {
6679
+ ...properties,
6680
+ ...safeDimensions
6681
+ },
6682
+ children: editorTemplateCreateRequest?.children ?? []
6683
+ };
6684
+ }
6685
+ function getCreateAtParentElement(relativeParent, createAt) {
6686
+ if (createAt === "root") {
6687
+ const parentInstanceId = getEditStore().runtimeEntitiesManager.widgets.getAnyInstanceIdForSourceId(relativeParent.id);
6688
+ const pageComponent = getEditStore().runtimeEntitiesManager.getClosestAncestorByType(parentInstanceId, "Page");
6689
+ if (!pageComponent) throw new Error(`Page component not found for parent: ${relativeParent.id}`);
6690
+ return { source: { id: pageComponent.sourceId } };
6691
+ } else return { source: relativeParent };
6692
+ }
6693
+ async function createComponent({ componentType, parent, scopeName, baseProperties = {}, skipSecondaryComponentsCreation, otherComponentsUpdates }) {
6694
+ const parentInfo = getParentInfo(parent);
6695
+ if (!isNestable(componentType, parentInfo.type)) {
6696
+ console.error(`${componentType} cannot be nested under ${parentInfo.type}`);
6697
+ return;
6698
+ }
6699
+ const editorTemplates = root_store_default.componentRegistry.getEditorTemplates(componentType);
6700
+ if (editorTemplates && editorTemplates.length > 1) throw new Error(`Multiple editor templates are not supported yet. Found ${editorTemplates.length} for component type: ${componentType}.`);
6701
+ const context$1 = {
6702
+ generateUniqueName,
6703
+ parentInfo,
6704
+ defaultTagNames: root_store_default.componentRegistry.defaultTagNames,
6705
+ selfTagName: componentType
6706
+ };
6707
+ const editorTemplateCreateRequest = editorTemplates?.[0]?.create?.(context$1);
6708
+ const primaryEditorTemplateCreateRequest = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest[0] : editorTemplateCreateRequest;
6709
+ 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}`);
6710
+ const editorTemplateCreateRequests = Array.isArray(editorTemplateCreateRequest) ? editorTemplateCreateRequest : [editorTemplateCreateRequest];
6711
+ const editStore = getEditStore();
6712
+ function editorTemplateCreateRequestToInternalCreateRequest({ editorTemplateCreateRequest: editorTemplateCreateRequest$1, baseProperties: baseProperties$1 }) {
6713
+ const type = editorTemplateCreateRequest$1?.type ?? componentType;
6714
+ const { properties: propertiesFromType, children } = getComponentBaseProperties(type, parentInfo, editorTemplateCreateRequest$1);
6715
+ const properties = {
6716
+ ...propertiesFromType,
6717
+ ...baseProperties$1
6718
+ };
6719
+ return {
6720
+ parentElement: getCreateAtParentElement(parent, editorTemplateCreateRequest$1?.createAt),
6721
+ tagName: type,
6722
+ properties,
6723
+ children,
6724
+ scopeName,
6725
+ id: editStore.operationManager.generateSourceId()
7092
6726
  };
7093
- }, []);
6727
+ }
6728
+ const createRequests = editorTemplateCreateRequests.map((editorTemplateCreateRequest$1, index) => editorTemplateCreateRequestToInternalCreateRequest({
6729
+ editorTemplateCreateRequest: editorTemplateCreateRequest$1,
6730
+ baseProperties: index === 0 ? baseProperties : {}
6731
+ }));
6732
+ const hasOtherComponentsUpdates = otherComponentsUpdates && Object.keys(otherComponentsUpdates).length > 0;
6733
+ const hasMultipleCreateComponents = editorTemplateCreateRequests.length > 1 && !skipSecondaryComponentsCreation;
6734
+ if (hasOtherComponentsUpdates || hasMultipleCreateComponents) {
6735
+ const performOtherComponentsUpdates = (otherComponentsUpdates$1) => {
6736
+ Object.entries(otherComponentsUpdates$1).forEach(([sourceId, updates]) => {
6737
+ editStore.operationManager.setWidgetProperties({
6738
+ sourceId,
6739
+ properties: updates
6740
+ });
6741
+ });
6742
+ };
6743
+ editStore.operationManager.batchUpdate(() => {
6744
+ if (skipSecondaryComponentsCreation) editStore.operationManager.createComponent(createRequests[0]);
6745
+ else createRequests.forEach((createRequest) => {
6746
+ editStore.operationManager.createComponent(createRequest);
6747
+ });
6748
+ if (hasOtherComponentsUpdates) performOtherComponentsUpdates(otherComponentsUpdates);
6749
+ });
6750
+ } else editStore.operationManager.createComponent(createRequests[0]);
6751
+ /**
6752
+ * Returns the single id, or the the last component if there are multiple.
6753
+ * See EditorTemplate's definition to understand why.
6754
+ */
6755
+ return createRequests.at(-1).id;
7094
6756
  }
7095
6757
 
7096
6758
  //#endregion
@@ -7114,7 +6776,7 @@ const fixCursorSnapOffset = (args) => {
7114
6776
  const sortedCollisions = rectIntersection(updated).filter((collision) => {
7115
6777
  const activeRootInstanceId = editStore.interactionLayerManager.activeRootInstanceId;
7116
6778
  if (!activeRootInstanceId) return true;
7117
- return collision.id === activeRootInstanceId || editStore.runtimeEntitiesManager.isChildOf(collision.id, activeRootInstanceId);
6779
+ return collision.id === activeRootInstanceId || doesInteractionLayerContainInstance(activeRootInstanceId, collision.id);
7118
6780
  }).map((collision) => {
7119
6781
  const rect = collision.data?.droppableContainer?.rect.current;
7120
6782
  const pointerInside = rect && x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
@@ -7169,6 +6831,184 @@ const bubblingToParentIfFar = (args) => {
7169
6831
  };
7170
6832
  var collision_detection_default = fixCursorSnapOffset;
7171
6833
 
6834
+ //#endregion
6835
+ //#region src/edit-mode/dnd/handle-stack-drop.ts
6836
+ const mergeDroppedDimensions = (draggedType, draggedProps, activeDragRect) => {
6837
+ const safeExistingDimensions = filterSafeStackDimensionProperties({
6838
+ width: draggedProps?.width,
6839
+ height: draggedProps?.height,
6840
+ size: draggedProps?.size
6841
+ });
6842
+ const width = safeExistingDimensions.width;
6843
+ const height = safeExistingDimensions.height;
6844
+ if (draggedType === "Icon") return { size: safeExistingDimensions.size ?? (activeDragRect?.height ? Property$1.Dimension(Dim$1.px(activeDragRect.height)) : Property$1.Static("")) };
6845
+ return {
6846
+ width,
6847
+ height
6848
+ };
6849
+ };
6850
+ const handleStackDropWithinCanvas = (params) => {
6851
+ const { dropInfo, draggedId, dropTargetId } = params;
6852
+ const editStore = getEditStore();
6853
+ const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
6854
+ const draggedSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(draggedId);
6855
+ if (!dropSourceId || !draggedSourceId) throw new Error(`Missing IDs: dragging ${draggedId} to ${dropTargetId}`);
6856
+ console.log(`Dragged ${draggedSourceId} to ${dropSourceId}`, {
6857
+ dropInfo,
6858
+ index: dropInfo.insertionIndex
6859
+ });
6860
+ if (dropInfo.noopDrop) return;
6861
+ const draggedType = editStore.runtimeEntitiesManager.getEditorWidgetType(draggedId);
6862
+ if (!draggedType) throw new Error(`Missing dragged type: ${draggedId}`);
6863
+ const activeDragRect = editStore.ui.dnd.activeDragRect;
6864
+ const draggedProps = editStore.runtimeEntitiesManager.getEditorWidgetMeta(draggedId)?.props;
6865
+ editStore.operationManager.dropComponent({
6866
+ from: { source: { id: draggedSourceId } },
6867
+ to: { source: {
6868
+ id: dropSourceId,
6869
+ index: dropInfo.insertionIndex
6870
+ } },
6871
+ propsToChange: { ...mergeDroppedDimensions(draggedType, draggedProps, activeDragRect) }
6872
+ });
6873
+ };
6874
+ const handleStackDropForNewComponent = ({ componentType, dropInfo, dropTargetId }) => {
6875
+ const editStore = getEditStore();
6876
+ const dropSourceId = editStore.runtimeEntitiesManager.getEditorWidgetSourceId(dropTargetId);
6877
+ const dropScopeId = editStore.runtimeEntitiesManager.getEditorWidgetScopeId(dropTargetId);
6878
+ if (!dropSourceId || !dropScopeId) throw new Error("Missing drop source id");
6879
+ const scopeName = root_store_default.entityManager.getScopeName(dropScopeId);
6880
+ return createComponent({
6881
+ componentType,
6882
+ parent: {
6883
+ index: dropInfo.insertionIndex,
6884
+ id: dropSourceId
6885
+ },
6886
+ scopeName
6887
+ });
6888
+ };
6889
+ const handleStackDrop = async ({ dropInfo, draggedId, dropTargetId, isDraggingNewComponent, newComponentType }) => {
6890
+ if (dropInfo.insertionIndex == null) throw new Error("No insertion index found");
6891
+ if (isDraggingNewComponent) {
6892
+ if (!newComponentType) throw new Error("Missing componentType to create new component");
6893
+ return handleStackDropForNewComponent({
6894
+ componentType: newComponentType,
6895
+ dropTargetId,
6896
+ dropInfo
6897
+ });
6898
+ } else {
6899
+ if (!draggedId) throw new Error("Missing dragged id");
6900
+ handleStackDropWithinCanvas({
6901
+ dropInfo,
6902
+ draggedId,
6903
+ dropTargetId
6904
+ });
6905
+ }
6906
+ };
6907
+
6908
+ //#endregion
6909
+ //#region src/edit-mode/dnd/hooks/use-handle-dnd-events.ts
6910
+ const measureRect = (id) => {
6911
+ const rect = id ? getBoundingBoxForWidget(id) : null;
6912
+ if (!rect) return null;
6913
+ return {
6914
+ left: rect.left,
6915
+ top: rect.top,
6916
+ right: rect.right,
6917
+ bottom: rect.bottom,
6918
+ width: rect.width,
6919
+ height: rect.height
6920
+ };
6921
+ };
6922
+ const useHandleDnDEvents = () => {
6923
+ const setActiveDragRect = useMemo(() => {
6924
+ const editStore = getEditStore();
6925
+ const throttled = throttle((rect) => {
6926
+ editStore.ui.dnd.setActiveDragRect(rect);
6927
+ }, 10, {
6928
+ leading: true,
6929
+ trailing: true
6930
+ });
6931
+ return (val) => {
6932
+ throttled(val);
6933
+ };
6934
+ }, []);
6935
+ const setActiveTargetInfo = useMemo(() => {
6936
+ const editStore = getEditStore();
6937
+ const throttled = throttle((id, rect) => {
6938
+ editStore.ui.dnd.setDropTargetId(id);
6939
+ editStore.ui.dnd.setActiveTargetRect(rect);
6940
+ }, 10, {
6941
+ leading: true,
6942
+ trailing: true
6943
+ });
6944
+ return (id, val) => {
6945
+ throttled(id, val);
6946
+ };
6947
+ }, []);
6948
+ useDndMonitor({
6949
+ onDragStart: useCallback((event) => {
6950
+ const editStore = getEditStore();
6951
+ if (!event.active?.data.current && !editStore.ui.dnd.isDraggingNewComponent) {
6952
+ console.error("No active widget data");
6953
+ return;
6954
+ }
6955
+ editStore.ui.dnd.setDropTargetId(null);
6956
+ editStore.ui.dnd.setIsDragging(true);
6957
+ if (editStore.ui.dnd.isDraggingNewComponent) {
6958
+ editStore.ui.selectWidget(null);
6959
+ editStore.ui.dnd.resizePageIfNeeded();
6960
+ } else editStore.ui.selectWidget(event.active?.id ? event.active.id : null, event.activatorEvent?.shiftKey);
6961
+ }, []),
6962
+ onDragMove: useCallback((event) => {
6963
+ setActiveTargetInfo(event.over?.id ?? null, event.over?.rect ?? null);
6964
+ const collisionRect = event.collisions?.[0]?.data?.injectedCollisionRect;
6965
+ if (collisionRect) setActiveDragRect(collisionRect);
6966
+ else setActiveDragRect(null);
6967
+ }, [setActiveDragRect, setActiveTargetInfo]),
6968
+ onDragOver: useCallback((event) => {
6969
+ const overId = event.over?.id ? String(event.over?.id) : null;
6970
+ setActiveTargetInfo(overId, measureRect(overId));
6971
+ }, [setActiveTargetInfo]),
6972
+ onDragCancel: useCallback((_event) => {
6973
+ const editStore = getEditStore();
6974
+ editStore.ui.dnd.setIsDragging(false);
6975
+ editStore.ui.dnd.cancelNewComponentDrag();
6976
+ }, []),
6977
+ onDragEnd: useCallback(async (event) => {
6978
+ const editStore = getEditStore();
6979
+ let possibleNewComponentId;
6980
+ try {
6981
+ if (!editStore.ui.dnd.isProspectiveDropValid) {
6982
+ editorBridge.sendNotification("error", "You cannot drop a component here.");
6983
+ return;
6984
+ }
6985
+ const dropTargetId = event.over?.id ? String(event.over.id) : null;
6986
+ const draggedId = event.active?.id ? String(event.active?.id) : null;
6987
+ if (dropTargetId !== editStore.ui.dnd.dropTargetId) throw new Error("Drop target id and drag over id do not match");
6988
+ if (!dropTargetId) throw new Error("No drop target id");
6989
+ if (editStore.ui.dnd.isDropTargetStackLike) {
6990
+ const dropInfo = editStore.ui.dnd.stack.refreshPositionsAndGetDropIndex();
6991
+ possibleNewComponentId = await handleStackDrop({
6992
+ dropInfo,
6993
+ isDraggingNewComponent: editStore.ui.dnd.isDraggingNewComponent,
6994
+ newComponentType: editStore.ui.dnd.dragToCanvasComponentType,
6995
+ dropTargetId,
6996
+ draggedId
6997
+ });
6998
+ } else throw new Error("Grid is no longer supported");
6999
+ } catch (e) {
7000
+ console.error("Error dropping item", e);
7001
+ } finally {
7002
+ runInAction(() => {
7003
+ editStore.ui.dnd.setIsDragging(false);
7004
+ editStore.ui.dnd.cancelNewComponentDrag();
7005
+ if (possibleNewComponentId) editStore.ui.selectNewComponentBySourceId(possibleNewComponentId);
7006
+ });
7007
+ }
7008
+ }, [])
7009
+ });
7010
+ };
7011
+
7172
7012
  //#endregion
7173
7013
  //#region src/edit-mode/dnd/dnd-provider.tsx
7174
7014
  const pointerConfig = { activationConstraint: { distance: 10 } };
@@ -7183,14 +7023,18 @@ var CustomPointerSensor = class extends PointerSensor {
7183
7023
  }
7184
7024
  }];
7185
7025
  };
7026
+ const DragHandlerComponent = () => {
7027
+ useHandleDnDEvents();
7028
+ return null;
7029
+ };
7186
7030
  const DnDProvider = (props) => {
7187
7031
  const pointerSensor = useSensor(PointerSensor, pointerConfig);
7188
7032
  const customPointerSensor = useSensor(CustomPointerSensor);
7189
7033
  const sensors = useSensors(pointerSensor, customPointerSensor);
7190
- return /* @__PURE__ */ jsx(DndContext, {
7034
+ return /* @__PURE__ */ jsxs(DndContext, {
7191
7035
  sensors,
7192
7036
  collisionDetection: collision_detection_default,
7193
- children: props.children
7037
+ children: [props.children, /* @__PURE__ */ jsx(DragHandlerComponent, {})]
7194
7038
  });
7195
7039
  };
7196
7040
 
@@ -7332,9 +7176,16 @@ var InteractionLayerManager = class {
7332
7176
  * if set to the detached component id, the interaction layer will be disabled on the page
7333
7177
  */
7334
7178
  activeRootInstanceId = void 0;
7179
+ interactionLayerInstanceIds = /* @__PURE__ */ new Set();
7335
7180
  constructor() {
7336
7181
  makeAutoObservable(this);
7337
7182
  }
7183
+ @action addInteractionLayerInstanceId(instanceId) {
7184
+ this.interactionLayerInstanceIds.add(instanceId);
7185
+ }
7186
+ @action removeInteractionLayerInstanceId(instanceId) {
7187
+ this.interactionLayerInstanceIds.delete(instanceId);
7188
+ }
7338
7189
  @action setActiveRootInstanceId(rootInstanceId) {
7339
7190
  this.activeRootInstanceId = rootInstanceId;
7340
7191
  }
@@ -8225,7 +8076,8 @@ var RuntimeEntitiesManager = class {
8225
8076
  this.entitiesWithLocalBindings = new Set(entities);
8226
8077
  }
8227
8078
  doesEntityHaveLocalBindings(entity) {
8228
- return this.entitiesWithLocalBindings.has(entity);
8079
+ const entitySourceId = this.getEditorWidgetSourceId(entity);
8080
+ return entitySourceId && this.entitiesWithLocalBindings.has(entitySourceId);
8229
8081
  }
8230
8082
  getOptimisticWidgetChildrenIds(instanceId) {
8231
8083
  return this.getChildrenWithOptimisticUpdates(instanceId).reduce((acc, child) => {
@@ -8707,14 +8559,36 @@ var DragAndDropManager = class {
8707
8559
  const draggedInstanceId = this.root.editStore.ui.getSelectedInstanceIds()[0];
8708
8560
  return draggedInstanceId ? getEditStore().runtimeEntitiesManager.getEditorWidgetType(draggedInstanceId) : void 0;
8709
8561
  }
8562
+ get draggedWidgetInstanceId() {
8563
+ if (this.isDraggingNewComponent) return;
8564
+ return this.root.editStore.ui.getSelectedInstanceIds()[0];
8565
+ }
8710
8566
  get dragToCanvasComponentType() {
8711
8567
  return this._dragToCanvasComponentType;
8712
8568
  }
8713
8569
  get validRootIds() {
8714
8570
  return this._validRootIds;
8715
8571
  }
8716
- get invalidDropTarget() {
8717
- return this._invalidDropTarget;
8572
+ get isProspectiveDropValid() {
8573
+ const dropTargetInstanceId = this.dropTargetId;
8574
+ const draggedInstanceId = this.draggedWidgetInstanceId;
8575
+ if (!dropTargetInstanceId) return false;
8576
+ const isDraggingNewComponent = this.isDraggingNewComponent;
8577
+ if (!areDragAndDropInstancesValid({
8578
+ dropTargetInstanceId,
8579
+ draggedInstanceId,
8580
+ isDraggingNewComponent
8581
+ })) return false;
8582
+ const draggedType = this.draggedWidgetType;
8583
+ const dropTargetType = this.dropTargetWidgetType;
8584
+ if (!draggedType || !dropTargetType) return false;
8585
+ const dropTargetEmpty = (dropTargetInstanceId && getEditStore().runtimeEntitiesManager.getEditorWidgetMeta(dropTargetInstanceId)?.children?.length === 0) ?? true;
8586
+ return isDragAndDropTypeValid({
8587
+ draggedType,
8588
+ dropTargetType,
8589
+ isDraggingNewComponent,
8590
+ dropTargetEmpty
8591
+ });
8718
8592
  }
8719
8593
  canDragWidget(instanceId) {
8720
8594
  const editStore = getEditStore();
@@ -8743,7 +8617,6 @@ var DragAndDropManager = class {
8743
8617
  this._activeDragRect = null;
8744
8618
  this._activeTargetRect = null;
8745
8619
  this._validRootIds = null;
8746
- this._invalidDropTarget = false;
8747
8620
  }
8748
8621
  }
8749
8622
  /**
@@ -8786,9 +8659,6 @@ var DragAndDropManager = class {
8786
8659
  @action setValidRootIds(ids) {
8787
8660
  this._validRootIds = ids;
8788
8661
  }
8789
- @action setInvalidDropTarget(invalid) {
8790
- this._invalidDropTarget = invalid;
8791
- }
8792
8662
  @action setDropTargetId(id) {
8793
8663
  this._dropTargetInstanceId = id;
8794
8664
  if (id == null) this._activeTargetRect = null;
@@ -10382,7 +10252,7 @@ function useDialogEditing(props) {
10382
10252
  const selectedInstanceId = features.selectWidget.value;
10383
10253
  useEffect(() => {
10384
10254
  if (isEditing && instanceId) if (isOpen) {
10385
- if (!selectedInstanceId || selectedInstanceId !== instanceId && !getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId))
10255
+ if (!selectedInstanceId || selectedInstanceId !== instanceId && !doesInteractionLayerContainInstance(instanceId, selectedInstanceId))
10386
10256
  /**
10387
10257
  * If the dialog is open and the dialog or its children are not selected, then select it.
10388
10258
  * This happens when an event handler changes the open state of the dialog.
@@ -10398,10 +10268,10 @@ function useDialogEditing(props) {
10398
10268
  if (isEditing && instanceId) {
10399
10269
  if (prevIsOpenRef.current !== isOpen && !(prevIsOpenRef.current === void 0 && isOpen === false)) return;
10400
10270
  if (isOpen) {
10401
- if (selectedInstanceId && selectedInstanceId !== instanceId && !getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId)) update((entity) => {
10271
+ if (selectedInstanceId && selectedInstanceId !== instanceId && !doesInteractionLayerContainInstance(instanceId, selectedInstanceId)) update((entity) => {
10402
10272
  set(entity, isOpenPropertyName, false);
10403
10273
  });
10404
- } else if (selectedInstanceId === instanceId || selectedInstanceId && getEditStore().runtimeEntitiesManager.isChildOf(selectedInstanceId, instanceId)) update((entity) => {
10274
+ } else if (selectedInstanceId === instanceId || selectedInstanceId && doesInteractionLayerContainInstance(instanceId, selectedInstanceId)) update((entity) => {
10405
10275
  set(entity, isOpenPropertyName, true);
10406
10276
  });
10407
10277
  }
@@ -11424,7 +11294,10 @@ function DroppableContainer({ name, componentType, isOpen, children, layout, cla
11424
11294
  ref: dropTargetRef,
11425
11295
  id: getEditWrapperIdWithType(instanceId, componentType),
11426
11296
  style: EXPANDED,
11427
- children: [internalContainer, isOpen && /* @__PURE__ */ jsx(interaction_layer_default, {
11297
+ children: [/* @__PURE__ */ jsx(InteractionLayerProvider, {
11298
+ instanceId,
11299
+ children: internalContainer
11300
+ }), isOpen && /* @__PURE__ */ jsx(interaction_layer_default, {
11428
11301
  rootType: componentType,
11429
11302
  rootInstanceId: instanceId,
11430
11303
  rootName: name