@archie/devtools 0.0.21 → 0.0.22

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.
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key2, value) => key2 in obj ? __defProp(obj, key2, {
3
3
  var __publicField = (obj, key2, value) => __defNormalProp(obj, typeof key2 !== "symbol" ? key2 + "" : key2, value);
4
4
 
5
5
  // src/client/dnd/DndProvider.tsx
6
- import { useCallback as useCallback9, useEffect as useEffect13 } from "react";
6
+ import { useCallback as useCallback9, useEffect as useEffect12 } from "react";
7
7
 
8
8
  // node_modules/@dnd-kit/core/dist/core.esm.js
9
9
  import React2, { createContext, useContext, useEffect as useEffect2, useState as useState2, useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2, memo, useReducer, cloneElement, forwardRef } from "react";
@@ -4280,6 +4280,9 @@ function findMetaOwnerElement(el) {
4280
4280
  }
4281
4281
  function resolveHostElementFromFiberChain(el) {
4282
4282
  if (shouldIgnoreAsVirtualRuntime(el)) return null;
4283
+ if (el.hasAttribute("data-dnd-force-allow")) {
4284
+ return el;
4285
+ }
4283
4286
  const directMeta = getDirectEditorMeta(el);
4284
4287
  const ownerMeta = directMeta ?? getEditorMeta(el);
4285
4288
  if (isPassthroughMeta(ownerMeta)) {
@@ -4635,8 +4638,8 @@ function buildEmptyArrangeSessionState() {
4635
4638
  var useDesignModeStore = create((set, get) => ({
4636
4639
  // UI state
4637
4640
  enabled: false,
4638
- hoveredSelector: null,
4639
4641
  selectedSelector: null,
4642
+ inspectorSelectedNodeIds: [],
4640
4643
  historyMode: "local",
4641
4644
  inspectorTheme: DEFAULT_INSPECTOR_THEME,
4642
4645
  canUndo: false,
@@ -4652,16 +4655,23 @@ var useDesignModeStore = create((set, get) => ({
4652
4655
  // UI actions
4653
4656
  toggle: () => set((s) => ({ enabled: !s.enabled, ...buildEmptyArrangeSessionState() })),
4654
4657
  setEnabled: (enabled) => set({ enabled }),
4655
- setHovered: (selector) => set({ hoveredSelector: selector }),
4656
4658
  setSelected: (selector) => set({ selectedSelector: selector }),
4659
+ setInspectorSelection: (nodeIds) => {
4660
+ const next = nodeIds.filter((id) => typeof id === "string" && id.length > 0);
4661
+ const prev = get().inspectorSelectedNodeIds;
4662
+ if (prev.length === next.length && prev.every((id, i) => id === next[i])) {
4663
+ return;
4664
+ }
4665
+ set({ inspectorSelectedNodeIds: next });
4666
+ },
4657
4667
  setHistoryMode: (historyMode) => set({ historyMode }),
4658
4668
  setInspectorTheme: (theme) => set((s) => ({ inspectorTheme: mergeInspectorTheme({ ...s.inspectorTheme, ...theme }) })),
4659
4669
  setHistoryAvailability: (canUndo, canRedo) => set({ canUndo, canRedo }),
4660
4670
  requestUndo: () => set((s) => ({ undoRequestId: s.undoRequestId + 1 })),
4661
4671
  requestRedo: () => set((s) => ({ redoRequestId: s.redoRequestId + 1 })),
4662
4672
  resetAll: () => set({
4663
- hoveredSelector: null,
4664
4673
  selectedSelector: null,
4674
+ inspectorSelectedNodeIds: [],
4665
4675
  canUndo: false,
4666
4676
  canRedo: false
4667
4677
  }),
@@ -4779,9 +4789,13 @@ var useDesignModeStore = create((set, get) => ({
4779
4789
  inspectorRef,
4780
4790
  displayName,
4781
4791
  html,
4792
+ tsxCode,
4793
+ tsxImports,
4782
4794
  containerId,
4783
4795
  containerNodeKey,
4784
- index
4796
+ index,
4797
+ beforeSiblingInspectorRef,
4798
+ beforeSiblingNodeKey
4785
4799
  }) => {
4786
4800
  const now = Date.now();
4787
4801
  const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
@@ -4793,9 +4807,13 @@ var useDesignModeStore = create((set, get) => ({
4793
4807
  inspectorRef,
4794
4808
  displayName,
4795
4809
  html,
4810
+ tsxCode: tsxCode ?? null,
4811
+ tsxImports: tsxImports ?? null,
4796
4812
  containerId,
4797
4813
  containerNodeKey,
4798
4814
  index,
4815
+ beforeSiblingInspectorRef: beforeSiblingInspectorRef ?? null,
4816
+ beforeSiblingNodeKey: beforeSiblingNodeKey ?? null,
4799
4817
  at: now
4800
4818
  };
4801
4819
  set((s) => {
@@ -4873,7 +4891,7 @@ var useDesignModeStore = create((set, get) => ({
4873
4891
  }));
4874
4892
 
4875
4893
  // src/client/dnd/design-mode/DesignModeOverlay.tsx
4876
- import { useRef as useRef10, useCallback as useCallback8, useEffect as useEffect12, useLayoutEffect as useLayoutEffect2, useState as useState6, useMemo as useMemo6 } from "react";
4894
+ import { useRef as useRef10, useCallback as useCallback8, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useState as useState6, useMemo as useMemo6 } from "react";
4877
4895
 
4878
4896
  // src/client/dnd/design-mode/useElementScanner.ts
4879
4897
  import { useState as useState4, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
@@ -5402,14 +5420,14 @@ function handlePosition(dir) {
5402
5420
  };
5403
5421
  return positions[dir];
5404
5422
  }
5405
- function getOutlineStyle(rect, isSelected, isHovered, inspectorTheme) {
5423
+ function getOutlineStyle(rect, isSelected, inspectorTheme) {
5406
5424
  return {
5407
5425
  ...OUTLINE_BASE_STYLE,
5408
5426
  left: rect.left,
5409
5427
  top: rect.top,
5410
5428
  width: rect.width,
5411
5429
  height: rect.height,
5412
- border: isSelected ? `2px solid ${inspectorTheme.accent}` : isHovered ? `2px dashed ${inspectorTheme.hover}` : `1px dashed ${inspectorTheme.shared}`,
5430
+ border: isSelected ? `2px solid ${inspectorTheme.accent}` : `1px dashed ${inspectorTheme.shared}`,
5413
5431
  backgroundColor: isSelected ? inspectorTheme.accentSoft : "transparent"
5414
5432
  };
5415
5433
  }
@@ -5439,11 +5457,13 @@ function ElementHighlight({
5439
5457
  elements,
5440
5458
  draggingNodeId,
5441
5459
  activeEl,
5460
+ arrangeSelectedNodeId,
5461
+ externalDragActive,
5442
5462
  onResizeHandlePointerDown
5443
5463
  }) {
5444
- const hoveredSelector = useDesignModeStore((s) => s.hoveredSelector);
5445
- const selectedSelector = useDesignModeStore((s) => s.selectedSelector);
5446
5464
  const inspectorTheme = useDesignModeStore((s) => s.inspectorTheme);
5465
+ const internalDragInProgress = draggingNodeId !== null;
5466
+ const overlayVisible = arrangeSelectedNodeId !== null || internalDragInProgress;
5447
5467
  const containerRef = useRef5(null);
5448
5468
  const rafRef = useRef5(0);
5449
5469
  const syncPositions = useCallback5(() => {
@@ -5467,7 +5487,6 @@ function ElementHighlight({
5467
5487
  }
5468
5488
  }, [elements]);
5469
5489
  useEffect5(() => {
5470
- if (draggingNodeId) return;
5471
5490
  let running = true;
5472
5491
  const loop = () => {
5473
5492
  if (!running) return;
@@ -5479,8 +5498,9 @@ function ElementHighlight({
5479
5498
  running = false;
5480
5499
  cancelAnimationFrame(rafRef.current);
5481
5500
  };
5482
- }, [syncPositions, draggingNodeId]);
5483
- if (draggingNodeId) return null;
5501
+ }, [syncPositions]);
5502
+ if (!overlayVisible) return null;
5503
+ if (externalDragActive) return null;
5484
5504
  return /* @__PURE__ */ jsx2(
5485
5505
  "div",
5486
5506
  {
@@ -5490,10 +5510,10 @@ function ElementHighlight({
5490
5510
  children: elements.map((el) => {
5491
5511
  if (el.nodeId === draggingNodeId) return null;
5492
5512
  if (activeEl && activeEl !== el.element && activeEl.contains(el.element)) return null;
5493
- const isHovered = el.nodeId === hoveredSelector;
5494
- const isSelected = el.nodeId === selectedSelector;
5513
+ const isSelected = el.nodeId === arrangeSelectedNodeId;
5514
+ if (!isSelected && !internalDragInProgress) return null;
5495
5515
  const rect = el.element.getBoundingClientRect();
5496
- const showLabel = isHovered || isSelected;
5516
+ const showLabel = isSelected;
5497
5517
  const labelTop = isSelected ? Math.max(0, rect.top - 20) : rect.top;
5498
5518
  const labelLeft = isSelected ? rect.left + 12 : rect.left;
5499
5519
  return /* @__PURE__ */ jsxs("div", { children: [
@@ -5502,7 +5522,7 @@ function ElementHighlight({
5502
5522
  {
5503
5523
  "data-outline-for": el.nodeId,
5504
5524
  "data-design-mode-ui": true,
5505
- style: getOutlineStyle(rect, isSelected, isHovered, inspectorTheme),
5525
+ style: getOutlineStyle(rect, isSelected, inspectorTheme),
5506
5526
  children: isSelected && HANDLES.map((dir) => {
5507
5527
  const pos = handlePosition(dir);
5508
5528
  return /* @__PURE__ */ jsx2(
@@ -5797,6 +5817,57 @@ function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
5797
5817
  };
5798
5818
  }
5799
5819
 
5820
+ // src/client/dnd/design-mode/inserted-descendants.ts
5821
+ var NON_DRAGGABLE_DESCENDANT_TAGS = /* @__PURE__ */ new Set([
5822
+ // SVG internals — the whole <svg> is the unit; its parts must stay together.
5823
+ "svg",
5824
+ "path",
5825
+ "circle",
5826
+ "rect",
5827
+ "line",
5828
+ "polyline",
5829
+ "polygon",
5830
+ "g",
5831
+ "defs",
5832
+ "use",
5833
+ // <select>/<option>: options live inside their <select>, never standalone.
5834
+ "option",
5835
+ "optgroup",
5836
+ // Table internals: only meaningful in their <table> tree.
5837
+ "caption",
5838
+ "thead",
5839
+ "tbody",
5840
+ "tfoot",
5841
+ "tr",
5842
+ "th",
5843
+ "td",
5844
+ "col",
5845
+ "colgroup",
5846
+ // Self-closing inline atoms with no draggable surface.
5847
+ "br",
5848
+ "wbr",
5849
+ "hr",
5850
+ // Non-rendered metadata.
5851
+ "script",
5852
+ "style",
5853
+ "meta",
5854
+ "link",
5855
+ "title",
5856
+ "noscript",
5857
+ // Replaced media controls handled by their parent player.
5858
+ "source",
5859
+ "track"
5860
+ ]);
5861
+ function markInsertedDescendants(root) {
5862
+ const descendants = root.querySelectorAll("*");
5863
+ for (const node of descendants) {
5864
+ const tag = node.tagName.toLowerCase();
5865
+ if (NON_DRAGGABLE_DESCENDANT_TAGS.has(tag)) continue;
5866
+ node.setAttribute("data-dnd-force-allow", "");
5867
+ node.setAttribute("data-dnd-moved", "");
5868
+ }
5869
+ }
5870
+
5800
5871
  // src/client/dnd/design-mode/history.ts
5801
5872
  function applyInsertCommand(command, direction, resolveNodeElement) {
5802
5873
  if (direction === "undo") {
@@ -5819,6 +5890,7 @@ function applyInsertCommand(command, direction, resolveNodeElement) {
5819
5890
  (c) => c instanceof HTMLElement
5820
5891
  );
5821
5892
  container.insertBefore(newEl, kids[command.index] ?? null);
5893
+ markInsertedDescendants(newEl);
5822
5894
  return true;
5823
5895
  }
5824
5896
  var DEFAULT_LIMIT = 300;
@@ -6344,6 +6416,8 @@ function serializeArrangeChange(event, index) {
6344
6416
  containerId: event.kind === "insert" ? event.containerId : void 0,
6345
6417
  containerNodeKey: event.kind === "insert" ? event.containerNodeKey : void 0,
6346
6418
  insertIndex: event.kind === "insert" ? event.index : void 0,
6419
+ beforeSiblingInspectorRef: event.kind === "insert" ? event.beforeSiblingInspectorRef : void 0,
6420
+ beforeSiblingNodeKey: event.kind === "insert" ? event.beforeSiblingNodeKey : void 0,
6347
6421
  summary: summarizeEditorChangeEvent(event),
6348
6422
  at: event.at
6349
6423
  };
@@ -6641,50 +6715,8 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
6641
6715
  }), []);
6642
6716
  }
6643
6717
 
6644
- // src/client/dnd/design-mode/useHoverDetection.ts
6645
- import { useEffect as useEffect8 } from "react";
6646
- function useHoverDetection({
6647
- enabled,
6648
- activeDrag,
6649
- elementsRef,
6650
- setHovered
6651
- }) {
6652
- useEffect8(() => {
6653
- if (!enabled) {
6654
- setHovered(null);
6655
- return;
6656
- }
6657
- let lastNodeId = null;
6658
- const fn = (e) => {
6659
- if (activeDrag) return;
6660
- let best = null;
6661
- let bestArea = Infinity;
6662
- for (const sc of elementsRef.current) {
6663
- const r = sc.rect;
6664
- if (e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom) {
6665
- const a = r.width * r.height;
6666
- if (a < bestArea) {
6667
- bestArea = a;
6668
- best = sc;
6669
- }
6670
- }
6671
- }
6672
- const nodeId = best?.nodeId ?? null;
6673
- if (nodeId !== lastNodeId) {
6674
- lastNodeId = nodeId;
6675
- setHovered(nodeId);
6676
- }
6677
- };
6678
- document.addEventListener("mousemove", fn);
6679
- return () => {
6680
- document.removeEventListener("mousemove", fn);
6681
- setHovered(null);
6682
- };
6683
- }, [enabled, setHovered, activeDrag]);
6684
- }
6685
-
6686
6718
  // src/client/dnd/design-mode/useDragVisualLoop.ts
6687
- import { useEffect as useEffect9 } from "react";
6719
+ import { useEffect as useEffect8 } from "react";
6688
6720
 
6689
6721
  // src/client/dnd/design-mode/quadtree.ts
6690
6722
  function overlaps(a, b) {
@@ -7573,7 +7605,7 @@ function useDragVisualLoop({
7573
7605
  setInsideRect,
7574
7606
  setDropLine
7575
7607
  }) {
7576
- useEffect9(() => {
7608
+ useEffect8(() => {
7577
7609
  const engine = refs.engineRef.current;
7578
7610
  const snapshot = refs.snapshotRef.current;
7579
7611
  if (!activeDrag || !engine || !snapshot) return;
@@ -8195,7 +8227,7 @@ function useDragLifecycle({
8195
8227
  }
8196
8228
 
8197
8229
  // src/client/dnd/design-mode/useResizeSession.ts
8198
- import { useCallback as useCallback7, useEffect as useEffect10 } from "react";
8230
+ import { useCallback as useCallback7, useEffect as useEffect9 } from "react";
8199
8231
  var RESIZE_POINTER_TOLERANCE_PX = 2;
8200
8232
  var RESIZE_DRAG_BLOCK_MS = 180;
8201
8233
  var RESIZE_MIN = 24;
@@ -8367,7 +8399,7 @@ function useResizeSession({
8367
8399
  });
8368
8400
  syncHistoryAvailability();
8369
8401
  }, [applyCommand, recordResizeChange, syncHistoryAvailability]);
8370
- useEffect10(() => {
8402
+ useEffect9(() => {
8371
8403
  if (!enabled) return;
8372
8404
  const handleResizePointerCancel = (e) => {
8373
8405
  const session = refs.resizeSessionRef.current;
@@ -8392,8 +8424,13 @@ function useResizeSession({
8392
8424
  }
8393
8425
 
8394
8426
  // src/client/dnd/design-mode/useExternalDragLoop.ts
8395
- import { useEffect as useEffect11, useRef as useRef9 } from "react";
8427
+ import { useEffect as useEffect10, useRef as useRef9 } from "react";
8396
8428
  var EXTERNAL_DRAG_ACTIVE_ID = "__external-drag-placeholder__";
8429
+ var insertNodeIdCounter = 0;
8430
+ function nextInsertNodeId() {
8431
+ insertNodeIdCounter += 1;
8432
+ return `insert:${Date.now()}:${insertNodeIdCounter}`;
8433
+ }
8397
8434
  function useExternalDragLoop({
8398
8435
  externalDrag,
8399
8436
  refs,
@@ -8403,7 +8440,7 @@ function useExternalDragLoop({
8403
8440
  }) {
8404
8441
  const engineRef = useRef9(null);
8405
8442
  const lastIntentRef = useRef9(null);
8406
- useEffect11(() => {
8443
+ useEffect10(() => {
8407
8444
  if (!externalDrag) {
8408
8445
  engineRef.current = null;
8409
8446
  lastIntentRef.current = null;
@@ -8493,7 +8530,7 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8493
8530
  setDropLine(null);
8494
8531
  return;
8495
8532
  }
8496
- const nodeId = `insert:${Date.now()}`;
8533
+ const nodeId = nextInsertNodeId();
8497
8534
  newElement.setAttribute(DND_NODE_ID_ATTR, nodeId);
8498
8535
  newElement.setAttribute("data-dnd-force-allow", "");
8499
8536
  newElement.setAttribute("data-dnd-moved", "");
@@ -8502,6 +8539,23 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8502
8539
  );
8503
8540
  const beforeChild = children[intent.index] ?? null;
8504
8541
  containerEl.insertBefore(newElement, beforeChild);
8542
+ markInsertedDescendants(newElement);
8543
+ const postInsertChildren = Array.from(containerEl.children).filter(
8544
+ (child) => child instanceof HTMLElement
8545
+ );
8546
+ let beforeSiblingEl = null;
8547
+ let beforeSiblingNodeId = null;
8548
+ const startIdx = postInsertChildren.indexOf(newElement) + 1;
8549
+ for (let i = startIdx; i < postInsertChildren.length; i += 1) {
8550
+ const candidate = postInsertChildren[i];
8551
+ const candidateNodeId = candidate.getAttribute(DND_NODE_ID_ATTR);
8552
+ if (!candidateNodeId) continue;
8553
+ const isEarlierInsert = candidateNodeId.startsWith("insert:");
8554
+ if (!isEarlierInsert && !getInspectorRefFromElement(candidate)) continue;
8555
+ beforeSiblingEl = candidate;
8556
+ beforeSiblingNodeId = candidateNodeId;
8557
+ break;
8558
+ }
8505
8559
  const insertCommand = {
8506
8560
  type: "insert",
8507
8561
  nodeId,
@@ -8527,6 +8581,15 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8527
8581
  inspectorRef: getInspectorRefFromElement(containerEl)
8528
8582
  };
8529
8583
  }
8584
+ let beforeSiblingIdentity = null;
8585
+ if (beforeSiblingEl && beforeSiblingNodeId) {
8586
+ beforeSiblingIdentity = {
8587
+ nodeId: beforeSiblingNodeId,
8588
+ nodeKey: getNodeKeyFromElement(beforeSiblingEl),
8589
+ selector: buildNodeSelector(beforeSiblingNodeId),
8590
+ inspectorRef: getInspectorRefFromElement(beforeSiblingEl)
8591
+ };
8592
+ }
8530
8593
  const operationId = `${insertCommand.at}:${nodeId}`;
8531
8594
  useDesignModeStore.getState().recordInsertChange({
8532
8595
  operationId,
@@ -8535,9 +8598,13 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8535
8598
  inspectorRef,
8536
8599
  displayName: component.displayName,
8537
8600
  html: component.html,
8601
+ tsxCode: component.tsxCode ?? null,
8602
+ tsxImports: component.tsxImports ?? null,
8538
8603
  containerId: intent.containerId,
8539
8604
  containerNodeKey,
8540
- index: intent.index
8605
+ index: intent.index,
8606
+ beforeSiblingInspectorRef: beforeSiblingIdentity?.inspectorRef ?? null,
8607
+ beforeSiblingNodeKey: beforeSiblingIdentity?.nodeKey ?? null
8541
8608
  });
8542
8609
  dispatchRuntimeEvent({
8543
8610
  type: "element-inserted",
@@ -8546,8 +8613,11 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8546
8613
  nodeKey,
8547
8614
  displayName: component.displayName,
8548
8615
  html: component.html,
8616
+ tsxCode: component.tsxCode ?? null,
8617
+ tsxImports: component.tsxImports ?? null,
8549
8618
  container: containerIdentity,
8550
- index: intent.index
8619
+ index: intent.index,
8620
+ beforeSibling: beforeSiblingIdentity
8551
8621
  });
8552
8622
  }
8553
8623
  setDropLine(null);
@@ -8598,8 +8668,12 @@ function HitArea({
8598
8668
  selectedNodeId,
8599
8669
  onResizeHandlePointerDown
8600
8670
  }) {
8601
- const { setNodeRef, listeners, attributes, isDragging } = useDraggable({ id: scanned.nodeId });
8602
- useEffect12(() => {
8671
+ const isSelected = scanned.nodeId === selectedNodeId;
8672
+ const { setNodeRef, listeners, attributes, isDragging } = useDraggable({
8673
+ id: scanned.nodeId,
8674
+ disabled: !isSelected
8675
+ });
8676
+ useEffect11(() => {
8603
8677
  setNodeRef(scanned.element);
8604
8678
  return () => setNodeRef(null);
8605
8679
  }, [setNodeRef, scanned.element]);
@@ -8611,7 +8685,7 @@ function HitArea({
8611
8685
  el.style.removeProperty("opacity");
8612
8686
  }
8613
8687
  }, [isDragging, scanned.element]);
8614
- useEffect12(() => () => {
8688
+ useEffect11(() => () => {
8615
8689
  scanned.element.style.removeProperty("opacity");
8616
8690
  scanned.element.style.removeProperty("transform");
8617
8691
  scanned.element.style.removeProperty("transition");
@@ -8619,8 +8693,18 @@ function HitArea({
8619
8693
  }, [scanned.element]);
8620
8694
  const divRef = useRef10(null);
8621
8695
  const [hoverResizeHandle, setHoverResizeHandle] = useState6(null);
8622
- const isSelected = scanned.nodeId === selectedNodeId;
8623
- useEffect12(() => {
8696
+ const justDraggedRef = useRef10(false);
8697
+ useEffect11(() => {
8698
+ if (isDragging) {
8699
+ justDraggedRef.current = true;
8700
+ return;
8701
+ }
8702
+ const id = window.setTimeout(() => {
8703
+ justDraggedRef.current = false;
8704
+ }, 0);
8705
+ return () => window.clearTimeout(id);
8706
+ }, [isDragging]);
8707
+ useEffect11(() => {
8624
8708
  const div = divRef.current;
8625
8709
  if (!div) return;
8626
8710
  const onWheel = (e) => {
@@ -8636,7 +8720,7 @@ function HitArea({
8636
8720
  return () => div.removeEventListener("wheel", onWheel);
8637
8721
  }, []);
8638
8722
  const { left, top, width, height } = scanned.rect;
8639
- const cursor = isDragging ? "grabbing" : isSelected && hoverResizeHandle ? resizeCursorFromHandle(hoverResizeHandle) : "grab";
8723
+ const cursor = isDragging ? "grabbing" : !isSelected ? "default" : hoverResizeHandle ? resizeCursorFromHandle(hoverResizeHandle) : "grab";
8640
8724
  return /* @__PURE__ */ jsx4(
8641
8725
  "div",
8642
8726
  {
@@ -8667,6 +8751,35 @@ function HitArea({
8667
8751
  ...attributes,
8668
8752
  ...listeners,
8669
8753
  onClick: (e) => {
8754
+ if (justDraggedRef.current) {
8755
+ e.preventDefault();
8756
+ e.stopPropagation();
8757
+ return;
8758
+ }
8759
+ const stack = document.elementsFromPoint(e.clientX, e.clientY);
8760
+ for (const candidate of stack) {
8761
+ if (!(candidate instanceof HTMLElement)) continue;
8762
+ if (candidate.hasAttribute("data-design-mode-ui")) continue;
8763
+ if (candidate === scanned.element) break;
8764
+ const candidateNodeId = candidate.getAttribute("data-dnd-node-id");
8765
+ if (candidateNodeId && candidateNodeId !== scanned.nodeId) {
8766
+ e.preventDefault();
8767
+ e.stopPropagation();
8768
+ candidate.dispatchEvent(
8769
+ new MouseEvent("mousedown", {
8770
+ bubbles: true,
8771
+ cancelable: true,
8772
+ clientX: e.clientX,
8773
+ clientY: e.clientY,
8774
+ metaKey: e.metaKey,
8775
+ ctrlKey: e.ctrlKey,
8776
+ shiftKey: e.shiftKey,
8777
+ altKey: e.altKey
8778
+ })
8779
+ );
8780
+ return;
8781
+ }
8782
+ }
8670
8783
  e.preventDefault();
8671
8784
  e.stopPropagation();
8672
8785
  onActivate(scanned.nodeId);
@@ -8677,9 +8790,11 @@ function HitArea({
8677
8790
  function DesignModeOverlay() {
8678
8791
  const enabled = useDesignModeStore((s) => s.enabled);
8679
8792
  const historyMode = useDesignModeStore((s) => s.historyMode);
8680
- const setHovered = useDesignModeStore((s) => s.setHovered);
8681
8793
  const selectElement = useDesignModeStore((s) => s.setSelected);
8682
- const selectedSelector = useDesignModeStore((s) => s.selectedSelector);
8794
+ const inspectorSelectedNodeIds = useDesignModeStore(
8795
+ (s) => s.inspectorSelectedNodeIds
8796
+ );
8797
+ const arrangeSelectedNodeId = inspectorSelectedNodeIds.length === 1 ? inspectorSelectedNodeIds[0] : null;
8683
8798
  const setHistoryAvailability = useDesignModeStore((s) => s.setHistoryAvailability);
8684
8799
  const undoRequestId = useDesignModeStore((s) => s.undoRequestId);
8685
8800
  const redoRequestId = useDesignModeStore((s) => s.redoRequestId);
@@ -8705,16 +8820,23 @@ function DesignModeOverlay() {
8705
8820
  (el) => el.draggable !== false
8706
8821
  );
8707
8822
  }, [elements, nodeMap]);
8823
+ const arrangeHitAreaElement = useMemo6(() => {
8824
+ if (!arrangeSelectedNodeId) return null;
8825
+ if (externalDrag) return null;
8826
+ return draggableElements.find(
8827
+ (candidate) => candidate.nodeId === arrangeSelectedNodeId
8828
+ ) ?? null;
8829
+ }, [arrangeSelectedNodeId, externalDrag, draggableElements]);
8708
8830
  const refs = useOverlayRefs(undoRequestId, redoRequestId);
8709
8831
  refs.elementsRef.current = elements;
8710
8832
  refs.nodeMapRef.current = nodeMap;
8711
- useEffect12(() => {
8833
+ useEffect11(() => {
8712
8834
  const m = /* @__PURE__ */ new Map();
8713
8835
  for (const el of draggableElements) m.set(el.nodeId, el);
8714
8836
  refs.draggableNodeMapRef.current = m;
8715
8837
  }, [draggableElements]);
8716
8838
  const [grabFeedback, setGrabFeedback] = useState6(null);
8717
- useEffect12(() => {
8839
+ useEffect11(() => {
8718
8840
  if (!enabled) return;
8719
8841
  const onPointerDown = (e) => {
8720
8842
  if (!shouldShowGrabFeedback(
@@ -8728,7 +8850,7 @@ function DesignModeOverlay() {
8728
8850
  document.addEventListener("pointerdown", onPointerDown, true);
8729
8851
  return () => document.removeEventListener("pointerdown", onPointerDown, true);
8730
8852
  }, [enabled]);
8731
- useEffect12(() => {
8853
+ useEffect11(() => {
8732
8854
  if (!grabFeedback) return;
8733
8855
  const t = setTimeout(() => setGrabFeedback(null), 1400);
8734
8856
  return () => clearTimeout(t);
@@ -8785,7 +8907,7 @@ function DesignModeOverlay() {
8785
8907
  }
8786
8908
  setHistoryAvailability(refs.historyRef.current.canUndo(), refs.historyRef.current.canRedo());
8787
8909
  }, [historyMode, setHistoryAvailability]);
8788
- useEffect12(() => {
8910
+ useEffect11(() => {
8789
8911
  refs.historyRef.current.clear();
8790
8912
  syncHistoryAvailability();
8791
8913
  }, [enabled, syncHistoryAvailability]);
@@ -8799,7 +8921,7 @@ function DesignModeOverlay() {
8799
8921
  );
8800
8922
  const [insideRect, setInsideRect] = useState6(null);
8801
8923
  const [dropLine, setDropLine] = useState6(null);
8802
- useEffect12(() => {
8924
+ useEffect11(() => {
8803
8925
  if (!enabled) return;
8804
8926
  const fn = (e) => {
8805
8927
  refs.mouseRef.current = { x: e.clientX, y: e.clientY };
@@ -8807,7 +8929,7 @@ function DesignModeOverlay() {
8807
8929
  window.addEventListener("pointermove", fn, { capture: true, passive: true });
8808
8930
  return () => window.removeEventListener("pointermove", fn, { capture: true });
8809
8931
  }, [enabled]);
8810
- useEffect12(() => {
8932
+ useEffect11(() => {
8811
8933
  if (!enabled) return;
8812
8934
  if (historyMode !== "local") return;
8813
8935
  const onKeyDown = (e) => {
@@ -8836,7 +8958,7 @@ function DesignModeOverlay() {
8836
8958
  setInsideRect,
8837
8959
  setDropLine
8838
8960
  });
8839
- useEffect12(() => {
8961
+ useEffect11(() => {
8840
8962
  if (!enabled || activeDrag) return;
8841
8963
  if (undoRequestId === refs.processedUndoIdRef.current) return;
8842
8964
  refs.processedUndoIdRef.current = undoRequestId;
@@ -8853,7 +8975,7 @@ function DesignModeOverlay() {
8853
8975
  });
8854
8976
  syncHistoryAvailability();
8855
8977
  }, [undoRequestId, enabled, activeDrag, applyCommand, resume, selectElement, syncHistoryAvailability, undoLastChange]);
8856
- useEffect12(() => {
8978
+ useEffect11(() => {
8857
8979
  if (!enabled || activeDrag || historyMode !== "local") return;
8858
8980
  if (redoRequestId === refs.processedRedoIdRef.current) return;
8859
8981
  refs.processedRedoIdRef.current = redoRequestId;
@@ -8865,18 +8987,18 @@ function DesignModeOverlay() {
8865
8987
  }
8866
8988
  syncHistoryAvailability();
8867
8989
  }, [redoRequestId, enabled, activeDrag, applyCommand, historyMode, resume, selectElement, syncHistoryAvailability, redoLastChange]);
8868
- useEffect12(() => {
8990
+ useEffect11(() => {
8869
8991
  syncHistoryAvailability();
8870
8992
  }, [syncHistoryAvailability]);
8871
- useEffect12(() => {
8993
+ useEffect11(() => {
8872
8994
  dispatchRuntimeEvent({
8873
8995
  type: "design-mode-changed",
8874
8996
  mode: enabled ? "design" : "off"
8875
8997
  });
8876
8998
  }, [enabled]);
8877
- useEffect12(() => {
8999
+ useEffect11(() => {
8878
9000
  const aiOutput = exportChangesForAI();
8879
- const updatedAt = orderedChanges.length > 0 ? orderedChanges[orderedChanges.length - 1]?.at ?? Date.now() : Date.now();
9001
+ const updatedAt = Date.now();
8880
9002
  dispatchRuntimeEvent({
8881
9003
  type: "arrange-session-changed",
8882
9004
  session: buildArrangeSessionSnapshot({
@@ -8887,12 +9009,11 @@ function DesignModeOverlay() {
8887
9009
  })
8888
9010
  });
8889
9011
  }, [enabled, exportChangesForAI, orderedChanges]);
8890
- useEffect12(() => {
9012
+ useEffect11(() => {
8891
9013
  if (!enabled) return;
8892
9014
  document.body.classList.add("design-mode-active");
8893
9015
  return () => document.body.classList.remove("design-mode-active");
8894
9016
  }, [enabled]);
8895
- useHoverDetection({ enabled, activeDrag, elementsRef: refs.elementsRef, setHovered });
8896
9017
  useDesignModeAutoScroll({
8897
9018
  active: !!activeDrag,
8898
9019
  mouseRef: refs.mouseRef,
@@ -8931,19 +9052,21 @@ function DesignModeOverlay() {
8931
9052
  elements,
8932
9053
  draggingNodeId: activeDrag?.nodeId ?? null,
8933
9054
  activeEl: refs.activeElRef.current,
9055
+ arrangeSelectedNodeId,
9056
+ externalDragActive: externalDrag !== null,
8934
9057
  onResizeHandlePointerDown: handleResizeHandlePointerDown
8935
9058
  }
8936
9059
  ),
8937
- draggableElements.map((el) => /* @__PURE__ */ jsx4(
9060
+ arrangeHitAreaElement && /* @__PURE__ */ jsx4(
8938
9061
  HitArea,
8939
9062
  {
8940
- scanned: el,
9063
+ scanned: arrangeHitAreaElement,
8941
9064
  onActivate: selectElement,
8942
- selectedNodeId: selectedSelector,
9065
+ selectedNodeId: arrangeHitAreaElement.nodeId,
8943
9066
  onResizeHandlePointerDown: handleResizeHandlePointerDown
8944
9067
  },
8945
- el.nodeId
8946
- )),
9068
+ arrangeHitAreaElement.nodeId
9069
+ ),
8947
9070
  grabFeedback ? /* @__PURE__ */ jsx4(
8948
9071
  "div",
8949
9072
  {
@@ -9058,7 +9181,7 @@ function DndProvider({ children }) {
9058
9181
  designModeState.resetArrangeSession();
9059
9182
  designModeState.setEnabled(nextEnabled);
9060
9183
  }, []);
9061
- useEffect13(() => {
9184
+ useEffect12(() => {
9062
9185
  const handleKeyDown = (e) => {
9063
9186
  if (e.ctrlKey && e.shiftKey && e.key === "D") {
9064
9187
  e.preventDefault();
@@ -9068,7 +9191,7 @@ function DndProvider({ children }) {
9068
9191
  window.addEventListener("keydown", handleKeyDown);
9069
9192
  return () => window.removeEventListener("keydown", handleKeyDown);
9070
9193
  }, [transitionDesignMode]);
9071
- useEffect13(() => {
9194
+ useEffect12(() => {
9072
9195
  const handleHostCommand = (event) => {
9073
9196
  const detail = event.detail;
9074
9197
  if (!detail || typeof detail !== "object") return;
@@ -9127,6 +9250,25 @@ function DndProvider({ children }) {
9127
9250
  setInspectorTheme,
9128
9251
  requestUndo
9129
9252
  ]);
9253
+ useEffect12(() => {
9254
+ const bridgeWindow = window;
9255
+ const bridge = {
9256
+ setInspectorSelection: (nodeIds) => {
9257
+ useDesignModeStore.getState().setInspectorSelection(nodeIds);
9258
+ }
9259
+ };
9260
+ bridgeWindow.__ARCHIE_DESIGN_MODE__ = bridge;
9261
+ const pending = bridgeWindow.__ARCHIE_DESIGN_MODE_PENDING__;
9262
+ if (Array.isArray(pending)) {
9263
+ bridge.setInspectorSelection(pending);
9264
+ delete bridgeWindow.__ARCHIE_DESIGN_MODE_PENDING__;
9265
+ }
9266
+ return () => {
9267
+ if (bridgeWindow.__ARCHIE_DESIGN_MODE__ === bridge) {
9268
+ delete bridgeWindow.__ARCHIE_DESIGN_MODE__;
9269
+ }
9270
+ };
9271
+ }, []);
9130
9272
  const pointerSensor = useSensor(PointerSensor, { activationConstraint: { distance: 8 } });
9131
9273
  const keyboardSensor = useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates });
9132
9274
  const sensors = useSensors(pointerSensor, keyboardSensor);
@@ -9198,12 +9340,12 @@ function DndProvider({ children }) {
9198
9340
  }
9199
9341
 
9200
9342
  // src/client/useArchieDevToolsRuntime.ts
9201
- import { useEffect as useEffect14, useRef as useRef11 } from "react";
9343
+ import { useEffect as useEffect13, useRef as useRef11 } from "react";
9202
9344
 
9203
9345
  // src/client/archieLocalInspectorEnv.ts
9204
9346
  function readArchieLocalInspectorFlag() {
9205
9347
  try {
9206
- return import.meta.env?.VITE_ARCHIE_LOCAL_INSPECTOR === "true";
9348
+ return false;
9207
9349
  } catch {
9208
9350
  return false;
9209
9351
  }
@@ -9424,7 +9566,7 @@ function useArchieDevToolsRuntime({
9424
9566
  const stableOptionsKey = JSON.stringify(inspectorOptions ?? null);
9425
9567
  const inspectorOptionsRef = useRef11(inspectorOptions);
9426
9568
  inspectorOptionsRef.current = inspectorOptions;
9427
- useEffect14(() => {
9569
+ useEffect13(() => {
9428
9570
  if (process.env.NODE_ENV !== "development") {
9429
9571
  return;
9430
9572
  }