@archie/devtools 0.0.21 → 0.0.23

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";
@@ -4112,6 +4112,12 @@ var FIBER_KEY_PREFIX = "__reactFiber$";
4112
4112
  var PROPS_KEY_PREFIX = "__reactProps$";
4113
4113
  var metaCache = /* @__PURE__ */ new WeakMap();
4114
4114
  var directMetaCache = /* @__PURE__ */ new WeakMap();
4115
+ function readEditorMetaValue(value) {
4116
+ if (typeof value === "function") {
4117
+ return value();
4118
+ }
4119
+ return value ?? null;
4120
+ }
4115
4121
  function hasEditorMetaInFiberChain(fiber) {
4116
4122
  let current = fiber;
4117
4123
  while (current) {
@@ -4227,8 +4233,8 @@ function getDirectEditorMeta(el) {
4227
4233
  const selection = getFiberSelectionFromElement(el);
4228
4234
  const cached = readFiberAwareCache(directMetaCache, el, selection);
4229
4235
  if (cached !== void 0) return cached;
4230
- const meta = selection.fiber?.memoizedProps?.__editorMeta;
4231
- return writeFiberAwareCache(directMetaCache, el, selection, meta ?? null);
4236
+ const meta = readEditorMetaValue(selection.fiber?.memoizedProps?.__editorMeta);
4237
+ return writeFiberAwareCache(directMetaCache, el, selection, meta);
4232
4238
  }
4233
4239
  function getEditorMeta(el) {
4234
4240
  const selection = getFiberSelectionFromElement(el);
@@ -4236,7 +4242,7 @@ function getEditorMeta(el) {
4236
4242
  if (cached !== void 0) return cached;
4237
4243
  let fiber = selection.fiber;
4238
4244
  while (fiber) {
4239
- const meta = fiber.memoizedProps?.__editorMeta;
4245
+ const meta = readEditorMetaValue(fiber.memoizedProps?.__editorMeta);
4240
4246
  if (meta) {
4241
4247
  return writeFiberAwareCache(metaCache, el, selection, meta);
4242
4248
  }
@@ -4280,6 +4286,9 @@ function findMetaOwnerElement(el) {
4280
4286
  }
4281
4287
  function resolveHostElementFromFiberChain(el) {
4282
4288
  if (shouldIgnoreAsVirtualRuntime(el)) return null;
4289
+ if (el.hasAttribute("data-dnd-force-allow")) {
4290
+ return el;
4291
+ }
4283
4292
  const directMeta = getDirectEditorMeta(el);
4284
4293
  const ownerMeta = directMeta ?? getEditorMeta(el);
4285
4294
  if (isPassthroughMeta(ownerMeta)) {
@@ -4635,8 +4644,8 @@ function buildEmptyArrangeSessionState() {
4635
4644
  var useDesignModeStore = create((set, get) => ({
4636
4645
  // UI state
4637
4646
  enabled: false,
4638
- hoveredSelector: null,
4639
4647
  selectedSelector: null,
4648
+ inspectorSelectedNodeIds: [],
4640
4649
  historyMode: "local",
4641
4650
  inspectorTheme: DEFAULT_INSPECTOR_THEME,
4642
4651
  canUndo: false,
@@ -4652,16 +4661,23 @@ var useDesignModeStore = create((set, get) => ({
4652
4661
  // UI actions
4653
4662
  toggle: () => set((s) => ({ enabled: !s.enabled, ...buildEmptyArrangeSessionState() })),
4654
4663
  setEnabled: (enabled) => set({ enabled }),
4655
- setHovered: (selector) => set({ hoveredSelector: selector }),
4656
4664
  setSelected: (selector) => set({ selectedSelector: selector }),
4665
+ setInspectorSelection: (nodeIds) => {
4666
+ const next = nodeIds.filter((id) => typeof id === "string" && id.length > 0);
4667
+ const prev = get().inspectorSelectedNodeIds;
4668
+ if (prev.length === next.length && prev.every((id, i) => id === next[i])) {
4669
+ return;
4670
+ }
4671
+ set({ inspectorSelectedNodeIds: next });
4672
+ },
4657
4673
  setHistoryMode: (historyMode) => set({ historyMode }),
4658
4674
  setInspectorTheme: (theme) => set((s) => ({ inspectorTheme: mergeInspectorTheme({ ...s.inspectorTheme, ...theme }) })),
4659
4675
  setHistoryAvailability: (canUndo, canRedo) => set({ canUndo, canRedo }),
4660
4676
  requestUndo: () => set((s) => ({ undoRequestId: s.undoRequestId + 1 })),
4661
4677
  requestRedo: () => set((s) => ({ redoRequestId: s.redoRequestId + 1 })),
4662
4678
  resetAll: () => set({
4663
- hoveredSelector: null,
4664
4679
  selectedSelector: null,
4680
+ inspectorSelectedNodeIds: [],
4665
4681
  canUndo: false,
4666
4682
  canRedo: false
4667
4683
  }),
@@ -4779,9 +4795,13 @@ var useDesignModeStore = create((set, get) => ({
4779
4795
  inspectorRef,
4780
4796
  displayName,
4781
4797
  html,
4798
+ tsxCode,
4799
+ tsxImports,
4782
4800
  containerId,
4783
4801
  containerNodeKey,
4784
- index
4802
+ index,
4803
+ beforeSiblingInspectorRef,
4804
+ beforeSiblingNodeKey
4785
4805
  }) => {
4786
4806
  const now = Date.now();
4787
4807
  const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
@@ -4793,9 +4813,13 @@ var useDesignModeStore = create((set, get) => ({
4793
4813
  inspectorRef,
4794
4814
  displayName,
4795
4815
  html,
4816
+ tsxCode: tsxCode ?? null,
4817
+ tsxImports: tsxImports ?? null,
4796
4818
  containerId,
4797
4819
  containerNodeKey,
4798
4820
  index,
4821
+ beforeSiblingInspectorRef: beforeSiblingInspectorRef ?? null,
4822
+ beforeSiblingNodeKey: beforeSiblingNodeKey ?? null,
4799
4823
  at: now
4800
4824
  };
4801
4825
  set((s) => {
@@ -4873,7 +4897,7 @@ var useDesignModeStore = create((set, get) => ({
4873
4897
  }));
4874
4898
 
4875
4899
  // 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";
4900
+ import { useRef as useRef10, useCallback as useCallback8, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useState as useState6, useMemo as useMemo6 } from "react";
4877
4901
 
4878
4902
  // src/client/dnd/design-mode/useElementScanner.ts
4879
4903
  import { useState as useState4, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
@@ -5036,7 +5060,7 @@ function projectUsageMeta(el) {
5036
5060
  const owner = getEditorMetaOwnerFiber(el);
5037
5061
  if (!owner) return null;
5038
5062
  if (getSingleHostElement(owner) !== el) return null;
5039
- return owner.memoizedProps?.__editorMeta ?? null;
5063
+ return readEditorMetaValue(owner.memoizedProps?.__editorMeta);
5040
5064
  }
5041
5065
  function isRuntimeVisualInternal(el) {
5042
5066
  if (shouldIgnoreAsVirtualRuntime(el)) return true;
@@ -5402,14 +5426,14 @@ function handlePosition(dir) {
5402
5426
  };
5403
5427
  return positions[dir];
5404
5428
  }
5405
- function getOutlineStyle(rect, isSelected, isHovered, inspectorTheme) {
5429
+ function getOutlineStyle(rect, isSelected, inspectorTheme) {
5406
5430
  return {
5407
5431
  ...OUTLINE_BASE_STYLE,
5408
5432
  left: rect.left,
5409
5433
  top: rect.top,
5410
5434
  width: rect.width,
5411
5435
  height: rect.height,
5412
- border: isSelected ? `2px solid ${inspectorTheme.accent}` : isHovered ? `2px dashed ${inspectorTheme.hover}` : `1px dashed ${inspectorTheme.shared}`,
5436
+ border: isSelected ? `2px solid ${inspectorTheme.accent}` : `1px dashed ${inspectorTheme.shared}`,
5413
5437
  backgroundColor: isSelected ? inspectorTheme.accentSoft : "transparent"
5414
5438
  };
5415
5439
  }
@@ -5439,11 +5463,13 @@ function ElementHighlight({
5439
5463
  elements,
5440
5464
  draggingNodeId,
5441
5465
  activeEl,
5466
+ arrangeSelectedNodeId,
5467
+ externalDragActive,
5442
5468
  onResizeHandlePointerDown
5443
5469
  }) {
5444
- const hoveredSelector = useDesignModeStore((s) => s.hoveredSelector);
5445
- const selectedSelector = useDesignModeStore((s) => s.selectedSelector);
5446
5470
  const inspectorTheme = useDesignModeStore((s) => s.inspectorTheme);
5471
+ const internalDragInProgress = draggingNodeId !== null;
5472
+ const overlayVisible = arrangeSelectedNodeId !== null || internalDragInProgress;
5447
5473
  const containerRef = useRef5(null);
5448
5474
  const rafRef = useRef5(0);
5449
5475
  const syncPositions = useCallback5(() => {
@@ -5467,7 +5493,6 @@ function ElementHighlight({
5467
5493
  }
5468
5494
  }, [elements]);
5469
5495
  useEffect5(() => {
5470
- if (draggingNodeId) return;
5471
5496
  let running = true;
5472
5497
  const loop = () => {
5473
5498
  if (!running) return;
@@ -5479,8 +5504,9 @@ function ElementHighlight({
5479
5504
  running = false;
5480
5505
  cancelAnimationFrame(rafRef.current);
5481
5506
  };
5482
- }, [syncPositions, draggingNodeId]);
5483
- if (draggingNodeId) return null;
5507
+ }, [syncPositions]);
5508
+ if (!overlayVisible) return null;
5509
+ if (externalDragActive) return null;
5484
5510
  return /* @__PURE__ */ jsx2(
5485
5511
  "div",
5486
5512
  {
@@ -5490,10 +5516,10 @@ function ElementHighlight({
5490
5516
  children: elements.map((el) => {
5491
5517
  if (el.nodeId === draggingNodeId) return null;
5492
5518
  if (activeEl && activeEl !== el.element && activeEl.contains(el.element)) return null;
5493
- const isHovered = el.nodeId === hoveredSelector;
5494
- const isSelected = el.nodeId === selectedSelector;
5519
+ const isSelected = el.nodeId === arrangeSelectedNodeId;
5520
+ if (!isSelected && !internalDragInProgress) return null;
5495
5521
  const rect = el.element.getBoundingClientRect();
5496
- const showLabel = isHovered || isSelected;
5522
+ const showLabel = isSelected;
5497
5523
  const labelTop = isSelected ? Math.max(0, rect.top - 20) : rect.top;
5498
5524
  const labelLeft = isSelected ? rect.left + 12 : rect.left;
5499
5525
  return /* @__PURE__ */ jsxs("div", { children: [
@@ -5502,7 +5528,7 @@ function ElementHighlight({
5502
5528
  {
5503
5529
  "data-outline-for": el.nodeId,
5504
5530
  "data-design-mode-ui": true,
5505
- style: getOutlineStyle(rect, isSelected, isHovered, inspectorTheme),
5531
+ style: getOutlineStyle(rect, isSelected, inspectorTheme),
5506
5532
  children: isSelected && HANDLES.map((dir) => {
5507
5533
  const pos = handlePosition(dir);
5508
5534
  return /* @__PURE__ */ jsx2(
@@ -5797,6 +5823,57 @@ function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
5797
5823
  };
5798
5824
  }
5799
5825
 
5826
+ // src/client/dnd/design-mode/inserted-descendants.ts
5827
+ var NON_DRAGGABLE_DESCENDANT_TAGS = /* @__PURE__ */ new Set([
5828
+ // SVG internals — the whole <svg> is the unit; its parts must stay together.
5829
+ "svg",
5830
+ "path",
5831
+ "circle",
5832
+ "rect",
5833
+ "line",
5834
+ "polyline",
5835
+ "polygon",
5836
+ "g",
5837
+ "defs",
5838
+ "use",
5839
+ // <select>/<option>: options live inside their <select>, never standalone.
5840
+ "option",
5841
+ "optgroup",
5842
+ // Table internals: only meaningful in their <table> tree.
5843
+ "caption",
5844
+ "thead",
5845
+ "tbody",
5846
+ "tfoot",
5847
+ "tr",
5848
+ "th",
5849
+ "td",
5850
+ "col",
5851
+ "colgroup",
5852
+ // Self-closing inline atoms with no draggable surface.
5853
+ "br",
5854
+ "wbr",
5855
+ "hr",
5856
+ // Non-rendered metadata.
5857
+ "script",
5858
+ "style",
5859
+ "meta",
5860
+ "link",
5861
+ "title",
5862
+ "noscript",
5863
+ // Replaced media controls handled by their parent player.
5864
+ "source",
5865
+ "track"
5866
+ ]);
5867
+ function markInsertedDescendants(root) {
5868
+ const descendants = root.querySelectorAll("*");
5869
+ for (const node of descendants) {
5870
+ const tag = node.tagName.toLowerCase();
5871
+ if (NON_DRAGGABLE_DESCENDANT_TAGS.has(tag)) continue;
5872
+ node.setAttribute("data-dnd-force-allow", "");
5873
+ node.setAttribute("data-dnd-moved", "");
5874
+ }
5875
+ }
5876
+
5800
5877
  // src/client/dnd/design-mode/history.ts
5801
5878
  function applyInsertCommand(command, direction, resolveNodeElement) {
5802
5879
  if (direction === "undo") {
@@ -5819,6 +5896,7 @@ function applyInsertCommand(command, direction, resolveNodeElement) {
5819
5896
  (c) => c instanceof HTMLElement
5820
5897
  );
5821
5898
  container.insertBefore(newEl, kids[command.index] ?? null);
5899
+ markInsertedDescendants(newEl);
5822
5900
  return true;
5823
5901
  }
5824
5902
  var DEFAULT_LIMIT = 300;
@@ -6344,6 +6422,8 @@ function serializeArrangeChange(event, index) {
6344
6422
  containerId: event.kind === "insert" ? event.containerId : void 0,
6345
6423
  containerNodeKey: event.kind === "insert" ? event.containerNodeKey : void 0,
6346
6424
  insertIndex: event.kind === "insert" ? event.index : void 0,
6425
+ beforeSiblingInspectorRef: event.kind === "insert" ? event.beforeSiblingInspectorRef : void 0,
6426
+ beforeSiblingNodeKey: event.kind === "insert" ? event.beforeSiblingNodeKey : void 0,
6347
6427
  summary: summarizeEditorChangeEvent(event),
6348
6428
  at: event.at
6349
6429
  };
@@ -6641,50 +6721,8 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
6641
6721
  }), []);
6642
6722
  }
6643
6723
 
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
6724
  // src/client/dnd/design-mode/useDragVisualLoop.ts
6687
- import { useEffect as useEffect9 } from "react";
6725
+ import { useEffect as useEffect8 } from "react";
6688
6726
 
6689
6727
  // src/client/dnd/design-mode/quadtree.ts
6690
6728
  function overlaps(a, b) {
@@ -7573,7 +7611,7 @@ function useDragVisualLoop({
7573
7611
  setInsideRect,
7574
7612
  setDropLine
7575
7613
  }) {
7576
- useEffect9(() => {
7614
+ useEffect8(() => {
7577
7615
  const engine = refs.engineRef.current;
7578
7616
  const snapshot = refs.snapshotRef.current;
7579
7617
  if (!activeDrag || !engine || !snapshot) return;
@@ -8195,7 +8233,7 @@ function useDragLifecycle({
8195
8233
  }
8196
8234
 
8197
8235
  // src/client/dnd/design-mode/useResizeSession.ts
8198
- import { useCallback as useCallback7, useEffect as useEffect10 } from "react";
8236
+ import { useCallback as useCallback7, useEffect as useEffect9 } from "react";
8199
8237
  var RESIZE_POINTER_TOLERANCE_PX = 2;
8200
8238
  var RESIZE_DRAG_BLOCK_MS = 180;
8201
8239
  var RESIZE_MIN = 24;
@@ -8367,7 +8405,7 @@ function useResizeSession({
8367
8405
  });
8368
8406
  syncHistoryAvailability();
8369
8407
  }, [applyCommand, recordResizeChange, syncHistoryAvailability]);
8370
- useEffect10(() => {
8408
+ useEffect9(() => {
8371
8409
  if (!enabled) return;
8372
8410
  const handleResizePointerCancel = (e) => {
8373
8411
  const session = refs.resizeSessionRef.current;
@@ -8392,8 +8430,13 @@ function useResizeSession({
8392
8430
  }
8393
8431
 
8394
8432
  // src/client/dnd/design-mode/useExternalDragLoop.ts
8395
- import { useEffect as useEffect11, useRef as useRef9 } from "react";
8433
+ import { useEffect as useEffect10, useRef as useRef9 } from "react";
8396
8434
  var EXTERNAL_DRAG_ACTIVE_ID = "__external-drag-placeholder__";
8435
+ var insertNodeIdCounter = 0;
8436
+ function nextInsertNodeId() {
8437
+ insertNodeIdCounter += 1;
8438
+ return `insert:${Date.now()}:${insertNodeIdCounter}`;
8439
+ }
8397
8440
  function useExternalDragLoop({
8398
8441
  externalDrag,
8399
8442
  refs,
@@ -8403,7 +8446,7 @@ function useExternalDragLoop({
8403
8446
  }) {
8404
8447
  const engineRef = useRef9(null);
8405
8448
  const lastIntentRef = useRef9(null);
8406
- useEffect11(() => {
8449
+ useEffect10(() => {
8407
8450
  if (!externalDrag) {
8408
8451
  engineRef.current = null;
8409
8452
  lastIntentRef.current = null;
@@ -8493,7 +8536,7 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8493
8536
  setDropLine(null);
8494
8537
  return;
8495
8538
  }
8496
- const nodeId = `insert:${Date.now()}`;
8539
+ const nodeId = nextInsertNodeId();
8497
8540
  newElement.setAttribute(DND_NODE_ID_ATTR, nodeId);
8498
8541
  newElement.setAttribute("data-dnd-force-allow", "");
8499
8542
  newElement.setAttribute("data-dnd-moved", "");
@@ -8502,6 +8545,23 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8502
8545
  );
8503
8546
  const beforeChild = children[intent.index] ?? null;
8504
8547
  containerEl.insertBefore(newElement, beforeChild);
8548
+ markInsertedDescendants(newElement);
8549
+ const postInsertChildren = Array.from(containerEl.children).filter(
8550
+ (child) => child instanceof HTMLElement
8551
+ );
8552
+ let beforeSiblingEl = null;
8553
+ let beforeSiblingNodeId = null;
8554
+ const startIdx = postInsertChildren.indexOf(newElement) + 1;
8555
+ for (let i = startIdx; i < postInsertChildren.length; i += 1) {
8556
+ const candidate = postInsertChildren[i];
8557
+ const candidateNodeId = candidate.getAttribute(DND_NODE_ID_ATTR);
8558
+ if (!candidateNodeId) continue;
8559
+ const isEarlierInsert = candidateNodeId.startsWith("insert:");
8560
+ if (!isEarlierInsert && !getInspectorRefFromElement(candidate)) continue;
8561
+ beforeSiblingEl = candidate;
8562
+ beforeSiblingNodeId = candidateNodeId;
8563
+ break;
8564
+ }
8505
8565
  const insertCommand = {
8506
8566
  type: "insert",
8507
8567
  nodeId,
@@ -8527,6 +8587,15 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8527
8587
  inspectorRef: getInspectorRefFromElement(containerEl)
8528
8588
  };
8529
8589
  }
8590
+ let beforeSiblingIdentity = null;
8591
+ if (beforeSiblingEl && beforeSiblingNodeId) {
8592
+ beforeSiblingIdentity = {
8593
+ nodeId: beforeSiblingNodeId,
8594
+ nodeKey: getNodeKeyFromElement(beforeSiblingEl),
8595
+ selector: buildNodeSelector(beforeSiblingNodeId),
8596
+ inspectorRef: getInspectorRefFromElement(beforeSiblingEl)
8597
+ };
8598
+ }
8530
8599
  const operationId = `${insertCommand.at}:${nodeId}`;
8531
8600
  useDesignModeStore.getState().recordInsertChange({
8532
8601
  operationId,
@@ -8535,9 +8604,13 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8535
8604
  inspectorRef,
8536
8605
  displayName: component.displayName,
8537
8606
  html: component.html,
8607
+ tsxCode: component.tsxCode ?? null,
8608
+ tsxImports: component.tsxImports ?? null,
8538
8609
  containerId: intent.containerId,
8539
8610
  containerNodeKey,
8540
- index: intent.index
8611
+ index: intent.index,
8612
+ beforeSiblingInspectorRef: beforeSiblingIdentity?.inspectorRef ?? null,
8613
+ beforeSiblingNodeKey: beforeSiblingIdentity?.nodeKey ?? null
8541
8614
  });
8542
8615
  dispatchRuntimeEvent({
8543
8616
  type: "element-inserted",
@@ -8546,8 +8619,11 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
8546
8619
  nodeKey,
8547
8620
  displayName: component.displayName,
8548
8621
  html: component.html,
8622
+ tsxCode: component.tsxCode ?? null,
8623
+ tsxImports: component.tsxImports ?? null,
8549
8624
  container: containerIdentity,
8550
- index: intent.index
8625
+ index: intent.index,
8626
+ beforeSibling: beforeSiblingIdentity
8551
8627
  });
8552
8628
  }
8553
8629
  setDropLine(null);
@@ -8598,8 +8674,12 @@ function HitArea({
8598
8674
  selectedNodeId,
8599
8675
  onResizeHandlePointerDown
8600
8676
  }) {
8601
- const { setNodeRef, listeners, attributes, isDragging } = useDraggable({ id: scanned.nodeId });
8602
- useEffect12(() => {
8677
+ const isSelected = scanned.nodeId === selectedNodeId;
8678
+ const { setNodeRef, listeners, attributes, isDragging } = useDraggable({
8679
+ id: scanned.nodeId,
8680
+ disabled: !isSelected
8681
+ });
8682
+ useEffect11(() => {
8603
8683
  setNodeRef(scanned.element);
8604
8684
  return () => setNodeRef(null);
8605
8685
  }, [setNodeRef, scanned.element]);
@@ -8611,7 +8691,7 @@ function HitArea({
8611
8691
  el.style.removeProperty("opacity");
8612
8692
  }
8613
8693
  }, [isDragging, scanned.element]);
8614
- useEffect12(() => () => {
8694
+ useEffect11(() => () => {
8615
8695
  scanned.element.style.removeProperty("opacity");
8616
8696
  scanned.element.style.removeProperty("transform");
8617
8697
  scanned.element.style.removeProperty("transition");
@@ -8619,8 +8699,18 @@ function HitArea({
8619
8699
  }, [scanned.element]);
8620
8700
  const divRef = useRef10(null);
8621
8701
  const [hoverResizeHandle, setHoverResizeHandle] = useState6(null);
8622
- const isSelected = scanned.nodeId === selectedNodeId;
8623
- useEffect12(() => {
8702
+ const justDraggedRef = useRef10(false);
8703
+ useEffect11(() => {
8704
+ if (isDragging) {
8705
+ justDraggedRef.current = true;
8706
+ return;
8707
+ }
8708
+ const id = window.setTimeout(() => {
8709
+ justDraggedRef.current = false;
8710
+ }, 0);
8711
+ return () => window.clearTimeout(id);
8712
+ }, [isDragging]);
8713
+ useEffect11(() => {
8624
8714
  const div = divRef.current;
8625
8715
  if (!div) return;
8626
8716
  const onWheel = (e) => {
@@ -8636,7 +8726,7 @@ function HitArea({
8636
8726
  return () => div.removeEventListener("wheel", onWheel);
8637
8727
  }, []);
8638
8728
  const { left, top, width, height } = scanned.rect;
8639
- const cursor = isDragging ? "grabbing" : isSelected && hoverResizeHandle ? resizeCursorFromHandle(hoverResizeHandle) : "grab";
8729
+ const cursor = isDragging ? "grabbing" : !isSelected ? "default" : hoverResizeHandle ? resizeCursorFromHandle(hoverResizeHandle) : "grab";
8640
8730
  return /* @__PURE__ */ jsx4(
8641
8731
  "div",
8642
8732
  {
@@ -8667,6 +8757,35 @@ function HitArea({
8667
8757
  ...attributes,
8668
8758
  ...listeners,
8669
8759
  onClick: (e) => {
8760
+ if (justDraggedRef.current) {
8761
+ e.preventDefault();
8762
+ e.stopPropagation();
8763
+ return;
8764
+ }
8765
+ const stack = document.elementsFromPoint(e.clientX, e.clientY);
8766
+ for (const candidate of stack) {
8767
+ if (!(candidate instanceof HTMLElement)) continue;
8768
+ if (candidate.hasAttribute("data-design-mode-ui")) continue;
8769
+ if (candidate === scanned.element) break;
8770
+ const candidateNodeId = candidate.getAttribute("data-dnd-node-id");
8771
+ if (candidateNodeId && candidateNodeId !== scanned.nodeId) {
8772
+ e.preventDefault();
8773
+ e.stopPropagation();
8774
+ candidate.dispatchEvent(
8775
+ new MouseEvent("mousedown", {
8776
+ bubbles: true,
8777
+ cancelable: true,
8778
+ clientX: e.clientX,
8779
+ clientY: e.clientY,
8780
+ metaKey: e.metaKey,
8781
+ ctrlKey: e.ctrlKey,
8782
+ shiftKey: e.shiftKey,
8783
+ altKey: e.altKey
8784
+ })
8785
+ );
8786
+ return;
8787
+ }
8788
+ }
8670
8789
  e.preventDefault();
8671
8790
  e.stopPropagation();
8672
8791
  onActivate(scanned.nodeId);
@@ -8677,9 +8796,11 @@ function HitArea({
8677
8796
  function DesignModeOverlay() {
8678
8797
  const enabled = useDesignModeStore((s) => s.enabled);
8679
8798
  const historyMode = useDesignModeStore((s) => s.historyMode);
8680
- const setHovered = useDesignModeStore((s) => s.setHovered);
8681
8799
  const selectElement = useDesignModeStore((s) => s.setSelected);
8682
- const selectedSelector = useDesignModeStore((s) => s.selectedSelector);
8800
+ const inspectorSelectedNodeIds = useDesignModeStore(
8801
+ (s) => s.inspectorSelectedNodeIds
8802
+ );
8803
+ const arrangeSelectedNodeId = inspectorSelectedNodeIds.length === 1 ? inspectorSelectedNodeIds[0] : null;
8683
8804
  const setHistoryAvailability = useDesignModeStore((s) => s.setHistoryAvailability);
8684
8805
  const undoRequestId = useDesignModeStore((s) => s.undoRequestId);
8685
8806
  const redoRequestId = useDesignModeStore((s) => s.redoRequestId);
@@ -8705,16 +8826,23 @@ function DesignModeOverlay() {
8705
8826
  (el) => el.draggable !== false
8706
8827
  );
8707
8828
  }, [elements, nodeMap]);
8829
+ const arrangeHitAreaElement = useMemo6(() => {
8830
+ if (!arrangeSelectedNodeId) return null;
8831
+ if (externalDrag) return null;
8832
+ return draggableElements.find(
8833
+ (candidate) => candidate.nodeId === arrangeSelectedNodeId
8834
+ ) ?? null;
8835
+ }, [arrangeSelectedNodeId, externalDrag, draggableElements]);
8708
8836
  const refs = useOverlayRefs(undoRequestId, redoRequestId);
8709
8837
  refs.elementsRef.current = elements;
8710
8838
  refs.nodeMapRef.current = nodeMap;
8711
- useEffect12(() => {
8839
+ useEffect11(() => {
8712
8840
  const m = /* @__PURE__ */ new Map();
8713
8841
  for (const el of draggableElements) m.set(el.nodeId, el);
8714
8842
  refs.draggableNodeMapRef.current = m;
8715
8843
  }, [draggableElements]);
8716
8844
  const [grabFeedback, setGrabFeedback] = useState6(null);
8717
- useEffect12(() => {
8845
+ useEffect11(() => {
8718
8846
  if (!enabled) return;
8719
8847
  const onPointerDown = (e) => {
8720
8848
  if (!shouldShowGrabFeedback(
@@ -8728,7 +8856,7 @@ function DesignModeOverlay() {
8728
8856
  document.addEventListener("pointerdown", onPointerDown, true);
8729
8857
  return () => document.removeEventListener("pointerdown", onPointerDown, true);
8730
8858
  }, [enabled]);
8731
- useEffect12(() => {
8859
+ useEffect11(() => {
8732
8860
  if (!grabFeedback) return;
8733
8861
  const t = setTimeout(() => setGrabFeedback(null), 1400);
8734
8862
  return () => clearTimeout(t);
@@ -8785,7 +8913,7 @@ function DesignModeOverlay() {
8785
8913
  }
8786
8914
  setHistoryAvailability(refs.historyRef.current.canUndo(), refs.historyRef.current.canRedo());
8787
8915
  }, [historyMode, setHistoryAvailability]);
8788
- useEffect12(() => {
8916
+ useEffect11(() => {
8789
8917
  refs.historyRef.current.clear();
8790
8918
  syncHistoryAvailability();
8791
8919
  }, [enabled, syncHistoryAvailability]);
@@ -8799,7 +8927,7 @@ function DesignModeOverlay() {
8799
8927
  );
8800
8928
  const [insideRect, setInsideRect] = useState6(null);
8801
8929
  const [dropLine, setDropLine] = useState6(null);
8802
- useEffect12(() => {
8930
+ useEffect11(() => {
8803
8931
  if (!enabled) return;
8804
8932
  const fn = (e) => {
8805
8933
  refs.mouseRef.current = { x: e.clientX, y: e.clientY };
@@ -8807,7 +8935,7 @@ function DesignModeOverlay() {
8807
8935
  window.addEventListener("pointermove", fn, { capture: true, passive: true });
8808
8936
  return () => window.removeEventListener("pointermove", fn, { capture: true });
8809
8937
  }, [enabled]);
8810
- useEffect12(() => {
8938
+ useEffect11(() => {
8811
8939
  if (!enabled) return;
8812
8940
  if (historyMode !== "local") return;
8813
8941
  const onKeyDown = (e) => {
@@ -8836,7 +8964,7 @@ function DesignModeOverlay() {
8836
8964
  setInsideRect,
8837
8965
  setDropLine
8838
8966
  });
8839
- useEffect12(() => {
8967
+ useEffect11(() => {
8840
8968
  if (!enabled || activeDrag) return;
8841
8969
  if (undoRequestId === refs.processedUndoIdRef.current) return;
8842
8970
  refs.processedUndoIdRef.current = undoRequestId;
@@ -8853,7 +8981,7 @@ function DesignModeOverlay() {
8853
8981
  });
8854
8982
  syncHistoryAvailability();
8855
8983
  }, [undoRequestId, enabled, activeDrag, applyCommand, resume, selectElement, syncHistoryAvailability, undoLastChange]);
8856
- useEffect12(() => {
8984
+ useEffect11(() => {
8857
8985
  if (!enabled || activeDrag || historyMode !== "local") return;
8858
8986
  if (redoRequestId === refs.processedRedoIdRef.current) return;
8859
8987
  refs.processedRedoIdRef.current = redoRequestId;
@@ -8865,18 +8993,18 @@ function DesignModeOverlay() {
8865
8993
  }
8866
8994
  syncHistoryAvailability();
8867
8995
  }, [redoRequestId, enabled, activeDrag, applyCommand, historyMode, resume, selectElement, syncHistoryAvailability, redoLastChange]);
8868
- useEffect12(() => {
8996
+ useEffect11(() => {
8869
8997
  syncHistoryAvailability();
8870
8998
  }, [syncHistoryAvailability]);
8871
- useEffect12(() => {
8999
+ useEffect11(() => {
8872
9000
  dispatchRuntimeEvent({
8873
9001
  type: "design-mode-changed",
8874
9002
  mode: enabled ? "design" : "off"
8875
9003
  });
8876
9004
  }, [enabled]);
8877
- useEffect12(() => {
9005
+ useEffect11(() => {
8878
9006
  const aiOutput = exportChangesForAI();
8879
- const updatedAt = orderedChanges.length > 0 ? orderedChanges[orderedChanges.length - 1]?.at ?? Date.now() : Date.now();
9007
+ const updatedAt = Date.now();
8880
9008
  dispatchRuntimeEvent({
8881
9009
  type: "arrange-session-changed",
8882
9010
  session: buildArrangeSessionSnapshot({
@@ -8887,12 +9015,11 @@ function DesignModeOverlay() {
8887
9015
  })
8888
9016
  });
8889
9017
  }, [enabled, exportChangesForAI, orderedChanges]);
8890
- useEffect12(() => {
9018
+ useEffect11(() => {
8891
9019
  if (!enabled) return;
8892
9020
  document.body.classList.add("design-mode-active");
8893
9021
  return () => document.body.classList.remove("design-mode-active");
8894
9022
  }, [enabled]);
8895
- useHoverDetection({ enabled, activeDrag, elementsRef: refs.elementsRef, setHovered });
8896
9023
  useDesignModeAutoScroll({
8897
9024
  active: !!activeDrag,
8898
9025
  mouseRef: refs.mouseRef,
@@ -8931,19 +9058,21 @@ function DesignModeOverlay() {
8931
9058
  elements,
8932
9059
  draggingNodeId: activeDrag?.nodeId ?? null,
8933
9060
  activeEl: refs.activeElRef.current,
9061
+ arrangeSelectedNodeId,
9062
+ externalDragActive: externalDrag !== null,
8934
9063
  onResizeHandlePointerDown: handleResizeHandlePointerDown
8935
9064
  }
8936
9065
  ),
8937
- draggableElements.map((el) => /* @__PURE__ */ jsx4(
9066
+ arrangeHitAreaElement && /* @__PURE__ */ jsx4(
8938
9067
  HitArea,
8939
9068
  {
8940
- scanned: el,
9069
+ scanned: arrangeHitAreaElement,
8941
9070
  onActivate: selectElement,
8942
- selectedNodeId: selectedSelector,
9071
+ selectedNodeId: arrangeHitAreaElement.nodeId,
8943
9072
  onResizeHandlePointerDown: handleResizeHandlePointerDown
8944
9073
  },
8945
- el.nodeId
8946
- )),
9074
+ arrangeHitAreaElement.nodeId
9075
+ ),
8947
9076
  grabFeedback ? /* @__PURE__ */ jsx4(
8948
9077
  "div",
8949
9078
  {
@@ -9058,7 +9187,7 @@ function DndProvider({ children }) {
9058
9187
  designModeState.resetArrangeSession();
9059
9188
  designModeState.setEnabled(nextEnabled);
9060
9189
  }, []);
9061
- useEffect13(() => {
9190
+ useEffect12(() => {
9062
9191
  const handleKeyDown = (e) => {
9063
9192
  if (e.ctrlKey && e.shiftKey && e.key === "D") {
9064
9193
  e.preventDefault();
@@ -9068,7 +9197,7 @@ function DndProvider({ children }) {
9068
9197
  window.addEventListener("keydown", handleKeyDown);
9069
9198
  return () => window.removeEventListener("keydown", handleKeyDown);
9070
9199
  }, [transitionDesignMode]);
9071
- useEffect13(() => {
9200
+ useEffect12(() => {
9072
9201
  const handleHostCommand = (event) => {
9073
9202
  const detail = event.detail;
9074
9203
  if (!detail || typeof detail !== "object") return;
@@ -9127,6 +9256,25 @@ function DndProvider({ children }) {
9127
9256
  setInspectorTheme,
9128
9257
  requestUndo
9129
9258
  ]);
9259
+ useEffect12(() => {
9260
+ const bridgeWindow = window;
9261
+ const bridge = {
9262
+ setInspectorSelection: (nodeIds) => {
9263
+ useDesignModeStore.getState().setInspectorSelection(nodeIds);
9264
+ }
9265
+ };
9266
+ bridgeWindow.__ARCHIE_DESIGN_MODE__ = bridge;
9267
+ const pending = bridgeWindow.__ARCHIE_DESIGN_MODE_PENDING__;
9268
+ if (Array.isArray(pending)) {
9269
+ bridge.setInspectorSelection(pending);
9270
+ delete bridgeWindow.__ARCHIE_DESIGN_MODE_PENDING__;
9271
+ }
9272
+ return () => {
9273
+ if (bridgeWindow.__ARCHIE_DESIGN_MODE__ === bridge) {
9274
+ delete bridgeWindow.__ARCHIE_DESIGN_MODE__;
9275
+ }
9276
+ };
9277
+ }, []);
9130
9278
  const pointerSensor = useSensor(PointerSensor, { activationConstraint: { distance: 8 } });
9131
9279
  const keyboardSensor = useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates });
9132
9280
  const sensors = useSensors(pointerSensor, keyboardSensor);
@@ -9198,12 +9346,12 @@ function DndProvider({ children }) {
9198
9346
  }
9199
9347
 
9200
9348
  // src/client/useArchieDevToolsRuntime.ts
9201
- import { useEffect as useEffect14, useRef as useRef11 } from "react";
9349
+ import { useEffect as useEffect13, useRef as useRef11 } from "react";
9202
9350
 
9203
9351
  // src/client/archieLocalInspectorEnv.ts
9204
9352
  function readArchieLocalInspectorFlag() {
9205
9353
  try {
9206
- return import.meta.env?.VITE_ARCHIE_LOCAL_INSPECTOR === "true";
9354
+ return false;
9207
9355
  } catch {
9208
9356
  return false;
9209
9357
  }
@@ -9424,7 +9572,7 @@ function useArchieDevToolsRuntime({
9424
9572
  const stableOptionsKey = JSON.stringify(inspectorOptions ?? null);
9425
9573
  const inspectorOptionsRef = useRef11(inspectorOptions);
9426
9574
  inspectorOptionsRef.current = inspectorOptions;
9427
- useEffect14(() => {
9575
+ useEffect13(() => {
9428
9576
  if (process.env.NODE_ENV !== "development") {
9429
9577
  return;
9430
9578
  }