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.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 getSourceFromDebugStack(fiber) {
2046
- const rawStack = fiber?._debugStack?.stack;
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 formattedStack = formatOwnerDebugStack(rawStack);
2051
- if (!formattedStack) return null;
2052
- const stackFrames = parseDebugStack(formattedStack);
2053
- const functionNameToRscFrames = buildFunctionNameToRscFramesMap(fiber);
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
- return null;
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 getSourceFromFiber2(fiber) {
2071
- const debugSource = fiber?._debugSource;
2072
- if (debugSource?.fileName) return debugSource;
2073
- const owner = fiber?._debugOwner;
2074
- const ownerPending = owner?.pendingProps?.__source;
2075
- if (ownerPending?.fileName) return ownerPending;
2076
- const ownerMemo = owner?.memoizedProps?.__source;
2077
- if (ownerMemo?.fileName) return ownerMemo;
2078
- const pending = fiber?.pendingProps?.__source;
2079
- if (pending?.fileName) return pending;
2080
- const memo = fiber?.memoizedProps?.__source;
2081
- if (memo?.fileName) return memo;
2082
- const fromDebugStack = getSourceFromDebugStack(fiber);
2083
- if (fromDebugStack?.fileName) return fromDebugStack;
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 buildFrame2(fiber) {
2087
- const type = fiber?.type;
2088
- if (typeof type !== "function" && typeof type !== "object") return null;
2089
- const name = type?.displayName || type?.name || null;
2090
- if (!name || name === "Fragment") return null;
2091
- const frame = { name };
2092
- const source = getSourceFromFiber2(fiber);
2093
- if (source?.fileName) {
2094
- frame.file = source.fileName;
2095
- if (typeof source.lineNumber === "number") {
2096
- frame.line = source.lineNumber;
2097
- }
2098
- if (typeof source.columnNumber === "number") {
2099
- frame.column = source.columnNumber;
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 frame;
1975
+ return null;
2103
1976
  }
2104
- function shouldIncludeFrame2(frame, lastFrame) {
2105
- if (!lastFrame) return true;
2106
- if (frame.name !== lastFrame.name) return true;
2107
- if (!lastFrame.file && frame.file) return true;
2108
- if (lastFrame.file && frame.file && lastFrame.line == null && frame.line != null) return true;
2109
- if (lastFrame.file && frame.file && lastFrame.line != null && frame.line != null && lastFrame.column == null && frame.column != null) {
2110
- return true;
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
- return false;
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 getOwnerStack2(fiber) {
2115
- const frames = [];
2116
- let current = fiber;
2117
- let lastFrame = null;
2118
- let nearestComponentFiber = null;
2119
- while (current) {
2120
- const frame = buildFrame2(current);
2121
- if (frame && shouldIncludeFrame2(frame, lastFrame)) {
2122
- frames.push(frame);
2123
- lastFrame = frame;
2124
- if (!nearestComponentFiber) {
2125
- nearestComponentFiber = current;
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 { frames, nearestComponentFiber };
2007
+ return null;
2131
2008
  }
2132
- function getRenderStack2(fiber) {
2133
- const frames = [];
2134
- let current = fiber;
2135
- let lastFrame = null;
2136
- let nearestComponentFiber = null;
2137
- while (current) {
2138
- const frame = buildFrame2(current);
2139
- if (frame && shouldIncludeFrame2(frame, lastFrame)) {
2140
- frames.push(frame);
2141
- lastFrame = frame;
2142
- if (!nearestComponentFiber) {
2143
- nearestComponentFiber = current;
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
- return { frames, nearestComponentFiber };
2149
- }
2150
- function getReactComponentInfo2(element) {
2151
- const fiber = getFiberForElement2(element);
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
- return { ...getRenderStack2(fiber), elementSourceFile };
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 = getFiberForElement2(element);
2378
+ let fiber = getFiberForElement(element);
2480
2379
  while (fiber && !seenFibers.has(fiber)) {
2481
2380
  seenFibers.add(fiber);
2482
- const fiberSource = getSourceFromFiber2(fiber);
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 } = getReactComponentInfo2(element);
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.useEffect(() => {
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) => e.stopPropagation(),
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,