@elixpo/lixsketch 5.5.20 → 5.5.21

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.
Files changed (105) hide show
  1. package/dist/react/{CopyPaste-KJZ34MIP.js → CopyPaste-FJN7K5LS.js} +39 -11
  2. package/dist/react/CopyPaste-FJN7K5LS.js.map +7 -0
  3. package/dist/react/{EventDispatcher-XDRQS7BD.js → EventDispatcher-O7HCQQNM.js} +13 -13
  4. package/dist/react/Frame-RLSMJJSK.js +11 -0
  5. package/dist/react/{GraphEngine-KQXHNTZQ.js → GraphEngine-MM6ALA2N.js} +105 -148
  6. package/dist/react/{GraphEngine-KQXHNTZQ.js.map → GraphEngine-MM6ALA2N.js.map} +2 -2
  7. package/dist/react/IconShape-7OPXAKLK.js +10 -0
  8. package/dist/react/ImageShape-LRNJQCF3.js +10 -0
  9. package/dist/react/Line-WWQFBNX5.js +10 -0
  10. package/dist/react/{SceneSerializer-VY3HY4PF.js → SceneSerializer-GSJR7ZHC.js} +32 -8
  11. package/dist/react/SceneSerializer-GSJR7ZHC.js.map +7 -0
  12. package/dist/react/{Selection-U2AR6NQS.js → Selection-ZL3G6IAO.js} +4 -4
  13. package/dist/react/{SketchEngine-ZFYUTKET.js → SketchEngine-BFLHJPCG.js} +21 -21
  14. package/dist/react/{UndoRedo-BZ6W4QTV.js → UndoRedo-NL7KLR5B.js} +2 -2
  15. package/dist/react/{arrowTool-LKFSZKXC.js → arrowTool-CNVGM6RX.js} +3 -3
  16. package/dist/react/{chunk-RFHMFWVR.js → chunk-2FMFOPGW.js} +5 -6
  17. package/dist/react/{chunk-RFHMFWVR.js.map → chunk-2FMFOPGW.js.map} +2 -2
  18. package/dist/react/{chunk-SBSM3GQD.js → chunk-2THKDSWW.js} +4 -4
  19. package/dist/react/{chunk-JOPQ27YH.js → chunk-4BLMNGTR.js} +3 -3
  20. package/dist/react/{chunk-C62SXFBL.js → chunk-4TAS67SL.js} +23 -22
  21. package/dist/react/chunk-4TAS67SL.js.map +7 -0
  22. package/dist/react/{chunk-7VBI7S7T.js → chunk-AH4PWNEB.js} +10 -11
  23. package/dist/react/chunk-AH4PWNEB.js.map +7 -0
  24. package/dist/react/{chunk-R5QXEVZ5.js → chunk-GC3KTQDA.js} +74 -15
  25. package/dist/react/chunk-GC3KTQDA.js.map +7 -0
  26. package/dist/react/{chunk-2V7G2PLX.js → chunk-GPIYXREE.js} +3 -3
  27. package/dist/react/{chunk-73VLPCBC.js → chunk-HFQZYCHJ.js} +3 -3
  28. package/dist/react/{chunk-C72OHQLE.js → chunk-ILGAFR56.js} +3 -3
  29. package/dist/react/{chunk-75G7XSZU.js → chunk-KVAQPCUH.js} +17 -3
  30. package/dist/react/chunk-KVAQPCUH.js.map +7 -0
  31. package/dist/react/{chunk-WEWMB35W.js → chunk-OFGJJKPH.js} +3 -3
  32. package/dist/react/{chunk-6G3ITAS5.js → chunk-SZD7DKYJ.js} +18 -9
  33. package/dist/react/chunk-SZD7DKYJ.js.map +7 -0
  34. package/dist/react/{chunk-MYYBFZD3.js → chunk-U3TB4KRS.js} +45 -6
  35. package/dist/react/chunk-U3TB4KRS.js.map +7 -0
  36. package/dist/react/{chunk-UQBT7F4K.js → chunk-V2QTYSBK.js} +2 -2
  37. package/dist/react/{chunk-2I3GH65Z.js → chunk-XFQECTTF.js} +44 -19
  38. package/dist/react/chunk-XFQECTTF.js.map +7 -0
  39. package/dist/react/{chunk-O64N5JPO.js → chunk-YF3TK7SC.js} +2 -2
  40. package/dist/react/{circleTool-RDOIMKKV.js → circleTool-KICNRQCI.js} +4 -4
  41. package/dist/react/{codeTool-VBDB2ES6.js → codeTool-NCQ73R6M.js} +4 -4
  42. package/dist/react/{frameTool-Z5ZDCX6H.js → frameTool-Y6KB67DO.js} +4 -4
  43. package/dist/react/{freehandTool-AAQCTMVM.js → freehandTool-MMULHCQ7.js} +4 -4
  44. package/dist/react/{iconTool-5WNDHI5T.js → iconTool-LSW2DYGB.js} +4 -4
  45. package/dist/react/{imageTool-ECPMT3BL.js → imageTool-2DSR32RX.js} +4 -4
  46. package/dist/react/index.js +141 -66
  47. package/dist/react/index.js.map +3 -3
  48. package/dist/react/{lineTool-XLOOZE3E.js → lineTool-N5I7IGT7.js} +4 -4
  49. package/dist/react/{rectangleTool-AEYDDJCA.js → rectangleTool-YUT7ZK2E.js} +4 -4
  50. package/dist/react/{textTool-5IJKTWVQ.js → textTool-IQOYPELP.js} +5 -5
  51. package/package.json +1 -1
  52. package/src/core/CopyPaste.js +34 -4
  53. package/src/core/GraphEngine.js +129 -185
  54. package/src/core/SceneSerializer.js +26 -0
  55. package/src/core/Selection.js +12 -11
  56. package/src/core/UndoRedo.js +47 -3
  57. package/src/react/components/canvas/MultiSelectActions.jsx +4 -1
  58. package/src/react/components/sidebars/IconSidebar.jsx +14 -23
  59. package/src/react/components/sidebars/ImageSidebar.jsx +47 -24
  60. package/src/react/store/useUIStore.js +71 -14
  61. package/src/shapes/Frame.js +19 -2
  62. package/src/shapes/IconShape.js +23 -25
  63. package/src/shapes/ImageShape.js +6 -2
  64. package/src/tools/frameTool.js +19 -9
  65. package/src/tools/iconTool.js +60 -25
  66. package/src/tools/imageTool.js +77 -13
  67. package/dist/react/CopyPaste-KJZ34MIP.js.map +0 -7
  68. package/dist/react/Frame-QLBAVLGW.js +0 -11
  69. package/dist/react/IconShape-32EYI2MA.js +0 -10
  70. package/dist/react/ImageShape-MYP2DVVH.js +0 -10
  71. package/dist/react/Line-FCCF2BOB.js +0 -10
  72. package/dist/react/SceneSerializer-VY3HY4PF.js.map +0 -7
  73. package/dist/react/chunk-2I3GH65Z.js.map +0 -7
  74. package/dist/react/chunk-6G3ITAS5.js.map +0 -7
  75. package/dist/react/chunk-75G7XSZU.js.map +0 -7
  76. package/dist/react/chunk-7VBI7S7T.js.map +0 -7
  77. package/dist/react/chunk-C62SXFBL.js.map +0 -7
  78. package/dist/react/chunk-MYYBFZD3.js.map +0 -7
  79. package/dist/react/chunk-R5QXEVZ5.js.map +0 -7
  80. /package/dist/react/{EventDispatcher-XDRQS7BD.js.map → EventDispatcher-O7HCQQNM.js.map} +0 -0
  81. /package/dist/react/{Frame-QLBAVLGW.js.map → Frame-RLSMJJSK.js.map} +0 -0
  82. /package/dist/react/{IconShape-32EYI2MA.js.map → IconShape-7OPXAKLK.js.map} +0 -0
  83. /package/dist/react/{ImageShape-MYP2DVVH.js.map → ImageShape-LRNJQCF3.js.map} +0 -0
  84. /package/dist/react/{Line-FCCF2BOB.js.map → Line-WWQFBNX5.js.map} +0 -0
  85. /package/dist/react/{Selection-U2AR6NQS.js.map → Selection-ZL3G6IAO.js.map} +0 -0
  86. /package/dist/react/{SketchEngine-ZFYUTKET.js.map → SketchEngine-BFLHJPCG.js.map} +0 -0
  87. /package/dist/react/{UndoRedo-BZ6W4QTV.js.map → UndoRedo-NL7KLR5B.js.map} +0 -0
  88. /package/dist/react/{arrowTool-LKFSZKXC.js.map → arrowTool-CNVGM6RX.js.map} +0 -0
  89. /package/dist/react/{chunk-SBSM3GQD.js.map → chunk-2THKDSWW.js.map} +0 -0
  90. /package/dist/react/{chunk-JOPQ27YH.js.map → chunk-4BLMNGTR.js.map} +0 -0
  91. /package/dist/react/{chunk-2V7G2PLX.js.map → chunk-GPIYXREE.js.map} +0 -0
  92. /package/dist/react/{chunk-73VLPCBC.js.map → chunk-HFQZYCHJ.js.map} +0 -0
  93. /package/dist/react/{chunk-C72OHQLE.js.map → chunk-ILGAFR56.js.map} +0 -0
  94. /package/dist/react/{chunk-WEWMB35W.js.map → chunk-OFGJJKPH.js.map} +0 -0
  95. /package/dist/react/{chunk-UQBT7F4K.js.map → chunk-V2QTYSBK.js.map} +0 -0
  96. /package/dist/react/{chunk-O64N5JPO.js.map → chunk-YF3TK7SC.js.map} +0 -0
  97. /package/dist/react/{circleTool-RDOIMKKV.js.map → circleTool-KICNRQCI.js.map} +0 -0
  98. /package/dist/react/{codeTool-VBDB2ES6.js.map → codeTool-NCQ73R6M.js.map} +0 -0
  99. /package/dist/react/{frameTool-Z5ZDCX6H.js.map → frameTool-Y6KB67DO.js.map} +0 -0
  100. /package/dist/react/{freehandTool-AAQCTMVM.js.map → freehandTool-MMULHCQ7.js.map} +0 -0
  101. /package/dist/react/{iconTool-5WNDHI5T.js.map → iconTool-LSW2DYGB.js.map} +0 -0
  102. /package/dist/react/{imageTool-ECPMT3BL.js.map → imageTool-2DSR32RX.js.map} +0 -0
  103. /package/dist/react/{lineTool-XLOOZE3E.js.map → lineTool-N5I7IGT7.js.map} +0 -0
  104. /package/dist/react/{rectangleTool-AEYDDJCA.js.map → rectangleTool-YUT7ZK2E.js.map} +0 -0
  105. /package/dist/react/{textTool-5IJKTWVQ.js.map → textTool-IQOYPELP.js.map} +0 -0
@@ -30,10 +30,16 @@ const minImageSize = 20;
30
30
  let draggedShapeInitialFrameImage = null;
31
31
  let hoveredFrameImage = null;
32
32
 
33
- // Per-room image size limit: 5MB total
34
- const ROOM_IMAGE_LIMIT_BYTES = 5 * 1024 * 1024;
35
33
  if (!window.__roomImageBytesUsed) window.__roomImageBytesUsed = 0;
36
34
 
35
+ function getRoomImageLimitBytes() {
36
+ return Number(window.__roomImageLimitBytes) || 2 * 1024 * 1024;
37
+ }
38
+
39
+ function usesPersonalCloudinary() {
40
+ return Boolean(window.__personalCloudinary?.connected && window.__personalCloudinary?.useForUploads);
41
+ }
42
+
37
43
 
38
44
  // Convert SVG element to our ImageShape class
39
45
  function wrapImageElement(element) {
@@ -69,6 +75,37 @@ async function uploadImageToCloudinary(imageShape) {
69
75
  const compressed = await compressImage(href);
70
76
  if (signal.aborted) return;
71
77
 
78
+ const roomLimit = getRoomImageLimitBytes();
79
+ const oldSize = imageShape.element.__fileSize || 0;
80
+ if (!usesPersonalCloudinary() && (window.__roomImageBytesUsed || 0) - oldSize + compressed.compressedSize > roomLimit) {
81
+ throw new Error(`Room image limit reached (${Math.round(roomLimit / (1024 * 1024))} MB)`);
82
+ }
83
+
84
+ if (usesPersonalCloudinary()) {
85
+ const personalForm = new FormData();
86
+ personalForm.append('file', compressed.blob, `image_${Date.now()}`);
87
+ personalForm.append('sessionId', sessionId);
88
+ const personalResponse = await fetch('/api/images/personal-upload', {
89
+ method: 'POST',
90
+ body: personalForm,
91
+ signal,
92
+ });
93
+ const personalData = await personalResponse.json().catch(() => ({}));
94
+ if (!personalResponse.ok || !personalData.url) {
95
+ throw new Error(personalData.error || 'Personal Cloudinary upload failed');
96
+ }
97
+ imageShape.element.setAttribute('href', personalData.url);
98
+ imageShape.element.setAttribute('data-href', personalData.url);
99
+ imageShape.element.setAttribute('data-cloudinary-id', personalData.publicId);
100
+ imageShape.element.setAttribute('data-storage-provider', 'user_cloudinary');
101
+ imageShape.element.setAttribute('data-storage-cloud-name', personalData.cloudName || '');
102
+ imageShape.element.__fileSize = 0;
103
+ imageShape.element.setAttribute('data-file-size', '0');
104
+ window.__roomImageBytesUsed = Math.max(0, (window.__roomImageBytesUsed || 0) - oldSize);
105
+ imageShape.uploadStatus = 'done';
106
+ return;
107
+ }
108
+
72
109
  // Step 2: Get signed upload params
73
110
  const signRes = await fetch(`${workerUrl}/api/images/sign`, {
74
111
  method: 'POST',
@@ -76,10 +113,14 @@ async function uploadImageToCloudinary(imageShape) {
76
113
  body: JSON.stringify({
77
114
  sessionId,
78
115
  filename: `img_${Date.now()}`,
116
+ sizeBytes: compressed.compressedSize,
79
117
  }),
80
118
  signal,
81
119
  });
82
- if (!signRes.ok) throw new Error('Failed to get upload signature');
120
+ if (!signRes.ok) {
121
+ const errorBody = await signRes.json().catch(() => ({}));
122
+ throw new Error(errorBody.message || 'Failed to get upload signature');
123
+ }
83
124
  const signData = await signRes.json();
84
125
  if (signal.aborted) return;
85
126
 
@@ -100,6 +141,17 @@ async function uploadImageToCloudinary(imageShape) {
100
141
  const uploadData = await uploadRes.json();
101
142
  if (signal.aborted) return;
102
143
 
144
+ await fetch(`${workerUrl}/api/images/complete`, {
145
+ method: 'POST',
146
+ headers: { 'Content-Type': 'application/json' },
147
+ body: JSON.stringify({
148
+ sessionId,
149
+ publicId: uploadData.public_id || signData.publicId,
150
+ sizeBytes: uploadData.bytes || compressed.compressedSize,
151
+ }),
152
+ signal,
153
+ }).catch(() => {});
154
+
103
155
  // Step 4: Replace base64 with Cloudinary URL
104
156
  const cloudUrl = uploadData.secure_url || uploadData.url;
105
157
  imageShape.element.setAttribute('href', cloudUrl);
@@ -107,9 +159,9 @@ async function uploadImageToCloudinary(imageShape) {
107
159
  imageShape.element.setAttribute('data-cloudinary-id', uploadData.public_id);
108
160
 
109
161
  // Update file size tracking with actual compressed size
110
- const oldSize = imageShape.element.__fileSize || 0;
111
162
  const newSize = uploadData.bytes || compressed.compressedSize;
112
163
  imageShape.element.__fileSize = newSize;
164
+ imageShape.element.setAttribute('data-file-size', String(newSize));
113
165
  window.__roomImageBytesUsed = Math.max(0, (window.__roomImageBytesUsed || 0) - oldSize + newSize);
114
166
 
115
167
  imageShape.uploadStatus = 'done';
@@ -209,19 +261,20 @@ const handleImageUpload = async (file) => {
209
261
  return;
210
262
  }
211
263
 
212
- // Per-room 5MB total image limit
213
- if (window.__roomImageBytesUsed + file.size > ROOM_IMAGE_LIMIT_BYTES) {
264
+ const roomImageLimitBytes = getRoomImageLimitBytes();
265
+ const personalStorage = usesPersonalCloudinary();
266
+ if (!personalStorage && window.__roomImageBytesUsed + file.size > roomImageLimitBytes) {
214
267
  const usedMB = (window.__roomImageBytesUsed / (1024 * 1024)).toFixed(2);
215
268
  const fileMB = (file.size / (1024 * 1024)).toFixed(2);
216
- alert(`Room image limit reached (5 MB). Used: ${usedMB} MB, this file: ${fileMB} MB. Delete some images to free space.`);
269
+ alert(`Room image limit reached (${Math.round(roomImageLimitBytes / (1024 * 1024))} MB). Used: ${usedMB} MB, this file: ${fileMB} MB. Delete some images to free space.`);
217
270
  isImageToolActive = false;
218
271
  return;
219
272
  }
220
273
 
221
- const maxSize = 5 * 1024 * 1024; // 5MB per file (matches room limit)
274
+ const maxSize = personalStorage ? 20 * 1024 * 1024 : roomImageLimitBytes;
222
275
  if (file.size > maxSize) {
223
276
  console.error('File size too large');
224
- alert('Image file is too large. Please select an image smaller than 5 MB.');
277
+ alert(`Image file is too large. Please select an image smaller than ${Math.round(maxSize / (1024 * 1024))} MB.`);
225
278
  return;
226
279
  }
227
280
 
@@ -471,6 +524,7 @@ const handleMouseDownImage = async (e) => {
471
524
  // Track image size for room limit
472
525
  const placedFileSize = window.__pendingImageFileSize || 0;
473
526
  finalImage.__fileSize = placedFileSize;
527
+ finalImage.setAttribute('data-file-size', String(placedFileSize));
474
528
  window.__roomImageBytesUsed = (window.__roomImageBytesUsed || 0) + placedFileSize;
475
529
  window.__pendingImageFileSize = 0;
476
530
 
@@ -538,8 +592,8 @@ const handleMouseUpImage = (e) => {
538
592
  }
539
593
  };
540
594
 
541
- function selectImage(event) {
542
- if (!isSelectionToolActive) return;
595
+ function selectImage(event, force = false) {
596
+ if (!isSelectionToolActive && !force) return;
543
597
 
544
598
  event.stopPropagation(); // Prevent click from propagating to the SVG
545
599
 
@@ -1270,9 +1324,11 @@ function deleteCurrentImage() {
1270
1324
  const match = imgHref.match(/\/upload\/(?:v\d+\/)?(lixsketch\/.+?)(?:\.\w+)?$/);
1271
1325
  if (match) {
1272
1326
  const publicId = match[1];
1327
+ const isPersonal = selectedImage.getAttribute('data-storage-provider') === 'user_cloudinary';
1273
1328
  const workerUrl = window.__WORKER_URL;
1274
- if (workerUrl) {
1275
- fetch(`${workerUrl}/api/images/delete`, {
1329
+ const deleteUrl = isPersonal ? '/api/images/personal-delete' : (workerUrl ? `${workerUrl}/api/images/delete` : null);
1330
+ if (deleteUrl) {
1331
+ fetch(deleteUrl, {
1276
1332
  method: 'DELETE',
1277
1333
  headers: { 'Content-Type': 'application/json' },
1278
1334
  body: JSON.stringify({ publicId }),
@@ -1321,6 +1377,14 @@ document.addEventListener('keydown', (e) => {
1321
1377
  // Expose upload pipeline globally so generated/pasted images can use it
1322
1378
  window.uploadImageToCloudinary = uploadImageToCloudinary;
1323
1379
 
1380
+ // Programmatic selection bridge used by generated vector-image shapes.
1381
+ // Keeping the selection state in this module prevents a second, divergent
1382
+ // implementation of image dragging and screen-space resize controls.
1383
+ window.__selectImageElement = function(element, { force = false } = {}) {
1384
+ if (!element) return;
1385
+ selectImage({ target: element, stopPropagation: () => {} }, force);
1386
+ };
1387
+
1324
1388
  // Window bridge: allow React UI to trigger the file picker
1325
1389
  window.openImageFilePicker = function() {
1326
1390
  isImageToolActive = true;
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/CopyPaste.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Centralized Copy/Paste system for ALL shape types\n// Supports single and multi-selection copy/paste\n// Pastes at mouse pointer position with offset to prevent stacking\n\nimport { pushCreateAction } from './UndoRedo.js';\nimport { Rectangle } from '../shapes/Rectangle.js';\nimport { Circle } from '../shapes/Circle.js';\nimport { Line } from '../shapes/Line.js';\nimport { Arrow } from '../shapes/Arrow.js';\nimport { FreehandStroke } from '../shapes/FreehandStroke.js';\nimport { Frame } from '../shapes/Frame.js';\nimport { TextShape } from '../shapes/TextShape.js';\nimport { CodeShape } from '../shapes/CodeShape.js';\nimport { ImageShape } from '../shapes/ImageShape.js';\nimport { isAllowedImage, isAllowedImageDataUrl } from '../utils/allowedImageTypes.js';\nimport { compressImage } from '../utils/imageCompressor.js';\nimport { IconShape } from '../shapes/IconShape.js';\n\n// Clipboard storage\nlet clipboard = null; // { shapes: [...clonedData], centerX, centerY }\nlet pasteCount = 0; // Increments per paste to offset repeated pastes\n\n// Last known mouse position in SVG coordinates\nlet lastMouseSVG = { x: 0, y: 0 };\n\nfunction getSVGElement() {\n return document.getElementById('freehand-canvas');\n}\n\nfunction getSVGCoordsFromMouse(e) {\n const svgEl = getSVGElement();\n if (!svgEl) return { x: 0, y: 0 };\n const viewBox = svgEl.viewBox.baseVal;\n const rect = svgEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;\n const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;\n return { x: svgX, y: svgY };\n}\n\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\n// ============================================================\n// SERIALIZE: Extract copyable data from a shape\n// ============================================================\nfunction serializeShape(shape) {\n switch (shape.shapeName) {\n case 'rectangle':\n return {\n type: 'rectangle',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'circle':\n return {\n type: 'circle',\n x: shape.x,\n y: shape.y,\n rx: shape.rx,\n ry: shape.ry,\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'line':\n return {\n type: 'line',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint: shape.controlPoint ? { x: shape.controlPoint.x, y: shape.controlPoint.y } : null,\n isCurved: shape.isCurved || false,\n options: cloneOptions(shape.options)\n };\n\n case 'arrow':\n return {\n type: 'arrow',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint1: shape.controlPoint1 ? { x: shape.controlPoint1.x, y: shape.controlPoint1.y } : null,\n controlPoint2: shape.controlPoint2 ? { x: shape.controlPoint2.x, y: shape.controlPoint2.y } : null,\n options: cloneOptions(shape.options),\n arrowOutlineStyle: shape.arrowOutlineStyle,\n arrowHeadStyle: shape.arrowHeadStyle,\n arrowCurved: shape.arrowCurved,\n arrowCurveAmount: shape.arrowCurveAmount\n };\n\n case 'freehandStroke':\n return {\n type: 'freehandStroke',\n points: JSON.parse(JSON.stringify(shape.points)),\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'frame':\n return {\n type: 'frame',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n frameName: shape.frameName,\n options: cloneOptions(shape.options)\n };\n\n case 'text': {\n const group = shape.group;\n const textEl = group.querySelector('text');\n return {\n type: 'text',\n x: shape.x,\n y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML\n };\n }\n\n case 'code': {\n const group = shape.group;\n return {\n type: 'code',\n x: shape.x,\n y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML\n };\n }\n\n case 'image': {\n const el = shape.element;\n return {\n type: 'image',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n href: el.getAttribute('href') || el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || ''\n };\n }\n\n case 'icon': {\n const el = shape.element;\n return {\n type: 'icon',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n elementHTML: el.cloneNode(true).outerHTML,\n viewboxWidth: parseFloat(el.getAttribute('data-viewbox-width')) || 24,\n viewboxHeight: parseFloat(el.getAttribute('data-viewbox-height')) || 24\n };\n }\n\n default:\n console.warn('Copy not supported for shape type:', shape.shapeName);\n return null;\n }\n}\n\n// ============================================================\n// Get bounding center of a serialized shape\n// ============================================================\nfunction getShapeCenter(data) {\n switch (data.type) {\n case 'rectangle':\n case 'frame':\n return { x: data.x + data.width / 2, y: data.y + data.height / 2 };\n case 'circle':\n return { x: data.x, y: data.y };\n case 'line':\n return {\n x: (data.startPoint.x + data.endPoint.x) / 2,\n y: (data.startPoint.y + data.endPoint.y) / 2\n };\n case 'arrow':\n return {\n x: (data.startPoint.x + data.endPoint.x) / 2,\n y: (data.startPoint.y + data.endPoint.y) / 2\n };\n case 'freehandStroke': {\n if (!data.points.length) return { x: 0, y: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n data.points.forEach(p => {\n if (p[0] < minX) minX = p[0];\n if (p[1] < minY) minY = p[1];\n if (p[0] > maxX) maxX = p[0];\n if (p[1] > maxY) maxY = p[1];\n });\n return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 };\n }\n case 'text':\n case 'code':\n return { x: data.x, y: data.y };\n case 'image':\n case 'icon':\n return { x: data.x + data.width / 2, y: data.y + data.height / 2 };\n default:\n return { x: 0, y: 0 };\n }\n}\n\n// ============================================================\n// DESERIALIZE: Create a new shape from copied data at offset\n// ============================================================\nfunction createShapeFromData(data, offsetX, offsetY) {\n const svgEl = getSVGElement();\n if (!svgEl) return null;\n\n switch (data.type) {\n case 'rectangle': {\n const newRect = new Rectangle(\n data.x + offsetX,\n data.y + offsetY,\n data.width,\n data.height,\n cloneOptions(data.options)\n );\n newRect.rotation = data.rotation;\n newRect.draw();\n return newRect;\n }\n\n case 'circle': {\n const newCircle = new Circle(\n data.x + offsetX,\n data.y + offsetY,\n data.rx,\n data.ry,\n cloneOptions(data.options)\n );\n newCircle.rotation = data.rotation;\n newCircle.draw();\n return newCircle;\n }\n\n case 'line': {\n const newLine = new Line(\n { x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },\n { x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },\n cloneOptions(data.options)\n );\n if (data.isCurved && data.controlPoint) {\n newLine.isCurved = true;\n newLine.controlPoint = { x: data.controlPoint.x + offsetX, y: data.controlPoint.y + offsetY };\n }\n newLine.draw();\n return newLine;\n }\n\n case 'arrow': {\n const opts = {\n ...cloneOptions(data.options),\n arrowOutlineStyle: data.arrowOutlineStyle,\n arrowHeadStyle: data.arrowHeadStyle,\n arrowCurved: data.arrowCurved,\n arrowCurveAmount: data.arrowCurveAmount,\n controlPoint1: data.controlPoint1 ? { x: data.controlPoint1.x + offsetX, y: data.controlPoint1.y + offsetY } : null,\n controlPoint2: data.controlPoint2 ? { x: data.controlPoint2.x + offsetX, y: data.controlPoint2.y + offsetY } : null\n };\n const newArrow = new Arrow(\n { x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },\n { x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },\n opts\n );\n return newArrow;\n }\n\n case 'freehandStroke': {\n const offsetPoints = data.points.map(p => [\n p[0] + offsetX,\n p[1] + offsetY,\n p[2] || 0.5\n ]);\n const newStroke = new FreehandStroke(offsetPoints, cloneOptions(data.options));\n newStroke.rotation = data.rotation;\n newStroke.draw();\n return newStroke;\n }\n\n case 'frame': {\n const newFrame = new Frame(\n data.x + offsetX,\n data.y + offsetY,\n data.width,\n data.height,\n { ...cloneOptions(data.options), frameName: data.frameName, rotation: data.rotation }\n );\n newFrame.rotation = data.rotation;\n return newFrame;\n }\n\n case 'text': {\n // Parse the cloned HTML and insert into SVG\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = data.groupHTML;\n const clonedGroup = tempDiv.firstElementChild;\n if (!clonedGroup) return null;\n\n // Generate new unique ID\n const newID = `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedGroup.setAttribute('id', newID);\n const textChild = clonedGroup.querySelector('text');\n if (textChild) textChild.setAttribute('id', `${newID}-text`);\n\n // Update position\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const rotation = data.rotation || 0;\n if (textChild && rotation) {\n try {\n const bbox = { x: 0, y: 0, width: 100, height: 30 }; // approximate until appended\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY}) rotate(${rotation}, ${bbox.width / 2}, ${bbox.height / 2})`);\n } catch (e) {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n } else {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n clonedGroup.setAttribute('data-x', newX);\n clonedGroup.setAttribute('data-y', newY);\n\n svgEl.appendChild(clonedGroup);\n\n const textShape = new TextShape(clonedGroup);\n return textShape;\n }\n\n case 'code': {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = data.groupHTML;\n const clonedGroup = tempDiv.firstElementChild;\n if (!clonedGroup) return null;\n\n const newID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedGroup.setAttribute('id', newID);\n const codeChild = clonedGroup.querySelector('text');\n if (codeChild) codeChild.setAttribute('id', `${newID}-code`);\n\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const rotation = data.rotation || 0;\n if (rotation) {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY}) rotate(${rotation}, 0, 0)`);\n } else {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n clonedGroup.setAttribute('data-x', newX);\n clonedGroup.setAttribute('data-y', newY);\n\n svgEl.appendChild(clonedGroup);\n\n const codeShape = new CodeShape(clonedGroup);\n return codeShape;\n }\n\n case 'image': {\n const imgEl = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n imgEl.setAttribute('x', newX);\n imgEl.setAttribute('y', newY);\n imgEl.setAttribute('width', data.width);\n imgEl.setAttribute('height', data.height);\n imgEl.setAttribute('href', data.href);\n imgEl.setAttribute('data-shape-x', newX);\n imgEl.setAttribute('data-shape-y', newY);\n imgEl.setAttribute('data-shape-width', data.width);\n imgEl.setAttribute('data-shape-height', data.height);\n imgEl.setAttribute('preserveAspectRatio', 'none');\n imgEl.setAttribute('style', 'cursor: pointer;');\n\n // ImageShape constructor moves element into a group and appends to svg\n svgEl.appendChild(imgEl);\n const imageShape = new ImageShape(imgEl);\n imageShape.rotation = data.rotation;\n return imageShape;\n }\n\n case 'icon': {\n // Parse inside an SVG document. Parsing a copied <g> through an\n // HTML <div> creates it in the HTML namespace, so it can be added\n // to shapes[] but the SVG renderer will not paint it.\n const parser = new DOMParser();\n const parsed = parser.parseFromString(\n `<svg xmlns=\"http://www.w3.org/2000/svg\">${data.elementHTML}</svg>`,\n 'image/svg+xml'\n );\n const parsedGroup = parsed.querySelector('g');\n if (!parsedGroup || parsed.querySelector('parsererror')) return null;\n const clonedEl = svgEl.ownerDocument.importNode(parsedGroup, true);\n\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const newID = `icon-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedEl.setAttribute('id', newID);\n clonedEl.setAttribute('x', newX);\n clonedEl.setAttribute('y', newY);\n clonedEl.setAttribute('data-shape-x', newX);\n clonedEl.setAttribute('data-shape-y', newY);\n clonedEl.setAttribute('data-shape-width', data.width);\n clonedEl.setAttribute('data-shape-height', data.height);\n clonedEl.setAttribute('data-shape-rotation', data.rotation);\n clonedEl.setAttribute('data-viewbox-width', data.viewboxWidth);\n clonedEl.setAttribute('data-viewbox-height', data.viewboxHeight);\n\n // Recalculate transform\n const scale = data.width / Math.max(data.viewboxWidth, data.viewboxHeight);\n const localCenterX = data.width / 2 / scale;\n const localCenterY = data.height / 2 / scale;\n clonedEl.setAttribute('transform', `translate(${newX}, ${newY}) scale(${scale}) rotate(${data.rotation}, ${localCenterX}, ${localCenterY})`);\n\n svgEl.appendChild(clonedEl);\n\n const iconShape = new IconShape(clonedEl);\n return iconShape;\n }\n\n default:\n return null;\n }\n}\n\n// ============================================================\n// COPY: Serialize currently selected shapes\n// ============================================================\nfunction copySelected() {\n const shapesToCopy = [];\n\n // Check multi-selection first\n if (window.multiSelection && window.multiSelection.selectedShapes && window.multiSelection.selectedShapes.size > 0) {\n window.multiSelection.selectedShapes.forEach(shape => {\n const data = serializeShape(shape);\n if (data) shapesToCopy.push(data);\n });\n }\n // Fall back to single currentShape\n else if (typeof currentShape !== 'undefined' && currentShape && currentShape.isSelected) {\n const data = serializeShape(currentShape);\n if (data) shapesToCopy.push(data);\n }\n\n if (shapesToCopy.length === 0) return false;\n\n // Calculate center of all copied shapes\n let totalX = 0, totalY = 0;\n shapesToCopy.forEach(d => {\n const c = getShapeCenter(d);\n totalX += c.x;\n totalY += c.y;\n });\n const centerX = totalX / shapesToCopy.length;\n const centerY = totalY / shapesToCopy.length;\n\n clipboard = {\n shapes: shapesToCopy,\n centerX,\n centerY\n };\n pasteCount = 0;\n\n return true;\n}\n\n// ============================================================\n// PASTE: Create new shapes from clipboard at mouse position\n// ============================================================\nfunction pasteClipboard() {\n if (!clipboard || clipboard.shapes.length === 0) return false;\n\n pasteCount++;\n const baseOffset = 20 * pasteCount;\n\n // Calculate paste position: center the group on the mouse pointer\n const targetX = lastMouseSVG.x;\n const targetY = lastMouseSVG.y;\n const groupOffsetX = targetX - clipboard.centerX + baseOffset;\n const groupOffsetY = targetY - clipboard.centerY + baseOffset;\n\n // Deselect all currently selected shapes\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(s => {\n if (s.isSelected && typeof s.removeSelection === 'function') {\n s.removeSelection();\n s.isSelected = false;\n }\n });\n }\n if (window.multiSelection) {\n window.multiSelection.clearSelection();\n }\n if (typeof currentShape !== 'undefined') {\n currentShape = null;\n }\n if (typeof disableAllSideBars === 'function') {\n disableAllSideBars();\n }\n\n const pastedShapes = [];\n\n clipboard.shapes.forEach(data => {\n const newShape = createShapeFromData(data, groupOffsetX, groupOffsetY);\n if (newShape) {\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(newShape);\n }\n pushCreateAction(newShape);\n pastedShapes.push(newShape);\n }\n });\n\n // Select the pasted shapes\n if (pastedShapes.length === 1) {\n const s = pastedShapes[0];\n s.isSelected = true;\n currentShape = s;\n if (typeof s.addAnchors === 'function') {\n s.addAnchors();\n } else if (typeof s.selectShape === 'function') {\n s.selectShape();\n }\n } else if (pastedShapes.length > 1 && window.multiSelection) {\n pastedShapes.forEach(s => {\n window.multiSelection.addShape(s);\n });\n window.multiSelection.updateControls();\n }\n\n return true;\n}\n\n// ============================================================\n// KEYBOARD HANDLER: Ctrl+C / Ctrl+V\n// ============================================================\nfunction handleCopyPasteKeydown(e) {\n // Don't intercept if user is typing in an input/textarea/contenteditable\n const tag = (e.target.tagName || '').toLowerCase();\n if (tag === 'input' || tag === 'textarea' || e.target.isContentEditable) return;\n\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'c') {\n if (copySelected()) {\n e.preventDefault();\n }\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'v') {\n if (pasteClipboard()) {\n e.preventDefault();\n }\n }\n}\n\n// Track mouse position for paste placement\nfunction handleMouseMoveForPaste(e) {\n const svgEl = getSVGElement();\n if (!svgEl) return;\n const viewBox = svgEl.viewBox.baseVal;\n const rect = svgEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n lastMouseSVG.x = viewBox.x + (mouseX / rect.width) * viewBox.width;\n lastMouseSVG.y = viewBox.y + (mouseY / rect.height) * viewBox.height;\n}\n\n// ============================================================\n// PASTE IMAGE FROM CLIPBOARD (external images, screenshots)\n// ============================================================\nfunction handlePasteEvent(e) {\n // Don't intercept if user is typing\n const tag = (e.target.tagName || '').toLowerCase();\n if (tag === 'input' || tag === 'textarea' || e.target.isContentEditable) return;\n\n const items = e.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n e.preventDefault();\n const blob = item.getAsFile();\n if (!blob) return;\n\n // Validate against the canonical allowlist \u2014 clipboard sources\n // can include animated GIFs / HEIC / TIFF / arbitrary mime types.\n if (!isAllowedImage(blob)) {\n console.warn('[CopyPaste] Rejected pasted image type:', blob.type);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = async (ev) => {\n const rawDataUrl = ev.target.result;\n const isSvg = (blob.type || '').toLowerCase() === 'image/svg+xml';\n let placedDataUrl = rawDataUrl;\n if (!isSvg) {\n try {\n const compressed = await compressImage(rawDataUrl);\n if (compressed?.dataUrl) placedDataUrl = compressed.dataUrl;\n } catch (err) {\n console.warn('[CopyPaste] Pre-placement compression failed, using raw:', err);\n }\n }\n placeImageFromDataUrl(placedDataUrl);\n };\n reader.readAsDataURL(blob);\n return; // only handle first image\n }\n }\n}\n\nfunction placeImageFromDataUrl(dataUrl) {\n const svgEl = getSVGElement();\n if (!svgEl || !window.ImageShape) return;\n\n const img = new Image();\n img.onload = () => {\n const aspectRatio = img.height / img.width;\n const displayW = Math.min(400, img.width);\n const displayH = displayW * aspectRatio;\n\n // Place at center of current viewport\n const vb = svgEl.viewBox.baseVal;\n const cx = vb.x + vb.width / 2;\n const cy = vb.y + vb.height / 2;\n\n const imgEl = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n imgEl.setAttribute('href', dataUrl);\n imgEl.setAttribute('x', cx - displayW / 2);\n imgEl.setAttribute('y', cy - displayH / 2);\n imgEl.setAttribute('width', displayW);\n imgEl.setAttribute('height', displayH);\n imgEl.setAttribute('data-shape-x', cx - displayW / 2);\n imgEl.setAttribute('data-shape-y', cy - displayH / 2);\n imgEl.setAttribute('data-shape-width', displayW);\n imgEl.setAttribute('data-shape-height', displayH);\n imgEl.setAttribute('type', 'image');\n imgEl.setAttribute('preserveAspectRatio', 'none');\n\n svgEl.appendChild(imgEl);\n const imageShape = new ImageShape(imgEl);\n if (window.shapes) window.shapes.push(imageShape);\n if (window.pushCreateAction) window.pushCreateAction(imageShape);\n\n // Compress and upload to Cloudinary\n if (window.uploadImageToCloudinary) {\n window.uploadImageToCloudinary(imageShape);\n }\n\n console.log('[CopyPaste] Pasted image from clipboard');\n };\n img.src = dataUrl;\n}\n\n// ============================================================\n// INIT: Set up event listeners\n// ============================================================\nfunction initCopyPaste() {\n document.addEventListener('keydown', handleCopyPasteKeydown);\n document.addEventListener('pointermove', handleMouseMoveForPaste);\n document.addEventListener('paste', handlePasteEvent);\n\n // Expose for context menu\n window.copySelected = copySelected;\n window.pasteClipboard = pasteClipboard;\n}\n\nexport { initCopyPaste, copySelected, pasteClipboard };\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,11 +0,0 @@
1
- "use client";
2
- import {
3
- Frame
4
- } from "./chunk-75G7XSZU.js";
5
- import "./chunk-PAKA6HUX.js";
6
- import "./chunk-O64N5JPO.js";
7
- import "./chunk-MYYBFZD3.js";
8
- export {
9
- Frame
10
- };
11
- //# sourceMappingURL=Frame-QLBAVLGW.js.map
@@ -1,10 +0,0 @@
1
- "use client";
2
- import {
3
- IconShape
4
- } from "./chunk-C62SXFBL.js";
5
- import "./chunk-O64N5JPO.js";
6
- import "./chunk-MYYBFZD3.js";
7
- export {
8
- IconShape
9
- };
10
- //# sourceMappingURL=IconShape-32EYI2MA.js.map
@@ -1,10 +0,0 @@
1
- "use client";
2
- import {
3
- ImageShape
4
- } from "./chunk-RFHMFWVR.js";
5
- import "./chunk-O64N5JPO.js";
6
- import "./chunk-MYYBFZD3.js";
7
- export {
8
- ImageShape
9
- };
10
- //# sourceMappingURL=ImageShape-MYP2DVVH.js.map
@@ -1,10 +0,0 @@
1
- "use client";
2
- import {
3
- Line
4
- } from "./chunk-UQBT7F4K.js";
5
- import "./chunk-O64N5JPO.js";
6
- import "./chunk-MYYBFZD3.js";
7
- export {
8
- Line
9
- };
10
- //# sourceMappingURL=Line-FCCF2BOB.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/SceneSerializer.js"],
4
- "sourcesContent": ["/* eslint-disable */\n/**\n * SceneSerializer - Save and load .lixsketch scene files\n *\n * Format: JSON with metadata + serialized shapes array\n * File extension: .lixsketch (actually JSON)\n */\n\nimport { Rectangle } from '../shapes/Rectangle.js';\nimport { Circle } from '../shapes/Circle.js';\nimport { Line } from '../shapes/Line.js';\nimport { Arrow } from '../shapes/Arrow.js';\nimport { FreehandStroke } from '../shapes/FreehandStroke.js';\nimport { Frame } from '../shapes/Frame.js';\nimport { TextShape } from '../shapes/TextShape.js';\nimport { CodeShape } from '../shapes/CodeShape.js';\nimport { ImageShape } from '../shapes/ImageShape.js';\nimport { IconShape } from '../shapes/IconShape.js';\n\nconst FORMAT_VERSION = 1;\n\n// Generate a unique session ID for each scene\nlet _sessionID = null;\nexport function getSessionID() {\n if (!_sessionID) {\n _sessionID = `lx-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n return _sessionID;\n}\nexport function resetSessionID() {\n _sessionID = null;\n}\n\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\nfunction restoreDocBlockLinks(shape, data) {\n const ids = [...new Set((Array.isArray(data.docBlockIds)\n ? data.docBlockIds\n : (data.docBlockId ? [data.docBlockId] : [])).filter(Boolean))];\n shape.docBlockIds = ids;\n delete shape.docBlockId;\n if (ids.length) {\n (shape.group || shape.element)?.setAttribute('data-doc-block-ids', JSON.stringify(ids));\n }\n}\n\n// ============================================================\n// SERIALIZE a single shape to plain data\n// ============================================================\nfunction serializeShape(shape) {\n const base = {\n shapeID: shape.shapeID,\n // Optional many-to-many connections to BlockNote document blocks.\n // Stored with the encrypted scene so navigation survives restore.\n docBlockIds: [...new Set((Array.isArray(shape.docBlockIds)\n ? shape.docBlockIds\n : (shape.docBlockId ? [shape.docBlockId] : [])).filter(Boolean))],\n parentFrame: shape.parentFrame ? shape.parentFrame.shapeID : null,\n // Group membership \u2014 null when the shape isn't part of a group.\n // All shapes sharing a non-null groupId move/resize/rotate as a\n // unit (see Selection.handleMultiSelectionMouseDown).\n groupId: shape.groupId || null,\n };\n\n switch (shape.shapeName) {\n case 'rectangle':\n return {\n ...base,\n type: 'rectangle',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'circle':\n return {\n ...base,\n type: 'circle',\n x: shape.x, y: shape.y,\n rx: shape.rx, ry: shape.ry,\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'line':\n return {\n ...base,\n type: 'line',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint: shape.controlPoint ? { x: shape.controlPoint.x, y: shape.controlPoint.y } : null,\n isCurved: shape.isCurved || false,\n options: cloneOptions(shape.options),\n };\n\n case 'arrow': {\n const data = {\n ...base,\n type: 'arrow',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n options: cloneOptions(shape.options),\n arrowOutlineStyle: shape.arrowOutlineStyle,\n arrowHeadStyle: shape.arrowHeadStyle,\n arrowCurved: shape.arrowCurved,\n arrowCurveAmount: shape.arrowCurveAmount,\n };\n if (shape.controlPoint1) data.controlPoint1 = { x: shape.controlPoint1.x, y: shape.controlPoint1.y };\n if (shape.controlPoint2) data.controlPoint2 = { x: shape.controlPoint2.x, y: shape.controlPoint2.y };\n // Serialize attachments by shapeID\n if (shape.startAttachment) data.startAttachmentID = shape.startAttachment.shapeID;\n if (shape.endAttachment) data.endAttachmentID = shape.endAttachment.shapeID;\n return data;\n }\n\n case 'freehandStroke':\n return {\n ...base,\n type: 'freehandStroke',\n points: JSON.parse(JSON.stringify(shape.points)),\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'frame':\n return {\n ...base,\n type: 'frame',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n frameName: shape.frameName,\n fillStyle: shape.fillStyle || 'transparent',\n fillColor: shape.fillColor || '#1e1e28',\n gridSize: shape.gridSize || 20,\n gridColor: shape.gridColor || 'rgba(255,255,255,0.06)',\n options: cloneOptions(shape.options),\n // Issue #24 bug #10: filter out null / undefined / shapeID-less\n // children. A stale reference would serialize as `null` and the\n // load path would skip it (logging a misleading \"missing shape\"\n // warning) \u2014 but also previously skewed the order tracking.\n containedShapeIDs: shape.containedShapes\n ? Array.from(shape.containedShapes)\n .filter(s => s && s.shapeID)\n .map(s => s.shapeID)\n : [],\n };\n\n case 'text': {\n const group = shape.group;\n return {\n ...base,\n type: 'text',\n x: shape.x, y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML,\n };\n }\n\n case 'code': {\n const group = shape.group;\n return {\n ...base,\n type: 'code',\n x: shape.x, y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML,\n };\n }\n\n case 'image': {\n const el = shape.element;\n return {\n ...base,\n type: 'image',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n href: el.getAttribute('href') || el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || '',\n };\n }\n\n case 'icon': {\n const el = shape.element;\n return {\n ...base,\n type: 'icon',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n elementHTML: el.cloneNode(true).outerHTML,\n viewboxWidth: parseFloat(el.getAttribute('data-viewbox-width')) || 24,\n viewboxHeight: parseFloat(el.getAttribute('data-viewbox-height')) || 24,\n };\n }\n\n default:\n console.warn('[SceneSerializer] Unknown shape type:', shape.shapeName);\n return null;\n }\n}\n\n// ============================================================\n// DESERIALIZE: Create a shape from saved data\n// ============================================================\nfunction deserializeShape(data) {\n const svgEl = window.svg;\n if (!svgEl) return null;\n const ns = 'http://www.w3.org/2000/svg';\n\n switch (data.type) {\n case 'rectangle': {\n const shape = new Rectangle(data.x, data.y, data.width, data.height, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'circle': {\n const shape = new Circle(data.x, data.y, data.rx, data.ry, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'line': {\n const shape = new Line(data.startPoint, data.endPoint, data.options || {});\n if (data.controlPoint) shape.controlPoint = data.controlPoint;\n if (data.isCurved) shape.isCurved = data.isCurved;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'arrow': {\n const shape = new Arrow(data.startPoint, data.endPoint, data.options || {});\n if (data.controlPoint1) shape.controlPoint1 = data.controlPoint1;\n if (data.controlPoint2) shape.controlPoint2 = data.controlPoint2;\n if (data.arrowOutlineStyle) shape.arrowOutlineStyle = data.arrowOutlineStyle;\n if (data.arrowHeadStyle) shape.arrowHeadStyle = data.arrowHeadStyle;\n if (data.arrowCurved) shape.arrowCurved = data.arrowCurved;\n if (data.arrowCurveAmount) shape.arrowCurveAmount = data.arrowCurveAmount;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'freehandStroke': {\n const shape = new FreehandStroke(data.points, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'frame': {\n const frameOpts = { ...(data.options || {}), frameName: data.frameName || 'Frame' };\n if (data.fillStyle) frameOpts.fillStyle = data.fillStyle;\n if (data.fillColor) frameOpts.fillColor = data.fillColor;\n if (data.gridSize) frameOpts.gridSize = data.gridSize;\n if (data.gridColor) frameOpts.gridColor = data.gridColor;\n const shape = new Frame(data.x, data.y, data.width, data.height, frameOpts);\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n shape.draw();\n return shape;\n }\n\n case 'text': {\n if (!data.groupHTML) return null;\n const parser = new DOMParser();\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.groupHTML}</svg>`, 'image/svg+xml');\n const group = doc.querySelector('g');\n if (!group) return null;\n const imported = svgEl.ownerDocument.importNode(group, true);\n svgEl.appendChild(imported);\n const shape = new TextShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'code': {\n if (!data.groupHTML) return null;\n const parser = new DOMParser();\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.groupHTML}</svg>`, 'image/svg+xml');\n const group = doc.querySelector('g');\n if (!group) return null;\n const imported = svgEl.ownerDocument.importNode(group, true);\n svgEl.appendChild(imported);\n const shape = new CodeShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'image': {\n const imgEl = document.createElementNS(ns, 'image');\n imgEl.setAttribute('x', data.x);\n imgEl.setAttribute('y', data.y);\n imgEl.setAttribute('width', data.width);\n imgEl.setAttribute('height', data.height);\n imgEl.setAttribute('href', data.href);\n imgEl.setAttribute('preserveAspectRatio', 'none');\n svgEl.appendChild(imgEl);\n const shape = new ImageShape(imgEl);\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'icon': {\n if (!data.elementHTML) return null;\n const parser = new DOMParser();\n // Wrap in <svg> so the parser treats the <g> as a valid child, not a document root\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.elementHTML}</svg>`, 'image/svg+xml');\n const iconGroup = doc.querySelector('g');\n if (!iconGroup) return null;\n const imported = svgEl.ownerDocument.importNode(iconGroup, true);\n svgEl.appendChild(imported);\n const shape = new IconShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n default:\n console.warn('[SceneSerializer] Unknown type:', data.type);\n return null;\n }\n}\n\n// ============================================================\n// SAVE: Serialize entire scene to .lixsketch JSON\n// ============================================================\nexport function saveScene(workspaceName = 'Untitled') {\n const allShapes = window.shapes || [];\n const serialized = [];\n\n // Issue #24 bug #10: rebuild containment from each shape's own\n // `parentFrame` ref before serialising. The `containedShapes` array\n // on the frame side drifts over time (eraser, partial deletes, drag\n // out + drag back, etc.), and a missing entry there means the child\n // gets serialised as a top-level shape and the frame restores empty.\n // Each shape knows its own parent, so we trust THAT and override the\n // frame's array at save time.\n const childrenByFrame = new Map();\n for (const s of allShapes) {\n if (s && s.parentFrame && s.shapeID && s !== s.parentFrame) {\n const arr = childrenByFrame.get(s.parentFrame.shapeID) || [];\n arr.push(s.shapeID);\n childrenByFrame.set(s.parentFrame.shapeID, arr);\n }\n }\n\n for (const shape of allShapes) {\n const data = serializeShape(shape);\n if (!data) continue;\n if (data.type === 'frame' && shape.shapeID && childrenByFrame.has(shape.shapeID)) {\n const merged = new Set(data.containedShapeIDs || []);\n for (const id of childrenByFrame.get(shape.shapeID)) merged.add(id);\n data.containedShapeIDs = Array.from(merged);\n }\n serialized.push(data);\n }\n\n const scene = {\n format: 'lixsketch',\n version: FORMAT_VERSION,\n sessionID: getSessionID(),\n name: workspaceName,\n createdAt: new Date().toISOString(),\n viewport: window.currentViewBox ? { ...window.currentViewBox } : null,\n zoom: window.currentZoom || 1,\n shapes: serialized,\n };\n\n return scene;\n}\n\n// ============================================================\n// LOAD: Deserialize .lixsketch JSON and recreate scene\n// ============================================================\nexport function loadScene(sceneData) {\n if (!sceneData || sceneData.format !== 'lixsketch') {\n console.error('[SceneSerializer] Invalid scene format');\n return false;\n }\n\n // Clear current scene\n const svgEl = window.svg;\n if (!svgEl) return false;\n\n // Remove all existing shape DOM elements\n const existingShapes = window.shapes || [];\n existingShapes.forEach(shape => {\n // For frames, clean up clipGroup and clipPath too\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n if (shape.group && shape.group.parentNode) {\n shape.group.parentNode.removeChild(shape.group);\n } else if (shape.element && shape.element.parentNode) {\n shape.element.parentNode.removeChild(shape.element);\n }\n });\n\n // Clear arrays IN PLACE \u2014 tool modules hold direct references to these\n // arrays from import-time, so replacing them breaks interactivity.\n if (window.shapes) window.shapes.length = 0; else window.shapes = [];\n window.currentShape = null;\n if (window.historyStack) window.historyStack.length = 0; else window.historyStack = [];\n if (window.redoStack) window.redoStack.length = 0; else window.redoStack = [];\n\n // Build ID -> shape map for frame containment and arrow attachments\n const idMap = new Map();\n\n // First pass: create all shapes (frames first to allow containment)\n const frameData = sceneData.shapes.filter(s => s.type === 'frame');\n const otherData = sceneData.shapes.filter(s => s.type !== 'frame');\n\n // Create frames first\n for (const data of frameData) {\n const shape = deserializeShape(data);\n if (shape) {\n // Restore group membership if present.\n if (data.groupId) shape.groupId = data.groupId;\n restoreDocBlockLinks(shape, data);\n window.shapes.push(shape);\n if (data.shapeID) idMap.set(data.shapeID, shape);\n }\n }\n\n // Create all other shapes\n for (const data of otherData) {\n const shape = deserializeShape(data);\n if (shape) {\n if (data.groupId) shape.groupId = data.groupId;\n restoreDocBlockLinks(shape, data);\n window.shapes.push(shape);\n if (data.shapeID) idMap.set(data.shapeID, shape);\n }\n }\n\n // Second pass: restore frame containment\n for (const data of frameData) {\n const frame = idMap.get(data.shapeID);\n if (frame && data.containedShapeIDs && data.containedShapeIDs.length > 0) {\n for (const childID of data.containedShapeIDs) {\n const child = idMap.get(childID);\n if (!child) {\n console.warn(`[SceneSerializer] Frame \"${data.frameName}\" references missing shape: ${childID}`);\n continue;\n }\n try {\n if (typeof frame.addShapeToFrame === 'function') {\n frame.addShapeToFrame(child);\n } else {\n // Fallback: manually set containment\n frame.containedShapes.push(child);\n child.parentFrame = frame;\n }\n } catch (err) {\n console.warn(`[SceneSerializer] Failed to restore containment for ${childID} in frame ${data.shapeID}:`, err);\n // Fallback: at least set the reference\n if (!frame.containedShapes.includes(child)) {\n frame.containedShapes.push(child);\n }\n child.parentFrame = frame;\n }\n }\n }\n }\n\n // Third pass: restore arrow attachments\n for (const data of sceneData.shapes) {\n if (data.type === 'arrow') {\n const arrow = idMap.get(data.shapeID);\n if (!arrow) continue;\n if (data.startAttachmentID) {\n const target = idMap.get(data.startAttachmentID);\n if (target && arrow.setStartAttachment) arrow.setStartAttachment(target);\n }\n if (data.endAttachmentID) {\n const target = idMap.get(data.endAttachmentID);\n if (target && arrow.setEndAttachment) arrow.setEndAttachment(target);\n }\n }\n }\n\n // \u2500\u2500 Fourth pass: frame containment reconciliation (issue #24 bug #10) \u2500\u2500\n //\n // The pass above attaches each child via `frame.addShapeToFrame(child)`,\n // which is supposed to move the child's <g> into the frame's clipGroup.\n // In practice LixScript-rendered scenes were reloading with empty\n // frames \u2014 children present in the shapes array, frame box drawn, but\n // the children's <g> elements stranded at the svg root (so visually\n // they look orphaned). The cause varies (transient `isBeingMovedByFrame`\n // flag carried over from save time, ordering glitches when nested\n // frames are restored, etc.). Rather than chase the source, repair the\n // DOM state here from the authoritative `containedShapes` array.\n for (const data of frameData) {\n const frame = idMap.get(data.shapeID);\n if (!frame) continue;\n\n // Clear stale flags that suppress DOM mutation inside addShapeToFrame.\n delete frame.isBeingMovedByFrame;\n delete frame.isDraggedOutTemporarily;\n\n // Ensure the frame's own clipGroup is direct child of svg \u2014 sub-frames\n // that didn't get re-parented yet are handled in the next loop.\n if (frame.clipGroup && frame.clipGroup.parentNode !== svgEl) {\n svgEl.appendChild(frame.clipGroup);\n }\n\n for (const child of frame.containedShapes || []) {\n if (!child) continue;\n delete child.isBeingMovedByFrame;\n delete child.isDraggedOutTemporarily;\n\n const el = child.group || child.element;\n if (el && el.parentNode !== frame.clipGroup) {\n if (el.parentNode) el.parentNode.removeChild(el);\n frame.clipGroup.appendChild(el);\n }\n // Sub-frames also carry their own clipGroup \u2014 nest it.\n if (child.shapeName === 'frame' && child.clipGroup\n && child.clipGroup.parentNode !== frame.clipGroup) {\n if (child.clipGroup.parentNode) child.clipGroup.parentNode.removeChild(child.clipGroup);\n frame.clipGroup.appendChild(child.clipGroup);\n }\n // Authoritative parent ref \u2014 `addShapeToFrame` should already\n // have set this but the no-op early return when the child was\n // already in containedShapes skips it.\n child.parentFrame = frame;\n }\n\n // Force the clip rect + visual to match. Some saved frames came\n // through with a stale clipRect from before the resize that lost\n // the children visually.\n if (typeof frame.updateClipPath === 'function') frame.updateClipPath();\n if (typeof frame.draw === 'function') {\n try { frame.draw(); } catch (err) { console.warn('[SceneSerializer] frame redraw failed:', err); }\n }\n }\n\n // Restore viewport\n if (sceneData.viewport && svgEl) {\n const vb = sceneData.viewport;\n window.currentViewBox = { ...vb };\n svgEl.setAttribute('viewBox', `${vb.x} ${vb.y} ${vb.width} ${vb.height}`);\n }\n if (sceneData.zoom) {\n window.currentZoom = sceneData.zoom;\n }\n\n console.log(`[SceneSerializer] Loaded ${window.shapes.length} shapes from \"${sceneData.name}\"`);\n window.dispatchEvent(new CustomEvent('lix-doc-canvas-links-changed'));\n\n // Re-sync tool flags so shapes are interactable after restore\n if (window.__sketchEngine && typeof window.__sketchEngine.setActiveTool === 'function') {\n const store = window.__sketchStoreApi;\n const currentTool = store ? store.getState().activeTool : 'select';\n window.__sketchEngine.setActiveTool(currentTool);\n } else {\n // Fallback: ensure selection tool is active\n window.isSelectionToolActive = true;\n }\n\n return true;\n}\n\n// ============================================================\n// DOWNLOAD: Trigger browser download of .lixsketch file\n// ============================================================\nexport function downloadScene(workspaceName = 'Untitled') {\n const scene = saveScene(workspaceName);\n const json = JSON.stringify(scene, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n\n const a = document.createElement('a');\n a.href = url;\n a.download = `${workspaceName.replace(/[^a-zA-Z0-9_-]/g, '_')}.lixjson`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n\n// ============================================================\n// UPLOAD: Open file picker and load .lixsketch file\n// ============================================================\n// Validate scene JSON structure before loading\nexport function validateScene(data) {\n if (!data || typeof data !== 'object') return { valid: false, error: 'Not a valid JSON object' };\n if (data.format !== 'lixsketch') return { valid: false, error: 'Not a LixSketch scene file (missing format field)' };\n if (!data.version || data.version > FORMAT_VERSION) return { valid: false, error: `Unsupported version: ${data.version}` };\n if (!Array.isArray(data.shapes)) return { valid: false, error: 'Invalid scene: missing shapes array' };\n return {\n valid: true,\n name: data.name || 'Untitled',\n shapeCount: data.shapes.length,\n sessionID: data.sessionID || null,\n createdAt: data.createdAt || null,\n };\n}\n\nexport function uploadScene() {\n return new Promise((resolve, reject) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.lixjson,.json';\n input.onchange = (e) => {\n const file = e.target.files[0];\n if (!file) return resolve(false);\n\n const reader = new FileReader();\n reader.onload = (ev) => {\n try {\n const data = JSON.parse(ev.target.result);\n const validation = validateScene(data);\n if (!validation.valid) {\n console.error('[SceneSerializer] Invalid file:', validation.error);\n resolve({ success: false, error: validation.error });\n return;\n }\n resetSessionID(); // New session for loaded scene\n const result = loadScene(data);\n resolve({ success: result, validation });\n } catch (err) {\n console.error('[SceneSerializer] Failed to parse file:', err);\n resolve({ success: false, error: 'Failed to parse JSON file' });\n }\n };\n reader.readAsText(file);\n };\n input.click();\n });\n}\n\n// ============================================================\n// EXPORT as PNG\n// ============================================================\nexport function exportAsPNG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n // Remove selection UI elements\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const canvas = document.createElement('canvas');\n const vb = svgEl.viewBox.baseVal;\n canvas.width = vb.width * 2; // 2x for retina\n canvas.height = vb.height * 2;\n const ctx = canvas.getContext('2d');\n ctx.scale(2, 2);\n\n const img = new Image();\n const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n img.onload = () => {\n // Draw dark background\n ctx.fillStyle = '#121212';\n ctx.fillRect(0, 0, vb.width, vb.height);\n ctx.drawImage(img, 0, 0, vb.width, vb.height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(blob => {\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = 'lixsketch-export.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n }, 'image/png');\n };\n img.src = url;\n}\n\n// ============================================================\n// COPY to clipboard as PNG\n// ============================================================\nexport function copyAsPNG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const canvas = document.createElement('canvas');\n const vb = svgEl.viewBox.baseVal;\n canvas.width = vb.width * 2;\n canvas.height = vb.height * 2;\n const ctx = canvas.getContext('2d');\n ctx.scale(2, 2);\n\n const img = new Image();\n const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n img.onload = () => {\n ctx.fillStyle = '#121212';\n ctx.fillRect(0, 0, vb.width, vb.height);\n ctx.drawImage(img, 0, 0, vb.width, vb.height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(blob => {\n if (!blob) return;\n navigator.clipboard.write([\n new ClipboardItem({ 'image/png': blob })\n ]).catch(err => console.warn('[SceneSerializer] Clipboard write failed:', err));\n }, 'image/png');\n };\n img.src = url;\n}\n\n// ============================================================\n// COPY to clipboard as SVG\n// ============================================================\nexport function copyAsSVG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n navigator.clipboard.writeText(svgData)\n .catch(err => console.warn('[SceneSerializer] Clipboard write failed:', err));\n}\n\n// ============================================================\n// EXPORT as PDF (uses browser print)\n// ============================================================\nexport function exportAsPDF() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const printWindow = window.open('', '_blank');\n printWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head><title>LixSketch Export</title>\n <style>\n body { margin: 0; background: #121212; display: flex; align-items: center; justify-content: center; min-height: 100vh; }\n svg { max-width: 100vw; max-height: 100vh; }\n @media print { body { background: white; } }\n </style>\n </head>\n <body>${svgData}</body>\n </html>\n `);\n printWindow.document.close();\n printWindow.focus();\n setTimeout(() => printWindow.print(), 500);\n}\n\n// ============================================================\n// RESET: Clear the entire canvas\n// ============================================================\nexport function resetCanvas() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n // Remove all shape DOM elements + frame clipGroups/clipPaths\n const existingShapes = window.shapes || [];\n existingShapes.forEach(shape => {\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n if (shape.group && shape.group.parentNode) {\n shape.group.parentNode.removeChild(shape.group);\n } else if (shape.element && shape.element.parentNode) {\n shape.element.parentNode.removeChild(shape.element);\n }\n });\n\n // Remove selection UI\n svgEl.querySelectorAll(\n '.selection-outline, .resize-anchor, .rotation-anchor, [data-selection]'\n ).forEach(el => el.remove());\n\n // Clear arrays IN PLACE (same reason as loadScene)\n if (window.shapes) window.shapes.length = 0; else window.shapes = [];\n window.currentShape = null;\n if (window.historyStack) window.historyStack.length = 0; else window.historyStack = [];\n if (window.redoStack) window.redoStack.length = 0; else window.redoStack = [];\n\n if (typeof window.clearAllSelections === 'function') {\n window.clearAllSelections();\n }\n if (typeof window.disableAllSideBars === 'function') {\n window.disableAllSideBars();\n }\n\n // Clear auto-save (both legacy and session-scoped keys)\n try {\n localStorage.removeItem('lixsketch-autosave');\n localStorage.removeItem('lixsketch-autosave-meta');\n const sid = window.__sessionID;\n if (sid) {\n localStorage.removeItem(`lixsketch-autosave-${sid}`);\n localStorage.removeItem(`lixsketch-autosave-meta-${sid}`);\n }\n } catch (_) {}\n\n console.log('[SceneSerializer] Canvas reset');\n if (typeof window.__collabSceneChanged === 'function') {\n window.__collabSceneChanged();\n }\n}\n\n// ============================================================\n// FIND: Search for text content on the canvas\n// ============================================================\nexport function findTextOnCanvas(query) {\n const allShapes = window.shapes || [];\n if (!query || query.trim() === '') return [];\n\n const lowerQuery = query.toLowerCase();\n const results = [];\n\n for (const shape of allShapes) {\n let textContent = '';\n\n if (shape.shapeName === 'text' || shape.shapeName === 'code') {\n const group = shape.group;\n if (group) {\n // Get all text content from SVG text/tspan elements\n const textEls = group.querySelectorAll('text, tspan');\n textEls.forEach(el => {\n if (el.textContent) textContent += el.textContent + ' ';\n });\n // Also check foreignObject content\n const foreignEls = group.querySelectorAll('foreignObject *');\n foreignEls.forEach(el => {\n if (el.textContent) textContent += el.textContent + ' ';\n });\n }\n } else if (shape.shapeName === 'frame') {\n textContent = shape.frameName || '';\n }\n\n textContent = textContent.trim();\n if (textContent && textContent.toLowerCase().includes(lowerQuery)) {\n results.push({\n shape,\n text: textContent,\n type: shape.shapeName,\n x: shape.x || 0,\n y: shape.y || 0,\n });\n }\n }\n\n return results;\n}\n\n// ============================================================\n// Initialize bridge for React components\n// ============================================================\nexport function initSceneSerializer() {\n window.__sceneSerializer = {\n save: saveScene,\n load: loadScene,\n download: downloadScene,\n upload: uploadScene,\n exportPNG: exportAsPNG,\n exportPDF: exportAsPDF,\n copyAsPNG,\n copyAsSVG,\n resetCanvas,\n findText: findTextOnCanvas,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }