made-refine 0.2.17 → 0.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +476 -506
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +476 -506
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-lksVP2Wq.d.mts → utils-CpmjloNg.d.mts} +0 -8
- package/dist/{utils-lksVP2Wq.d.ts → utils-CpmjloNg.d.ts} +0 -8
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1756 -1754
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +1756 -1754
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -197,6 +197,255 @@ function getZoomScale() {
|
|
|
197
197
|
return snap.active ? snap.zoom : 1;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
// src/utils/debug-stack.ts
|
|
201
|
+
var STACK_SOURCE_FILE_EXTENSION_REGEX = /\.(jsx|tsx|ts|js)$/;
|
|
202
|
+
var STACK_BUNDLED_FILE_PATTERN_REGEX = /(\.min|bundle|chunk|vendor|vendors|runtime|polyfill|polyfills)\.(js|mjs|cjs)$|(chunk|bundle|vendor|vendors|runtime|polyfill|polyfills|framework|app|main|index)[-_.][A-Za-z0-9_-]{4,}\.(js|mjs|cjs)$|[\da-f]{8,}\.(js|mjs|cjs)$|[-_.][\da-f]{20,}\.(js|mjs|cjs)$|\/dist\/|\/build\/|\/.next\/|\/out\/|\/node_modules\/|\.webpack\.|\.vite\.|\.turbopack\./i;
|
|
203
|
+
var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
|
|
204
|
+
var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
|
|
205
|
+
var SERVER_FRAME_MARKER = "(at Server)";
|
|
206
|
+
var STACK_INTERNAL_SCHEME_PREFIXES = [
|
|
207
|
+
"rsc://",
|
|
208
|
+
"about://React/",
|
|
209
|
+
"React/Server/",
|
|
210
|
+
"file:///",
|
|
211
|
+
"webpack://",
|
|
212
|
+
"webpack-internal://",
|
|
213
|
+
"node:",
|
|
214
|
+
"turbopack://",
|
|
215
|
+
"/app-pages-browser/"
|
|
216
|
+
];
|
|
217
|
+
function formatOwnerDebugStack(stack) {
|
|
218
|
+
if (!stack) return "";
|
|
219
|
+
const lines = stack.split("\n");
|
|
220
|
+
const filtered = [];
|
|
221
|
+
for (const line of lines) {
|
|
222
|
+
const trimmed = line.trim();
|
|
223
|
+
if (!trimmed) continue;
|
|
224
|
+
if (trimmed === "Error: react-stack-top-frame") continue;
|
|
225
|
+
if (trimmed.includes("react_stack_bottom_frame") || trimmed.includes("react-stack-bottom-frame")) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
filtered.push(line);
|
|
229
|
+
}
|
|
230
|
+
if (filtered.length > 0 && filtered[0].includes("fakeJSXCallSite")) {
|
|
231
|
+
filtered.shift();
|
|
232
|
+
}
|
|
233
|
+
return filtered.join("\n");
|
|
234
|
+
}
|
|
235
|
+
function extractStackLocation(urlLike) {
|
|
236
|
+
if (!urlLike.includes(":")) return [urlLike, void 0, void 0];
|
|
237
|
+
const isWrappedLocation = urlLike.startsWith("(") && /:\d+\)$/.test(urlLike);
|
|
238
|
+
const sanitizedResult = isWrappedLocation ? urlLike.slice(1, -1) : urlLike;
|
|
239
|
+
const parts = /(.+?)(?::(\d+))?(?::(\d+))?$/.exec(sanitizedResult);
|
|
240
|
+
if (!parts) return [sanitizedResult, void 0, void 0];
|
|
241
|
+
return [
|
|
242
|
+
parts[1],
|
|
243
|
+
parts[2] !== void 0 ? Number(parts[2]) : void 0,
|
|
244
|
+
parts[3] !== void 0 ? Number(parts[3]) : void 0
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
function parseV8StackLine(line) {
|
|
248
|
+
let currentLine = line;
|
|
249
|
+
if (currentLine.includes("(eval ")) {
|
|
250
|
+
currentLine = currentLine.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
251
|
+
}
|
|
252
|
+
let sanitizedLine = currentLine.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
253
|
+
const locationMatch = sanitizedLine.match(/ (\(.+\)$)/);
|
|
254
|
+
if (locationMatch) {
|
|
255
|
+
sanitizedLine = sanitizedLine.replace(locationMatch[0], "");
|
|
256
|
+
}
|
|
257
|
+
const [fileName, lineNumber, columnNumber] = extractStackLocation(
|
|
258
|
+
locationMatch ? locationMatch[1] : sanitizedLine
|
|
259
|
+
);
|
|
260
|
+
const functionName = locationMatch && sanitizedLine ? sanitizedLine : void 0;
|
|
261
|
+
if (fileName === "eval" || fileName === "<anonymous>") {
|
|
262
|
+
return {
|
|
263
|
+
functionName
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
functionName,
|
|
268
|
+
fileName,
|
|
269
|
+
lineNumber,
|
|
270
|
+
columnNumber,
|
|
271
|
+
source: currentLine,
|
|
272
|
+
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function parseFFOrSafariStackLine(line) {
|
|
276
|
+
let currentLine = line;
|
|
277
|
+
if (currentLine.includes(" > eval")) {
|
|
278
|
+
currentLine = currentLine.replace(
|
|
279
|
+
/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
|
|
280
|
+
":$1"
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const trimmed = currentLine.trim();
|
|
284
|
+
if (!trimmed || SAFARI_NATIVE_CODE_REGEXP.test(trimmed)) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
if (!trimmed.includes("@") && !trimmed.includes(":")) {
|
|
288
|
+
return {
|
|
289
|
+
functionName: trimmed,
|
|
290
|
+
source: currentLine,
|
|
291
|
+
isServer: trimmed.includes(SERVER_FRAME_MARKER)
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
const atIndex = trimmed.lastIndexOf("@");
|
|
295
|
+
if (atIndex === -1) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const maybeFunctionName = trimmed.slice(0, atIndex);
|
|
299
|
+
const location = trimmed.slice(atIndex + 1);
|
|
300
|
+
const [fileName, lineNumber, columnNumber] = extractStackLocation(location);
|
|
301
|
+
return {
|
|
302
|
+
functionName: maybeFunctionName || void 0,
|
|
303
|
+
fileName,
|
|
304
|
+
lineNumber,
|
|
305
|
+
columnNumber,
|
|
306
|
+
source: currentLine,
|
|
307
|
+
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function parseInStackLine(line) {
|
|
311
|
+
const functionName = line.replace(/^\s*in\s+/, "").replace(/\s*\(at .*\)$/, "").trim();
|
|
312
|
+
if (!functionName) return null;
|
|
313
|
+
return {
|
|
314
|
+
functionName,
|
|
315
|
+
source: line,
|
|
316
|
+
isServer: line.includes(SERVER_FRAME_MARKER)
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function parseDebugStack(stack) {
|
|
320
|
+
const frames = [];
|
|
321
|
+
for (const rawLine of stack.split("\n")) {
|
|
322
|
+
if (FIREFOX_SAFARI_STACK_REGEXP.test(rawLine)) {
|
|
323
|
+
const parsed = parseFFOrSafariStackLine(rawLine);
|
|
324
|
+
if (parsed) frames.push(parsed);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (/^\s*at\s+/.test(rawLine)) {
|
|
328
|
+
const parsed = parseV8StackLine(rawLine);
|
|
329
|
+
if (parsed) frames.push(parsed);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (/^\s*in\s+/.test(rawLine)) {
|
|
333
|
+
const parsed = parseInStackLine(rawLine);
|
|
334
|
+
if (parsed) frames.push(parsed);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return frames;
|
|
338
|
+
}
|
|
339
|
+
function normalizeStackFileName(fileName) {
|
|
340
|
+
if (!fileName) return "";
|
|
341
|
+
let normalized = fileName;
|
|
342
|
+
const isHttpUrl = normalized.startsWith("http://") || normalized.startsWith("https://");
|
|
343
|
+
if (isHttpUrl) {
|
|
344
|
+
try {
|
|
345
|
+
normalized = new URL(normalized).pathname;
|
|
346
|
+
} catch {
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
let didStripPrefix = true;
|
|
350
|
+
while (didStripPrefix) {
|
|
351
|
+
didStripPrefix = false;
|
|
352
|
+
for (const prefix of STACK_INTERNAL_SCHEME_PREFIXES) {
|
|
353
|
+
if (normalized.startsWith(prefix)) {
|
|
354
|
+
normalized = normalized.slice(prefix.length);
|
|
355
|
+
if (prefix === "file:///") {
|
|
356
|
+
normalized = `/${normalized.replace(/^\/+/, "")}`;
|
|
357
|
+
}
|
|
358
|
+
didStripPrefix = true;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
normalized = normalized.replace(/^\/\(app-pages-browser\)\//, "/").replace(/^\/\.\//, "/").replace(/^\.\//, "");
|
|
364
|
+
const queryIndex = normalized.indexOf("?");
|
|
365
|
+
if (queryIndex !== -1) {
|
|
366
|
+
normalized = normalized.slice(0, queryIndex);
|
|
367
|
+
}
|
|
368
|
+
return normalized;
|
|
369
|
+
}
|
|
370
|
+
function isSourceStackFile(fileName) {
|
|
371
|
+
const normalizedFileName = normalizeStackFileName(fileName);
|
|
372
|
+
if (!normalizedFileName) return false;
|
|
373
|
+
if (!STACK_SOURCE_FILE_EXTENSION_REGEX.test(normalizedFileName)) return false;
|
|
374
|
+
return !STACK_BUNDLED_FILE_PATTERN_REGEX.test(normalizedFileName);
|
|
375
|
+
}
|
|
376
|
+
function buildFunctionNameToRscFramesMap(fiber) {
|
|
377
|
+
const functionNameToRscFrames = /* @__PURE__ */ new Map();
|
|
378
|
+
const visited = /* @__PURE__ */ new Set();
|
|
379
|
+
let current = fiber;
|
|
380
|
+
while (current && !visited.has(current)) {
|
|
381
|
+
visited.add(current);
|
|
382
|
+
const rawStack = current?._debugStack?.stack;
|
|
383
|
+
const stack = typeof rawStack === "string" ? formatOwnerDebugStack(rawStack) : "";
|
|
384
|
+
if (stack) {
|
|
385
|
+
const frames = parseDebugStack(stack);
|
|
386
|
+
for (const frame of frames) {
|
|
387
|
+
if (!frame.functionName || !frame.fileName) continue;
|
|
388
|
+
if (!frame.fileName.startsWith("rsc://")) continue;
|
|
389
|
+
const normalized = normalizeStackFileName(frame.fileName);
|
|
390
|
+
if (!normalized) continue;
|
|
391
|
+
const existing = functionNameToRscFrames.get(frame.functionName) ?? [];
|
|
392
|
+
const duplicate = existing.some(
|
|
393
|
+
(candidate) => candidate.fileName === normalized && candidate.lineNumber === frame.lineNumber && candidate.columnNumber === frame.columnNumber
|
|
394
|
+
);
|
|
395
|
+
if (!duplicate) {
|
|
396
|
+
existing.push({
|
|
397
|
+
fileName: normalized,
|
|
398
|
+
lineNumber: frame.lineNumber,
|
|
399
|
+
columnNumber: frame.columnNumber
|
|
400
|
+
});
|
|
401
|
+
functionNameToRscFrames.set(frame.functionName, existing);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
current = current._debugOwner ?? current.return ?? null;
|
|
406
|
+
}
|
|
407
|
+
return functionNameToRscFrames;
|
|
408
|
+
}
|
|
409
|
+
function enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) {
|
|
410
|
+
if (!frame.functionName) return frame;
|
|
411
|
+
const available = functionNameToRscFrames.get(frame.functionName);
|
|
412
|
+
if (!available) return frame;
|
|
413
|
+
const usageIndex = functionNameToUsageIndex.get(frame.functionName) ?? 0;
|
|
414
|
+
const resolved = available[usageIndex % available.length];
|
|
415
|
+
functionNameToUsageIndex.set(frame.functionName, usageIndex + 1);
|
|
416
|
+
return {
|
|
417
|
+
...frame,
|
|
418
|
+
fileName: resolved.fileName,
|
|
419
|
+
lineNumber: resolved.lineNumber,
|
|
420
|
+
columnNumber: resolved.columnNumber
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function getSourceFromDebugStack(fiber) {
|
|
424
|
+
const rawStack = fiber?._debugStack?.stack;
|
|
425
|
+
if (typeof rawStack !== "string" || rawStack.length === 0) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
const formattedStack = formatOwnerDebugStack(rawStack);
|
|
429
|
+
if (!formattedStack) return null;
|
|
430
|
+
const stackFrames = parseDebugStack(formattedStack);
|
|
431
|
+
const functionNameToRscFrames = buildFunctionNameToRscFramesMap(fiber);
|
|
432
|
+
const functionNameToUsageIndex = /* @__PURE__ */ new Map();
|
|
433
|
+
for (const frame of stackFrames) {
|
|
434
|
+
const maybeEnriched = frame.isServer ? enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) : frame;
|
|
435
|
+
if (!maybeEnriched.fileName) continue;
|
|
436
|
+
const normalizedFileName = normalizeStackFileName(maybeEnriched.fileName);
|
|
437
|
+
if (!normalizedFileName) continue;
|
|
438
|
+
if (isSourceStackFile(normalizedFileName)) {
|
|
439
|
+
return {
|
|
440
|
+
fileName: normalizedFileName,
|
|
441
|
+
lineNumber: maybeEnriched.lineNumber,
|
|
442
|
+
columnNumber: maybeEnriched.columnNumber
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
|
|
200
449
|
// src/utils/react-fiber.ts
|
|
201
450
|
function getFiberForElement(element) {
|
|
202
451
|
if (typeof window !== "undefined") {
|
|
@@ -224,6 +473,8 @@ function getSourceFromFiber(fiber) {
|
|
|
224
473
|
if (pending?.fileName) return pending;
|
|
225
474
|
const memo = fiber?.memoizedProps?.__source;
|
|
226
475
|
if (memo?.fileName) return memo;
|
|
476
|
+
const fromDebugStack = getSourceFromDebugStack(fiber);
|
|
477
|
+
if (fromDebugStack?.fileName) return fromDebugStack;
|
|
227
478
|
return null;
|
|
228
479
|
}
|
|
229
480
|
function buildFrame(fiber) {
|
|
@@ -1647,516 +1898,164 @@ function htmlChildren(el) {
|
|
|
1647
1898
|
function findFlexAncestor(element, boundary) {
|
|
1648
1899
|
let current = element;
|
|
1649
1900
|
while (current && current !== document.body) {
|
|
1650
|
-
const parent = current.parentElement;
|
|
1651
|
-
if (!parent) break;
|
|
1652
|
-
const display = getComputedStyle(parent).display;
|
|
1653
|
-
if (display === "flex" || display === "inline-flex") {
|
|
1654
|
-
return { flexParent: parent, child: current };
|
|
1655
|
-
}
|
|
1656
|
-
if (boundary && parent === boundary) break;
|
|
1657
|
-
current = parent;
|
|
1658
|
-
}
|
|
1659
|
-
return null;
|
|
1660
|
-
}
|
|
1661
|
-
function computeHoverHighlight(elementUnder, selectedElement) {
|
|
1662
|
-
if (!elementUnder || elementUnder === document.body || elementUnder === document.documentElement || elementUnder.closest("[data-direct-edit]") || elementUnder.closest("[data-direct-edit-host]") || elementUnder === selectedElement) {
|
|
1663
|
-
return null;
|
|
1664
|
-
}
|
|
1665
|
-
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1666
|
-
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
1667
|
-
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
1668
|
-
return { flexContainer: elementUnder, children: htmlChildren(elementUnder) };
|
|
1669
|
-
}
|
|
1670
|
-
const found = findFlexAncestor(elementUnder, boundary);
|
|
1671
|
-
if (found) {
|
|
1672
|
-
return { flexContainer: found.flexParent, children: htmlChildren(found.flexParent) };
|
|
1673
|
-
}
|
|
1674
|
-
return { flexContainer: elementUnder, children: [] };
|
|
1675
|
-
}
|
|
1676
|
-
function resolveElementTarget(elementUnder, selectedElement) {
|
|
1677
|
-
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1678
|
-
const found = findFlexAncestor(elementUnder, boundary);
|
|
1679
|
-
if (found && found.flexParent === boundary) return elementUnder;
|
|
1680
|
-
return found?.child ?? elementUnder;
|
|
1681
|
-
}
|
|
1682
|
-
function findChildAtPoint(parent, clientX, clientY) {
|
|
1683
|
-
const children = htmlChildren(parent);
|
|
1684
|
-
if (children.length === 0) return null;
|
|
1685
|
-
const hit = children.find((child) => {
|
|
1686
|
-
const r = child.getBoundingClientRect();
|
|
1687
|
-
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
|
|
1688
|
-
});
|
|
1689
|
-
if (hit) return hit;
|
|
1690
|
-
if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
|
|
1691
|
-
return null;
|
|
1692
|
-
}
|
|
1693
|
-
function elementFromPointWithoutOverlays(x, y) {
|
|
1694
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1695
|
-
if (host) host.style.display = "none";
|
|
1696
|
-
const el = document.elementFromPoint(x, y);
|
|
1697
|
-
if (host) host.style.display = "";
|
|
1698
|
-
return el;
|
|
1699
|
-
}
|
|
1700
|
-
function isLayoutContainer(element) {
|
|
1701
|
-
const display = window.getComputedStyle(element).display;
|
|
1702
|
-
return display === "flex" || display === "inline-flex" || display === "grid" || display === "inline-grid";
|
|
1703
|
-
}
|
|
1704
|
-
function isBlockContainer(element) {
|
|
1705
|
-
const display = window.getComputedStyle(element).display;
|
|
1706
|
-
return display === "block" || display === "flow-root" || display === "inline-block" || display === "list-item";
|
|
1707
|
-
}
|
|
1708
|
-
function skipElement(el, exclude) {
|
|
1709
|
-
if (exclude && exclude.contains(el)) return true;
|
|
1710
|
-
if (el === document.body || el === document.documentElement) return true;
|
|
1711
|
-
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) return true;
|
|
1712
|
-
return false;
|
|
1713
|
-
}
|
|
1714
|
-
function findContainerViaTraversal(x, y, exclude) {
|
|
1715
|
-
const el = elementFromPointWithoutOverlays(x, y);
|
|
1716
|
-
if (!el) return null;
|
|
1717
|
-
let current = el;
|
|
1718
|
-
while (current) {
|
|
1719
|
-
if (!skipElement(current, exclude)) {
|
|
1720
|
-
if (isLayoutContainer(current) || isBlockContainer(current)) return current;
|
|
1721
|
-
}
|
|
1722
|
-
current = current.parentElement;
|
|
1723
|
-
}
|
|
1724
|
-
return null;
|
|
1725
|
-
}
|
|
1726
|
-
function findContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1727
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1728
|
-
if (host) host.style.display = "none";
|
|
1729
|
-
const elements = document.elementsFromPoint(x, y);
|
|
1730
|
-
if (host) host.style.display = "";
|
|
1731
|
-
for (const el of elements) {
|
|
1732
|
-
if (skipElement(el, exclude)) continue;
|
|
1733
|
-
if (isLayoutContainer(el) || isBlockContainer(el)) return el;
|
|
1734
|
-
}
|
|
1735
|
-
if (preferredParent && (isLayoutContainer(preferredParent) || isBlockContainer(preferredParent))) {
|
|
1736
|
-
for (const el of elements) {
|
|
1737
|
-
if (el === preferredParent) return preferredParent;
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
return findContainerViaTraversal(x, y, exclude);
|
|
1741
|
-
}
|
|
1742
|
-
function findLayoutContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1743
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1744
|
-
if (host) host.style.display = "none";
|
|
1745
|
-
const elements = document.elementsFromPoint(x, y);
|
|
1746
|
-
if (host) host.style.display = "";
|
|
1747
|
-
for (const el of elements) {
|
|
1748
|
-
if (skipElement(el, exclude)) continue;
|
|
1749
|
-
if (isLayoutContainer(el)) return el;
|
|
1750
|
-
}
|
|
1751
|
-
if (preferredParent && isLayoutContainer(preferredParent)) {
|
|
1752
|
-
for (const el of elements) {
|
|
1753
|
-
if (el === preferredParent) return preferredParent;
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
return null;
|
|
1757
|
-
}
|
|
1758
|
-
function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
|
|
1759
|
-
const { axis, reversed: isReversed } = detectChildrenDirection(container, draggedElement);
|
|
1760
|
-
const isHorizontal = axis === "horizontal";
|
|
1761
|
-
const children = Array.from(container.children).filter(
|
|
1762
|
-
(child) => child !== draggedElement && child instanceof HTMLElement
|
|
1763
|
-
);
|
|
1764
|
-
if (children.length === 0) {
|
|
1765
|
-
const containerRect2 = container.getBoundingClientRect();
|
|
1766
|
-
return {
|
|
1767
|
-
insertBefore: null,
|
|
1768
|
-
indicator: {
|
|
1769
|
-
x: containerRect2.left + 4,
|
|
1770
|
-
y: containerRect2.top + 4,
|
|
1771
|
-
width: isHorizontal ? 1 : containerRect2.width - 8,
|
|
1772
|
-
height: isHorizontal ? containerRect2.height - 8 : 1
|
|
1773
|
-
}
|
|
1774
|
-
};
|
|
1775
|
-
}
|
|
1776
|
-
const containerRect = container.getBoundingClientRect();
|
|
1777
|
-
let insertBefore = null;
|
|
1778
|
-
let indicatorPosition = 0;
|
|
1779
|
-
for (let i = 0; i < children.length; i++) {
|
|
1780
|
-
const child = children[i];
|
|
1781
|
-
const rect = child.getBoundingClientRect();
|
|
1782
|
-
const midpoint = isHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
|
|
1783
|
-
const pointer = isHorizontal ? pointerX : pointerY;
|
|
1784
|
-
const beforeMidpoint = isReversed ? pointer > midpoint : pointer < midpoint;
|
|
1785
|
-
if (beforeMidpoint) {
|
|
1786
|
-
insertBefore = child;
|
|
1787
|
-
indicatorPosition = isHorizontal ? rect.left : rect.top;
|
|
1788
|
-
break;
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
if (!insertBefore) {
|
|
1792
|
-
const lastChild = children[children.length - 1];
|
|
1793
|
-
const lastRect = lastChild.getBoundingClientRect();
|
|
1794
|
-
indicatorPosition = isHorizontal ? lastRect.right : lastRect.bottom;
|
|
1795
|
-
}
|
|
1796
|
-
const indicator = isHorizontal ? {
|
|
1797
|
-
x: indicatorPosition,
|
|
1798
|
-
y: containerRect.top + 4,
|
|
1799
|
-
width: 2,
|
|
1800
|
-
height: containerRect.height - 8
|
|
1801
|
-
} : {
|
|
1802
|
-
x: containerRect.left + 4,
|
|
1803
|
-
y: indicatorPosition,
|
|
1804
|
-
width: containerRect.width - 8,
|
|
1805
|
-
height: 2
|
|
1806
|
-
};
|
|
1807
|
-
return { insertBefore, indicator };
|
|
1808
|
-
}
|
|
1809
|
-
function getFiberForElement2(element) {
|
|
1810
|
-
if (typeof window !== "undefined") {
|
|
1811
|
-
const devtools = window.__DIRECT_EDIT_DEVTOOLS__;
|
|
1812
|
-
if (devtools?.getFiberForElement) {
|
|
1813
|
-
const fiber = devtools.getFiberForElement(element);
|
|
1814
|
-
if (fiber) return fiber;
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
const fiberKey = Object.keys(element).find(
|
|
1818
|
-
(key) => key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$")
|
|
1819
|
-
);
|
|
1820
|
-
if (!fiberKey) return null;
|
|
1821
|
-
return element[fiberKey] || null;
|
|
1822
|
-
}
|
|
1823
|
-
var STACK_SOURCE_FILE_EXTENSION_REGEX = /\.(jsx|tsx|ts|js)$/;
|
|
1824
|
-
var STACK_BUNDLED_FILE_PATTERN_REGEX = /(\.min|bundle|chunk|vendor|vendors|runtime|polyfill|polyfills)\.(js|mjs|cjs)$|(chunk|bundle|vendor|vendors|runtime|polyfill|polyfills|framework|app|main|index)[-_.][A-Za-z0-9_-]{4,}\.(js|mjs|cjs)$|[\da-f]{8,}\.(js|mjs|cjs)$|[-_.][\da-f]{20,}\.(js|mjs|cjs)$|\/dist\/|\/build\/|\/.next\/|\/out\/|\/node_modules\/|\.webpack\.|\.vite\.|\.turbopack\./i;
|
|
1825
|
-
var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
|
|
1826
|
-
var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
|
|
1827
|
-
var SERVER_FRAME_MARKER = "(at Server)";
|
|
1828
|
-
var STACK_INTERNAL_SCHEME_PREFIXES = [
|
|
1829
|
-
"rsc://",
|
|
1830
|
-
"about://React/",
|
|
1831
|
-
"React/Server/",
|
|
1832
|
-
"file:///",
|
|
1833
|
-
"webpack://",
|
|
1834
|
-
"webpack-internal://",
|
|
1835
|
-
"node:",
|
|
1836
|
-
"turbopack://",
|
|
1837
|
-
"/app-pages-browser/"
|
|
1838
|
-
];
|
|
1839
|
-
function formatOwnerDebugStack(stack) {
|
|
1840
|
-
if (!stack) return "";
|
|
1841
|
-
const lines = stack.split("\n");
|
|
1842
|
-
const filtered = [];
|
|
1843
|
-
for (const line of lines) {
|
|
1844
|
-
const trimmed = line.trim();
|
|
1845
|
-
if (!trimmed) continue;
|
|
1846
|
-
if (trimmed === "Error: react-stack-top-frame") continue;
|
|
1847
|
-
if (trimmed.includes("react_stack_bottom_frame") || trimmed.includes("react-stack-bottom-frame")) {
|
|
1848
|
-
continue;
|
|
1849
|
-
}
|
|
1850
|
-
filtered.push(line);
|
|
1851
|
-
}
|
|
1852
|
-
if (filtered.length > 0 && filtered[0].includes("fakeJSXCallSite")) {
|
|
1853
|
-
filtered.shift();
|
|
1854
|
-
}
|
|
1855
|
-
return filtered.join("\n");
|
|
1856
|
-
}
|
|
1857
|
-
function extractStackLocation(urlLike) {
|
|
1858
|
-
if (!urlLike.includes(":")) return [urlLike, void 0, void 0];
|
|
1859
|
-
const isWrappedLocation = urlLike.startsWith("(") && /:\d+\)$/.test(urlLike);
|
|
1860
|
-
const sanitizedResult = isWrappedLocation ? urlLike.slice(1, -1) : urlLike;
|
|
1861
|
-
const parts = /(.+?)(?::(\d+))?(?::(\d+))?$/.exec(sanitizedResult);
|
|
1862
|
-
if (!parts) return [sanitizedResult, void 0, void 0];
|
|
1863
|
-
return [
|
|
1864
|
-
parts[1],
|
|
1865
|
-
parts[2] !== void 0 ? Number(parts[2]) : void 0,
|
|
1866
|
-
parts[3] !== void 0 ? Number(parts[3]) : void 0
|
|
1867
|
-
];
|
|
1868
|
-
}
|
|
1869
|
-
function parseV8StackLine(line) {
|
|
1870
|
-
let currentLine = line;
|
|
1871
|
-
if (currentLine.includes("(eval ")) {
|
|
1872
|
-
currentLine = currentLine.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
1873
|
-
}
|
|
1874
|
-
let sanitizedLine = currentLine.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
1875
|
-
const locationMatch = sanitizedLine.match(/ (\(.+\)$)/);
|
|
1876
|
-
if (locationMatch) {
|
|
1877
|
-
sanitizedLine = sanitizedLine.replace(locationMatch[0], "");
|
|
1878
|
-
}
|
|
1879
|
-
const [fileName, lineNumber, columnNumber] = extractStackLocation(
|
|
1880
|
-
locationMatch ? locationMatch[1] : sanitizedLine
|
|
1881
|
-
);
|
|
1882
|
-
const functionName = locationMatch && sanitizedLine ? sanitizedLine : void 0;
|
|
1883
|
-
if (fileName === "eval" || fileName === "<anonymous>") {
|
|
1884
|
-
return {
|
|
1885
|
-
functionName
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1888
|
-
return {
|
|
1889
|
-
functionName,
|
|
1890
|
-
fileName,
|
|
1891
|
-
lineNumber,
|
|
1892
|
-
columnNumber,
|
|
1893
|
-
source: currentLine,
|
|
1894
|
-
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
1895
|
-
};
|
|
1896
|
-
}
|
|
1897
|
-
function parseFFOrSafariStackLine(line) {
|
|
1898
|
-
let currentLine = line;
|
|
1899
|
-
if (currentLine.includes(" > eval")) {
|
|
1900
|
-
currentLine = currentLine.replace(
|
|
1901
|
-
/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
|
|
1902
|
-
":$1"
|
|
1903
|
-
);
|
|
1904
|
-
}
|
|
1905
|
-
const trimmed = currentLine.trim();
|
|
1906
|
-
if (!trimmed || SAFARI_NATIVE_CODE_REGEXP.test(trimmed)) {
|
|
1907
|
-
return null;
|
|
1908
|
-
}
|
|
1909
|
-
if (!trimmed.includes("@") && !trimmed.includes(":")) {
|
|
1910
|
-
return {
|
|
1911
|
-
functionName: trimmed,
|
|
1912
|
-
source: currentLine,
|
|
1913
|
-
isServer: trimmed.includes(SERVER_FRAME_MARKER)
|
|
1914
|
-
};
|
|
1915
|
-
}
|
|
1916
|
-
const atIndex = trimmed.lastIndexOf("@");
|
|
1917
|
-
if (atIndex === -1) {
|
|
1918
|
-
return null;
|
|
1919
|
-
}
|
|
1920
|
-
const maybeFunctionName = trimmed.slice(0, atIndex);
|
|
1921
|
-
const location = trimmed.slice(atIndex + 1);
|
|
1922
|
-
const [fileName, lineNumber, columnNumber] = extractStackLocation(location);
|
|
1923
|
-
return {
|
|
1924
|
-
functionName: maybeFunctionName || void 0,
|
|
1925
|
-
fileName,
|
|
1926
|
-
lineNumber,
|
|
1927
|
-
columnNumber,
|
|
1928
|
-
source: currentLine,
|
|
1929
|
-
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
1930
|
-
};
|
|
1931
|
-
}
|
|
1932
|
-
function parseInStackLine(line) {
|
|
1933
|
-
const functionName = line.replace(/^\s*in\s+/, "").replace(/\s*\(at .*\)$/, "").trim();
|
|
1934
|
-
if (!functionName) return null;
|
|
1935
|
-
return {
|
|
1936
|
-
functionName,
|
|
1937
|
-
source: line,
|
|
1938
|
-
isServer: line.includes(SERVER_FRAME_MARKER)
|
|
1939
|
-
};
|
|
1940
|
-
}
|
|
1941
|
-
function parseDebugStack(stack) {
|
|
1942
|
-
const frames = [];
|
|
1943
|
-
for (const rawLine of stack.split("\n")) {
|
|
1944
|
-
if (FIREFOX_SAFARI_STACK_REGEXP.test(rawLine)) {
|
|
1945
|
-
const parsed = parseFFOrSafariStackLine(rawLine);
|
|
1946
|
-
if (parsed) frames.push(parsed);
|
|
1947
|
-
continue;
|
|
1948
|
-
}
|
|
1949
|
-
if (/^\s*at\s+/.test(rawLine)) {
|
|
1950
|
-
const parsed = parseV8StackLine(rawLine);
|
|
1951
|
-
if (parsed) frames.push(parsed);
|
|
1952
|
-
continue;
|
|
1953
|
-
}
|
|
1954
|
-
if (/^\s*in\s+/.test(rawLine)) {
|
|
1955
|
-
const parsed = parseInStackLine(rawLine);
|
|
1956
|
-
if (parsed) frames.push(parsed);
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
return frames;
|
|
1960
|
-
}
|
|
1961
|
-
function normalizeStackFileName(fileName) {
|
|
1962
|
-
if (!fileName) return "";
|
|
1963
|
-
let normalized = fileName;
|
|
1964
|
-
const isHttpUrl = normalized.startsWith("http://") || normalized.startsWith("https://");
|
|
1965
|
-
if (isHttpUrl) {
|
|
1966
|
-
try {
|
|
1967
|
-
normalized = new URL(normalized).pathname;
|
|
1968
|
-
} catch {
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
let didStripPrefix = true;
|
|
1972
|
-
while (didStripPrefix) {
|
|
1973
|
-
didStripPrefix = false;
|
|
1974
|
-
for (const prefix of STACK_INTERNAL_SCHEME_PREFIXES) {
|
|
1975
|
-
if (normalized.startsWith(prefix)) {
|
|
1976
|
-
normalized = normalized.slice(prefix.length);
|
|
1977
|
-
if (prefix === "file:///") {
|
|
1978
|
-
normalized = `/${normalized.replace(/^\/+/, "")}`;
|
|
1979
|
-
}
|
|
1980
|
-
didStripPrefix = true;
|
|
1981
|
-
break;
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
normalized = normalized.replace(/^\/\(app-pages-browser\)\//, "/").replace(/^\/\.\//, "/").replace(/^\.\//, "");
|
|
1986
|
-
const queryIndex = normalized.indexOf("?");
|
|
1987
|
-
if (queryIndex !== -1) {
|
|
1988
|
-
normalized = normalized.slice(0, queryIndex);
|
|
1989
|
-
}
|
|
1990
|
-
return normalized;
|
|
1991
|
-
}
|
|
1992
|
-
function isSourceStackFile(fileName) {
|
|
1993
|
-
const normalizedFileName = normalizeStackFileName(fileName);
|
|
1994
|
-
if (!normalizedFileName) return false;
|
|
1995
|
-
if (!STACK_SOURCE_FILE_EXTENSION_REGEX.test(normalizedFileName)) return false;
|
|
1996
|
-
return !STACK_BUNDLED_FILE_PATTERN_REGEX.test(normalizedFileName);
|
|
1997
|
-
}
|
|
1998
|
-
function buildFunctionNameToRscFramesMap(fiber) {
|
|
1999
|
-
const functionNameToRscFrames = /* @__PURE__ */ new Map();
|
|
2000
|
-
const visited = /* @__PURE__ */ new Set();
|
|
2001
|
-
let current = fiber;
|
|
2002
|
-
while (current && !visited.has(current)) {
|
|
2003
|
-
visited.add(current);
|
|
2004
|
-
const rawStack = current?._debugStack?.stack;
|
|
2005
|
-
const stack = typeof rawStack === "string" ? formatOwnerDebugStack(rawStack) : "";
|
|
2006
|
-
if (stack) {
|
|
2007
|
-
const frames = parseDebugStack(stack);
|
|
2008
|
-
for (const frame of frames) {
|
|
2009
|
-
if (!frame.functionName || !frame.fileName) continue;
|
|
2010
|
-
if (!frame.fileName.startsWith("rsc://")) continue;
|
|
2011
|
-
const normalized = normalizeStackFileName(frame.fileName);
|
|
2012
|
-
if (!normalized) continue;
|
|
2013
|
-
const existing = functionNameToRscFrames.get(frame.functionName) ?? [];
|
|
2014
|
-
const duplicate = existing.some(
|
|
2015
|
-
(candidate) => candidate.fileName === normalized && candidate.lineNumber === frame.lineNumber && candidate.columnNumber === frame.columnNumber
|
|
2016
|
-
);
|
|
2017
|
-
if (!duplicate) {
|
|
2018
|
-
existing.push({
|
|
2019
|
-
fileName: normalized,
|
|
2020
|
-
lineNumber: frame.lineNumber,
|
|
2021
|
-
columnNumber: frame.columnNumber
|
|
2022
|
-
});
|
|
2023
|
-
functionNameToRscFrames.set(frame.functionName, existing);
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
current = current._debugOwner ?? current.return ?? null;
|
|
2028
|
-
}
|
|
2029
|
-
return functionNameToRscFrames;
|
|
2030
|
-
}
|
|
2031
|
-
function enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) {
|
|
2032
|
-
if (!frame.functionName) return frame;
|
|
2033
|
-
const available = functionNameToRscFrames.get(frame.functionName);
|
|
2034
|
-
if (!available) return frame;
|
|
2035
|
-
const usageIndex = functionNameToUsageIndex.get(frame.functionName) ?? 0;
|
|
2036
|
-
const resolved = available[usageIndex % available.length];
|
|
2037
|
-
functionNameToUsageIndex.set(frame.functionName, usageIndex + 1);
|
|
2038
|
-
return {
|
|
2039
|
-
...frame,
|
|
2040
|
-
fileName: resolved.fileName,
|
|
2041
|
-
lineNumber: resolved.lineNumber,
|
|
2042
|
-
columnNumber: resolved.columnNumber
|
|
2043
|
-
};
|
|
1901
|
+
const parent = current.parentElement;
|
|
1902
|
+
if (!parent) break;
|
|
1903
|
+
const display = getComputedStyle(parent).display;
|
|
1904
|
+
if (display === "flex" || display === "inline-flex") {
|
|
1905
|
+
return { flexParent: parent, child: current };
|
|
1906
|
+
}
|
|
1907
|
+
if (boundary && parent === boundary) break;
|
|
1908
|
+
current = parent;
|
|
1909
|
+
}
|
|
1910
|
+
return null;
|
|
2044
1911
|
}
|
|
2045
|
-
function
|
|
2046
|
-
|
|
2047
|
-
if (typeof rawStack !== "string" || rawStack.length === 0) {
|
|
1912
|
+
function computeHoverHighlight(elementUnder, selectedElement) {
|
|
1913
|
+
if (!elementUnder || elementUnder === document.body || elementUnder === document.documentElement || elementUnder.closest("[data-direct-edit]") || elementUnder.closest("[data-direct-edit-host]") || elementUnder === selectedElement) {
|
|
2048
1914
|
return null;
|
|
2049
1915
|
}
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
const functionNameToUsageIndex = /* @__PURE__ */ new Map();
|
|
2055
|
-
for (const frame of stackFrames) {
|
|
2056
|
-
const maybeEnriched = frame.isServer ? enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) : frame;
|
|
2057
|
-
if (!maybeEnriched.fileName) continue;
|
|
2058
|
-
const normalizedFileName = normalizeStackFileName(maybeEnriched.fileName);
|
|
2059
|
-
if (!normalizedFileName) continue;
|
|
2060
|
-
if (isSourceStackFile(normalizedFileName)) {
|
|
2061
|
-
return {
|
|
2062
|
-
fileName: normalizedFileName,
|
|
2063
|
-
lineNumber: maybeEnriched.lineNumber,
|
|
2064
|
-
columnNumber: maybeEnriched.columnNumber
|
|
2065
|
-
};
|
|
2066
|
-
}
|
|
1916
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1917
|
+
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
1918
|
+
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
1919
|
+
return { flexContainer: elementUnder, children: htmlChildren(elementUnder) };
|
|
2067
1920
|
}
|
|
2068
|
-
|
|
1921
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1922
|
+
if (found) {
|
|
1923
|
+
return { flexContainer: found.flexParent, children: htmlChildren(found.flexParent) };
|
|
1924
|
+
}
|
|
1925
|
+
return { flexContainer: elementUnder, children: [] };
|
|
2069
1926
|
}
|
|
2070
|
-
function
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
if (
|
|
1927
|
+
function resolveElementTarget(elementUnder, selectedElement) {
|
|
1928
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1929
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1930
|
+
if (found && found.flexParent === boundary) return elementUnder;
|
|
1931
|
+
return found?.child ?? elementUnder;
|
|
1932
|
+
}
|
|
1933
|
+
function findChildAtPoint(parent, clientX, clientY) {
|
|
1934
|
+
const children = htmlChildren(parent);
|
|
1935
|
+
if (children.length === 0) return null;
|
|
1936
|
+
const hit = children.find((child) => {
|
|
1937
|
+
const r = child.getBoundingClientRect();
|
|
1938
|
+
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
|
|
1939
|
+
});
|
|
1940
|
+
if (hit) return hit;
|
|
1941
|
+
if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
|
|
2084
1942
|
return null;
|
|
2085
1943
|
}
|
|
2086
|
-
function
|
|
2087
|
-
const
|
|
2088
|
-
if (
|
|
2089
|
-
const
|
|
2090
|
-
if (
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1944
|
+
function elementFromPointWithoutOverlays(x, y) {
|
|
1945
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1946
|
+
if (host) host.style.display = "none";
|
|
1947
|
+
const el = document.elementFromPoint(x, y);
|
|
1948
|
+
if (host) host.style.display = "";
|
|
1949
|
+
return el;
|
|
1950
|
+
}
|
|
1951
|
+
function isLayoutContainer(element) {
|
|
1952
|
+
const display = window.getComputedStyle(element).display;
|
|
1953
|
+
return display === "flex" || display === "inline-flex" || display === "grid" || display === "inline-grid";
|
|
1954
|
+
}
|
|
1955
|
+
function isBlockContainer(element) {
|
|
1956
|
+
const display = window.getComputedStyle(element).display;
|
|
1957
|
+
return display === "block" || display === "flow-root" || display === "inline-block" || display === "list-item";
|
|
1958
|
+
}
|
|
1959
|
+
function skipElement(el, exclude) {
|
|
1960
|
+
if (exclude && exclude.contains(el)) return true;
|
|
1961
|
+
if (el === document.body || el === document.documentElement) return true;
|
|
1962
|
+
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) return true;
|
|
1963
|
+
return false;
|
|
1964
|
+
}
|
|
1965
|
+
function findContainerViaTraversal(x, y, exclude) {
|
|
1966
|
+
const el = elementFromPointWithoutOverlays(x, y);
|
|
1967
|
+
if (!el) return null;
|
|
1968
|
+
let current = el;
|
|
1969
|
+
while (current) {
|
|
1970
|
+
if (!skipElement(current, exclude)) {
|
|
1971
|
+
if (isLayoutContainer(current) || isBlockContainer(current)) return current;
|
|
2100
1972
|
}
|
|
1973
|
+
current = current.parentElement;
|
|
2101
1974
|
}
|
|
2102
|
-
return
|
|
1975
|
+
return null;
|
|
2103
1976
|
}
|
|
2104
|
-
function
|
|
2105
|
-
|
|
2106
|
-
if (
|
|
2107
|
-
|
|
2108
|
-
if (
|
|
2109
|
-
|
|
2110
|
-
|
|
1977
|
+
function findContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1978
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1979
|
+
if (host) host.style.display = "none";
|
|
1980
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1981
|
+
if (host) host.style.display = "";
|
|
1982
|
+
for (const el of elements) {
|
|
1983
|
+
if (skipElement(el, exclude)) continue;
|
|
1984
|
+
if (isLayoutContainer(el) || isBlockContainer(el)) return el;
|
|
2111
1985
|
}
|
|
2112
|
-
|
|
1986
|
+
if (preferredParent && (isLayoutContainer(preferredParent) || isBlockContainer(preferredParent))) {
|
|
1987
|
+
for (const el of elements) {
|
|
1988
|
+
if (el === preferredParent) return preferredParent;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
return findContainerViaTraversal(x, y, exclude);
|
|
2113
1992
|
}
|
|
2114
|
-
function
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
if (
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
}
|
|
1993
|
+
function findLayoutContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1994
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1995
|
+
if (host) host.style.display = "none";
|
|
1996
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1997
|
+
if (host) host.style.display = "";
|
|
1998
|
+
for (const el of elements) {
|
|
1999
|
+
if (skipElement(el, exclude)) continue;
|
|
2000
|
+
if (isLayoutContainer(el)) return el;
|
|
2001
|
+
}
|
|
2002
|
+
if (preferredParent && isLayoutContainer(preferredParent)) {
|
|
2003
|
+
for (const el of elements) {
|
|
2004
|
+
if (el === preferredParent) return preferredParent;
|
|
2127
2005
|
}
|
|
2128
|
-
current = current._debugOwner;
|
|
2129
2006
|
}
|
|
2130
|
-
return
|
|
2007
|
+
return null;
|
|
2131
2008
|
}
|
|
2132
|
-
function
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2009
|
+
function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
|
|
2010
|
+
const { axis, reversed: isReversed } = detectChildrenDirection(container, draggedElement);
|
|
2011
|
+
const isHorizontal = axis === "horizontal";
|
|
2012
|
+
const children = Array.from(container.children).filter(
|
|
2013
|
+
(child) => child !== draggedElement && child instanceof HTMLElement
|
|
2014
|
+
);
|
|
2015
|
+
if (children.length === 0) {
|
|
2016
|
+
const containerRect2 = container.getBoundingClientRect();
|
|
2017
|
+
return {
|
|
2018
|
+
insertBefore: null,
|
|
2019
|
+
indicator: {
|
|
2020
|
+
x: containerRect2.left + 4,
|
|
2021
|
+
y: containerRect2.top + 4,
|
|
2022
|
+
width: isHorizontal ? 1 : containerRect2.width - 8,
|
|
2023
|
+
height: isHorizontal ? containerRect2.height - 8 : 1
|
|
2144
2024
|
}
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
const containerRect = container.getBoundingClientRect();
|
|
2028
|
+
let insertBefore = null;
|
|
2029
|
+
let indicatorPosition = 0;
|
|
2030
|
+
for (let i = 0; i < children.length; i++) {
|
|
2031
|
+
const child = children[i];
|
|
2032
|
+
const rect = child.getBoundingClientRect();
|
|
2033
|
+
const midpoint = isHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
|
|
2034
|
+
const pointer = isHorizontal ? pointerX : pointerY;
|
|
2035
|
+
const beforeMidpoint = isReversed ? pointer > midpoint : pointer < midpoint;
|
|
2036
|
+
if (beforeMidpoint) {
|
|
2037
|
+
insertBefore = child;
|
|
2038
|
+
indicatorPosition = isHorizontal ? rect.left : rect.top;
|
|
2039
|
+
break;
|
|
2145
2040
|
}
|
|
2146
|
-
current = current.return;
|
|
2147
2041
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
if (!fiber) return { frames: [], nearestComponentFiber: null };
|
|
2153
|
-
const elementSource = getSourceFromFiber2(fiber);
|
|
2154
|
-
const elementSourceFile = elementSource?.fileName || void 0;
|
|
2155
|
-
const ownerResult = getOwnerStack2(fiber);
|
|
2156
|
-
if (ownerResult.frames.length > 0) {
|
|
2157
|
-
return { ...ownerResult, elementSourceFile };
|
|
2042
|
+
if (!insertBefore) {
|
|
2043
|
+
const lastChild = children[children.length - 1];
|
|
2044
|
+
const lastRect = lastChild.getBoundingClientRect();
|
|
2045
|
+
indicatorPosition = isHorizontal ? lastRect.right : lastRect.bottom;
|
|
2158
2046
|
}
|
|
2159
|
-
|
|
2047
|
+
const indicator = isHorizontal ? {
|
|
2048
|
+
x: indicatorPosition,
|
|
2049
|
+
y: containerRect.top + 4,
|
|
2050
|
+
width: 2,
|
|
2051
|
+
height: containerRect.height - 8
|
|
2052
|
+
} : {
|
|
2053
|
+
x: containerRect.left + 4,
|
|
2054
|
+
y: indicatorPosition,
|
|
2055
|
+
width: containerRect.width - 8,
|
|
2056
|
+
height: 2
|
|
2057
|
+
};
|
|
2058
|
+
return { insertBefore, indicator };
|
|
2160
2059
|
}
|
|
2161
2060
|
function getElementDisplayName(element) {
|
|
2162
2061
|
const tag = element.tagName.toLowerCase();
|
|
@@ -2476,10 +2375,10 @@ function getElementSource(element) {
|
|
|
2476
2375
|
const domSource = parseDomSource(element);
|
|
2477
2376
|
if (domSource) return domSource;
|
|
2478
2377
|
const seenFibers = /* @__PURE__ */ new Set();
|
|
2479
|
-
let fiber =
|
|
2378
|
+
let fiber = getFiberForElement(element);
|
|
2480
2379
|
while (fiber && !seenFibers.has(fiber)) {
|
|
2481
2380
|
seenFibers.add(fiber);
|
|
2482
|
-
const fiberSource =
|
|
2381
|
+
const fiberSource = getSourceFromFiber(fiber);
|
|
2483
2382
|
if (fiberSource?.fileName) {
|
|
2484
2383
|
return {
|
|
2485
2384
|
file: fiberSource.fileName,
|
|
@@ -2494,7 +2393,7 @@ function getElementSource(element) {
|
|
|
2494
2393
|
function getElementLocator(element) {
|
|
2495
2394
|
const elementInfo = getElementInfo(element);
|
|
2496
2395
|
const domSource = getElementSource(element);
|
|
2497
|
-
const { frames, nearestComponentFiber, elementSourceFile } =
|
|
2396
|
+
const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo(element);
|
|
2498
2397
|
const componentName = nearestComponentFiber?.type?.displayName || nearestComponentFiber?.type?.name || void 0;
|
|
2499
2398
|
const authoredProps = nearestComponentFiber ? getComponentProps(nearestComponentFiber) : void 0;
|
|
2500
2399
|
const classification = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile);
|
|
@@ -4555,6 +4454,49 @@ function useSessionManager({
|
|
|
4555
4454
|
pushUndo: false
|
|
4556
4455
|
});
|
|
4557
4456
|
}, [applySelection, buildSelectionSnapshot, getSanitizedSelection, pushUndo, saveCurrentToSession, stateRef]);
|
|
4457
|
+
const deleteSelection = React3.useCallback(() => {
|
|
4458
|
+
const selected = getSanitizedSelection(stateRef.current.selectedElements);
|
|
4459
|
+
if (selected.length === 0 || !stateRef.current.editModeActive) return;
|
|
4460
|
+
if (selected.some((el) => el === document.body || !el.parentElement)) return;
|
|
4461
|
+
saveCurrentToSession();
|
|
4462
|
+
const restoreSelection = buildSelectionSnapshot();
|
|
4463
|
+
const snapshots = selected.map((el) => ({
|
|
4464
|
+
element: el,
|
|
4465
|
+
parent: el.parentElement,
|
|
4466
|
+
nextSibling: el.nextSibling
|
|
4467
|
+
}));
|
|
4468
|
+
const sessionSnapshots = /* @__PURE__ */ new Map();
|
|
4469
|
+
for (const el of selected) {
|
|
4470
|
+
const edit = sessionEditsRef.current.get(el);
|
|
4471
|
+
if (edit) sessionSnapshots.set(el, edit);
|
|
4472
|
+
sessionEditsRef.current.delete(el);
|
|
4473
|
+
}
|
|
4474
|
+
syncSessionItemCount();
|
|
4475
|
+
for (const { element } of snapshots) {
|
|
4476
|
+
if (element.isConnected) element.remove();
|
|
4477
|
+
}
|
|
4478
|
+
pushUndo({
|
|
4479
|
+
type: "structure",
|
|
4480
|
+
restoreSelection,
|
|
4481
|
+
undo: () => {
|
|
4482
|
+
for (let i = snapshots.length - 1; i >= 0; i--) {
|
|
4483
|
+
const { element, parent, nextSibling } = snapshots[i];
|
|
4484
|
+
if (!element.isConnected && parent.isConnected) {
|
|
4485
|
+
if (nextSibling && nextSibling.parentNode === parent) {
|
|
4486
|
+
parent.insertBefore(element, nextSibling);
|
|
4487
|
+
} else {
|
|
4488
|
+
parent.appendChild(element);
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
for (const [el, edit] of sessionSnapshots) {
|
|
4493
|
+
sessionEditsRef.current.set(el, edit);
|
|
4494
|
+
}
|
|
4495
|
+
syncSessionItemCount();
|
|
4496
|
+
}
|
|
4497
|
+
});
|
|
4498
|
+
applySelection([], { primaryElement: null, pushUndo: false });
|
|
4499
|
+
}, [applySelection, buildSelectionSnapshot, getSanitizedSelection, pushUndo, saveCurrentToSession, stateRef, syncSessionItemCount]);
|
|
4558
4500
|
const resetToOriginal = React3.useCallback(() => {
|
|
4559
4501
|
const current = stateRef.current;
|
|
4560
4502
|
const el = current.selectedElement;
|
|
@@ -5091,6 +5033,7 @@ ${exportMarkdown}`);
|
|
|
5091
5033
|
selectChild,
|
|
5092
5034
|
insertElement,
|
|
5093
5035
|
groupSelection,
|
|
5036
|
+
deleteSelection,
|
|
5094
5037
|
resetToOriginal,
|
|
5095
5038
|
undo,
|
|
5096
5039
|
handleMoveComplete,
|
|
@@ -5984,6 +5927,7 @@ function useKeyboardShortcuts({
|
|
|
5984
5927
|
closePanel,
|
|
5985
5928
|
clearSelection,
|
|
5986
5929
|
groupSelection,
|
|
5930
|
+
deleteSelection,
|
|
5987
5931
|
insertElement,
|
|
5988
5932
|
setState,
|
|
5989
5933
|
toggleCanvas,
|
|
@@ -6071,6 +6015,13 @@ function useKeyboardShortcuts({
|
|
|
6071
6015
|
return;
|
|
6072
6016
|
}
|
|
6073
6017
|
}
|
|
6018
|
+
if ((e.key === "Backspace" || e.key === "Delete") && s.editModeActive && !s.textEditingElement) {
|
|
6019
|
+
if (!isInputFocused() && s.selectedElements.length > 0) {
|
|
6020
|
+
e.preventDefault();
|
|
6021
|
+
deleteSelection();
|
|
6022
|
+
return;
|
|
6023
|
+
}
|
|
6024
|
+
}
|
|
6074
6025
|
if (e.key === "Enter" && s.editModeActive && !s.textEditingElement && s.selectedElement) {
|
|
6075
6026
|
if (!isInputFocused() && isTextElement2(s.selectedElement)) {
|
|
6076
6027
|
e.preventDefault();
|
|
@@ -6103,7 +6054,7 @@ function useKeyboardShortcuts({
|
|
|
6103
6054
|
}
|
|
6104
6055
|
window.addEventListener("keydown", handleKeyDown);
|
|
6105
6056
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
6106
|
-
}, [clearSelection, closePanel, commitTextEditing, fitCanvasToViewport, groupSelection, insertElement, setCanvasZoom, setState, startTextEditing, toggleCanvas, toggleEditMode, toggleFlexLayout, undo, usesMetaForUndo, zoomCanvasTo100]);
|
|
6057
|
+
}, [clearSelection, closePanel, commitTextEditing, deleteSelection, fitCanvasToViewport, groupSelection, insertElement, setCanvasZoom, setState, startTextEditing, toggleCanvas, toggleEditMode, toggleFlexLayout, undo, usesMetaForUndo, zoomCanvasTo100]);
|
|
6107
6058
|
}
|
|
6108
6059
|
|
|
6109
6060
|
// src/use-canvas.ts
|
|
@@ -6753,6 +6704,7 @@ function DirectEditProvider({ children }) {
|
|
|
6753
6704
|
removeSessionEdit,
|
|
6754
6705
|
clearSessionEdits,
|
|
6755
6706
|
groupSelection,
|
|
6707
|
+
deleteSelection,
|
|
6756
6708
|
insertElement
|
|
6757
6709
|
} = useSessionManager({
|
|
6758
6710
|
stateRef,
|
|
@@ -6981,6 +6933,7 @@ function DirectEditProvider({ children }) {
|
|
|
6981
6933
|
setState,
|
|
6982
6934
|
clearSelection,
|
|
6983
6935
|
groupSelection,
|
|
6936
|
+
deleteSelection,
|
|
6984
6937
|
insertElement,
|
|
6985
6938
|
toggleCanvas: toggleCanvasWithPreference,
|
|
6986
6939
|
setCanvasZoom,
|
|
@@ -7048,6 +7001,7 @@ function DirectEditProvider({ children }) {
|
|
|
7048
7001
|
startTextEditing,
|
|
7049
7002
|
commitTextEditing,
|
|
7050
7003
|
groupSelection,
|
|
7004
|
+
deleteSelection,
|
|
7051
7005
|
insertElement,
|
|
7052
7006
|
toggleCanvas: toggleCanvasWithPreference,
|
|
7053
7007
|
setCanvasZoom,
|
|
@@ -7100,6 +7054,7 @@ function DirectEditProvider({ children }) {
|
|
|
7100
7054
|
startTextEditing,
|
|
7101
7055
|
commitTextEditing,
|
|
7102
7056
|
groupSelection,
|
|
7057
|
+
deleteSelection,
|
|
7103
7058
|
insertElement,
|
|
7104
7059
|
toggleCanvasWithPreference,
|
|
7105
7060
|
setCanvasZoom,
|
|
@@ -7723,6 +7678,8 @@ function useMove({ onMoveComplete }) {
|
|
|
7723
7678
|
React12.useEffect(() => {
|
|
7724
7679
|
if (!dragState.isDragging) return;
|
|
7725
7680
|
function handlePointerMove(e) {
|
|
7681
|
+
e.stopPropagation();
|
|
7682
|
+
e.preventDefault();
|
|
7726
7683
|
const current = dragStateRef.current;
|
|
7727
7684
|
const { draggedElement, dragOffset, originalParent } = current;
|
|
7728
7685
|
setDragState((prev) => ({
|
|
@@ -7810,12 +7767,17 @@ function useMove({ onMoveComplete }) {
|
|
|
7810
7767
|
clearReorderPreview();
|
|
7811
7768
|
}
|
|
7812
7769
|
}
|
|
7813
|
-
function handlePointerUp() {
|
|
7770
|
+
function handlePointerUp(e) {
|
|
7771
|
+
e.stopPropagation();
|
|
7814
7772
|
completeDrag();
|
|
7815
7773
|
}
|
|
7816
|
-
function handlePointerCancel() {
|
|
7774
|
+
function handlePointerCancel(e) {
|
|
7775
|
+
e.stopPropagation();
|
|
7817
7776
|
cancelDrag();
|
|
7818
7777
|
}
|
|
7778
|
+
function blockMouseEvent(e) {
|
|
7779
|
+
e.stopPropagation();
|
|
7780
|
+
}
|
|
7819
7781
|
function handleKeyDown(e) {
|
|
7820
7782
|
if (e.key === "Escape") {
|
|
7821
7783
|
cancelDrag();
|
|
@@ -7824,15 +7786,19 @@ function useMove({ onMoveComplete }) {
|
|
|
7824
7786
|
function handleBlur() {
|
|
7825
7787
|
cancelDrag();
|
|
7826
7788
|
}
|
|
7827
|
-
window.addEventListener("pointermove", handlePointerMove);
|
|
7828
|
-
window.addEventListener("pointerup", handlePointerUp);
|
|
7829
|
-
window.addEventListener("pointercancel", handlePointerCancel);
|
|
7789
|
+
window.addEventListener("pointermove", handlePointerMove, true);
|
|
7790
|
+
window.addEventListener("pointerup", handlePointerUp, true);
|
|
7791
|
+
window.addEventListener("pointercancel", handlePointerCancel, true);
|
|
7792
|
+
window.addEventListener("mousemove", blockMouseEvent, true);
|
|
7793
|
+
window.addEventListener("mouseup", blockMouseEvent, true);
|
|
7830
7794
|
window.addEventListener("keydown", handleKeyDown);
|
|
7831
7795
|
window.addEventListener("blur", handleBlur);
|
|
7832
7796
|
return () => {
|
|
7833
|
-
window.removeEventListener("pointermove", handlePointerMove);
|
|
7834
|
-
window.removeEventListener("pointerup", handlePointerUp);
|
|
7835
|
-
window.removeEventListener("pointercancel", handlePointerCancel);
|
|
7797
|
+
window.removeEventListener("pointermove", handlePointerMove, true);
|
|
7798
|
+
window.removeEventListener("pointerup", handlePointerUp, true);
|
|
7799
|
+
window.removeEventListener("pointercancel", handlePointerCancel, true);
|
|
7800
|
+
window.removeEventListener("mousemove", blockMouseEvent, true);
|
|
7801
|
+
window.removeEventListener("mouseup", blockMouseEvent, true);
|
|
7836
7802
|
window.removeEventListener("keydown", handleKeyDown);
|
|
7837
7803
|
window.removeEventListener("blur", handleBlur);
|
|
7838
7804
|
};
|
|
@@ -8614,7 +8580,7 @@ function SelectedCommentComposer({
|
|
|
8614
8580
|
React17.useLayoutEffect(() => {
|
|
8615
8581
|
updatePosition();
|
|
8616
8582
|
}, [text, updatePosition]);
|
|
8617
|
-
React17.
|
|
8583
|
+
const handleComposerClick = React17.useCallback(() => {
|
|
8618
8584
|
inputRef.current?.focus();
|
|
8619
8585
|
}, []);
|
|
8620
8586
|
React17.useEffect(() => {
|
|
@@ -8665,7 +8631,10 @@ function SelectedCommentComposer({
|
|
|
8665
8631
|
width: position.width,
|
|
8666
8632
|
pointerEvents: "auto"
|
|
8667
8633
|
},
|
|
8668
|
-
onClick: (e) =>
|
|
8634
|
+
onClick: (e) => {
|
|
8635
|
+
e.stopPropagation();
|
|
8636
|
+
handleComposerClick();
|
|
8637
|
+
},
|
|
8669
8638
|
children: [
|
|
8670
8639
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
8671
8640
|
"textarea",
|
|
@@ -12912,7 +12881,8 @@ function DirectEditPanelContent() {
|
|
|
12912
12881
|
sendCommentToAgent: sendCommentToAgent2,
|
|
12913
12882
|
setActiveCommentId,
|
|
12914
12883
|
startTextEditing,
|
|
12915
|
-
toggleEditMode
|
|
12884
|
+
toggleEditMode,
|
|
12885
|
+
deleteSelection
|
|
12916
12886
|
} = useDirectEditActions();
|
|
12917
12887
|
const {
|
|
12918
12888
|
position,
|