@archie/devtools 0.0.12-beta → 0.0.13
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/dist/client/client.d.mts +38 -1
- package/dist/client/client.d.ts +38 -1
- package/dist/client/client.js +1443 -727
- package/dist/client/client.mjs +1405 -689
- package/dist/index.js +9 -3
- package/dist/index.mjs +9 -3
- package/package.json +2 -2
package/dist/client/client.js
CHANGED
|
@@ -37,7 +37,7 @@ __export(client_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(client_exports);
|
|
38
38
|
|
|
39
39
|
// src/client/dnd/DndProvider.tsx
|
|
40
|
-
var
|
|
40
|
+
var import_react19 = require("react");
|
|
41
41
|
|
|
42
42
|
// node_modules/@dnd-kit/core/dist/core.esm.js
|
|
43
43
|
var import_react3 = __toESM(require("react"));
|
|
@@ -4104,19 +4104,498 @@ function mergeInspectorTheme(theme) {
|
|
|
4104
4104
|
};
|
|
4105
4105
|
}
|
|
4106
4106
|
|
|
4107
|
+
// src/client/dnd/design-mode/structural-policy.ts
|
|
4108
|
+
var STRUCTURAL_COMPONENT_RE = /(?:Page|Provider|RootLayout)$/;
|
|
4109
|
+
var STRUCTURAL_TAGS = /* @__PURE__ */ new Set(["html", "body"]);
|
|
4110
|
+
function isStructuralComponentName(componentName) {
|
|
4111
|
+
return !!componentName && STRUCTURAL_COMPONENT_RE.test(componentName);
|
|
4112
|
+
}
|
|
4113
|
+
function isHighLevelStructuralElement(el) {
|
|
4114
|
+
if (!el) return false;
|
|
4115
|
+
if (el.hasAttribute("data-dnd-structural")) return true;
|
|
4116
|
+
const tag = el.tagName.toLowerCase();
|
|
4117
|
+
if (STRUCTURAL_TAGS.has(tag)) return true;
|
|
4118
|
+
if (el.id === "root") return true;
|
|
4119
|
+
return tag === "main" && (el.parentElement === document.body || el.parentElement?.id === "root");
|
|
4120
|
+
}
|
|
4121
|
+
function isStructuralScannedElement(scanned) {
|
|
4122
|
+
if (!scanned) return false;
|
|
4123
|
+
if (isHighLevelStructuralElement(scanned.element)) return true;
|
|
4124
|
+
return isStructuralComponentName(scanned.editorMeta?.componentName);
|
|
4125
|
+
}
|
|
4126
|
+
function isStructuralContainer(containerId, nodeMap) {
|
|
4127
|
+
return isStructuralScannedElement(nodeMap.get(containerId));
|
|
4128
|
+
}
|
|
4129
|
+
function isValidLaneContainer(containerId, projection, nodeMap) {
|
|
4130
|
+
const container = projection.containerIndex.get(containerId);
|
|
4131
|
+
if (!container) return false;
|
|
4132
|
+
if (container.children.length === 0) return false;
|
|
4133
|
+
return !isStructuralContainer(containerId, nodeMap);
|
|
4134
|
+
}
|
|
4135
|
+
function buildBlockedStructuralContainerIds(projection, nodeMap, sourceContainerId) {
|
|
4136
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
4137
|
+
for (const containerId of projection.containerIndex.keys()) {
|
|
4138
|
+
if (containerId === sourceContainerId) continue;
|
|
4139
|
+
if (isStructuralContainer(containerId, nodeMap)) blocked.add(containerId);
|
|
4140
|
+
}
|
|
4141
|
+
return blocked;
|
|
4142
|
+
}
|
|
4143
|
+
|
|
4144
|
+
// src/client/dnd/design-mode/fiber-bridge.ts
|
|
4145
|
+
var FIBER_KEY_PREFIX = "__reactFiber$";
|
|
4146
|
+
var PROPS_KEY_PREFIX = "__reactProps$";
|
|
4147
|
+
var metaCache = /* @__PURE__ */ new WeakMap();
|
|
4148
|
+
var directMetaCache = /* @__PURE__ */ new WeakMap();
|
|
4149
|
+
function hasEditorMetaInFiberChain(fiber) {
|
|
4150
|
+
let current = fiber;
|
|
4151
|
+
while (current) {
|
|
4152
|
+
if (current.memoizedProps?.__editorMeta) return true;
|
|
4153
|
+
current = current.return;
|
|
4154
|
+
}
|
|
4155
|
+
return false;
|
|
4156
|
+
}
|
|
4157
|
+
function compareFiberCandidates(candidate, currentBest) {
|
|
4158
|
+
if (!currentBest) return 1;
|
|
4159
|
+
const candidateScore = [
|
|
4160
|
+
candidate.hasMatchingProps ? 1 : 0,
|
|
4161
|
+
candidate.hasDirectEditorMeta ? 1 : 0,
|
|
4162
|
+
candidate.hasCompanionPropsKey ? 1 : 0,
|
|
4163
|
+
candidate.hasEditorMetaInReturnChain ? 1 : 0,
|
|
4164
|
+
candidate.order
|
|
4165
|
+
];
|
|
4166
|
+
const currentScore = [
|
|
4167
|
+
currentBest.hasMatchingProps ? 1 : 0,
|
|
4168
|
+
currentBest.hasDirectEditorMeta ? 1 : 0,
|
|
4169
|
+
currentBest.hasCompanionPropsKey ? 1 : 0,
|
|
4170
|
+
currentBest.hasEditorMetaInReturnChain ? 1 : 0,
|
|
4171
|
+
currentBest.order
|
|
4172
|
+
];
|
|
4173
|
+
for (let i = 0; i < candidateScore.length; i += 1) {
|
|
4174
|
+
if (candidateScore[i] === currentScore[i]) continue;
|
|
4175
|
+
return candidateScore[i] > currentScore[i] ? 1 : -1;
|
|
4176
|
+
}
|
|
4177
|
+
return 0;
|
|
4178
|
+
}
|
|
4179
|
+
function getFiberSelectionFromElement(el) {
|
|
4180
|
+
const record = el;
|
|
4181
|
+
const keys = Object.keys(record);
|
|
4182
|
+
let bestCandidate = null;
|
|
4183
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
4184
|
+
const fiberKey = keys[i];
|
|
4185
|
+
if (!fiberKey.startsWith(FIBER_KEY_PREFIX)) continue;
|
|
4186
|
+
const fiber = record[fiberKey];
|
|
4187
|
+
if (!fiber) continue;
|
|
4188
|
+
if (fiber.stateNode && fiber.stateNode !== el) continue;
|
|
4189
|
+
const suffix = fiberKey.slice(FIBER_KEY_PREFIX.length);
|
|
4190
|
+
const propsKey = `${PROPS_KEY_PREFIX}${suffix}`;
|
|
4191
|
+
const hasCompanionPropsKey = Object.prototype.hasOwnProperty.call(record, propsKey);
|
|
4192
|
+
const companionProps = hasCompanionPropsKey ? record[propsKey] : void 0;
|
|
4193
|
+
const candidate = {
|
|
4194
|
+
fiber,
|
|
4195
|
+
fiberKey,
|
|
4196
|
+
hasMatchingProps: hasCompanionPropsKey && fiber.memoizedProps === companionProps,
|
|
4197
|
+
hasDirectEditorMeta: !!fiber.memoizedProps?.__editorMeta,
|
|
4198
|
+
hasCompanionPropsKey,
|
|
4199
|
+
hasEditorMetaInReturnChain: hasEditorMetaInFiberChain(fiber),
|
|
4200
|
+
// Tiebreaker: higher index in Object.keys = later React fiber attachment.
|
|
4201
|
+
// Relies on spec-guaranteed insertion-order for string keys (ES2015+).
|
|
4202
|
+
order: i
|
|
4203
|
+
};
|
|
4204
|
+
if (compareFiberCandidates(candidate, bestCandidate) > 0) {
|
|
4205
|
+
bestCandidate = candidate;
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
if (!bestCandidate) {
|
|
4209
|
+
return { fiber: null, fiberKey: null };
|
|
4210
|
+
}
|
|
4211
|
+
return { fiber: bestCandidate.fiber, fiberKey: bestCandidate.fiberKey };
|
|
4212
|
+
}
|
|
4213
|
+
function readFiberAwareCache(cache, el, selection) {
|
|
4214
|
+
const cached = cache.get(el);
|
|
4215
|
+
if (!cached) return void 0;
|
|
4216
|
+
if (cached.fiber !== selection.fiber) return void 0;
|
|
4217
|
+
if (cached.fiberKey !== selection.fiberKey) return void 0;
|
|
4218
|
+
return cached.value;
|
|
4219
|
+
}
|
|
4220
|
+
function writeFiberAwareCache(cache, el, selection, value) {
|
|
4221
|
+
cache.set(el, {
|
|
4222
|
+
fiber: selection.fiber,
|
|
4223
|
+
fiberKey: selection.fiberKey,
|
|
4224
|
+
value
|
|
4225
|
+
});
|
|
4226
|
+
return value;
|
|
4227
|
+
}
|
|
4228
|
+
function isRootSvg(el) {
|
|
4229
|
+
return el instanceof SVGElement && el.tagName.toLowerCase() === "svg";
|
|
4230
|
+
}
|
|
4231
|
+
function isPassthroughMeta(meta) {
|
|
4232
|
+
return !!meta?.staticProps && meta.staticProps.asChild === true;
|
|
4233
|
+
}
|
|
4234
|
+
function isWrapperMeta(meta) {
|
|
4235
|
+
if (!meta?.componentName) return false;
|
|
4236
|
+
return meta.componentName[0] !== meta.componentName[0].toLowerCase();
|
|
4237
|
+
}
|
|
4238
|
+
function hasOwnTextContent(el) {
|
|
4239
|
+
for (const node of Array.from(el.childNodes)) {
|
|
4240
|
+
if (node.nodeType !== Node.TEXT_NODE) continue;
|
|
4241
|
+
if (node.textContent?.trim()) return true;
|
|
4242
|
+
}
|
|
4243
|
+
return false;
|
|
4244
|
+
}
|
|
4245
|
+
function getCandidateChildren(el) {
|
|
4246
|
+
return Array.from(el.children).filter((child) => {
|
|
4247
|
+
if (!(child instanceof HTMLElement)) return false;
|
|
4248
|
+
if (child.hasAttribute("data-design-mode-ui")) return false;
|
|
4249
|
+
if (child.hasAttribute("data-design-mode-allow")) return false;
|
|
4250
|
+
return !shouldIgnoreAsVirtualRuntime(child);
|
|
4251
|
+
});
|
|
4252
|
+
}
|
|
4253
|
+
function shouldIgnoreAsVirtualRuntime(el) {
|
|
4254
|
+
const tag = el.tagName.toLowerCase();
|
|
4255
|
+
if (tag === "canvas") return true;
|
|
4256
|
+
if (tag === "script" || tag === "style" || tag === "noscript") return true;
|
|
4257
|
+
if (el instanceof SVGElement && !isRootSvg(el)) return true;
|
|
4258
|
+
return false;
|
|
4259
|
+
}
|
|
4260
|
+
function getDirectEditorMeta(el) {
|
|
4261
|
+
const selection = getFiberSelectionFromElement(el);
|
|
4262
|
+
const cached = readFiberAwareCache(directMetaCache, el, selection);
|
|
4263
|
+
if (cached !== void 0) return cached;
|
|
4264
|
+
const meta = selection.fiber?.memoizedProps?.__editorMeta;
|
|
4265
|
+
return writeFiberAwareCache(directMetaCache, el, selection, meta ?? null);
|
|
4266
|
+
}
|
|
4267
|
+
function getEditorMeta(el) {
|
|
4268
|
+
const selection = getFiberSelectionFromElement(el);
|
|
4269
|
+
const cached = readFiberAwareCache(metaCache, el, selection);
|
|
4270
|
+
if (cached !== void 0) return cached;
|
|
4271
|
+
let fiber = selection.fiber;
|
|
4272
|
+
while (fiber) {
|
|
4273
|
+
const meta = fiber.memoizedProps?.__editorMeta;
|
|
4274
|
+
if (meta) {
|
|
4275
|
+
return writeFiberAwareCache(metaCache, el, selection, meta);
|
|
4276
|
+
}
|
|
4277
|
+
fiber = fiber.return;
|
|
4278
|
+
}
|
|
4279
|
+
return writeFiberAwareCache(metaCache, el, selection, null);
|
|
4280
|
+
}
|
|
4281
|
+
function findMetaOwnerElement(el) {
|
|
4282
|
+
let current = el;
|
|
4283
|
+
while (current) {
|
|
4284
|
+
if (getEditorMeta(current)) return current;
|
|
4285
|
+
current = current.parentElement;
|
|
4286
|
+
}
|
|
4287
|
+
return null;
|
|
4288
|
+
}
|
|
4289
|
+
function resolveHostElementFromFiberChain(el) {
|
|
4290
|
+
if (shouldIgnoreAsVirtualRuntime(el)) return null;
|
|
4291
|
+
const directMeta = getDirectEditorMeta(el);
|
|
4292
|
+
const ownerMeta = directMeta ?? getEditorMeta(el);
|
|
4293
|
+
if (isPassthroughMeta(ownerMeta)) {
|
|
4294
|
+
const children = getCandidateChildren(el);
|
|
4295
|
+
if (children.length !== 1) return null;
|
|
4296
|
+
return children[0];
|
|
4297
|
+
}
|
|
4298
|
+
if (directMeta && !isWrapperMeta(directMeta)) return el;
|
|
4299
|
+
const MAX_STEPS = 10;
|
|
4300
|
+
const ownerNodeId = ownerMeta?.nodeId ?? null;
|
|
4301
|
+
let outermost = el;
|
|
4302
|
+
let parent = el.parentElement;
|
|
4303
|
+
for (let i = 0; i < MAX_STEPS; i += 1) {
|
|
4304
|
+
if (!parent || parent === document.body) break;
|
|
4305
|
+
if (shouldIgnoreAsVirtualRuntime(parent)) break;
|
|
4306
|
+
const parentMeta = getEditorMeta(parent);
|
|
4307
|
+
if (!parentMeta) break;
|
|
4308
|
+
if (ownerNodeId && parentMeta.nodeId !== ownerNodeId) break;
|
|
4309
|
+
if (isStructuralComponentName(parentMeta.componentName)) break;
|
|
4310
|
+
if (!isWrapperMeta(parentMeta)) break;
|
|
4311
|
+
if (isPassthroughMeta(parentMeta)) break;
|
|
4312
|
+
if (hasOwnTextContent(parent)) break;
|
|
4313
|
+
const children = getCandidateChildren(parent);
|
|
4314
|
+
if (children.length !== 1) break;
|
|
4315
|
+
outermost = parent;
|
|
4316
|
+
parent = parent.parentElement;
|
|
4317
|
+
}
|
|
4318
|
+
return outermost;
|
|
4319
|
+
}
|
|
4320
|
+
function resolveDragSurface(el) {
|
|
4321
|
+
const host = resolveHostElementFromFiberChain(el);
|
|
4322
|
+
if (!host) {
|
|
4323
|
+
return { host: null, metaOwner: null, kind: "direct-host" };
|
|
4324
|
+
}
|
|
4325
|
+
const metaOwner = findMetaOwnerElement(host) ?? findMetaOwnerElement(el);
|
|
4326
|
+
const ownerMeta = metaOwner ? getEditorMeta(metaOwner) : null;
|
|
4327
|
+
const kind = isPassthroughMeta(ownerMeta) ? "passthrough-slot" : metaOwner && metaOwner !== host && isWrapperMeta(ownerMeta) ? "wrapper-to-host" : "direct-host";
|
|
4328
|
+
return {
|
|
4329
|
+
host,
|
|
4330
|
+
metaOwner,
|
|
4331
|
+
kind
|
|
4332
|
+
};
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4335
|
+
// src/client/dnd/design-mode/node-key.ts
|
|
4336
|
+
var _runtimeKeyMap = /* @__PURE__ */ new WeakMap();
|
|
4337
|
+
var _runtimeKeyCounter = 0;
|
|
4338
|
+
function getRuntimeKey(el) {
|
|
4339
|
+
const existing = _runtimeKeyMap.get(el);
|
|
4340
|
+
if (existing) return existing;
|
|
4341
|
+
const key2 = `runtime:${++_runtimeKeyCounter}`;
|
|
4342
|
+
_runtimeKeyMap.set(el, key2);
|
|
4343
|
+
return key2;
|
|
4344
|
+
}
|
|
4345
|
+
function getNodeKeyFromElement(el) {
|
|
4346
|
+
const resolved = resolveDragSurface(el);
|
|
4347
|
+
const host = resolved.host ?? el;
|
|
4348
|
+
const meta = getEditorMeta(host);
|
|
4349
|
+
if (meta) return meta.nodeId;
|
|
4350
|
+
const persisted = host.getAttribute("data-dnd-node-id");
|
|
4351
|
+
if (persisted) return persisted;
|
|
4352
|
+
return getRuntimeKey(host);
|
|
4353
|
+
}
|
|
4354
|
+
function getInspectorRefFromElement(el) {
|
|
4355
|
+
const resolved = resolveDragSurface(el);
|
|
4356
|
+
const host = resolved.host ?? el;
|
|
4357
|
+
const meta = getEditorMeta(host);
|
|
4358
|
+
if (!meta) return null;
|
|
4359
|
+
return { relativePath: meta.file, line: meta.line, column: meta.col };
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
// src/client/dnd/design-mode/arrange-persistence-diagnostics.ts
|
|
4363
|
+
function isSourceBackedRuntimeNodeKey(nodeKey) {
|
|
4364
|
+
return typeof nodeKey === "string" && nodeKey.trim().length > 0 && !nodeKey.startsWith("runtime:");
|
|
4365
|
+
}
|
|
4366
|
+
function mergeRuntimeArrangeDiagnostics(diagnosticsEntries) {
|
|
4367
|
+
const blockedReasons = /* @__PURE__ */ new Set();
|
|
4368
|
+
const notes = /* @__PURE__ */ new Set();
|
|
4369
|
+
let structurallyUnsafe = false;
|
|
4370
|
+
for (const diagnostics of diagnosticsEntries) {
|
|
4371
|
+
if (!diagnostics) continue;
|
|
4372
|
+
if (diagnostics.structurallyUnsafe === true) {
|
|
4373
|
+
structurallyUnsafe = true;
|
|
4374
|
+
}
|
|
4375
|
+
for (const reason of diagnostics.blockedReasons ?? []) {
|
|
4376
|
+
if (typeof reason === "string" && reason.trim().length > 0) {
|
|
4377
|
+
blockedReasons.add(reason);
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
for (const note of diagnostics.notes ?? []) {
|
|
4381
|
+
if (typeof note === "string" && note.trim().length > 0) {
|
|
4382
|
+
notes.add(note);
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
if (!structurallyUnsafe && blockedReasons.size === 0 && notes.size === 0) {
|
|
4387
|
+
return null;
|
|
4388
|
+
}
|
|
4389
|
+
return {
|
|
4390
|
+
...structurallyUnsafe ? { structurallyUnsafe: true } : {},
|
|
4391
|
+
...blockedReasons.size > 0 ? { blockedReasons: Array.from(blockedReasons) } : {},
|
|
4392
|
+
...notes.size > 0 ? { notes: Array.from(notes) } : {}
|
|
4393
|
+
};
|
|
4394
|
+
}
|
|
4395
|
+
function detectDuplicateSourceBackedNodeKeys(nodeKeys) {
|
|
4396
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
4397
|
+
const duplicateKeys = /* @__PURE__ */ new Set();
|
|
4398
|
+
for (const nodeKey of nodeKeys) {
|
|
4399
|
+
if (!isSourceBackedRuntimeNodeKey(nodeKey)) {
|
|
4400
|
+
continue;
|
|
4401
|
+
}
|
|
4402
|
+
if (seenKeys.has(nodeKey)) {
|
|
4403
|
+
duplicateKeys.add(nodeKey);
|
|
4404
|
+
continue;
|
|
4405
|
+
}
|
|
4406
|
+
seenKeys.add(nodeKey);
|
|
4407
|
+
}
|
|
4408
|
+
return Array.from(duplicateKeys);
|
|
4409
|
+
}
|
|
4410
|
+
function buildOccurrenceNodeId(nodeKey, occurrenceIndex) {
|
|
4411
|
+
return `${nodeKey}::${occurrenceIndex}`;
|
|
4412
|
+
}
|
|
4413
|
+
function buildEffectiveNodeIdsByCommitNodeId(commitNodeIds, nodeKeysByCommitNodeId) {
|
|
4414
|
+
const countsByNodeKey = /* @__PURE__ */ new Map();
|
|
4415
|
+
for (const commitNodeId of commitNodeIds) {
|
|
4416
|
+
const nodeKey = nodeKeysByCommitNodeId.get(commitNodeId);
|
|
4417
|
+
if (!isSourceBackedRuntimeNodeKey(nodeKey)) {
|
|
4418
|
+
continue;
|
|
4419
|
+
}
|
|
4420
|
+
countsByNodeKey.set(nodeKey, (countsByNodeKey.get(nodeKey) ?? 0) + 1);
|
|
4421
|
+
}
|
|
4422
|
+
const seenByNodeKey = /* @__PURE__ */ new Map();
|
|
4423
|
+
const effectiveNodeIdsByCommitNodeId = /* @__PURE__ */ new Map();
|
|
4424
|
+
for (const commitNodeId of commitNodeIds) {
|
|
4425
|
+
const nodeKey = nodeKeysByCommitNodeId.get(commitNodeId);
|
|
4426
|
+
if (!isSourceBackedRuntimeNodeKey(nodeKey) || (countsByNodeKey.get(nodeKey) ?? 0) < 2) {
|
|
4427
|
+
effectiveNodeIdsByCommitNodeId.set(commitNodeId, null);
|
|
4428
|
+
continue;
|
|
4429
|
+
}
|
|
4430
|
+
const occurrenceIndex = seenByNodeKey.get(nodeKey) ?? 0;
|
|
4431
|
+
seenByNodeKey.set(nodeKey, occurrenceIndex + 1);
|
|
4432
|
+
effectiveNodeIdsByCommitNodeId.set(
|
|
4433
|
+
commitNodeId,
|
|
4434
|
+
buildOccurrenceNodeId(nodeKey, occurrenceIndex)
|
|
4435
|
+
);
|
|
4436
|
+
}
|
|
4437
|
+
return effectiveNodeIdsByCommitNodeId;
|
|
4438
|
+
}
|
|
4439
|
+
function createCommitLaneIdentitySnapshot(params) {
|
|
4440
|
+
return {
|
|
4441
|
+
laneContainerId: params.laneContainerId,
|
|
4442
|
+
commitNodeIds: [...params.commitNodeIds],
|
|
4443
|
+
nodeKeysByCommitNodeId: new Map(params.nodeKeysByCommitNodeId),
|
|
4444
|
+
effectiveNodeIdsByCommitNodeId: buildEffectiveNodeIdsByCommitNodeId(
|
|
4445
|
+
params.commitNodeIds,
|
|
4446
|
+
params.nodeKeysByCommitNodeId
|
|
4447
|
+
),
|
|
4448
|
+
committable: true
|
|
4449
|
+
};
|
|
4450
|
+
}
|
|
4451
|
+
function hasSafeOccurrenceIdentities(lane, duplicateNodeKey) {
|
|
4452
|
+
const effectiveNodeIds = lane.commitNodeIds.filter(
|
|
4453
|
+
(commitNodeId) => lane.nodeKeysByCommitNodeId.get(commitNodeId) === duplicateNodeKey
|
|
4454
|
+
).map(
|
|
4455
|
+
(commitNodeId) => lane.effectiveNodeIdsByCommitNodeId.get(commitNodeId) ?? null
|
|
4456
|
+
);
|
|
4457
|
+
return effectiveNodeIds.length > 1 && effectiveNodeIds.every(
|
|
4458
|
+
(effectiveNodeId) => typeof effectiveNodeId === "string" && effectiveNodeId.length > 0
|
|
4459
|
+
) && new Set(effectiveNodeIds).size === effectiveNodeIds.length;
|
|
4460
|
+
}
|
|
4461
|
+
function buildLanePersistenceDiagnostics(params) {
|
|
4462
|
+
const duplicateNodeKeys = detectDuplicateSourceBackedNodeKeys(
|
|
4463
|
+
buildNodeKeysFromCommitIds(
|
|
4464
|
+
params.lane.commitNodeIds,
|
|
4465
|
+
params.lane.nodeKeysByCommitNodeId
|
|
4466
|
+
)
|
|
4467
|
+
);
|
|
4468
|
+
if (duplicateNodeKeys.length === 0) {
|
|
4469
|
+
return null;
|
|
4470
|
+
}
|
|
4471
|
+
const safeDuplicateNodeKeys = duplicateNodeKeys.filter(
|
|
4472
|
+
(nodeKey) => hasSafeOccurrenceIdentities(params.lane, nodeKey)
|
|
4473
|
+
);
|
|
4474
|
+
if (safeDuplicateNodeKeys.length === duplicateNodeKeys.length) {
|
|
4475
|
+
return {
|
|
4476
|
+
notes: safeDuplicateNodeKeys.map(
|
|
4477
|
+
(nodeKey) => `Arrange lane ${params.lane.laneContainerId} repeats source-backed nodeKey ${nodeKey}, but runtime assigned explicit occurrence identities for each commit root.`
|
|
4478
|
+
)
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
4481
|
+
return {
|
|
4482
|
+
structurallyUnsafe: true,
|
|
4483
|
+
blockedReasons: duplicateNodeKeys.map(
|
|
4484
|
+
(nodeKey) => `Arrange lane ${params.lane.laneContainerId} contains multiple commit roots with the same source-backed nodeKey (${nodeKey}), so local save is unsafe.`
|
|
4485
|
+
),
|
|
4486
|
+
notes: [
|
|
4487
|
+
`Lane ${params.lane.laneContainerId} duplicates source-backed nodeKeys: ${duplicateNodeKeys.join(", ")}`
|
|
4488
|
+
]
|
|
4489
|
+
};
|
|
4490
|
+
}
|
|
4491
|
+
function removeCommitNodeId(commitNodeIds, commitNodeId) {
|
|
4492
|
+
return commitNodeIds.filter((candidate) => candidate !== commitNodeId);
|
|
4493
|
+
}
|
|
4494
|
+
function buildNodeKeysFromCommitIds(commitNodeIds, nodeKeysByCommitNodeId) {
|
|
4495
|
+
return commitNodeIds.map(
|
|
4496
|
+
(commitNodeId) => nodeKeysByCommitNodeId.get(commitNodeId) ?? null
|
|
4497
|
+
);
|
|
4498
|
+
}
|
|
4499
|
+
function captureCommitLaneIdentitySnapshot(lane, resolveNodeElement) {
|
|
4500
|
+
if (!lane?.committable) return null;
|
|
4501
|
+
const nodeKeysByCommitNodeId = /* @__PURE__ */ new Map();
|
|
4502
|
+
for (const commitNodeId of lane.orderedCommitNodeIds) {
|
|
4503
|
+
const element = resolveNodeElement(commitNodeId);
|
|
4504
|
+
if (!element) return null;
|
|
4505
|
+
nodeKeysByCommitNodeId.set(commitNodeId, getNodeKeyFromElement(element));
|
|
4506
|
+
}
|
|
4507
|
+
return createCommitLaneIdentitySnapshot({
|
|
4508
|
+
laneContainerId: lane.laneContainerId,
|
|
4509
|
+
nodeKeysByCommitNodeId,
|
|
4510
|
+
commitNodeIds: lane.orderedCommitNodeIds
|
|
4511
|
+
});
|
|
4512
|
+
}
|
|
4513
|
+
function projectCommitNodeIdsForMove(params) {
|
|
4514
|
+
const withoutMovedCommit = removeCommitNodeId(
|
|
4515
|
+
params.commitNodeIds,
|
|
4516
|
+
params.movedCommitNodeId
|
|
4517
|
+
);
|
|
4518
|
+
if (typeof params.targetIndex !== "number" || !Number.isFinite(params.targetIndex)) {
|
|
4519
|
+
return [...withoutMovedCommit, params.movedCommitNodeId];
|
|
4520
|
+
}
|
|
4521
|
+
const insertionIndex = Math.max(
|
|
4522
|
+
0,
|
|
4523
|
+
Math.min(params.targetIndex, withoutMovedCommit.length)
|
|
4524
|
+
);
|
|
4525
|
+
return [
|
|
4526
|
+
...withoutMovedCommit.slice(0, insertionIndex),
|
|
4527
|
+
params.movedCommitNodeId,
|
|
4528
|
+
...withoutMovedCommit.slice(insertionIndex)
|
|
4529
|
+
];
|
|
4530
|
+
}
|
|
4531
|
+
function buildMovePersistenceDiagnostics(params) {
|
|
4532
|
+
const {
|
|
4533
|
+
sourceLane,
|
|
4534
|
+
targetLane,
|
|
4535
|
+
movedCommitNodeId,
|
|
4536
|
+
sourceLaneContainerId,
|
|
4537
|
+
targetLaneContainerId,
|
|
4538
|
+
targetIndex
|
|
4539
|
+
} = params;
|
|
4540
|
+
const sameLane = !!sourceLaneContainerId && !!targetLaneContainerId && sourceLaneContainerId === targetLaneContainerId;
|
|
4541
|
+
const targetSnapshot = sameLane ? targetLane ?? sourceLane : targetLane;
|
|
4542
|
+
const sourceLaneAfter = !sameLane && sourceLane?.committable ? createCommitLaneIdentitySnapshot({
|
|
4543
|
+
laneContainerId: sourceLane.laneContainerId,
|
|
4544
|
+
commitNodeIds: removeCommitNodeId(
|
|
4545
|
+
sourceLane.commitNodeIds,
|
|
4546
|
+
movedCommitNodeId
|
|
4547
|
+
),
|
|
4548
|
+
nodeKeysByCommitNodeId: sourceLane.nodeKeysByCommitNodeId
|
|
4549
|
+
}) : null;
|
|
4550
|
+
const targetLaneAfter = targetSnapshot?.committable ? createCommitLaneIdentitySnapshot({
|
|
4551
|
+
laneContainerId: targetSnapshot.laneContainerId,
|
|
4552
|
+
commitNodeIds: projectCommitNodeIdsForMove({
|
|
4553
|
+
commitNodeIds: targetSnapshot.commitNodeIds,
|
|
4554
|
+
movedCommitNodeId,
|
|
4555
|
+
targetIndex
|
|
4556
|
+
}),
|
|
4557
|
+
nodeKeysByCommitNodeId: new Map([
|
|
4558
|
+
...targetSnapshot.nodeKeysByCommitNodeId,
|
|
4559
|
+
...sourceLane?.nodeKeysByCommitNodeId.has(movedCommitNodeId) ? [
|
|
4560
|
+
[
|
|
4561
|
+
movedCommitNodeId,
|
|
4562
|
+
sourceLane.nodeKeysByCommitNodeId.get(movedCommitNodeId) ?? null
|
|
4563
|
+
]
|
|
4564
|
+
] : []
|
|
4565
|
+
])
|
|
4566
|
+
}) : null;
|
|
4567
|
+
return mergeRuntimeArrangeDiagnostics([
|
|
4568
|
+
sourceLaneAfter ? buildLanePersistenceDiagnostics({ lane: sourceLaneAfter }) : null,
|
|
4569
|
+
targetLaneAfter ? buildLanePersistenceDiagnostics({ lane: targetLaneAfter }) : null
|
|
4570
|
+
]);
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4107
4573
|
// src/client/dnd/design-mode/store.ts
|
|
4108
4574
|
function summarizeEditorChangeEvent(event) {
|
|
4575
|
+
if (event.kind === "insert") {
|
|
4576
|
+
return `insert ${event.displayName} at ${event.containerId}[${event.index}]`;
|
|
4577
|
+
}
|
|
4109
4578
|
if (event.kind === "move") {
|
|
4110
4579
|
const selectedHint = event.selectedNodeKey && event.selectedNodeKey !== event.nodeKey ? ` (selected ${event.selectedNodeKey})` : "";
|
|
4111
4580
|
const anchorHint = event.anchorNodeKey && event.anchorNodeKey !== event.nodeKey ? ` (anchor ${event.anchorNodeKey})` : "";
|
|
4112
|
-
const
|
|
4113
|
-
|
|
4581
|
+
const beforeParentNodeId = event.payload.before.effectiveContainerNodeId ?? event.payload.before.parentNodeId;
|
|
4582
|
+
const afterParentNodeId = event.payload.after.effectiveContainerNodeId ?? event.payload.after.parentNodeId;
|
|
4583
|
+
const commitNodeId = event.payload.after.effectiveCommitNodeId ?? event.payload.after.commitNodeId;
|
|
4584
|
+
const beforeNodeId = event.payload.after.effectiveBeforeNodeId ?? event.payload.after.beforeNodeId;
|
|
4585
|
+
const afterNodeId = event.payload.after.effectiveAfterNodeId ?? event.payload.after.afterNodeId;
|
|
4586
|
+
return `move ${event.nodeKey}: parent ${beforeParentNodeId}[${event.payload.before.index}] \u2192 ${afterParentNodeId}[${event.payload.after.index}]${commitNodeId ? ` (commit ${commitNodeId}` : ""}${beforeNodeId ? ` before ${beforeNodeId}` : ""}${afterNodeId ? ` after ${afterNodeId}` : ""}${commitNodeId ? ")" : ""}${selectedHint}${anchorHint}`;
|
|
4114
4587
|
}
|
|
4115
4588
|
if (event.payload.after.mode === "grid-span") {
|
|
4116
4589
|
return `resize(grid-span) ${event.nodeKey}: col ${event.payload.before.colSpan ?? 1}\u2192${event.payload.after.colSpan ?? 1}, row ${event.payload.before.rowSpan ?? 1}\u2192${event.payload.after.rowSpan ?? 1}`;
|
|
4117
4590
|
}
|
|
4118
4591
|
return `resize(px) ${event.nodeKey}: ${event.payload.before.width}\xD7${event.payload.before.height} \u2192 ${event.payload.after.width}\xD7${event.payload.after.height}`;
|
|
4119
4592
|
}
|
|
4593
|
+
function buildFallbackOperationId(now, nodeId) {
|
|
4594
|
+
return `${now}:${nodeId}`;
|
|
4595
|
+
}
|
|
4596
|
+
function inferMoveCommandType(before, after) {
|
|
4597
|
+
return before.parentNodeId === after.parentNodeId ? "reorder" : "moveCrossContainer";
|
|
4598
|
+
}
|
|
4120
4599
|
function rebuildNodeEdit(orderedChanges, nodeKey) {
|
|
4121
4600
|
let latestMove;
|
|
4122
4601
|
let latestResize;
|
|
@@ -4131,11 +4610,36 @@ function rebuildNodeEdit(orderedChanges, nodeKey) {
|
|
|
4131
4610
|
nodeId = ev.nodeId;
|
|
4132
4611
|
inspectorRef = ev.inspectorRef;
|
|
4133
4612
|
if (ev.kind === "move") latestMove = ev.payload;
|
|
4134
|
-
else latestResize = ev.payload;
|
|
4613
|
+
else if (ev.kind === "resize") latestResize = ev.payload;
|
|
4135
4614
|
}
|
|
4136
4615
|
if (count === 0) return null;
|
|
4137
4616
|
return { nodeKey, nodeId, inspectorRef, latestMove, latestResize, changeCount: count, lastUpdatedAt: lastAt };
|
|
4138
4617
|
}
|
|
4618
|
+
function coalesceOrderedChanges(changes) {
|
|
4619
|
+
if (changes.length <= 1) return changes;
|
|
4620
|
+
const result = [];
|
|
4621
|
+
for (const event of changes) {
|
|
4622
|
+
const prev = result[result.length - 1];
|
|
4623
|
+
if (prev && prev.kind === "resize" && event.kind === "resize" && prev.nodeKey === event.nodeKey) {
|
|
4624
|
+
result[result.length - 1] = {
|
|
4625
|
+
...event,
|
|
4626
|
+
payload: { before: prev.payload.before, after: event.payload.after }
|
|
4627
|
+
};
|
|
4628
|
+
} else {
|
|
4629
|
+
result.push(event);
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
return result;
|
|
4633
|
+
}
|
|
4634
|
+
function buildEmptyArrangeSessionState() {
|
|
4635
|
+
return {
|
|
4636
|
+
nodeEditsByKey: {},
|
|
4637
|
+
orderedChanges: [],
|
|
4638
|
+
undoneChanges: [],
|
|
4639
|
+
canUndo: false,
|
|
4640
|
+
canRedo: false
|
|
4641
|
+
};
|
|
4642
|
+
}
|
|
4139
4643
|
var useDesignModeStore = create((set, get) => ({
|
|
4140
4644
|
// UI state
|
|
4141
4645
|
enabled: false,
|
|
@@ -4151,8 +4655,10 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4151
4655
|
nodeEditsByKey: {},
|
|
4152
4656
|
orderedChanges: [],
|
|
4153
4657
|
undoneChanges: [],
|
|
4658
|
+
// External drag
|
|
4659
|
+
externalDrag: null,
|
|
4154
4660
|
// UI actions
|
|
4155
|
-
toggle: () => set((s) => ({ enabled: !s.enabled })),
|
|
4661
|
+
toggle: () => set((s) => ({ enabled: !s.enabled, ...buildEmptyArrangeSessionState() })),
|
|
4156
4662
|
setEnabled: (enabled) => set({ enabled }),
|
|
4157
4663
|
setHovered: (selector) => set({ hoveredSelector: selector }),
|
|
4158
4664
|
setSelected: (selector) => set({ selectedSelector: selector }),
|
|
@@ -4167,6 +4673,7 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4167
4673
|
canUndo: false,
|
|
4168
4674
|
canRedo: false
|
|
4169
4675
|
}),
|
|
4676
|
+
resetArrangeSession: () => set(buildEmptyArrangeSessionState()),
|
|
4170
4677
|
// Change tracking actions
|
|
4171
4678
|
recordMoveChange: ({
|
|
4172
4679
|
operationId,
|
|
@@ -4179,18 +4686,24 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4179
4686
|
selectedInspectorRef,
|
|
4180
4687
|
anchorNodeKey,
|
|
4181
4688
|
anchorNodeId,
|
|
4689
|
+
sourceContainer,
|
|
4690
|
+
sourceBeforeSibling,
|
|
4691
|
+
sourceAfterSibling,
|
|
4182
4692
|
container,
|
|
4183
4693
|
beforeSibling,
|
|
4184
4694
|
afterSibling,
|
|
4695
|
+
diagnostics,
|
|
4185
4696
|
componentName,
|
|
4186
4697
|
before,
|
|
4187
4698
|
after
|
|
4188
4699
|
}) => {
|
|
4189
4700
|
const now = Date.now();
|
|
4701
|
+
const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
|
|
4702
|
+
const normalizedCommandType = commandType ?? inferMoveCommandType(before, after);
|
|
4190
4703
|
const event = {
|
|
4191
4704
|
kind: "move",
|
|
4192
|
-
operationId:
|
|
4193
|
-
commandType:
|
|
4705
|
+
operationId: normalizedOperationId,
|
|
4706
|
+
commandType: normalizedCommandType,
|
|
4194
4707
|
nodeKey,
|
|
4195
4708
|
nodeId,
|
|
4196
4709
|
inspectorRef,
|
|
@@ -4199,9 +4712,13 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4199
4712
|
selectedInspectorRef,
|
|
4200
4713
|
anchorNodeKey,
|
|
4201
4714
|
anchorNodeId,
|
|
4715
|
+
sourceContainer: sourceContainer ?? null,
|
|
4716
|
+
sourceBeforeSibling: sourceBeforeSibling ?? null,
|
|
4717
|
+
sourceAfterSibling: sourceAfterSibling ?? null,
|
|
4202
4718
|
container: container ?? null,
|
|
4203
4719
|
beforeSibling: beforeSibling ?? null,
|
|
4204
4720
|
afterSibling: afterSibling ?? null,
|
|
4721
|
+
diagnostics: diagnostics ?? null,
|
|
4205
4722
|
payload: { before, after },
|
|
4206
4723
|
at: now
|
|
4207
4724
|
};
|
|
@@ -4224,11 +4741,20 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4224
4741
|
};
|
|
4225
4742
|
});
|
|
4226
4743
|
},
|
|
4227
|
-
recordResizeChange: ({
|
|
4744
|
+
recordResizeChange: ({
|
|
4745
|
+
operationId,
|
|
4746
|
+
nodeKey,
|
|
4747
|
+
nodeId,
|
|
4748
|
+
inspectorRef,
|
|
4749
|
+
componentName,
|
|
4750
|
+
before,
|
|
4751
|
+
after
|
|
4752
|
+
}) => {
|
|
4228
4753
|
const now = Date.now();
|
|
4754
|
+
const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
|
|
4229
4755
|
const event = {
|
|
4230
4756
|
kind: "resize",
|
|
4231
|
-
operationId:
|
|
4757
|
+
operationId: normalizedOperationId,
|
|
4232
4758
|
nodeKey,
|
|
4233
4759
|
nodeId,
|
|
4234
4760
|
inspectorRef,
|
|
@@ -4254,6 +4780,52 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4254
4780
|
};
|
|
4255
4781
|
});
|
|
4256
4782
|
},
|
|
4783
|
+
recordInsertChange: ({
|
|
4784
|
+
operationId,
|
|
4785
|
+
nodeKey,
|
|
4786
|
+
nodeId,
|
|
4787
|
+
inspectorRef,
|
|
4788
|
+
displayName,
|
|
4789
|
+
html,
|
|
4790
|
+
containerId,
|
|
4791
|
+
containerNodeKey,
|
|
4792
|
+
index
|
|
4793
|
+
}) => {
|
|
4794
|
+
const now = Date.now();
|
|
4795
|
+
const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
|
|
4796
|
+
const event = {
|
|
4797
|
+
kind: "insert",
|
|
4798
|
+
operationId: normalizedOperationId,
|
|
4799
|
+
nodeKey,
|
|
4800
|
+
nodeId,
|
|
4801
|
+
inspectorRef,
|
|
4802
|
+
displayName,
|
|
4803
|
+
html,
|
|
4804
|
+
containerId,
|
|
4805
|
+
containerNodeKey,
|
|
4806
|
+
index,
|
|
4807
|
+
at: now
|
|
4808
|
+
};
|
|
4809
|
+
set((s) => {
|
|
4810
|
+
const prev = s.nodeEditsByKey[nodeKey];
|
|
4811
|
+
const meta = {
|
|
4812
|
+
nodeKey,
|
|
4813
|
+
nodeId,
|
|
4814
|
+
inspectorRef,
|
|
4815
|
+
latestMove: prev?.latestMove,
|
|
4816
|
+
latestResize: prev?.latestResize,
|
|
4817
|
+
changeCount: (prev?.changeCount ?? 0) + 1,
|
|
4818
|
+
lastUpdatedAt: now
|
|
4819
|
+
};
|
|
4820
|
+
return {
|
|
4821
|
+
orderedChanges: [...s.orderedChanges, event],
|
|
4822
|
+
nodeEditsByKey: { ...s.nodeEditsByKey, [nodeKey]: meta },
|
|
4823
|
+
undoneChanges: []
|
|
4824
|
+
};
|
|
4825
|
+
});
|
|
4826
|
+
},
|
|
4827
|
+
startExternalDrag: (component) => set({ externalDrag: component }),
|
|
4828
|
+
cancelExternalDrag: () => set({ externalDrag: null }),
|
|
4257
4829
|
undoLastChange: () => {
|
|
4258
4830
|
const { orderedChanges, undoneChanges } = get();
|
|
4259
4831
|
if (orderedChanges.length === 0) return null;
|
|
@@ -4279,7 +4851,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4279
4851
|
},
|
|
4280
4852
|
clearChanges: () => set({ orderedChanges: [], undoneChanges: [], nodeEditsByKey: {} }),
|
|
4281
4853
|
exportChangesForAI: () => {
|
|
4282
|
-
const { orderedChanges, nodeEditsByKey } = get();
|
|
4854
|
+
const { orderedChanges: rawChanges, nodeEditsByKey } = get();
|
|
4855
|
+
const orderedChanges = coalesceOrderedChanges(rawChanges);
|
|
4283
4856
|
const changesByFile = {};
|
|
4284
4857
|
for (const event of orderedChanges) {
|
|
4285
4858
|
const fileKey = event.inspectorRef?.relativePath ?? "__runtime__";
|
|
@@ -4293,180 +4866,127 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4293
4866
|
lines.push(` ${summarizeEditorChangeEvent(ev)}`);
|
|
4294
4867
|
}
|
|
4295
4868
|
}
|
|
4869
|
+
const diagnostics = mergeRuntimeArrangeDiagnostics(
|
|
4870
|
+
orderedChanges.map(
|
|
4871
|
+
(event) => event.kind === "move" ? event.diagnostics : null
|
|
4872
|
+
)
|
|
4873
|
+
);
|
|
4296
4874
|
return {
|
|
4297
4875
|
changesByFile,
|
|
4298
4876
|
finalSnapshot: { ...nodeEditsByKey },
|
|
4299
|
-
aiPromptContext: lines.join("\n")
|
|
4877
|
+
aiPromptContext: lines.join("\n"),
|
|
4878
|
+
...diagnostics ? { diagnostics } : {}
|
|
4300
4879
|
};
|
|
4301
4880
|
}
|
|
4302
4881
|
}));
|
|
4303
4882
|
|
|
4304
4883
|
// src/client/dnd/design-mode/DesignModeOverlay.tsx
|
|
4305
|
-
var
|
|
4884
|
+
var import_react17 = require("react");
|
|
4306
4885
|
|
|
4307
4886
|
// src/client/dnd/design-mode/useElementScanner.ts
|
|
4308
4887
|
var import_react6 = require("react");
|
|
4309
4888
|
|
|
4310
|
-
// src/client/dnd/design-mode/
|
|
4311
|
-
var
|
|
4312
|
-
var
|
|
4313
|
-
|
|
4314
|
-
|
|
4889
|
+
// src/client/dnd/design-mode/helpers.ts
|
|
4890
|
+
var DND_NODE_ID_ATTR = "data-dnd-node-id";
|
|
4891
|
+
var PAGE_EDGE_GUARD = 10;
|
|
4892
|
+
var HARD_PAGE_EDGE_GUARD = 4;
|
|
4893
|
+
var SAFE_ZONE_INSET = 8;
|
|
4894
|
+
function clamp(value, min, max) {
|
|
4895
|
+
return Math.max(min, Math.min(max, value));
|
|
4315
4896
|
}
|
|
4316
|
-
function
|
|
4317
|
-
|
|
4318
|
-
const tag = el.tagName.toLowerCase();
|
|
4319
|
-
if (STRUCTURAL_TAGS.has(tag)) return true;
|
|
4320
|
-
if (el.id === "root") return true;
|
|
4321
|
-
return tag === "main" && (el.parentElement === document.body || el.parentElement?.id === "root");
|
|
4897
|
+
function buildNodeSelector(nodeId) {
|
|
4898
|
+
return `[${DND_NODE_ID_ATTR}="${escapeCssAttrValue(nodeId)}"]`;
|
|
4322
4899
|
}
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4900
|
+
var LARGE_NODE_NEST_BLOCK_MIN_WIDTH = 520;
|
|
4901
|
+
var LARGE_NODE_NEST_BLOCK_MIN_HEIGHT = 260;
|
|
4902
|
+
var LARGE_NODE_NEST_BLOCK_MIN_AREA = 18e4;
|
|
4903
|
+
function isEligibleForDrag(sc) {
|
|
4904
|
+
const source = sc.eligibilitySource ?? "editor-meta";
|
|
4905
|
+
return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant";
|
|
4327
4906
|
}
|
|
4328
|
-
function
|
|
4329
|
-
return
|
|
4907
|
+
function isPointerInEdgeZone(px, py, guard) {
|
|
4908
|
+
return px <= guard || py <= guard || px >= window.innerWidth - guard || py >= window.innerHeight - guard;
|
|
4330
4909
|
}
|
|
4331
|
-
function
|
|
4332
|
-
|
|
4333
|
-
if (!container) return false;
|
|
4334
|
-
if (container.children.length < 2) return false;
|
|
4335
|
-
return !isStructuralContainer(containerId, nodeMap);
|
|
4910
|
+
function isPointerInPageEdgeZone(px, py) {
|
|
4911
|
+
return isPointerInEdgeZone(px, py, PAGE_EDGE_GUARD);
|
|
4336
4912
|
}
|
|
4337
|
-
function
|
|
4338
|
-
|
|
4339
|
-
for (const containerId of projection.containerIndex.keys()) {
|
|
4340
|
-
if (containerId === sourceContainerId) continue;
|
|
4341
|
-
if (isStructuralContainer(containerId, nodeMap)) blocked.add(containerId);
|
|
4342
|
-
}
|
|
4343
|
-
return blocked;
|
|
4913
|
+
function isPointerInHardPageEdgeZone(px, py) {
|
|
4914
|
+
return isPointerInEdgeZone(px, py, HARD_PAGE_EDGE_GUARD);
|
|
4344
4915
|
}
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
const
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
}
|
|
4356
|
-
return null;
|
|
4916
|
+
function resolveSafeZoneRect() {
|
|
4917
|
+
const root = document.getElementById("root");
|
|
4918
|
+
if (!root) return null;
|
|
4919
|
+
const rect = root.getBoundingClientRect();
|
|
4920
|
+
const left = rect.left + SAFE_ZONE_INSET;
|
|
4921
|
+
const top = rect.top + SAFE_ZONE_INSET;
|
|
4922
|
+
const right = rect.right - SAFE_ZONE_INSET;
|
|
4923
|
+
const bottom = rect.bottom - SAFE_ZONE_INSET;
|
|
4924
|
+
if (right <= left || bottom <= top) return null;
|
|
4925
|
+
return { left, top, right, bottom };
|
|
4357
4926
|
}
|
|
4358
|
-
function
|
|
4359
|
-
|
|
4927
|
+
function isPointerInSafeZone(px, py, safeZone) {
|
|
4928
|
+
if (!safeZone) return true;
|
|
4929
|
+
return px >= safeZone.left && px <= safeZone.right && py >= safeZone.top && py <= safeZone.bottom;
|
|
4360
4930
|
}
|
|
4361
|
-
function
|
|
4362
|
-
return
|
|
4931
|
+
function isPointerOutsideSafeZone(px, py, safeZone) {
|
|
4932
|
+
return !isPointerInSafeZone(px, py, safeZone);
|
|
4363
4933
|
}
|
|
4364
|
-
function
|
|
4365
|
-
|
|
4366
|
-
return meta.componentName[0] !== meta.componentName[0].toLowerCase();
|
|
4934
|
+
function isPointerBlocked(px, py, safeZone) {
|
|
4935
|
+
return isPointerInHardPageEdgeZone(px, py) || isPointerOutsideSafeZone(px, py, safeZone);
|
|
4367
4936
|
}
|
|
4368
|
-
function
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4937
|
+
function shouldBlockNestForLargeNode(w, h) {
|
|
4938
|
+
return w >= LARGE_NODE_NEST_BLOCK_MIN_WIDTH || h >= LARGE_NODE_NEST_BLOCK_MIN_HEIGHT || w * h >= LARGE_NODE_NEST_BLOCK_MIN_AREA;
|
|
4939
|
+
}
|
|
4940
|
+
function findScrollableAncestor(start, dx, dy) {
|
|
4941
|
+
let el = start;
|
|
4942
|
+
while (el && el !== document.body) {
|
|
4943
|
+
const cs = getComputedStyle(el);
|
|
4944
|
+
if (dy !== 0 && (cs.overflowY === "auto" || cs.overflowY === "scroll") && el.scrollHeight > el.clientHeight + 1) return el;
|
|
4945
|
+
if (dx !== 0 && (cs.overflowX === "auto" || cs.overflowX === "scroll") && el.scrollWidth > el.clientWidth + 1) return el;
|
|
4946
|
+
el = el.parentElement;
|
|
4372
4947
|
}
|
|
4373
|
-
return
|
|
4948
|
+
return null;
|
|
4374
4949
|
}
|
|
4375
|
-
function
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
if (child.hasAttribute("data-design-mode-ui")) return false;
|
|
4379
|
-
if (child.hasAttribute("data-design-mode-allow")) return false;
|
|
4380
|
-
return !shouldIgnoreAsVirtualRuntime(child);
|
|
4381
|
-
});
|
|
4950
|
+
function escapeCssAttrValue(value) {
|
|
4951
|
+
const esc = globalThis.CSS?.escape;
|
|
4952
|
+
return esc ? esc(value) : value.replace(/["\\]/g, "\\$&");
|
|
4382
4953
|
}
|
|
4383
|
-
function
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
if (tag === "script" || tag === "style" || tag === "noscript") return true;
|
|
4387
|
-
if (el instanceof SVGElement && !isRootSvg(el)) return true;
|
|
4388
|
-
return false;
|
|
4954
|
+
function isDesignModeUiElement(el) {
|
|
4955
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
4956
|
+
return el.hasAttribute("data-design-mode-ui") || !!el.closest("[data-design-mode-ui]");
|
|
4389
4957
|
}
|
|
4390
|
-
function
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
const
|
|
4394
|
-
const
|
|
4395
|
-
|
|
4396
|
-
directMetaCache.set(el, resolved);
|
|
4397
|
-
return resolved;
|
|
4958
|
+
function isElementScrollable(el) {
|
|
4959
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
4960
|
+
const cs = getComputedStyle(el);
|
|
4961
|
+
const overY = cs.overflowY;
|
|
4962
|
+
const overX = cs.overflowX;
|
|
4963
|
+
return (overY === "auto" || overY === "scroll") && el.scrollHeight > el.clientHeight || (overX === "auto" || overX === "scroll") && el.scrollWidth > el.clientWidth;
|
|
4398
4964
|
}
|
|
4399
|
-
function
|
|
4400
|
-
const
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
metaCache.set(el, meta);
|
|
4407
|
-
return meta;
|
|
4965
|
+
function resolveScrollableFromHitStack(stack) {
|
|
4966
|
+
for (const hit of stack) {
|
|
4967
|
+
if (isDesignModeUiElement(hit)) continue;
|
|
4968
|
+
let el = hit;
|
|
4969
|
+
while (el) {
|
|
4970
|
+
if (isElementScrollable(el)) return el;
|
|
4971
|
+
el = el.parentElement;
|
|
4408
4972
|
}
|
|
4409
|
-
fiber = fiber.return;
|
|
4410
4973
|
}
|
|
4411
|
-
metaCache.set(el, null);
|
|
4412
4974
|
return null;
|
|
4413
4975
|
}
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
}
|
|
4422
|
-
function resolveHostElementFromFiberChain(el) {
|
|
4423
|
-
if (shouldIgnoreAsVirtualRuntime(el)) return null;
|
|
4424
|
-
const directMeta = getDirectEditorMeta(el);
|
|
4425
|
-
const ownerMeta = directMeta ?? getEditorMeta(el);
|
|
4426
|
-
if (isPassthroughMeta(ownerMeta)) {
|
|
4427
|
-
const children = getCandidateChildren(el);
|
|
4428
|
-
if (children.length !== 1) return null;
|
|
4429
|
-
return children[0];
|
|
4430
|
-
}
|
|
4431
|
-
if (directMeta && !isWrapperMeta(directMeta)) return el;
|
|
4432
|
-
const MAX_STEPS = 10;
|
|
4433
|
-
const ownerNodeId = ownerMeta?.nodeId ?? null;
|
|
4434
|
-
let outermost = el;
|
|
4435
|
-
let parent = el.parentElement;
|
|
4436
|
-
for (let i = 0; i < MAX_STEPS; i += 1) {
|
|
4437
|
-
if (!parent || parent === document.body) break;
|
|
4438
|
-
if (shouldIgnoreAsVirtualRuntime(parent)) break;
|
|
4439
|
-
const parentMeta = getEditorMeta(parent);
|
|
4440
|
-
if (!parentMeta) break;
|
|
4441
|
-
if (ownerNodeId && parentMeta.nodeId !== ownerNodeId) break;
|
|
4442
|
-
if (isStructuralComponentName(parentMeta.componentName)) break;
|
|
4443
|
-
if (!isWrapperMeta(parentMeta)) break;
|
|
4444
|
-
if (isPassthroughMeta(parentMeta)) break;
|
|
4445
|
-
if (hasOwnTextContent(parent)) break;
|
|
4446
|
-
const children = getCandidateChildren(parent);
|
|
4447
|
-
if (children.length !== 1) break;
|
|
4448
|
-
outermost = parent;
|
|
4449
|
-
parent = parent.parentElement;
|
|
4450
|
-
}
|
|
4451
|
-
return outermost;
|
|
4452
|
-
}
|
|
4453
|
-
function resolveDragSurface(el) {
|
|
4454
|
-
const host = resolveHostElementFromFiberChain(el);
|
|
4455
|
-
if (!host) {
|
|
4456
|
-
return { host: null, metaOwner: null, kind: "direct-host" };
|
|
4976
|
+
var _undoParentNodeIdMap = /* @__PURE__ */ new WeakMap();
|
|
4977
|
+
var _undoParentNodeIdCounter = 0;
|
|
4978
|
+
function ensureParentNodeId(el) {
|
|
4979
|
+
const existing = el.getAttribute(DND_NODE_ID_ATTR);
|
|
4980
|
+
if (existing) return existing;
|
|
4981
|
+
if (!_undoParentNodeIdMap.has(el)) {
|
|
4982
|
+
_undoParentNodeIdMap.set(el, `dnd-parent:${++_undoParentNodeIdCounter}`);
|
|
4457
4983
|
}
|
|
4458
|
-
const
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
return {
|
|
4462
|
-
host,
|
|
4463
|
-
metaOwner,
|
|
4464
|
-
kind
|
|
4465
|
-
};
|
|
4984
|
+
const id = _undoParentNodeIdMap.get(el);
|
|
4985
|
+
el.setAttribute(DND_NODE_ID_ATTR, id);
|
|
4986
|
+
return id;
|
|
4466
4987
|
}
|
|
4467
4988
|
|
|
4468
4989
|
// src/client/dnd/design-mode/useElementScanner.ts
|
|
4469
|
-
var DND_NODE_ID_ATTR = "data-dnd-node-id";
|
|
4470
4990
|
function resolveContainerStrategy(el) {
|
|
4471
4991
|
const cs = getComputedStyle(el);
|
|
4472
4992
|
const d = cs.display;
|
|
@@ -4497,7 +5017,7 @@ function getRuntimeNodeId(el) {
|
|
|
4497
5017
|
}
|
|
4498
5018
|
function getEditorMetaNodeId(el) {
|
|
4499
5019
|
if (!(el instanceof HTMLElement)) return null;
|
|
4500
|
-
return
|
|
5020
|
+
return getDirectEditorMeta(el)?.nodeId ?? null;
|
|
4501
5021
|
}
|
|
4502
5022
|
function isInspectorEligible(el) {
|
|
4503
5023
|
if (getEditorMetaNodeId(el) !== null) return "editor-meta";
|
|
@@ -4521,7 +5041,7 @@ function inferEligibilityFromSortableParent(el) {
|
|
|
4521
5041
|
if (child.hasAttribute("data-design-mode-ui")) return false;
|
|
4522
5042
|
return !isRuntimeVisualInternal(child);
|
|
4523
5043
|
});
|
|
4524
|
-
if (siblingElements.length <
|
|
5044
|
+
if (siblingElements.length < 1) return null;
|
|
4525
5045
|
return "inferred-sortable-descendant";
|
|
4526
5046
|
}
|
|
4527
5047
|
function ensureUniqueNodeId(base, used) {
|
|
@@ -5075,7 +5595,15 @@ function buildProjection(elements, rectOverrides) {
|
|
|
5075
5595
|
}
|
|
5076
5596
|
const containerIndex = /* @__PURE__ */ new Map();
|
|
5077
5597
|
for (const node of nodeMap.values()) {
|
|
5078
|
-
if (node.children.length === 0)
|
|
5598
|
+
if (node.children.length === 0) {
|
|
5599
|
+
const scanInfo = elementIndex.get(node.id);
|
|
5600
|
+
const eligible = scanInfo?.editorMeta || scanInfo?.eligibilitySource === "force-allow";
|
|
5601
|
+
if (!eligible) continue;
|
|
5602
|
+
node.sortable = true;
|
|
5603
|
+
node.strategy = "vertical";
|
|
5604
|
+
containerIndex.set(node.id, node);
|
|
5605
|
+
continue;
|
|
5606
|
+
}
|
|
5079
5607
|
node.sortable = true;
|
|
5080
5608
|
const firstChild = elementIndex.get(node.children[0]);
|
|
5081
5609
|
node.strategy = firstChild?.containerStrategy ?? "vertical";
|
|
@@ -5144,33 +5672,27 @@ function buildSlotIndex(containerIndex, nodeMap) {
|
|
|
5144
5672
|
}
|
|
5145
5673
|
function buildVerticalSlotRect(children, nodeMap, cRect, i, n) {
|
|
5146
5674
|
const top = i === 0 ? cRect.top : nodeMap.get(children[i - 1])?.rect.bottom ?? cRect.top;
|
|
5147
|
-
const bottom = i === n ? cRect.bottom : nodeMap.get(children[i])?.rect.top ?? cRect.bottom;
|
|
5148
|
-
const height = Math.max(0, bottom - top);
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
width: cRect.width,
|
|
5157
|
-
height
|
|
5158
|
-
};
|
|
5675
|
+
const bottom = i === n ? cRect.bottom : nodeMap.get(children[i])?.rect.top ?? cRect.bottom;
|
|
5676
|
+
const height = Math.max(0, bottom - top);
|
|
5677
|
+
const prevRect = i > 0 ? nodeMap.get(children[i - 1])?.rect : null;
|
|
5678
|
+
const nextRect = i < n ? nodeMap.get(children[i])?.rect : null;
|
|
5679
|
+
const refRect = prevRect ?? nextRect;
|
|
5680
|
+
const left = refRect ? refRect.left : cRect.left;
|
|
5681
|
+
const right = refRect ? refRect.right : cRect.right;
|
|
5682
|
+
const width = Math.max(0, right - left);
|
|
5683
|
+
return { x: left, y: top, left, top, right, bottom: top + height, width, height };
|
|
5159
5684
|
}
|
|
5160
5685
|
function buildHorizontalSlotRect(children, nodeMap, cRect, i, n) {
|
|
5161
5686
|
const left = i === 0 ? cRect.left : nodeMap.get(children[i - 1])?.rect.right ?? cRect.left;
|
|
5162
5687
|
const right = i === n ? cRect.right : nodeMap.get(children[i])?.rect.left ?? cRect.right;
|
|
5163
5688
|
const width = Math.max(0, right - left);
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
width,
|
|
5172
|
-
height: cRect.height
|
|
5173
|
-
};
|
|
5689
|
+
const prevRect = i > 0 ? nodeMap.get(children[i - 1])?.rect : null;
|
|
5690
|
+
const nextRect = i < n ? nodeMap.get(children[i])?.rect : null;
|
|
5691
|
+
const refRect = prevRect ?? nextRect;
|
|
5692
|
+
const top = refRect ? refRect.top : cRect.top;
|
|
5693
|
+
const bottom = refRect ? refRect.bottom : cRect.bottom;
|
|
5694
|
+
const height = Math.max(0, bottom - top);
|
|
5695
|
+
return { x: left, y: top, left, top, right: left + width, bottom, width, height };
|
|
5174
5696
|
}
|
|
5175
5697
|
function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
|
|
5176
5698
|
const findRow = (childIdx) => rows.find((r) => childIdx >= r.startIdx && childIdx <= r.endIdx) ?? null;
|
|
@@ -5234,6 +5756,79 @@ function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
|
|
|
5234
5756
|
};
|
|
5235
5757
|
}
|
|
5236
5758
|
|
|
5759
|
+
// src/client/dnd/design-mode/history.ts
|
|
5760
|
+
function applyInsertCommand(command, direction, resolveNodeElement) {
|
|
5761
|
+
if (direction === "undo") {
|
|
5762
|
+
const el = resolveNodeElement(command.nodeId);
|
|
5763
|
+
if (el?.isConnected) el.remove();
|
|
5764
|
+
return true;
|
|
5765
|
+
}
|
|
5766
|
+
const container = resolveNodeElement(command.containerId);
|
|
5767
|
+
if (!container) return false;
|
|
5768
|
+
const existing = resolveNodeElement(command.nodeId);
|
|
5769
|
+
if (existing?.isConnected) return true;
|
|
5770
|
+
const template = document.createElement("template");
|
|
5771
|
+
template.innerHTML = command.html.trim();
|
|
5772
|
+
const newEl = template.content.firstElementChild;
|
|
5773
|
+
if (!newEl) return false;
|
|
5774
|
+
newEl.setAttribute("data-dnd-node-id", command.nodeId);
|
|
5775
|
+
newEl.setAttribute("data-dnd-force-allow", "");
|
|
5776
|
+
newEl.setAttribute("data-dnd-moved", "");
|
|
5777
|
+
const kids = Array.from(container.children).filter(
|
|
5778
|
+
(c) => c instanceof HTMLElement
|
|
5779
|
+
);
|
|
5780
|
+
container.insertBefore(newEl, kids[command.index] ?? null);
|
|
5781
|
+
return true;
|
|
5782
|
+
}
|
|
5783
|
+
var DEFAULT_LIMIT = 300;
|
|
5784
|
+
var DndCommandHistory = class {
|
|
5785
|
+
constructor(limit = DEFAULT_LIMIT) {
|
|
5786
|
+
this.limit = limit;
|
|
5787
|
+
__publicField(this, "undoStack", []);
|
|
5788
|
+
__publicField(this, "redoStack", []);
|
|
5789
|
+
}
|
|
5790
|
+
execute(command, apply) {
|
|
5791
|
+
const applied = apply(command, "redo");
|
|
5792
|
+
if (!applied) return false;
|
|
5793
|
+
this.undoStack.push(command);
|
|
5794
|
+
if (this.undoStack.length > this.limit) this.undoStack.shift();
|
|
5795
|
+
this.redoStack = [];
|
|
5796
|
+
return true;
|
|
5797
|
+
}
|
|
5798
|
+
undo(apply) {
|
|
5799
|
+
const command = this.undoStack.pop();
|
|
5800
|
+
if (!command) return false;
|
|
5801
|
+
const applied = apply(command, "undo");
|
|
5802
|
+
if (!applied) {
|
|
5803
|
+
this.undoStack.push(command);
|
|
5804
|
+
return false;
|
|
5805
|
+
}
|
|
5806
|
+
this.redoStack.push(command);
|
|
5807
|
+
return true;
|
|
5808
|
+
}
|
|
5809
|
+
redo(apply) {
|
|
5810
|
+
const command = this.redoStack.pop();
|
|
5811
|
+
if (!command) return false;
|
|
5812
|
+
const applied = apply(command, "redo");
|
|
5813
|
+
if (!applied) {
|
|
5814
|
+
this.redoStack.push(command);
|
|
5815
|
+
return false;
|
|
5816
|
+
}
|
|
5817
|
+
this.undoStack.push(command);
|
|
5818
|
+
return true;
|
|
5819
|
+
}
|
|
5820
|
+
clear() {
|
|
5821
|
+
this.undoStack = [];
|
|
5822
|
+
this.redoStack = [];
|
|
5823
|
+
}
|
|
5824
|
+
canUndo() {
|
|
5825
|
+
return this.undoStack.length > 0;
|
|
5826
|
+
}
|
|
5827
|
+
canRedo() {
|
|
5828
|
+
return this.redoStack.length > 0;
|
|
5829
|
+
}
|
|
5830
|
+
};
|
|
5831
|
+
|
|
5237
5832
|
// src/client/dnd/design-mode/resize.ts
|
|
5238
5833
|
function splitTopLevelSpaceSeparated(value) {
|
|
5239
5834
|
const tokens = [];
|
|
@@ -5265,9 +5860,6 @@ function parseSpanValue(value) {
|
|
|
5265
5860
|
const parsed = Number.parseInt(match[1], 10);
|
|
5266
5861
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
|
|
5267
5862
|
}
|
|
5268
|
-
function clamp(value, min, max) {
|
|
5269
|
-
return Math.max(min, Math.min(max, value));
|
|
5270
|
-
}
|
|
5271
5863
|
function resolveResizeTargetElement(selectedEl) {
|
|
5272
5864
|
const elementChildren = Array.from(selectedEl.children).filter(
|
|
5273
5865
|
(child2) => child2 instanceof HTMLElement
|
|
@@ -5348,100 +5940,6 @@ function applyStyleSnapshot(el, snapshot) {
|
|
|
5348
5940
|
}
|
|
5349
5941
|
}
|
|
5350
5942
|
|
|
5351
|
-
// src/client/dnd/design-mode/helpers.ts
|
|
5352
|
-
var DND_NODE_ID_ATTR2 = "data-dnd-node-id";
|
|
5353
|
-
var PAGE_EDGE_GUARD = 10;
|
|
5354
|
-
var HARD_PAGE_EDGE_GUARD = 4;
|
|
5355
|
-
var SAFE_ZONE_INSET = 8;
|
|
5356
|
-
var LARGE_NODE_NEST_BLOCK_MIN_WIDTH = 520;
|
|
5357
|
-
var LARGE_NODE_NEST_BLOCK_MIN_HEIGHT = 260;
|
|
5358
|
-
var LARGE_NODE_NEST_BLOCK_MIN_AREA = 18e4;
|
|
5359
|
-
function isEligibleForDrag(sc) {
|
|
5360
|
-
const source = sc.eligibilitySource ?? "editor-meta";
|
|
5361
|
-
return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant";
|
|
5362
|
-
}
|
|
5363
|
-
function isPointerInPageEdgeZone(px, py) {
|
|
5364
|
-
return px <= PAGE_EDGE_GUARD || py <= PAGE_EDGE_GUARD || px >= window.innerWidth - PAGE_EDGE_GUARD || py >= window.innerHeight - PAGE_EDGE_GUARD;
|
|
5365
|
-
}
|
|
5366
|
-
function isPointerInHardPageEdgeZone(px, py) {
|
|
5367
|
-
return px <= HARD_PAGE_EDGE_GUARD || py <= HARD_PAGE_EDGE_GUARD || px >= window.innerWidth - HARD_PAGE_EDGE_GUARD || py >= window.innerHeight - HARD_PAGE_EDGE_GUARD;
|
|
5368
|
-
}
|
|
5369
|
-
function resolveSafeZoneRect() {
|
|
5370
|
-
const root = document.getElementById("root");
|
|
5371
|
-
if (!root) return null;
|
|
5372
|
-
const rect = root.getBoundingClientRect();
|
|
5373
|
-
const left = rect.left + SAFE_ZONE_INSET;
|
|
5374
|
-
const top = rect.top + SAFE_ZONE_INSET;
|
|
5375
|
-
const right = rect.right - SAFE_ZONE_INSET;
|
|
5376
|
-
const bottom = rect.bottom - SAFE_ZONE_INSET;
|
|
5377
|
-
if (right <= left || bottom <= top) return null;
|
|
5378
|
-
return { left, top, right, bottom };
|
|
5379
|
-
}
|
|
5380
|
-
function isPointerInSafeZone(px, py, safeZone) {
|
|
5381
|
-
if (!safeZone) return true;
|
|
5382
|
-
return px >= safeZone.left && px <= safeZone.right && py >= safeZone.top && py <= safeZone.bottom;
|
|
5383
|
-
}
|
|
5384
|
-
function isPointerOutsideSafeZone(px, py, safeZone) {
|
|
5385
|
-
return !isPointerInSafeZone(px, py, safeZone);
|
|
5386
|
-
}
|
|
5387
|
-
function isPointerBlocked(px, py, safeZone) {
|
|
5388
|
-
return isPointerInHardPageEdgeZone(px, py) || isPointerOutsideSafeZone(px, py, safeZone);
|
|
5389
|
-
}
|
|
5390
|
-
function shouldBlockNestForLargeNode(w, h) {
|
|
5391
|
-
return w >= LARGE_NODE_NEST_BLOCK_MIN_WIDTH || h >= LARGE_NODE_NEST_BLOCK_MIN_HEIGHT || w * h >= LARGE_NODE_NEST_BLOCK_MIN_AREA;
|
|
5392
|
-
}
|
|
5393
|
-
function findScrollableAncestor(start, dx, dy) {
|
|
5394
|
-
let el = start;
|
|
5395
|
-
while (el && el !== document.body) {
|
|
5396
|
-
const cs = getComputedStyle(el);
|
|
5397
|
-
if (dy !== 0 && (cs.overflowY === "auto" || cs.overflowY === "scroll") && el.scrollHeight > el.clientHeight + 1) return el;
|
|
5398
|
-
if (dx !== 0 && (cs.overflowX === "auto" || cs.overflowX === "scroll") && el.scrollWidth > el.clientWidth + 1) return el;
|
|
5399
|
-
el = el.parentElement;
|
|
5400
|
-
}
|
|
5401
|
-
return null;
|
|
5402
|
-
}
|
|
5403
|
-
function escapeCssAttrValue(value) {
|
|
5404
|
-
const esc = globalThis.CSS?.escape;
|
|
5405
|
-
return esc ? esc(value) : value.replace(/["\\]/g, "\\$&");
|
|
5406
|
-
}
|
|
5407
|
-
function isDesignModeUiElement(el) {
|
|
5408
|
-
if (!(el instanceof HTMLElement)) return false;
|
|
5409
|
-
return el.hasAttribute("data-design-mode-ui") || !!el.closest("[data-design-mode-ui]");
|
|
5410
|
-
}
|
|
5411
|
-
function isElementScrollable(el) {
|
|
5412
|
-
if (!(el instanceof HTMLElement)) return false;
|
|
5413
|
-
const cs = getComputedStyle(el);
|
|
5414
|
-
const overY = cs.overflowY;
|
|
5415
|
-
const overX = cs.overflowX;
|
|
5416
|
-
return (overY === "auto" || overY === "scroll") && el.scrollHeight > el.clientHeight || (overX === "auto" || overX === "scroll") && el.scrollWidth > el.clientWidth;
|
|
5417
|
-
}
|
|
5418
|
-
function resolveScrollableFromHitStack(stack) {
|
|
5419
|
-
for (const hit of stack) {
|
|
5420
|
-
if (isDesignModeUiElement(hit)) continue;
|
|
5421
|
-
let el = hit;
|
|
5422
|
-
while (el) {
|
|
5423
|
-
if (isElementScrollable(el)) return el;
|
|
5424
|
-
el = el.parentElement;
|
|
5425
|
-
}
|
|
5426
|
-
}
|
|
5427
|
-
return null;
|
|
5428
|
-
}
|
|
5429
|
-
var _undoParentNodeIdMap = /* @__PURE__ */ new WeakMap();
|
|
5430
|
-
var _undoParentNodeIdCounter = 0;
|
|
5431
|
-
function ensureParentNodeId(el) {
|
|
5432
|
-
const existing = el.getAttribute(DND_NODE_ID_ATTR2);
|
|
5433
|
-
if (existing) return existing;
|
|
5434
|
-
if (!_undoParentNodeIdMap.has(el)) {
|
|
5435
|
-
_undoParentNodeIdMap.set(el, `dnd-parent:${++_undoParentNodeIdCounter}`);
|
|
5436
|
-
}
|
|
5437
|
-
const id = _undoParentNodeIdMap.get(el);
|
|
5438
|
-
el.setAttribute(DND_NODE_ID_ATTR2, id);
|
|
5439
|
-
return id;
|
|
5440
|
-
}
|
|
5441
|
-
function ensureElementNodeId(el) {
|
|
5442
|
-
return ensureParentNodeId(el);
|
|
5443
|
-
}
|
|
5444
|
-
|
|
5445
5943
|
// src/client/dnd/design-mode/drag-preview.tsx
|
|
5446
5944
|
var import_react9 = require("react");
|
|
5447
5945
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -5542,7 +6040,7 @@ function findNearestContainerId(nodeId, projection, nodeMap, allowStructuralFall
|
|
|
5542
6040
|
const parentId = node?.parentId ?? null;
|
|
5543
6041
|
if (!parentId) break;
|
|
5544
6042
|
const parentContainer = projection.containerIndex.get(parentId);
|
|
5545
|
-
if (parentContainer && parentContainer.children.length >=
|
|
6043
|
+
if (parentContainer && parentContainer.children.length >= 1) {
|
|
5546
6044
|
if (isValidLaneContainer(parentId, projection, nodeMap)) return parentId;
|
|
5547
6045
|
if (allowStructuralFallback && !structuralFallback) structuralFallback = parentId;
|
|
5548
6046
|
}
|
|
@@ -5627,12 +6125,6 @@ function findDirectChildUnderParent(child, parent) {
|
|
|
5627
6125
|
}
|
|
5628
6126
|
return null;
|
|
5629
6127
|
}
|
|
5630
|
-
function isContiguous(indices) {
|
|
5631
|
-
if (indices.length === 0) return false;
|
|
5632
|
-
const min = Math.min(...indices);
|
|
5633
|
-
const max = Math.max(...indices);
|
|
5634
|
-
return max - min + 1 === indices.length;
|
|
5635
|
-
}
|
|
5636
6128
|
function createPlacement(parentNodeId, laneContainerId, commitNodeId, beforeNodeId, afterNodeId, index) {
|
|
5637
6129
|
return {
|
|
5638
6130
|
parentNodeId,
|
|
@@ -5646,7 +6138,16 @@ function createPlacement(parentNodeId, laneContainerId, commitNodeId, beforeNode
|
|
|
5646
6138
|
function buildCommitLaneSnapshot(laneContainerId, projection, nodeMap) {
|
|
5647
6139
|
const lane = projection.containerIndex.get(laneContainerId);
|
|
5648
6140
|
const laneElement = nodeMap.get(laneContainerId)?.element ?? null;
|
|
5649
|
-
if (!lane ||
|
|
6141
|
+
if (!lane || !laneElement) return null;
|
|
6142
|
+
if (lane.children.length === 0) {
|
|
6143
|
+
return {
|
|
6144
|
+
laneContainerId,
|
|
6145
|
+
commitParentNodeId: ensureParentNodeId(laneElement),
|
|
6146
|
+
orderedCommitNodeIds: [],
|
|
6147
|
+
commitNodeByAnchorId: /* @__PURE__ */ new Map(),
|
|
6148
|
+
committable: true
|
|
6149
|
+
};
|
|
6150
|
+
}
|
|
5650
6151
|
const childElements = lane.children.map((childId) => nodeMap.get(childId)?.element ?? null).filter((el) => !!el);
|
|
5651
6152
|
if (childElements.length !== lane.children.length) return null;
|
|
5652
6153
|
const commitParent = findLowestCommonAncestor(childElements, laneElement);
|
|
@@ -5663,19 +6164,18 @@ function buildCommitLaneSnapshot(laneContainerId, projection, nodeMap) {
|
|
|
5663
6164
|
if (seenRoots.has(commitRoot)) return null;
|
|
5664
6165
|
seenRoots.add(commitRoot);
|
|
5665
6166
|
commitRoots.push(commitRoot);
|
|
5666
|
-
commitNodeByAnchorId.set(anchorNodeId,
|
|
6167
|
+
commitNodeByAnchorId.set(anchorNodeId, ensureParentNodeId(commitRoot));
|
|
5667
6168
|
}
|
|
5668
6169
|
const childList = Array.from(commitParent.children).filter(
|
|
5669
6170
|
(child) => child instanceof HTMLElement
|
|
5670
6171
|
);
|
|
5671
6172
|
const commitRootIndices = commitRoots.map((root) => childList.indexOf(root));
|
|
5672
6173
|
if (commitRootIndices.some((index) => index < 0)) return null;
|
|
5673
|
-
if (!isContiguous(commitRootIndices)) return null;
|
|
5674
6174
|
const domOrderedRoots = [...commitRoots].sort(
|
|
5675
6175
|
(a, b) => childList.indexOf(a) - childList.indexOf(b)
|
|
5676
6176
|
);
|
|
5677
|
-
const projectionOrderedIds = commitRoots.map((root) =>
|
|
5678
|
-
const domOrderedIds = domOrderedRoots.map((root) =>
|
|
6177
|
+
const projectionOrderedIds = commitRoots.map((root) => ensureParentNodeId(root));
|
|
6178
|
+
const domOrderedIds = domOrderedRoots.map((root) => ensureParentNodeId(root));
|
|
5679
6179
|
if (projectionOrderedIds.length !== domOrderedIds.length) return null;
|
|
5680
6180
|
if (projectionOrderedIds.some((id, index) => id !== domOrderedIds[index])) return null;
|
|
5681
6181
|
return {
|
|
@@ -5720,7 +6220,7 @@ function resolveAppendCommitPlacement(parentEl, commitNodeId, laneContainerId) {
|
|
|
5720
6220
|
const children = Array.from(parentEl.children).filter(
|
|
5721
6221
|
(child) => child instanceof HTMLElement
|
|
5722
6222
|
);
|
|
5723
|
-
const lastChild = children.length > 0 ?
|
|
6223
|
+
const lastChild = children.length > 0 ? ensureParentNodeId(children[children.length - 1]) : null;
|
|
5724
6224
|
return createPlacement(
|
|
5725
6225
|
ensureParentNodeId(parentEl),
|
|
5726
6226
|
laneContainerId,
|
|
@@ -5775,6 +6275,58 @@ function createDesignModeCollisionDetection(blockedContainerIds) {
|
|
|
5775
6275
|
};
|
|
5776
6276
|
}
|
|
5777
6277
|
|
|
6278
|
+
// src/client/dnd/design-mode/arrange-session.ts
|
|
6279
|
+
function serializeArrangeChange(event, index) {
|
|
6280
|
+
return {
|
|
6281
|
+
id: `${event.kind}:${event.operationId}:${index}`,
|
|
6282
|
+
kind: event.kind,
|
|
6283
|
+
operationId: event.operationId,
|
|
6284
|
+
commandType: event.kind === "move" ? event.commandType : void 0,
|
|
6285
|
+
nodeKey: event.nodeKey,
|
|
6286
|
+
nodeId: event.nodeId,
|
|
6287
|
+
inspectorRef: event.inspectorRef,
|
|
6288
|
+
selectedNodeKey: event.kind === "move" ? event.selectedNodeKey : void 0,
|
|
6289
|
+
selectedNodeId: event.kind === "move" ? event.selectedNodeId : void 0,
|
|
6290
|
+
selectedInspectorRef: event.kind === "move" ? event.selectedInspectorRef : void 0,
|
|
6291
|
+
anchorNodeKey: event.kind === "move" ? event.anchorNodeKey : void 0,
|
|
6292
|
+
anchorNodeId: event.kind === "move" ? event.anchorNodeId : void 0,
|
|
6293
|
+
container: event.kind === "move" ? event.container : void 0,
|
|
6294
|
+
beforeSibling: event.kind === "move" ? event.beforeSibling : void 0,
|
|
6295
|
+
afterSibling: event.kind === "move" ? event.afterSibling : void 0,
|
|
6296
|
+
sourceContainer: event.kind === "move" ? event.sourceContainer : void 0,
|
|
6297
|
+
sourceBeforeSibling: event.kind === "move" ? event.sourceBeforeSibling : void 0,
|
|
6298
|
+
sourceAfterSibling: event.kind === "move" ? event.sourceAfterSibling : void 0,
|
|
6299
|
+
diagnostics: event.kind === "move" ? event.diagnostics : void 0,
|
|
6300
|
+
// Insert-specific fields
|
|
6301
|
+
displayName: event.kind === "insert" ? event.displayName : void 0,
|
|
6302
|
+
html: event.kind === "insert" ? event.html : void 0,
|
|
6303
|
+
containerId: event.kind === "insert" ? event.containerId : void 0,
|
|
6304
|
+
containerNodeKey: event.kind === "insert" ? event.containerNodeKey : void 0,
|
|
6305
|
+
insertIndex: event.kind === "insert" ? event.index : void 0,
|
|
6306
|
+
summary: summarizeEditorChangeEvent(event),
|
|
6307
|
+
at: event.at
|
|
6308
|
+
};
|
|
6309
|
+
}
|
|
6310
|
+
function buildArrangeSessionSnapshot(params) {
|
|
6311
|
+
const { enabled, aiOutput } = params;
|
|
6312
|
+
const coalescedChanges = coalesceOrderedChanges(params.orderedChanges);
|
|
6313
|
+
const updatedAt = typeof params.updatedAt === "number" ? params.updatedAt : Date.now();
|
|
6314
|
+
return {
|
|
6315
|
+
mode: enabled ? "arrange" : "off",
|
|
6316
|
+
canUndo: params.orderedChanges.length > 0,
|
|
6317
|
+
changes: coalescedChanges.map(
|
|
6318
|
+
(event, index) => serializeArrangeChange(event, index)
|
|
6319
|
+
),
|
|
6320
|
+
diagnostics: aiOutput.diagnostics ?? null,
|
|
6321
|
+
output: {
|
|
6322
|
+
json: aiOutput,
|
|
6323
|
+
prompt: aiOutput.aiPromptContext,
|
|
6324
|
+
summary: coalescedChanges.length === 0 ? "No arrange changes recorded yet." : `${coalescedChanges.length} arrange change${coalescedChanges.length === 1 ? "" : "s"} recorded.`
|
|
6325
|
+
},
|
|
6326
|
+
updatedAt
|
|
6327
|
+
};
|
|
6328
|
+
}
|
|
6329
|
+
|
|
5778
6330
|
// src/client/dnd/design-mode/useDesignModeAutoScroll.ts
|
|
5779
6331
|
var import_react10 = require("react");
|
|
5780
6332
|
function edgeVelocity(distanceToEdge, zone, maxSpeed) {
|
|
@@ -5790,11 +6342,16 @@ function findScrollableAtPoint(x, y) {
|
|
|
5790
6342
|
return resolveScrollableFromHitStack(stack) ?? (document.scrollingElement ?? document.documentElement);
|
|
5791
6343
|
}
|
|
5792
6344
|
function getScrollerKey(el) {
|
|
5793
|
-
return el.getAttribute?.(
|
|
6345
|
+
return el.getAttribute?.(DND_NODE_ID_ATTR) ?? el.id ?? el.tagName.toLowerCase();
|
|
5794
6346
|
}
|
|
5795
6347
|
function pointerInsideRect(x, y, rect, inset = 0) {
|
|
5796
6348
|
return x >= rect.left - inset && x <= rect.right + inset && y >= rect.top - inset && y <= rect.bottom + inset;
|
|
5797
6349
|
}
|
|
6350
|
+
var AUTO_SCROLL_ZONE_PX = 120;
|
|
6351
|
+
var AUTO_SCROLL_MAX_SPEED = 24;
|
|
6352
|
+
var SCROLLER_RECT_RECALC_INTERVAL = 8;
|
|
6353
|
+
var SCROLLER_SWITCH_FRAMES = 3;
|
|
6354
|
+
var SCROLLER_EDGE_HYSTERESIS_PX = 18;
|
|
5798
6355
|
function useDesignModeAutoScroll({
|
|
5799
6356
|
active,
|
|
5800
6357
|
mouseRef,
|
|
@@ -5803,11 +6360,6 @@ function useDesignModeAutoScroll({
|
|
|
5803
6360
|
}) {
|
|
5804
6361
|
(0, import_react10.useEffect)(() => {
|
|
5805
6362
|
if (!active) return;
|
|
5806
|
-
const ZONE = 120;
|
|
5807
|
-
const MAX = 24;
|
|
5808
|
-
const RECALC_INTERVAL = 8;
|
|
5809
|
-
const SWITCH_FRAMES = 3;
|
|
5810
|
-
const SCROLLER_EDGE_HYSTERESIS = 18;
|
|
5811
6363
|
let scrollEl = findScrollableAtPoint(mouseRef.current.x, mouseRef.current.y);
|
|
5812
6364
|
let cachedRect = scrollEl.getBoundingClientRect();
|
|
5813
6365
|
let rectAge = 0;
|
|
@@ -5815,17 +6367,17 @@ function useDesignModeAutoScroll({
|
|
|
5815
6367
|
const tick = () => {
|
|
5816
6368
|
const { x, y } = mouseRef.current;
|
|
5817
6369
|
const safeZone = safeZoneRef.current;
|
|
5818
|
-
if (++rectAge >
|
|
6370
|
+
if (++rectAge > SCROLLER_RECT_RECALC_INTERVAL) {
|
|
5819
6371
|
const candidate = findScrollableAtPoint(x, y);
|
|
5820
6372
|
const candidateKey = getScrollerKey(candidate);
|
|
5821
6373
|
const currentKey = getScrollerKey(scrollEl);
|
|
5822
6374
|
const currentRect = scrollEl.getBoundingClientRect();
|
|
5823
|
-
if (candidateKey !== currentKey && !pointerInsideRect(x, y, currentRect,
|
|
6375
|
+
if (candidateKey !== currentKey && !pointerInsideRect(x, y, currentRect, SCROLLER_EDGE_HYSTERESIS_PX)) {
|
|
5824
6376
|
const pendingKey = autoScrollStateRef.current.pendingScrollerKey;
|
|
5825
6377
|
const pendingFrames = pendingKey === candidateKey ? (autoScrollStateRef.current.pendingFrames ?? 0) + 1 : 1;
|
|
5826
6378
|
autoScrollStateRef.current.pendingScrollerKey = candidateKey;
|
|
5827
6379
|
autoScrollStateRef.current.pendingFrames = pendingFrames;
|
|
5828
|
-
if (pendingFrames >=
|
|
6380
|
+
if (pendingFrames >= SCROLLER_SWITCH_FRAMES) {
|
|
5829
6381
|
scrollEl = candidate;
|
|
5830
6382
|
cachedRect = candidate.getBoundingClientRect();
|
|
5831
6383
|
autoScrollStateRef.current.pendingScrollerKey = null;
|
|
@@ -5834,98 +6386,52 @@ function useDesignModeAutoScroll({
|
|
|
5834
6386
|
} else {
|
|
5835
6387
|
scrollEl = candidateKey === currentKey ? scrollEl : candidate;
|
|
5836
6388
|
cachedRect = scrollEl.getBoundingClientRect();
|
|
5837
|
-
autoScrollStateRef.current.pendingScrollerKey = null;
|
|
5838
|
-
autoScrollStateRef.current.pendingFrames = 0;
|
|
5839
|
-
}
|
|
5840
|
-
rectAge = 0;
|
|
5841
|
-
}
|
|
5842
|
-
if (isPointerInPageEdgeZone(x, y) || isPointerOutsideSafeZone(x, y, safeZone)) {
|
|
5843
|
-
autoScrollStateRef.current = {
|
|
5844
|
-
...autoScrollStateRef.current,
|
|
5845
|
-
scrollerKey: null,
|
|
5846
|
-
vx: 0,
|
|
5847
|
-
vy: 0
|
|
5848
|
-
};
|
|
5849
|
-
raf = requestAnimationFrame(tick);
|
|
5850
|
-
return;
|
|
5851
|
-
}
|
|
5852
|
-
const dTop = y - cachedRect.top;
|
|
5853
|
-
const dBot = cachedRect.bottom - y;
|
|
5854
|
-
let dy = 0;
|
|
5855
|
-
if (dTop > 0 && dTop <
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
if (
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
}
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
var
|
|
5883
|
-
constructor(limit = DEFAULT_LIMIT) {
|
|
5884
|
-
this.limit = limit;
|
|
5885
|
-
__publicField(this, "undoStack", []);
|
|
5886
|
-
__publicField(this, "redoStack", []);
|
|
5887
|
-
}
|
|
5888
|
-
execute(command, apply) {
|
|
5889
|
-
const applied = apply(command, "redo");
|
|
5890
|
-
if (!applied) return false;
|
|
5891
|
-
this.undoStack.push(command);
|
|
5892
|
-
if (this.undoStack.length > this.limit) this.undoStack.shift();
|
|
5893
|
-
this.redoStack = [];
|
|
5894
|
-
return true;
|
|
5895
|
-
}
|
|
5896
|
-
undo(apply) {
|
|
5897
|
-
const command = this.undoStack.pop();
|
|
5898
|
-
if (!command) return false;
|
|
5899
|
-
const applied = apply(command, "undo");
|
|
5900
|
-
if (!applied) {
|
|
5901
|
-
this.undoStack.push(command);
|
|
5902
|
-
return false;
|
|
5903
|
-
}
|
|
5904
|
-
this.redoStack.push(command);
|
|
5905
|
-
return true;
|
|
5906
|
-
}
|
|
5907
|
-
redo(apply) {
|
|
5908
|
-
const command = this.redoStack.pop();
|
|
5909
|
-
if (!command) return false;
|
|
5910
|
-
const applied = apply(command, "redo");
|
|
5911
|
-
if (!applied) {
|
|
5912
|
-
this.redoStack.push(command);
|
|
5913
|
-
return false;
|
|
5914
|
-
}
|
|
5915
|
-
this.undoStack.push(command);
|
|
5916
|
-
return true;
|
|
5917
|
-
}
|
|
5918
|
-
clear() {
|
|
5919
|
-
this.undoStack = [];
|
|
5920
|
-
this.redoStack = [];
|
|
5921
|
-
}
|
|
5922
|
-
canUndo() {
|
|
5923
|
-
return this.undoStack.length > 0;
|
|
5924
|
-
}
|
|
5925
|
-
canRedo() {
|
|
5926
|
-
return this.redoStack.length > 0;
|
|
5927
|
-
}
|
|
5928
|
-
};
|
|
6389
|
+
autoScrollStateRef.current.pendingScrollerKey = null;
|
|
6390
|
+
autoScrollStateRef.current.pendingFrames = 0;
|
|
6391
|
+
}
|
|
6392
|
+
rectAge = 0;
|
|
6393
|
+
}
|
|
6394
|
+
if (isPointerInPageEdgeZone(x, y) || isPointerOutsideSafeZone(x, y, safeZone)) {
|
|
6395
|
+
autoScrollStateRef.current = {
|
|
6396
|
+
...autoScrollStateRef.current,
|
|
6397
|
+
scrollerKey: null,
|
|
6398
|
+
vx: 0,
|
|
6399
|
+
vy: 0
|
|
6400
|
+
};
|
|
6401
|
+
raf = requestAnimationFrame(tick);
|
|
6402
|
+
return;
|
|
6403
|
+
}
|
|
6404
|
+
const dTop = y - cachedRect.top;
|
|
6405
|
+
const dBot = cachedRect.bottom - y;
|
|
6406
|
+
let dy = 0;
|
|
6407
|
+
if (dTop > 0 && dTop < AUTO_SCROLL_ZONE_PX)
|
|
6408
|
+
dy = -edgeVelocity(dTop, AUTO_SCROLL_ZONE_PX, AUTO_SCROLL_MAX_SPEED);
|
|
6409
|
+
else if (dBot > 0 && dBot < AUTO_SCROLL_ZONE_PX)
|
|
6410
|
+
dy = edgeVelocity(dBot, AUTO_SCROLL_ZONE_PX, AUTO_SCROLL_MAX_SPEED);
|
|
6411
|
+
const dLeft = x - cachedRect.left;
|
|
6412
|
+
const dRight = cachedRect.right - x;
|
|
6413
|
+
let dx = 0;
|
|
6414
|
+
if (dLeft > 0 && dLeft < AUTO_SCROLL_ZONE_PX)
|
|
6415
|
+
dx = -edgeVelocity(dLeft, AUTO_SCROLL_ZONE_PX, AUTO_SCROLL_MAX_SPEED);
|
|
6416
|
+
else if (dRight > 0 && dRight < AUTO_SCROLL_ZONE_PX)
|
|
6417
|
+
dx = edgeVelocity(dRight, AUTO_SCROLL_ZONE_PX, AUTO_SCROLL_MAX_SPEED);
|
|
6418
|
+
if (dy !== 0) scrollEl.scrollTop += dy;
|
|
6419
|
+
if (dx !== 0) scrollEl.scrollLeft += dx;
|
|
6420
|
+
autoScrollStateRef.current = {
|
|
6421
|
+
...autoScrollStateRef.current,
|
|
6422
|
+
scrollerKey: getScrollerKey(scrollEl),
|
|
6423
|
+
vx: dx,
|
|
6424
|
+
vy: dy
|
|
6425
|
+
};
|
|
6426
|
+
raf = requestAnimationFrame(tick);
|
|
6427
|
+
};
|
|
6428
|
+
raf = requestAnimationFrame(tick);
|
|
6429
|
+
return () => cancelAnimationFrame(raf);
|
|
6430
|
+
}, [active, autoScrollStateRef, mouseRef, safeZoneRef]);
|
|
6431
|
+
}
|
|
6432
|
+
|
|
6433
|
+
// src/client/dnd/design-mode/useOverlayRefs.ts
|
|
6434
|
+
var import_react11 = require("react");
|
|
5929
6435
|
|
|
5930
6436
|
// src/client/dnd/design-mode/sortable-preview-animator.ts
|
|
5931
6437
|
function isIdentityTransform(transform) {
|
|
@@ -6139,43 +6645,6 @@ function useHoverDetection({
|
|
|
6139
6645
|
// src/client/dnd/design-mode/useDragVisualLoop.ts
|
|
6140
6646
|
var import_react13 = require("react");
|
|
6141
6647
|
|
|
6142
|
-
// src/client/dnd/design-mode/drag-lock.ts
|
|
6143
|
-
var MIN_UNLOCK_MARGIN = 32;
|
|
6144
|
-
var MAX_UNLOCK_MARGIN = 72;
|
|
6145
|
-
var MIN_UNLOCK_DWELL_MS = 170;
|
|
6146
|
-
var MAX_UNLOCK_DWELL_MS = 300;
|
|
6147
|
-
function clamp2(value, min, max) {
|
|
6148
|
-
return Math.min(max, Math.max(min, value));
|
|
6149
|
-
}
|
|
6150
|
-
function resolveCrossUnlockParams(rect) {
|
|
6151
|
-
const width = Math.max(0, rect.right - rect.left);
|
|
6152
|
-
const height = Math.max(0, rect.bottom - rect.top);
|
|
6153
|
-
const shortest = Math.max(1, Math.min(width, height));
|
|
6154
|
-
const margin = Math.round(clamp2(shortest * 0.14, MIN_UNLOCK_MARGIN, MAX_UNLOCK_MARGIN));
|
|
6155
|
-
const dwellMs = Math.round(clamp2(shortest * 0.7, MIN_UNLOCK_DWELL_MS, MAX_UNLOCK_DWELL_MS));
|
|
6156
|
-
return { margin, dwellMs };
|
|
6157
|
-
}
|
|
6158
|
-
function checkCrossUnlock(lock, adjustedPx, adjustedPy, lockRect, now, margin, dwellMs, graceMs) {
|
|
6159
|
-
if (lock.isCrossUnlocked) {
|
|
6160
|
-
if (lock.unlockUntilTs !== null && now < lock.unlockUntilTs) return lock;
|
|
6161
|
-
return lock;
|
|
6162
|
-
}
|
|
6163
|
-
const outsideBand = adjustedPx < lockRect.left - margin || adjustedPx > lockRect.right + margin || adjustedPy < lockRect.top - margin || adjustedPy > lockRect.bottom + margin;
|
|
6164
|
-
if (!outsideBand) {
|
|
6165
|
-
return lock.exitSince !== null ? { ...lock, exitSince: null } : lock;
|
|
6166
|
-
}
|
|
6167
|
-
const exitSince = lock.exitSince ?? now;
|
|
6168
|
-
if (now - exitSince >= dwellMs) {
|
|
6169
|
-
return {
|
|
6170
|
-
containerId: lock.containerId,
|
|
6171
|
-
isCrossUnlocked: true,
|
|
6172
|
-
exitSince,
|
|
6173
|
-
unlockUntilTs: now + graceMs
|
|
6174
|
-
};
|
|
6175
|
-
}
|
|
6176
|
-
return lock.exitSince !== null ? lock : { ...lock, exitSince: now };
|
|
6177
|
-
}
|
|
6178
|
-
|
|
6179
6648
|
// src/client/dnd/design-mode/quadtree.ts
|
|
6180
6649
|
function overlaps(a, b) {
|
|
6181
6650
|
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
|
|
@@ -6185,6 +6654,7 @@ function fitsInside(outer, inner) {
|
|
|
6185
6654
|
}
|
|
6186
6655
|
var CAPACITY = 8;
|
|
6187
6656
|
var MAX_DEPTH2 = 8;
|
|
6657
|
+
var ROOT_BOUNDS_PAD = 100;
|
|
6188
6658
|
var QTNode = class _QTNode {
|
|
6189
6659
|
constructor(bounds, depth = 0) {
|
|
6190
6660
|
__publicField(this, "bounds");
|
|
@@ -6282,12 +6752,11 @@ var Quadtree = class _Quadtree {
|
|
|
6282
6752
|
if (r.right > maxX) maxX = r.right;
|
|
6283
6753
|
if (r.bottom > maxY) maxY = r.bottom;
|
|
6284
6754
|
}
|
|
6285
|
-
const PAD = 100;
|
|
6286
6755
|
const root = new QTNode({
|
|
6287
|
-
x: minX -
|
|
6288
|
-
y: minY -
|
|
6289
|
-
w: maxX - minX + 2 *
|
|
6290
|
-
h: maxY - minY + 2 *
|
|
6756
|
+
x: minX - ROOT_BOUNDS_PAD,
|
|
6757
|
+
y: minY - ROOT_BOUNDS_PAD,
|
|
6758
|
+
w: maxX - minX + 2 * ROOT_BOUNDS_PAD,
|
|
6759
|
+
h: maxY - minY + 2 * ROOT_BOUNDS_PAD
|
|
6291
6760
|
});
|
|
6292
6761
|
for (const [id, r] of rects) {
|
|
6293
6762
|
if (r.width > 0 && r.height > 0) {
|
|
@@ -6389,9 +6858,9 @@ function getSlotQueryRadius() {
|
|
|
6389
6858
|
const vh = window.innerHeight;
|
|
6390
6859
|
return Math.min(500, Math.max(100, Math.max(vw, vh) * 0.2));
|
|
6391
6860
|
}
|
|
6392
|
-
var NEST_EDGE_FRACTION = 0.
|
|
6393
|
-
var ORIGIN_RETURN_BAND_PX =
|
|
6394
|
-
var LAST_CONTAINER_REENTRY_SLOP_PX =
|
|
6861
|
+
var NEST_EDGE_FRACTION = 0.2;
|
|
6862
|
+
var ORIGIN_RETURN_BAND_PX = 24;
|
|
6863
|
+
var LAST_CONTAINER_REENTRY_SLOP_PX = 16;
|
|
6395
6864
|
var ROW_OVERLAP_TOLERANCE_PX = 1;
|
|
6396
6865
|
function normalizeContainerSet(containers) {
|
|
6397
6866
|
if (!containers) return null;
|
|
@@ -6469,8 +6938,6 @@ var DragIntentEngine = class {
|
|
|
6469
6938
|
// Pre-computed set of slot IDs that would produce no movement for the active item.
|
|
6470
6939
|
__publicField(this, "noOpSlotIds");
|
|
6471
6940
|
__publicField(this, "originContainerId");
|
|
6472
|
-
__publicField(this, "laneRootContainerId");
|
|
6473
|
-
__publicField(this, "laneParentId");
|
|
6474
6941
|
__publicField(this, "laneAllowedContainers");
|
|
6475
6942
|
__publicField(this, "blockedContainerIds");
|
|
6476
6943
|
__publicField(this, "targetPlane", "lane");
|
|
@@ -6482,8 +6949,6 @@ var DragIntentEngine = class {
|
|
|
6482
6949
|
this.queryRadius = getSlotQueryRadius();
|
|
6483
6950
|
this.slotsByContainer = buildSlotsByContainer(projection.slotIndex);
|
|
6484
6951
|
this.originContainerId = this.getNodeParentContainerId(activeId);
|
|
6485
|
-
this.laneRootContainerId = options?.laneRootContainerId ?? this.originContainerId;
|
|
6486
|
-
this.laneParentId = this.laneRootContainerId ? this.containerIndex.get(this.laneRootContainerId)?.parentId ?? null : null;
|
|
6487
6952
|
this.laneAllowedContainers = normalizeContainerSet(options?.laneAllowedContainers);
|
|
6488
6953
|
this.blockedContainerIds = normalizeContainerSet(options?.blockedContainerIds);
|
|
6489
6954
|
const noOpSlotIds = /* @__PURE__ */ new Set();
|
|
@@ -6515,10 +6980,6 @@ var DragIntentEngine = class {
|
|
|
6515
6980
|
setTargetPlane(plane) {
|
|
6516
6981
|
this.targetPlane = plane;
|
|
6517
6982
|
}
|
|
6518
|
-
setLaneAllowedContainers(containers) {
|
|
6519
|
-
this.laneAllowedContainers = normalizeContainerSet(containers);
|
|
6520
|
-
this.reset();
|
|
6521
|
-
}
|
|
6522
6983
|
getTargetPlane() {
|
|
6523
6984
|
return this.targetPlane;
|
|
6524
6985
|
}
|
|
@@ -6617,7 +7078,7 @@ var DragIntentEngine = class {
|
|
|
6617
7078
|
if (this.isInvalidDropContainer(pointerContainerId)) return null;
|
|
6618
7079
|
for (const childId of container.children) {
|
|
6619
7080
|
if (childId === this.activeId) continue;
|
|
6620
|
-
if (this.
|
|
7081
|
+
if (this.isInvalidDropContainer(childId)) continue;
|
|
6621
7082
|
const childNode = this.getNodeRect(childId);
|
|
6622
7083
|
if (!childNode) continue;
|
|
6623
7084
|
if (!pointInRect(px, py, childNode)) continue;
|
|
@@ -6642,9 +7103,16 @@ var DragIntentEngine = class {
|
|
|
6642
7103
|
if (laneLock && !this.isLaneContainer(id)) continue;
|
|
6643
7104
|
if (!pointInRect(px, py, node.rect)) continue;
|
|
6644
7105
|
if (this.hasUsableSlots(id) === false) continue;
|
|
6645
|
-
|
|
7106
|
+
const r = node.rect;
|
|
7107
|
+
const edgeDistX = Math.min(px - r.left, r.right - px);
|
|
7108
|
+
const edgeDistY = Math.min(py - r.top, r.bottom - py);
|
|
7109
|
+
const minDim = Math.min(r.width, r.height);
|
|
7110
|
+
const edgeFraction = Math.min(edgeDistX, edgeDistY) / Math.max(1, minDim);
|
|
7111
|
+
const edgePenalty = edgeFraction < 0.1 ? 1 : 0;
|
|
7112
|
+
pointerContainers.push({ id, depth: node.depth, area: node.rect.width * node.rect.height, edgePenalty });
|
|
6646
7113
|
}
|
|
6647
7114
|
pointerContainers.sort((a, b) => {
|
|
7115
|
+
if (a.edgePenalty !== b.edgePenalty) return a.edgePenalty - b.edgePenalty;
|
|
6648
7116
|
if (b.depth !== a.depth) return b.depth - a.depth;
|
|
6649
7117
|
return a.area - b.area;
|
|
6650
7118
|
});
|
|
@@ -6657,7 +7125,9 @@ var DragIntentEngine = class {
|
|
|
6657
7125
|
}
|
|
6658
7126
|
if (this.originContainerId && this.originContainerId !== pointerContainerId && !this.isInvalidDropContainer(this.originContainerId) && !this.isBlockedContainer(this.originContainerId) && (!laneLock || this.isLaneContainer(this.originContainerId)) && this.hasUsableSlots(this.originContainerId)) {
|
|
6659
7127
|
const originNode = this.containerIndex.get(this.originContainerId);
|
|
6660
|
-
|
|
7128
|
+
const currentNode = pointerContainerId ? this.containerIndex.get(pointerContainerId) : null;
|
|
7129
|
+
const originIsDeeper = originNode && (!currentNode || originNode.depth >= currentNode.depth);
|
|
7130
|
+
if (originIsDeeper && originNode && pointInExpandedRect(px, py, originNode.rect, ORIGIN_RETURN_BAND_PX)) {
|
|
6661
7131
|
pointerContainerId = this.originContainerId;
|
|
6662
7132
|
}
|
|
6663
7133
|
}
|
|
@@ -6724,8 +7194,13 @@ var DragIntentEngine = class {
|
|
|
6724
7194
|
}
|
|
6725
7195
|
return n;
|
|
6726
7196
|
}
|
|
7197
|
+
const SLOT_ZONE_PX = 30;
|
|
6727
7198
|
for (const child of childRects) {
|
|
6728
7199
|
const midY = child.rect.top + child.rect.height / 2;
|
|
7200
|
+
const clampedTop = Math.max(child.rect.top, midY - SLOT_ZONE_PX);
|
|
7201
|
+
if (py < clampedTop) return child.index;
|
|
7202
|
+
const clampedBottom = Math.min(child.rect.bottom, midY + SLOT_ZONE_PX);
|
|
7203
|
+
if (py > clampedBottom) continue;
|
|
6729
7204
|
if (py < midY) return child.index;
|
|
6730
7205
|
}
|
|
6731
7206
|
return n;
|
|
@@ -6794,15 +7269,14 @@ var DragIntentEngine = class {
|
|
|
6794
7269
|
hasUsableSlots(containerId) {
|
|
6795
7270
|
const filtered = this.getContainerSlots(containerId);
|
|
6796
7271
|
if (filtered.length > 0) return true;
|
|
6797
|
-
|
|
7272
|
+
const raw = this.slotsByContainer.get(containerId) ?? [];
|
|
7273
|
+
if (raw.length === 0) return false;
|
|
7274
|
+
const container = this.containerIndex.get(containerId);
|
|
7275
|
+
return !container || container.children.length <= 1;
|
|
6798
7276
|
}
|
|
6799
7277
|
isLaneContainer(containerId) {
|
|
6800
7278
|
if (this.laneAllowedContainers) return this.laneAllowedContainers.has(containerId);
|
|
6801
|
-
|
|
6802
|
-
if (containerId === this.laneRootContainerId) return true;
|
|
6803
|
-
const node = this.containerIndex.get(containerId);
|
|
6804
|
-
if (!node) return false;
|
|
6805
|
-
return node.parentId === this.laneParentId;
|
|
7279
|
+
return true;
|
|
6806
7280
|
}
|
|
6807
7281
|
isBlockedContainer(containerId) {
|
|
6808
7282
|
return this.blockedContainerIds?.has(containerId) ?? false;
|
|
@@ -6813,9 +7287,11 @@ function createDragIntentEngine(projection, activeId, options) {
|
|
|
6813
7287
|
}
|
|
6814
7288
|
|
|
6815
7289
|
// src/client/dnd/design-mode/drop-line.ts
|
|
7290
|
+
var DROP_LINE_THICKNESS_PX = 2;
|
|
7291
|
+
var DROP_LINE_MIN_LENGTH_PX = 40;
|
|
6816
7292
|
function slotDropLine(slot, container, projectionTree, sdx, sdy) {
|
|
6817
|
-
const T =
|
|
6818
|
-
const MIN =
|
|
7293
|
+
const T = DROP_LINE_THICKNESS_PX;
|
|
7294
|
+
const MIN = DROP_LINE_MIN_LENGTH_PX;
|
|
6819
7295
|
const bp = computeSlotBoundaryPoint(slot, container, projectionTree);
|
|
6820
7296
|
if (container.strategy === "horizontal") {
|
|
6821
7297
|
return {
|
|
@@ -6855,9 +7331,6 @@ function slotDropLine(slot, container, projectionTree, sdx, sdy) {
|
|
|
6855
7331
|
}
|
|
6856
7332
|
|
|
6857
7333
|
// src/client/dnd/design-mode/preview-layout.ts
|
|
6858
|
-
function clampIndex(index, min, max) {
|
|
6859
|
-
return Math.max(min, Math.min(index, max));
|
|
6860
|
-
}
|
|
6861
7334
|
function getContainerChildren(projection, containerId) {
|
|
6862
7335
|
return [...projection.containerIndex.get(containerId)?.children ?? []];
|
|
6863
7336
|
}
|
|
@@ -6977,7 +7450,7 @@ function buildPreviewLayout({
|
|
|
6977
7450
|
const originalItemIds = getContainerChildren(projection, containerId);
|
|
6978
7451
|
const activeIndex = originalItemIds.indexOf(anchorNodeId);
|
|
6979
7452
|
if (activeIndex < 0) return null;
|
|
6980
|
-
const overIndex =
|
|
7453
|
+
const overIndex = clamp(targetIndex, 0, Math.max(0, originalItemIds.length - 1));
|
|
6981
7454
|
const previewItemIds = arrayMove(originalItemIds, activeIndex, overIndex);
|
|
6982
7455
|
const strategy = getContainerStrategy(projection, containerId);
|
|
6983
7456
|
containers.set(containerId, {
|
|
@@ -7017,7 +7490,7 @@ function buildPreviewLayout({
|
|
|
7017
7490
|
activePreviewContainers.add(sourceContainerId);
|
|
7018
7491
|
const targetOriginalItemIds = targetChildren.filter((id) => id !== anchorNodeId);
|
|
7019
7492
|
const targetPreviewItemIds = [...targetOriginalItemIds];
|
|
7020
|
-
const targetOverIndex =
|
|
7493
|
+
const targetOverIndex = clamp(targetIndex, 0, targetOriginalItemIds.length);
|
|
7021
7494
|
targetPreviewItemIds.splice(targetOverIndex, 0, anchorNodeId);
|
|
7022
7495
|
const targetStrategy = getContainerStrategy(projection, targetContainerId);
|
|
7023
7496
|
const targetStrategyItemIds = [...targetOriginalItemIds, anchorNodeId];
|
|
@@ -7049,9 +7522,8 @@ function buildPreviewLayout({
|
|
|
7049
7522
|
}
|
|
7050
7523
|
|
|
7051
7524
|
// src/client/dnd/design-mode/useDragVisualLoop.ts
|
|
7052
|
-
var CONTAINER_SWITCH_HYSTERESIS =
|
|
7053
|
-
var
|
|
7054
|
-
var SMALL_NODE_NEST_DWELL_MS = 180;
|
|
7525
|
+
var CONTAINER_SWITCH_HYSTERESIS = 12;
|
|
7526
|
+
var SMALL_NODE_NEST_DWELL_MS = 100;
|
|
7055
7527
|
var LARGE_NODE_NEST_DWELL_MS = 320;
|
|
7056
7528
|
function useDragVisualLoop({
|
|
7057
7529
|
activeDrag,
|
|
@@ -7100,33 +7572,12 @@ function useDragVisualLoop({
|
|
|
7100
7572
|
const scrollDy = window.scrollY - snapshot.scroll.y;
|
|
7101
7573
|
const adjustedPx = px + scrollDx;
|
|
7102
7574
|
const adjustedPy = py + scrollDy;
|
|
7103
|
-
const lockContainer = refs.lockRef.current.containerId ? refs.projectionRef.current.containerIndex.get(refs.lockRef.current.containerId) ?? null : null;
|
|
7104
|
-
if (!refs.lockRef.current.isCrossUnlocked && lockContainer) {
|
|
7105
|
-
const { margin, dwellMs } = resolveCrossUnlockParams(lockContainer.rect);
|
|
7106
|
-
const nextLock = checkCrossUnlock(
|
|
7107
|
-
refs.lockRef.current,
|
|
7108
|
-
adjustedPx,
|
|
7109
|
-
adjustedPy,
|
|
7110
|
-
lockContainer.rect,
|
|
7111
|
-
performance.now(),
|
|
7112
|
-
margin,
|
|
7113
|
-
dwellMs,
|
|
7114
|
-
CROSS_UNLOCK_GRACE_MS
|
|
7115
|
-
);
|
|
7116
|
-
if (nextLock !== refs.lockRef.current) {
|
|
7117
|
-
refs.lockRef.current = nextLock;
|
|
7118
|
-
if (nextLock.isCrossUnlocked) engine.setLaneAllowedContainers(null);
|
|
7119
|
-
}
|
|
7120
|
-
}
|
|
7121
7575
|
const nestPreview = engine.peekNestIntent(px, py, window.scrollX, window.scrollY, snapshot.scroll.x, snapshot.scroll.y);
|
|
7122
7576
|
const isLargeDraggedNode = shouldBlockNestForLargeNode(activeDrag.w, activeDrag.h);
|
|
7123
7577
|
let allowNest = false;
|
|
7124
7578
|
if (nestPreview) {
|
|
7125
7579
|
const childId = nestPreview.slotId.split("::nest::")[1] ?? "";
|
|
7126
|
-
|
|
7127
|
-
const isSiblingList = siblings.length >= 2;
|
|
7128
|
-
const isSourceContainerNest = nestPreview.containerId === refs.sourceContainerIdRef.current;
|
|
7129
|
-
allowNest = !!childId && !isSiblingList && !isLargeDraggedNode && !isSourceContainerNest;
|
|
7580
|
+
allowNest = !!childId && !isLargeDraggedNode;
|
|
7130
7581
|
}
|
|
7131
7582
|
if (!allowNest) {
|
|
7132
7583
|
refs.nestCandidateRef.current = null;
|
|
@@ -7136,7 +7587,12 @@ function useDragVisualLoop({
|
|
|
7136
7587
|
const now = performance.now();
|
|
7137
7588
|
if (!refs.nestCandidateRef.current || refs.nestCandidateRef.current.id !== nestPreview.slotId) {
|
|
7138
7589
|
refs.nestCandidateRef.current = { id: nestPreview.slotId, since: now };
|
|
7139
|
-
|
|
7590
|
+
const hintTargetId = nestPreview.slotId.split("::nest::")[1] ?? "";
|
|
7591
|
+
refs.nestTargetRef.current = refs.nodeMapRef.current.get(hintTargetId) ?? null;
|
|
7592
|
+
const hintRect = snapshot.rects.get(hintTargetId);
|
|
7593
|
+
if (hintRect) {
|
|
7594
|
+
setInsideRect(new DOMRect(hintRect.left - scrollDx, hintRect.top - scrollDy, hintRect.width, hintRect.height));
|
|
7595
|
+
}
|
|
7140
7596
|
setTargetPlane("lane");
|
|
7141
7597
|
} else if (now - refs.nestCandidateRef.current.since >= (isLargeDraggedNode ? LARGE_NODE_NEST_DWELL_MS : SMALL_NODE_NEST_DWELL_MS)) {
|
|
7142
7598
|
setTargetPlane("nest");
|
|
@@ -7195,18 +7651,6 @@ function useDragVisualLoop({
|
|
|
7195
7651
|
setTargetPlane("lane");
|
|
7196
7652
|
refs.nestCandidateRef.current = null;
|
|
7197
7653
|
refs.nestTargetRef.current = null;
|
|
7198
|
-
const lockedParentId = refs.lockRef.current.containerId;
|
|
7199
|
-
if (!refs.lockRef.current.isCrossUnlocked && (!lockedParentId || intent.containerId !== lockedParentId)) {
|
|
7200
|
-
refs.lastIntentRef.current = null;
|
|
7201
|
-
refs.visualIntentRef.current = null;
|
|
7202
|
-
refs.resolvedReorderRef.current = null;
|
|
7203
|
-
refs.finalVisualKeyRef.current = null;
|
|
7204
|
-
setInsideRect(null);
|
|
7205
|
-
setDropLine(null);
|
|
7206
|
-
animator.clear();
|
|
7207
|
-
rafId = requestAnimationFrame(tick);
|
|
7208
|
-
return;
|
|
7209
|
-
}
|
|
7210
7654
|
refs.lastIntentRef.current = intent;
|
|
7211
7655
|
refs.visualIntentRef.current = intent;
|
|
7212
7656
|
setInsideRect(null);
|
|
@@ -7238,19 +7682,43 @@ function useDragVisualLoop({
|
|
|
7238
7682
|
}
|
|
7239
7683
|
const sourceCommitLane = refs.sourceCommitLaneRef.current ?? getCommitLaneSnapshot(sourceContainerId);
|
|
7240
7684
|
const targetCommitLane = getCommitLaneSnapshot(intent.containerId);
|
|
7241
|
-
|
|
7685
|
+
let commitPlacement = resolveCommitPlacementFromVisualTarget(
|
|
7242
7686
|
targetCommitLane,
|
|
7243
7687
|
sourceCommitLane,
|
|
7244
7688
|
activeDrag.anchorNodeId,
|
|
7245
7689
|
targetInsertIndex
|
|
7246
7690
|
);
|
|
7247
7691
|
if (!commitPlacement) {
|
|
7248
|
-
refs.
|
|
7249
|
-
refs.
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7692
|
+
const containerEl = refs.nodeMapRef.current.get(intent.containerId)?.element;
|
|
7693
|
+
const sourceCommitNodeId = refs.sourceCommitLaneRef.current?.commitNodeByAnchorId.get(activeDrag.anchorNodeId) ?? activeDrag.anchorNodeId;
|
|
7694
|
+
if (!containerEl) {
|
|
7695
|
+
refs.resolvedReorderRef.current = null;
|
|
7696
|
+
refs.finalVisualKeyRef.current = null;
|
|
7697
|
+
setDropLine(null);
|
|
7698
|
+
animator.clear();
|
|
7699
|
+
rafId = requestAnimationFrame(tick);
|
|
7700
|
+
return;
|
|
7701
|
+
}
|
|
7702
|
+
const targetChildren = Array.from(containerEl.children).filter(
|
|
7703
|
+
(child) => child instanceof HTMLElement
|
|
7704
|
+
);
|
|
7705
|
+
const filteredChildren = targetChildren.filter(
|
|
7706
|
+
(child) => child.getAttribute(DND_NODE_ID_ATTR) !== sourceCommitNodeId
|
|
7707
|
+
);
|
|
7708
|
+
const idx = Math.max(0, Math.min(targetInsertIndex, filteredChildren.length));
|
|
7709
|
+
const beforeChild = filteredChildren[idx] ?? null;
|
|
7710
|
+
const afterChild = idx > 0 ? filteredChildren[idx - 1] ?? null : null;
|
|
7711
|
+
const parentNodeId = ensureParentNodeId(containerEl);
|
|
7712
|
+
const beforeNodeId = beforeChild?.getAttribute(DND_NODE_ID_ATTR) ? ensureParentNodeId(beforeChild) : null;
|
|
7713
|
+
const afterNodeId = afterChild?.getAttribute(DND_NODE_ID_ATTR) ? ensureParentNodeId(afterChild) : null;
|
|
7714
|
+
commitPlacement = {
|
|
7715
|
+
parentNodeId,
|
|
7716
|
+
laneContainerId: intent.containerId,
|
|
7717
|
+
commitNodeId: sourceCommitNodeId,
|
|
7718
|
+
beforeNodeId,
|
|
7719
|
+
afterNodeId,
|
|
7720
|
+
index: idx
|
|
7721
|
+
};
|
|
7254
7722
|
}
|
|
7255
7723
|
setDropLine(slotDropLine(slot, container, proj.projectionTree, scrollDx, scrollDy));
|
|
7256
7724
|
refs.resolvedReorderRef.current = {
|
|
@@ -7295,56 +7763,175 @@ function useDragVisualLoop({
|
|
|
7295
7763
|
|
|
7296
7764
|
// src/client/dnd/design-mode/useDragLifecycle.ts
|
|
7297
7765
|
var import_react14 = require("react");
|
|
7298
|
-
|
|
7299
|
-
// src/client/dnd/design-mode/node-key.ts
|
|
7300
|
-
var _runtimeKeyMap = /* @__PURE__ */ new WeakMap();
|
|
7301
|
-
var _runtimeKeyCounter = 0;
|
|
7302
|
-
function getRuntimeKey(el) {
|
|
7303
|
-
const existing = _runtimeKeyMap.get(el);
|
|
7304
|
-
if (existing) return existing;
|
|
7305
|
-
const key2 = `runtime:${++_runtimeKeyCounter}`;
|
|
7306
|
-
_runtimeKeyMap.set(el, key2);
|
|
7307
|
-
return key2;
|
|
7308
|
-
}
|
|
7309
|
-
function getNodeKeyFromElement(el) {
|
|
7310
|
-
const resolved = resolveDragSurface(el);
|
|
7311
|
-
const host = resolved.host ?? el;
|
|
7312
|
-
const meta = getEditorMeta(host);
|
|
7313
|
-
if (meta) return meta.nodeId;
|
|
7314
|
-
const persisted = host.getAttribute("data-dnd-node-id");
|
|
7315
|
-
if (persisted) return persisted;
|
|
7316
|
-
return getRuntimeKey(host);
|
|
7317
|
-
}
|
|
7318
|
-
function getInspectorRefFromElement(el) {
|
|
7319
|
-
const resolved = resolveDragSurface(el);
|
|
7320
|
-
const host = resolved.host ?? el;
|
|
7321
|
-
const meta = getEditorMeta(host);
|
|
7322
|
-
if (!meta) return null;
|
|
7323
|
-
return { relativePath: meta.file, line: meta.line, column: meta.col };
|
|
7324
|
-
}
|
|
7325
|
-
|
|
7326
|
-
// src/client/dnd/design-mode/useDragLifecycle.ts
|
|
7327
|
-
var SOFT_COMMIT_DISTANCE_PX = 14;
|
|
7328
|
-
function isLaneCommitValid(intent, resolvedReorder, lockedParentId) {
|
|
7329
|
-
if (!intent || intent.mode !== "reorder") return false;
|
|
7330
|
-
if (!resolvedReorder) return false;
|
|
7331
|
-
if (!lockedParentId) return false;
|
|
7332
|
-
if (intent.containerId !== lockedParentId) return false;
|
|
7333
|
-
if (resolvedReorder.visual.slotId !== intent.slotId) return false;
|
|
7334
|
-
if (resolvedReorder.visual.parentNodeId !== intent.containerId) return false;
|
|
7335
|
-
return true;
|
|
7336
|
-
}
|
|
7337
|
-
function buildRuntimeIdentityLocal(nodeId, resolveNodeElement) {
|
|
7766
|
+
function buildRuntimeIdentityLocal(nodeId, resolveNodeElement, effectiveLaneSnapshot) {
|
|
7338
7767
|
if (!nodeId) return null;
|
|
7339
7768
|
const element = resolveNodeElement(nodeId);
|
|
7340
7769
|
if (!element) return null;
|
|
7770
|
+
const nodeKey = getNodeKeyFromElement(element);
|
|
7771
|
+
const inspectorRef = getInspectorRefFromElement(element);
|
|
7772
|
+
const laneEffectiveNodeId = effectiveLaneSnapshot?.effectiveNodeIdsByCommitNodeId.get(nodeId) ?? null;
|
|
7773
|
+
const effectiveNodeId = typeof laneEffectiveNodeId === "string" && laneEffectiveNodeId.length > 0 ? laneEffectiveNodeId : isSourceBackedRuntimeNodeKey(nodeKey) ? nodeKey : null;
|
|
7774
|
+
const shouldExposeEffectiveIdentity = typeof effectiveNodeId === "string" && effectiveNodeId.length > 0;
|
|
7341
7775
|
return {
|
|
7342
7776
|
nodeId,
|
|
7343
|
-
nodeKey
|
|
7344
|
-
selector: element.getAttribute(
|
|
7345
|
-
inspectorRef
|
|
7777
|
+
nodeKey,
|
|
7778
|
+
selector: element.getAttribute(DND_NODE_ID_ATTR) ? buildNodeSelector(nodeId) : null,
|
|
7779
|
+
inspectorRef,
|
|
7780
|
+
...shouldExposeEffectiveIdentity ? {
|
|
7781
|
+
effectiveNodeId,
|
|
7782
|
+
effectiveNodeKey: effectiveNodeId,
|
|
7783
|
+
effectiveInspectorRef: inspectorRef
|
|
7784
|
+
} : {}
|
|
7785
|
+
};
|
|
7786
|
+
}
|
|
7787
|
+
function buildMovePayloadWithEffectiveIdentities(params) {
|
|
7788
|
+
const {
|
|
7789
|
+
placement,
|
|
7790
|
+
containerIdentity,
|
|
7791
|
+
beforeSiblingIdentity,
|
|
7792
|
+
afterSiblingIdentity,
|
|
7793
|
+
commitIdentity
|
|
7794
|
+
} = params;
|
|
7795
|
+
return {
|
|
7796
|
+
...placement,
|
|
7797
|
+
effectiveContainerNodeId: containerIdentity?.effectiveNodeId ?? null,
|
|
7798
|
+
effectiveContainerNodeKey: containerIdentity?.effectiveNodeKey ?? null,
|
|
7799
|
+
effectiveContainerInspectorRef: containerIdentity?.effectiveInspectorRef ?? null,
|
|
7800
|
+
effectiveBeforeNodeId: beforeSiblingIdentity?.effectiveNodeId ?? null,
|
|
7801
|
+
effectiveBeforeNodeKey: beforeSiblingIdentity?.effectiveNodeKey ?? null,
|
|
7802
|
+
effectiveBeforeInspectorRef: beforeSiblingIdentity?.effectiveInspectorRef ?? null,
|
|
7803
|
+
effectiveAfterNodeId: afterSiblingIdentity?.effectiveNodeId ?? null,
|
|
7804
|
+
effectiveAfterNodeKey: afterSiblingIdentity?.effectiveNodeKey ?? null,
|
|
7805
|
+
effectiveAfterInspectorRef: afterSiblingIdentity?.effectiveInspectorRef ?? null,
|
|
7806
|
+
effectiveCommitNodeId: commitIdentity?.effectiveNodeId ?? null,
|
|
7807
|
+
effectiveCommitNodeKey: commitIdentity?.effectiveNodeKey ?? null,
|
|
7808
|
+
effectiveCommitInspectorRef: commitIdentity?.effectiveInspectorRef ?? null
|
|
7346
7809
|
};
|
|
7347
7810
|
}
|
|
7811
|
+
function recordCommittedMove(args) {
|
|
7812
|
+
const {
|
|
7813
|
+
command,
|
|
7814
|
+
anchorNodeId,
|
|
7815
|
+
selectedNodeId,
|
|
7816
|
+
anchorEl,
|
|
7817
|
+
selectedEl,
|
|
7818
|
+
nodeKey,
|
|
7819
|
+
inspRef,
|
|
7820
|
+
selectedNodeKey,
|
|
7821
|
+
selectedInspectorRef,
|
|
7822
|
+
sourceLaneSnapshot,
|
|
7823
|
+
targetLaneSnapshot,
|
|
7824
|
+
resolveNodeElement,
|
|
7825
|
+
recordMoveChange
|
|
7826
|
+
} = args;
|
|
7827
|
+
const sourceLaneIdentitySnapshot = captureCommitLaneIdentitySnapshot(
|
|
7828
|
+
sourceLaneSnapshot,
|
|
7829
|
+
resolveNodeElement
|
|
7830
|
+
);
|
|
7831
|
+
const targetLaneIdentitySnapshot = command.to.laneContainerId === command.from.laneContainerId ? sourceLaneIdentitySnapshot : captureCommitLaneIdentitySnapshot(targetLaneSnapshot, resolveNodeElement);
|
|
7832
|
+
const targetLaneAfterIdentitySnapshot = targetLaneIdentitySnapshot ? createCommitLaneIdentitySnapshot({
|
|
7833
|
+
laneContainerId: targetLaneIdentitySnapshot.laneContainerId,
|
|
7834
|
+
commitNodeIds: projectCommitNodeIdsForMove({
|
|
7835
|
+
commitNodeIds: targetLaneIdentitySnapshot.commitNodeIds,
|
|
7836
|
+
movedCommitNodeId: command.commitNodeId,
|
|
7837
|
+
targetIndex: command.to.index
|
|
7838
|
+
}),
|
|
7839
|
+
nodeKeysByCommitNodeId: new Map([
|
|
7840
|
+
...targetLaneIdentitySnapshot.nodeKeysByCommitNodeId,
|
|
7841
|
+
...sourceLaneIdentitySnapshot?.nodeKeysByCommitNodeId.has(command.commitNodeId) ? [[command.commitNodeId, sourceLaneIdentitySnapshot.nodeKeysByCommitNodeId.get(command.commitNodeId) ?? null]] : []
|
|
7842
|
+
])
|
|
7843
|
+
}) : null;
|
|
7844
|
+
const sourceContainerIdentity = buildRuntimeIdentityLocal(
|
|
7845
|
+
command.from.parentNodeId ?? command.from.laneContainerId,
|
|
7846
|
+
resolveNodeElement,
|
|
7847
|
+
sourceLaneIdentitySnapshot
|
|
7848
|
+
);
|
|
7849
|
+
const sourceBeforeSiblingIdentity = buildRuntimeIdentityLocal(command.from.beforeNodeId, resolveNodeElement, sourceLaneIdentitySnapshot);
|
|
7850
|
+
const sourceAfterSiblingIdentity = buildRuntimeIdentityLocal(command.from.afterNodeId, resolveNodeElement, sourceLaneIdentitySnapshot);
|
|
7851
|
+
const sourceCommitIdentity = buildRuntimeIdentityLocal(command.commitNodeId, resolveNodeElement, sourceLaneIdentitySnapshot);
|
|
7852
|
+
const containerIdentity = buildRuntimeIdentityLocal(
|
|
7853
|
+
command.to.parentNodeId ?? command.to.laneContainerId,
|
|
7854
|
+
resolveNodeElement,
|
|
7855
|
+
targetLaneAfterIdentitySnapshot
|
|
7856
|
+
);
|
|
7857
|
+
const beforeSiblingIdentity = buildRuntimeIdentityLocal(command.to.beforeNodeId, resolveNodeElement, targetLaneAfterIdentitySnapshot);
|
|
7858
|
+
const afterSiblingIdentity = buildRuntimeIdentityLocal(command.to.afterNodeId, resolveNodeElement, targetLaneAfterIdentitySnapshot);
|
|
7859
|
+
const targetCommitIdentity = buildRuntimeIdentityLocal(command.commitNodeId, resolveNodeElement, targetLaneAfterIdentitySnapshot);
|
|
7860
|
+
const diagnostics = buildMovePersistenceDiagnostics({
|
|
7861
|
+
sourceLane: sourceLaneIdentitySnapshot,
|
|
7862
|
+
targetLane: targetLaneIdentitySnapshot,
|
|
7863
|
+
movedCommitNodeId: command.commitNodeId,
|
|
7864
|
+
sourceLaneContainerId: command.from.laneContainerId,
|
|
7865
|
+
targetLaneContainerId: command.to.laneContainerId,
|
|
7866
|
+
targetIndex: command.to.index
|
|
7867
|
+
});
|
|
7868
|
+
const componentName = getEditorMeta(anchorEl)?.componentName;
|
|
7869
|
+
const operationId = `${command.at}:${anchorNodeId}`;
|
|
7870
|
+
const beforePayload = buildMovePayloadWithEffectiveIdentities({
|
|
7871
|
+
placement: command.from,
|
|
7872
|
+
containerIdentity: sourceContainerIdentity,
|
|
7873
|
+
beforeSiblingIdentity: sourceBeforeSiblingIdentity,
|
|
7874
|
+
afterSiblingIdentity: sourceAfterSiblingIdentity,
|
|
7875
|
+
commitIdentity: sourceCommitIdentity
|
|
7876
|
+
});
|
|
7877
|
+
const afterPayload = buildMovePayloadWithEffectiveIdentities({
|
|
7878
|
+
placement: command.to,
|
|
7879
|
+
containerIdentity,
|
|
7880
|
+
beforeSiblingIdentity,
|
|
7881
|
+
afterSiblingIdentity,
|
|
7882
|
+
commitIdentity: targetCommitIdentity
|
|
7883
|
+
});
|
|
7884
|
+
recordMoveChange({
|
|
7885
|
+
operationId,
|
|
7886
|
+
commandType: command.type,
|
|
7887
|
+
nodeKey,
|
|
7888
|
+
nodeId: anchorNodeId,
|
|
7889
|
+
inspectorRef: inspRef,
|
|
7890
|
+
selectedNodeKey,
|
|
7891
|
+
selectedNodeId,
|
|
7892
|
+
selectedInspectorRef,
|
|
7893
|
+
anchorNodeKey: nodeKey,
|
|
7894
|
+
anchorNodeId,
|
|
7895
|
+
sourceContainer: sourceContainerIdentity,
|
|
7896
|
+
sourceBeforeSibling: sourceBeforeSiblingIdentity,
|
|
7897
|
+
sourceAfterSibling: sourceAfterSiblingIdentity,
|
|
7898
|
+
diagnostics,
|
|
7899
|
+
container: containerIdentity,
|
|
7900
|
+
beforeSibling: beforeSiblingIdentity,
|
|
7901
|
+
afterSibling: afterSiblingIdentity,
|
|
7902
|
+
componentName,
|
|
7903
|
+
before: beforePayload,
|
|
7904
|
+
after: afterPayload
|
|
7905
|
+
});
|
|
7906
|
+
dispatchRuntimeEvent({
|
|
7907
|
+
type: "element-moved",
|
|
7908
|
+
operationId,
|
|
7909
|
+
commandType: command.type,
|
|
7910
|
+
selected: {
|
|
7911
|
+
nodeId: selectedNodeId,
|
|
7912
|
+
nodeKey: selectedNodeKey,
|
|
7913
|
+
selector: selectedEl.getAttribute(DND_NODE_ID_ATTR) ? buildNodeSelector(selectedNodeId) : null,
|
|
7914
|
+
inspectorRef: selectedInspectorRef,
|
|
7915
|
+
...targetCommitIdentity?.effectiveNodeId ? { effectiveNodeId: targetCommitIdentity.effectiveNodeId, effectiveNodeKey: targetCommitIdentity.effectiveNodeKey } : {}
|
|
7916
|
+
},
|
|
7917
|
+
anchor: {
|
|
7918
|
+
nodeId: anchorNodeId,
|
|
7919
|
+
nodeKey,
|
|
7920
|
+
selector: anchorEl.getAttribute(DND_NODE_ID_ATTR) ? buildNodeSelector(anchorNodeId) : null,
|
|
7921
|
+
inspectorRef: inspRef,
|
|
7922
|
+
...targetCommitIdentity?.effectiveNodeId ? { effectiveNodeId: targetCommitIdentity.effectiveNodeId, effectiveNodeKey: targetCommitIdentity.effectiveNodeKey } : {}
|
|
7923
|
+
},
|
|
7924
|
+
sourceContainer: sourceContainerIdentity,
|
|
7925
|
+
sourceBeforeSibling: sourceBeforeSiblingIdentity,
|
|
7926
|
+
sourceAfterSibling: sourceAfterSiblingIdentity,
|
|
7927
|
+
container: containerIdentity,
|
|
7928
|
+
beforeSibling: beforeSiblingIdentity,
|
|
7929
|
+
afterSibling: afterSiblingIdentity,
|
|
7930
|
+
diagnostics,
|
|
7931
|
+
before: beforePayload,
|
|
7932
|
+
after: afterPayload
|
|
7933
|
+
});
|
|
7934
|
+
}
|
|
7348
7935
|
function useDragLifecycle({
|
|
7349
7936
|
refs,
|
|
7350
7937
|
pause,
|
|
@@ -7426,12 +8013,10 @@ function useDragLifecycle({
|
|
|
7426
8013
|
const srcContainerId = anchor.sourceContainerId;
|
|
7427
8014
|
const sourceCommitLane = getCommitLaneSnapshot(srcContainerId);
|
|
7428
8015
|
const startPosition = getCurrentCommitPlacement(anchorNodeId, srcContainerId);
|
|
7429
|
-
const laneAllowed = srcContainerId ? /* @__PURE__ */ new Set([srcContainerId]) : null;
|
|
7430
8016
|
const blockedContainerIds = buildBlockedStructuralContainerIds(proj, refs.nodeMapRef.current, srcContainerId);
|
|
7431
8017
|
refs.blockedContainerIdsRef.current = blockedContainerIds;
|
|
7432
8018
|
refs.engineRef.current = createDragIntentEngine(proj, anchorNodeId, {
|
|
7433
8019
|
laneRootContainerId: srcContainerId,
|
|
7434
|
-
laneAllowedContainers: laneAllowed,
|
|
7435
8020
|
blockedContainerIds
|
|
7436
8021
|
});
|
|
7437
8022
|
refs.engineRef.current.setTargetPlane("lane");
|
|
@@ -7439,7 +8024,7 @@ function useDragLifecycle({
|
|
|
7439
8024
|
refs.sourceContainerIdRef.current = srcContainerId;
|
|
7440
8025
|
refs.sourceCommitLaneRef.current = sourceCommitLane;
|
|
7441
8026
|
refs.dragSessionAnchorRef.current = anchor;
|
|
7442
|
-
refs.lockRef.current = { containerId: srcContainerId, isCrossUnlocked:
|
|
8027
|
+
refs.lockRef.current = { containerId: srcContainerId, isCrossUnlocked: true, exitSince: null, unlockUntilTs: null };
|
|
7443
8028
|
refs.dragStartPositionRef.current = startPosition;
|
|
7444
8029
|
refs.safeZoneRef.current = resolveSafeZoneRect();
|
|
7445
8030
|
pause();
|
|
@@ -7465,22 +8050,34 @@ function useDragLifecycle({
|
|
|
7465
8050
|
const pointer = refs.mouseRef.current;
|
|
7466
8051
|
const safeZone = refs.safeZoneRef.current;
|
|
7467
8052
|
const blockedByGuard = isPointerOutsideSafeZone(pointer.x, pointer.y, safeZone) || isPointerInHardPageEdgeZone(pointer.x, pointer.y);
|
|
7468
|
-
|
|
8053
|
+
let sourcePos = refs.dragStartPositionRef.current ?? getCurrentCommitPlacement(anchorNodeId, refs.sourceContainerIdRef.current);
|
|
8054
|
+
if (!sourcePos && activeEl && activeEl.parentElement) {
|
|
8055
|
+
const parentEl = activeEl.parentElement;
|
|
8056
|
+
const commitNodeId = activeEl.getAttribute(DND_NODE_ID_ATTR) ?? anchorNodeId;
|
|
8057
|
+
const siblings = Array.from(parentEl.children).filter((c) => c instanceof HTMLElement);
|
|
8058
|
+
const idx = siblings.indexOf(activeEl);
|
|
8059
|
+
if (idx >= 0) {
|
|
8060
|
+
sourcePos = {
|
|
8061
|
+
parentNodeId: ensureParentNodeId(parentEl),
|
|
8062
|
+
laneContainerId: refs.sourceContainerIdRef.current,
|
|
8063
|
+
commitNodeId,
|
|
8064
|
+
beforeNodeId: idx < siblings.length - 1 ? siblings[idx + 1].getAttribute(DND_NODE_ID_ATTR) ?? ensureParentNodeId(siblings[idx + 1]) : null,
|
|
8065
|
+
afterNodeId: idx > 0 ? siblings[idx - 1].getAttribute(DND_NODE_ID_ATTR) ?? ensureParentNodeId(siblings[idx - 1]) : null,
|
|
8066
|
+
index: idx
|
|
8067
|
+
};
|
|
8068
|
+
}
|
|
8069
|
+
}
|
|
7469
8070
|
const intent = refs.visualIntentRef.current;
|
|
7470
|
-
const finalVisual = refs.finalVisualKeyRef.current;
|
|
7471
8071
|
const nestTarget = refs.nestTargetRef.current;
|
|
7472
8072
|
const intentHasContainer = intent ? refs.projectionRef.current.containerIndex.has(intent.containerId) : false;
|
|
7473
8073
|
const intentHasSlot = intent ? intent.mode === "nest" || refs.projectionRef.current.slotIndex.has(intent.slotId) : false;
|
|
7474
8074
|
const intentValid = !!intent && intentHasContainer && intentHasSlot;
|
|
7475
8075
|
if (!blockedByGuard && activeEl && sourcePos && (nestTarget || intentValid)) {
|
|
7476
8076
|
const dropTargetId = nestTarget?.nodeId ?? intent?.containerId;
|
|
7477
|
-
if (dropTargetId) {
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
syncHistoryAvailability();
|
|
7482
|
-
return;
|
|
7483
|
-
}
|
|
8077
|
+
if (dropTargetId && !refs.nodeMapRef.current.has(dropTargetId)) {
|
|
8078
|
+
clearDragState();
|
|
8079
|
+
syncHistoryAvailability();
|
|
8080
|
+
return;
|
|
7484
8081
|
}
|
|
7485
8082
|
let command = null;
|
|
7486
8083
|
if (nestTarget) {
|
|
@@ -7500,46 +8097,8 @@ function useDragLifecycle({
|
|
|
7500
8097
|
};
|
|
7501
8098
|
}
|
|
7502
8099
|
} else if (intentValid && intent.mode === "reorder") {
|
|
7503
|
-
const lockedParentId = refs.lockRef.current.containerId;
|
|
7504
|
-
if (!refs.lockRef.current.isCrossUnlocked && (!lockedParentId || intent.containerId !== lockedParentId)) {
|
|
7505
|
-
clearDragState();
|
|
7506
|
-
syncHistoryAvailability();
|
|
7507
|
-
return;
|
|
7508
|
-
}
|
|
7509
|
-
const snapshot = refs.snapshotRef.current;
|
|
7510
|
-
const targetContainer = refs.projectionRef.current.containerIndex.get(intent.containerId);
|
|
7511
|
-
if (targetContainer) {
|
|
7512
|
-
const scrollDx = window.scrollX - (snapshot?.scroll.x ?? 0);
|
|
7513
|
-
const scrollDy = window.scrollY - (snapshot?.scroll.y ?? 0);
|
|
7514
|
-
const adjPx = pointer.x + scrollDx;
|
|
7515
|
-
const adjPy = pointer.y + scrollDy;
|
|
7516
|
-
const r = targetContainer.rect;
|
|
7517
|
-
const inContainer = adjPx >= r.left - 40 && adjPx <= r.right + 40 && adjPy >= r.top - 40 && adjPy <= r.bottom + 40;
|
|
7518
|
-
if (!inContainer) {
|
|
7519
|
-
const softFallbackAllowed = finalVisual?.mode === "reorder" && finalVisual.containerId === intent.containerId && (() => {
|
|
7520
|
-
const slot = refs.projectionRef.current.slotIndex.get(finalVisual.slotId);
|
|
7521
|
-
const container = refs.projectionRef.current.containerIndex.get(finalVisual.containerId);
|
|
7522
|
-
if (!slot || !container) return false;
|
|
7523
|
-
const bp = computeSlotBoundaryPoint(slot, container, refs.projectionRef.current.projectionTree);
|
|
7524
|
-
const dist = Math.hypot(adjPx - bp.x, adjPy - bp.y);
|
|
7525
|
-
return dist <= SOFT_COMMIT_DISTANCE_PX;
|
|
7526
|
-
})();
|
|
7527
|
-
if (!softFallbackAllowed) {
|
|
7528
|
-
clearDragState();
|
|
7529
|
-
syncHistoryAvailability();
|
|
7530
|
-
return;
|
|
7531
|
-
}
|
|
7532
|
-
}
|
|
7533
|
-
}
|
|
7534
8100
|
const resolvedReorder = refs.resolvedReorderRef.current;
|
|
7535
|
-
|
|
7536
|
-
if (!laneValid) {
|
|
7537
|
-
clearDragState();
|
|
7538
|
-
syncHistoryAvailability();
|
|
7539
|
-
return;
|
|
7540
|
-
}
|
|
7541
|
-
const visualParity = !!finalVisual && finalVisual.mode === "reorder" && finalVisual.anchorNodeId === anchorNodeId && finalVisual.slotId === resolvedReorder.visual.slotId && finalVisual.parentNodeId === resolvedReorder.visual.parentNodeId && finalVisual.index === resolvedReorder.visual.index && finalVisual.containerId === intent.containerId;
|
|
7542
|
-
if (!visualParity) {
|
|
8101
|
+
if (!resolvedReorder || resolvedReorder.visual.containerId !== intent.containerId) {
|
|
7543
8102
|
clearDragState();
|
|
7544
8103
|
syncHistoryAvailability();
|
|
7545
8104
|
return;
|
|
@@ -7555,62 +8114,32 @@ function useDragLifecycle({
|
|
|
7555
8114
|
};
|
|
7556
8115
|
}
|
|
7557
8116
|
if (command) {
|
|
8117
|
+
const anchorEl = resolveNodeElement(anchorNodeId) ?? activeEl;
|
|
8118
|
+
const selectedEl = resolveNodeElement(selectedNodeId) ?? anchorEl;
|
|
8119
|
+
const nodeKey = getNodeKeyFromElement(anchorEl);
|
|
8120
|
+
const inspRef = getInspectorRefFromElement(anchorEl);
|
|
8121
|
+
const selectedNodeKey = getNodeKeyFromElement(selectedEl);
|
|
8122
|
+
const selectedInspectorRef = getInspectorRefFromElement(selectedEl);
|
|
8123
|
+
const sourceLaneSnapshot = refs.sourceCommitLaneRef.current ?? getCommitLaneSnapshot(command.from.laneContainerId);
|
|
8124
|
+
const targetLaneSnapshot = command.to.laneContainerId === command.from.laneContainerId ? sourceLaneSnapshot : getCommitLaneSnapshot(command.to.laneContainerId);
|
|
7558
8125
|
const committed = refs.historyRef.current.execute(command, applyCommand);
|
|
7559
8126
|
if (committed) {
|
|
7560
8127
|
activeEl.setAttribute("data-dnd-moved", "");
|
|
7561
8128
|
selectElement(null);
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
const containerIdentity = buildRuntimeIdentityLocal(
|
|
7569
|
-
command.to.parentNodeId ?? command.to.laneContainerId,
|
|
7570
|
-
resolveNodeElement
|
|
7571
|
-
);
|
|
7572
|
-
const beforeSiblingIdentity = buildRuntimeIdentityLocal(command.to.beforeNodeId, resolveNodeElement);
|
|
7573
|
-
const afterSiblingIdentity = buildRuntimeIdentityLocal(command.to.afterNodeId, resolveNodeElement);
|
|
7574
|
-
const operationId = `${command.at}:${anchorNodeId}`;
|
|
7575
|
-
recordMoveChange({
|
|
7576
|
-
operationId,
|
|
7577
|
-
commandType: command.type,
|
|
8129
|
+
recordCommittedMove({
|
|
8130
|
+
command,
|
|
8131
|
+
anchorNodeId,
|
|
8132
|
+
selectedNodeId,
|
|
8133
|
+
anchorEl,
|
|
8134
|
+
selectedEl,
|
|
7578
8135
|
nodeKey,
|
|
7579
|
-
|
|
7580
|
-
inspectorRef: inspRef,
|
|
8136
|
+
inspRef,
|
|
7581
8137
|
selectedNodeKey,
|
|
7582
|
-
selectedNodeId,
|
|
7583
8138
|
selectedInspectorRef,
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
afterSibling: afterSiblingIdentity,
|
|
7589
|
-
componentName: getEditorMeta(anchorEl)?.componentName,
|
|
7590
|
-
before: command.from,
|
|
7591
|
-
after: command.to
|
|
7592
|
-
});
|
|
7593
|
-
dispatchRuntimeEvent({
|
|
7594
|
-
type: "element-moved",
|
|
7595
|
-
operationId,
|
|
7596
|
-
commandType: command.type,
|
|
7597
|
-
selected: {
|
|
7598
|
-
nodeId: selectedNodeId,
|
|
7599
|
-
nodeKey: selectedNodeKey,
|
|
7600
|
-
selector: selectedEl.getAttribute(DND_NODE_ID_ATTR2) ? `[${DND_NODE_ID_ATTR2}="${escapeCssAttrValue(selectedNodeId)}"]` : null,
|
|
7601
|
-
inspectorRef: selectedInspectorRef
|
|
7602
|
-
},
|
|
7603
|
-
anchor: {
|
|
7604
|
-
nodeId: anchorNodeId,
|
|
7605
|
-
nodeKey,
|
|
7606
|
-
selector: anchorEl.getAttribute(DND_NODE_ID_ATTR2) ? `[${DND_NODE_ID_ATTR2}="${escapeCssAttrValue(anchorNodeId)}"]` : null,
|
|
7607
|
-
inspectorRef: inspRef
|
|
7608
|
-
},
|
|
7609
|
-
container: containerIdentity,
|
|
7610
|
-
beforeSibling: beforeSiblingIdentity,
|
|
7611
|
-
afterSibling: afterSiblingIdentity,
|
|
7612
|
-
before: command.from,
|
|
7613
|
-
after: command.to
|
|
8139
|
+
sourceLaneSnapshot,
|
|
8140
|
+
targetLaneSnapshot,
|
|
8141
|
+
resolveNodeElement,
|
|
8142
|
+
recordMoveChange
|
|
7614
8143
|
});
|
|
7615
8144
|
}
|
|
7616
8145
|
}
|
|
@@ -7649,7 +8178,7 @@ function useResizeSession({
|
|
|
7649
8178
|
const rect = resizeTargetEl.getBoundingClientRect();
|
|
7650
8179
|
const selectedNodeKey = getNodeKeyFromElement(selectedEl);
|
|
7651
8180
|
const targetNodeKey = getNodeKeyFromElement(resizeTargetEl);
|
|
7652
|
-
const targetNodeId =
|
|
8181
|
+
const targetNodeId = ensureParentNodeId(resizeTargetEl);
|
|
7653
8182
|
const startColSpan = parseSpanValue(getComputedStyle(resizeTargetEl).gridColumnEnd || resizeTargetEl.style.gridColumnEnd);
|
|
7654
8183
|
const startRowSpan = parseSpanValue(getComputedStyle(resizeTargetEl).gridRowEnd || resizeTargetEl.style.gridRowEnd);
|
|
7655
8184
|
const columnTrackCount = getGridTrackCount(resizeTargetParent ? getComputedStyle(resizeTargetParent).gridTemplateColumns : null);
|
|
@@ -7774,13 +8303,13 @@ function useResizeSession({
|
|
|
7774
8303
|
selected: {
|
|
7775
8304
|
nodeId: selectedNodeId,
|
|
7776
8305
|
nodeKey: selectedNodeKey,
|
|
7777
|
-
selector:
|
|
8306
|
+
selector: buildNodeSelector(selectedNodeId),
|
|
7778
8307
|
inspectorRef
|
|
7779
8308
|
},
|
|
7780
8309
|
anchor: {
|
|
7781
8310
|
nodeId: targetNodeId,
|
|
7782
8311
|
nodeKey: targetNodeKey,
|
|
7783
|
-
selector:
|
|
8312
|
+
selector: buildNodeSelector(targetNodeId),
|
|
7784
8313
|
inspectorRef: getInspectorRefFromElement(element)
|
|
7785
8314
|
},
|
|
7786
8315
|
resize: {
|
|
@@ -7821,6 +8350,169 @@ function useResizeSession({
|
|
|
7821
8350
|
return { handleResizeHandlePointerDown };
|
|
7822
8351
|
}
|
|
7823
8352
|
|
|
8353
|
+
// src/client/dnd/design-mode/useExternalDragLoop.ts
|
|
8354
|
+
var import_react16 = require("react");
|
|
8355
|
+
var EXTERNAL_DRAG_ACTIVE_ID = "__external-drag-placeholder__";
|
|
8356
|
+
function useExternalDragLoop({
|
|
8357
|
+
externalDrag,
|
|
8358
|
+
refs,
|
|
8359
|
+
elements,
|
|
8360
|
+
resolveNodeElement,
|
|
8361
|
+
setDropLine
|
|
8362
|
+
}) {
|
|
8363
|
+
const engineRef = (0, import_react16.useRef)(null);
|
|
8364
|
+
const lastIntentRef = (0, import_react16.useRef)(null);
|
|
8365
|
+
(0, import_react16.useEffect)(() => {
|
|
8366
|
+
if (!externalDrag) {
|
|
8367
|
+
engineRef.current = null;
|
|
8368
|
+
lastIntentRef.current = null;
|
|
8369
|
+
setDropLine(null);
|
|
8370
|
+
externalDragMouse.commitRequested = false;
|
|
8371
|
+
return;
|
|
8372
|
+
}
|
|
8373
|
+
const projection = buildProjection(elements);
|
|
8374
|
+
if (projection.containerIndex.size === 0) return;
|
|
8375
|
+
const rects = /* @__PURE__ */ new Map();
|
|
8376
|
+
for (const el of elements) {
|
|
8377
|
+
rects.set(el.nodeId, el.rect);
|
|
8378
|
+
}
|
|
8379
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
8380
|
+
for (const el of elements) nodeMap.set(el.nodeId, el);
|
|
8381
|
+
const blockedContainerIds = buildBlockedStructuralContainerIds(projection, nodeMap, null);
|
|
8382
|
+
const engine = new DragIntentEngine(projection, EXTERNAL_DRAG_ACTIVE_ID, {
|
|
8383
|
+
blockedContainerIds
|
|
8384
|
+
});
|
|
8385
|
+
engineRef.current = engine;
|
|
8386
|
+
const scrollX = window.scrollX;
|
|
8387
|
+
const scrollY = window.scrollY;
|
|
8388
|
+
let rafId;
|
|
8389
|
+
const tick = () => {
|
|
8390
|
+
if (externalDragMouse.commitRequested) {
|
|
8391
|
+
externalDragMouse.commitRequested = false;
|
|
8392
|
+
commitExternalDrop(
|
|
8393
|
+
externalDragMouse.x,
|
|
8394
|
+
externalDragMouse.y,
|
|
8395
|
+
engine,
|
|
8396
|
+
externalDrag,
|
|
8397
|
+
refs,
|
|
8398
|
+
resolveNodeElement,
|
|
8399
|
+
setDropLine
|
|
8400
|
+
);
|
|
8401
|
+
return;
|
|
8402
|
+
}
|
|
8403
|
+
const intent = engine.resolve(
|
|
8404
|
+
externalDragMouse.x,
|
|
8405
|
+
externalDragMouse.y,
|
|
8406
|
+
window.scrollX,
|
|
8407
|
+
window.scrollY,
|
|
8408
|
+
scrollX,
|
|
8409
|
+
scrollY
|
|
8410
|
+
);
|
|
8411
|
+
if (intent && intent.mode === "reorder") {
|
|
8412
|
+
lastIntentRef.current = intent;
|
|
8413
|
+
const slot = projection.slotIndex.get(intent.slotId);
|
|
8414
|
+
const container = projection.containerIndex.get(intent.containerId);
|
|
8415
|
+
if (slot && container) {
|
|
8416
|
+
const scrollDx = window.scrollX - scrollX;
|
|
8417
|
+
const scrollDy = window.scrollY - scrollY;
|
|
8418
|
+
setDropLine(slotDropLine(slot, container, projection.projectionTree, scrollDx, scrollDy));
|
|
8419
|
+
} else {
|
|
8420
|
+
setDropLine(null);
|
|
8421
|
+
}
|
|
8422
|
+
} else {
|
|
8423
|
+
lastIntentRef.current = null;
|
|
8424
|
+
setDropLine(null);
|
|
8425
|
+
}
|
|
8426
|
+
rafId = requestAnimationFrame(tick);
|
|
8427
|
+
};
|
|
8428
|
+
rafId = requestAnimationFrame(tick);
|
|
8429
|
+
return () => cancelAnimationFrame(rafId);
|
|
8430
|
+
}, [externalDrag, elements, refs, resolveNodeElement, setDropLine]);
|
|
8431
|
+
}
|
|
8432
|
+
function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, setDropLine) {
|
|
8433
|
+
const scrollX = window.scrollX;
|
|
8434
|
+
const scrollY = window.scrollY;
|
|
8435
|
+
const intent = engine.resolve(x, y, scrollX, scrollY, scrollX, scrollY);
|
|
8436
|
+
if (!intent || intent.mode !== "reorder") {
|
|
8437
|
+
useDesignModeStore.getState().cancelExternalDrag();
|
|
8438
|
+
setDropLine(null);
|
|
8439
|
+
return;
|
|
8440
|
+
}
|
|
8441
|
+
const containerEl = resolveNodeElement(intent.containerId);
|
|
8442
|
+
if (!containerEl) {
|
|
8443
|
+
useDesignModeStore.getState().cancelExternalDrag();
|
|
8444
|
+
setDropLine(null);
|
|
8445
|
+
return;
|
|
8446
|
+
}
|
|
8447
|
+
const template = document.createElement("template");
|
|
8448
|
+
template.innerHTML = component.html.trim();
|
|
8449
|
+
const newElement = template.content.firstElementChild;
|
|
8450
|
+
if (!newElement) {
|
|
8451
|
+
useDesignModeStore.getState().cancelExternalDrag();
|
|
8452
|
+
setDropLine(null);
|
|
8453
|
+
return;
|
|
8454
|
+
}
|
|
8455
|
+
const nodeId = `insert:${Date.now()}`;
|
|
8456
|
+
newElement.setAttribute(DND_NODE_ID_ATTR, nodeId);
|
|
8457
|
+
newElement.setAttribute("data-dnd-force-allow", "");
|
|
8458
|
+
newElement.setAttribute("data-dnd-moved", "");
|
|
8459
|
+
const children = Array.from(containerEl.children).filter(
|
|
8460
|
+
(child) => child instanceof HTMLElement
|
|
8461
|
+
);
|
|
8462
|
+
const beforeChild = children[intent.index] ?? null;
|
|
8463
|
+
containerEl.insertBefore(newElement, beforeChild);
|
|
8464
|
+
const insertCommand = {
|
|
8465
|
+
type: "insert",
|
|
8466
|
+
nodeId,
|
|
8467
|
+
html: component.html,
|
|
8468
|
+
containerId: intent.containerId,
|
|
8469
|
+
index: intent.index,
|
|
8470
|
+
at: Date.now()
|
|
8471
|
+
};
|
|
8472
|
+
const applied = refs.historyRef.current.execute(insertCommand, (command, direction) => {
|
|
8473
|
+
if (command.type !== "insert") return false;
|
|
8474
|
+
return applyInsertCommand(command, direction, resolveNodeElement);
|
|
8475
|
+
});
|
|
8476
|
+
if (applied) {
|
|
8477
|
+
const nodeKey = getNodeKeyFromElement(newElement);
|
|
8478
|
+
const inspectorRef = getInspectorRefFromElement(newElement);
|
|
8479
|
+
const containerNodeKey = getNodeKeyFromElement(containerEl);
|
|
8480
|
+
let containerIdentity = null;
|
|
8481
|
+
if (containerEl) {
|
|
8482
|
+
containerIdentity = {
|
|
8483
|
+
nodeId: intent.containerId,
|
|
8484
|
+
nodeKey: getNodeKeyFromElement(containerEl),
|
|
8485
|
+
selector: containerEl.getAttribute(DND_NODE_ID_ATTR) ? buildNodeSelector(intent.containerId) : null,
|
|
8486
|
+
inspectorRef: getInspectorRefFromElement(containerEl)
|
|
8487
|
+
};
|
|
8488
|
+
}
|
|
8489
|
+
const operationId = `${insertCommand.at}:${nodeId}`;
|
|
8490
|
+
useDesignModeStore.getState().recordInsertChange({
|
|
8491
|
+
operationId,
|
|
8492
|
+
nodeKey,
|
|
8493
|
+
nodeId,
|
|
8494
|
+
inspectorRef,
|
|
8495
|
+
displayName: component.displayName,
|
|
8496
|
+
html: component.html,
|
|
8497
|
+
containerId: intent.containerId,
|
|
8498
|
+
containerNodeKey,
|
|
8499
|
+
index: intent.index
|
|
8500
|
+
});
|
|
8501
|
+
dispatchRuntimeEvent({
|
|
8502
|
+
type: "element-inserted",
|
|
8503
|
+
operationId,
|
|
8504
|
+
nodeId,
|
|
8505
|
+
nodeKey,
|
|
8506
|
+
displayName: component.displayName,
|
|
8507
|
+
html: component.html,
|
|
8508
|
+
container: containerIdentity,
|
|
8509
|
+
index: intent.index
|
|
8510
|
+
});
|
|
8511
|
+
}
|
|
8512
|
+
setDropLine(null);
|
|
8513
|
+
useDesignModeStore.getState().cancelExternalDrag();
|
|
8514
|
+
}
|
|
8515
|
+
|
|
7824
8516
|
// src/client/dnd/design-mode/DesignModeOverlay.tsx
|
|
7825
8517
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
7826
8518
|
var DROP_ANIMATION = { duration: DURATION_MS, easing: EASING };
|
|
@@ -7866,11 +8558,11 @@ function HitArea({
|
|
|
7866
8558
|
onResizeHandlePointerDown
|
|
7867
8559
|
}) {
|
|
7868
8560
|
const { setNodeRef, listeners, attributes, isDragging } = useDraggable({ id: scanned.nodeId });
|
|
7869
|
-
(0,
|
|
8561
|
+
(0, import_react17.useEffect)(() => {
|
|
7870
8562
|
setNodeRef(scanned.element);
|
|
7871
8563
|
return () => setNodeRef(null);
|
|
7872
8564
|
}, [setNodeRef, scanned.element]);
|
|
7873
|
-
(0,
|
|
8565
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
7874
8566
|
const el = scanned.element;
|
|
7875
8567
|
if (isDragging) {
|
|
7876
8568
|
el.style.opacity = "0";
|
|
@@ -7878,16 +8570,16 @@ function HitArea({
|
|
|
7878
8570
|
el.style.removeProperty("opacity");
|
|
7879
8571
|
}
|
|
7880
8572
|
}, [isDragging, scanned.element]);
|
|
7881
|
-
(0,
|
|
8573
|
+
(0, import_react17.useEffect)(() => () => {
|
|
7882
8574
|
scanned.element.style.removeProperty("opacity");
|
|
7883
8575
|
scanned.element.style.removeProperty("transform");
|
|
7884
8576
|
scanned.element.style.removeProperty("transition");
|
|
7885
8577
|
scanned.element.style.removeProperty("will-change");
|
|
7886
8578
|
}, [scanned.element]);
|
|
7887
|
-
const divRef = (0,
|
|
7888
|
-
const [hoverResizeHandle, setHoverResizeHandle] = (0,
|
|
8579
|
+
const divRef = (0, import_react17.useRef)(null);
|
|
8580
|
+
const [hoverResizeHandle, setHoverResizeHandle] = (0, import_react17.useState)(null);
|
|
7889
8581
|
const isSelected = scanned.nodeId === selectedNodeId;
|
|
7890
|
-
(0,
|
|
8582
|
+
(0, import_react17.useEffect)(() => {
|
|
7891
8583
|
const div = divRef.current;
|
|
7892
8584
|
if (!div) return;
|
|
7893
8585
|
const onWheel = (e) => {
|
|
@@ -7958,13 +8650,14 @@ function DesignModeOverlay() {
|
|
|
7958
8650
|
const redoLastChange = useDesignModeStore((s) => s.redoLastChange);
|
|
7959
8651
|
const orderedChanges = useDesignModeStore((s) => s.orderedChanges);
|
|
7960
8652
|
const exportChangesForAI = useDesignModeStore((s) => s.exportChangesForAI);
|
|
8653
|
+
const externalDrag = useDesignModeStore((s) => s.externalDrag);
|
|
7961
8654
|
const { elements, pause, resume } = useElementScanner(enabled);
|
|
7962
|
-
const nodeMap = (0,
|
|
8655
|
+
const nodeMap = (0, import_react17.useMemo)(() => {
|
|
7963
8656
|
const m = /* @__PURE__ */ new Map();
|
|
7964
8657
|
for (const el of elements) m.set(el.nodeId, el);
|
|
7965
8658
|
return m;
|
|
7966
8659
|
}, [elements]);
|
|
7967
|
-
const draggableElements = (0,
|
|
8660
|
+
const draggableElements = (0, import_react17.useMemo)(() => {
|
|
7968
8661
|
if (elements.length === 0) return [];
|
|
7969
8662
|
const projection = buildProjection(elements);
|
|
7970
8663
|
return collectDraggableAnchors(elements, projection, nodeMap);
|
|
@@ -7972,21 +8665,21 @@ function DesignModeOverlay() {
|
|
|
7972
8665
|
const refs = useOverlayRefs(undoRequestId, redoRequestId);
|
|
7973
8666
|
refs.elementsRef.current = elements;
|
|
7974
8667
|
refs.nodeMapRef.current = nodeMap;
|
|
7975
|
-
(0,
|
|
8668
|
+
(0, import_react17.useEffect)(() => {
|
|
7976
8669
|
const m = /* @__PURE__ */ new Map();
|
|
7977
8670
|
for (const el of draggableElements) m.set(el.nodeId, el);
|
|
7978
8671
|
refs.draggableNodeMapRef.current = m;
|
|
7979
8672
|
}, [draggableElements]);
|
|
7980
|
-
const resolveNodeElement = (0,
|
|
8673
|
+
const resolveNodeElement = (0, import_react17.useCallback)((nodeId) => {
|
|
7981
8674
|
const known = refs.nodeMapRef.current.get(nodeId)?.element;
|
|
7982
8675
|
if (known) return known;
|
|
7983
|
-
return document.querySelector(
|
|
8676
|
+
return document.querySelector(buildNodeSelector(nodeId));
|
|
7984
8677
|
}, []);
|
|
7985
|
-
const clearCommitLaneCache = (0,
|
|
8678
|
+
const clearCommitLaneCache = (0, import_react17.useCallback)(() => {
|
|
7986
8679
|
refs.commitLaneCacheRef.current.clear();
|
|
7987
8680
|
refs.sourceCommitLaneRef.current = null;
|
|
7988
8681
|
}, []);
|
|
7989
|
-
const getCommitLaneSnapshot = (0,
|
|
8682
|
+
const getCommitLaneSnapshot = (0, import_react17.useCallback)((laneContainerId) => {
|
|
7990
8683
|
if (!laneContainerId) return null;
|
|
7991
8684
|
if (refs.commitLaneCacheRef.current.has(laneContainerId)) {
|
|
7992
8685
|
return refs.commitLaneCacheRef.current.get(laneContainerId) ?? null;
|
|
@@ -7995,15 +8688,15 @@ function DesignModeOverlay() {
|
|
|
7995
8688
|
refs.commitLaneCacheRef.current.set(laneContainerId, snapshot);
|
|
7996
8689
|
return snapshot;
|
|
7997
8690
|
}, []);
|
|
7998
|
-
const getCurrentCommitPlacement = (0,
|
|
8691
|
+
const getCurrentCommitPlacement = (0, import_react17.useCallback)((anchorNodeId, laneContainerId) => {
|
|
7999
8692
|
const lane = getCommitLaneSnapshot(laneContainerId);
|
|
8000
8693
|
return resolveCurrentCommitPlacement(lane, anchorNodeId);
|
|
8001
8694
|
}, [getCommitLaneSnapshot]);
|
|
8002
|
-
const applyCommand = (0,
|
|
8695
|
+
const applyCommand = (0, import_react17.useCallback)((command, direction) => {
|
|
8003
8696
|
if (command.type === "resize") {
|
|
8004
8697
|
const resCmd = command;
|
|
8005
8698
|
const targetId = resCmd.targetNodeId ?? resCmd.nodeId;
|
|
8006
|
-
const targetEl = document.querySelector(
|
|
8699
|
+
const targetEl = document.querySelector(buildNodeSelector(targetId));
|
|
8007
8700
|
if (!targetEl) return false;
|
|
8008
8701
|
const snapshot = direction === "redo" ? resCmd.after : resCmd.before;
|
|
8009
8702
|
if (snapshot.styles) {
|
|
@@ -8014,29 +8707,36 @@ function DesignModeOverlay() {
|
|
|
8014
8707
|
}
|
|
8015
8708
|
return true;
|
|
8016
8709
|
}
|
|
8710
|
+
if (command.type === "insert") {
|
|
8711
|
+
return applyInsertCommand(command, direction, resolveNodeElement);
|
|
8712
|
+
}
|
|
8017
8713
|
const applied = applyDndCommandPlacement(command, direction, resolveNodeElement);
|
|
8018
8714
|
if (!applied) return false;
|
|
8019
8715
|
clearCommitLaneCache();
|
|
8020
8716
|
return true;
|
|
8021
8717
|
}, [clearCommitLaneCache, resolveNodeElement]);
|
|
8022
|
-
const syncHistoryAvailability = (0,
|
|
8718
|
+
const syncHistoryAvailability = (0, import_react17.useCallback)(() => {
|
|
8023
8719
|
if (historyMode === "host") {
|
|
8024
8720
|
setHistoryAvailability(false, false);
|
|
8025
8721
|
return;
|
|
8026
8722
|
}
|
|
8027
8723
|
setHistoryAvailability(refs.historyRef.current.canUndo(), refs.historyRef.current.canRedo());
|
|
8028
8724
|
}, [historyMode, setHistoryAvailability]);
|
|
8725
|
+
(0, import_react17.useEffect)(() => {
|
|
8726
|
+
refs.historyRef.current.clear();
|
|
8727
|
+
syncHistoryAvailability();
|
|
8728
|
+
}, [enabled, syncHistoryAvailability]);
|
|
8029
8729
|
const sensors = useSensors(
|
|
8030
8730
|
useSensor(PointerSensor, { activationConstraint: { distance: 8 } })
|
|
8031
8731
|
);
|
|
8032
|
-
const collisionDetection = (0,
|
|
8732
|
+
const collisionDetection = (0, import_react17.useCallback)(
|
|
8033
8733
|
(args) => createDesignModeCollisionDetection(refs.blockedContainerIdsRef.current)(args),
|
|
8034
8734
|
[]
|
|
8035
8735
|
// eslint-disable-line react-hooks/exhaustive-deps -- refs are stable
|
|
8036
8736
|
);
|
|
8037
|
-
const [insideRect, setInsideRect] = (0,
|
|
8038
|
-
const [dropLine, setDropLine] = (0,
|
|
8039
|
-
(0,
|
|
8737
|
+
const [insideRect, setInsideRect] = (0, import_react17.useState)(null);
|
|
8738
|
+
const [dropLine, setDropLine] = (0, import_react17.useState)(null);
|
|
8739
|
+
(0, import_react17.useEffect)(() => {
|
|
8040
8740
|
if (!enabled) return;
|
|
8041
8741
|
const fn = (e) => {
|
|
8042
8742
|
refs.mouseRef.current = { x: e.clientX, y: e.clientY };
|
|
@@ -8044,7 +8744,7 @@ function DesignModeOverlay() {
|
|
|
8044
8744
|
window.addEventListener("pointermove", fn, { capture: true, passive: true });
|
|
8045
8745
|
return () => window.removeEventListener("pointermove", fn, { capture: true });
|
|
8046
8746
|
}, [enabled]);
|
|
8047
|
-
(0,
|
|
8747
|
+
(0, import_react17.useEffect)(() => {
|
|
8048
8748
|
if (!enabled) return;
|
|
8049
8749
|
if (historyMode !== "local") return;
|
|
8050
8750
|
const onKeyDown = (e) => {
|
|
@@ -8073,7 +8773,7 @@ function DesignModeOverlay() {
|
|
|
8073
8773
|
setInsideRect,
|
|
8074
8774
|
setDropLine
|
|
8075
8775
|
});
|
|
8076
|
-
(0,
|
|
8776
|
+
(0, import_react17.useEffect)(() => {
|
|
8077
8777
|
if (!enabled || activeDrag) return;
|
|
8078
8778
|
if (undoRequestId === refs.processedUndoIdRef.current) return;
|
|
8079
8779
|
refs.processedUndoIdRef.current = undoRequestId;
|
|
@@ -8090,7 +8790,7 @@ function DesignModeOverlay() {
|
|
|
8090
8790
|
});
|
|
8091
8791
|
syncHistoryAvailability();
|
|
8092
8792
|
}, [undoRequestId, enabled, activeDrag, applyCommand, resume, selectElement, syncHistoryAvailability, undoLastChange]);
|
|
8093
|
-
(0,
|
|
8793
|
+
(0, import_react17.useEffect)(() => {
|
|
8094
8794
|
if (!enabled || activeDrag || historyMode !== "local") return;
|
|
8095
8795
|
if (redoRequestId === refs.processedRedoIdRef.current) return;
|
|
8096
8796
|
refs.processedRedoIdRef.current = redoRequestId;
|
|
@@ -8102,49 +8802,29 @@ function DesignModeOverlay() {
|
|
|
8102
8802
|
}
|
|
8103
8803
|
syncHistoryAvailability();
|
|
8104
8804
|
}, [redoRequestId, enabled, activeDrag, applyCommand, historyMode, resume, selectElement, syncHistoryAvailability, redoLastChange]);
|
|
8105
|
-
(0,
|
|
8805
|
+
(0, import_react17.useEffect)(() => {
|
|
8106
8806
|
syncHistoryAvailability();
|
|
8107
8807
|
}, [syncHistoryAvailability]);
|
|
8108
|
-
(0,
|
|
8808
|
+
(0, import_react17.useEffect)(() => {
|
|
8109
8809
|
dispatchRuntimeEvent({
|
|
8110
8810
|
type: "design-mode-changed",
|
|
8111
8811
|
mode: enabled ? "design" : "off"
|
|
8112
8812
|
});
|
|
8113
8813
|
}, [enabled]);
|
|
8114
|
-
(0,
|
|
8814
|
+
(0, import_react17.useEffect)(() => {
|
|
8115
8815
|
const aiOutput = exportChangesForAI();
|
|
8116
8816
|
const updatedAt = orderedChanges.length > 0 ? orderedChanges[orderedChanges.length - 1]?.at ?? Date.now() : Date.now();
|
|
8117
8817
|
dispatchRuntimeEvent({
|
|
8118
8818
|
type: "arrange-session-changed",
|
|
8119
|
-
session: {
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
id: `${event.kind}:${event.operationId}:${index}`,
|
|
8124
|
-
kind: event.kind,
|
|
8125
|
-
operationId: event.operationId,
|
|
8126
|
-
commandType: event.kind === "move" ? event.commandType : void 0,
|
|
8127
|
-
nodeKey: event.nodeKey,
|
|
8128
|
-
nodeId: event.nodeId,
|
|
8129
|
-
inspectorRef: event.inspectorRef,
|
|
8130
|
-
selectedNodeKey: event.kind === "move" ? event.selectedNodeKey : void 0,
|
|
8131
|
-
selectedNodeId: event.kind === "move" ? event.selectedNodeId : void 0,
|
|
8132
|
-
selectedInspectorRef: event.kind === "move" ? event.selectedInspectorRef : void 0,
|
|
8133
|
-
anchorNodeKey: event.kind === "move" ? event.anchorNodeKey : void 0,
|
|
8134
|
-
anchorNodeId: event.kind === "move" ? event.anchorNodeId : void 0,
|
|
8135
|
-
summary: summarizeEditorChangeEvent(event),
|
|
8136
|
-
at: event.at
|
|
8137
|
-
})),
|
|
8138
|
-
output: {
|
|
8139
|
-
json: aiOutput,
|
|
8140
|
-
prompt: aiOutput.aiPromptContext,
|
|
8141
|
-
summary: orderedChanges.length === 0 ? "No arrange changes recorded yet." : `${orderedChanges.length} arrange change${orderedChanges.length === 1 ? "" : "s"} recorded.`
|
|
8142
|
-
},
|
|
8819
|
+
session: buildArrangeSessionSnapshot({
|
|
8820
|
+
enabled,
|
|
8821
|
+
orderedChanges,
|
|
8822
|
+
aiOutput,
|
|
8143
8823
|
updatedAt
|
|
8144
|
-
}
|
|
8824
|
+
})
|
|
8145
8825
|
});
|
|
8146
8826
|
}, [enabled, exportChangesForAI, orderedChanges]);
|
|
8147
|
-
(0,
|
|
8827
|
+
(0, import_react17.useEffect)(() => {
|
|
8148
8828
|
if (!enabled) return;
|
|
8149
8829
|
document.body.classList.add("design-mode-active");
|
|
8150
8830
|
return () => document.body.classList.remove("design-mode-active");
|
|
@@ -8157,6 +8837,13 @@ function DesignModeOverlay() {
|
|
|
8157
8837
|
autoScrollStateRef: refs.autoScrollStateRef
|
|
8158
8838
|
});
|
|
8159
8839
|
useDragVisualLoop({ activeDrag, refs, getCommitLaneSnapshot, setInsideRect, setDropLine });
|
|
8840
|
+
useExternalDragLoop({
|
|
8841
|
+
externalDrag,
|
|
8842
|
+
refs,
|
|
8843
|
+
elements,
|
|
8844
|
+
resolveNodeElement,
|
|
8845
|
+
setDropLine
|
|
8846
|
+
});
|
|
8160
8847
|
const { handleResizeHandlePointerDown } = useResizeSession({
|
|
8161
8848
|
enabled,
|
|
8162
8849
|
refs,
|
|
@@ -8212,7 +8899,7 @@ function DesignModeOverlay() {
|
|
|
8212
8899
|
}
|
|
8213
8900
|
}
|
|
8214
8901
|
),
|
|
8215
|
-
dropLine && activeDrag && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8902
|
+
dropLine && (activeDrag ?? externalDrag) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8216
8903
|
"div",
|
|
8217
8904
|
{
|
|
8218
8905
|
"data-design-mode-ui": true,
|
|
@@ -8237,8 +8924,8 @@ function DesignModeOverlay() {
|
|
|
8237
8924
|
}
|
|
8238
8925
|
|
|
8239
8926
|
// src/client/dnd/design-mode/DesignModeErrorBoundary.tsx
|
|
8240
|
-
var
|
|
8241
|
-
var DesignModeErrorBoundary = class extends
|
|
8927
|
+
var import_react18 = __toESM(require("react"));
|
|
8928
|
+
var DesignModeErrorBoundary = class extends import_react18.default.Component {
|
|
8242
8929
|
constructor(props) {
|
|
8243
8930
|
super(props);
|
|
8244
8931
|
this.state = { hasError: false };
|
|
@@ -8271,35 +8958,40 @@ var combinedCollisionDetection = (args) => {
|
|
|
8271
8958
|
|
|
8272
8959
|
// src/client/dnd/DndProvider.tsx
|
|
8273
8960
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
8961
|
+
var externalDragMouse = { x: 0, y: 0, commitRequested: false };
|
|
8274
8962
|
function DndProvider({ children }) {
|
|
8275
8963
|
const setActive = useDndStore((s) => s.setActive);
|
|
8276
8964
|
const dragEndHandlers = useDndStore((s) => s.dragEndHandlers);
|
|
8277
|
-
const toggle = useDesignModeStore((s) => s.toggle);
|
|
8278
8965
|
const designModeEnabled = useDesignModeStore((s) => s.enabled);
|
|
8279
|
-
const setDesignModeEnabled = useDesignModeStore((s) => s.setEnabled);
|
|
8280
8966
|
const setHistoryMode = useDesignModeStore((s) => s.setHistoryMode);
|
|
8281
8967
|
const setInspectorTheme = useDesignModeStore((s) => s.setInspectorTheme);
|
|
8282
8968
|
const requestUndo = useDesignModeStore((s) => s.requestUndo);
|
|
8283
|
-
(0,
|
|
8969
|
+
const transitionDesignMode = (0, import_react19.useCallback)((nextEnabled) => {
|
|
8970
|
+
const designModeState = useDesignModeStore.getState();
|
|
8971
|
+
if (designModeState.enabled === nextEnabled) return;
|
|
8972
|
+
designModeState.resetArrangeSession();
|
|
8973
|
+
designModeState.setEnabled(nextEnabled);
|
|
8974
|
+
}, []);
|
|
8975
|
+
(0, import_react19.useEffect)(() => {
|
|
8284
8976
|
const handleKeyDown = (e) => {
|
|
8285
8977
|
if (e.ctrlKey && e.shiftKey && e.key === "D") {
|
|
8286
8978
|
e.preventDefault();
|
|
8287
|
-
|
|
8979
|
+
transitionDesignMode(!useDesignModeStore.getState().enabled);
|
|
8288
8980
|
}
|
|
8289
8981
|
};
|
|
8290
8982
|
window.addEventListener("keydown", handleKeyDown);
|
|
8291
8983
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
8292
|
-
}, [
|
|
8293
|
-
(0,
|
|
8984
|
+
}, [transitionDesignMode]);
|
|
8985
|
+
(0, import_react19.useEffect)(() => {
|
|
8294
8986
|
const handleHostCommand = (event) => {
|
|
8295
8987
|
const detail = event.detail;
|
|
8296
8988
|
if (!detail || typeof detail !== "object") return;
|
|
8297
8989
|
switch (detail.type) {
|
|
8298
8990
|
case "sync-editor-state":
|
|
8299
8991
|
if (detail.mode === "design") {
|
|
8300
|
-
|
|
8992
|
+
transitionDesignMode(true);
|
|
8301
8993
|
} else if (detail.mode === "inspect" || detail.mode === "off") {
|
|
8302
|
-
|
|
8994
|
+
transitionDesignMode(false);
|
|
8303
8995
|
}
|
|
8304
8996
|
if (detail.historyMode) {
|
|
8305
8997
|
setHistoryMode(detail.historyMode);
|
|
@@ -8309,7 +9001,7 @@ function DndProvider({ children }) {
|
|
|
8309
9001
|
}
|
|
8310
9002
|
break;
|
|
8311
9003
|
case "set-design-mode":
|
|
8312
|
-
|
|
9004
|
+
transitionDesignMode(detail.enabled);
|
|
8313
9005
|
break;
|
|
8314
9006
|
case "set-history-mode":
|
|
8315
9007
|
setHistoryMode(detail.historyMode);
|
|
@@ -8320,6 +9012,21 @@ function DndProvider({ children }) {
|
|
|
8320
9012
|
case "request-undo":
|
|
8321
9013
|
requestUndo();
|
|
8322
9014
|
break;
|
|
9015
|
+
case "external-drag-start":
|
|
9016
|
+
useDesignModeStore.getState().startExternalDrag(detail.component);
|
|
9017
|
+
break;
|
|
9018
|
+
case "external-drag-move":
|
|
9019
|
+
externalDragMouse.x = detail.clientX;
|
|
9020
|
+
externalDragMouse.y = detail.clientY;
|
|
9021
|
+
break;
|
|
9022
|
+
case "external-drag-end":
|
|
9023
|
+
externalDragMouse.x = detail.clientX;
|
|
9024
|
+
externalDragMouse.y = detail.clientY;
|
|
9025
|
+
externalDragMouse.commitRequested = true;
|
|
9026
|
+
break;
|
|
9027
|
+
case "external-drag-cancel":
|
|
9028
|
+
useDesignModeStore.getState().cancelExternalDrag();
|
|
9029
|
+
break;
|
|
8323
9030
|
default:
|
|
8324
9031
|
break;
|
|
8325
9032
|
}
|
|
@@ -8329,7 +9036,7 @@ function DndProvider({ children }) {
|
|
|
8329
9036
|
window.removeEventListener(HOST_COMMAND_EVENT, handleHostCommand);
|
|
8330
9037
|
};
|
|
8331
9038
|
}, [
|
|
8332
|
-
|
|
9039
|
+
transitionDesignMode,
|
|
8333
9040
|
setHistoryMode,
|
|
8334
9041
|
setInspectorTheme,
|
|
8335
9042
|
requestUndo
|
|
@@ -8337,7 +9044,7 @@ function DndProvider({ children }) {
|
|
|
8337
9044
|
const pointerSensor = useSensor(PointerSensor, { activationConstraint: { distance: 8 } });
|
|
8338
9045
|
const keyboardSensor = useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates });
|
|
8339
9046
|
const sensors = useSensors(pointerSensor, keyboardSensor);
|
|
8340
|
-
const handleDragStart = (0,
|
|
9047
|
+
const handleDragStart = (0, import_react19.useCallback)(
|
|
8341
9048
|
(event) => {
|
|
8342
9049
|
const { active } = event;
|
|
8343
9050
|
const element = document.querySelector(`[data-canvas-node="${active.id}"]`);
|
|
@@ -8345,7 +9052,7 @@ function DndProvider({ children }) {
|
|
|
8345
9052
|
},
|
|
8346
9053
|
[setActive]
|
|
8347
9054
|
);
|
|
8348
|
-
const handleDragEnd = (0,
|
|
9055
|
+
const handleDragEnd = (0, import_react19.useCallback)(
|
|
8349
9056
|
(event) => {
|
|
8350
9057
|
const { active, over } = event;
|
|
8351
9058
|
const dragEndEvent = {
|
|
@@ -8361,9 +9068,10 @@ function DndProvider({ children }) {
|
|
|
8361
9068
|
},
|
|
8362
9069
|
[dragEndHandlers, setActive]
|
|
8363
9070
|
);
|
|
8364
|
-
const handleDesignModeCrash = (0,
|
|
9071
|
+
const handleDesignModeCrash = (0, import_react19.useCallback)(() => {
|
|
8365
9072
|
const designModeState = useDesignModeStore.getState();
|
|
8366
9073
|
designModeState.resetAll();
|
|
9074
|
+
designModeState.resetArrangeSession();
|
|
8367
9075
|
designModeState.setEnabled(false);
|
|
8368
9076
|
}, []);
|
|
8369
9077
|
if (designModeEnabled) {
|
|
@@ -8404,7 +9112,7 @@ function DndProvider({ children }) {
|
|
|
8404
9112
|
}
|
|
8405
9113
|
|
|
8406
9114
|
// src/client/useArchieDevToolsRuntime.ts
|
|
8407
|
-
var
|
|
9115
|
+
var import_react21 = require("react");
|
|
8408
9116
|
|
|
8409
9117
|
// src/client/inject-inspector/archieOrigins.ts
|
|
8410
9118
|
var ARCHIE_HOST_ORIGINS = [
|
|
@@ -8510,10 +9218,9 @@ function injectInspector(opts = {}) {
|
|
|
8510
9218
|
document.head.appendChild(script);
|
|
8511
9219
|
return null;
|
|
8512
9220
|
}
|
|
8513
|
-
const localInspectorModulePath = "./inspector.js";
|
|
8514
9221
|
return import(
|
|
8515
9222
|
/* @vite-ignore */
|
|
8516
|
-
|
|
9223
|
+
"./inspector.js"
|
|
8517
9224
|
).then((m) => {
|
|
8518
9225
|
try {
|
|
8519
9226
|
m.default();
|
|
@@ -8599,13 +9306,13 @@ function setupArchieRouteListener(router) {
|
|
|
8599
9306
|
}
|
|
8600
9307
|
|
|
8601
9308
|
// src/client/runtime/domMetaSanitizer.ts
|
|
8602
|
-
var
|
|
9309
|
+
var import_react20 = __toESM(require("react"));
|
|
8603
9310
|
var _installed = false;
|
|
8604
9311
|
function installDomMetaSanitizer() {
|
|
8605
9312
|
if (_installed) return;
|
|
8606
9313
|
_installed = true;
|
|
8607
|
-
const _origCE =
|
|
8608
|
-
|
|
9314
|
+
const _origCE = import_react20.default.createElement.bind(import_react20.default);
|
|
9315
|
+
import_react20.default.createElement = function patchedCreateElement(type, props, ...children) {
|
|
8609
9316
|
if (typeof type === "string" && props != null && "__editorMeta" in props) {
|
|
8610
9317
|
const { __editorMeta: _stripped, ...rest } = props;
|
|
8611
9318
|
return _origCE(type, rest, ...children);
|
|
@@ -8629,18 +9336,26 @@ installDomMetaSanitizer();
|
|
|
8629
9336
|
installDomMetaSanitizer();
|
|
8630
9337
|
function useArchieDevToolsRuntime({
|
|
8631
9338
|
router,
|
|
8632
|
-
inspector
|
|
9339
|
+
inspector,
|
|
9340
|
+
inspectorOptions
|
|
8633
9341
|
}) {
|
|
8634
|
-
|
|
9342
|
+
const stableOptionsKey = JSON.stringify(inspectorOptions ?? null);
|
|
9343
|
+
const inspectorOptionsRef = (0, import_react21.useRef)(inspectorOptions);
|
|
9344
|
+
inspectorOptionsRef.current = inspectorOptions;
|
|
9345
|
+
(0, import_react21.useEffect)(() => {
|
|
8635
9346
|
if (process.env.NODE_ENV !== "development") {
|
|
8636
9347
|
return;
|
|
8637
9348
|
}
|
|
8638
9349
|
const unsubscribe = setupArchieRouteListener(router);
|
|
8639
|
-
if (inspector) {
|
|
8640
|
-
|
|
9350
|
+
if (inspector !== false) {
|
|
9351
|
+
const isLocalHost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
|
|
9352
|
+
injectInspector({
|
|
9353
|
+
scriptSource: isLocalHost ? "local" : "remote",
|
|
9354
|
+
...inspectorOptionsRef.current
|
|
9355
|
+
});
|
|
8641
9356
|
}
|
|
8642
9357
|
return unsubscribe;
|
|
8643
|
-
}, [router, inspector]);
|
|
9358
|
+
}, [router, inspector, stableOptionsKey]);
|
|
8644
9359
|
}
|
|
8645
9360
|
|
|
8646
9361
|
// src/client/ArchieDevToolProvider.tsx
|
|
@@ -8648,9 +9363,10 @@ var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
|
8648
9363
|
function ArchieDevToolProvider({
|
|
8649
9364
|
children,
|
|
8650
9365
|
router,
|
|
8651
|
-
inspector
|
|
9366
|
+
inspector,
|
|
9367
|
+
inspectorOptions
|
|
8652
9368
|
}) {
|
|
8653
|
-
useArchieDevToolsRuntime({ router, inspector });
|
|
9369
|
+
useArchieDevToolsRuntime({ router, inspector, inspectorOptions });
|
|
8654
9370
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DndProvider, { children });
|
|
8655
9371
|
}
|
|
8656
9372
|
// Annotate the CommonJS export names for ESM import in node:
|