@archie/devtools 0.0.48 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/{chunk-P5XMHBFS.mjs → chunk-THKKWDMJ.mjs} +98 -2
- package/dist/client/client.js +159 -2
- package/dist/client/client.mjs +159 -2
- package/dist/collection-binding.js +1 -0
- package/dist/collection-binding.mjs +1 -1
- package/dist/index.d.mts +92 -1
- package/dist/index.d.ts +92 -1
- package/dist/index.js +98 -2
- package/dist/index.mjs +1 -1
- package/dist/inspector.standalone.js +133 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -73,6 +73,42 @@ Changes to `babel-plugin-editor-meta.ts`'s `__editorMeta` prop shape and
|
|
|
73
73
|
`inspector.standalone.js`'s meta-read paths have a load-bearing publish
|
|
74
74
|
order — see [`docs/deploy-order.md`](docs/deploy-order.md).
|
|
75
75
|
|
|
76
|
+
## Identidad `data-vid`, NodeMeta, protocolo 1.x
|
|
77
|
+
|
|
78
|
+
`babelPluginEditorMeta` ahora LEE `data-vid` (persistido en el source por el
|
|
79
|
+
stamper de Genesis, `/^[a-z0-9]{6,8}$/`) en vez de derivar la identidad de
|
|
80
|
+
`file:line:col:componentName`, que se invalida en cada escritura del source.
|
|
81
|
+
Cuando el elemento tiene `data-vid`, `__editorMeta.nodeId === __editorMeta.vid`
|
|
82
|
+
y el plugin también emite los campos de `NodeMeta`
|
|
83
|
+
(`@8base-archie/editor-protocol`): `dynamicType`, `isKitOrigin`, `isChrome`,
|
|
84
|
+
`containerKind` y, cuando aplica, `lockReason`. `parentNodeId` usa el `vid`
|
|
85
|
+
del padre cuando existe.
|
|
86
|
+
|
|
87
|
+
Sin `data-vid`, el plugin cae al direccionamiento legado SOLO cuando la
|
|
88
|
+
opción `allowLegacyIds` es `true` (default en esta versión — transicional,
|
|
89
|
+
se eliminará más adelante); con `allowLegacyIds: false` el elemento no se
|
|
90
|
+
instrumenta.
|
|
91
|
+
|
|
92
|
+
En runtime, `node-key.ts` resuelve la identidad con la prioridad
|
|
93
|
+
`meta.vid` → `data-vid` del DOM → (legado) `meta.nodeId` → `runtime:N`, y
|
|
94
|
+
`fiber-bridge.ts` expone `getNodeMeta(el)`, que valida el `NodeMeta`
|
|
95
|
+
ensamblado contra `NodeMetaSchema` antes de devolverlo. `structural-policy.ts`
|
|
96
|
+
añade `isNonDraggableNodeMeta`, `isNonDroppableNodeMeta` y
|
|
97
|
+
`computeDroppableSet` sobre esos mismos campos.
|
|
98
|
+
|
|
99
|
+
El handshake (`INSPECTOR_SCRIPT_LOADED`/`CAPABILITIES_RESULT`) añade
|
|
100
|
+
`editorProtocolVersion` (el `PROTOCOL_VERSION` semver del paquete de
|
|
101
|
+
contrato — un campo NUEVO, nunca superpuesto al `protocolVersion` numérico
|
|
102
|
+
existente que `archie-app` ya compara estrictamente) y las capabilities
|
|
103
|
+
`vidIdentity`, `nodeMeta`, `refusals`. `ELEMENT_SELECTED` añade `vid` y
|
|
104
|
+
`nodeMeta`. El vocabulario `REFUSED{code, cause, vid}` está disponible
|
|
105
|
+
(`refuseNode` en `inspector.standalone.js`) para cuando un host rechaza un
|
|
106
|
+
gesto de arrastre/drop fuera de política.
|
|
107
|
+
|
|
108
|
+
Consume `@8base-archie/editor-protocol` como fuente única del contrato
|
|
109
|
+
(`Vid`, `NodeMeta`, `LockReason`, los schemas Zod) — ver
|
|
110
|
+
`src/types/editor-meta.ts`, que re-exporta esos tipos en vez de duplicarlos.
|
|
111
|
+
|
|
76
112
|
## Local linking
|
|
77
113
|
|
|
78
114
|
```bash
|
|
@@ -6,6 +6,7 @@ var getDirname = () => path.dirname(getFilename());
|
|
|
6
6
|
var __dirname = /* @__PURE__ */ getDirname();
|
|
7
7
|
|
|
8
8
|
// src/babel-plugin-editor-meta.ts
|
|
9
|
+
import { VID_ATTR, VID_PATTERN } from "@8base-archie/editor-protocol";
|
|
9
10
|
import * as nodePath from "path";
|
|
10
11
|
function meaningfulChildren(t, children) {
|
|
11
12
|
return children.filter((child) => {
|
|
@@ -61,7 +62,8 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
|
|
|
61
62
|
instrumentImported = true,
|
|
62
63
|
includeHostSourceRef = false,
|
|
63
64
|
origin = "screen",
|
|
64
|
-
templateOrigin = false
|
|
65
|
+
templateOrigin = false,
|
|
66
|
+
allowLegacyIds = true
|
|
65
67
|
} = opts;
|
|
66
68
|
function getJSXTagName(el) {
|
|
67
69
|
const { name } = el;
|
|
@@ -109,6 +111,77 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
|
|
|
109
111
|
function computeNodeId(file, line, col, componentName) {
|
|
110
112
|
return `${file}:${line}:${col}:${componentName}`;
|
|
111
113
|
}
|
|
114
|
+
function readVidAttr(attrs) {
|
|
115
|
+
for (const attr of attrs) {
|
|
116
|
+
if (!t.isJSXAttribute(attr)) continue;
|
|
117
|
+
if (!t.isJSXIdentifier(attr.name, { name: VID_ATTR })) continue;
|
|
118
|
+
const { value } = attr;
|
|
119
|
+
let raw = null;
|
|
120
|
+
if (t.isStringLiteral(value)) {
|
|
121
|
+
raw = value.value;
|
|
122
|
+
} else if (t.isJSXExpressionContainer(value) && t.isStringLiteral(value.expression)) {
|
|
123
|
+
raw = value.expression.value;
|
|
124
|
+
}
|
|
125
|
+
if (raw !== null && VID_PATTERN.test(raw)) return raw;
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function computeDynamicType(path2) {
|
|
131
|
+
let current = path2.parentPath;
|
|
132
|
+
while (current) {
|
|
133
|
+
if (current.isJSXExpressionContainer()) {
|
|
134
|
+
const expr = current.node.expression;
|
|
135
|
+
if (t.isConditionalExpression(expr) || t.isLogicalExpression(expr)) {
|
|
136
|
+
return "CONDITIONAL";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (current.isArrowFunctionExpression() || current.isFunctionExpression()) {
|
|
140
|
+
const call = current.parentPath;
|
|
141
|
+
if (call?.isCallExpression()) {
|
|
142
|
+
const callee = call.node.callee;
|
|
143
|
+
if (t.isMemberExpression(callee) && !callee.computed && t.isIdentifier(callee.property) && /^(map|flatMap|forEach)$/.test(callee.property.name)) {
|
|
144
|
+
return "ARRAY";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
if (current.isFunctionDeclaration()) break;
|
|
150
|
+
current = current.parentPath;
|
|
151
|
+
}
|
|
152
|
+
return "STATIC";
|
|
153
|
+
}
|
|
154
|
+
const SHELL_FILE_RE = /(^|\/)shell\.jsx$/;
|
|
155
|
+
const SHELL_DIR_RE = /(^|\/)components\/shell\//;
|
|
156
|
+
const CHROME_ANCESTOR_TAGS = /* @__PURE__ */ new Set(["nav", "aside", "header"]);
|
|
157
|
+
function computeIsChrome(file, path2) {
|
|
158
|
+
if (SHELL_FILE_RE.test(file) || SHELL_DIR_RE.test(file)) return true;
|
|
159
|
+
let current = path2.parentPath;
|
|
160
|
+
while (current) {
|
|
161
|
+
if (current.isJSXElement()) {
|
|
162
|
+
const tag = getJSXTagName(current.node.openingElement);
|
|
163
|
+
if (CHROME_ANCESTOR_TAGS.has(tag)) return true;
|
|
164
|
+
}
|
|
165
|
+
current = current.parentPath;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
function computeContainerKind(path2) {
|
|
170
|
+
const elPath = path2.parentPath;
|
|
171
|
+
if (!elPath?.isJSXElement()) return "none";
|
|
172
|
+
const children = meaningfulChildren(t, elPath.node.children);
|
|
173
|
+
if (children.length === 0) return "none";
|
|
174
|
+
const allPlain = children.every((c) => t.isJSXElement(c) || t.isJSXText(c));
|
|
175
|
+
return allPlain ? "plain" : "expression";
|
|
176
|
+
}
|
|
177
|
+
function computeLockReason(isKitOrigin, isChrome, dynamicType, containerKind) {
|
|
178
|
+
if (isKitOrigin) return "KIT_INTERNAL";
|
|
179
|
+
if (isChrome) return "CHROME_STRUCTURAL";
|
|
180
|
+
if (dynamicType === "ARRAY") return "DYNAMIC_ARRAY";
|
|
181
|
+
if (dynamicType === "CONDITIONAL") return "DYNAMIC_CONDITIONAL";
|
|
182
|
+
if (containerKind === "expression") return "EXPRESSION_CONTAINER";
|
|
183
|
+
return void 0;
|
|
184
|
+
}
|
|
112
185
|
function isMovable(path2) {
|
|
113
186
|
const elPath = path2.parentPath;
|
|
114
187
|
if (!elPath) return false;
|
|
@@ -126,6 +199,9 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
|
|
|
126
199
|
while (ancestor) {
|
|
127
200
|
if (ancestor.isJSXElement()) {
|
|
128
201
|
const opening = ancestor.node.openingElement;
|
|
202
|
+
const parentVid = readVidAttr(opening.attributes);
|
|
203
|
+
if (parentVid) return parentVid;
|
|
204
|
+
if (!allowLegacyIds) return null;
|
|
129
205
|
const loc = opening.loc?.start;
|
|
130
206
|
if (loc) {
|
|
131
207
|
const tag = getJSXTagName(opening);
|
|
@@ -752,7 +828,9 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
|
|
|
752
828
|
return;
|
|
753
829
|
}
|
|
754
830
|
}
|
|
755
|
-
const
|
|
831
|
+
const vid = readVidAttr(path2.node.attributes);
|
|
832
|
+
if (!vid && !allowLegacyIds) return;
|
|
833
|
+
const nodeId = vid ?? computeNodeId(file, line, col, componentName);
|
|
756
834
|
const isKitOrigin = origin === "kit" || hasSlotAttr;
|
|
757
835
|
const movable = isKitOrigin ? false : isMovable(path2);
|
|
758
836
|
const parentNodeId = getParentNodeId(path2, file);
|
|
@@ -774,6 +852,24 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
|
|
|
774
852
|
parentNodeId ? t.stringLiteral(parentNodeId) : t.nullLiteral()
|
|
775
853
|
)
|
|
776
854
|
]);
|
|
855
|
+
if (vid) {
|
|
856
|
+
const dynamicType = computeDynamicType(path2);
|
|
857
|
+
const isChrome = computeIsChrome(file, path2);
|
|
858
|
+
const containerKind = computeContainerKind(path2);
|
|
859
|
+
const lockReason = computeLockReason(isKitOrigin, isChrome, dynamicType, containerKind);
|
|
860
|
+
metaObj.properties.push(
|
|
861
|
+
t.objectProperty(t.identifier("vid"), t.stringLiteral(vid)),
|
|
862
|
+
t.objectProperty(t.identifier("isKitOrigin"), t.booleanLiteral(isKitOrigin)),
|
|
863
|
+
t.objectProperty(t.identifier("dynamicType"), t.stringLiteral(dynamicType)),
|
|
864
|
+
t.objectProperty(t.identifier("isChrome"), t.booleanLiteral(isChrome)),
|
|
865
|
+
t.objectProperty(t.identifier("containerKind"), t.stringLiteral(containerKind))
|
|
866
|
+
);
|
|
867
|
+
if (lockReason) {
|
|
868
|
+
metaObj.properties.push(
|
|
869
|
+
t.objectProperty(t.identifier("lockReason"), t.stringLiteral(lockReason))
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
777
873
|
if (isKitOrigin) {
|
|
778
874
|
if (templateOrigin) {
|
|
779
875
|
metaObj.properties.push(
|
package/dist/client/client.js
CHANGED
|
@@ -4116,13 +4116,21 @@ function summarizeRuntimeEvent(detail) {
|
|
|
4116
4116
|
container: summarizeIdentity(detail.container),
|
|
4117
4117
|
beforeSibling: summarizeIdentity(detail.beforeSibling),
|
|
4118
4118
|
sourceContainer: summarizeIdentity(detail.sourceContainer),
|
|
4119
|
-
diagnostics: detail.diagnostics ?? null
|
|
4119
|
+
diagnostics: detail.diagnostics ?? null,
|
|
4120
|
+
targetVid: detail.targetVid ?? null,
|
|
4121
|
+
containerVid: detail.containerVid ?? null,
|
|
4122
|
+
index: detail.index
|
|
4120
4123
|
};
|
|
4124
|
+
case "drag-started":
|
|
4125
|
+
return { targetVid: detail.targetVid, droppableCount: detail.droppable.length };
|
|
4126
|
+
case "drag-refused":
|
|
4127
|
+
return { code: detail.code, cause: detail.cause, vid: detail.vid };
|
|
4121
4128
|
case "element-resized":
|
|
4122
4129
|
return {
|
|
4123
4130
|
operationId: detail.operationId,
|
|
4124
4131
|
selected: summarizeIdentity(detail.selected),
|
|
4125
4132
|
anchor: summarizeIdentity(detail.anchor),
|
|
4133
|
+
targetVid: detail.targetVid ?? null,
|
|
4126
4134
|
resize: {
|
|
4127
4135
|
mode: detail.resize.mode,
|
|
4128
4136
|
selectedNodeKey: detail.resize.selectedNodeKey,
|
|
@@ -4139,6 +4147,8 @@ function summarizeRuntimeEvent(detail) {
|
|
|
4139
4147
|
nodeKey: detail.nodeKey,
|
|
4140
4148
|
displayName: detail.displayName,
|
|
4141
4149
|
container: summarizeIdentity(detail.container),
|
|
4150
|
+
containerVid: detail.containerVid ?? null,
|
|
4151
|
+
insertedVid: detail.insertedVid ?? null,
|
|
4142
4152
|
index: detail.index,
|
|
4143
4153
|
beforeSibling: summarizeIdentity(detail.beforeSibling),
|
|
4144
4154
|
hasTsxCode: !!detail.tsxCode,
|
|
@@ -4220,6 +4230,58 @@ function isValidLaneContainer(containerId, projection, nodeMap) {
|
|
|
4220
4230
|
if (container.children.length === 0) return false;
|
|
4221
4231
|
return !isStructuralContainer(containerId, nodeMap);
|
|
4222
4232
|
}
|
|
4233
|
+
function isNonDroppableNodeMeta(meta) {
|
|
4234
|
+
if (!meta) return false;
|
|
4235
|
+
if (meta.containerKind && meta.containerKind !== "plain") return true;
|
|
4236
|
+
if (meta.isChrome) return true;
|
|
4237
|
+
if (meta.isKitOrigin) return true;
|
|
4238
|
+
return false;
|
|
4239
|
+
}
|
|
4240
|
+
function isNonDraggableNodeMeta(meta) {
|
|
4241
|
+
if (!meta) return false;
|
|
4242
|
+
if (meta.dynamicType && meta.dynamicType !== "STATIC") return true;
|
|
4243
|
+
if (meta.isChrome) return true;
|
|
4244
|
+
if (meta.isKitOrigin) return true;
|
|
4245
|
+
return false;
|
|
4246
|
+
}
|
|
4247
|
+
function collectSubtreeIds(rootId, projection) {
|
|
4248
|
+
const ids2 = /* @__PURE__ */ new Set([rootId]);
|
|
4249
|
+
const stack = [rootId];
|
|
4250
|
+
while (stack.length > 0) {
|
|
4251
|
+
const id = stack.pop();
|
|
4252
|
+
const node = projection.containerIndex.get(id);
|
|
4253
|
+
if (!node) continue;
|
|
4254
|
+
for (const childId of node.children) {
|
|
4255
|
+
if (ids2.has(childId)) continue;
|
|
4256
|
+
ids2.add(childId);
|
|
4257
|
+
stack.push(childId);
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
return ids2;
|
|
4261
|
+
}
|
|
4262
|
+
function computeDroppableSet(sourceId, projection, nodeMap) {
|
|
4263
|
+
const excluded = collectSubtreeIds(sourceId, projection);
|
|
4264
|
+
const droppable = /* @__PURE__ */ new Set();
|
|
4265
|
+
for (const containerId of projection.containerIndex.keys()) {
|
|
4266
|
+
if (excluded.has(containerId)) continue;
|
|
4267
|
+
if (isStructuralContainer(containerId, nodeMap)) continue;
|
|
4268
|
+
if (isNonDroppableNodeMeta(nodeMap.get(containerId)?.editorMeta)) continue;
|
|
4269
|
+
droppable.add(containerId);
|
|
4270
|
+
}
|
|
4271
|
+
return droppable;
|
|
4272
|
+
}
|
|
4273
|
+
function buildBlockedNodeMetaContainerIds(projection, nodeMap) {
|
|
4274
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
4275
|
+
for (const containerId of projection.containerIndex.keys()) {
|
|
4276
|
+
if (isNonDroppableNodeMeta(nodeMap.get(containerId)?.editorMeta)) {
|
|
4277
|
+
blocked.add(containerId);
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
return blocked;
|
|
4281
|
+
}
|
|
4282
|
+
function resolveRefusalCode(meta, fallback) {
|
|
4283
|
+
return meta?.lockReason ?? fallback;
|
|
4284
|
+
}
|
|
4223
4285
|
function buildBlockedStructuralContainerIds(projection, nodeMap, sourceContainerId) {
|
|
4224
4286
|
const blocked = /* @__PURE__ */ new Set();
|
|
4225
4287
|
for (const containerId of projection.containerIndex.keys()) {
|
|
@@ -4229,6 +4291,9 @@ function buildBlockedStructuralContainerIds(projection, nodeMap, sourceContainer
|
|
|
4229
4291
|
return blocked;
|
|
4230
4292
|
}
|
|
4231
4293
|
|
|
4294
|
+
// src/client/dnd/design-mode/node-meta-guard.ts
|
|
4295
|
+
var VID_PATTERN = /^[a-z0-9]{6,8}$/;
|
|
4296
|
+
|
|
4232
4297
|
// src/client/dnd/design-mode/fiber-bridge.ts
|
|
4233
4298
|
var FIBER_KEY_PREFIX = "__reactFiber$";
|
|
4234
4299
|
var PROPS_KEY_PREFIX = "__reactProps$";
|
|
@@ -4509,11 +4574,18 @@ function getNodeKeyFromElement(el) {
|
|
|
4509
4574
|
const resolved = resolveDragSurface(el);
|
|
4510
4575
|
const host = resolved.host ?? el;
|
|
4511
4576
|
const meta = identityMeta(host);
|
|
4577
|
+
if (meta?.vid) return meta.vid;
|
|
4578
|
+
const domVid = host.getAttribute("data-vid");
|
|
4579
|
+
if (domVid) return domVid;
|
|
4512
4580
|
if (meta) return meta.nodeId;
|
|
4513
4581
|
const persisted = host.getAttribute("data-dnd-node-id");
|
|
4514
4582
|
if (persisted) return persisted;
|
|
4515
4583
|
return getRuntimeKey(host);
|
|
4516
4584
|
}
|
|
4585
|
+
function resolveVidFromElement(el) {
|
|
4586
|
+
const key2 = getNodeKeyFromElement(el);
|
|
4587
|
+
return VID_PATTERN.test(key2) ? key2 : null;
|
|
4588
|
+
}
|
|
4517
4589
|
function getInspectorRefFromElement(el) {
|
|
4518
4590
|
const resolved = resolveDragSurface(el);
|
|
4519
4591
|
const host = resolved.host ?? el;
|
|
@@ -4840,6 +4912,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4840
4912
|
afterSibling,
|
|
4841
4913
|
diagnostics,
|
|
4842
4914
|
binding,
|
|
4915
|
+
targetVid,
|
|
4916
|
+
containerVid,
|
|
4843
4917
|
componentName,
|
|
4844
4918
|
before,
|
|
4845
4919
|
after
|
|
@@ -4867,6 +4941,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4867
4941
|
afterSibling: afterSibling ?? null,
|
|
4868
4942
|
diagnostics: diagnostics ?? null,
|
|
4869
4943
|
binding: binding ?? null,
|
|
4944
|
+
targetVid: targetVid ?? null,
|
|
4945
|
+
containerVid: containerVid ?? null,
|
|
4870
4946
|
payload: { before, after },
|
|
4871
4947
|
at: now
|
|
4872
4948
|
};
|
|
@@ -4895,6 +4971,7 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4895
4971
|
nodeId,
|
|
4896
4972
|
inspectorRef,
|
|
4897
4973
|
componentName,
|
|
4974
|
+
targetVid,
|
|
4898
4975
|
before,
|
|
4899
4976
|
after
|
|
4900
4977
|
}) => {
|
|
@@ -4906,6 +4983,7 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4906
4983
|
nodeKey,
|
|
4907
4984
|
nodeId,
|
|
4908
4985
|
inspectorRef,
|
|
4986
|
+
targetVid: targetVid ?? null,
|
|
4909
4987
|
payload: { before, after },
|
|
4910
4988
|
at: now
|
|
4911
4989
|
};
|
|
@@ -4939,6 +5017,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4939
5017
|
tsxImports,
|
|
4940
5018
|
containerId,
|
|
4941
5019
|
containerNodeKey,
|
|
5020
|
+
containerVid,
|
|
5021
|
+
insertedVid,
|
|
4942
5022
|
index,
|
|
4943
5023
|
beforeSiblingInspectorRef,
|
|
4944
5024
|
beforeSiblingNodeKey
|
|
@@ -4957,6 +5037,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4957
5037
|
tsxImports: tsxImports ?? null,
|
|
4958
5038
|
containerId,
|
|
4959
5039
|
containerNodeKey,
|
|
5040
|
+
containerVid: containerVid ?? null,
|
|
5041
|
+
insertedVid: insertedVid ?? null,
|
|
4960
5042
|
index,
|
|
4961
5043
|
beforeSiblingInspectorRef: beforeSiblingInspectorRef ?? null,
|
|
4962
5044
|
beforeSiblingNodeKey: beforeSiblingNodeKey ?? null,
|
|
@@ -5070,6 +5152,7 @@ function shouldShowGrabFeedback(target, scannedByNodeId) {
|
|
|
5070
5152
|
}
|
|
5071
5153
|
function isEligibleForDrag(sc) {
|
|
5072
5154
|
if (sc.draggable === false) return false;
|
|
5155
|
+
if (isNonDraggableNodeMeta(sc.editorMeta)) return false;
|
|
5073
5156
|
const source = sc.eligibilitySource ?? "editor-meta";
|
|
5074
5157
|
return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant" || // RFC E2.4 P1: single host root of a kit-component usage (MetricCard,
|
|
5075
5158
|
// Section, …) carrying the usage's projected meta.
|
|
@@ -6692,6 +6775,15 @@ function serializeArrangeChange(event, index) {
|
|
|
6692
6775
|
diagnostics: event.kind === "move" ? event.diagnostics : void 0,
|
|
6693
6776
|
// ARCH-1065 D17 — which slice row this move addresses.
|
|
6694
6777
|
binding: event.kind === "move" ? event.binding : void 0,
|
|
6778
|
+
// `data-vid` identity migration (`host-bridge.ts`'s `RuntimeMoveDetail`
|
|
6779
|
+
// fields). `index` here is `event.payload.after.index` — the MOVE's own
|
|
6780
|
+
// JSX-child index — never the `index` PARAMETER above (this change's
|
|
6781
|
+
// sequence position in the session). `targetVid` also carries the
|
|
6782
|
+
// resized node's vid on a `resize` change; `containerVid` also carries
|
|
6783
|
+
// the drop container's vid on an `insert` change.
|
|
6784
|
+
targetVid: event.kind === "move" || event.kind === "resize" ? event.targetVid : void 0,
|
|
6785
|
+
containerVid: event.kind === "move" || event.kind === "insert" ? event.containerVid : void 0,
|
|
6786
|
+
index: event.kind === "move" ? event.payload.after.index : void 0,
|
|
6695
6787
|
// Insert-specific fields
|
|
6696
6788
|
displayName: event.kind === "insert" ? event.displayName : void 0,
|
|
6697
6789
|
html: event.kind === "insert" ? event.html : void 0,
|
|
@@ -6699,6 +6791,7 @@ function serializeArrangeChange(event, index) {
|
|
|
6699
6791
|
tsxImports: event.kind === "insert" ? event.tsxImports : void 0,
|
|
6700
6792
|
containerId: event.kind === "insert" ? event.containerId : void 0,
|
|
6701
6793
|
containerNodeKey: event.kind === "insert" ? event.containerNodeKey : void 0,
|
|
6794
|
+
insertedVid: event.kind === "insert" ? event.insertedVid : void 0,
|
|
6702
6795
|
insertIndex: event.kind === "insert" ? event.index : void 0,
|
|
6703
6796
|
beforeSiblingInspectorRef: event.kind === "insert" ? event.beforeSiblingInspectorRef : void 0,
|
|
6704
6797
|
beforeSiblingNodeKey: event.kind === "insert" ? event.beforeSiblingNodeKey : void 0,
|
|
@@ -6955,6 +7048,7 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6955
7048
|
const resolvedReorderRef = (0, import_react11.useRef)(null);
|
|
6956
7049
|
const finalVisualKeyRef = (0, import_react11.useRef)(null);
|
|
6957
7050
|
const dragStartPositionRef = (0, import_react11.useRef)(null);
|
|
7051
|
+
const droppableContainerIdsRef = (0, import_react11.useRef)(null);
|
|
6958
7052
|
const sourceCommitLaneRef = (0, import_react11.useRef)(null);
|
|
6959
7053
|
const commitLaneCacheRef = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
|
|
6960
7054
|
const safeZoneRef = (0, import_react11.useRef)(null);
|
|
@@ -6986,6 +7080,7 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6986
7080
|
resolvedReorderRef,
|
|
6987
7081
|
finalVisualKeyRef,
|
|
6988
7082
|
dragStartPositionRef,
|
|
7083
|
+
droppableContainerIdsRef,
|
|
6989
7084
|
sourceCommitLaneRef,
|
|
6990
7085
|
commitLaneCacheRef,
|
|
6991
7086
|
safeZoneRef,
|
|
@@ -8187,6 +8282,14 @@ function useDragVisualLoop({
|
|
|
8187
8282
|
|
|
8188
8283
|
// src/client/dnd/design-mode/useDragLifecycle.ts
|
|
8189
8284
|
var import_react13 = require("react");
|
|
8285
|
+
function emitRefused(code, cause, element) {
|
|
8286
|
+
dispatchRuntimeEvent({
|
|
8287
|
+
type: "drag-refused",
|
|
8288
|
+
code,
|
|
8289
|
+
cause,
|
|
8290
|
+
vid: element ? resolveVidFromElement(element) : null
|
|
8291
|
+
});
|
|
8292
|
+
}
|
|
8190
8293
|
function resolveLaneAllowedContainers(anchorElement, srcContainerId) {
|
|
8191
8294
|
if (!srcContainerId) return null;
|
|
8192
8295
|
if (!resolveRowBinding(anchorElement)) return null;
|
|
@@ -8303,6 +8406,10 @@ function recordCommittedMove(args) {
|
|
|
8303
8406
|
});
|
|
8304
8407
|
const componentName = getEditorMeta(anchorEl)?.componentName;
|
|
8305
8408
|
const operationId = `${command.at}:${anchorNodeId}`;
|
|
8409
|
+
const targetVid = resolveVidFromElement(selectedEl);
|
|
8410
|
+
const targetContainerId = command.to.parentNodeId ?? command.to.laneContainerId;
|
|
8411
|
+
const targetContainerEl = targetContainerId ? resolveNodeElement(targetContainerId) : null;
|
|
8412
|
+
const containerVid = targetContainerEl ? resolveVidFromElement(targetContainerEl) : null;
|
|
8306
8413
|
const binding = resolveRowBinding(selectedEl);
|
|
8307
8414
|
const beforePayload = buildMovePayloadWithEffectiveIdentities({
|
|
8308
8415
|
placement: command.from,
|
|
@@ -8334,6 +8441,8 @@ function recordCommittedMove(args) {
|
|
|
8334
8441
|
sourceAfterSibling: sourceAfterSiblingIdentity,
|
|
8335
8442
|
diagnostics,
|
|
8336
8443
|
binding,
|
|
8444
|
+
targetVid,
|
|
8445
|
+
containerVid,
|
|
8337
8446
|
container: containerIdentity,
|
|
8338
8447
|
beforeSibling: beforeSiblingIdentity,
|
|
8339
8448
|
afterSibling: afterSiblingIdentity,
|
|
@@ -8345,6 +8454,9 @@ function recordCommittedMove(args) {
|
|
|
8345
8454
|
type: "element-moved",
|
|
8346
8455
|
operationId,
|
|
8347
8456
|
commandType: command.type,
|
|
8457
|
+
targetVid,
|
|
8458
|
+
containerVid,
|
|
8459
|
+
index: command.to.index,
|
|
8348
8460
|
selected: {
|
|
8349
8461
|
nodeId: selectedNodeId,
|
|
8350
8462
|
nodeKey: selectedNodeKey,
|
|
@@ -8407,6 +8519,7 @@ function useDragLifecycle({
|
|
|
8407
8519
|
refs.resolvedReorderRef.current = null;
|
|
8408
8520
|
refs.finalVisualKeyRef.current = null;
|
|
8409
8521
|
refs.dragStartPositionRef.current = null;
|
|
8522
|
+
refs.droppableContainerIdsRef.current = null;
|
|
8410
8523
|
clearCommitLaneCache();
|
|
8411
8524
|
refs.safeZoneRef.current = null;
|
|
8412
8525
|
setInsideRect(null);
|
|
@@ -8440,6 +8553,11 @@ function useDragLifecycle({
|
|
|
8440
8553
|
eligibilitySource: found.eligibilitySource ?? "editor-meta",
|
|
8441
8554
|
draggable: found.draggable
|
|
8442
8555
|
});
|
|
8556
|
+
emitRefused(
|
|
8557
|
+
resolveRefusalCode(found.editorMeta, "GATE_REJECT"),
|
|
8558
|
+
"Node is not draggable (dynamic render, chrome, or kit-origin).",
|
|
8559
|
+
found.element
|
|
8560
|
+
);
|
|
8443
8561
|
return;
|
|
8444
8562
|
}
|
|
8445
8563
|
veTrace("dnd", "drag:start", {
|
|
@@ -8463,12 +8581,29 @@ function useDragLifecycle({
|
|
|
8463
8581
|
clearCommitLaneCache();
|
|
8464
8582
|
const anchor = resolveDragAnchor(activeId, proj, refs.nodeMapRef.current);
|
|
8465
8583
|
const anchorScanned = refs.nodeMapRef.current.get(anchor.anchorNodeId) ?? found;
|
|
8466
|
-
if (!anchorScanned || !isEligibleForDrag(anchorScanned))
|
|
8584
|
+
if (!anchorScanned || !isEligibleForDrag(anchorScanned)) {
|
|
8585
|
+
emitRefused(
|
|
8586
|
+
resolveRefusalCode(anchorScanned?.editorMeta, "GATE_REJECT"),
|
|
8587
|
+
"Resolved drag anchor is not draggable.",
|
|
8588
|
+
anchorScanned?.element ?? found.element
|
|
8589
|
+
);
|
|
8590
|
+
return;
|
|
8591
|
+
}
|
|
8467
8592
|
const anchorNodeId = anchor.anchorNodeId;
|
|
8468
8593
|
const srcContainerId = anchor.sourceContainerId;
|
|
8469
8594
|
const sourceCommitLane = getCommitLaneSnapshot(srcContainerId);
|
|
8470
8595
|
const startPosition = getCurrentCommitPlacement(anchorNodeId, srcContainerId);
|
|
8471
8596
|
const blockedContainerIds = buildBlockedStructuralContainerIds(proj, refs.nodeMapRef.current, srcContainerId);
|
|
8597
|
+
for (const id of buildBlockedNodeMetaContainerIds(proj, refs.nodeMapRef.current)) {
|
|
8598
|
+
blockedContainerIds.add(id);
|
|
8599
|
+
}
|
|
8600
|
+
const droppableSet = computeDroppableSet(anchorNodeId, proj, refs.nodeMapRef.current);
|
|
8601
|
+
refs.droppableContainerIdsRef.current = droppableSet;
|
|
8602
|
+
dispatchRuntimeEvent({
|
|
8603
|
+
type: "drag-started",
|
|
8604
|
+
targetVid: resolveVidFromElement(anchorScanned.element),
|
|
8605
|
+
droppable: Array.from(droppableSet)
|
|
8606
|
+
});
|
|
8472
8607
|
const engineOptions = buildDragIntentEngineOptions(anchorScanned.element, srcContainerId, blockedContainerIds);
|
|
8473
8608
|
refs.rowLockedRef.current = !!engineOptions.laneAllowedContainers;
|
|
8474
8609
|
refs.engineRef.current = createDragIntentEngine(proj, anchorNodeId, engineOptions);
|
|
@@ -8541,6 +8676,19 @@ function useDragLifecycle({
|
|
|
8541
8676
|
syncHistoryAvailability();
|
|
8542
8677
|
return;
|
|
8543
8678
|
}
|
|
8679
|
+
if (dropTargetId && !refs.droppableContainerIdsRef.current?.has(dropTargetId)) {
|
|
8680
|
+
const targetContainerEl = resolveNodeElement(dropTargetId);
|
|
8681
|
+
const targetMeta = refs.nodeMapRef.current.get(dropTargetId)?.editorMeta;
|
|
8682
|
+
const fallbackCode = targetMeta?.containerKind === "expression" ? "EXPRESSION_CONTAINER" : "CONTAINER_NOT_PLAIN";
|
|
8683
|
+
emitRefused(
|
|
8684
|
+
resolveRefusalCode(targetMeta, fallbackCode),
|
|
8685
|
+
"Drop target is outside the droppable set for this node.",
|
|
8686
|
+
targetContainerEl
|
|
8687
|
+
);
|
|
8688
|
+
clearDragState();
|
|
8689
|
+
syncHistoryAvailability();
|
|
8690
|
+
return;
|
|
8691
|
+
}
|
|
8544
8692
|
let command = null;
|
|
8545
8693
|
if (nestTarget) {
|
|
8546
8694
|
if (!activeEl.contains(nestTarget.element) && !nestTarget.element.contains(activeEl) && sourcePos?.commitNodeId) {
|
|
@@ -8752,6 +8900,7 @@ function useResizeSession({
|
|
|
8752
8900
|
return;
|
|
8753
8901
|
}
|
|
8754
8902
|
const inspectorRef = getInspectorRefFromElement(element);
|
|
8903
|
+
const targetVid = resolveVidFromElement(element);
|
|
8755
8904
|
const resizeCmd = {
|
|
8756
8905
|
type: "resize",
|
|
8757
8906
|
mode,
|
|
@@ -8771,12 +8920,14 @@ function useResizeSession({
|
|
|
8771
8920
|
nodeId: selectedNodeId,
|
|
8772
8921
|
inspectorRef,
|
|
8773
8922
|
componentName: getEditorMeta(element)?.componentName,
|
|
8923
|
+
targetVid,
|
|
8774
8924
|
before: { mode, selectedNodeKey, targetNodeKey, targetNodeId, width: resizeCmd.before.width, height: resizeCmd.before.height, colSpan: resizeCmd.before.colSpan, rowSpan: resizeCmd.before.rowSpan, styleDiff: { before: beforeStyles, after: afterStyles } },
|
|
8775
8925
|
after: { mode, selectedNodeKey, targetNodeKey, targetNodeId, width: resizeCmd.after.width, height: resizeCmd.after.height, colSpan: resizeCmd.after.colSpan, rowSpan: resizeCmd.after.rowSpan, styleDiff: { before: beforeStyles, after: afterStyles } }
|
|
8776
8926
|
});
|
|
8777
8927
|
dispatchRuntimeEvent({
|
|
8778
8928
|
type: "element-resized",
|
|
8779
8929
|
operationId,
|
|
8930
|
+
targetVid,
|
|
8780
8931
|
selected: {
|
|
8781
8932
|
nodeId: selectedNodeId,
|
|
8782
8933
|
nodeKey: selectedNodeKey,
|
|
@@ -8999,6 +9150,8 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
|
|
|
8999
9150
|
};
|
|
9000
9151
|
}
|
|
9001
9152
|
const operationId = `${insertCommand.at}:${nodeId}`;
|
|
9153
|
+
const containerVid = containerEl ? resolveVidFromElement(containerEl) : null;
|
|
9154
|
+
const insertedVid = resolveVidFromElement(newElement);
|
|
9002
9155
|
useDesignModeStore.getState().recordInsertChange({
|
|
9003
9156
|
operationId,
|
|
9004
9157
|
nodeKey,
|
|
@@ -9010,6 +9163,8 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
|
|
|
9010
9163
|
tsxImports: component.tsxImports ?? null,
|
|
9011
9164
|
containerId: intent.containerId,
|
|
9012
9165
|
containerNodeKey,
|
|
9166
|
+
containerVid,
|
|
9167
|
+
insertedVid,
|
|
9013
9168
|
index: intent.index,
|
|
9014
9169
|
beforeSiblingInspectorRef: beforeSiblingIdentity?.inspectorRef ?? null,
|
|
9015
9170
|
beforeSiblingNodeKey: beforeSiblingIdentity?.nodeKey ?? null
|
|
@@ -9024,6 +9179,8 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
|
|
|
9024
9179
|
tsxCode: component.tsxCode ?? null,
|
|
9025
9180
|
tsxImports: component.tsxImports ?? null,
|
|
9026
9181
|
container: containerIdentity,
|
|
9182
|
+
containerVid,
|
|
9183
|
+
insertedVid,
|
|
9027
9184
|
index: intent.index,
|
|
9028
9185
|
beforeSibling: beforeSiblingIdentity
|
|
9029
9186
|
});
|