@archie/devtools 0.0.34 → 0.0.36

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.
@@ -4085,6 +4085,46 @@ function DragOverlay2() {
4085
4085
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragOverlay, { dropAnimation: null, children: renderContent() });
4086
4086
  }
4087
4087
 
4088
+ // src/client/dnd/design-mode/debug-trace.ts
4089
+ var MAX_ENTRIES = 800;
4090
+ function traceWindow() {
4091
+ return typeof window === "undefined" ? null : window;
4092
+ }
4093
+ function isVeDebugEnabled() {
4094
+ const w = traceWindow();
4095
+ if (!w) return false;
4096
+ if (w.__ARCHIE_VE_DEBUG__ === true || w._inspectorDebug === true) return true;
4097
+ try {
4098
+ return w.localStorage?.getItem("ARCHIE_VE_DEBUG") === "1";
4099
+ } catch {
4100
+ return false;
4101
+ }
4102
+ }
4103
+ function veTrace(layer, event, data) {
4104
+ const w = traceWindow();
4105
+ if (!w) return;
4106
+ let resolved;
4107
+ if (typeof data === "function") {
4108
+ try {
4109
+ resolved = data();
4110
+ } catch (error) {
4111
+ resolved = { __traceDataError: String(error) };
4112
+ }
4113
+ } else {
4114
+ resolved = data;
4115
+ }
4116
+ const entry = { t: Date.now(), layer, event, ...resolved === void 0 ? {} : { data: resolved } };
4117
+ const buffer = w.__ARCHIE_VE_TRACE__ ?? (w.__ARCHIE_VE_TRACE__ = []);
4118
+ buffer.push(entry);
4119
+ if (buffer.length > MAX_ENTRIES) buffer.splice(0, buffer.length - MAX_ENTRIES);
4120
+ if (!w.__ARCHIE_VE_TRACE_DUMP__) {
4121
+ w.__ARCHIE_VE_TRACE_DUMP__ = () => JSON.stringify(w.__ARCHIE_VE_TRACE__ ?? []);
4122
+ }
4123
+ if (isVeDebugEnabled()) {
4124
+ console.log(`[archie-ve:${layer}]`, event, resolved ?? "");
4125
+ }
4126
+ }
4127
+
4088
4128
  // src/client/dnd/design-mode/host-bridge.ts
4089
4129
  var DEFAULT_INSPECTOR_THEME = {
4090
4130
  accent: "#8b5cf6",
@@ -4094,8 +4134,80 @@ var DEFAULT_INSPECTOR_THEME = {
4094
4134
  };
4095
4135
  var HOST_COMMAND_EVENT = "archie:editor-host-command";
4096
4136
  var DND_RUNTIME_EVENT = "archie:dnd-runtime-event";
4137
+ function summarizeIdentity(identity2) {
4138
+ if (!identity2) return null;
4139
+ return {
4140
+ nodeId: identity2.nodeId,
4141
+ nodeKey: identity2.nodeKey,
4142
+ ref: identity2.inspectorRef ? `${identity2.inspectorRef.relativePath}:${identity2.inspectorRef.line}:${identity2.inspectorRef.column}` : null,
4143
+ ...identity2.effectiveNodeId && identity2.effectiveNodeId !== identity2.nodeId ? { effectiveNodeId: identity2.effectiveNodeId } : {}
4144
+ };
4145
+ }
4146
+ function summarizeRuntimeEvent(detail) {
4147
+ switch (detail.type) {
4148
+ case "element-moved":
4149
+ return {
4150
+ operationId: detail.operationId,
4151
+ commandType: detail.commandType,
4152
+ selected: summarizeIdentity(detail.selected),
4153
+ anchor: summarizeIdentity(detail.anchor),
4154
+ container: summarizeIdentity(detail.container),
4155
+ beforeSibling: summarizeIdentity(detail.beforeSibling),
4156
+ sourceContainer: summarizeIdentity(detail.sourceContainer),
4157
+ diagnostics: detail.diagnostics ?? null
4158
+ };
4159
+ case "element-resized":
4160
+ return {
4161
+ operationId: detail.operationId,
4162
+ selected: summarizeIdentity(detail.selected),
4163
+ anchor: summarizeIdentity(detail.anchor),
4164
+ resize: {
4165
+ mode: detail.resize.mode,
4166
+ selectedNodeKey: detail.resize.selectedNodeKey,
4167
+ targetNodeKey: detail.resize.targetNodeKey,
4168
+ targetNodeId: detail.resize.targetNodeId,
4169
+ width: detail.resize.width,
4170
+ height: detail.resize.height
4171
+ }
4172
+ };
4173
+ case "element-inserted":
4174
+ return {
4175
+ operationId: detail.operationId,
4176
+ nodeId: detail.nodeId,
4177
+ nodeKey: detail.nodeKey,
4178
+ displayName: detail.displayName,
4179
+ container: summarizeIdentity(detail.container),
4180
+ index: detail.index,
4181
+ beforeSibling: summarizeIdentity(detail.beforeSibling),
4182
+ hasTsxCode: !!detail.tsxCode,
4183
+ htmlLength: detail.html?.length ?? 0
4184
+ };
4185
+ case "arrange-session-changed":
4186
+ return {
4187
+ mode: detail.session.mode,
4188
+ canUndo: detail.session.canUndo,
4189
+ changeCount: detail.session.changes.length,
4190
+ changes: detail.session.changes.map((c) => ({
4191
+ id: c.id,
4192
+ kind: c.kind,
4193
+ operationId: c.operationId,
4194
+ nodeKey: c.nodeKey,
4195
+ ref: c.inspectorRef ? `${c.inspectorRef.relativePath}:${c.inspectorRef.line}:${c.inspectorRef.column}` : null
4196
+ }))
4197
+ };
4198
+ case "arrange-undo-applied":
4199
+ return { success: detail.success, updatedAt: detail.updatedAt };
4200
+ case "design-mode-changed":
4201
+ return { mode: detail.mode };
4202
+ case "design-mode-error":
4203
+ return { error: detail.error };
4204
+ default:
4205
+ return null;
4206
+ }
4207
+ }
4097
4208
  function dispatchRuntimeEvent(detail) {
4098
4209
  if (typeof window === "undefined") return;
4210
+ veTrace("dnd", `runtime-event:${detail.type}`, () => summarizeRuntimeEvent(detail));
4099
4211
  window.dispatchEvent(new CustomEvent(DND_RUNTIME_EVENT, { detail }));
4100
4212
  }
4101
4213
  function resolveRowBinding(el) {
@@ -6088,6 +6200,8 @@ function resolveResizeTargetElement(selectedEl) {
6088
6200
  );
6089
6201
  if (elementChildren.length !== 1) return selectedEl;
6090
6202
  const child = elementChildren[0];
6203
+ const childId = child.getAttribute(DND_NODE_ID_ATTR);
6204
+ if (childId && !childId.startsWith("dnd-parent:")) return selectedEl;
6091
6205
  const ownText = Array.from(selectedEl.childNodes).some((node) => {
6092
6206
  if (node.nodeType !== Node.TEXT_NODE) return false;
6093
6207
  return (node.textContent ?? "").trim().length > 0;
@@ -8194,8 +8308,23 @@ function useDragLifecycle({
8194
8308
  if (refs.resizeSessionRef.current || Date.now() < refs.resizeDragBlockUntilRef.current) return;
8195
8309
  const activeId = active.id;
8196
8310
  const found = refs.draggableNodeMapRef.current.get(activeId) ?? refs.nodeMapRef.current.get(activeId);
8197
- if (!found) return;
8198
- if (!isEligibleForDrag(found)) return;
8311
+ if (!found) {
8312
+ veTrace("dnd", "drag:start-rejected", { nodeId: activeId, reason: "not-scanned" });
8313
+ return;
8314
+ }
8315
+ if (!isEligibleForDrag(found)) {
8316
+ veTrace("dnd", "drag:start-rejected", {
8317
+ nodeId: activeId,
8318
+ reason: "not-eligible",
8319
+ eligibilitySource: found.eligibilitySource ?? "editor-meta",
8320
+ draggable: found.draggable
8321
+ });
8322
+ return;
8323
+ }
8324
+ veTrace("dnd", "drag:start", {
8325
+ nodeId: activeId,
8326
+ eligibilitySource: found.eligibilitySource ?? "editor-meta"
8327
+ });
8199
8328
  refs.lastIntentRef.current = null;
8200
8329
  refs.visualIntentRef.current = null;
8201
8330
  refs.targetPlaneRef.current = "lane";
@@ -8254,6 +8383,16 @@ function useDragLifecycle({
8254
8383
  const pointer = refs.mouseRef.current;
8255
8384
  const safeZone = refs.safeZoneRef.current;
8256
8385
  const blockedByGuard = isPointerOutsideSafeZone(pointer.x, pointer.y, safeZone) || isPointerInHardPageEdgeZone(pointer.x, pointer.y);
8386
+ veTrace("dnd", "drag:end", () => ({
8387
+ selectedNodeId,
8388
+ anchorNodeId,
8389
+ blockedByGuard,
8390
+ intent: refs.visualIntentRef.current ? {
8391
+ mode: refs.visualIntentRef.current.mode,
8392
+ containerId: refs.visualIntentRef.current.containerId,
8393
+ index: refs.visualIntentRef.current.index
8394
+ } : null
8395
+ }));
8257
8396
  let sourcePos = refs.dragStartPositionRef.current ?? getCurrentCommitPlacement(anchorNodeId, refs.sourceContainerIdRef.current);
8258
8397
  if (!sourcePos && activeEl && activeEl.parentElement) {
8259
8398
  const parentEl = activeEl.parentElement;
@@ -8352,6 +8491,7 @@ function useDragLifecycle({
8352
8491
  syncHistoryAvailability();
8353
8492
  }, [applyCommand, classifyCommandType, clearDragState, getCurrentCommitPlacement, recordMoveChange, resolveNodeElement, selectElement, syncHistoryAvailability]);
8354
8493
  const handleDragCancel = (0, import_react13.useCallback)(() => {
8494
+ veTrace("dnd", "drag:cancel");
8355
8495
  clearDragState();
8356
8496
  }, [clearDragState]);
8357
8497
  return { activeDrag, handleDragStart, handleDragEnd, handleDragCancel };
@@ -8413,6 +8553,17 @@ function useResizeSession({
8413
8553
  beforeStyles,
8414
8554
  hasMoved: false
8415
8555
  };
8556
+ veTrace("dnd", "resize:start", {
8557
+ dir,
8558
+ mode,
8559
+ selectedNodeId: nodeId,
8560
+ selectedNodeKey,
8561
+ targetNodeId,
8562
+ targetNodeKey,
8563
+ retargeted: resizeTargetEl !== selectedEl,
8564
+ startW: Math.round(rect.width),
8565
+ startH: Math.round(rect.height)
8566
+ });
8416
8567
  pointerTarget?.setPointerCapture?.(e.pointerId);
8417
8568
  }, []);
8418
8569
  const handleResizePointerMove = (0, import_react14.useCallback)((e) => {
@@ -8475,6 +8626,7 @@ function useResizeSession({
8475
8626
  const afterStyles = readStyleSnapshot(element, ["width", "height", "grid-column", "grid-column-end", "grid-row", "grid-row-end"]);
8476
8627
  const unchanged = mode === "grid-span" ? afterColSpan === startColSpan && afterRowSpan === startRowSpan : afterW === Math.round(startW) && afterH === Math.round(startH);
8477
8628
  if (unchanged) {
8629
+ veTrace("dnd", "resize:noop", { selectedNodeId, targetNodeId });
8478
8630
  syncHistoryAvailability();
8479
8631
  return;
8480
8632
  }
@@ -8536,6 +8688,10 @@ function useResizeSession({
8536
8688
  const session = refs.resizeSessionRef.current;
8537
8689
  if (!session || session.pointerId !== e.pointerId) return;
8538
8690
  if (session.pointerTarget?.hasPointerCapture?.(e.pointerId)) session.pointerTarget.releasePointerCapture(e.pointerId);
8691
+ veTrace("dnd", "resize:cancel", {
8692
+ selectedNodeId: session.selectedNodeId,
8693
+ targetNodeId: session.targetNodeId
8694
+ });
8539
8695
  for (const [prop, value] of Object.entries(session.beforeStyles)) {
8540
8696
  if (value === null) session.element.style.removeProperty(prop);
8541
8697
  else session.element.style.setProperty(prop, value);
@@ -9326,6 +9482,13 @@ function DndProvider({ children }) {
9326
9482
  const handleHostCommand = (event) => {
9327
9483
  const detail = event.detail;
9328
9484
  if (!detail || typeof detail !== "object") return;
9485
+ if (detail.type !== "external-drag-move") {
9486
+ veTrace(
9487
+ "dnd",
9488
+ `host-command:${detail.type}`,
9489
+ () => detail.type === "external-drag-start" ? { displayName: detail.component.displayName, category: detail.component.category } : detail.type === "sync-editor-state" ? { mode: detail.mode ?? null, historyMode: detail.historyMode ?? null } : detail.type === "set-design-mode" ? { enabled: detail.enabled } : void 0
9490
+ );
9491
+ }
9329
9492
  switch (detail.type) {
9330
9493
  case "sync-editor-state":
9331
9494
  if (detail.mode === "design") {
@@ -4050,6 +4050,46 @@ function DragOverlay2() {
4050
4050
  return /* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: renderContent() });
4051
4051
  }
4052
4052
 
4053
+ // src/client/dnd/design-mode/debug-trace.ts
4054
+ var MAX_ENTRIES = 800;
4055
+ function traceWindow() {
4056
+ return typeof window === "undefined" ? null : window;
4057
+ }
4058
+ function isVeDebugEnabled() {
4059
+ const w = traceWindow();
4060
+ if (!w) return false;
4061
+ if (w.__ARCHIE_VE_DEBUG__ === true || w._inspectorDebug === true) return true;
4062
+ try {
4063
+ return w.localStorage?.getItem("ARCHIE_VE_DEBUG") === "1";
4064
+ } catch {
4065
+ return false;
4066
+ }
4067
+ }
4068
+ function veTrace(layer, event, data) {
4069
+ const w = traceWindow();
4070
+ if (!w) return;
4071
+ let resolved;
4072
+ if (typeof data === "function") {
4073
+ try {
4074
+ resolved = data();
4075
+ } catch (error) {
4076
+ resolved = { __traceDataError: String(error) };
4077
+ }
4078
+ } else {
4079
+ resolved = data;
4080
+ }
4081
+ const entry = { t: Date.now(), layer, event, ...resolved === void 0 ? {} : { data: resolved } };
4082
+ const buffer = w.__ARCHIE_VE_TRACE__ ?? (w.__ARCHIE_VE_TRACE__ = []);
4083
+ buffer.push(entry);
4084
+ if (buffer.length > MAX_ENTRIES) buffer.splice(0, buffer.length - MAX_ENTRIES);
4085
+ if (!w.__ARCHIE_VE_TRACE_DUMP__) {
4086
+ w.__ARCHIE_VE_TRACE_DUMP__ = () => JSON.stringify(w.__ARCHIE_VE_TRACE__ ?? []);
4087
+ }
4088
+ if (isVeDebugEnabled()) {
4089
+ console.log(`[archie-ve:${layer}]`, event, resolved ?? "");
4090
+ }
4091
+ }
4092
+
4053
4093
  // src/client/dnd/design-mode/host-bridge.ts
4054
4094
  var DEFAULT_INSPECTOR_THEME = {
4055
4095
  accent: "#8b5cf6",
@@ -4059,8 +4099,80 @@ var DEFAULT_INSPECTOR_THEME = {
4059
4099
  };
4060
4100
  var HOST_COMMAND_EVENT = "archie:editor-host-command";
4061
4101
  var DND_RUNTIME_EVENT = "archie:dnd-runtime-event";
4102
+ function summarizeIdentity(identity2) {
4103
+ if (!identity2) return null;
4104
+ return {
4105
+ nodeId: identity2.nodeId,
4106
+ nodeKey: identity2.nodeKey,
4107
+ ref: identity2.inspectorRef ? `${identity2.inspectorRef.relativePath}:${identity2.inspectorRef.line}:${identity2.inspectorRef.column}` : null,
4108
+ ...identity2.effectiveNodeId && identity2.effectiveNodeId !== identity2.nodeId ? { effectiveNodeId: identity2.effectiveNodeId } : {}
4109
+ };
4110
+ }
4111
+ function summarizeRuntimeEvent(detail) {
4112
+ switch (detail.type) {
4113
+ case "element-moved":
4114
+ return {
4115
+ operationId: detail.operationId,
4116
+ commandType: detail.commandType,
4117
+ selected: summarizeIdentity(detail.selected),
4118
+ anchor: summarizeIdentity(detail.anchor),
4119
+ container: summarizeIdentity(detail.container),
4120
+ beforeSibling: summarizeIdentity(detail.beforeSibling),
4121
+ sourceContainer: summarizeIdentity(detail.sourceContainer),
4122
+ diagnostics: detail.diagnostics ?? null
4123
+ };
4124
+ case "element-resized":
4125
+ return {
4126
+ operationId: detail.operationId,
4127
+ selected: summarizeIdentity(detail.selected),
4128
+ anchor: summarizeIdentity(detail.anchor),
4129
+ resize: {
4130
+ mode: detail.resize.mode,
4131
+ selectedNodeKey: detail.resize.selectedNodeKey,
4132
+ targetNodeKey: detail.resize.targetNodeKey,
4133
+ targetNodeId: detail.resize.targetNodeId,
4134
+ width: detail.resize.width,
4135
+ height: detail.resize.height
4136
+ }
4137
+ };
4138
+ case "element-inserted":
4139
+ return {
4140
+ operationId: detail.operationId,
4141
+ nodeId: detail.nodeId,
4142
+ nodeKey: detail.nodeKey,
4143
+ displayName: detail.displayName,
4144
+ container: summarizeIdentity(detail.container),
4145
+ index: detail.index,
4146
+ beforeSibling: summarizeIdentity(detail.beforeSibling),
4147
+ hasTsxCode: !!detail.tsxCode,
4148
+ htmlLength: detail.html?.length ?? 0
4149
+ };
4150
+ case "arrange-session-changed":
4151
+ return {
4152
+ mode: detail.session.mode,
4153
+ canUndo: detail.session.canUndo,
4154
+ changeCount: detail.session.changes.length,
4155
+ changes: detail.session.changes.map((c) => ({
4156
+ id: c.id,
4157
+ kind: c.kind,
4158
+ operationId: c.operationId,
4159
+ nodeKey: c.nodeKey,
4160
+ ref: c.inspectorRef ? `${c.inspectorRef.relativePath}:${c.inspectorRef.line}:${c.inspectorRef.column}` : null
4161
+ }))
4162
+ };
4163
+ case "arrange-undo-applied":
4164
+ return { success: detail.success, updatedAt: detail.updatedAt };
4165
+ case "design-mode-changed":
4166
+ return { mode: detail.mode };
4167
+ case "design-mode-error":
4168
+ return { error: detail.error };
4169
+ default:
4170
+ return null;
4171
+ }
4172
+ }
4062
4173
  function dispatchRuntimeEvent(detail) {
4063
4174
  if (typeof window === "undefined") return;
4175
+ veTrace("dnd", `runtime-event:${detail.type}`, () => summarizeRuntimeEvent(detail));
4064
4176
  window.dispatchEvent(new CustomEvent(DND_RUNTIME_EVENT, { detail }));
4065
4177
  }
4066
4178
  function resolveRowBinding(el) {
@@ -6053,6 +6165,8 @@ function resolveResizeTargetElement(selectedEl) {
6053
6165
  );
6054
6166
  if (elementChildren.length !== 1) return selectedEl;
6055
6167
  const child = elementChildren[0];
6168
+ const childId = child.getAttribute(DND_NODE_ID_ATTR);
6169
+ if (childId && !childId.startsWith("dnd-parent:")) return selectedEl;
6056
6170
  const ownText = Array.from(selectedEl.childNodes).some((node) => {
6057
6171
  if (node.nodeType !== Node.TEXT_NODE) return false;
6058
6172
  return (node.textContent ?? "").trim().length > 0;
@@ -8159,8 +8273,23 @@ function useDragLifecycle({
8159
8273
  if (refs.resizeSessionRef.current || Date.now() < refs.resizeDragBlockUntilRef.current) return;
8160
8274
  const activeId = active.id;
8161
8275
  const found = refs.draggableNodeMapRef.current.get(activeId) ?? refs.nodeMapRef.current.get(activeId);
8162
- if (!found) return;
8163
- if (!isEligibleForDrag(found)) return;
8276
+ if (!found) {
8277
+ veTrace("dnd", "drag:start-rejected", { nodeId: activeId, reason: "not-scanned" });
8278
+ return;
8279
+ }
8280
+ if (!isEligibleForDrag(found)) {
8281
+ veTrace("dnd", "drag:start-rejected", {
8282
+ nodeId: activeId,
8283
+ reason: "not-eligible",
8284
+ eligibilitySource: found.eligibilitySource ?? "editor-meta",
8285
+ draggable: found.draggable
8286
+ });
8287
+ return;
8288
+ }
8289
+ veTrace("dnd", "drag:start", {
8290
+ nodeId: activeId,
8291
+ eligibilitySource: found.eligibilitySource ?? "editor-meta"
8292
+ });
8164
8293
  refs.lastIntentRef.current = null;
8165
8294
  refs.visualIntentRef.current = null;
8166
8295
  refs.targetPlaneRef.current = "lane";
@@ -8219,6 +8348,16 @@ function useDragLifecycle({
8219
8348
  const pointer = refs.mouseRef.current;
8220
8349
  const safeZone = refs.safeZoneRef.current;
8221
8350
  const blockedByGuard = isPointerOutsideSafeZone(pointer.x, pointer.y, safeZone) || isPointerInHardPageEdgeZone(pointer.x, pointer.y);
8351
+ veTrace("dnd", "drag:end", () => ({
8352
+ selectedNodeId,
8353
+ anchorNodeId,
8354
+ blockedByGuard,
8355
+ intent: refs.visualIntentRef.current ? {
8356
+ mode: refs.visualIntentRef.current.mode,
8357
+ containerId: refs.visualIntentRef.current.containerId,
8358
+ index: refs.visualIntentRef.current.index
8359
+ } : null
8360
+ }));
8222
8361
  let sourcePos = refs.dragStartPositionRef.current ?? getCurrentCommitPlacement(anchorNodeId, refs.sourceContainerIdRef.current);
8223
8362
  if (!sourcePos && activeEl && activeEl.parentElement) {
8224
8363
  const parentEl = activeEl.parentElement;
@@ -8317,6 +8456,7 @@ function useDragLifecycle({
8317
8456
  syncHistoryAvailability();
8318
8457
  }, [applyCommand, classifyCommandType, clearDragState, getCurrentCommitPlacement, recordMoveChange, resolveNodeElement, selectElement, syncHistoryAvailability]);
8319
8458
  const handleDragCancel = useCallback6(() => {
8459
+ veTrace("dnd", "drag:cancel");
8320
8460
  clearDragState();
8321
8461
  }, [clearDragState]);
8322
8462
  return { activeDrag, handleDragStart, handleDragEnd, handleDragCancel };
@@ -8378,6 +8518,17 @@ function useResizeSession({
8378
8518
  beforeStyles,
8379
8519
  hasMoved: false
8380
8520
  };
8521
+ veTrace("dnd", "resize:start", {
8522
+ dir,
8523
+ mode,
8524
+ selectedNodeId: nodeId,
8525
+ selectedNodeKey,
8526
+ targetNodeId,
8527
+ targetNodeKey,
8528
+ retargeted: resizeTargetEl !== selectedEl,
8529
+ startW: Math.round(rect.width),
8530
+ startH: Math.round(rect.height)
8531
+ });
8381
8532
  pointerTarget?.setPointerCapture?.(e.pointerId);
8382
8533
  }, []);
8383
8534
  const handleResizePointerMove = useCallback7((e) => {
@@ -8440,6 +8591,7 @@ function useResizeSession({
8440
8591
  const afterStyles = readStyleSnapshot(element, ["width", "height", "grid-column", "grid-column-end", "grid-row", "grid-row-end"]);
8441
8592
  const unchanged = mode === "grid-span" ? afterColSpan === startColSpan && afterRowSpan === startRowSpan : afterW === Math.round(startW) && afterH === Math.round(startH);
8442
8593
  if (unchanged) {
8594
+ veTrace("dnd", "resize:noop", { selectedNodeId, targetNodeId });
8443
8595
  syncHistoryAvailability();
8444
8596
  return;
8445
8597
  }
@@ -8501,6 +8653,10 @@ function useResizeSession({
8501
8653
  const session = refs.resizeSessionRef.current;
8502
8654
  if (!session || session.pointerId !== e.pointerId) return;
8503
8655
  if (session.pointerTarget?.hasPointerCapture?.(e.pointerId)) session.pointerTarget.releasePointerCapture(e.pointerId);
8656
+ veTrace("dnd", "resize:cancel", {
8657
+ selectedNodeId: session.selectedNodeId,
8658
+ targetNodeId: session.targetNodeId
8659
+ });
8504
8660
  for (const [prop, value] of Object.entries(session.beforeStyles)) {
8505
8661
  if (value === null) session.element.style.removeProperty(prop);
8506
8662
  else session.element.style.setProperty(prop, value);
@@ -9291,6 +9447,13 @@ function DndProvider({ children }) {
9291
9447
  const handleHostCommand = (event) => {
9292
9448
  const detail = event.detail;
9293
9449
  if (!detail || typeof detail !== "object") return;
9450
+ if (detail.type !== "external-drag-move") {
9451
+ veTrace(
9452
+ "dnd",
9453
+ `host-command:${detail.type}`,
9454
+ () => detail.type === "external-drag-start" ? { displayName: detail.component.displayName, category: detail.component.category } : detail.type === "sync-editor-state" ? { mode: detail.mode ?? null, historyMode: detail.historyMode ?? null } : detail.type === "set-design-mode" ? { enabled: detail.enabled } : void 0
9455
+ );
9456
+ }
9294
9457
  switch (detail.type) {
9295
9458
  case "sync-editor-state":
9296
9459
  if (detail.mode === "design") {
@@ -796,6 +796,29 @@
796
796
  }
797
797
  var ARCHIE_SOURCE_REF_ATTR = "data-archie-source-ref"
798
798
 
799
+ /**
800
+ * True for any element inside a palette-inserted, not-yet-saved subtree.
801
+ * The host stamps `data-archie-inserted` on every element of the palette
802
+ * HTML; the `insert:` nodeId covers roots dropped before the stamping
803
+ * existed. These nodes have NO source of their own, so every ancestor-
804
+ * walking fallback (nearest meta, legacy component root) would attribute
805
+ * them to a DIFFERENT node's source — grouping the whole inserted
806
+ * subtree (and its host component) into one shared-edit signature, which
807
+ * is how painting one inserted div flooded the AppShell main and every
808
+ * sibling insert.
809
+ */
810
+ function isInsertedSubtreeElement(element) {
811
+ if (!element || typeof element.closest !== "function") return false
812
+ try {
813
+ return !!(
814
+ element.closest("[data-archie-inserted]") ||
815
+ element.closest('[data-dnd-node-id^="insert:"]')
816
+ )
817
+ } catch (e) {
818
+ return false
819
+ }
820
+ }
821
+
799
822
  function normalizeSharedSignaturePart(value) {
800
823
  if (value == null) return ""
801
824
  return String(value).trim()
@@ -815,6 +838,9 @@
815
838
 
816
839
  function getLegacySharedSignatureFromElement(element) {
817
840
  if (!element || typeof element.closest !== "function") return ""
841
+ // An inserted node's closest component root is its DROP TARGET, not
842
+ // its own source — sharing that signature floods the host component.
843
+ if (isInsertedSubtreeElement(element)) return ""
818
844
  var componentRoot = element.closest("[data-inspector-relative-path]")
819
845
  if (!componentRoot) return ""
820
846
 
@@ -875,6 +901,11 @@
875
901
  function getCoarseSharedSignatureFromElement(element) {
876
902
  if (!element) return ""
877
903
 
904
+ // Nearest-meta is an ANCESTOR walk; for an inserted node it lands on
905
+ // the drop container's meta (e.g. AppShell main), which is not this
906
+ // node's identity. No signature ⇒ no shared grouping.
907
+ if (isInsertedSubtreeElement(element)) return ""
908
+
878
909
  var nearestMeta = findNearestEditorMeta(element)
879
910
  var nearestSignature =
880
911
  nearestMeta && nearestMeta.meta
@@ -1177,6 +1208,13 @@
1177
1208
  return buildInspectorInfoFromExactSignature(exactSignature, element)
1178
1209
  }
1179
1210
 
1211
+ // Everything below walks ANCESTORS. A palette-inserted node has no
1212
+ // source until its insert is saved; reporting the drop container's
1213
+ // source as its own is what routed edits to the AppShell main.
1214
+ if (isInsertedSubtreeElement(element)) {
1215
+ return null
1216
+ }
1217
+
1180
1218
  var metaResult = findNearestEditorMeta(element)
1181
1219
  if (metaResult && metaResult.meta) {
1182
1220
  return buildInspectorInfoFromMeta(metaResult.meta)
@@ -1214,6 +1252,20 @@
1214
1252
  var inspectTarget = resolveExactInspectTarget(referenceElement)
1215
1253
  if (!inspectTarget) return []
1216
1254
 
1255
+ // A palette-inserted node is a one-off DOM instance: it shares source
1256
+ // with nothing, so an edit on it must never fan out. (Choke point for
1257
+ // every APPLY_* handler's shared spread — the signature guards above
1258
+ // make this redundant for new indexes, but an already-built index may
1259
+ // still hold a stale group.)
1260
+ if (isInsertedSubtreeElement(inspectTarget)) {
1261
+ veTrace("shared-targets", {
1262
+ via: "inserted-subtree",
1263
+ count: 1,
1264
+ nodeId: inspectTarget.getAttribute("data-dnd-node-id") || null,
1265
+ })
1266
+ return [inspectTarget]
1267
+ }
1268
+
1217
1269
  var signature = resolveSharedGroupSignature(inspectTarget)
1218
1270
  if (signature) {
1219
1271
  rebuildSharedTargetIndex()
@@ -1221,14 +1273,32 @@
1221
1273
  inspectTarget,
1222
1274
  sharedTargetIndex.sharedBySignature.get(signature) || []
1223
1275
  )
1224
- if (sharedTargets.length > 0) return sharedTargets
1276
+ if (sharedTargets.length > 0) {
1277
+ veTrace("shared-targets", {
1278
+ via: "signature",
1279
+ signature: String(signature).slice(0, 160),
1280
+ count: sharedTargets.length,
1281
+ nodeId: inspectTarget.getAttribute("data-dnd-node-id") || null,
1282
+ })
1283
+ return sharedTargets
1284
+ }
1225
1285
  }
1226
1286
 
1227
1287
  var legacyTargets = resolveLegacySharedTargets(inspectTarget)
1228
1288
  if (legacyTargets.length > 0) {
1289
+ veTrace("shared-targets", {
1290
+ via: "legacy",
1291
+ count: legacyTargets.length,
1292
+ nodeId: inspectTarget.getAttribute("data-dnd-node-id") || null,
1293
+ })
1229
1294
  return legacyTargets
1230
1295
  }
1231
1296
 
1297
+ veTrace("shared-targets", {
1298
+ via: "self-only",
1299
+ count: 1,
1300
+ nodeId: inspectTarget.getAttribute("data-dnd-node-id") || null,
1301
+ })
1232
1302
  return [inspectTarget]
1233
1303
  }
1234
1304
 
@@ -1332,10 +1402,24 @@
1332
1402
 
1333
1403
  syncBridgeStateFromWindow()
1334
1404
  if (!bridgeState.targetOrigin || bridgeState.targetOrigin === "*") {
1405
+ if (msg && msg.type && msg.type !== "ELEMENT_POSITION_UPDATE") {
1406
+ veTrace("out:" + msg.type + ":queued", {
1407
+ requestId: (msg && msg.requestId) || null,
1408
+ })
1409
+ }
1335
1410
  bridgeState.pendingParentMessages.push(msg)
1336
1411
  return
1337
1412
  }
1338
1413
 
1414
+ if (msg && msg.type && msg.type !== "ELEMENT_POSITION_UPDATE") {
1415
+ veTrace("out:" + msg.type, {
1416
+ requestId: (msg && msg.requestId) || null,
1417
+ operationId:
1418
+ (msg && msg.operationId) ||
1419
+ (msg && msg.payload && msg.payload.operationId) ||
1420
+ null,
1421
+ })
1422
+ }
1339
1423
  window.parent.postMessage(msg, bridgeState.targetOrigin)
1340
1424
  }
1341
1425
 
@@ -1408,6 +1492,41 @@
1408
1492
  }
1409
1493
  }
1410
1494
 
1495
+ /**
1496
+ * Always-on trace ring buffer, shared shape with the design-mode engine
1497
+ * (`debug-trace.ts`): reproduce a broken gesture, then read
1498
+ * `window.__ARCHIE_VE_TRACE__` / `window.__ARCHIE_VE_TRACE_DUMP__()` in
1499
+ * THIS frame's console. Console echo only with `_inspectorDebug` /
1500
+ * `__ARCHIE_VE_DEBUG__`. Payloads must be small summaries — ids, types,
1501
+ * refs — never elements or full HTML.
1502
+ */
1503
+ var VE_TRACE_MAX = 800
1504
+ function veTrace(event, data) {
1505
+ try {
1506
+ var buffer = window.__ARCHIE_VE_TRACE__
1507
+ if (!buffer) {
1508
+ buffer = window.__ARCHIE_VE_TRACE__ = []
1509
+ }
1510
+ var entry = { t: Date.now(), layer: "inspector", event: event }
1511
+ if (typeof data !== "undefined") entry.data = data
1512
+ buffer.push(entry)
1513
+ if (buffer.length > VE_TRACE_MAX) {
1514
+ buffer.splice(0, buffer.length - VE_TRACE_MAX)
1515
+ }
1516
+ if (!window.__ARCHIE_VE_TRACE_DUMP__) {
1517
+ window.__ARCHIE_VE_TRACE_DUMP__ = function () {
1518
+ return JSON.stringify(window.__ARCHIE_VE_TRACE__ || [])
1519
+ }
1520
+ }
1521
+ if (window._inspectorDebug || window.__ARCHIE_VE_DEBUG__ === true) {
1522
+ // eslint-disable-next-line no-console
1523
+ console.log("[archie-ve:inspector]", event, data || "")
1524
+ }
1525
+ } catch (e) {
1526
+ // Tracing must never break the inspector.
1527
+ }
1528
+ }
1529
+
1411
1530
  postMessageToParent({
1412
1531
  type: "INSPECTOR_SCRIPT_LOADED",
1413
1532
  timestamp: Date.now(),
@@ -2611,6 +2730,31 @@
2611
2730
  } catch (e) {}
2612
2731
  }
2613
2732
 
2733
+ veTrace("resolve-mutation-element", {
2734
+ selector: hasSelector ? selector : null,
2735
+ inspectorSource:
2736
+ inspectorSource && typeof inspectorSource === "object"
2737
+ ? (inspectorSource.file || "") +
2738
+ ":" +
2739
+ (inspectorSource.line || "") +
2740
+ ":" +
2741
+ (inspectorSource.column || "")
2742
+ : null,
2743
+ matchedSelector: !!selectorElement,
2744
+ resolvedVia: !element
2745
+ ? "none"
2746
+ : element === selectorElement
2747
+ ? "selector"
2748
+ : "inspector-source-or-fallback",
2749
+ resolvedNodeId: element
2750
+ ? element.getAttribute("data-dnd-node-id") || null
2751
+ : null,
2752
+ resolvedSourceRef: element
2753
+ ? element.getAttribute("data-archie-source-ref") || null
2754
+ : null,
2755
+ resolvedTag: element ? String(element.tagName || "").toLowerCase() : null,
2756
+ })
2757
+
2614
2758
  return element
2615
2759
  }
2616
2760
 
@@ -3160,6 +3304,10 @@
3160
3304
  return
3161
3305
  }
3162
3306
 
3307
+ veTrace("runtime-event:" + detail.type, {
3308
+ operationId: detail.operationId || null,
3309
+ })
3310
+
3163
3311
  if (detail.type === "design-mode-changed") {
3164
3312
  // In unified inspect the arrange overlay flips its internal
3165
3313
  // design-mode store as a side effect ("design" on mount, "off" on
@@ -3169,6 +3317,9 @@
3169
3317
  // only needs runtime-originated mode changes in the legacy
3170
3318
  // design-only flow.
3171
3319
  if (hostCommandedEditorMode === "inspect") {
3320
+ veTrace("runtime-event:design-mode-changed:suppressed", {
3321
+ hostCommandedEditorMode: hostCommandedEditorMode,
3322
+ })
3172
3323
  return
3173
3324
  }
3174
3325
  postMessageToParent({
@@ -3257,6 +3408,12 @@
3257
3408
  event.data.type,
3258
3409
  event.data
3259
3410
  )
3411
+ if (event.data.type !== "EXTERNAL_DRAG_MOVE") {
3412
+ veTrace("in:" + event.data.type, {
3413
+ requestId: event.data.requestId || null,
3414
+ selector: event.data.selector || null,
3415
+ })
3416
+ }
3260
3417
  }
3261
3418
 
3262
3419
  if (event.data && event.data.type === "SET_EDITOR_MODE") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archie/devtools",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "description": "DevTools for Archie generated applications - Route synchronization and editor communication",
5
5
  "repository": {
6
6
  "type": "git",