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.mjs
CHANGED
|
@@ -117,6 +117,255 @@ function getZoomScale() {
|
|
|
117
117
|
return snap.active ? snap.zoom : 1;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
// src/utils/debug-stack.ts
|
|
121
|
+
var STACK_SOURCE_FILE_EXTENSION_REGEX = /\.(jsx|tsx|ts|js)$/;
|
|
122
|
+
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;
|
|
123
|
+
var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
|
|
124
|
+
var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
|
|
125
|
+
var SERVER_FRAME_MARKER = "(at Server)";
|
|
126
|
+
var STACK_INTERNAL_SCHEME_PREFIXES = [
|
|
127
|
+
"rsc://",
|
|
128
|
+
"about://React/",
|
|
129
|
+
"React/Server/",
|
|
130
|
+
"file:///",
|
|
131
|
+
"webpack://",
|
|
132
|
+
"webpack-internal://",
|
|
133
|
+
"node:",
|
|
134
|
+
"turbopack://",
|
|
135
|
+
"/app-pages-browser/"
|
|
136
|
+
];
|
|
137
|
+
function formatOwnerDebugStack(stack) {
|
|
138
|
+
if (!stack) return "";
|
|
139
|
+
const lines = stack.split("\n");
|
|
140
|
+
const filtered = [];
|
|
141
|
+
for (const line of lines) {
|
|
142
|
+
const trimmed = line.trim();
|
|
143
|
+
if (!trimmed) continue;
|
|
144
|
+
if (trimmed === "Error: react-stack-top-frame") continue;
|
|
145
|
+
if (trimmed.includes("react_stack_bottom_frame") || trimmed.includes("react-stack-bottom-frame")) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
filtered.push(line);
|
|
149
|
+
}
|
|
150
|
+
if (filtered.length > 0 && filtered[0].includes("fakeJSXCallSite")) {
|
|
151
|
+
filtered.shift();
|
|
152
|
+
}
|
|
153
|
+
return filtered.join("\n");
|
|
154
|
+
}
|
|
155
|
+
function extractStackLocation(urlLike) {
|
|
156
|
+
if (!urlLike.includes(":")) return [urlLike, void 0, void 0];
|
|
157
|
+
const isWrappedLocation = urlLike.startsWith("(") && /:\d+\)$/.test(urlLike);
|
|
158
|
+
const sanitizedResult = isWrappedLocation ? urlLike.slice(1, -1) : urlLike;
|
|
159
|
+
const parts = /(.+?)(?::(\d+))?(?::(\d+))?$/.exec(sanitizedResult);
|
|
160
|
+
if (!parts) return [sanitizedResult, void 0, void 0];
|
|
161
|
+
return [
|
|
162
|
+
parts[1],
|
|
163
|
+
parts[2] !== void 0 ? Number(parts[2]) : void 0,
|
|
164
|
+
parts[3] !== void 0 ? Number(parts[3]) : void 0
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
function parseV8StackLine(line) {
|
|
168
|
+
let currentLine = line;
|
|
169
|
+
if (currentLine.includes("(eval ")) {
|
|
170
|
+
currentLine = currentLine.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
171
|
+
}
|
|
172
|
+
let sanitizedLine = currentLine.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
173
|
+
const locationMatch = sanitizedLine.match(/ (\(.+\)$)/);
|
|
174
|
+
if (locationMatch) {
|
|
175
|
+
sanitizedLine = sanitizedLine.replace(locationMatch[0], "");
|
|
176
|
+
}
|
|
177
|
+
const [fileName, lineNumber, columnNumber] = extractStackLocation(
|
|
178
|
+
locationMatch ? locationMatch[1] : sanitizedLine
|
|
179
|
+
);
|
|
180
|
+
const functionName = locationMatch && sanitizedLine ? sanitizedLine : void 0;
|
|
181
|
+
if (fileName === "eval" || fileName === "<anonymous>") {
|
|
182
|
+
return {
|
|
183
|
+
functionName
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
functionName,
|
|
188
|
+
fileName,
|
|
189
|
+
lineNumber,
|
|
190
|
+
columnNumber,
|
|
191
|
+
source: currentLine,
|
|
192
|
+
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function parseFFOrSafariStackLine(line) {
|
|
196
|
+
let currentLine = line;
|
|
197
|
+
if (currentLine.includes(" > eval")) {
|
|
198
|
+
currentLine = currentLine.replace(
|
|
199
|
+
/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
|
|
200
|
+
":$1"
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
const trimmed = currentLine.trim();
|
|
204
|
+
if (!trimmed || SAFARI_NATIVE_CODE_REGEXP.test(trimmed)) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
if (!trimmed.includes("@") && !trimmed.includes(":")) {
|
|
208
|
+
return {
|
|
209
|
+
functionName: trimmed,
|
|
210
|
+
source: currentLine,
|
|
211
|
+
isServer: trimmed.includes(SERVER_FRAME_MARKER)
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
const atIndex = trimmed.lastIndexOf("@");
|
|
215
|
+
if (atIndex === -1) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
const maybeFunctionName = trimmed.slice(0, atIndex);
|
|
219
|
+
const location = trimmed.slice(atIndex + 1);
|
|
220
|
+
const [fileName, lineNumber, columnNumber] = extractStackLocation(location);
|
|
221
|
+
return {
|
|
222
|
+
functionName: maybeFunctionName || void 0,
|
|
223
|
+
fileName,
|
|
224
|
+
lineNumber,
|
|
225
|
+
columnNumber,
|
|
226
|
+
source: currentLine,
|
|
227
|
+
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function parseInStackLine(line) {
|
|
231
|
+
const functionName = line.replace(/^\s*in\s+/, "").replace(/\s*\(at .*\)$/, "").trim();
|
|
232
|
+
if (!functionName) return null;
|
|
233
|
+
return {
|
|
234
|
+
functionName,
|
|
235
|
+
source: line,
|
|
236
|
+
isServer: line.includes(SERVER_FRAME_MARKER)
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function parseDebugStack(stack) {
|
|
240
|
+
const frames = [];
|
|
241
|
+
for (const rawLine of stack.split("\n")) {
|
|
242
|
+
if (FIREFOX_SAFARI_STACK_REGEXP.test(rawLine)) {
|
|
243
|
+
const parsed = parseFFOrSafariStackLine(rawLine);
|
|
244
|
+
if (parsed) frames.push(parsed);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (/^\s*at\s+/.test(rawLine)) {
|
|
248
|
+
const parsed = parseV8StackLine(rawLine);
|
|
249
|
+
if (parsed) frames.push(parsed);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (/^\s*in\s+/.test(rawLine)) {
|
|
253
|
+
const parsed = parseInStackLine(rawLine);
|
|
254
|
+
if (parsed) frames.push(parsed);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return frames;
|
|
258
|
+
}
|
|
259
|
+
function normalizeStackFileName(fileName) {
|
|
260
|
+
if (!fileName) return "";
|
|
261
|
+
let normalized = fileName;
|
|
262
|
+
const isHttpUrl = normalized.startsWith("http://") || normalized.startsWith("https://");
|
|
263
|
+
if (isHttpUrl) {
|
|
264
|
+
try {
|
|
265
|
+
normalized = new URL(normalized).pathname;
|
|
266
|
+
} catch {
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
let didStripPrefix = true;
|
|
270
|
+
while (didStripPrefix) {
|
|
271
|
+
didStripPrefix = false;
|
|
272
|
+
for (const prefix of STACK_INTERNAL_SCHEME_PREFIXES) {
|
|
273
|
+
if (normalized.startsWith(prefix)) {
|
|
274
|
+
normalized = normalized.slice(prefix.length);
|
|
275
|
+
if (prefix === "file:///") {
|
|
276
|
+
normalized = `/${normalized.replace(/^\/+/, "")}`;
|
|
277
|
+
}
|
|
278
|
+
didStripPrefix = true;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
normalized = normalized.replace(/^\/\(app-pages-browser\)\//, "/").replace(/^\/\.\//, "/").replace(/^\.\//, "");
|
|
284
|
+
const queryIndex = normalized.indexOf("?");
|
|
285
|
+
if (queryIndex !== -1) {
|
|
286
|
+
normalized = normalized.slice(0, queryIndex);
|
|
287
|
+
}
|
|
288
|
+
return normalized;
|
|
289
|
+
}
|
|
290
|
+
function isSourceStackFile(fileName) {
|
|
291
|
+
const normalizedFileName = normalizeStackFileName(fileName);
|
|
292
|
+
if (!normalizedFileName) return false;
|
|
293
|
+
if (!STACK_SOURCE_FILE_EXTENSION_REGEX.test(normalizedFileName)) return false;
|
|
294
|
+
return !STACK_BUNDLED_FILE_PATTERN_REGEX.test(normalizedFileName);
|
|
295
|
+
}
|
|
296
|
+
function buildFunctionNameToRscFramesMap(fiber) {
|
|
297
|
+
const functionNameToRscFrames = /* @__PURE__ */ new Map();
|
|
298
|
+
const visited = /* @__PURE__ */ new Set();
|
|
299
|
+
let current = fiber;
|
|
300
|
+
while (current && !visited.has(current)) {
|
|
301
|
+
visited.add(current);
|
|
302
|
+
const rawStack = current?._debugStack?.stack;
|
|
303
|
+
const stack = typeof rawStack === "string" ? formatOwnerDebugStack(rawStack) : "";
|
|
304
|
+
if (stack) {
|
|
305
|
+
const frames = parseDebugStack(stack);
|
|
306
|
+
for (const frame of frames) {
|
|
307
|
+
if (!frame.functionName || !frame.fileName) continue;
|
|
308
|
+
if (!frame.fileName.startsWith("rsc://")) continue;
|
|
309
|
+
const normalized = normalizeStackFileName(frame.fileName);
|
|
310
|
+
if (!normalized) continue;
|
|
311
|
+
const existing = functionNameToRscFrames.get(frame.functionName) ?? [];
|
|
312
|
+
const duplicate = existing.some(
|
|
313
|
+
(candidate) => candidate.fileName === normalized && candidate.lineNumber === frame.lineNumber && candidate.columnNumber === frame.columnNumber
|
|
314
|
+
);
|
|
315
|
+
if (!duplicate) {
|
|
316
|
+
existing.push({
|
|
317
|
+
fileName: normalized,
|
|
318
|
+
lineNumber: frame.lineNumber,
|
|
319
|
+
columnNumber: frame.columnNumber
|
|
320
|
+
});
|
|
321
|
+
functionNameToRscFrames.set(frame.functionName, existing);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
current = current._debugOwner ?? current.return ?? null;
|
|
326
|
+
}
|
|
327
|
+
return functionNameToRscFrames;
|
|
328
|
+
}
|
|
329
|
+
function enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) {
|
|
330
|
+
if (!frame.functionName) return frame;
|
|
331
|
+
const available = functionNameToRscFrames.get(frame.functionName);
|
|
332
|
+
if (!available) return frame;
|
|
333
|
+
const usageIndex = functionNameToUsageIndex.get(frame.functionName) ?? 0;
|
|
334
|
+
const resolved = available[usageIndex % available.length];
|
|
335
|
+
functionNameToUsageIndex.set(frame.functionName, usageIndex + 1);
|
|
336
|
+
return {
|
|
337
|
+
...frame,
|
|
338
|
+
fileName: resolved.fileName,
|
|
339
|
+
lineNumber: resolved.lineNumber,
|
|
340
|
+
columnNumber: resolved.columnNumber
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function getSourceFromDebugStack(fiber) {
|
|
344
|
+
const rawStack = fiber?._debugStack?.stack;
|
|
345
|
+
if (typeof rawStack !== "string" || rawStack.length === 0) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
const formattedStack = formatOwnerDebugStack(rawStack);
|
|
349
|
+
if (!formattedStack) return null;
|
|
350
|
+
const stackFrames = parseDebugStack(formattedStack);
|
|
351
|
+
const functionNameToRscFrames = buildFunctionNameToRscFramesMap(fiber);
|
|
352
|
+
const functionNameToUsageIndex = /* @__PURE__ */ new Map();
|
|
353
|
+
for (const frame of stackFrames) {
|
|
354
|
+
const maybeEnriched = frame.isServer ? enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) : frame;
|
|
355
|
+
if (!maybeEnriched.fileName) continue;
|
|
356
|
+
const normalizedFileName = normalizeStackFileName(maybeEnriched.fileName);
|
|
357
|
+
if (!normalizedFileName) continue;
|
|
358
|
+
if (isSourceStackFile(normalizedFileName)) {
|
|
359
|
+
return {
|
|
360
|
+
fileName: normalizedFileName,
|
|
361
|
+
lineNumber: maybeEnriched.lineNumber,
|
|
362
|
+
columnNumber: maybeEnriched.columnNumber
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
|
|
120
369
|
// src/utils/react-fiber.ts
|
|
121
370
|
function getFiberForElement(element) {
|
|
122
371
|
if (typeof window !== "undefined") {
|
|
@@ -144,6 +393,8 @@ function getSourceFromFiber(fiber) {
|
|
|
144
393
|
if (pending?.fileName) return pending;
|
|
145
394
|
const memo = fiber?.memoizedProps?.__source;
|
|
146
395
|
if (memo?.fileName) return memo;
|
|
396
|
+
const fromDebugStack = getSourceFromDebugStack(fiber);
|
|
397
|
+
if (fromDebugStack?.fileName) return fromDebugStack;
|
|
147
398
|
return null;
|
|
148
399
|
}
|
|
149
400
|
function buildFrame(fiber) {
|
|
@@ -1567,516 +1818,164 @@ function htmlChildren(el) {
|
|
|
1567
1818
|
function findFlexAncestor(element, boundary) {
|
|
1568
1819
|
let current = element;
|
|
1569
1820
|
while (current && current !== document.body) {
|
|
1570
|
-
const parent = current.parentElement;
|
|
1571
|
-
if (!parent) break;
|
|
1572
|
-
const display = getComputedStyle(parent).display;
|
|
1573
|
-
if (display === "flex" || display === "inline-flex") {
|
|
1574
|
-
return { flexParent: parent, child: current };
|
|
1575
|
-
}
|
|
1576
|
-
if (boundary && parent === boundary) break;
|
|
1577
|
-
current = parent;
|
|
1578
|
-
}
|
|
1579
|
-
return null;
|
|
1580
|
-
}
|
|
1581
|
-
function computeHoverHighlight(elementUnder, selectedElement) {
|
|
1582
|
-
if (!elementUnder || elementUnder === document.body || elementUnder === document.documentElement || elementUnder.closest("[data-direct-edit]") || elementUnder.closest("[data-direct-edit-host]") || elementUnder === selectedElement) {
|
|
1583
|
-
return null;
|
|
1584
|
-
}
|
|
1585
|
-
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1586
|
-
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
1587
|
-
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
1588
|
-
return { flexContainer: elementUnder, children: htmlChildren(elementUnder) };
|
|
1589
|
-
}
|
|
1590
|
-
const found = findFlexAncestor(elementUnder, boundary);
|
|
1591
|
-
if (found) {
|
|
1592
|
-
return { flexContainer: found.flexParent, children: htmlChildren(found.flexParent) };
|
|
1593
|
-
}
|
|
1594
|
-
return { flexContainer: elementUnder, children: [] };
|
|
1595
|
-
}
|
|
1596
|
-
function resolveElementTarget(elementUnder, selectedElement) {
|
|
1597
|
-
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1598
|
-
const found = findFlexAncestor(elementUnder, boundary);
|
|
1599
|
-
if (found && found.flexParent === boundary) return elementUnder;
|
|
1600
|
-
return found?.child ?? elementUnder;
|
|
1601
|
-
}
|
|
1602
|
-
function findChildAtPoint(parent, clientX, clientY) {
|
|
1603
|
-
const children = htmlChildren(parent);
|
|
1604
|
-
if (children.length === 0) return null;
|
|
1605
|
-
const hit = children.find((child) => {
|
|
1606
|
-
const r = child.getBoundingClientRect();
|
|
1607
|
-
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
|
|
1608
|
-
});
|
|
1609
|
-
if (hit) return hit;
|
|
1610
|
-
if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
|
|
1611
|
-
return null;
|
|
1612
|
-
}
|
|
1613
|
-
function elementFromPointWithoutOverlays(x, y) {
|
|
1614
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1615
|
-
if (host) host.style.display = "none";
|
|
1616
|
-
const el = document.elementFromPoint(x, y);
|
|
1617
|
-
if (host) host.style.display = "";
|
|
1618
|
-
return el;
|
|
1619
|
-
}
|
|
1620
|
-
function isLayoutContainer(element) {
|
|
1621
|
-
const display = window.getComputedStyle(element).display;
|
|
1622
|
-
return display === "flex" || display === "inline-flex" || display === "grid" || display === "inline-grid";
|
|
1623
|
-
}
|
|
1624
|
-
function isBlockContainer(element) {
|
|
1625
|
-
const display = window.getComputedStyle(element).display;
|
|
1626
|
-
return display === "block" || display === "flow-root" || display === "inline-block" || display === "list-item";
|
|
1627
|
-
}
|
|
1628
|
-
function skipElement(el, exclude) {
|
|
1629
|
-
if (exclude && exclude.contains(el)) return true;
|
|
1630
|
-
if (el === document.body || el === document.documentElement) return true;
|
|
1631
|
-
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) return true;
|
|
1632
|
-
return false;
|
|
1633
|
-
}
|
|
1634
|
-
function findContainerViaTraversal(x, y, exclude) {
|
|
1635
|
-
const el = elementFromPointWithoutOverlays(x, y);
|
|
1636
|
-
if (!el) return null;
|
|
1637
|
-
let current = el;
|
|
1638
|
-
while (current) {
|
|
1639
|
-
if (!skipElement(current, exclude)) {
|
|
1640
|
-
if (isLayoutContainer(current) || isBlockContainer(current)) return current;
|
|
1641
|
-
}
|
|
1642
|
-
current = current.parentElement;
|
|
1643
|
-
}
|
|
1644
|
-
return null;
|
|
1645
|
-
}
|
|
1646
|
-
function findContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1647
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1648
|
-
if (host) host.style.display = "none";
|
|
1649
|
-
const elements = document.elementsFromPoint(x, y);
|
|
1650
|
-
if (host) host.style.display = "";
|
|
1651
|
-
for (const el of elements) {
|
|
1652
|
-
if (skipElement(el, exclude)) continue;
|
|
1653
|
-
if (isLayoutContainer(el) || isBlockContainer(el)) return el;
|
|
1654
|
-
}
|
|
1655
|
-
if (preferredParent && (isLayoutContainer(preferredParent) || isBlockContainer(preferredParent))) {
|
|
1656
|
-
for (const el of elements) {
|
|
1657
|
-
if (el === preferredParent) return preferredParent;
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
return findContainerViaTraversal(x, y, exclude);
|
|
1661
|
-
}
|
|
1662
|
-
function findLayoutContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1663
|
-
const host = document.querySelector("[data-direct-edit-host]");
|
|
1664
|
-
if (host) host.style.display = "none";
|
|
1665
|
-
const elements = document.elementsFromPoint(x, y);
|
|
1666
|
-
if (host) host.style.display = "";
|
|
1667
|
-
for (const el of elements) {
|
|
1668
|
-
if (skipElement(el, exclude)) continue;
|
|
1669
|
-
if (isLayoutContainer(el)) return el;
|
|
1670
|
-
}
|
|
1671
|
-
if (preferredParent && isLayoutContainer(preferredParent)) {
|
|
1672
|
-
for (const el of elements) {
|
|
1673
|
-
if (el === preferredParent) return preferredParent;
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
return null;
|
|
1677
|
-
}
|
|
1678
|
-
function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
|
|
1679
|
-
const { axis, reversed: isReversed } = detectChildrenDirection(container, draggedElement);
|
|
1680
|
-
const isHorizontal = axis === "horizontal";
|
|
1681
|
-
const children = Array.from(container.children).filter(
|
|
1682
|
-
(child) => child !== draggedElement && child instanceof HTMLElement
|
|
1683
|
-
);
|
|
1684
|
-
if (children.length === 0) {
|
|
1685
|
-
const containerRect2 = container.getBoundingClientRect();
|
|
1686
|
-
return {
|
|
1687
|
-
insertBefore: null,
|
|
1688
|
-
indicator: {
|
|
1689
|
-
x: containerRect2.left + 4,
|
|
1690
|
-
y: containerRect2.top + 4,
|
|
1691
|
-
width: isHorizontal ? 1 : containerRect2.width - 8,
|
|
1692
|
-
height: isHorizontal ? containerRect2.height - 8 : 1
|
|
1693
|
-
}
|
|
1694
|
-
};
|
|
1695
|
-
}
|
|
1696
|
-
const containerRect = container.getBoundingClientRect();
|
|
1697
|
-
let insertBefore = null;
|
|
1698
|
-
let indicatorPosition = 0;
|
|
1699
|
-
for (let i = 0; i < children.length; i++) {
|
|
1700
|
-
const child = children[i];
|
|
1701
|
-
const rect = child.getBoundingClientRect();
|
|
1702
|
-
const midpoint = isHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
|
|
1703
|
-
const pointer = isHorizontal ? pointerX : pointerY;
|
|
1704
|
-
const beforeMidpoint = isReversed ? pointer > midpoint : pointer < midpoint;
|
|
1705
|
-
if (beforeMidpoint) {
|
|
1706
|
-
insertBefore = child;
|
|
1707
|
-
indicatorPosition = isHorizontal ? rect.left : rect.top;
|
|
1708
|
-
break;
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
if (!insertBefore) {
|
|
1712
|
-
const lastChild = children[children.length - 1];
|
|
1713
|
-
const lastRect = lastChild.getBoundingClientRect();
|
|
1714
|
-
indicatorPosition = isHorizontal ? lastRect.right : lastRect.bottom;
|
|
1715
|
-
}
|
|
1716
|
-
const indicator = isHorizontal ? {
|
|
1717
|
-
x: indicatorPosition,
|
|
1718
|
-
y: containerRect.top + 4,
|
|
1719
|
-
width: 2,
|
|
1720
|
-
height: containerRect.height - 8
|
|
1721
|
-
} : {
|
|
1722
|
-
x: containerRect.left + 4,
|
|
1723
|
-
y: indicatorPosition,
|
|
1724
|
-
width: containerRect.width - 8,
|
|
1725
|
-
height: 2
|
|
1726
|
-
};
|
|
1727
|
-
return { insertBefore, indicator };
|
|
1728
|
-
}
|
|
1729
|
-
function getFiberForElement2(element) {
|
|
1730
|
-
if (typeof window !== "undefined") {
|
|
1731
|
-
const devtools = window.__DIRECT_EDIT_DEVTOOLS__;
|
|
1732
|
-
if (devtools?.getFiberForElement) {
|
|
1733
|
-
const fiber = devtools.getFiberForElement(element);
|
|
1734
|
-
if (fiber) return fiber;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
const fiberKey = Object.keys(element).find(
|
|
1738
|
-
(key) => key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$")
|
|
1739
|
-
);
|
|
1740
|
-
if (!fiberKey) return null;
|
|
1741
|
-
return element[fiberKey] || null;
|
|
1742
|
-
}
|
|
1743
|
-
var STACK_SOURCE_FILE_EXTENSION_REGEX = /\.(jsx|tsx|ts|js)$/;
|
|
1744
|
-
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;
|
|
1745
|
-
var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
|
|
1746
|
-
var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
|
|
1747
|
-
var SERVER_FRAME_MARKER = "(at Server)";
|
|
1748
|
-
var STACK_INTERNAL_SCHEME_PREFIXES = [
|
|
1749
|
-
"rsc://",
|
|
1750
|
-
"about://React/",
|
|
1751
|
-
"React/Server/",
|
|
1752
|
-
"file:///",
|
|
1753
|
-
"webpack://",
|
|
1754
|
-
"webpack-internal://",
|
|
1755
|
-
"node:",
|
|
1756
|
-
"turbopack://",
|
|
1757
|
-
"/app-pages-browser/"
|
|
1758
|
-
];
|
|
1759
|
-
function formatOwnerDebugStack(stack) {
|
|
1760
|
-
if (!stack) return "";
|
|
1761
|
-
const lines = stack.split("\n");
|
|
1762
|
-
const filtered = [];
|
|
1763
|
-
for (const line of lines) {
|
|
1764
|
-
const trimmed = line.trim();
|
|
1765
|
-
if (!trimmed) continue;
|
|
1766
|
-
if (trimmed === "Error: react-stack-top-frame") continue;
|
|
1767
|
-
if (trimmed.includes("react_stack_bottom_frame") || trimmed.includes("react-stack-bottom-frame")) {
|
|
1768
|
-
continue;
|
|
1769
|
-
}
|
|
1770
|
-
filtered.push(line);
|
|
1771
|
-
}
|
|
1772
|
-
if (filtered.length > 0 && filtered[0].includes("fakeJSXCallSite")) {
|
|
1773
|
-
filtered.shift();
|
|
1774
|
-
}
|
|
1775
|
-
return filtered.join("\n");
|
|
1776
|
-
}
|
|
1777
|
-
function extractStackLocation(urlLike) {
|
|
1778
|
-
if (!urlLike.includes(":")) return [urlLike, void 0, void 0];
|
|
1779
|
-
const isWrappedLocation = urlLike.startsWith("(") && /:\d+\)$/.test(urlLike);
|
|
1780
|
-
const sanitizedResult = isWrappedLocation ? urlLike.slice(1, -1) : urlLike;
|
|
1781
|
-
const parts = /(.+?)(?::(\d+))?(?::(\d+))?$/.exec(sanitizedResult);
|
|
1782
|
-
if (!parts) return [sanitizedResult, void 0, void 0];
|
|
1783
|
-
return [
|
|
1784
|
-
parts[1],
|
|
1785
|
-
parts[2] !== void 0 ? Number(parts[2]) : void 0,
|
|
1786
|
-
parts[3] !== void 0 ? Number(parts[3]) : void 0
|
|
1787
|
-
];
|
|
1788
|
-
}
|
|
1789
|
-
function parseV8StackLine(line) {
|
|
1790
|
-
let currentLine = line;
|
|
1791
|
-
if (currentLine.includes("(eval ")) {
|
|
1792
|
-
currentLine = currentLine.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
|
|
1793
|
-
}
|
|
1794
|
-
let sanitizedLine = currentLine.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
|
|
1795
|
-
const locationMatch = sanitizedLine.match(/ (\(.+\)$)/);
|
|
1796
|
-
if (locationMatch) {
|
|
1797
|
-
sanitizedLine = sanitizedLine.replace(locationMatch[0], "");
|
|
1798
|
-
}
|
|
1799
|
-
const [fileName, lineNumber, columnNumber] = extractStackLocation(
|
|
1800
|
-
locationMatch ? locationMatch[1] : sanitizedLine
|
|
1801
|
-
);
|
|
1802
|
-
const functionName = locationMatch && sanitizedLine ? sanitizedLine : void 0;
|
|
1803
|
-
if (fileName === "eval" || fileName === "<anonymous>") {
|
|
1804
|
-
return {
|
|
1805
|
-
functionName
|
|
1806
|
-
};
|
|
1807
|
-
}
|
|
1808
|
-
return {
|
|
1809
|
-
functionName,
|
|
1810
|
-
fileName,
|
|
1811
|
-
lineNumber,
|
|
1812
|
-
columnNumber,
|
|
1813
|
-
source: currentLine,
|
|
1814
|
-
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
1815
|
-
};
|
|
1816
|
-
}
|
|
1817
|
-
function parseFFOrSafariStackLine(line) {
|
|
1818
|
-
let currentLine = line;
|
|
1819
|
-
if (currentLine.includes(" > eval")) {
|
|
1820
|
-
currentLine = currentLine.replace(
|
|
1821
|
-
/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,
|
|
1822
|
-
":$1"
|
|
1823
|
-
);
|
|
1824
|
-
}
|
|
1825
|
-
const trimmed = currentLine.trim();
|
|
1826
|
-
if (!trimmed || SAFARI_NATIVE_CODE_REGEXP.test(trimmed)) {
|
|
1827
|
-
return null;
|
|
1828
|
-
}
|
|
1829
|
-
if (!trimmed.includes("@") && !trimmed.includes(":")) {
|
|
1830
|
-
return {
|
|
1831
|
-
functionName: trimmed,
|
|
1832
|
-
source: currentLine,
|
|
1833
|
-
isServer: trimmed.includes(SERVER_FRAME_MARKER)
|
|
1834
|
-
};
|
|
1835
|
-
}
|
|
1836
|
-
const atIndex = trimmed.lastIndexOf("@");
|
|
1837
|
-
if (atIndex === -1) {
|
|
1838
|
-
return null;
|
|
1839
|
-
}
|
|
1840
|
-
const maybeFunctionName = trimmed.slice(0, atIndex);
|
|
1841
|
-
const location = trimmed.slice(atIndex + 1);
|
|
1842
|
-
const [fileName, lineNumber, columnNumber] = extractStackLocation(location);
|
|
1843
|
-
return {
|
|
1844
|
-
functionName: maybeFunctionName || void 0,
|
|
1845
|
-
fileName,
|
|
1846
|
-
lineNumber,
|
|
1847
|
-
columnNumber,
|
|
1848
|
-
source: currentLine,
|
|
1849
|
-
isServer: currentLine.includes(SERVER_FRAME_MARKER) || fileName.startsWith("rsc://")
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
|
-
function parseInStackLine(line) {
|
|
1853
|
-
const functionName = line.replace(/^\s*in\s+/, "").replace(/\s*\(at .*\)$/, "").trim();
|
|
1854
|
-
if (!functionName) return null;
|
|
1855
|
-
return {
|
|
1856
|
-
functionName,
|
|
1857
|
-
source: line,
|
|
1858
|
-
isServer: line.includes(SERVER_FRAME_MARKER)
|
|
1859
|
-
};
|
|
1860
|
-
}
|
|
1861
|
-
function parseDebugStack(stack) {
|
|
1862
|
-
const frames = [];
|
|
1863
|
-
for (const rawLine of stack.split("\n")) {
|
|
1864
|
-
if (FIREFOX_SAFARI_STACK_REGEXP.test(rawLine)) {
|
|
1865
|
-
const parsed = parseFFOrSafariStackLine(rawLine);
|
|
1866
|
-
if (parsed) frames.push(parsed);
|
|
1867
|
-
continue;
|
|
1868
|
-
}
|
|
1869
|
-
if (/^\s*at\s+/.test(rawLine)) {
|
|
1870
|
-
const parsed = parseV8StackLine(rawLine);
|
|
1871
|
-
if (parsed) frames.push(parsed);
|
|
1872
|
-
continue;
|
|
1873
|
-
}
|
|
1874
|
-
if (/^\s*in\s+/.test(rawLine)) {
|
|
1875
|
-
const parsed = parseInStackLine(rawLine);
|
|
1876
|
-
if (parsed) frames.push(parsed);
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
return frames;
|
|
1880
|
-
}
|
|
1881
|
-
function normalizeStackFileName(fileName) {
|
|
1882
|
-
if (!fileName) return "";
|
|
1883
|
-
let normalized = fileName;
|
|
1884
|
-
const isHttpUrl = normalized.startsWith("http://") || normalized.startsWith("https://");
|
|
1885
|
-
if (isHttpUrl) {
|
|
1886
|
-
try {
|
|
1887
|
-
normalized = new URL(normalized).pathname;
|
|
1888
|
-
} catch {
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
let didStripPrefix = true;
|
|
1892
|
-
while (didStripPrefix) {
|
|
1893
|
-
didStripPrefix = false;
|
|
1894
|
-
for (const prefix of STACK_INTERNAL_SCHEME_PREFIXES) {
|
|
1895
|
-
if (normalized.startsWith(prefix)) {
|
|
1896
|
-
normalized = normalized.slice(prefix.length);
|
|
1897
|
-
if (prefix === "file:///") {
|
|
1898
|
-
normalized = `/${normalized.replace(/^\/+/, "")}`;
|
|
1899
|
-
}
|
|
1900
|
-
didStripPrefix = true;
|
|
1901
|
-
break;
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
normalized = normalized.replace(/^\/\(app-pages-browser\)\//, "/").replace(/^\/\.\//, "/").replace(/^\.\//, "");
|
|
1906
|
-
const queryIndex = normalized.indexOf("?");
|
|
1907
|
-
if (queryIndex !== -1) {
|
|
1908
|
-
normalized = normalized.slice(0, queryIndex);
|
|
1909
|
-
}
|
|
1910
|
-
return normalized;
|
|
1911
|
-
}
|
|
1912
|
-
function isSourceStackFile(fileName) {
|
|
1913
|
-
const normalizedFileName = normalizeStackFileName(fileName);
|
|
1914
|
-
if (!normalizedFileName) return false;
|
|
1915
|
-
if (!STACK_SOURCE_FILE_EXTENSION_REGEX.test(normalizedFileName)) return false;
|
|
1916
|
-
return !STACK_BUNDLED_FILE_PATTERN_REGEX.test(normalizedFileName);
|
|
1917
|
-
}
|
|
1918
|
-
function buildFunctionNameToRscFramesMap(fiber) {
|
|
1919
|
-
const functionNameToRscFrames = /* @__PURE__ */ new Map();
|
|
1920
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1921
|
-
let current = fiber;
|
|
1922
|
-
while (current && !visited.has(current)) {
|
|
1923
|
-
visited.add(current);
|
|
1924
|
-
const rawStack = current?._debugStack?.stack;
|
|
1925
|
-
const stack = typeof rawStack === "string" ? formatOwnerDebugStack(rawStack) : "";
|
|
1926
|
-
if (stack) {
|
|
1927
|
-
const frames = parseDebugStack(stack);
|
|
1928
|
-
for (const frame of frames) {
|
|
1929
|
-
if (!frame.functionName || !frame.fileName) continue;
|
|
1930
|
-
if (!frame.fileName.startsWith("rsc://")) continue;
|
|
1931
|
-
const normalized = normalizeStackFileName(frame.fileName);
|
|
1932
|
-
if (!normalized) continue;
|
|
1933
|
-
const existing = functionNameToRscFrames.get(frame.functionName) ?? [];
|
|
1934
|
-
const duplicate = existing.some(
|
|
1935
|
-
(candidate) => candidate.fileName === normalized && candidate.lineNumber === frame.lineNumber && candidate.columnNumber === frame.columnNumber
|
|
1936
|
-
);
|
|
1937
|
-
if (!duplicate) {
|
|
1938
|
-
existing.push({
|
|
1939
|
-
fileName: normalized,
|
|
1940
|
-
lineNumber: frame.lineNumber,
|
|
1941
|
-
columnNumber: frame.columnNumber
|
|
1942
|
-
});
|
|
1943
|
-
functionNameToRscFrames.set(frame.functionName, existing);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
current = current._debugOwner ?? current.return ?? null;
|
|
1948
|
-
}
|
|
1949
|
-
return functionNameToRscFrames;
|
|
1950
|
-
}
|
|
1951
|
-
function enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) {
|
|
1952
|
-
if (!frame.functionName) return frame;
|
|
1953
|
-
const available = functionNameToRscFrames.get(frame.functionName);
|
|
1954
|
-
if (!available) return frame;
|
|
1955
|
-
const usageIndex = functionNameToUsageIndex.get(frame.functionName) ?? 0;
|
|
1956
|
-
const resolved = available[usageIndex % available.length];
|
|
1957
|
-
functionNameToUsageIndex.set(frame.functionName, usageIndex + 1);
|
|
1958
|
-
return {
|
|
1959
|
-
...frame,
|
|
1960
|
-
fileName: resolved.fileName,
|
|
1961
|
-
lineNumber: resolved.lineNumber,
|
|
1962
|
-
columnNumber: resolved.columnNumber
|
|
1963
|
-
};
|
|
1821
|
+
const parent = current.parentElement;
|
|
1822
|
+
if (!parent) break;
|
|
1823
|
+
const display = getComputedStyle(parent).display;
|
|
1824
|
+
if (display === "flex" || display === "inline-flex") {
|
|
1825
|
+
return { flexParent: parent, child: current };
|
|
1826
|
+
}
|
|
1827
|
+
if (boundary && parent === boundary) break;
|
|
1828
|
+
current = parent;
|
|
1829
|
+
}
|
|
1830
|
+
return null;
|
|
1964
1831
|
}
|
|
1965
|
-
function
|
|
1966
|
-
|
|
1967
|
-
if (typeof rawStack !== "string" || rawStack.length === 0) {
|
|
1832
|
+
function computeHoverHighlight(elementUnder, selectedElement) {
|
|
1833
|
+
if (!elementUnder || elementUnder === document.body || elementUnder === document.documentElement || elementUnder.closest("[data-direct-edit]") || elementUnder.closest("[data-direct-edit-host]") || elementUnder === selectedElement) {
|
|
1968
1834
|
return null;
|
|
1969
1835
|
}
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
const functionNameToUsageIndex = /* @__PURE__ */ new Map();
|
|
1975
|
-
for (const frame of stackFrames) {
|
|
1976
|
-
const maybeEnriched = frame.isServer ? enrichServerFrame(frame, functionNameToRscFrames, functionNameToUsageIndex) : frame;
|
|
1977
|
-
if (!maybeEnriched.fileName) continue;
|
|
1978
|
-
const normalizedFileName = normalizeStackFileName(maybeEnriched.fileName);
|
|
1979
|
-
if (!normalizedFileName) continue;
|
|
1980
|
-
if (isSourceStackFile(normalizedFileName)) {
|
|
1981
|
-
return {
|
|
1982
|
-
fileName: normalizedFileName,
|
|
1983
|
-
lineNumber: maybeEnriched.lineNumber,
|
|
1984
|
-
columnNumber: maybeEnriched.columnNumber
|
|
1985
|
-
};
|
|
1986
|
-
}
|
|
1836
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1837
|
+
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
1838
|
+
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
1839
|
+
return { flexContainer: elementUnder, children: htmlChildren(elementUnder) };
|
|
1987
1840
|
}
|
|
1988
|
-
|
|
1841
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1842
|
+
if (found) {
|
|
1843
|
+
return { flexContainer: found.flexParent, children: htmlChildren(found.flexParent) };
|
|
1844
|
+
}
|
|
1845
|
+
return { flexContainer: elementUnder, children: [] };
|
|
1989
1846
|
}
|
|
1990
|
-
function
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
if (
|
|
1847
|
+
function resolveElementTarget(elementUnder, selectedElement) {
|
|
1848
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1849
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1850
|
+
if (found && found.flexParent === boundary) return elementUnder;
|
|
1851
|
+
return found?.child ?? elementUnder;
|
|
1852
|
+
}
|
|
1853
|
+
function findChildAtPoint(parent, clientX, clientY) {
|
|
1854
|
+
const children = htmlChildren(parent);
|
|
1855
|
+
if (children.length === 0) return null;
|
|
1856
|
+
const hit = children.find((child) => {
|
|
1857
|
+
const r = child.getBoundingClientRect();
|
|
1858
|
+
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
|
|
1859
|
+
});
|
|
1860
|
+
if (hit) return hit;
|
|
1861
|
+
if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
|
|
2004
1862
|
return null;
|
|
2005
1863
|
}
|
|
2006
|
-
function
|
|
2007
|
-
const
|
|
2008
|
-
if (
|
|
2009
|
-
const
|
|
2010
|
-
if (
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
1864
|
+
function elementFromPointWithoutOverlays(x, y) {
|
|
1865
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1866
|
+
if (host) host.style.display = "none";
|
|
1867
|
+
const el = document.elementFromPoint(x, y);
|
|
1868
|
+
if (host) host.style.display = "";
|
|
1869
|
+
return el;
|
|
1870
|
+
}
|
|
1871
|
+
function isLayoutContainer(element) {
|
|
1872
|
+
const display = window.getComputedStyle(element).display;
|
|
1873
|
+
return display === "flex" || display === "inline-flex" || display === "grid" || display === "inline-grid";
|
|
1874
|
+
}
|
|
1875
|
+
function isBlockContainer(element) {
|
|
1876
|
+
const display = window.getComputedStyle(element).display;
|
|
1877
|
+
return display === "block" || display === "flow-root" || display === "inline-block" || display === "list-item";
|
|
1878
|
+
}
|
|
1879
|
+
function skipElement(el, exclude) {
|
|
1880
|
+
if (exclude && exclude.contains(el)) return true;
|
|
1881
|
+
if (el === document.body || el === document.documentElement) return true;
|
|
1882
|
+
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) return true;
|
|
1883
|
+
return false;
|
|
1884
|
+
}
|
|
1885
|
+
function findContainerViaTraversal(x, y, exclude) {
|
|
1886
|
+
const el = elementFromPointWithoutOverlays(x, y);
|
|
1887
|
+
if (!el) return null;
|
|
1888
|
+
let current = el;
|
|
1889
|
+
while (current) {
|
|
1890
|
+
if (!skipElement(current, exclude)) {
|
|
1891
|
+
if (isLayoutContainer(current) || isBlockContainer(current)) return current;
|
|
2020
1892
|
}
|
|
1893
|
+
current = current.parentElement;
|
|
2021
1894
|
}
|
|
2022
|
-
return
|
|
1895
|
+
return null;
|
|
2023
1896
|
}
|
|
2024
|
-
function
|
|
2025
|
-
|
|
2026
|
-
if (
|
|
2027
|
-
|
|
2028
|
-
if (
|
|
2029
|
-
|
|
2030
|
-
|
|
1897
|
+
function findContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1898
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1899
|
+
if (host) host.style.display = "none";
|
|
1900
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1901
|
+
if (host) host.style.display = "";
|
|
1902
|
+
for (const el of elements) {
|
|
1903
|
+
if (skipElement(el, exclude)) continue;
|
|
1904
|
+
if (isLayoutContainer(el) || isBlockContainer(el)) return el;
|
|
2031
1905
|
}
|
|
2032
|
-
|
|
1906
|
+
if (preferredParent && (isLayoutContainer(preferredParent) || isBlockContainer(preferredParent))) {
|
|
1907
|
+
for (const el of elements) {
|
|
1908
|
+
if (el === preferredParent) return preferredParent;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
return findContainerViaTraversal(x, y, exclude);
|
|
2033
1912
|
}
|
|
2034
|
-
function
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
if (
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
}
|
|
1913
|
+
function findLayoutContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1914
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1915
|
+
if (host) host.style.display = "none";
|
|
1916
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1917
|
+
if (host) host.style.display = "";
|
|
1918
|
+
for (const el of elements) {
|
|
1919
|
+
if (skipElement(el, exclude)) continue;
|
|
1920
|
+
if (isLayoutContainer(el)) return el;
|
|
1921
|
+
}
|
|
1922
|
+
if (preferredParent && isLayoutContainer(preferredParent)) {
|
|
1923
|
+
for (const el of elements) {
|
|
1924
|
+
if (el === preferredParent) return preferredParent;
|
|
2047
1925
|
}
|
|
2048
|
-
current = current._debugOwner;
|
|
2049
1926
|
}
|
|
2050
|
-
return
|
|
1927
|
+
return null;
|
|
2051
1928
|
}
|
|
2052
|
-
function
|
|
2053
|
-
const
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
1929
|
+
function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
|
|
1930
|
+
const { axis, reversed: isReversed } = detectChildrenDirection(container, draggedElement);
|
|
1931
|
+
const isHorizontal = axis === "horizontal";
|
|
1932
|
+
const children = Array.from(container.children).filter(
|
|
1933
|
+
(child) => child !== draggedElement && child instanceof HTMLElement
|
|
1934
|
+
);
|
|
1935
|
+
if (children.length === 0) {
|
|
1936
|
+
const containerRect2 = container.getBoundingClientRect();
|
|
1937
|
+
return {
|
|
1938
|
+
insertBefore: null,
|
|
1939
|
+
indicator: {
|
|
1940
|
+
x: containerRect2.left + 4,
|
|
1941
|
+
y: containerRect2.top + 4,
|
|
1942
|
+
width: isHorizontal ? 1 : containerRect2.width - 8,
|
|
1943
|
+
height: isHorizontal ? containerRect2.height - 8 : 1
|
|
2064
1944
|
}
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
const containerRect = container.getBoundingClientRect();
|
|
1948
|
+
let insertBefore = null;
|
|
1949
|
+
let indicatorPosition = 0;
|
|
1950
|
+
for (let i = 0; i < children.length; i++) {
|
|
1951
|
+
const child = children[i];
|
|
1952
|
+
const rect = child.getBoundingClientRect();
|
|
1953
|
+
const midpoint = isHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
|
|
1954
|
+
const pointer = isHorizontal ? pointerX : pointerY;
|
|
1955
|
+
const beforeMidpoint = isReversed ? pointer > midpoint : pointer < midpoint;
|
|
1956
|
+
if (beforeMidpoint) {
|
|
1957
|
+
insertBefore = child;
|
|
1958
|
+
indicatorPosition = isHorizontal ? rect.left : rect.top;
|
|
1959
|
+
break;
|
|
2065
1960
|
}
|
|
2066
|
-
current = current.return;
|
|
2067
1961
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
if (!fiber) return { frames: [], nearestComponentFiber: null };
|
|
2073
|
-
const elementSource = getSourceFromFiber2(fiber);
|
|
2074
|
-
const elementSourceFile = elementSource?.fileName || void 0;
|
|
2075
|
-
const ownerResult = getOwnerStack2(fiber);
|
|
2076
|
-
if (ownerResult.frames.length > 0) {
|
|
2077
|
-
return { ...ownerResult, elementSourceFile };
|
|
1962
|
+
if (!insertBefore) {
|
|
1963
|
+
const lastChild = children[children.length - 1];
|
|
1964
|
+
const lastRect = lastChild.getBoundingClientRect();
|
|
1965
|
+
indicatorPosition = isHorizontal ? lastRect.right : lastRect.bottom;
|
|
2078
1966
|
}
|
|
2079
|
-
|
|
1967
|
+
const indicator = isHorizontal ? {
|
|
1968
|
+
x: indicatorPosition,
|
|
1969
|
+
y: containerRect.top + 4,
|
|
1970
|
+
width: 2,
|
|
1971
|
+
height: containerRect.height - 8
|
|
1972
|
+
} : {
|
|
1973
|
+
x: containerRect.left + 4,
|
|
1974
|
+
y: indicatorPosition,
|
|
1975
|
+
width: containerRect.width - 8,
|
|
1976
|
+
height: 2
|
|
1977
|
+
};
|
|
1978
|
+
return { insertBefore, indicator };
|
|
2080
1979
|
}
|
|
2081
1980
|
function getElementDisplayName(element) {
|
|
2082
1981
|
const tag = element.tagName.toLowerCase();
|
|
@@ -2396,10 +2295,10 @@ function getElementSource(element) {
|
|
|
2396
2295
|
const domSource = parseDomSource(element);
|
|
2397
2296
|
if (domSource) return domSource;
|
|
2398
2297
|
const seenFibers = /* @__PURE__ */ new Set();
|
|
2399
|
-
let fiber =
|
|
2298
|
+
let fiber = getFiberForElement(element);
|
|
2400
2299
|
while (fiber && !seenFibers.has(fiber)) {
|
|
2401
2300
|
seenFibers.add(fiber);
|
|
2402
|
-
const fiberSource =
|
|
2301
|
+
const fiberSource = getSourceFromFiber(fiber);
|
|
2403
2302
|
if (fiberSource?.fileName) {
|
|
2404
2303
|
return {
|
|
2405
2304
|
file: fiberSource.fileName,
|
|
@@ -2414,7 +2313,7 @@ function getElementSource(element) {
|
|
|
2414
2313
|
function getElementLocator(element) {
|
|
2415
2314
|
const elementInfo = getElementInfo(element);
|
|
2416
2315
|
const domSource = getElementSource(element);
|
|
2417
|
-
const { frames, nearestComponentFiber, elementSourceFile } =
|
|
2316
|
+
const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo(element);
|
|
2418
2317
|
const componentName = nearestComponentFiber?.type?.displayName || nearestComponentFiber?.type?.name || void 0;
|
|
2419
2318
|
const authoredProps = nearestComponentFiber ? getComponentProps(nearestComponentFiber) : void 0;
|
|
2420
2319
|
const classification = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile);
|
|
@@ -4475,6 +4374,49 @@ function useSessionManager({
|
|
|
4475
4374
|
pushUndo: false
|
|
4476
4375
|
});
|
|
4477
4376
|
}, [applySelection, buildSelectionSnapshot, getSanitizedSelection, pushUndo, saveCurrentToSession, stateRef]);
|
|
4377
|
+
const deleteSelection = React3.useCallback(() => {
|
|
4378
|
+
const selected = getSanitizedSelection(stateRef.current.selectedElements);
|
|
4379
|
+
if (selected.length === 0 || !stateRef.current.editModeActive) return;
|
|
4380
|
+
if (selected.some((el) => el === document.body || !el.parentElement)) return;
|
|
4381
|
+
saveCurrentToSession();
|
|
4382
|
+
const restoreSelection = buildSelectionSnapshot();
|
|
4383
|
+
const snapshots = selected.map((el) => ({
|
|
4384
|
+
element: el,
|
|
4385
|
+
parent: el.parentElement,
|
|
4386
|
+
nextSibling: el.nextSibling
|
|
4387
|
+
}));
|
|
4388
|
+
const sessionSnapshots = /* @__PURE__ */ new Map();
|
|
4389
|
+
for (const el of selected) {
|
|
4390
|
+
const edit = sessionEditsRef.current.get(el);
|
|
4391
|
+
if (edit) sessionSnapshots.set(el, edit);
|
|
4392
|
+
sessionEditsRef.current.delete(el);
|
|
4393
|
+
}
|
|
4394
|
+
syncSessionItemCount();
|
|
4395
|
+
for (const { element } of snapshots) {
|
|
4396
|
+
if (element.isConnected) element.remove();
|
|
4397
|
+
}
|
|
4398
|
+
pushUndo({
|
|
4399
|
+
type: "structure",
|
|
4400
|
+
restoreSelection,
|
|
4401
|
+
undo: () => {
|
|
4402
|
+
for (let i = snapshots.length - 1; i >= 0; i--) {
|
|
4403
|
+
const { element, parent, nextSibling } = snapshots[i];
|
|
4404
|
+
if (!element.isConnected && parent.isConnected) {
|
|
4405
|
+
if (nextSibling && nextSibling.parentNode === parent) {
|
|
4406
|
+
parent.insertBefore(element, nextSibling);
|
|
4407
|
+
} else {
|
|
4408
|
+
parent.appendChild(element);
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
for (const [el, edit] of sessionSnapshots) {
|
|
4413
|
+
sessionEditsRef.current.set(el, edit);
|
|
4414
|
+
}
|
|
4415
|
+
syncSessionItemCount();
|
|
4416
|
+
}
|
|
4417
|
+
});
|
|
4418
|
+
applySelection([], { primaryElement: null, pushUndo: false });
|
|
4419
|
+
}, [applySelection, buildSelectionSnapshot, getSanitizedSelection, pushUndo, saveCurrentToSession, stateRef, syncSessionItemCount]);
|
|
4478
4420
|
const resetToOriginal = React3.useCallback(() => {
|
|
4479
4421
|
const current = stateRef.current;
|
|
4480
4422
|
const el = current.selectedElement;
|
|
@@ -5011,6 +4953,7 @@ ${exportMarkdown}`);
|
|
|
5011
4953
|
selectChild,
|
|
5012
4954
|
insertElement,
|
|
5013
4955
|
groupSelection,
|
|
4956
|
+
deleteSelection,
|
|
5014
4957
|
resetToOriginal,
|
|
5015
4958
|
undo,
|
|
5016
4959
|
handleMoveComplete,
|
|
@@ -5904,6 +5847,7 @@ function useKeyboardShortcuts({
|
|
|
5904
5847
|
closePanel,
|
|
5905
5848
|
clearSelection,
|
|
5906
5849
|
groupSelection,
|
|
5850
|
+
deleteSelection,
|
|
5907
5851
|
insertElement,
|
|
5908
5852
|
setState,
|
|
5909
5853
|
toggleCanvas,
|
|
@@ -5991,6 +5935,13 @@ function useKeyboardShortcuts({
|
|
|
5991
5935
|
return;
|
|
5992
5936
|
}
|
|
5993
5937
|
}
|
|
5938
|
+
if ((e.key === "Backspace" || e.key === "Delete") && s.editModeActive && !s.textEditingElement) {
|
|
5939
|
+
if (!isInputFocused() && s.selectedElements.length > 0) {
|
|
5940
|
+
e.preventDefault();
|
|
5941
|
+
deleteSelection();
|
|
5942
|
+
return;
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5994
5945
|
if (e.key === "Enter" && s.editModeActive && !s.textEditingElement && s.selectedElement) {
|
|
5995
5946
|
if (!isInputFocused() && isTextElement2(s.selectedElement)) {
|
|
5996
5947
|
e.preventDefault();
|
|
@@ -6023,7 +5974,7 @@ function useKeyboardShortcuts({
|
|
|
6023
5974
|
}
|
|
6024
5975
|
window.addEventListener("keydown", handleKeyDown);
|
|
6025
5976
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
6026
|
-
}, [clearSelection, closePanel, commitTextEditing, fitCanvasToViewport, groupSelection, insertElement, setCanvasZoom, setState, startTextEditing, toggleCanvas, toggleEditMode, toggleFlexLayout, undo, usesMetaForUndo, zoomCanvasTo100]);
|
|
5977
|
+
}, [clearSelection, closePanel, commitTextEditing, deleteSelection, fitCanvasToViewport, groupSelection, insertElement, setCanvasZoom, setState, startTextEditing, toggleCanvas, toggleEditMode, toggleFlexLayout, undo, usesMetaForUndo, zoomCanvasTo100]);
|
|
6027
5978
|
}
|
|
6028
5979
|
|
|
6029
5980
|
// src/use-canvas.ts
|
|
@@ -6673,6 +6624,7 @@ function DirectEditProvider({ children }) {
|
|
|
6673
6624
|
removeSessionEdit,
|
|
6674
6625
|
clearSessionEdits,
|
|
6675
6626
|
groupSelection,
|
|
6627
|
+
deleteSelection,
|
|
6676
6628
|
insertElement
|
|
6677
6629
|
} = useSessionManager({
|
|
6678
6630
|
stateRef,
|
|
@@ -6901,6 +6853,7 @@ function DirectEditProvider({ children }) {
|
|
|
6901
6853
|
setState,
|
|
6902
6854
|
clearSelection,
|
|
6903
6855
|
groupSelection,
|
|
6856
|
+
deleteSelection,
|
|
6904
6857
|
insertElement,
|
|
6905
6858
|
toggleCanvas: toggleCanvasWithPreference,
|
|
6906
6859
|
setCanvasZoom,
|
|
@@ -6968,6 +6921,7 @@ function DirectEditProvider({ children }) {
|
|
|
6968
6921
|
startTextEditing,
|
|
6969
6922
|
commitTextEditing,
|
|
6970
6923
|
groupSelection,
|
|
6924
|
+
deleteSelection,
|
|
6971
6925
|
insertElement,
|
|
6972
6926
|
toggleCanvas: toggleCanvasWithPreference,
|
|
6973
6927
|
setCanvasZoom,
|
|
@@ -7020,6 +6974,7 @@ function DirectEditProvider({ children }) {
|
|
|
7020
6974
|
startTextEditing,
|
|
7021
6975
|
commitTextEditing,
|
|
7022
6976
|
groupSelection,
|
|
6977
|
+
deleteSelection,
|
|
7023
6978
|
insertElement,
|
|
7024
6979
|
toggleCanvasWithPreference,
|
|
7025
6980
|
setCanvasZoom,
|
|
@@ -7643,6 +7598,8 @@ function useMove({ onMoveComplete }) {
|
|
|
7643
7598
|
React12.useEffect(() => {
|
|
7644
7599
|
if (!dragState.isDragging) return;
|
|
7645
7600
|
function handlePointerMove(e) {
|
|
7601
|
+
e.stopPropagation();
|
|
7602
|
+
e.preventDefault();
|
|
7646
7603
|
const current = dragStateRef.current;
|
|
7647
7604
|
const { draggedElement, dragOffset, originalParent } = current;
|
|
7648
7605
|
setDragState((prev) => ({
|
|
@@ -7730,12 +7687,17 @@ function useMove({ onMoveComplete }) {
|
|
|
7730
7687
|
clearReorderPreview();
|
|
7731
7688
|
}
|
|
7732
7689
|
}
|
|
7733
|
-
function handlePointerUp() {
|
|
7690
|
+
function handlePointerUp(e) {
|
|
7691
|
+
e.stopPropagation();
|
|
7734
7692
|
completeDrag();
|
|
7735
7693
|
}
|
|
7736
|
-
function handlePointerCancel() {
|
|
7694
|
+
function handlePointerCancel(e) {
|
|
7695
|
+
e.stopPropagation();
|
|
7737
7696
|
cancelDrag();
|
|
7738
7697
|
}
|
|
7698
|
+
function blockMouseEvent(e) {
|
|
7699
|
+
e.stopPropagation();
|
|
7700
|
+
}
|
|
7739
7701
|
function handleKeyDown(e) {
|
|
7740
7702
|
if (e.key === "Escape") {
|
|
7741
7703
|
cancelDrag();
|
|
@@ -7744,15 +7706,19 @@ function useMove({ onMoveComplete }) {
|
|
|
7744
7706
|
function handleBlur() {
|
|
7745
7707
|
cancelDrag();
|
|
7746
7708
|
}
|
|
7747
|
-
window.addEventListener("pointermove", handlePointerMove);
|
|
7748
|
-
window.addEventListener("pointerup", handlePointerUp);
|
|
7749
|
-
window.addEventListener("pointercancel", handlePointerCancel);
|
|
7709
|
+
window.addEventListener("pointermove", handlePointerMove, true);
|
|
7710
|
+
window.addEventListener("pointerup", handlePointerUp, true);
|
|
7711
|
+
window.addEventListener("pointercancel", handlePointerCancel, true);
|
|
7712
|
+
window.addEventListener("mousemove", blockMouseEvent, true);
|
|
7713
|
+
window.addEventListener("mouseup", blockMouseEvent, true);
|
|
7750
7714
|
window.addEventListener("keydown", handleKeyDown);
|
|
7751
7715
|
window.addEventListener("blur", handleBlur);
|
|
7752
7716
|
return () => {
|
|
7753
|
-
window.removeEventListener("pointermove", handlePointerMove);
|
|
7754
|
-
window.removeEventListener("pointerup", handlePointerUp);
|
|
7755
|
-
window.removeEventListener("pointercancel", handlePointerCancel);
|
|
7717
|
+
window.removeEventListener("pointermove", handlePointerMove, true);
|
|
7718
|
+
window.removeEventListener("pointerup", handlePointerUp, true);
|
|
7719
|
+
window.removeEventListener("pointercancel", handlePointerCancel, true);
|
|
7720
|
+
window.removeEventListener("mousemove", blockMouseEvent, true);
|
|
7721
|
+
window.removeEventListener("mouseup", blockMouseEvent, true);
|
|
7756
7722
|
window.removeEventListener("keydown", handleKeyDown);
|
|
7757
7723
|
window.removeEventListener("blur", handleBlur);
|
|
7758
7724
|
};
|
|
@@ -8534,7 +8500,7 @@ function SelectedCommentComposer({
|
|
|
8534
8500
|
React17.useLayoutEffect(() => {
|
|
8535
8501
|
updatePosition();
|
|
8536
8502
|
}, [text, updatePosition]);
|
|
8537
|
-
React17.
|
|
8503
|
+
const handleComposerClick = React17.useCallback(() => {
|
|
8538
8504
|
inputRef.current?.focus();
|
|
8539
8505
|
}, []);
|
|
8540
8506
|
React17.useEffect(() => {
|
|
@@ -8585,7 +8551,10 @@ function SelectedCommentComposer({
|
|
|
8585
8551
|
width: position.width,
|
|
8586
8552
|
pointerEvents: "auto"
|
|
8587
8553
|
},
|
|
8588
|
-
onClick: (e) =>
|
|
8554
|
+
onClick: (e) => {
|
|
8555
|
+
e.stopPropagation();
|
|
8556
|
+
handleComposerClick();
|
|
8557
|
+
},
|
|
8589
8558
|
children: [
|
|
8590
8559
|
/* @__PURE__ */ jsx7(
|
|
8591
8560
|
"textarea",
|
|
@@ -12883,7 +12852,8 @@ function DirectEditPanelContent() {
|
|
|
12883
12852
|
sendCommentToAgent: sendCommentToAgent2,
|
|
12884
12853
|
setActiveCommentId,
|
|
12885
12854
|
startTextEditing,
|
|
12886
|
-
toggleEditMode
|
|
12855
|
+
toggleEditMode,
|
|
12856
|
+
deleteSelection
|
|
12887
12857
|
} = useDirectEditActions();
|
|
12888
12858
|
const {
|
|
12889
12859
|
position,
|