@archie/devtools 0.0.18 → 0.0.19

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.
@@ -4279,6 +4279,32 @@ function getEditorMeta(el) {
4279
4279
  }
4280
4280
  return writeFiberAwareCache(metaCache, el, selection, null);
4281
4281
  }
4282
+ function getEditorMetaOwnerFiber(el) {
4283
+ const selection = getFiberSelectionFromElement(el);
4284
+ let fiber = selection.fiber;
4285
+ while (fiber) {
4286
+ if (fiber.memoizedProps?.__editorMeta) return fiber;
4287
+ fiber = fiber.return;
4288
+ }
4289
+ return null;
4290
+ }
4291
+ function getSingleHostElement(owner) {
4292
+ const hosts = [];
4293
+ const stack = owner?.child ? [owner.child] : [];
4294
+ while (stack.length > 0) {
4295
+ const fiber = stack.pop();
4296
+ if (!fiber) continue;
4297
+ if (fiber.tag === 4) return null;
4298
+ if (typeof fiber.type === "string" && fiber.stateNode instanceof HTMLElement) {
4299
+ hosts.push(fiber.stateNode);
4300
+ if (hosts.length > 1) return null;
4301
+ } else if (fiber.child) {
4302
+ stack.push(fiber.child);
4303
+ }
4304
+ if (fiber.sibling) stack.push(fiber.sibling);
4305
+ }
4306
+ return hosts.length === 1 ? hosts[0] : null;
4307
+ }
4282
4308
  function findMetaOwnerElement(el) {
4283
4309
  let current = el;
4284
4310
  while (current) {
@@ -4902,8 +4928,11 @@ var LARGE_NODE_NEST_BLOCK_MIN_WIDTH = 520;
4902
4928
  var LARGE_NODE_NEST_BLOCK_MIN_HEIGHT = 260;
4903
4929
  var LARGE_NODE_NEST_BLOCK_MIN_AREA = 18e4;
4904
4930
  function isEligibleForDrag(sc) {
4931
+ if (sc.draggable === false) return false;
4905
4932
  const source = sc.eligibilitySource ?? "editor-meta";
4906
- return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant";
4933
+ return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant" || // RFC E2.4 P1: single host root of a kit-component usage (MetricCard,
4934
+ // Section, …) carrying the usage's projected meta.
4935
+ source === "projected-usage";
4907
4936
  }
4908
4937
  function isPointerInEdgeZone(px, py, guard) {
4909
4938
  return px <= guard || py <= guard || px >= window.innerWidth - guard || py >= window.innerHeight - guard;
@@ -5025,6 +5054,13 @@ function isInspectorEligible(el) {
5025
5054
  if (el.hasAttribute("data-dnd-force-allow")) return "force-allow";
5026
5055
  return null;
5027
5056
  }
5057
+ function projectUsageMeta(el) {
5058
+ if (getDirectEditorMeta(el)) return null;
5059
+ const owner = getEditorMetaOwnerFiber(el);
5060
+ if (!owner) return null;
5061
+ if (getSingleHostElement(owner) !== el) return null;
5062
+ return owner.memoizedProps?.__editorMeta ?? null;
5063
+ }
5028
5064
  function isRuntimeVisualInternal(el) {
5029
5065
  if (shouldIgnoreAsVirtualRuntime(el)) return true;
5030
5066
  const tag = el.tagName.toLowerCase();
@@ -5056,6 +5092,8 @@ function resolveStableNodeId(el, used) {
5056
5092
  if (persisted && !used.has(persisted)) return persisted;
5057
5093
  const metaId = getEditorMetaNodeId(el);
5058
5094
  if (metaId) return ensureUniqueNodeId(metaId, used);
5095
+ const projected = projectUsageMeta(el);
5096
+ if (projected) return ensureUniqueNodeId(projected.nodeId, used);
5059
5097
  return ensureUniqueNodeId(getRuntimeNodeId(el), used);
5060
5098
  }
5061
5099
  function getUniqueSelector(el) {
@@ -5147,9 +5185,31 @@ function scanElements(root, depth = 0, usedNodeIds = /* @__PURE__ */ new Set(),
5147
5185
  continue;
5148
5186
  }
5149
5187
  const eligibilitySource = isInspectorEligible(el);
5150
- const inferredEligibility = eligibilitySource ?? inferEligibilityFromSortableParent(el);
5188
+ const inferredEligibility = eligibilitySource ?? inferEligibilityFromSortableParent(el) ?? (projectUsageMeta(el) ? "projected-usage" : null);
5151
5189
  if (inferredEligibility === null) {
5152
- results.push(...scanElements(el, depth + 1, usedNodeIds, seenResolvedHosts));
5190
+ const childResults = scanElements(el, depth + 1, usedNodeIds, seenResolvedHosts);
5191
+ results.push(...childResults);
5192
+ if (isFlexOrGridParent(el) && !seenResolvedHosts.has(el) && childResults.some((r) => r.draggable && r.element.parentElement === el)) {
5193
+ const nodeId2 = resolveStableNodeId(el, usedNodeIds);
5194
+ seenResolvedHosts.add(el);
5195
+ usedNodeIds.add(nodeId2);
5196
+ el.setAttribute(DND_NODE_ID_ATTR, nodeId2);
5197
+ const selector = getUniqueSelector(el);
5198
+ results.push({
5199
+ nodeId: nodeId2,
5200
+ element: el,
5201
+ selector,
5202
+ sourceMetaNodeId: null,
5203
+ resolvedHostNodeId: nodeId2,
5204
+ resolvedHostSelector: selector,
5205
+ resolutionKind: "direct-host",
5206
+ label: getLabel(el),
5207
+ rect: el.getBoundingClientRect(),
5208
+ containerStrategy: resolveContainerStrategy(el),
5209
+ eligibilitySource: "container-of-eligible",
5210
+ draggable: false
5211
+ });
5212
+ }
5153
5213
  continue;
5154
5214
  }
5155
5215
  const dragSurface = resolveDragSurface(el);
@@ -5172,10 +5232,12 @@ function scanElements(root, depth = 0, usedNodeIds = /* @__PURE__ */ new Set(),
5172
5232
  const surfaceMeta = hostEl instanceof HTMLElement ? getDirectEditorMeta(hostEl) ?? void 0 : void 0;
5173
5233
  const ownerMeta = dragSurface.metaOwner && dragSurface.metaOwner instanceof HTMLElement ? getEditorMeta(dragSurface.metaOwner) : null;
5174
5234
  const resolvedSelector = getUniqueSelector(hostEl);
5235
+ const draggable = inferredEligibility === "force-allow" || !nodeId.startsWith("runtime:");
5175
5236
  results.push({
5176
5237
  nodeId,
5177
5238
  element: hostEl,
5178
5239
  selector: resolvedSelector,
5240
+ draggable,
5179
5241
  sourceMetaNodeId: ownerMeta?.nodeId ?? surfaceMeta?.nodeId ?? null,
5180
5242
  resolvedHostNodeId: nodeId,
5181
5243
  resolvedHostSelector: resolvedSelector,
@@ -5222,6 +5284,7 @@ function useElementScanner(enabled) {
5222
5284
  nodeId,
5223
5285
  element: el,
5224
5286
  selector,
5287
+ draggable: !nodeId.startsWith("runtime:"),
5225
5288
  sourceMetaNodeId: ownerMeta?.nodeId ?? surfaceMeta?.nodeId ?? null,
5226
5289
  resolvedHostNodeId: nodeId,
5227
5290
  resolvedHostSelector: selector,
@@ -8661,7 +8724,9 @@ function DesignModeOverlay() {
8661
8724
  const draggableElements = (0, import_react17.useMemo)(() => {
8662
8725
  if (elements.length === 0) return [];
8663
8726
  const projection = buildProjection(elements);
8664
- return collectDraggableAnchors(elements, projection, nodeMap);
8727
+ return collectDraggableAnchors(elements, projection, nodeMap).filter(
8728
+ (el) => el.draggable !== false
8729
+ );
8665
8730
  }, [elements, nodeMap]);
8666
8731
  const refs = useOverlayRefs(undoRequestId, redoRequestId);
8667
8732
  refs.elementsRef.current = elements;
@@ -4244,6 +4244,32 @@ function getEditorMeta(el) {
4244
4244
  }
4245
4245
  return writeFiberAwareCache(metaCache, el, selection, null);
4246
4246
  }
4247
+ function getEditorMetaOwnerFiber(el) {
4248
+ const selection = getFiberSelectionFromElement(el);
4249
+ let fiber = selection.fiber;
4250
+ while (fiber) {
4251
+ if (fiber.memoizedProps?.__editorMeta) return fiber;
4252
+ fiber = fiber.return;
4253
+ }
4254
+ return null;
4255
+ }
4256
+ function getSingleHostElement(owner) {
4257
+ const hosts = [];
4258
+ const stack = owner?.child ? [owner.child] : [];
4259
+ while (stack.length > 0) {
4260
+ const fiber = stack.pop();
4261
+ if (!fiber) continue;
4262
+ if (fiber.tag === 4) return null;
4263
+ if (typeof fiber.type === "string" && fiber.stateNode instanceof HTMLElement) {
4264
+ hosts.push(fiber.stateNode);
4265
+ if (hosts.length > 1) return null;
4266
+ } else if (fiber.child) {
4267
+ stack.push(fiber.child);
4268
+ }
4269
+ if (fiber.sibling) stack.push(fiber.sibling);
4270
+ }
4271
+ return hosts.length === 1 ? hosts[0] : null;
4272
+ }
4247
4273
  function findMetaOwnerElement(el) {
4248
4274
  let current = el;
4249
4275
  while (current) {
@@ -4867,8 +4893,11 @@ var LARGE_NODE_NEST_BLOCK_MIN_WIDTH = 520;
4867
4893
  var LARGE_NODE_NEST_BLOCK_MIN_HEIGHT = 260;
4868
4894
  var LARGE_NODE_NEST_BLOCK_MIN_AREA = 18e4;
4869
4895
  function isEligibleForDrag(sc) {
4896
+ if (sc.draggable === false) return false;
4870
4897
  const source = sc.eligibilitySource ?? "editor-meta";
4871
- return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant";
4898
+ return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant" || // RFC E2.4 P1: single host root of a kit-component usage (MetricCard,
4899
+ // Section, …) carrying the usage's projected meta.
4900
+ source === "projected-usage";
4872
4901
  }
4873
4902
  function isPointerInEdgeZone(px, py, guard) {
4874
4903
  return px <= guard || py <= guard || px >= window.innerWidth - guard || py >= window.innerHeight - guard;
@@ -4990,6 +5019,13 @@ function isInspectorEligible(el) {
4990
5019
  if (el.hasAttribute("data-dnd-force-allow")) return "force-allow";
4991
5020
  return null;
4992
5021
  }
5022
+ function projectUsageMeta(el) {
5023
+ if (getDirectEditorMeta(el)) return null;
5024
+ const owner = getEditorMetaOwnerFiber(el);
5025
+ if (!owner) return null;
5026
+ if (getSingleHostElement(owner) !== el) return null;
5027
+ return owner.memoizedProps?.__editorMeta ?? null;
5028
+ }
4993
5029
  function isRuntimeVisualInternal(el) {
4994
5030
  if (shouldIgnoreAsVirtualRuntime(el)) return true;
4995
5031
  const tag = el.tagName.toLowerCase();
@@ -5021,6 +5057,8 @@ function resolveStableNodeId(el, used) {
5021
5057
  if (persisted && !used.has(persisted)) return persisted;
5022
5058
  const metaId = getEditorMetaNodeId(el);
5023
5059
  if (metaId) return ensureUniqueNodeId(metaId, used);
5060
+ const projected = projectUsageMeta(el);
5061
+ if (projected) return ensureUniqueNodeId(projected.nodeId, used);
5024
5062
  return ensureUniqueNodeId(getRuntimeNodeId(el), used);
5025
5063
  }
5026
5064
  function getUniqueSelector(el) {
@@ -5112,9 +5150,31 @@ function scanElements(root, depth = 0, usedNodeIds = /* @__PURE__ */ new Set(),
5112
5150
  continue;
5113
5151
  }
5114
5152
  const eligibilitySource = isInspectorEligible(el);
5115
- const inferredEligibility = eligibilitySource ?? inferEligibilityFromSortableParent(el);
5153
+ const inferredEligibility = eligibilitySource ?? inferEligibilityFromSortableParent(el) ?? (projectUsageMeta(el) ? "projected-usage" : null);
5116
5154
  if (inferredEligibility === null) {
5117
- results.push(...scanElements(el, depth + 1, usedNodeIds, seenResolvedHosts));
5155
+ const childResults = scanElements(el, depth + 1, usedNodeIds, seenResolvedHosts);
5156
+ results.push(...childResults);
5157
+ if (isFlexOrGridParent(el) && !seenResolvedHosts.has(el) && childResults.some((r) => r.draggable && r.element.parentElement === el)) {
5158
+ const nodeId2 = resolveStableNodeId(el, usedNodeIds);
5159
+ seenResolvedHosts.add(el);
5160
+ usedNodeIds.add(nodeId2);
5161
+ el.setAttribute(DND_NODE_ID_ATTR, nodeId2);
5162
+ const selector = getUniqueSelector(el);
5163
+ results.push({
5164
+ nodeId: nodeId2,
5165
+ element: el,
5166
+ selector,
5167
+ sourceMetaNodeId: null,
5168
+ resolvedHostNodeId: nodeId2,
5169
+ resolvedHostSelector: selector,
5170
+ resolutionKind: "direct-host",
5171
+ label: getLabel(el),
5172
+ rect: el.getBoundingClientRect(),
5173
+ containerStrategy: resolveContainerStrategy(el),
5174
+ eligibilitySource: "container-of-eligible",
5175
+ draggable: false
5176
+ });
5177
+ }
5118
5178
  continue;
5119
5179
  }
5120
5180
  const dragSurface = resolveDragSurface(el);
@@ -5137,10 +5197,12 @@ function scanElements(root, depth = 0, usedNodeIds = /* @__PURE__ */ new Set(),
5137
5197
  const surfaceMeta = hostEl instanceof HTMLElement ? getDirectEditorMeta(hostEl) ?? void 0 : void 0;
5138
5198
  const ownerMeta = dragSurface.metaOwner && dragSurface.metaOwner instanceof HTMLElement ? getEditorMeta(dragSurface.metaOwner) : null;
5139
5199
  const resolvedSelector = getUniqueSelector(hostEl);
5200
+ const draggable = inferredEligibility === "force-allow" || !nodeId.startsWith("runtime:");
5140
5201
  results.push({
5141
5202
  nodeId,
5142
5203
  element: hostEl,
5143
5204
  selector: resolvedSelector,
5205
+ draggable,
5144
5206
  sourceMetaNodeId: ownerMeta?.nodeId ?? surfaceMeta?.nodeId ?? null,
5145
5207
  resolvedHostNodeId: nodeId,
5146
5208
  resolvedHostSelector: resolvedSelector,
@@ -5187,6 +5249,7 @@ function useElementScanner(enabled) {
5187
5249
  nodeId,
5188
5250
  element: el,
5189
5251
  selector,
5252
+ draggable: !nodeId.startsWith("runtime:"),
5190
5253
  sourceMetaNodeId: ownerMeta?.nodeId ?? surfaceMeta?.nodeId ?? null,
5191
5254
  resolvedHostNodeId: nodeId,
5192
5255
  resolvedHostSelector: selector,
@@ -8626,7 +8689,9 @@ function DesignModeOverlay() {
8626
8689
  const draggableElements = useMemo6(() => {
8627
8690
  if (elements.length === 0) return [];
8628
8691
  const projection = buildProjection(elements);
8629
- return collectDraggableAnchors(elements, projection, nodeMap);
8692
+ return collectDraggableAnchors(elements, projection, nodeMap).filter(
8693
+ (el) => el.draggable !== false
8694
+ );
8630
8695
  }, [elements, nodeMap]);
8631
8696
  const refs = useOverlayRefs(undoRequestId, redoRequestId);
8632
8697
  refs.elementsRef.current = elements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archie/devtools",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "DevTools for Archie generated applications - Route synchronization and editor communication",
5
5
  "repository": {
6
6
  "type": "git",
@@ -73,4 +73,4 @@
73
73
  "react-dom": ">=18.0.0",
74
74
  "react-router-dom": ">=6.4.0"
75
75
  }
76
- }
76
+ }