@archie/devtools 0.0.12 → 0.0.15
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 +1456 -713
- package/dist/client/client.mjs +1420 -677
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +43 -5
- package/dist/index.mjs +43 -5
- package/package.json +21 -21
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,18 +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
|
-
|
|
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}`;
|
|
4113
4587
|
}
|
|
4114
4588
|
if (event.payload.after.mode === "grid-span") {
|
|
4115
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}`;
|
|
4116
4590
|
}
|
|
4117
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}`;
|
|
4118
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
|
+
}
|
|
4119
4599
|
function rebuildNodeEdit(orderedChanges, nodeKey) {
|
|
4120
4600
|
let latestMove;
|
|
4121
4601
|
let latestResize;
|
|
@@ -4130,11 +4610,36 @@ function rebuildNodeEdit(orderedChanges, nodeKey) {
|
|
|
4130
4610
|
nodeId = ev.nodeId;
|
|
4131
4611
|
inspectorRef = ev.inspectorRef;
|
|
4132
4612
|
if (ev.kind === "move") latestMove = ev.payload;
|
|
4133
|
-
else latestResize = ev.payload;
|
|
4613
|
+
else if (ev.kind === "resize") latestResize = ev.payload;
|
|
4134
4614
|
}
|
|
4135
4615
|
if (count === 0) return null;
|
|
4136
4616
|
return { nodeKey, nodeId, inspectorRef, latestMove, latestResize, changeCount: count, lastUpdatedAt: lastAt };
|
|
4137
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
|
+
}
|
|
4138
4643
|
var useDesignModeStore = create((set, get) => ({
|
|
4139
4644
|
// UI state
|
|
4140
4645
|
enabled: false,
|
|
@@ -4150,8 +4655,10 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4150
4655
|
nodeEditsByKey: {},
|
|
4151
4656
|
orderedChanges: [],
|
|
4152
4657
|
undoneChanges: [],
|
|
4658
|
+
// External drag
|
|
4659
|
+
externalDrag: null,
|
|
4153
4660
|
// UI actions
|
|
4154
|
-
toggle: () => set((s) => ({ enabled: !s.enabled })),
|
|
4661
|
+
toggle: () => set((s) => ({ enabled: !s.enabled, ...buildEmptyArrangeSessionState() })),
|
|
4155
4662
|
setEnabled: (enabled) => set({ enabled }),
|
|
4156
4663
|
setHovered: (selector) => set({ hoveredSelector: selector }),
|
|
4157
4664
|
setSelected: (selector) => set({ selectedSelector: selector }),
|
|
@@ -4166,8 +4673,11 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4166
4673
|
canUndo: false,
|
|
4167
4674
|
canRedo: false
|
|
4168
4675
|
}),
|
|
4676
|
+
resetArrangeSession: () => set(buildEmptyArrangeSessionState()),
|
|
4169
4677
|
// Change tracking actions
|
|
4170
4678
|
recordMoveChange: ({
|
|
4679
|
+
operationId,
|
|
4680
|
+
commandType,
|
|
4171
4681
|
nodeKey,
|
|
4172
4682
|
nodeId,
|
|
4173
4683
|
inspectorRef,
|
|
@@ -4176,13 +4686,24 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4176
4686
|
selectedInspectorRef,
|
|
4177
4687
|
anchorNodeKey,
|
|
4178
4688
|
anchorNodeId,
|
|
4689
|
+
sourceContainer,
|
|
4690
|
+
sourceBeforeSibling,
|
|
4691
|
+
sourceAfterSibling,
|
|
4692
|
+
container,
|
|
4693
|
+
beforeSibling,
|
|
4694
|
+
afterSibling,
|
|
4695
|
+
diagnostics,
|
|
4179
4696
|
componentName,
|
|
4180
4697
|
before,
|
|
4181
4698
|
after
|
|
4182
4699
|
}) => {
|
|
4183
4700
|
const now = Date.now();
|
|
4701
|
+
const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
|
|
4702
|
+
const normalizedCommandType = commandType ?? inferMoveCommandType(before, after);
|
|
4184
4703
|
const event = {
|
|
4185
4704
|
kind: "move",
|
|
4705
|
+
operationId: normalizedOperationId,
|
|
4706
|
+
commandType: normalizedCommandType,
|
|
4186
4707
|
nodeKey,
|
|
4187
4708
|
nodeId,
|
|
4188
4709
|
inspectorRef,
|
|
@@ -4191,6 +4712,13 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4191
4712
|
selectedInspectorRef,
|
|
4192
4713
|
anchorNodeKey,
|
|
4193
4714
|
anchorNodeId,
|
|
4715
|
+
sourceContainer: sourceContainer ?? null,
|
|
4716
|
+
sourceBeforeSibling: sourceBeforeSibling ?? null,
|
|
4717
|
+
sourceAfterSibling: sourceAfterSibling ?? null,
|
|
4718
|
+
container: container ?? null,
|
|
4719
|
+
beforeSibling: beforeSibling ?? null,
|
|
4720
|
+
afterSibling: afterSibling ?? null,
|
|
4721
|
+
diagnostics: diagnostics ?? null,
|
|
4194
4722
|
payload: { before, after },
|
|
4195
4723
|
at: now
|
|
4196
4724
|
};
|
|
@@ -4213,10 +4741,20 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4213
4741
|
};
|
|
4214
4742
|
});
|
|
4215
4743
|
},
|
|
4216
|
-
recordResizeChange: ({
|
|
4744
|
+
recordResizeChange: ({
|
|
4745
|
+
operationId,
|
|
4746
|
+
nodeKey,
|
|
4747
|
+
nodeId,
|
|
4748
|
+
inspectorRef,
|
|
4749
|
+
componentName,
|
|
4750
|
+
before,
|
|
4751
|
+
after
|
|
4752
|
+
}) => {
|
|
4217
4753
|
const now = Date.now();
|
|
4754
|
+
const normalizedOperationId = operationId ?? buildFallbackOperationId(now, nodeId);
|
|
4218
4755
|
const event = {
|
|
4219
4756
|
kind: "resize",
|
|
4757
|
+
operationId: normalizedOperationId,
|
|
4220
4758
|
nodeKey,
|
|
4221
4759
|
nodeId,
|
|
4222
4760
|
inspectorRef,
|
|
@@ -4242,6 +4780,52 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4242
4780
|
};
|
|
4243
4781
|
});
|
|
4244
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 }),
|
|
4245
4829
|
undoLastChange: () => {
|
|
4246
4830
|
const { orderedChanges, undoneChanges } = get();
|
|
4247
4831
|
if (orderedChanges.length === 0) return null;
|
|
@@ -4267,7 +4851,8 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4267
4851
|
},
|
|
4268
4852
|
clearChanges: () => set({ orderedChanges: [], undoneChanges: [], nodeEditsByKey: {} }),
|
|
4269
4853
|
exportChangesForAI: () => {
|
|
4270
|
-
const { orderedChanges, nodeEditsByKey } = get();
|
|
4854
|
+
const { orderedChanges: rawChanges, nodeEditsByKey } = get();
|
|
4855
|
+
const orderedChanges = coalesceOrderedChanges(rawChanges);
|
|
4271
4856
|
const changesByFile = {};
|
|
4272
4857
|
for (const event of orderedChanges) {
|
|
4273
4858
|
const fileKey = event.inspectorRef?.relativePath ?? "__runtime__";
|
|
@@ -4281,180 +4866,127 @@ var useDesignModeStore = create((set, get) => ({
|
|
|
4281
4866
|
lines.push(` ${summarizeEditorChangeEvent(ev)}`);
|
|
4282
4867
|
}
|
|
4283
4868
|
}
|
|
4869
|
+
const diagnostics = mergeRuntimeArrangeDiagnostics(
|
|
4870
|
+
orderedChanges.map(
|
|
4871
|
+
(event) => event.kind === "move" ? event.diagnostics : null
|
|
4872
|
+
)
|
|
4873
|
+
);
|
|
4284
4874
|
return {
|
|
4285
4875
|
changesByFile,
|
|
4286
4876
|
finalSnapshot: { ...nodeEditsByKey },
|
|
4287
|
-
aiPromptContext: lines.join("\n")
|
|
4877
|
+
aiPromptContext: lines.join("\n"),
|
|
4878
|
+
...diagnostics ? { diagnostics } : {}
|
|
4288
4879
|
};
|
|
4289
4880
|
}
|
|
4290
4881
|
}));
|
|
4291
4882
|
|
|
4292
4883
|
// src/client/dnd/design-mode/DesignModeOverlay.tsx
|
|
4293
|
-
var
|
|
4884
|
+
var import_react17 = require("react");
|
|
4294
4885
|
|
|
4295
4886
|
// src/client/dnd/design-mode/useElementScanner.ts
|
|
4296
4887
|
var import_react6 = require("react");
|
|
4297
4888
|
|
|
4298
|
-
// src/client/dnd/design-mode/
|
|
4299
|
-
var
|
|
4300
|
-
var
|
|
4301
|
-
|
|
4302
|
-
|
|
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));
|
|
4303
4896
|
}
|
|
4304
|
-
function
|
|
4305
|
-
|
|
4306
|
-
const tag = el.tagName.toLowerCase();
|
|
4307
|
-
if (STRUCTURAL_TAGS.has(tag)) return true;
|
|
4308
|
-
if (el.id === "root") return true;
|
|
4309
|
-
return tag === "main" && (el.parentElement === document.body || el.parentElement?.id === "root");
|
|
4897
|
+
function buildNodeSelector(nodeId) {
|
|
4898
|
+
return `[${DND_NODE_ID_ATTR}="${escapeCssAttrValue(nodeId)}"]`;
|
|
4310
4899
|
}
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
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";
|
|
4315
4906
|
}
|
|
4316
|
-
function
|
|
4317
|
-
return
|
|
4907
|
+
function isPointerInEdgeZone(px, py, guard) {
|
|
4908
|
+
return px <= guard || py <= guard || px >= window.innerWidth - guard || py >= window.innerHeight - guard;
|
|
4318
4909
|
}
|
|
4319
|
-
function
|
|
4320
|
-
|
|
4321
|
-
if (!container) return false;
|
|
4322
|
-
if (container.children.length < 2) return false;
|
|
4323
|
-
return !isStructuralContainer(containerId, nodeMap);
|
|
4910
|
+
function isPointerInPageEdgeZone(px, py) {
|
|
4911
|
+
return isPointerInEdgeZone(px, py, PAGE_EDGE_GUARD);
|
|
4324
4912
|
}
|
|
4325
|
-
function
|
|
4326
|
-
|
|
4327
|
-
for (const containerId of projection.containerIndex.keys()) {
|
|
4328
|
-
if (containerId === sourceContainerId) continue;
|
|
4329
|
-
if (isStructuralContainer(containerId, nodeMap)) blocked.add(containerId);
|
|
4330
|
-
}
|
|
4331
|
-
return blocked;
|
|
4913
|
+
function isPointerInHardPageEdgeZone(px, py) {
|
|
4914
|
+
return isPointerInEdgeZone(px, py, HARD_PAGE_EDGE_GUARD);
|
|
4332
4915
|
}
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
const
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
}
|
|
4344
|
-
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 };
|
|
4345
4926
|
}
|
|
4346
|
-
function
|
|
4347
|
-
|
|
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;
|
|
4348
4930
|
}
|
|
4349
|
-
function
|
|
4350
|
-
return
|
|
4931
|
+
function isPointerOutsideSafeZone(px, py, safeZone) {
|
|
4932
|
+
return !isPointerInSafeZone(px, py, safeZone);
|
|
4351
4933
|
}
|
|
4352
|
-
function
|
|
4353
|
-
|
|
4354
|
-
return meta.componentName[0] !== meta.componentName[0].toLowerCase();
|
|
4934
|
+
function isPointerBlocked(px, py, safeZone) {
|
|
4935
|
+
return isPointerInHardPageEdgeZone(px, py) || isPointerOutsideSafeZone(px, py, safeZone);
|
|
4355
4936
|
}
|
|
4356
|
-
function
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
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;
|
|
4360
4947
|
}
|
|
4361
|
-
return
|
|
4948
|
+
return null;
|
|
4362
4949
|
}
|
|
4363
|
-
function
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
if (child.hasAttribute("data-design-mode-ui")) return false;
|
|
4367
|
-
if (child.hasAttribute("data-design-mode-allow")) return false;
|
|
4368
|
-
return !shouldIgnoreAsVirtualRuntime(child);
|
|
4369
|
-
});
|
|
4950
|
+
function escapeCssAttrValue(value) {
|
|
4951
|
+
const esc = globalThis.CSS?.escape;
|
|
4952
|
+
return esc ? esc(value) : value.replace(/["\\]/g, "\\$&");
|
|
4370
4953
|
}
|
|
4371
|
-
function
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
if (tag === "script" || tag === "style" || tag === "noscript") return true;
|
|
4375
|
-
if (el instanceof SVGElement && !isRootSvg(el)) return true;
|
|
4376
|
-
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]");
|
|
4377
4957
|
}
|
|
4378
|
-
function
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
const
|
|
4382
|
-
const
|
|
4383
|
-
|
|
4384
|
-
directMetaCache.set(el, resolved);
|
|
4385
|
-
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;
|
|
4386
4964
|
}
|
|
4387
|
-
function
|
|
4388
|
-
const
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
metaCache.set(el, meta);
|
|
4395
|
-
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;
|
|
4396
4972
|
}
|
|
4397
|
-
fiber = fiber.return;
|
|
4398
|
-
}
|
|
4399
|
-
metaCache.set(el, null);
|
|
4400
|
-
return null;
|
|
4401
|
-
}
|
|
4402
|
-
function findMetaOwnerElement(el) {
|
|
4403
|
-
let current = el;
|
|
4404
|
-
while (current) {
|
|
4405
|
-
if (getEditorMeta(current)) return current;
|
|
4406
|
-
current = current.parentElement;
|
|
4407
4973
|
}
|
|
4408
4974
|
return null;
|
|
4409
4975
|
}
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
const
|
|
4414
|
-
if (
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
return children[0];
|
|
4418
|
-
}
|
|
4419
|
-
if (directMeta && !isWrapperMeta(directMeta)) return el;
|
|
4420
|
-
const MAX_STEPS = 10;
|
|
4421
|
-
const ownerNodeId = ownerMeta?.nodeId ?? null;
|
|
4422
|
-
let outermost = el;
|
|
4423
|
-
let parent = el.parentElement;
|
|
4424
|
-
for (let i = 0; i < MAX_STEPS; i += 1) {
|
|
4425
|
-
if (!parent || parent === document.body) break;
|
|
4426
|
-
if (shouldIgnoreAsVirtualRuntime(parent)) break;
|
|
4427
|
-
const parentMeta = getEditorMeta(parent);
|
|
4428
|
-
if (!parentMeta) break;
|
|
4429
|
-
if (ownerNodeId && parentMeta.nodeId !== ownerNodeId) break;
|
|
4430
|
-
if (isStructuralComponentName(parentMeta.componentName)) break;
|
|
4431
|
-
if (!isWrapperMeta(parentMeta)) break;
|
|
4432
|
-
if (isPassthroughMeta(parentMeta)) break;
|
|
4433
|
-
if (hasOwnTextContent(parent)) break;
|
|
4434
|
-
const children = getCandidateChildren(parent);
|
|
4435
|
-
if (children.length !== 1) break;
|
|
4436
|
-
outermost = parent;
|
|
4437
|
-
parent = parent.parentElement;
|
|
4438
|
-
}
|
|
4439
|
-
return outermost;
|
|
4440
|
-
}
|
|
4441
|
-
function resolveDragSurface(el) {
|
|
4442
|
-
const host = resolveHostElementFromFiberChain(el);
|
|
4443
|
-
if (!host) {
|
|
4444
|
-
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}`);
|
|
4445
4983
|
}
|
|
4446
|
-
const
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
return {
|
|
4450
|
-
host,
|
|
4451
|
-
metaOwner,
|
|
4452
|
-
kind
|
|
4453
|
-
};
|
|
4984
|
+
const id = _undoParentNodeIdMap.get(el);
|
|
4985
|
+
el.setAttribute(DND_NODE_ID_ATTR, id);
|
|
4986
|
+
return id;
|
|
4454
4987
|
}
|
|
4455
4988
|
|
|
4456
4989
|
// src/client/dnd/design-mode/useElementScanner.ts
|
|
4457
|
-
var DND_NODE_ID_ATTR = "data-dnd-node-id";
|
|
4458
4990
|
function resolveContainerStrategy(el) {
|
|
4459
4991
|
const cs = getComputedStyle(el);
|
|
4460
4992
|
const d = cs.display;
|
|
@@ -4485,7 +5017,7 @@ function getRuntimeNodeId(el) {
|
|
|
4485
5017
|
}
|
|
4486
5018
|
function getEditorMetaNodeId(el) {
|
|
4487
5019
|
if (!(el instanceof HTMLElement)) return null;
|
|
4488
|
-
return
|
|
5020
|
+
return getDirectEditorMeta(el)?.nodeId ?? null;
|
|
4489
5021
|
}
|
|
4490
5022
|
function isInspectorEligible(el) {
|
|
4491
5023
|
if (getEditorMetaNodeId(el) !== null) return "editor-meta";
|
|
@@ -4509,7 +5041,7 @@ function inferEligibilityFromSortableParent(el) {
|
|
|
4509
5041
|
if (child.hasAttribute("data-design-mode-ui")) return false;
|
|
4510
5042
|
return !isRuntimeVisualInternal(child);
|
|
4511
5043
|
});
|
|
4512
|
-
if (siblingElements.length <
|
|
5044
|
+
if (siblingElements.length < 1) return null;
|
|
4513
5045
|
return "inferred-sortable-descendant";
|
|
4514
5046
|
}
|
|
4515
5047
|
function ensureUniqueNodeId(base, used) {
|
|
@@ -5063,7 +5595,15 @@ function buildProjection(elements, rectOverrides) {
|
|
|
5063
5595
|
}
|
|
5064
5596
|
const containerIndex = /* @__PURE__ */ new Map();
|
|
5065
5597
|
for (const node of nodeMap.values()) {
|
|
5066
|
-
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
|
+
}
|
|
5067
5607
|
node.sortable = true;
|
|
5068
5608
|
const firstChild = elementIndex.get(node.children[0]);
|
|
5069
5609
|
node.strategy = firstChild?.containerStrategy ?? "vertical";
|
|
@@ -5134,31 +5674,25 @@ function buildVerticalSlotRect(children, nodeMap, cRect, i, n) {
|
|
|
5134
5674
|
const top = i === 0 ? cRect.top : nodeMap.get(children[i - 1])?.rect.bottom ?? cRect.top;
|
|
5135
5675
|
const bottom = i === n ? cRect.bottom : nodeMap.get(children[i])?.rect.top ?? cRect.bottom;
|
|
5136
5676
|
const height = Math.max(0, bottom - top);
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
width: cRect.width,
|
|
5145
|
-
height
|
|
5146
|
-
};
|
|
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 };
|
|
5147
5684
|
}
|
|
5148
5685
|
function buildHorizontalSlotRect(children, nodeMap, cRect, i, n) {
|
|
5149
5686
|
const left = i === 0 ? cRect.left : nodeMap.get(children[i - 1])?.rect.right ?? cRect.left;
|
|
5150
5687
|
const right = i === n ? cRect.right : nodeMap.get(children[i])?.rect.left ?? cRect.right;
|
|
5151
5688
|
const width = Math.max(0, right - left);
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
width,
|
|
5160
|
-
height: cRect.height
|
|
5161
|
-
};
|
|
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 };
|
|
5162
5696
|
}
|
|
5163
5697
|
function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
|
|
5164
5698
|
const findRow = (childIdx) => rows.find((r) => childIdx >= r.startIdx && childIdx <= r.endIdx) ?? null;
|
|
@@ -5222,6 +5756,79 @@ function buildRectSlotRect(children, nodeMap, cRect, i, n, rows) {
|
|
|
5222
5756
|
};
|
|
5223
5757
|
}
|
|
5224
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
|
+
__publicField(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
|
+
|
|
5225
5832
|
// src/client/dnd/design-mode/resize.ts
|
|
5226
5833
|
function splitTopLevelSpaceSeparated(value) {
|
|
5227
5834
|
const tokens = [];
|
|
@@ -5253,9 +5860,6 @@ function parseSpanValue(value) {
|
|
|
5253
5860
|
const parsed = Number.parseInt(match[1], 10);
|
|
5254
5861
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
|
|
5255
5862
|
}
|
|
5256
|
-
function clamp(value, min, max) {
|
|
5257
|
-
return Math.max(min, Math.min(max, value));
|
|
5258
|
-
}
|
|
5259
5863
|
function resolveResizeTargetElement(selectedEl) {
|
|
5260
5864
|
const elementChildren = Array.from(selectedEl.children).filter(
|
|
5261
5865
|
(child2) => child2 instanceof HTMLElement
|
|
@@ -5336,100 +5940,6 @@ function applyStyleSnapshot(el, snapshot) {
|
|
|
5336
5940
|
}
|
|
5337
5941
|
}
|
|
5338
5942
|
|
|
5339
|
-
// src/client/dnd/design-mode/helpers.ts
|
|
5340
|
-
var DND_NODE_ID_ATTR2 = "data-dnd-node-id";
|
|
5341
|
-
var PAGE_EDGE_GUARD = 10;
|
|
5342
|
-
var HARD_PAGE_EDGE_GUARD = 4;
|
|
5343
|
-
var SAFE_ZONE_INSET = 8;
|
|
5344
|
-
var LARGE_NODE_NEST_BLOCK_MIN_WIDTH = 520;
|
|
5345
|
-
var LARGE_NODE_NEST_BLOCK_MIN_HEIGHT = 260;
|
|
5346
|
-
var LARGE_NODE_NEST_BLOCK_MIN_AREA = 18e4;
|
|
5347
|
-
function isEligibleForDrag(sc) {
|
|
5348
|
-
const source = sc.eligibilitySource ?? "editor-meta";
|
|
5349
|
-
return source === "editor-meta" || source === "force-allow" || source === "inferred-sortable-descendant";
|
|
5350
|
-
}
|
|
5351
|
-
function isPointerInPageEdgeZone(px, py) {
|
|
5352
|
-
return px <= PAGE_EDGE_GUARD || py <= PAGE_EDGE_GUARD || px >= window.innerWidth - PAGE_EDGE_GUARD || py >= window.innerHeight - PAGE_EDGE_GUARD;
|
|
5353
|
-
}
|
|
5354
|
-
function isPointerInHardPageEdgeZone(px, py) {
|
|
5355
|
-
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;
|
|
5356
|
-
}
|
|
5357
|
-
function resolveSafeZoneRect() {
|
|
5358
|
-
const root = document.getElementById("root");
|
|
5359
|
-
if (!root) return null;
|
|
5360
|
-
const rect = root.getBoundingClientRect();
|
|
5361
|
-
const left = rect.left + SAFE_ZONE_INSET;
|
|
5362
|
-
const top = rect.top + SAFE_ZONE_INSET;
|
|
5363
|
-
const right = rect.right - SAFE_ZONE_INSET;
|
|
5364
|
-
const bottom = rect.bottom - SAFE_ZONE_INSET;
|
|
5365
|
-
if (right <= left || bottom <= top) return null;
|
|
5366
|
-
return { left, top, right, bottom };
|
|
5367
|
-
}
|
|
5368
|
-
function isPointerInSafeZone(px, py, safeZone) {
|
|
5369
|
-
if (!safeZone) return true;
|
|
5370
|
-
return px >= safeZone.left && px <= safeZone.right && py >= safeZone.top && py <= safeZone.bottom;
|
|
5371
|
-
}
|
|
5372
|
-
function isPointerOutsideSafeZone(px, py, safeZone) {
|
|
5373
|
-
return !isPointerInSafeZone(px, py, safeZone);
|
|
5374
|
-
}
|
|
5375
|
-
function isPointerBlocked(px, py, safeZone) {
|
|
5376
|
-
return isPointerInHardPageEdgeZone(px, py) || isPointerOutsideSafeZone(px, py, safeZone);
|
|
5377
|
-
}
|
|
5378
|
-
function shouldBlockNestForLargeNode(w, h) {
|
|
5379
|
-
return w >= LARGE_NODE_NEST_BLOCK_MIN_WIDTH || h >= LARGE_NODE_NEST_BLOCK_MIN_HEIGHT || w * h >= LARGE_NODE_NEST_BLOCK_MIN_AREA;
|
|
5380
|
-
}
|
|
5381
|
-
function findScrollableAncestor(start, dx, dy) {
|
|
5382
|
-
let el = start;
|
|
5383
|
-
while (el && el !== document.body) {
|
|
5384
|
-
const cs = getComputedStyle(el);
|
|
5385
|
-
if (dy !== 0 && (cs.overflowY === "auto" || cs.overflowY === "scroll") && el.scrollHeight > el.clientHeight + 1) return el;
|
|
5386
|
-
if (dx !== 0 && (cs.overflowX === "auto" || cs.overflowX === "scroll") && el.scrollWidth > el.clientWidth + 1) return el;
|
|
5387
|
-
el = el.parentElement;
|
|
5388
|
-
}
|
|
5389
|
-
return null;
|
|
5390
|
-
}
|
|
5391
|
-
function escapeCssAttrValue(value) {
|
|
5392
|
-
const esc = globalThis.CSS?.escape;
|
|
5393
|
-
return esc ? esc(value) : value.replace(/["\\]/g, "\\$&");
|
|
5394
|
-
}
|
|
5395
|
-
function isDesignModeUiElement(el) {
|
|
5396
|
-
if (!(el instanceof HTMLElement)) return false;
|
|
5397
|
-
return el.hasAttribute("data-design-mode-ui") || !!el.closest("[data-design-mode-ui]");
|
|
5398
|
-
}
|
|
5399
|
-
function isElementScrollable(el) {
|
|
5400
|
-
if (!(el instanceof HTMLElement)) return false;
|
|
5401
|
-
const cs = getComputedStyle(el);
|
|
5402
|
-
const overY = cs.overflowY;
|
|
5403
|
-
const overX = cs.overflowX;
|
|
5404
|
-
return (overY === "auto" || overY === "scroll") && el.scrollHeight > el.clientHeight || (overX === "auto" || overX === "scroll") && el.scrollWidth > el.clientWidth;
|
|
5405
|
-
}
|
|
5406
|
-
function resolveScrollableFromHitStack(stack) {
|
|
5407
|
-
for (const hit of stack) {
|
|
5408
|
-
if (isDesignModeUiElement(hit)) continue;
|
|
5409
|
-
let el = hit;
|
|
5410
|
-
while (el) {
|
|
5411
|
-
if (isElementScrollable(el)) return el;
|
|
5412
|
-
el = el.parentElement;
|
|
5413
|
-
}
|
|
5414
|
-
}
|
|
5415
|
-
return null;
|
|
5416
|
-
}
|
|
5417
|
-
var _undoParentNodeIdMap = /* @__PURE__ */ new WeakMap();
|
|
5418
|
-
var _undoParentNodeIdCounter = 0;
|
|
5419
|
-
function ensureParentNodeId(el) {
|
|
5420
|
-
const existing = el.getAttribute(DND_NODE_ID_ATTR2);
|
|
5421
|
-
if (existing) return existing;
|
|
5422
|
-
if (!_undoParentNodeIdMap.has(el)) {
|
|
5423
|
-
_undoParentNodeIdMap.set(el, `dnd-parent:${++_undoParentNodeIdCounter}`);
|
|
5424
|
-
}
|
|
5425
|
-
const id = _undoParentNodeIdMap.get(el);
|
|
5426
|
-
el.setAttribute(DND_NODE_ID_ATTR2, id);
|
|
5427
|
-
return id;
|
|
5428
|
-
}
|
|
5429
|
-
function ensureElementNodeId(el) {
|
|
5430
|
-
return ensureParentNodeId(el);
|
|
5431
|
-
}
|
|
5432
|
-
|
|
5433
5943
|
// src/client/dnd/design-mode/drag-preview.tsx
|
|
5434
5944
|
var import_react9 = require("react");
|
|
5435
5945
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -5530,7 +6040,7 @@ function findNearestContainerId(nodeId, projection, nodeMap, allowStructuralFall
|
|
|
5530
6040
|
const parentId = node?.parentId ?? null;
|
|
5531
6041
|
if (!parentId) break;
|
|
5532
6042
|
const parentContainer = projection.containerIndex.get(parentId);
|
|
5533
|
-
if (parentContainer && parentContainer.children.length >=
|
|
6043
|
+
if (parentContainer && parentContainer.children.length >= 1) {
|
|
5534
6044
|
if (isValidLaneContainer(parentId, projection, nodeMap)) return parentId;
|
|
5535
6045
|
if (allowStructuralFallback && !structuralFallback) structuralFallback = parentId;
|
|
5536
6046
|
}
|
|
@@ -5615,12 +6125,6 @@ function findDirectChildUnderParent(child, parent) {
|
|
|
5615
6125
|
}
|
|
5616
6126
|
return null;
|
|
5617
6127
|
}
|
|
5618
|
-
function isContiguous(indices) {
|
|
5619
|
-
if (indices.length === 0) return false;
|
|
5620
|
-
const min = Math.min(...indices);
|
|
5621
|
-
const max = Math.max(...indices);
|
|
5622
|
-
return max - min + 1 === indices.length;
|
|
5623
|
-
}
|
|
5624
6128
|
function createPlacement(parentNodeId, laneContainerId, commitNodeId, beforeNodeId, afterNodeId, index) {
|
|
5625
6129
|
return {
|
|
5626
6130
|
parentNodeId,
|
|
@@ -5634,7 +6138,16 @@ function createPlacement(parentNodeId, laneContainerId, commitNodeId, beforeNode
|
|
|
5634
6138
|
function buildCommitLaneSnapshot(laneContainerId, projection, nodeMap) {
|
|
5635
6139
|
const lane = projection.containerIndex.get(laneContainerId);
|
|
5636
6140
|
const laneElement = nodeMap.get(laneContainerId)?.element ?? null;
|
|
5637
|
-
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
|
+
}
|
|
5638
6151
|
const childElements = lane.children.map((childId) => nodeMap.get(childId)?.element ?? null).filter((el) => !!el);
|
|
5639
6152
|
if (childElements.length !== lane.children.length) return null;
|
|
5640
6153
|
const commitParent = findLowestCommonAncestor(childElements, laneElement);
|
|
@@ -5651,19 +6164,18 @@ function buildCommitLaneSnapshot(laneContainerId, projection, nodeMap) {
|
|
|
5651
6164
|
if (seenRoots.has(commitRoot)) return null;
|
|
5652
6165
|
seenRoots.add(commitRoot);
|
|
5653
6166
|
commitRoots.push(commitRoot);
|
|
5654
|
-
commitNodeByAnchorId.set(anchorNodeId,
|
|
6167
|
+
commitNodeByAnchorId.set(anchorNodeId, ensureParentNodeId(commitRoot));
|
|
5655
6168
|
}
|
|
5656
6169
|
const childList = Array.from(commitParent.children).filter(
|
|
5657
6170
|
(child) => child instanceof HTMLElement
|
|
5658
6171
|
);
|
|
5659
6172
|
const commitRootIndices = commitRoots.map((root) => childList.indexOf(root));
|
|
5660
6173
|
if (commitRootIndices.some((index) => index < 0)) return null;
|
|
5661
|
-
if (!isContiguous(commitRootIndices)) return null;
|
|
5662
6174
|
const domOrderedRoots = [...commitRoots].sort(
|
|
5663
6175
|
(a, b) => childList.indexOf(a) - childList.indexOf(b)
|
|
5664
6176
|
);
|
|
5665
|
-
const projectionOrderedIds = commitRoots.map((root) =>
|
|
5666
|
-
const domOrderedIds = domOrderedRoots.map((root) =>
|
|
6177
|
+
const projectionOrderedIds = commitRoots.map((root) => ensureParentNodeId(root));
|
|
6178
|
+
const domOrderedIds = domOrderedRoots.map((root) => ensureParentNodeId(root));
|
|
5667
6179
|
if (projectionOrderedIds.length !== domOrderedIds.length) return null;
|
|
5668
6180
|
if (projectionOrderedIds.some((id, index) => id !== domOrderedIds[index])) return null;
|
|
5669
6181
|
return {
|
|
@@ -5708,7 +6220,7 @@ function resolveAppendCommitPlacement(parentEl, commitNodeId, laneContainerId) {
|
|
|
5708
6220
|
const children = Array.from(parentEl.children).filter(
|
|
5709
6221
|
(child) => child instanceof HTMLElement
|
|
5710
6222
|
);
|
|
5711
|
-
const lastChild = children.length > 0 ?
|
|
6223
|
+
const lastChild = children.length > 0 ? ensureParentNodeId(children[children.length - 1]) : null;
|
|
5712
6224
|
return createPlacement(
|
|
5713
6225
|
ensureParentNodeId(parentEl),
|
|
5714
6226
|
laneContainerId,
|
|
@@ -5763,6 +6275,58 @@ function createDesignModeCollisionDetection(blockedContainerIds) {
|
|
|
5763
6275
|
};
|
|
5764
6276
|
}
|
|
5765
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
|
+
|
|
5766
6330
|
// src/client/dnd/design-mode/useDesignModeAutoScroll.ts
|
|
5767
6331
|
var import_react10 = require("react");
|
|
5768
6332
|
function edgeVelocity(distanceToEdge, zone, maxSpeed) {
|
|
@@ -5778,11 +6342,16 @@ function findScrollableAtPoint(x, y) {
|
|
|
5778
6342
|
return resolveScrollableFromHitStack(stack) ?? (document.scrollingElement ?? document.documentElement);
|
|
5779
6343
|
}
|
|
5780
6344
|
function getScrollerKey(el) {
|
|
5781
|
-
return el.getAttribute?.(
|
|
6345
|
+
return el.getAttribute?.(DND_NODE_ID_ATTR) ?? el.id ?? el.tagName.toLowerCase();
|
|
5782
6346
|
}
|
|
5783
6347
|
function pointerInsideRect(x, y, rect, inset = 0) {
|
|
5784
6348
|
return x >= rect.left - inset && x <= rect.right + inset && y >= rect.top - inset && y <= rect.bottom + inset;
|
|
5785
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;
|
|
5786
6355
|
function useDesignModeAutoScroll({
|
|
5787
6356
|
active,
|
|
5788
6357
|
mouseRef,
|
|
@@ -5791,11 +6360,6 @@ function useDesignModeAutoScroll({
|
|
|
5791
6360
|
}) {
|
|
5792
6361
|
(0, import_react10.useEffect)(() => {
|
|
5793
6362
|
if (!active) return;
|
|
5794
|
-
const ZONE = 120;
|
|
5795
|
-
const MAX = 24;
|
|
5796
|
-
const RECALC_INTERVAL = 8;
|
|
5797
|
-
const SWITCH_FRAMES = 3;
|
|
5798
|
-
const SCROLLER_EDGE_HYSTERESIS = 18;
|
|
5799
6363
|
let scrollEl = findScrollableAtPoint(mouseRef.current.x, mouseRef.current.y);
|
|
5800
6364
|
let cachedRect = scrollEl.getBoundingClientRect();
|
|
5801
6365
|
let rectAge = 0;
|
|
@@ -5803,117 +6367,71 @@ function useDesignModeAutoScroll({
|
|
|
5803
6367
|
const tick = () => {
|
|
5804
6368
|
const { x, y } = mouseRef.current;
|
|
5805
6369
|
const safeZone = safeZoneRef.current;
|
|
5806
|
-
if (++rectAge >
|
|
6370
|
+
if (++rectAge > SCROLLER_RECT_RECALC_INTERVAL) {
|
|
5807
6371
|
const candidate = findScrollableAtPoint(x, y);
|
|
5808
6372
|
const candidateKey = getScrollerKey(candidate);
|
|
5809
6373
|
const currentKey = getScrollerKey(scrollEl);
|
|
5810
6374
|
const currentRect = scrollEl.getBoundingClientRect();
|
|
5811
|
-
if (candidateKey !== currentKey && !pointerInsideRect(x, y, currentRect,
|
|
6375
|
+
if (candidateKey !== currentKey && !pointerInsideRect(x, y, currentRect, SCROLLER_EDGE_HYSTERESIS_PX)) {
|
|
5812
6376
|
const pendingKey = autoScrollStateRef.current.pendingScrollerKey;
|
|
5813
6377
|
const pendingFrames = pendingKey === candidateKey ? (autoScrollStateRef.current.pendingFrames ?? 0) + 1 : 1;
|
|
5814
6378
|
autoScrollStateRef.current.pendingScrollerKey = candidateKey;
|
|
5815
6379
|
autoScrollStateRef.current.pendingFrames = pendingFrames;
|
|
5816
|
-
if (pendingFrames >=
|
|
6380
|
+
if (pendingFrames >= SCROLLER_SWITCH_FRAMES) {
|
|
5817
6381
|
scrollEl = candidate;
|
|
5818
6382
|
cachedRect = candidate.getBoundingClientRect();
|
|
5819
6383
|
autoScrollStateRef.current.pendingScrollerKey = null;
|
|
5820
6384
|
autoScrollStateRef.current.pendingFrames = 0;
|
|
5821
|
-
}
|
|
5822
|
-
} else {
|
|
5823
|
-
scrollEl = candidateKey === currentKey ? scrollEl : candidate;
|
|
5824
|
-
cachedRect = scrollEl.getBoundingClientRect();
|
|
5825
|
-
autoScrollStateRef.current.pendingScrollerKey = null;
|
|
5826
|
-
autoScrollStateRef.current.pendingFrames = 0;
|
|
5827
|
-
}
|
|
5828
|
-
rectAge = 0;
|
|
5829
|
-
}
|
|
5830
|
-
if (isPointerInPageEdgeZone(x, y) || isPointerOutsideSafeZone(x, y, safeZone)) {
|
|
5831
|
-
autoScrollStateRef.current = {
|
|
5832
|
-
...autoScrollStateRef.current,
|
|
5833
|
-
scrollerKey: null,
|
|
5834
|
-
vx: 0,
|
|
5835
|
-
vy: 0
|
|
5836
|
-
};
|
|
5837
|
-
raf = requestAnimationFrame(tick);
|
|
5838
|
-
return;
|
|
5839
|
-
}
|
|
5840
|
-
const dTop = y - cachedRect.top;
|
|
5841
|
-
const dBot = cachedRect.bottom - y;
|
|
5842
|
-
let dy = 0;
|
|
5843
|
-
if (dTop > 0 && dTop <
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
if (
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
}
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
var
|
|
5871
|
-
constructor(limit = DEFAULT_LIMIT) {
|
|
5872
|
-
this.limit = limit;
|
|
5873
|
-
__publicField(this, "undoStack", []);
|
|
5874
|
-
__publicField(this, "redoStack", []);
|
|
5875
|
-
}
|
|
5876
|
-
execute(command, apply) {
|
|
5877
|
-
const applied = apply(command, "redo");
|
|
5878
|
-
if (!applied) return false;
|
|
5879
|
-
this.undoStack.push(command);
|
|
5880
|
-
if (this.undoStack.length > this.limit) this.undoStack.shift();
|
|
5881
|
-
this.redoStack = [];
|
|
5882
|
-
return true;
|
|
5883
|
-
}
|
|
5884
|
-
undo(apply) {
|
|
5885
|
-
const command = this.undoStack.pop();
|
|
5886
|
-
if (!command) return false;
|
|
5887
|
-
const applied = apply(command, "undo");
|
|
5888
|
-
if (!applied) {
|
|
5889
|
-
this.undoStack.push(command);
|
|
5890
|
-
return false;
|
|
5891
|
-
}
|
|
5892
|
-
this.redoStack.push(command);
|
|
5893
|
-
return true;
|
|
5894
|
-
}
|
|
5895
|
-
redo(apply) {
|
|
5896
|
-
const command = this.redoStack.pop();
|
|
5897
|
-
if (!command) return false;
|
|
5898
|
-
const applied = apply(command, "redo");
|
|
5899
|
-
if (!applied) {
|
|
5900
|
-
this.redoStack.push(command);
|
|
5901
|
-
return false;
|
|
5902
|
-
}
|
|
5903
|
-
this.undoStack.push(command);
|
|
5904
|
-
return true;
|
|
5905
|
-
}
|
|
5906
|
-
clear() {
|
|
5907
|
-
this.undoStack = [];
|
|
5908
|
-
this.redoStack = [];
|
|
5909
|
-
}
|
|
5910
|
-
canUndo() {
|
|
5911
|
-
return this.undoStack.length > 0;
|
|
5912
|
-
}
|
|
5913
|
-
canRedo() {
|
|
5914
|
-
return this.redoStack.length > 0;
|
|
5915
|
-
}
|
|
5916
|
-
};
|
|
6385
|
+
}
|
|
6386
|
+
} else {
|
|
6387
|
+
scrollEl = candidateKey === currentKey ? scrollEl : candidate;
|
|
6388
|
+
cachedRect = scrollEl.getBoundingClientRect();
|
|
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");
|
|
5917
6435
|
|
|
5918
6436
|
// src/client/dnd/design-mode/sortable-preview-animator.ts
|
|
5919
6437
|
function isIdentityTransform(transform) {
|
|
@@ -6127,43 +6645,6 @@ function useHoverDetection({
|
|
|
6127
6645
|
// src/client/dnd/design-mode/useDragVisualLoop.ts
|
|
6128
6646
|
var import_react13 = require("react");
|
|
6129
6647
|
|
|
6130
|
-
// src/client/dnd/design-mode/drag-lock.ts
|
|
6131
|
-
var MIN_UNLOCK_MARGIN = 32;
|
|
6132
|
-
var MAX_UNLOCK_MARGIN = 72;
|
|
6133
|
-
var MIN_UNLOCK_DWELL_MS = 170;
|
|
6134
|
-
var MAX_UNLOCK_DWELL_MS = 300;
|
|
6135
|
-
function clamp2(value, min, max) {
|
|
6136
|
-
return Math.min(max, Math.max(min, value));
|
|
6137
|
-
}
|
|
6138
|
-
function resolveCrossUnlockParams(rect) {
|
|
6139
|
-
const width = Math.max(0, rect.right - rect.left);
|
|
6140
|
-
const height = Math.max(0, rect.bottom - rect.top);
|
|
6141
|
-
const shortest = Math.max(1, Math.min(width, height));
|
|
6142
|
-
const margin = Math.round(clamp2(shortest * 0.14, MIN_UNLOCK_MARGIN, MAX_UNLOCK_MARGIN));
|
|
6143
|
-
const dwellMs = Math.round(clamp2(shortest * 0.7, MIN_UNLOCK_DWELL_MS, MAX_UNLOCK_DWELL_MS));
|
|
6144
|
-
return { margin, dwellMs };
|
|
6145
|
-
}
|
|
6146
|
-
function checkCrossUnlock(lock, adjustedPx, adjustedPy, lockRect, now, margin, dwellMs, graceMs) {
|
|
6147
|
-
if (lock.isCrossUnlocked) {
|
|
6148
|
-
if (lock.unlockUntilTs !== null && now < lock.unlockUntilTs) return lock;
|
|
6149
|
-
return lock;
|
|
6150
|
-
}
|
|
6151
|
-
const outsideBand = adjustedPx < lockRect.left - margin || adjustedPx > lockRect.right + margin || adjustedPy < lockRect.top - margin || adjustedPy > lockRect.bottom + margin;
|
|
6152
|
-
if (!outsideBand) {
|
|
6153
|
-
return lock.exitSince !== null ? { ...lock, exitSince: null } : lock;
|
|
6154
|
-
}
|
|
6155
|
-
const exitSince = lock.exitSince ?? now;
|
|
6156
|
-
if (now - exitSince >= dwellMs) {
|
|
6157
|
-
return {
|
|
6158
|
-
containerId: lock.containerId,
|
|
6159
|
-
isCrossUnlocked: true,
|
|
6160
|
-
exitSince,
|
|
6161
|
-
unlockUntilTs: now + graceMs
|
|
6162
|
-
};
|
|
6163
|
-
}
|
|
6164
|
-
return lock.exitSince !== null ? lock : { ...lock, exitSince: now };
|
|
6165
|
-
}
|
|
6166
|
-
|
|
6167
6648
|
// src/client/dnd/design-mode/quadtree.ts
|
|
6168
6649
|
function overlaps(a, b) {
|
|
6169
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;
|
|
@@ -6173,6 +6654,7 @@ function fitsInside(outer, inner) {
|
|
|
6173
6654
|
}
|
|
6174
6655
|
var CAPACITY = 8;
|
|
6175
6656
|
var MAX_DEPTH2 = 8;
|
|
6657
|
+
var ROOT_BOUNDS_PAD = 100;
|
|
6176
6658
|
var QTNode = class _QTNode {
|
|
6177
6659
|
constructor(bounds, depth = 0) {
|
|
6178
6660
|
__publicField(this, "bounds");
|
|
@@ -6270,12 +6752,11 @@ var Quadtree = class _Quadtree {
|
|
|
6270
6752
|
if (r.right > maxX) maxX = r.right;
|
|
6271
6753
|
if (r.bottom > maxY) maxY = r.bottom;
|
|
6272
6754
|
}
|
|
6273
|
-
const PAD = 100;
|
|
6274
6755
|
const root = new QTNode({
|
|
6275
|
-
x: minX -
|
|
6276
|
-
y: minY -
|
|
6277
|
-
w: maxX - minX + 2 *
|
|
6278
|
-
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
|
|
6279
6760
|
});
|
|
6280
6761
|
for (const [id, r] of rects) {
|
|
6281
6762
|
if (r.width > 0 && r.height > 0) {
|
|
@@ -6377,9 +6858,9 @@ function getSlotQueryRadius() {
|
|
|
6377
6858
|
const vh = window.innerHeight;
|
|
6378
6859
|
return Math.min(500, Math.max(100, Math.max(vw, vh) * 0.2));
|
|
6379
6860
|
}
|
|
6380
|
-
var NEST_EDGE_FRACTION = 0.
|
|
6381
|
-
var ORIGIN_RETURN_BAND_PX =
|
|
6382
|
-
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;
|
|
6383
6864
|
var ROW_OVERLAP_TOLERANCE_PX = 1;
|
|
6384
6865
|
function normalizeContainerSet(containers) {
|
|
6385
6866
|
if (!containers) return null;
|
|
@@ -6457,8 +6938,6 @@ var DragIntentEngine = class {
|
|
|
6457
6938
|
// Pre-computed set of slot IDs that would produce no movement for the active item.
|
|
6458
6939
|
__publicField(this, "noOpSlotIds");
|
|
6459
6940
|
__publicField(this, "originContainerId");
|
|
6460
|
-
__publicField(this, "laneRootContainerId");
|
|
6461
|
-
__publicField(this, "laneParentId");
|
|
6462
6941
|
__publicField(this, "laneAllowedContainers");
|
|
6463
6942
|
__publicField(this, "blockedContainerIds");
|
|
6464
6943
|
__publicField(this, "targetPlane", "lane");
|
|
@@ -6470,8 +6949,6 @@ var DragIntentEngine = class {
|
|
|
6470
6949
|
this.queryRadius = getSlotQueryRadius();
|
|
6471
6950
|
this.slotsByContainer = buildSlotsByContainer(projection.slotIndex);
|
|
6472
6951
|
this.originContainerId = this.getNodeParentContainerId(activeId);
|
|
6473
|
-
this.laneRootContainerId = options?.laneRootContainerId ?? this.originContainerId;
|
|
6474
|
-
this.laneParentId = this.laneRootContainerId ? this.containerIndex.get(this.laneRootContainerId)?.parentId ?? null : null;
|
|
6475
6952
|
this.laneAllowedContainers = normalizeContainerSet(options?.laneAllowedContainers);
|
|
6476
6953
|
this.blockedContainerIds = normalizeContainerSet(options?.blockedContainerIds);
|
|
6477
6954
|
const noOpSlotIds = /* @__PURE__ */ new Set();
|
|
@@ -6503,10 +6980,6 @@ var DragIntentEngine = class {
|
|
|
6503
6980
|
setTargetPlane(plane) {
|
|
6504
6981
|
this.targetPlane = plane;
|
|
6505
6982
|
}
|
|
6506
|
-
setLaneAllowedContainers(containers) {
|
|
6507
|
-
this.laneAllowedContainers = normalizeContainerSet(containers);
|
|
6508
|
-
this.reset();
|
|
6509
|
-
}
|
|
6510
6983
|
getTargetPlane() {
|
|
6511
6984
|
return this.targetPlane;
|
|
6512
6985
|
}
|
|
@@ -6605,7 +7078,7 @@ var DragIntentEngine = class {
|
|
|
6605
7078
|
if (this.isInvalidDropContainer(pointerContainerId)) return null;
|
|
6606
7079
|
for (const childId of container.children) {
|
|
6607
7080
|
if (childId === this.activeId) continue;
|
|
6608
|
-
if (this.
|
|
7081
|
+
if (this.isInvalidDropContainer(childId)) continue;
|
|
6609
7082
|
const childNode = this.getNodeRect(childId);
|
|
6610
7083
|
if (!childNode) continue;
|
|
6611
7084
|
if (!pointInRect(px, py, childNode)) continue;
|
|
@@ -6630,9 +7103,16 @@ var DragIntentEngine = class {
|
|
|
6630
7103
|
if (laneLock && !this.isLaneContainer(id)) continue;
|
|
6631
7104
|
if (!pointInRect(px, py, node.rect)) continue;
|
|
6632
7105
|
if (this.hasUsableSlots(id) === false) continue;
|
|
6633
|
-
|
|
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 });
|
|
6634
7113
|
}
|
|
6635
7114
|
pointerContainers.sort((a, b) => {
|
|
7115
|
+
if (a.edgePenalty !== b.edgePenalty) return a.edgePenalty - b.edgePenalty;
|
|
6636
7116
|
if (b.depth !== a.depth) return b.depth - a.depth;
|
|
6637
7117
|
return a.area - b.area;
|
|
6638
7118
|
});
|
|
@@ -6645,7 +7125,9 @@ var DragIntentEngine = class {
|
|
|
6645
7125
|
}
|
|
6646
7126
|
if (this.originContainerId && this.originContainerId !== pointerContainerId && !this.isInvalidDropContainer(this.originContainerId) && !this.isBlockedContainer(this.originContainerId) && (!laneLock || this.isLaneContainer(this.originContainerId)) && this.hasUsableSlots(this.originContainerId)) {
|
|
6647
7127
|
const originNode = this.containerIndex.get(this.originContainerId);
|
|
6648
|
-
|
|
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)) {
|
|
6649
7131
|
pointerContainerId = this.originContainerId;
|
|
6650
7132
|
}
|
|
6651
7133
|
}
|
|
@@ -6712,8 +7194,13 @@ var DragIntentEngine = class {
|
|
|
6712
7194
|
}
|
|
6713
7195
|
return n;
|
|
6714
7196
|
}
|
|
7197
|
+
const SLOT_ZONE_PX = 30;
|
|
6715
7198
|
for (const child of childRects) {
|
|
6716
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;
|
|
6717
7204
|
if (py < midY) return child.index;
|
|
6718
7205
|
}
|
|
6719
7206
|
return n;
|
|
@@ -6782,15 +7269,14 @@ var DragIntentEngine = class {
|
|
|
6782
7269
|
hasUsableSlots(containerId) {
|
|
6783
7270
|
const filtered = this.getContainerSlots(containerId);
|
|
6784
7271
|
if (filtered.length > 0) return true;
|
|
6785
|
-
|
|
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;
|
|
6786
7276
|
}
|
|
6787
7277
|
isLaneContainer(containerId) {
|
|
6788
7278
|
if (this.laneAllowedContainers) return this.laneAllowedContainers.has(containerId);
|
|
6789
|
-
|
|
6790
|
-
if (containerId === this.laneRootContainerId) return true;
|
|
6791
|
-
const node = this.containerIndex.get(containerId);
|
|
6792
|
-
if (!node) return false;
|
|
6793
|
-
return node.parentId === this.laneParentId;
|
|
7279
|
+
return true;
|
|
6794
7280
|
}
|
|
6795
7281
|
isBlockedContainer(containerId) {
|
|
6796
7282
|
return this.blockedContainerIds?.has(containerId) ?? false;
|
|
@@ -6801,9 +7287,11 @@ function createDragIntentEngine(projection, activeId, options) {
|
|
|
6801
7287
|
}
|
|
6802
7288
|
|
|
6803
7289
|
// src/client/dnd/design-mode/drop-line.ts
|
|
7290
|
+
var DROP_LINE_THICKNESS_PX = 2;
|
|
7291
|
+
var DROP_LINE_MIN_LENGTH_PX = 40;
|
|
6804
7292
|
function slotDropLine(slot, container, projectionTree, sdx, sdy) {
|
|
6805
|
-
const T =
|
|
6806
|
-
const MIN =
|
|
7293
|
+
const T = DROP_LINE_THICKNESS_PX;
|
|
7294
|
+
const MIN = DROP_LINE_MIN_LENGTH_PX;
|
|
6807
7295
|
const bp = computeSlotBoundaryPoint(slot, container, projectionTree);
|
|
6808
7296
|
if (container.strategy === "horizontal") {
|
|
6809
7297
|
return {
|
|
@@ -6843,9 +7331,6 @@ function slotDropLine(slot, container, projectionTree, sdx, sdy) {
|
|
|
6843
7331
|
}
|
|
6844
7332
|
|
|
6845
7333
|
// src/client/dnd/design-mode/preview-layout.ts
|
|
6846
|
-
function clampIndex(index, min, max) {
|
|
6847
|
-
return Math.max(min, Math.min(index, max));
|
|
6848
|
-
}
|
|
6849
7334
|
function getContainerChildren(projection, containerId) {
|
|
6850
7335
|
return [...projection.containerIndex.get(containerId)?.children ?? []];
|
|
6851
7336
|
}
|
|
@@ -6965,7 +7450,7 @@ function buildPreviewLayout({
|
|
|
6965
7450
|
const originalItemIds = getContainerChildren(projection, containerId);
|
|
6966
7451
|
const activeIndex = originalItemIds.indexOf(anchorNodeId);
|
|
6967
7452
|
if (activeIndex < 0) return null;
|
|
6968
|
-
const overIndex =
|
|
7453
|
+
const overIndex = clamp(targetIndex, 0, Math.max(0, originalItemIds.length - 1));
|
|
6969
7454
|
const previewItemIds = arrayMove(originalItemIds, activeIndex, overIndex);
|
|
6970
7455
|
const strategy = getContainerStrategy(projection, containerId);
|
|
6971
7456
|
containers.set(containerId, {
|
|
@@ -7005,7 +7490,7 @@ function buildPreviewLayout({
|
|
|
7005
7490
|
activePreviewContainers.add(sourceContainerId);
|
|
7006
7491
|
const targetOriginalItemIds = targetChildren.filter((id) => id !== anchorNodeId);
|
|
7007
7492
|
const targetPreviewItemIds = [...targetOriginalItemIds];
|
|
7008
|
-
const targetOverIndex =
|
|
7493
|
+
const targetOverIndex = clamp(targetIndex, 0, targetOriginalItemIds.length);
|
|
7009
7494
|
targetPreviewItemIds.splice(targetOverIndex, 0, anchorNodeId);
|
|
7010
7495
|
const targetStrategy = getContainerStrategy(projection, targetContainerId);
|
|
7011
7496
|
const targetStrategyItemIds = [...targetOriginalItemIds, anchorNodeId];
|
|
@@ -7037,9 +7522,8 @@ function buildPreviewLayout({
|
|
|
7037
7522
|
}
|
|
7038
7523
|
|
|
7039
7524
|
// src/client/dnd/design-mode/useDragVisualLoop.ts
|
|
7040
|
-
var CONTAINER_SWITCH_HYSTERESIS =
|
|
7041
|
-
var
|
|
7042
|
-
var SMALL_NODE_NEST_DWELL_MS = 180;
|
|
7525
|
+
var CONTAINER_SWITCH_HYSTERESIS = 12;
|
|
7526
|
+
var SMALL_NODE_NEST_DWELL_MS = 100;
|
|
7043
7527
|
var LARGE_NODE_NEST_DWELL_MS = 320;
|
|
7044
7528
|
function useDragVisualLoop({
|
|
7045
7529
|
activeDrag,
|
|
@@ -7088,33 +7572,12 @@ function useDragVisualLoop({
|
|
|
7088
7572
|
const scrollDy = window.scrollY - snapshot.scroll.y;
|
|
7089
7573
|
const adjustedPx = px + scrollDx;
|
|
7090
7574
|
const adjustedPy = py + scrollDy;
|
|
7091
|
-
const lockContainer = refs.lockRef.current.containerId ? refs.projectionRef.current.containerIndex.get(refs.lockRef.current.containerId) ?? null : null;
|
|
7092
|
-
if (!refs.lockRef.current.isCrossUnlocked && lockContainer) {
|
|
7093
|
-
const { margin, dwellMs } = resolveCrossUnlockParams(lockContainer.rect);
|
|
7094
|
-
const nextLock = checkCrossUnlock(
|
|
7095
|
-
refs.lockRef.current,
|
|
7096
|
-
adjustedPx,
|
|
7097
|
-
adjustedPy,
|
|
7098
|
-
lockContainer.rect,
|
|
7099
|
-
performance.now(),
|
|
7100
|
-
margin,
|
|
7101
|
-
dwellMs,
|
|
7102
|
-
CROSS_UNLOCK_GRACE_MS
|
|
7103
|
-
);
|
|
7104
|
-
if (nextLock !== refs.lockRef.current) {
|
|
7105
|
-
refs.lockRef.current = nextLock;
|
|
7106
|
-
if (nextLock.isCrossUnlocked) engine.setLaneAllowedContainers(null);
|
|
7107
|
-
}
|
|
7108
|
-
}
|
|
7109
7575
|
const nestPreview = engine.peekNestIntent(px, py, window.scrollX, window.scrollY, snapshot.scroll.x, snapshot.scroll.y);
|
|
7110
7576
|
const isLargeDraggedNode = shouldBlockNestForLargeNode(activeDrag.w, activeDrag.h);
|
|
7111
7577
|
let allowNest = false;
|
|
7112
7578
|
if (nestPreview) {
|
|
7113
7579
|
const childId = nestPreview.slotId.split("::nest::")[1] ?? "";
|
|
7114
|
-
|
|
7115
|
-
const isSiblingList = siblings.length >= 2;
|
|
7116
|
-
const isSourceContainerNest = nestPreview.containerId === refs.sourceContainerIdRef.current;
|
|
7117
|
-
allowNest = !!childId && !isSiblingList && !isLargeDraggedNode && !isSourceContainerNest;
|
|
7580
|
+
allowNest = !!childId && !isLargeDraggedNode;
|
|
7118
7581
|
}
|
|
7119
7582
|
if (!allowNest) {
|
|
7120
7583
|
refs.nestCandidateRef.current = null;
|
|
@@ -7124,7 +7587,12 @@ function useDragVisualLoop({
|
|
|
7124
7587
|
const now = performance.now();
|
|
7125
7588
|
if (!refs.nestCandidateRef.current || refs.nestCandidateRef.current.id !== nestPreview.slotId) {
|
|
7126
7589
|
refs.nestCandidateRef.current = { id: nestPreview.slotId, since: now };
|
|
7127
|
-
|
|
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
|
+
}
|
|
7128
7596
|
setTargetPlane("lane");
|
|
7129
7597
|
} else if (now - refs.nestCandidateRef.current.since >= (isLargeDraggedNode ? LARGE_NODE_NEST_DWELL_MS : SMALL_NODE_NEST_DWELL_MS)) {
|
|
7130
7598
|
setTargetPlane("nest");
|
|
@@ -7183,18 +7651,6 @@ function useDragVisualLoop({
|
|
|
7183
7651
|
setTargetPlane("lane");
|
|
7184
7652
|
refs.nestCandidateRef.current = null;
|
|
7185
7653
|
refs.nestTargetRef.current = null;
|
|
7186
|
-
const lockedParentId = refs.lockRef.current.containerId;
|
|
7187
|
-
if (!refs.lockRef.current.isCrossUnlocked && (!lockedParentId || intent.containerId !== lockedParentId)) {
|
|
7188
|
-
refs.lastIntentRef.current = null;
|
|
7189
|
-
refs.visualIntentRef.current = null;
|
|
7190
|
-
refs.resolvedReorderRef.current = null;
|
|
7191
|
-
refs.finalVisualKeyRef.current = null;
|
|
7192
|
-
setInsideRect(null);
|
|
7193
|
-
setDropLine(null);
|
|
7194
|
-
animator.clear();
|
|
7195
|
-
rafId = requestAnimationFrame(tick);
|
|
7196
|
-
return;
|
|
7197
|
-
}
|
|
7198
7654
|
refs.lastIntentRef.current = intent;
|
|
7199
7655
|
refs.visualIntentRef.current = intent;
|
|
7200
7656
|
setInsideRect(null);
|
|
@@ -7226,19 +7682,43 @@ function useDragVisualLoop({
|
|
|
7226
7682
|
}
|
|
7227
7683
|
const sourceCommitLane = refs.sourceCommitLaneRef.current ?? getCommitLaneSnapshot(sourceContainerId);
|
|
7228
7684
|
const targetCommitLane = getCommitLaneSnapshot(intent.containerId);
|
|
7229
|
-
|
|
7685
|
+
let commitPlacement = resolveCommitPlacementFromVisualTarget(
|
|
7230
7686
|
targetCommitLane,
|
|
7231
7687
|
sourceCommitLane,
|
|
7232
7688
|
activeDrag.anchorNodeId,
|
|
7233
7689
|
targetInsertIndex
|
|
7234
7690
|
);
|
|
7235
7691
|
if (!commitPlacement) {
|
|
7236
|
-
refs.
|
|
7237
|
-
refs.
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
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
|
+
};
|
|
7242
7722
|
}
|
|
7243
7723
|
setDropLine(slotDropLine(slot, container, proj.projectionTree, scrollDx, scrollDy));
|
|
7244
7724
|
refs.resolvedReorderRef.current = {
|
|
@@ -7283,56 +7763,175 @@ function useDragVisualLoop({
|
|
|
7283
7763
|
|
|
7284
7764
|
// src/client/dnd/design-mode/useDragLifecycle.ts
|
|
7285
7765
|
var import_react14 = require("react");
|
|
7286
|
-
|
|
7287
|
-
// src/client/dnd/design-mode/node-key.ts
|
|
7288
|
-
var _runtimeKeyMap = /* @__PURE__ */ new WeakMap();
|
|
7289
|
-
var _runtimeKeyCounter = 0;
|
|
7290
|
-
function getRuntimeKey(el) {
|
|
7291
|
-
const existing = _runtimeKeyMap.get(el);
|
|
7292
|
-
if (existing) return existing;
|
|
7293
|
-
const key2 = `runtime:${++_runtimeKeyCounter}`;
|
|
7294
|
-
_runtimeKeyMap.set(el, key2);
|
|
7295
|
-
return key2;
|
|
7296
|
-
}
|
|
7297
|
-
function getNodeKeyFromElement(el) {
|
|
7298
|
-
const resolved = resolveDragSurface(el);
|
|
7299
|
-
const host = resolved.host ?? el;
|
|
7300
|
-
const meta = getEditorMeta(host);
|
|
7301
|
-
if (meta) return meta.nodeId;
|
|
7302
|
-
const persisted = host.getAttribute("data-dnd-node-id");
|
|
7303
|
-
if (persisted) return persisted;
|
|
7304
|
-
return getRuntimeKey(host);
|
|
7305
|
-
}
|
|
7306
|
-
function getInspectorRefFromElement(el) {
|
|
7307
|
-
const resolved = resolveDragSurface(el);
|
|
7308
|
-
const host = resolved.host ?? el;
|
|
7309
|
-
const meta = getEditorMeta(host);
|
|
7310
|
-
if (!meta) return null;
|
|
7311
|
-
return { relativePath: meta.file, line: meta.line, column: meta.col };
|
|
7312
|
-
}
|
|
7313
|
-
|
|
7314
|
-
// src/client/dnd/design-mode/useDragLifecycle.ts
|
|
7315
|
-
var SOFT_COMMIT_DISTANCE_PX = 14;
|
|
7316
|
-
function isLaneCommitValid(intent, resolvedReorder, lockedParentId) {
|
|
7317
|
-
if (!intent || intent.mode !== "reorder") return false;
|
|
7318
|
-
if (!resolvedReorder) return false;
|
|
7319
|
-
if (!lockedParentId) return false;
|
|
7320
|
-
if (intent.containerId !== lockedParentId) return false;
|
|
7321
|
-
if (resolvedReorder.visual.slotId !== intent.slotId) return false;
|
|
7322
|
-
if (resolvedReorder.visual.parentNodeId !== intent.containerId) return false;
|
|
7323
|
-
return true;
|
|
7324
|
-
}
|
|
7325
|
-
function buildRuntimeIdentityLocal(nodeId, resolveNodeElement) {
|
|
7766
|
+
function buildRuntimeIdentityLocal(nodeId, resolveNodeElement, effectiveLaneSnapshot) {
|
|
7326
7767
|
if (!nodeId) return null;
|
|
7327
7768
|
const element = resolveNodeElement(nodeId);
|
|
7328
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;
|
|
7329
7775
|
return {
|
|
7330
7776
|
nodeId,
|
|
7331
|
-
nodeKey
|
|
7332
|
-
selector: element.getAttribute(
|
|
7333
|
-
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
|
|
7334
7809
|
};
|
|
7335
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
|
+
}
|
|
7336
7935
|
function useDragLifecycle({
|
|
7337
7936
|
refs,
|
|
7338
7937
|
pause,
|
|
@@ -7414,12 +8013,10 @@ function useDragLifecycle({
|
|
|
7414
8013
|
const srcContainerId = anchor.sourceContainerId;
|
|
7415
8014
|
const sourceCommitLane = getCommitLaneSnapshot(srcContainerId);
|
|
7416
8015
|
const startPosition = getCurrentCommitPlacement(anchorNodeId, srcContainerId);
|
|
7417
|
-
const laneAllowed = srcContainerId ? /* @__PURE__ */ new Set([srcContainerId]) : null;
|
|
7418
8016
|
const blockedContainerIds = buildBlockedStructuralContainerIds(proj, refs.nodeMapRef.current, srcContainerId);
|
|
7419
8017
|
refs.blockedContainerIdsRef.current = blockedContainerIds;
|
|
7420
8018
|
refs.engineRef.current = createDragIntentEngine(proj, anchorNodeId, {
|
|
7421
8019
|
laneRootContainerId: srcContainerId,
|
|
7422
|
-
laneAllowedContainers: laneAllowed,
|
|
7423
8020
|
blockedContainerIds
|
|
7424
8021
|
});
|
|
7425
8022
|
refs.engineRef.current.setTargetPlane("lane");
|
|
@@ -7427,7 +8024,7 @@ function useDragLifecycle({
|
|
|
7427
8024
|
refs.sourceContainerIdRef.current = srcContainerId;
|
|
7428
8025
|
refs.sourceCommitLaneRef.current = sourceCommitLane;
|
|
7429
8026
|
refs.dragSessionAnchorRef.current = anchor;
|
|
7430
|
-
refs.lockRef.current = { containerId: srcContainerId, isCrossUnlocked:
|
|
8027
|
+
refs.lockRef.current = { containerId: srcContainerId, isCrossUnlocked: true, exitSince: null, unlockUntilTs: null };
|
|
7431
8028
|
refs.dragStartPositionRef.current = startPosition;
|
|
7432
8029
|
refs.safeZoneRef.current = resolveSafeZoneRect();
|
|
7433
8030
|
pause();
|
|
@@ -7453,22 +8050,34 @@ function useDragLifecycle({
|
|
|
7453
8050
|
const pointer = refs.mouseRef.current;
|
|
7454
8051
|
const safeZone = refs.safeZoneRef.current;
|
|
7455
8052
|
const blockedByGuard = isPointerOutsideSafeZone(pointer.x, pointer.y, safeZone) || isPointerInHardPageEdgeZone(pointer.x, pointer.y);
|
|
7456
|
-
|
|
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
|
+
}
|
|
7457
8070
|
const intent = refs.visualIntentRef.current;
|
|
7458
|
-
const finalVisual = refs.finalVisualKeyRef.current;
|
|
7459
8071
|
const nestTarget = refs.nestTargetRef.current;
|
|
7460
8072
|
const intentHasContainer = intent ? refs.projectionRef.current.containerIndex.has(intent.containerId) : false;
|
|
7461
8073
|
const intentHasSlot = intent ? intent.mode === "nest" || refs.projectionRef.current.slotIndex.has(intent.slotId) : false;
|
|
7462
8074
|
const intentValid = !!intent && intentHasContainer && intentHasSlot;
|
|
7463
8075
|
if (!blockedByGuard && activeEl && sourcePos && (nestTarget || intentValid)) {
|
|
7464
8076
|
const dropTargetId = nestTarget?.nodeId ?? intent?.containerId;
|
|
7465
|
-
if (dropTargetId) {
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
syncHistoryAvailability();
|
|
7470
|
-
return;
|
|
7471
|
-
}
|
|
8077
|
+
if (dropTargetId && !refs.nodeMapRef.current.has(dropTargetId)) {
|
|
8078
|
+
clearDragState();
|
|
8079
|
+
syncHistoryAvailability();
|
|
8080
|
+
return;
|
|
7472
8081
|
}
|
|
7473
8082
|
let command = null;
|
|
7474
8083
|
if (nestTarget) {
|
|
@@ -7488,46 +8097,8 @@ function useDragLifecycle({
|
|
|
7488
8097
|
};
|
|
7489
8098
|
}
|
|
7490
8099
|
} else if (intentValid && intent.mode === "reorder") {
|
|
7491
|
-
const lockedParentId = refs.lockRef.current.containerId;
|
|
7492
|
-
if (!refs.lockRef.current.isCrossUnlocked && (!lockedParentId || intent.containerId !== lockedParentId)) {
|
|
7493
|
-
clearDragState();
|
|
7494
|
-
syncHistoryAvailability();
|
|
7495
|
-
return;
|
|
7496
|
-
}
|
|
7497
|
-
const snapshot = refs.snapshotRef.current;
|
|
7498
|
-
const targetContainer = refs.projectionRef.current.containerIndex.get(intent.containerId);
|
|
7499
|
-
if (targetContainer) {
|
|
7500
|
-
const scrollDx = window.scrollX - (snapshot?.scroll.x ?? 0);
|
|
7501
|
-
const scrollDy = window.scrollY - (snapshot?.scroll.y ?? 0);
|
|
7502
|
-
const adjPx = pointer.x + scrollDx;
|
|
7503
|
-
const adjPy = pointer.y + scrollDy;
|
|
7504
|
-
const r = targetContainer.rect;
|
|
7505
|
-
const inContainer = adjPx >= r.left - 40 && adjPx <= r.right + 40 && adjPy >= r.top - 40 && adjPy <= r.bottom + 40;
|
|
7506
|
-
if (!inContainer) {
|
|
7507
|
-
const softFallbackAllowed = finalVisual?.mode === "reorder" && finalVisual.containerId === intent.containerId && (() => {
|
|
7508
|
-
const slot = refs.projectionRef.current.slotIndex.get(finalVisual.slotId);
|
|
7509
|
-
const container = refs.projectionRef.current.containerIndex.get(finalVisual.containerId);
|
|
7510
|
-
if (!slot || !container) return false;
|
|
7511
|
-
const bp = computeSlotBoundaryPoint(slot, container, refs.projectionRef.current.projectionTree);
|
|
7512
|
-
const dist = Math.hypot(adjPx - bp.x, adjPy - bp.y);
|
|
7513
|
-
return dist <= SOFT_COMMIT_DISTANCE_PX;
|
|
7514
|
-
})();
|
|
7515
|
-
if (!softFallbackAllowed) {
|
|
7516
|
-
clearDragState();
|
|
7517
|
-
syncHistoryAvailability();
|
|
7518
|
-
return;
|
|
7519
|
-
}
|
|
7520
|
-
}
|
|
7521
|
-
}
|
|
7522
8100
|
const resolvedReorder = refs.resolvedReorderRef.current;
|
|
7523
|
-
|
|
7524
|
-
if (!laneValid) {
|
|
7525
|
-
clearDragState();
|
|
7526
|
-
syncHistoryAvailability();
|
|
7527
|
-
return;
|
|
7528
|
-
}
|
|
7529
|
-
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;
|
|
7530
|
-
if (!visualParity) {
|
|
8101
|
+
if (!resolvedReorder || resolvedReorder.visual.containerId !== intent.containerId) {
|
|
7531
8102
|
clearDragState();
|
|
7532
8103
|
syncHistoryAvailability();
|
|
7533
8104
|
return;
|
|
@@ -7543,56 +8114,32 @@ function useDragLifecycle({
|
|
|
7543
8114
|
};
|
|
7544
8115
|
}
|
|
7545
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);
|
|
7546
8125
|
const committed = refs.historyRef.current.execute(command, applyCommand);
|
|
7547
8126
|
if (committed) {
|
|
7548
8127
|
activeEl.setAttribute("data-dnd-moved", "");
|
|
7549
8128
|
selectElement(null);
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
recordMoveChange({
|
|
8129
|
+
recordCommittedMove({
|
|
8130
|
+
command,
|
|
8131
|
+
anchorNodeId,
|
|
8132
|
+
selectedNodeId,
|
|
8133
|
+
anchorEl,
|
|
8134
|
+
selectedEl,
|
|
7557
8135
|
nodeKey,
|
|
7558
|
-
|
|
7559
|
-
inspectorRef: inspRef,
|
|
8136
|
+
inspRef,
|
|
7560
8137
|
selectedNodeKey,
|
|
7561
|
-
selectedNodeId,
|
|
7562
8138
|
selectedInspectorRef,
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
after: command.to
|
|
7568
|
-
});
|
|
7569
|
-
const containerIdentity = buildRuntimeIdentityLocal(
|
|
7570
|
-
command.to.laneContainerId ?? command.to.parentNodeId,
|
|
7571
|
-
resolveNodeElement
|
|
7572
|
-
);
|
|
7573
|
-
const beforeSiblingIdentity = buildRuntimeIdentityLocal(command.to.beforeNodeId, resolveNodeElement);
|
|
7574
|
-
const afterSiblingIdentity = buildRuntimeIdentityLocal(command.to.afterNodeId, resolveNodeElement);
|
|
7575
|
-
dispatchRuntimeEvent({
|
|
7576
|
-
type: "element-moved",
|
|
7577
|
-
operationId: `${command.at}:${anchorNodeId}`,
|
|
7578
|
-
commandType: command.type,
|
|
7579
|
-
selected: {
|
|
7580
|
-
nodeId: selectedNodeId,
|
|
7581
|
-
nodeKey: selectedNodeKey,
|
|
7582
|
-
selector: selectedEl.getAttribute(DND_NODE_ID_ATTR2) ? `[${DND_NODE_ID_ATTR2}="${escapeCssAttrValue(selectedNodeId)}"]` : null,
|
|
7583
|
-
inspectorRef: selectedInspectorRef
|
|
7584
|
-
},
|
|
7585
|
-
anchor: {
|
|
7586
|
-
nodeId: anchorNodeId,
|
|
7587
|
-
nodeKey,
|
|
7588
|
-
selector: anchorEl.getAttribute(DND_NODE_ID_ATTR2) ? `[${DND_NODE_ID_ATTR2}="${escapeCssAttrValue(anchorNodeId)}"]` : null,
|
|
7589
|
-
inspectorRef: inspRef
|
|
7590
|
-
},
|
|
7591
|
-
container: containerIdentity,
|
|
7592
|
-
beforeSibling: beforeSiblingIdentity,
|
|
7593
|
-
afterSibling: afterSiblingIdentity,
|
|
7594
|
-
before: command.from,
|
|
7595
|
-
after: command.to
|
|
8139
|
+
sourceLaneSnapshot,
|
|
8140
|
+
targetLaneSnapshot,
|
|
8141
|
+
resolveNodeElement,
|
|
8142
|
+
recordMoveChange
|
|
7596
8143
|
});
|
|
7597
8144
|
}
|
|
7598
8145
|
}
|
|
@@ -7631,7 +8178,7 @@ function useResizeSession({
|
|
|
7631
8178
|
const rect = resizeTargetEl.getBoundingClientRect();
|
|
7632
8179
|
const selectedNodeKey = getNodeKeyFromElement(selectedEl);
|
|
7633
8180
|
const targetNodeKey = getNodeKeyFromElement(resizeTargetEl);
|
|
7634
|
-
const targetNodeId =
|
|
8181
|
+
const targetNodeId = ensureParentNodeId(resizeTargetEl);
|
|
7635
8182
|
const startColSpan = parseSpanValue(getComputedStyle(resizeTargetEl).gridColumnEnd || resizeTargetEl.style.gridColumnEnd);
|
|
7636
8183
|
const startRowSpan = parseSpanValue(getComputedStyle(resizeTargetEl).gridRowEnd || resizeTargetEl.style.gridRowEnd);
|
|
7637
8184
|
const columnTrackCount = getGridTrackCount(resizeTargetParent ? getComputedStyle(resizeTargetParent).gridTemplateColumns : null);
|
|
@@ -7739,8 +8286,10 @@ function useResizeSession({
|
|
|
7739
8286
|
after: { width: afterW, height: afterH, colSpan: afterColSpan, rowSpan: afterRowSpan, styles: afterStyles },
|
|
7740
8287
|
at: Date.now()
|
|
7741
8288
|
};
|
|
8289
|
+
const operationId = `${resizeCmd.at}:${selectedNodeId}`;
|
|
7742
8290
|
refs.historyRef.current.execute(resizeCmd, applyCommand);
|
|
7743
8291
|
recordResizeChange({
|
|
8292
|
+
operationId,
|
|
7744
8293
|
nodeKey: selectedNodeKey,
|
|
7745
8294
|
nodeId: selectedNodeId,
|
|
7746
8295
|
inspectorRef,
|
|
@@ -7750,17 +8299,17 @@ function useResizeSession({
|
|
|
7750
8299
|
});
|
|
7751
8300
|
dispatchRuntimeEvent({
|
|
7752
8301
|
type: "element-resized",
|
|
7753
|
-
operationId
|
|
8302
|
+
operationId,
|
|
7754
8303
|
selected: {
|
|
7755
8304
|
nodeId: selectedNodeId,
|
|
7756
8305
|
nodeKey: selectedNodeKey,
|
|
7757
|
-
selector:
|
|
8306
|
+
selector: buildNodeSelector(selectedNodeId),
|
|
7758
8307
|
inspectorRef
|
|
7759
8308
|
},
|
|
7760
8309
|
anchor: {
|
|
7761
8310
|
nodeId: targetNodeId,
|
|
7762
8311
|
nodeKey: targetNodeKey,
|
|
7763
|
-
selector:
|
|
8312
|
+
selector: buildNodeSelector(targetNodeId),
|
|
7764
8313
|
inspectorRef: getInspectorRefFromElement(element)
|
|
7765
8314
|
},
|
|
7766
8315
|
resize: {
|
|
@@ -7801,6 +8350,169 @@ function useResizeSession({
|
|
|
7801
8350
|
return { handleResizeHandlePointerDown };
|
|
7802
8351
|
}
|
|
7803
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
|
+
|
|
7804
8516
|
// src/client/dnd/design-mode/DesignModeOverlay.tsx
|
|
7805
8517
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
7806
8518
|
var DROP_ANIMATION = { duration: DURATION_MS, easing: EASING };
|
|
@@ -7846,11 +8558,11 @@ function HitArea({
|
|
|
7846
8558
|
onResizeHandlePointerDown
|
|
7847
8559
|
}) {
|
|
7848
8560
|
const { setNodeRef, listeners, attributes, isDragging } = useDraggable({ id: scanned.nodeId });
|
|
7849
|
-
(0,
|
|
8561
|
+
(0, import_react17.useEffect)(() => {
|
|
7850
8562
|
setNodeRef(scanned.element);
|
|
7851
8563
|
return () => setNodeRef(null);
|
|
7852
8564
|
}, [setNodeRef, scanned.element]);
|
|
7853
|
-
(0,
|
|
8565
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
7854
8566
|
const el = scanned.element;
|
|
7855
8567
|
if (isDragging) {
|
|
7856
8568
|
el.style.opacity = "0";
|
|
@@ -7858,16 +8570,16 @@ function HitArea({
|
|
|
7858
8570
|
el.style.removeProperty("opacity");
|
|
7859
8571
|
}
|
|
7860
8572
|
}, [isDragging, scanned.element]);
|
|
7861
|
-
(0,
|
|
8573
|
+
(0, import_react17.useEffect)(() => () => {
|
|
7862
8574
|
scanned.element.style.removeProperty("opacity");
|
|
7863
8575
|
scanned.element.style.removeProperty("transform");
|
|
7864
8576
|
scanned.element.style.removeProperty("transition");
|
|
7865
8577
|
scanned.element.style.removeProperty("will-change");
|
|
7866
8578
|
}, [scanned.element]);
|
|
7867
|
-
const divRef = (0,
|
|
7868
|
-
const [hoverResizeHandle, setHoverResizeHandle] = (0,
|
|
8579
|
+
const divRef = (0, import_react17.useRef)(null);
|
|
8580
|
+
const [hoverResizeHandle, setHoverResizeHandle] = (0, import_react17.useState)(null);
|
|
7869
8581
|
const isSelected = scanned.nodeId === selectedNodeId;
|
|
7870
|
-
(0,
|
|
8582
|
+
(0, import_react17.useEffect)(() => {
|
|
7871
8583
|
const div = divRef.current;
|
|
7872
8584
|
if (!div) return;
|
|
7873
8585
|
const onWheel = (e) => {
|
|
@@ -7938,13 +8650,14 @@ function DesignModeOverlay() {
|
|
|
7938
8650
|
const redoLastChange = useDesignModeStore((s) => s.redoLastChange);
|
|
7939
8651
|
const orderedChanges = useDesignModeStore((s) => s.orderedChanges);
|
|
7940
8652
|
const exportChangesForAI = useDesignModeStore((s) => s.exportChangesForAI);
|
|
8653
|
+
const externalDrag = useDesignModeStore((s) => s.externalDrag);
|
|
7941
8654
|
const { elements, pause, resume } = useElementScanner(enabled);
|
|
7942
|
-
const nodeMap = (0,
|
|
8655
|
+
const nodeMap = (0, import_react17.useMemo)(() => {
|
|
7943
8656
|
const m = /* @__PURE__ */ new Map();
|
|
7944
8657
|
for (const el of elements) m.set(el.nodeId, el);
|
|
7945
8658
|
return m;
|
|
7946
8659
|
}, [elements]);
|
|
7947
|
-
const draggableElements = (0,
|
|
8660
|
+
const draggableElements = (0, import_react17.useMemo)(() => {
|
|
7948
8661
|
if (elements.length === 0) return [];
|
|
7949
8662
|
const projection = buildProjection(elements);
|
|
7950
8663
|
return collectDraggableAnchors(elements, projection, nodeMap);
|
|
@@ -7952,21 +8665,21 @@ function DesignModeOverlay() {
|
|
|
7952
8665
|
const refs = useOverlayRefs(undoRequestId, redoRequestId);
|
|
7953
8666
|
refs.elementsRef.current = elements;
|
|
7954
8667
|
refs.nodeMapRef.current = nodeMap;
|
|
7955
|
-
(0,
|
|
8668
|
+
(0, import_react17.useEffect)(() => {
|
|
7956
8669
|
const m = /* @__PURE__ */ new Map();
|
|
7957
8670
|
for (const el of draggableElements) m.set(el.nodeId, el);
|
|
7958
8671
|
refs.draggableNodeMapRef.current = m;
|
|
7959
8672
|
}, [draggableElements]);
|
|
7960
|
-
const resolveNodeElement = (0,
|
|
8673
|
+
const resolveNodeElement = (0, import_react17.useCallback)((nodeId) => {
|
|
7961
8674
|
const known = refs.nodeMapRef.current.get(nodeId)?.element;
|
|
7962
8675
|
if (known) return known;
|
|
7963
|
-
return document.querySelector(
|
|
8676
|
+
return document.querySelector(buildNodeSelector(nodeId));
|
|
7964
8677
|
}, []);
|
|
7965
|
-
const clearCommitLaneCache = (0,
|
|
8678
|
+
const clearCommitLaneCache = (0, import_react17.useCallback)(() => {
|
|
7966
8679
|
refs.commitLaneCacheRef.current.clear();
|
|
7967
8680
|
refs.sourceCommitLaneRef.current = null;
|
|
7968
8681
|
}, []);
|
|
7969
|
-
const getCommitLaneSnapshot = (0,
|
|
8682
|
+
const getCommitLaneSnapshot = (0, import_react17.useCallback)((laneContainerId) => {
|
|
7970
8683
|
if (!laneContainerId) return null;
|
|
7971
8684
|
if (refs.commitLaneCacheRef.current.has(laneContainerId)) {
|
|
7972
8685
|
return refs.commitLaneCacheRef.current.get(laneContainerId) ?? null;
|
|
@@ -7975,15 +8688,15 @@ function DesignModeOverlay() {
|
|
|
7975
8688
|
refs.commitLaneCacheRef.current.set(laneContainerId, snapshot);
|
|
7976
8689
|
return snapshot;
|
|
7977
8690
|
}, []);
|
|
7978
|
-
const getCurrentCommitPlacement = (0,
|
|
8691
|
+
const getCurrentCommitPlacement = (0, import_react17.useCallback)((anchorNodeId, laneContainerId) => {
|
|
7979
8692
|
const lane = getCommitLaneSnapshot(laneContainerId);
|
|
7980
8693
|
return resolveCurrentCommitPlacement(lane, anchorNodeId);
|
|
7981
8694
|
}, [getCommitLaneSnapshot]);
|
|
7982
|
-
const applyCommand = (0,
|
|
8695
|
+
const applyCommand = (0, import_react17.useCallback)((command, direction) => {
|
|
7983
8696
|
if (command.type === "resize") {
|
|
7984
8697
|
const resCmd = command;
|
|
7985
8698
|
const targetId = resCmd.targetNodeId ?? resCmd.nodeId;
|
|
7986
|
-
const targetEl = document.querySelector(
|
|
8699
|
+
const targetEl = document.querySelector(buildNodeSelector(targetId));
|
|
7987
8700
|
if (!targetEl) return false;
|
|
7988
8701
|
const snapshot = direction === "redo" ? resCmd.after : resCmd.before;
|
|
7989
8702
|
if (snapshot.styles) {
|
|
@@ -7994,29 +8707,36 @@ function DesignModeOverlay() {
|
|
|
7994
8707
|
}
|
|
7995
8708
|
return true;
|
|
7996
8709
|
}
|
|
8710
|
+
if (command.type === "insert") {
|
|
8711
|
+
return applyInsertCommand(command, direction, resolveNodeElement);
|
|
8712
|
+
}
|
|
7997
8713
|
const applied = applyDndCommandPlacement(command, direction, resolveNodeElement);
|
|
7998
8714
|
if (!applied) return false;
|
|
7999
8715
|
clearCommitLaneCache();
|
|
8000
8716
|
return true;
|
|
8001
8717
|
}, [clearCommitLaneCache, resolveNodeElement]);
|
|
8002
|
-
const syncHistoryAvailability = (0,
|
|
8718
|
+
const syncHistoryAvailability = (0, import_react17.useCallback)(() => {
|
|
8003
8719
|
if (historyMode === "host") {
|
|
8004
8720
|
setHistoryAvailability(false, false);
|
|
8005
8721
|
return;
|
|
8006
8722
|
}
|
|
8007
8723
|
setHistoryAvailability(refs.historyRef.current.canUndo(), refs.historyRef.current.canRedo());
|
|
8008
8724
|
}, [historyMode, setHistoryAvailability]);
|
|
8725
|
+
(0, import_react17.useEffect)(() => {
|
|
8726
|
+
refs.historyRef.current.clear();
|
|
8727
|
+
syncHistoryAvailability();
|
|
8728
|
+
}, [enabled, syncHistoryAvailability]);
|
|
8009
8729
|
const sensors = useSensors(
|
|
8010
8730
|
useSensor(PointerSensor, { activationConstraint: { distance: 8 } })
|
|
8011
8731
|
);
|
|
8012
|
-
const collisionDetection = (0,
|
|
8732
|
+
const collisionDetection = (0, import_react17.useCallback)(
|
|
8013
8733
|
(args) => createDesignModeCollisionDetection(refs.blockedContainerIdsRef.current)(args),
|
|
8014
8734
|
[]
|
|
8015
8735
|
// eslint-disable-line react-hooks/exhaustive-deps -- refs are stable
|
|
8016
8736
|
);
|
|
8017
|
-
const [insideRect, setInsideRect] = (0,
|
|
8018
|
-
const [dropLine, setDropLine] = (0,
|
|
8019
|
-
(0,
|
|
8737
|
+
const [insideRect, setInsideRect] = (0, import_react17.useState)(null);
|
|
8738
|
+
const [dropLine, setDropLine] = (0, import_react17.useState)(null);
|
|
8739
|
+
(0, import_react17.useEffect)(() => {
|
|
8020
8740
|
if (!enabled) return;
|
|
8021
8741
|
const fn = (e) => {
|
|
8022
8742
|
refs.mouseRef.current = { x: e.clientX, y: e.clientY };
|
|
@@ -8024,7 +8744,7 @@ function DesignModeOverlay() {
|
|
|
8024
8744
|
window.addEventListener("pointermove", fn, { capture: true, passive: true });
|
|
8025
8745
|
return () => window.removeEventListener("pointermove", fn, { capture: true });
|
|
8026
8746
|
}, [enabled]);
|
|
8027
|
-
(0,
|
|
8747
|
+
(0, import_react17.useEffect)(() => {
|
|
8028
8748
|
if (!enabled) return;
|
|
8029
8749
|
if (historyMode !== "local") return;
|
|
8030
8750
|
const onKeyDown = (e) => {
|
|
@@ -8053,7 +8773,7 @@ function DesignModeOverlay() {
|
|
|
8053
8773
|
setInsideRect,
|
|
8054
8774
|
setDropLine
|
|
8055
8775
|
});
|
|
8056
|
-
(0,
|
|
8776
|
+
(0, import_react17.useEffect)(() => {
|
|
8057
8777
|
if (!enabled || activeDrag) return;
|
|
8058
8778
|
if (undoRequestId === refs.processedUndoIdRef.current) return;
|
|
8059
8779
|
refs.processedUndoIdRef.current = undoRequestId;
|
|
@@ -8070,7 +8790,7 @@ function DesignModeOverlay() {
|
|
|
8070
8790
|
});
|
|
8071
8791
|
syncHistoryAvailability();
|
|
8072
8792
|
}, [undoRequestId, enabled, activeDrag, applyCommand, resume, selectElement, syncHistoryAvailability, undoLastChange]);
|
|
8073
|
-
(0,
|
|
8793
|
+
(0, import_react17.useEffect)(() => {
|
|
8074
8794
|
if (!enabled || activeDrag || historyMode !== "local") return;
|
|
8075
8795
|
if (redoRequestId === refs.processedRedoIdRef.current) return;
|
|
8076
8796
|
refs.processedRedoIdRef.current = redoRequestId;
|
|
@@ -8082,42 +8802,29 @@ function DesignModeOverlay() {
|
|
|
8082
8802
|
}
|
|
8083
8803
|
syncHistoryAvailability();
|
|
8084
8804
|
}, [redoRequestId, enabled, activeDrag, applyCommand, historyMode, resume, selectElement, syncHistoryAvailability, redoLastChange]);
|
|
8085
|
-
(0,
|
|
8805
|
+
(0, import_react17.useEffect)(() => {
|
|
8086
8806
|
syncHistoryAvailability();
|
|
8087
8807
|
}, [syncHistoryAvailability]);
|
|
8088
|
-
(0,
|
|
8808
|
+
(0, import_react17.useEffect)(() => {
|
|
8089
8809
|
dispatchRuntimeEvent({
|
|
8090
8810
|
type: "design-mode-changed",
|
|
8091
8811
|
mode: enabled ? "design" : "off"
|
|
8092
8812
|
});
|
|
8093
8813
|
}, [enabled]);
|
|
8094
|
-
(0,
|
|
8814
|
+
(0, import_react17.useEffect)(() => {
|
|
8095
8815
|
const aiOutput = exportChangesForAI();
|
|
8096
8816
|
const updatedAt = orderedChanges.length > 0 ? orderedChanges[orderedChanges.length - 1]?.at ?? Date.now() : Date.now();
|
|
8097
8817
|
dispatchRuntimeEvent({
|
|
8098
8818
|
type: "arrange-session-changed",
|
|
8099
|
-
session: {
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
id: `${event.kind}:${event.nodeKey}:${event.at}:${index}`,
|
|
8104
|
-
kind: event.kind,
|
|
8105
|
-
nodeKey: event.nodeKey,
|
|
8106
|
-
nodeId: event.nodeId,
|
|
8107
|
-
inspectorRef: event.inspectorRef,
|
|
8108
|
-
summary: summarizeEditorChangeEvent(event),
|
|
8109
|
-
at: event.at
|
|
8110
|
-
})),
|
|
8111
|
-
output: {
|
|
8112
|
-
json: aiOutput,
|
|
8113
|
-
prompt: aiOutput.aiPromptContext,
|
|
8114
|
-
summary: orderedChanges.length === 0 ? "No arrange changes recorded yet." : `${orderedChanges.length} arrange change${orderedChanges.length === 1 ? "" : "s"} recorded.`
|
|
8115
|
-
},
|
|
8819
|
+
session: buildArrangeSessionSnapshot({
|
|
8820
|
+
enabled,
|
|
8821
|
+
orderedChanges,
|
|
8822
|
+
aiOutput,
|
|
8116
8823
|
updatedAt
|
|
8117
|
-
}
|
|
8824
|
+
})
|
|
8118
8825
|
});
|
|
8119
8826
|
}, [enabled, exportChangesForAI, orderedChanges]);
|
|
8120
|
-
(0,
|
|
8827
|
+
(0, import_react17.useEffect)(() => {
|
|
8121
8828
|
if (!enabled) return;
|
|
8122
8829
|
document.body.classList.add("design-mode-active");
|
|
8123
8830
|
return () => document.body.classList.remove("design-mode-active");
|
|
@@ -8130,6 +8837,13 @@ function DesignModeOverlay() {
|
|
|
8130
8837
|
autoScrollStateRef: refs.autoScrollStateRef
|
|
8131
8838
|
});
|
|
8132
8839
|
useDragVisualLoop({ activeDrag, refs, getCommitLaneSnapshot, setInsideRect, setDropLine });
|
|
8840
|
+
useExternalDragLoop({
|
|
8841
|
+
externalDrag,
|
|
8842
|
+
refs,
|
|
8843
|
+
elements,
|
|
8844
|
+
resolveNodeElement,
|
|
8845
|
+
setDropLine
|
|
8846
|
+
});
|
|
8133
8847
|
const { handleResizeHandlePointerDown } = useResizeSession({
|
|
8134
8848
|
enabled,
|
|
8135
8849
|
refs,
|
|
@@ -8185,7 +8899,7 @@ function DesignModeOverlay() {
|
|
|
8185
8899
|
}
|
|
8186
8900
|
}
|
|
8187
8901
|
),
|
|
8188
|
-
dropLine && activeDrag && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8902
|
+
dropLine && (activeDrag ?? externalDrag) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8189
8903
|
"div",
|
|
8190
8904
|
{
|
|
8191
8905
|
"data-design-mode-ui": true,
|
|
@@ -8210,8 +8924,8 @@ function DesignModeOverlay() {
|
|
|
8210
8924
|
}
|
|
8211
8925
|
|
|
8212
8926
|
// src/client/dnd/design-mode/DesignModeErrorBoundary.tsx
|
|
8213
|
-
var
|
|
8214
|
-
var DesignModeErrorBoundary = class extends
|
|
8927
|
+
var import_react18 = __toESM(require("react"));
|
|
8928
|
+
var DesignModeErrorBoundary = class extends import_react18.default.Component {
|
|
8215
8929
|
constructor(props) {
|
|
8216
8930
|
super(props);
|
|
8217
8931
|
this.state = { hasError: false };
|
|
@@ -8244,35 +8958,40 @@ var combinedCollisionDetection = (args) => {
|
|
|
8244
8958
|
|
|
8245
8959
|
// src/client/dnd/DndProvider.tsx
|
|
8246
8960
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
8961
|
+
var externalDragMouse = { x: 0, y: 0, commitRequested: false };
|
|
8247
8962
|
function DndProvider({ children }) {
|
|
8248
8963
|
const setActive = useDndStore((s) => s.setActive);
|
|
8249
8964
|
const dragEndHandlers = useDndStore((s) => s.dragEndHandlers);
|
|
8250
|
-
const toggle = useDesignModeStore((s) => s.toggle);
|
|
8251
8965
|
const designModeEnabled = useDesignModeStore((s) => s.enabled);
|
|
8252
|
-
const setDesignModeEnabled = useDesignModeStore((s) => s.setEnabled);
|
|
8253
8966
|
const setHistoryMode = useDesignModeStore((s) => s.setHistoryMode);
|
|
8254
8967
|
const setInspectorTheme = useDesignModeStore((s) => s.setInspectorTheme);
|
|
8255
8968
|
const requestUndo = useDesignModeStore((s) => s.requestUndo);
|
|
8256
|
-
(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)(() => {
|
|
8257
8976
|
const handleKeyDown = (e) => {
|
|
8258
8977
|
if (e.ctrlKey && e.shiftKey && e.key === "D") {
|
|
8259
8978
|
e.preventDefault();
|
|
8260
|
-
|
|
8979
|
+
transitionDesignMode(!useDesignModeStore.getState().enabled);
|
|
8261
8980
|
}
|
|
8262
8981
|
};
|
|
8263
8982
|
window.addEventListener("keydown", handleKeyDown);
|
|
8264
8983
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
8265
|
-
}, [
|
|
8266
|
-
(0,
|
|
8984
|
+
}, [transitionDesignMode]);
|
|
8985
|
+
(0, import_react19.useEffect)(() => {
|
|
8267
8986
|
const handleHostCommand = (event) => {
|
|
8268
8987
|
const detail = event.detail;
|
|
8269
8988
|
if (!detail || typeof detail !== "object") return;
|
|
8270
8989
|
switch (detail.type) {
|
|
8271
8990
|
case "sync-editor-state":
|
|
8272
8991
|
if (detail.mode === "design") {
|
|
8273
|
-
|
|
8992
|
+
transitionDesignMode(true);
|
|
8274
8993
|
} else if (detail.mode === "inspect" || detail.mode === "off") {
|
|
8275
|
-
|
|
8994
|
+
transitionDesignMode(false);
|
|
8276
8995
|
}
|
|
8277
8996
|
if (detail.historyMode) {
|
|
8278
8997
|
setHistoryMode(detail.historyMode);
|
|
@@ -8282,7 +9001,7 @@ function DndProvider({ children }) {
|
|
|
8282
9001
|
}
|
|
8283
9002
|
break;
|
|
8284
9003
|
case "set-design-mode":
|
|
8285
|
-
|
|
9004
|
+
transitionDesignMode(detail.enabled);
|
|
8286
9005
|
break;
|
|
8287
9006
|
case "set-history-mode":
|
|
8288
9007
|
setHistoryMode(detail.historyMode);
|
|
@@ -8293,6 +9012,21 @@ function DndProvider({ children }) {
|
|
|
8293
9012
|
case "request-undo":
|
|
8294
9013
|
requestUndo();
|
|
8295
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;
|
|
8296
9030
|
default:
|
|
8297
9031
|
break;
|
|
8298
9032
|
}
|
|
@@ -8302,7 +9036,7 @@ function DndProvider({ children }) {
|
|
|
8302
9036
|
window.removeEventListener(HOST_COMMAND_EVENT, handleHostCommand);
|
|
8303
9037
|
};
|
|
8304
9038
|
}, [
|
|
8305
|
-
|
|
9039
|
+
transitionDesignMode,
|
|
8306
9040
|
setHistoryMode,
|
|
8307
9041
|
setInspectorTheme,
|
|
8308
9042
|
requestUndo
|
|
@@ -8310,7 +9044,7 @@ function DndProvider({ children }) {
|
|
|
8310
9044
|
const pointerSensor = useSensor(PointerSensor, { activationConstraint: { distance: 8 } });
|
|
8311
9045
|
const keyboardSensor = useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates });
|
|
8312
9046
|
const sensors = useSensors(pointerSensor, keyboardSensor);
|
|
8313
|
-
const handleDragStart = (0,
|
|
9047
|
+
const handleDragStart = (0, import_react19.useCallback)(
|
|
8314
9048
|
(event) => {
|
|
8315
9049
|
const { active } = event;
|
|
8316
9050
|
const element = document.querySelector(`[data-canvas-node="${active.id}"]`);
|
|
@@ -8318,7 +9052,7 @@ function DndProvider({ children }) {
|
|
|
8318
9052
|
},
|
|
8319
9053
|
[setActive]
|
|
8320
9054
|
);
|
|
8321
|
-
const handleDragEnd = (0,
|
|
9055
|
+
const handleDragEnd = (0, import_react19.useCallback)(
|
|
8322
9056
|
(event) => {
|
|
8323
9057
|
const { active, over } = event;
|
|
8324
9058
|
const dragEndEvent = {
|
|
@@ -8334,9 +9068,10 @@ function DndProvider({ children }) {
|
|
|
8334
9068
|
},
|
|
8335
9069
|
[dragEndHandlers, setActive]
|
|
8336
9070
|
);
|
|
8337
|
-
const handleDesignModeCrash = (0,
|
|
9071
|
+
const handleDesignModeCrash = (0, import_react19.useCallback)(() => {
|
|
8338
9072
|
const designModeState = useDesignModeStore.getState();
|
|
8339
9073
|
designModeState.resetAll();
|
|
9074
|
+
designModeState.resetArrangeSession();
|
|
8340
9075
|
designModeState.setEnabled(false);
|
|
8341
9076
|
}, []);
|
|
8342
9077
|
if (designModeEnabled) {
|
|
@@ -8377,7 +9112,7 @@ function DndProvider({ children }) {
|
|
|
8377
9112
|
}
|
|
8378
9113
|
|
|
8379
9114
|
// src/client/useArchieDevToolsRuntime.ts
|
|
8380
|
-
var
|
|
9115
|
+
var import_react21 = require("react");
|
|
8381
9116
|
|
|
8382
9117
|
// src/client/inject-inspector/archieOrigins.ts
|
|
8383
9118
|
var ARCHIE_HOST_ORIGINS = [
|
|
@@ -8483,10 +9218,9 @@ function injectInspector(opts = {}) {
|
|
|
8483
9218
|
document.head.appendChild(script);
|
|
8484
9219
|
return null;
|
|
8485
9220
|
}
|
|
8486
|
-
const localInspectorModulePath = "./inspector.js";
|
|
8487
9221
|
return import(
|
|
8488
9222
|
/* @vite-ignore */
|
|
8489
|
-
|
|
9223
|
+
"./inspector.js"
|
|
8490
9224
|
).then((m) => {
|
|
8491
9225
|
try {
|
|
8492
9226
|
m.default();
|
|
@@ -8572,13 +9306,13 @@ function setupArchieRouteListener(router) {
|
|
|
8572
9306
|
}
|
|
8573
9307
|
|
|
8574
9308
|
// src/client/runtime/domMetaSanitizer.ts
|
|
8575
|
-
var
|
|
9309
|
+
var import_react20 = __toESM(require("react"));
|
|
8576
9310
|
var _installed = false;
|
|
8577
9311
|
function installDomMetaSanitizer() {
|
|
8578
9312
|
if (_installed) return;
|
|
8579
9313
|
_installed = true;
|
|
8580
|
-
const _origCE =
|
|
8581
|
-
|
|
9314
|
+
const _origCE = import_react20.default.createElement.bind(import_react20.default);
|
|
9315
|
+
import_react20.default.createElement = function patchedCreateElement(type, props, ...children) {
|
|
8582
9316
|
if (typeof type === "string" && props != null && "__editorMeta" in props) {
|
|
8583
9317
|
const { __editorMeta: _stripped, ...rest } = props;
|
|
8584
9318
|
return _origCE(type, rest, ...children);
|
|
@@ -8602,18 +9336,26 @@ installDomMetaSanitizer();
|
|
|
8602
9336
|
installDomMetaSanitizer();
|
|
8603
9337
|
function useArchieDevToolsRuntime({
|
|
8604
9338
|
router,
|
|
8605
|
-
inspector
|
|
9339
|
+
inspector,
|
|
9340
|
+
inspectorOptions
|
|
8606
9341
|
}) {
|
|
8607
|
-
|
|
9342
|
+
const stableOptionsKey = JSON.stringify(inspectorOptions ?? null);
|
|
9343
|
+
const inspectorOptionsRef = (0, import_react21.useRef)(inspectorOptions);
|
|
9344
|
+
inspectorOptionsRef.current = inspectorOptions;
|
|
9345
|
+
(0, import_react21.useEffect)(() => {
|
|
8608
9346
|
if (process.env.NODE_ENV !== "development") {
|
|
8609
9347
|
return;
|
|
8610
9348
|
}
|
|
8611
9349
|
const unsubscribe = setupArchieRouteListener(router);
|
|
8612
|
-
if (inspector) {
|
|
8613
|
-
|
|
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
|
+
});
|
|
8614
9356
|
}
|
|
8615
9357
|
return unsubscribe;
|
|
8616
|
-
}, [router, inspector]);
|
|
9358
|
+
}, [router, inspector, stableOptionsKey]);
|
|
8617
9359
|
}
|
|
8618
9360
|
|
|
8619
9361
|
// src/client/ArchieDevToolProvider.tsx
|
|
@@ -8621,9 +9363,10 @@ var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
|
8621
9363
|
function ArchieDevToolProvider({
|
|
8622
9364
|
children,
|
|
8623
9365
|
router,
|
|
8624
|
-
inspector
|
|
9366
|
+
inspector,
|
|
9367
|
+
inspectorOptions
|
|
8625
9368
|
}) {
|
|
8626
|
-
useArchieDevToolsRuntime({ router, inspector });
|
|
9369
|
+
useArchieDevToolsRuntime({ router, inspector, inspectorOptions });
|
|
8627
9370
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DndProvider, { children });
|
|
8628
9371
|
}
|
|
8629
9372
|
// Annotate the CommonJS export names for ESM import in node:
|