@wix/astro 0.2.13 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/TailwindEditor/EditorPanel.d.ts +11 -0
- package/dist/components/TailwindEditor/EditorPanel.js +86 -0
- package/dist/components/TailwindEditor/dev-toolbar-app.d.ts +14 -0
- package/dist/components/TailwindEditor/dev-toolbar-app.js +39 -0
- package/dist/components/TailwindEditor/dev-toolbar.d.ts +13 -0
- package/dist/components/TailwindEditor/dev-toolbar.js +547 -0
- package/dist/components/TailwindEditor/index.d.ts +5 -0
- package/dist/components/TailwindEditor/index.js +155 -0
- package/dist/components/TailwindEditor/integration.d.ts +3 -0
- package/dist/components/TailwindEditor/integration.js +18 -0
- package/dist/components/TailwindEditor/types.d.ts +35 -0
- package/dist/components/TailwindEditor/types.js +2 -0
- package/dist/components/TailwindEditor/utils.d.ts +22 -0
- package/dist/components/TailwindEditor/utils.js +234 -0
- package/dist/components/login-helpers/bi-header-generator.d.ts +11 -0
- package/dist/components/login-helpers/bi-header-generator.js +18 -0
- package/dist/components/login-helpers/iframeUtils.d.ts +4 -0
- package/dist/components/login-helpers/iframeUtils.js +44 -0
- package/dist/components/login-helpers/login-helpers.d.ts +39 -0
- package/dist/components/login-helpers/login-helpers.js +117 -0
- package/dist/dev-toolbar/Editor/EditorPanel.d.ts +14 -0
- package/dist/dev-toolbar/Editor/EditorPanel.js +1273 -0
- package/dist/dev-toolbar/Editor/classes.d.ts +12 -0
- package/dist/dev-toolbar/Editor/classes.js +271 -0
- package/dist/dev-toolbar/Editor/dnd.d.ts +34 -0
- package/dist/dev-toolbar/Editor/dnd.js +1161 -0
- package/dist/dev-toolbar/Editor/index.d.ts +5 -0
- package/dist/dev-toolbar/Editor/index.js +136 -0
- package/dist/dev-toolbar/Editor/types.d.ts +42 -0
- package/dist/dev-toolbar/Editor/types.js +2 -0
- package/dist/dev-toolbar/agent-chat.d.ts +14 -0
- package/dist/dev-toolbar/agent-chat.js +362 -0
- package/dist/dev-toolbar/ai-agent-server.d.ts +1 -0
- package/dist/dev-toolbar/ai-agent-server.js +174 -0
- package/dist/dev-toolbar/ai-agent.d.ts +2 -0
- package/dist/dev-toolbar/ai-agent.js +171 -0
- package/dist/dev-toolbar/api-key-form.d.ts +7 -0
- package/dist/dev-toolbar/api-key-form.js +138 -0
- package/dist/dev-toolbar/astro-toolbar.d.ts +1156 -0
- package/dist/dev-toolbar/astro-toolbar.js +29 -0
- package/dist/dev-toolbar/editor.d.ts +2 -0
- package/dist/dev-toolbar/editor.js +19 -0
- package/dist/integration.d.ts +3 -1
- package/dist/integration.js +41 -10
- package/dist/routes/auth/callback.js +1 -1
- package/dist/src/auth-context.d.ts +5 -0
- package/dist/src/auth-context.js +3 -0
- package/dist/src/client.d.ts +15 -0
- package/dist/src/client.js +17 -0
- package/dist/src/entrypoints/server.d.ts +13 -0
- package/dist/src/entrypoints/server.js +37 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +5 -0
- package/dist/src/integration.d.ts +8 -0
- package/dist/src/integration.js +229 -0
- package/dist/src/loaders/blog.d.ts +2 -0
- package/dist/src/loaders/blog.js +49 -0
- package/dist/src/loaders/index.d.ts +2 -0
- package/dist/src/loaders/index.js +3 -0
- package/dist/src/middleware.d.ts +2 -0
- package/dist/src/middleware.js +90 -0
- package/dist/src/routes/auth/callback.d.ts +3 -0
- package/dist/src/routes/auth/callback.js +53 -0
- package/dist/src/routes/auth/constants.d.ts +5 -0
- package/dist/src/routes/auth/constants.js +6 -0
- package/dist/src/routes/auth/login.d.ts +3 -0
- package/dist/src/routes/auth/login.js +27 -0
- package/dist/src/routes/auth/logout-callback.d.ts +3 -0
- package/dist/src/routes/auth/logout-callback.js +10 -0
- package/dist/src/routes/auth/logout.d.ts +3 -0
- package/dist/src/routes/auth/logout.js +11 -0
- package/dist/src/routes/auth/runtime.d.ts +5 -0
- package/dist/src/routes/auth/runtime.js +8 -0
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.js +9 -0
- package/dist/src/vite-plugins/sdk-context.d.ts +4 -0
- package/dist/src/vite-plugins/sdk-context.js +68 -0
- package/dist/vite-plugins/sdk-context.d.ts +3 -1
- package/dist/vite-plugins/sdk-context.js +51 -70
- package/package.json +6 -3
|
@@ -0,0 +1,1161 @@
|
|
|
1
|
+
import { useDragLoader } from "../../hooks/use-loader-context.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
// Store the loader functions for global access
|
|
4
|
+
let showDragLoader = null;
|
|
5
|
+
let hideDragLoader = null;
|
|
6
|
+
// Hook to initialize the loader functions
|
|
7
|
+
export function useDragLoaderInit() {
|
|
8
|
+
const { showDragLoader: show, hideDragLoader: hide } = useDragLoader();
|
|
9
|
+
// Update the global references
|
|
10
|
+
showDragLoader = show;
|
|
11
|
+
hideDragLoader = hide;
|
|
12
|
+
}
|
|
13
|
+
// Constants
|
|
14
|
+
var EditorAttributes;
|
|
15
|
+
(function (EditorAttributes) {
|
|
16
|
+
EditorAttributes["DATA_PICASSO_DRAGGING"] = "data-picasso-dragging";
|
|
17
|
+
EditorAttributes["DATA_PICASSO_DRAG_SAVED_STYLE"] = "data-picasso-drag-saved-style";
|
|
18
|
+
EditorAttributes["DATA_PICASSO_DRAG_DIRECTION"] = "data-picasso-drag-direction";
|
|
19
|
+
EditorAttributes["DATA_PICASSO_DRAG_START_POSITION"] = "data-picasso-drag-start-position";
|
|
20
|
+
EditorAttributes["DATA_PICASSO_ORIGINAL_PARENT"] = "data-picasso-original-parent";
|
|
21
|
+
})(EditorAttributes || (EditorAttributes = {}));
|
|
22
|
+
// Add this near the top with other constants
|
|
23
|
+
const VALID_DROP_TARGET_CLASS = "picasso-valid-drop-target";
|
|
24
|
+
const INVALID_DROP_TARGET_CLASS = "picasso-invalid-drop-target";
|
|
25
|
+
// Store component move instructions internally
|
|
26
|
+
let componentMoveInstructions = [];
|
|
27
|
+
// Function to create a component move instruction
|
|
28
|
+
function createComponentMoveChange(component, sourceFile, fromLine, toLine, parentNode, parentId, toFile, originalParentNode, originalParentId) {
|
|
29
|
+
// Create the base instruction
|
|
30
|
+
const instruction = {
|
|
31
|
+
type: "componentMove",
|
|
32
|
+
timestamp: new Date().toISOString(),
|
|
33
|
+
component,
|
|
34
|
+
toLine,
|
|
35
|
+
parentNode,
|
|
36
|
+
parentId,
|
|
37
|
+
originalParentNode,
|
|
38
|
+
originalParentId
|
|
39
|
+
};
|
|
40
|
+
// For cross-file moves, add toFile property
|
|
41
|
+
if (toFile && toFile !== sourceFile) {
|
|
42
|
+
// Use type assertion to add toFile to the instruction
|
|
43
|
+
// This works around TypeScript errors if the types.tsx update hasn't been picked up
|
|
44
|
+
instruction.toFile = toFile;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
file: sourceFile,
|
|
48
|
+
line: fromLine,
|
|
49
|
+
instruction,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Function to add a component move change to the list
|
|
53
|
+
function addComponentMoveChange(change) {
|
|
54
|
+
componentMoveInstructions.push(change);
|
|
55
|
+
console.log("Component move change added:", change);
|
|
56
|
+
}
|
|
57
|
+
// Export a function to get all component move changes
|
|
58
|
+
export function getComponentMoveChanges() {
|
|
59
|
+
return [...componentMoveInstructions];
|
|
60
|
+
}
|
|
61
|
+
// Export a function to clear component move changes
|
|
62
|
+
export function clearComponentMoveChanges() {
|
|
63
|
+
componentMoveInstructions = [];
|
|
64
|
+
}
|
|
65
|
+
// Helper functions
|
|
66
|
+
function elementFromDomId(domId) {
|
|
67
|
+
return document.getElementById(domId);
|
|
68
|
+
}
|
|
69
|
+
function calculateMouseOffset(el, mouseX, mouseY) {
|
|
70
|
+
const rect = el.getBoundingClientRect();
|
|
71
|
+
return {
|
|
72
|
+
x: mouseX - rect.left,
|
|
73
|
+
y: mouseY - rect.top,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function isValidHtmlElement(node) {
|
|
77
|
+
return node instanceof HTMLElement;
|
|
78
|
+
}
|
|
79
|
+
function createStub(el) {
|
|
80
|
+
const stub = document.createElement("div");
|
|
81
|
+
stub.id = "drag-stub";
|
|
82
|
+
stub.style.height = `${el.offsetHeight}px`;
|
|
83
|
+
stub.style.width = `${el.offsetWidth}px`;
|
|
84
|
+
stub.style.background = "#e0e0e0";
|
|
85
|
+
stub.style.border = "2px dashed #aaa";
|
|
86
|
+
stub.style.borderRadius = "4px";
|
|
87
|
+
// Insert stub before the element being dragged
|
|
88
|
+
if (el.parentElement) {
|
|
89
|
+
el.parentElement.insertBefore(stub, el);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Add a variable to track the last insertion point to prevent jitter
|
|
93
|
+
let lastInsertionTarget = null;
|
|
94
|
+
let lastUpdateTime = 0;
|
|
95
|
+
const JITTER_THRESHOLD_PX = 20; // Minimum distance in pixels to trigger a change
|
|
96
|
+
const DEBOUNCE_DELAY = 150; // Minimum delay between updates in milliseconds
|
|
97
|
+
// Add variables to track last position for smooth movement
|
|
98
|
+
let lastDragX = 0;
|
|
99
|
+
let lastDragY = 0;
|
|
100
|
+
const MOVEMENT_SMOOTHING = 0.5; // Higher = less smoothing but more responsive
|
|
101
|
+
// Add a variable to store the last stable insertion index
|
|
102
|
+
let lastStableIndex = -1;
|
|
103
|
+
let stablePositionCount = 0;
|
|
104
|
+
const STABILITY_THRESHOLD = 3; // Number of consistent positions before committing
|
|
105
|
+
function moveStub(el, x, y) {
|
|
106
|
+
const stub = document.getElementById("drag-stub");
|
|
107
|
+
if (!stub)
|
|
108
|
+
return;
|
|
109
|
+
// Check if we're over a different container
|
|
110
|
+
const dropTarget = getDropTargetAt(x, y, el);
|
|
111
|
+
// If no drop target found, use the original parent
|
|
112
|
+
const originalParentId = el.getAttribute(EditorAttributes.DATA_PICASSO_ORIGINAL_PARENT);
|
|
113
|
+
const originalParent = originalParentId ? document.getElementById(originalParentId) : null;
|
|
114
|
+
const currentParent = stub.parentElement;
|
|
115
|
+
// Determine which container to use (drop target or original parent)
|
|
116
|
+
let targetContainer = dropTarget || (originalParent || el.parentElement);
|
|
117
|
+
// CRITICAL SAFETY CHECK: Never allow the stub to be its own container
|
|
118
|
+
// This prevents "Failed to execute 'appendChild' on 'Node': The new child element contains the parent" error
|
|
119
|
+
if (targetContainer === stub) {
|
|
120
|
+
console.error("Prevented circular reference: stub trying to append to itself");
|
|
121
|
+
targetContainer = originalParent || el.parentElement;
|
|
122
|
+
// If we still have an invalid container, abort the operation
|
|
123
|
+
if (!targetContainer || targetContainer === stub) {
|
|
124
|
+
console.error("Cannot find valid container for stub, aborting drag operation");
|
|
125
|
+
removeStub();
|
|
126
|
+
endAllDrag();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Additional safety check to prevent circular references:
|
|
131
|
+
// 1. Ensure target container is not null
|
|
132
|
+
// 2. Ensure it's not the element itself
|
|
133
|
+
// 3. Ensure it's not a descendant of the element
|
|
134
|
+
if (!targetContainer ||
|
|
135
|
+
targetContainer === el ||
|
|
136
|
+
isChildOf(targetContainer, el)) {
|
|
137
|
+
console.warn("Prevented potential circular reference in moveStub");
|
|
138
|
+
// Fall back to the original parent as a safe option
|
|
139
|
+
targetContainer = originalParent || el.parentElement;
|
|
140
|
+
// If we still have an invalid container, abort the operation
|
|
141
|
+
if (!targetContainer || targetContainer === el || isChildOf(targetContainer, el)) {
|
|
142
|
+
console.error("Cannot find valid container for stub, aborting drag operation");
|
|
143
|
+
removeStub();
|
|
144
|
+
endAllDrag();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// If the stub isn't already in the target container, move it
|
|
149
|
+
if (targetContainer && currentParent !== targetContainer) {
|
|
150
|
+
// Remove stub from current parent
|
|
151
|
+
if (currentParent) {
|
|
152
|
+
currentParent.removeChild(stub);
|
|
153
|
+
}
|
|
154
|
+
// One more safety check before appending
|
|
155
|
+
try {
|
|
156
|
+
// Add to new container
|
|
157
|
+
targetContainer.appendChild(stub);
|
|
158
|
+
console.log("Moved stub to new container:", targetContainer.tagName, targetContainer.id);
|
|
159
|
+
// Reset stability tracking when container changes
|
|
160
|
+
lastStableIndex = -1;
|
|
161
|
+
stablePositionCount = 0;
|
|
162
|
+
// Update immediately without delay
|
|
163
|
+
lastUpdateTime = 0;
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
console.error("Error moving stub to new container:", e);
|
|
167
|
+
// If we encounter an error, clean up and end the drag
|
|
168
|
+
removeStub();
|
|
169
|
+
endAllDrag();
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// If no valid container found, don't proceed
|
|
174
|
+
if (!targetContainer)
|
|
175
|
+
return;
|
|
176
|
+
// Now position within the container
|
|
177
|
+
const children = Array.from(targetContainer.children).filter((child) => isValidHtmlElement(child) && child !== el && child !== stub);
|
|
178
|
+
// If no children to compare, stub is already in the right place
|
|
179
|
+
if (children.length === 0)
|
|
180
|
+
return;
|
|
181
|
+
// Throttle updates to prevent jitter
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
if (now - lastUpdateTime < DEBOUNCE_DELAY) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// Get layout direction
|
|
187
|
+
const direction = getDisplayDirection(targetContainer);
|
|
188
|
+
// Sort children based on their position in the document
|
|
189
|
+
children.sort((a, b) => {
|
|
190
|
+
const aRect = a.getBoundingClientRect();
|
|
191
|
+
const bRect = b.getBoundingClientRect();
|
|
192
|
+
if (direction === "row") {
|
|
193
|
+
return aRect.left - bRect.left; // Sort by X for row
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return aRect.top - bRect.top; // Sort by Y for column
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
// Find insertion point
|
|
200
|
+
let insertBefore = null;
|
|
201
|
+
let currentInsertionIndex = -1;
|
|
202
|
+
for (let i = 0; i < children.length; i++) {
|
|
203
|
+
const child = children[i];
|
|
204
|
+
const rect = child.getBoundingClientRect();
|
|
205
|
+
if (direction === "row") {
|
|
206
|
+
// For row layout, compare X position
|
|
207
|
+
if (x < rect.left + rect.width / 2) {
|
|
208
|
+
insertBefore = child;
|
|
209
|
+
currentInsertionIndex = i;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// For column layout, compare Y position
|
|
215
|
+
if (y < rect.top + rect.height / 2) {
|
|
216
|
+
insertBefore = child;
|
|
217
|
+
currentInsertionIndex = i;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// If we didn't find an insertion point, we would insert at the end
|
|
223
|
+
if (insertBefore === null) {
|
|
224
|
+
currentInsertionIndex = children.length;
|
|
225
|
+
}
|
|
226
|
+
// Stability check - only commit position changes when they've been stable for a few checks
|
|
227
|
+
if (currentInsertionIndex === lastStableIndex) {
|
|
228
|
+
stablePositionCount++;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
lastStableIndex = currentInsertionIndex;
|
|
232
|
+
stablePositionCount = 1;
|
|
233
|
+
}
|
|
234
|
+
// Only update if position has been stable for a while or if it's far from the last position
|
|
235
|
+
let needsUpdate = false;
|
|
236
|
+
if (stablePositionCount >= STABILITY_THRESHOLD) {
|
|
237
|
+
needsUpdate = true;
|
|
238
|
+
}
|
|
239
|
+
else if (insertBefore &&
|
|
240
|
+
lastInsertionTarget &&
|
|
241
|
+
insertBefore !== lastInsertionTarget) {
|
|
242
|
+
// Check if the distance between old and new position is significant
|
|
243
|
+
const insertRect = insertBefore.getBoundingClientRect();
|
|
244
|
+
const lastRect = lastInsertionTarget.getBoundingClientRect();
|
|
245
|
+
const distance = direction === "row"
|
|
246
|
+
? Math.abs(insertRect.left - lastRect.left)
|
|
247
|
+
: Math.abs(insertRect.top - lastRect.top);
|
|
248
|
+
needsUpdate = distance > JITTER_THRESHOLD_PX * 2;
|
|
249
|
+
}
|
|
250
|
+
else if (insertBefore === null && lastInsertionTarget === null) {
|
|
251
|
+
// Both null, check if stub is already at the end
|
|
252
|
+
const isAtEnd = stub.nextElementSibling === null;
|
|
253
|
+
needsUpdate = !isAtEnd;
|
|
254
|
+
}
|
|
255
|
+
else if (insertBefore !== lastInsertionTarget) {
|
|
256
|
+
// One is null and the other isn't, definitely an update
|
|
257
|
+
needsUpdate = true;
|
|
258
|
+
}
|
|
259
|
+
// Only update the DOM if necessary
|
|
260
|
+
if (needsUpdate) {
|
|
261
|
+
// Move stub to the determined position
|
|
262
|
+
if (insertBefore) {
|
|
263
|
+
// Check if we'd be moving to the same place
|
|
264
|
+
if (stub.nextElementSibling !== insertBefore) {
|
|
265
|
+
console.log("Moving stub before element:", insertBefore.tagName);
|
|
266
|
+
targetContainer.insertBefore(stub, insertBefore);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// If no insert point found, append to the end
|
|
271
|
+
if (stub.nextElementSibling !== null) {
|
|
272
|
+
console.log("Moving stub to end of container");
|
|
273
|
+
targetContainer.appendChild(stub);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Log the achieved position
|
|
277
|
+
const allChildren = Array.from(targetContainer.children);
|
|
278
|
+
const stubPosition = allChildren.indexOf(stub);
|
|
279
|
+
console.log("Stub now at position", stubPosition, "of", allChildren.length);
|
|
280
|
+
// Update tracking variables
|
|
281
|
+
lastInsertionTarget = insertBefore;
|
|
282
|
+
lastUpdateTime = now;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Reset the tracking variables when drag ends
|
|
286
|
+
function removeStub() {
|
|
287
|
+
const stub = document.getElementById("drag-stub");
|
|
288
|
+
if (stub)
|
|
289
|
+
stub.remove();
|
|
290
|
+
// Reset tracking variables
|
|
291
|
+
lastInsertionTarget = null;
|
|
292
|
+
lastUpdateTime = 0;
|
|
293
|
+
lastStableIndex = -1;
|
|
294
|
+
stablePositionCount = 0;
|
|
295
|
+
}
|
|
296
|
+
function getCurrentStubIndex(parent, draggingEl) {
|
|
297
|
+
const stub = document.getElementById("drag-stub");
|
|
298
|
+
if (!stub)
|
|
299
|
+
return -1;
|
|
300
|
+
// The stub might be in a different parent now
|
|
301
|
+
const stubParent = stub.parentElement;
|
|
302
|
+
if (!stubParent)
|
|
303
|
+
return -1;
|
|
304
|
+
// Get all children of the stub's parent, excluding the dragging element
|
|
305
|
+
const childrenWithoutDraggingEl = Array.from(stubParent.children).filter((child) => isValidHtmlElement(child) && child !== draggingEl);
|
|
306
|
+
// Find the index of the stub in this filtered list
|
|
307
|
+
const stubIndex = childrenWithoutDraggingEl.indexOf(stub);
|
|
308
|
+
// Debug logging
|
|
309
|
+
console.log("Stub parent:", stubParent.tagName, stubParent.id);
|
|
310
|
+
console.log("Filtered children length:", childrenWithoutDraggingEl.length);
|
|
311
|
+
console.log("Stub found at filtered index:", stubIndex);
|
|
312
|
+
return stubIndex;
|
|
313
|
+
}
|
|
314
|
+
function restoreElementStyle(el) {
|
|
315
|
+
const savedStyleStr = el.getAttribute(EditorAttributes.DATA_PICASSO_DRAG_SAVED_STYLE);
|
|
316
|
+
if (!savedStyleStr)
|
|
317
|
+
return;
|
|
318
|
+
try {
|
|
319
|
+
const savedStyle = JSON.parse(savedStyleStr);
|
|
320
|
+
for (const [key, value] of Object.entries(savedStyle)) {
|
|
321
|
+
if (value) {
|
|
322
|
+
el.style[key] = value;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
el.style[key] = "";
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// Ensure these critical styles are explicitly reset
|
|
329
|
+
el.style.zIndex = "";
|
|
330
|
+
el.style.opacity = "";
|
|
331
|
+
el.style.pointerEvents = "";
|
|
332
|
+
el.style.boxShadow = "";
|
|
333
|
+
el.style.transition = "";
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
console.error("Error restoring element style:", e);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function getOrAssignDomId(el) {
|
|
340
|
+
if (el.id)
|
|
341
|
+
return el.id;
|
|
342
|
+
const newId = `picasso-element-${Math.random().toString(36).substr(2, 9)}`;
|
|
343
|
+
el.id = newId;
|
|
344
|
+
return newId;
|
|
345
|
+
}
|
|
346
|
+
function getDomElement(el, deep = true) {
|
|
347
|
+
return {
|
|
348
|
+
type: el.tagName.toLowerCase(),
|
|
349
|
+
id: getOrAssignDomId(el),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function getDisplayDirection(parent) {
|
|
353
|
+
const style = window.getComputedStyle(parent);
|
|
354
|
+
if (style.display === "flex" || style.display === "inline-flex") {
|
|
355
|
+
// Check for row or row-reverse
|
|
356
|
+
if (style.flexDirection === "row" ||
|
|
357
|
+
style.flexDirection === "row-reverse") {
|
|
358
|
+
return "row";
|
|
359
|
+
}
|
|
360
|
+
// All other flex directions (column, column-reverse) are treated as column
|
|
361
|
+
}
|
|
362
|
+
// Default to column for non-flex containers or column flex
|
|
363
|
+
return "column";
|
|
364
|
+
}
|
|
365
|
+
// Add a helper for direction-aware positioning
|
|
366
|
+
function getPositionInDirection(element, parent) {
|
|
367
|
+
const direction = getDisplayDirection(parent);
|
|
368
|
+
const rect = element.getBoundingClientRect();
|
|
369
|
+
const siblings = Array.from(parent.children).filter((child) => isValidHtmlElement(child) && child !== element);
|
|
370
|
+
// Sort siblings based on their position
|
|
371
|
+
return {
|
|
372
|
+
before: siblings.filter((sibling) => {
|
|
373
|
+
const sibRect = sibling.getBoundingClientRect();
|
|
374
|
+
return direction === "row"
|
|
375
|
+
? sibRect.left < rect.left // For row direction, compare X position
|
|
376
|
+
: sibRect.top < rect.top; // For column direction, compare Y position
|
|
377
|
+
}),
|
|
378
|
+
after: siblings.filter((sibling) => {
|
|
379
|
+
const sibRect = sibling.getBoundingClientRect();
|
|
380
|
+
return direction === "row"
|
|
381
|
+
? sibRect.left >= rect.left // For row direction, compare X position
|
|
382
|
+
: sibRect.top >= rect.top; // For column direction, compare Y position
|
|
383
|
+
}),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
// Find the closest draggable element (with data-source attribute)
|
|
387
|
+
function findDraggableElement(el) {
|
|
388
|
+
// Check if current element has data-source
|
|
389
|
+
if (el.hasAttribute("data-source")) {
|
|
390
|
+
return el;
|
|
391
|
+
}
|
|
392
|
+
// Find closest parent with data-source
|
|
393
|
+
let current = el;
|
|
394
|
+
while (current && current !== document.body) {
|
|
395
|
+
if (current.hasAttribute("data-source")) {
|
|
396
|
+
return current;
|
|
397
|
+
}
|
|
398
|
+
current = current.parentElement;
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
// Hook implementation
|
|
403
|
+
export function ButtonBar({ el, onHighlight, showDragOnly = false, dragButtonClassNames }) {
|
|
404
|
+
// Add duplicate button click handler
|
|
405
|
+
async function onDuplicate(e) {
|
|
406
|
+
e.preventDefault();
|
|
407
|
+
e.stopPropagation();
|
|
408
|
+
// Find the draggable element (element with data-source or closest parent with it)
|
|
409
|
+
const draggableEl = findDraggableElement(el);
|
|
410
|
+
if (draggableEl) {
|
|
411
|
+
// Get the source location from the data-source attribute
|
|
412
|
+
const source = draggableEl.getAttribute("data-source") ||
|
|
413
|
+
draggableEl.getAttribute("data-source-main");
|
|
414
|
+
if (source) {
|
|
415
|
+
const [sourceFile, line] = source.split(":");
|
|
416
|
+
try {
|
|
417
|
+
// Send duplication change to the API
|
|
418
|
+
const response = await fetch("http://localhost:3000/api/chat/canvas/change", {
|
|
419
|
+
method: "POST",
|
|
420
|
+
headers: {
|
|
421
|
+
"Content-Type": "application/json",
|
|
422
|
+
},
|
|
423
|
+
body: JSON.stringify([
|
|
424
|
+
{
|
|
425
|
+
file: sourceFile,
|
|
426
|
+
line: parseInt(line),
|
|
427
|
+
instruction: {
|
|
428
|
+
type: "duplicate_element",
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
]),
|
|
432
|
+
});
|
|
433
|
+
if (!response.ok) {
|
|
434
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
console.error("Error duplicating element:", error);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
// Add delete button click handler
|
|
444
|
+
async function onDelete(e) {
|
|
445
|
+
e.preventDefault();
|
|
446
|
+
e.stopPropagation();
|
|
447
|
+
// Find the draggable element (element with data-source or closest parent with it)
|
|
448
|
+
const draggableEl = findDraggableElement(el);
|
|
449
|
+
if (draggableEl) {
|
|
450
|
+
// Get the source location from the data-source attribute
|
|
451
|
+
const source = draggableEl.getAttribute("data-source") ||
|
|
452
|
+
draggableEl.getAttribute("data-source-main");
|
|
453
|
+
if (source) {
|
|
454
|
+
const [sourceFile, line] = source.split(":");
|
|
455
|
+
try {
|
|
456
|
+
// Send deletion change to the API
|
|
457
|
+
const response = await fetch("http://localhost:3000/api/chat/canvas/change", {
|
|
458
|
+
method: "POST",
|
|
459
|
+
headers: {
|
|
460
|
+
"Content-Type": "application/json",
|
|
461
|
+
},
|
|
462
|
+
body: JSON.stringify([
|
|
463
|
+
{
|
|
464
|
+
file: sourceFile,
|
|
465
|
+
line: parseInt(line),
|
|
466
|
+
instruction: {
|
|
467
|
+
type: "delete_element",
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
]),
|
|
471
|
+
});
|
|
472
|
+
if (!response.ok) {
|
|
473
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
console.error("Error deleting element:", error);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
let startX = 0;
|
|
483
|
+
let startY = 0;
|
|
484
|
+
let isDragging = false;
|
|
485
|
+
let mouseOffsetX = 0;
|
|
486
|
+
let mouseOffsetY = 0;
|
|
487
|
+
function onDrag(e) {
|
|
488
|
+
e.preventDefault();
|
|
489
|
+
e.stopPropagation();
|
|
490
|
+
// Find the draggable element (element with data-source or closest parent with it)
|
|
491
|
+
const draggableEl = findDraggableElement(el);
|
|
492
|
+
// If no draggable element found, do nothing
|
|
493
|
+
if (!draggableEl) {
|
|
494
|
+
console.warn("No draggable element found with data-source attribute");
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
// Ensure element has ID for dragging
|
|
498
|
+
getOrAssignDomId(draggableEl);
|
|
499
|
+
// Store the initial mouse position
|
|
500
|
+
startX = e.clientX;
|
|
501
|
+
startY = e.clientY;
|
|
502
|
+
// Calculate mouse offset relative to the element for more accurate dragging
|
|
503
|
+
const rect = draggableEl.getBoundingClientRect();
|
|
504
|
+
mouseOffsetX = startX - rect.left;
|
|
505
|
+
mouseOffsetY = startY - rect.top;
|
|
506
|
+
// Store the mouse offset on the element for later use
|
|
507
|
+
// Store the mouse offset on the element for later use
|
|
508
|
+
draggableEl.dataset["picassoDragMouseOffset"] = JSON.stringify({
|
|
509
|
+
x: mouseOffsetX,
|
|
510
|
+
y: mouseOffsetY,
|
|
511
|
+
});
|
|
512
|
+
isDragging = true;
|
|
513
|
+
// Start the drag operation
|
|
514
|
+
startDrag(draggableEl.id);
|
|
515
|
+
const handleMove = (moveEvent) => {
|
|
516
|
+
if (!isDragging)
|
|
517
|
+
return;
|
|
518
|
+
const currentX = moveEvent.clientX;
|
|
519
|
+
const currentY = moveEvent.clientY;
|
|
520
|
+
// Pass the current mouse coordinates for positioning
|
|
521
|
+
drag(draggableEl.id, currentX, currentY);
|
|
522
|
+
};
|
|
523
|
+
const handleUp = async () => {
|
|
524
|
+
if (!isDragging)
|
|
525
|
+
return;
|
|
526
|
+
isDragging = false;
|
|
527
|
+
// Reset element label position to "absolute" to prepare for recalculation
|
|
528
|
+
const elementLabel = document.querySelector('.element-label');
|
|
529
|
+
if (elementLabel) {
|
|
530
|
+
elementLabel.style.position = "absolute";
|
|
531
|
+
}
|
|
532
|
+
const result = endDrag(draggableEl.id);
|
|
533
|
+
if (result && result.parent && result.child && result.newIndex !== -1) {
|
|
534
|
+
const parentEl = elementFromDomId(result.parent.id);
|
|
535
|
+
const childEl = elementFromDomId(result.child.id);
|
|
536
|
+
if (parentEl && childEl) {
|
|
537
|
+
const children = Array.from(parentEl.children);
|
|
538
|
+
const currentIndex = children.indexOf(childEl);
|
|
539
|
+
// Only move if needed
|
|
540
|
+
if (currentIndex !== result.newIndex) {
|
|
541
|
+
console.log("Moving element from index", currentIndex, "to", result.newIndex);
|
|
542
|
+
// Get all children without the element we're moving
|
|
543
|
+
const filteredChildren = Array.from(parentEl.children).filter((child) => child !== childEl);
|
|
544
|
+
// If the target index is at the end, we simply append
|
|
545
|
+
if (result.newIndex >= filteredChildren.length) {
|
|
546
|
+
console.log("Appending element to the end");
|
|
547
|
+
parentEl.appendChild(childEl);
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
// Otherwise, we need to insert before the element at the target index
|
|
551
|
+
// in the filtered list (which doesn't include the element we're moving)
|
|
552
|
+
const targetNode = filteredChildren[result.newIndex];
|
|
553
|
+
console.log("Inserting element before", targetNode.tagName);
|
|
554
|
+
parentEl.insertBefore(childEl, targetNode);
|
|
555
|
+
}
|
|
556
|
+
// Make sure the element is correctly positioned and selectable again
|
|
557
|
+
childEl.style.position =
|
|
558
|
+
childEl.style.position === "static"
|
|
559
|
+
? "relative"
|
|
560
|
+
: childEl.style.position;
|
|
561
|
+
childEl.style.pointerEvents = "";
|
|
562
|
+
const sourceFile = result.sourceFile;
|
|
563
|
+
const fromLine = result.fromLine;
|
|
564
|
+
// Get the target element's data-source to determine the correct toLine
|
|
565
|
+
let toLine = fromLine; // Default fallback
|
|
566
|
+
let targetFile = sourceFile; // Default to the same file for intra-file movement
|
|
567
|
+
// Get the actual element at the new position
|
|
568
|
+
const filteredChildren = Array.from(parentEl.children).filter((child) => child !== childEl);
|
|
569
|
+
if (result.newIndex < filteredChildren.length) {
|
|
570
|
+
// Get the element we're inserting before
|
|
571
|
+
const targetElement = filteredChildren[result.newIndex];
|
|
572
|
+
const targetSource = targetElement.getAttribute("data-source");
|
|
573
|
+
if (targetSource) {
|
|
574
|
+
const [targetSourceFile, targetLineStr] = targetSource.split(":");
|
|
575
|
+
targetFile = targetSourceFile; // Set the target file from the element we're inserting before
|
|
576
|
+
toLine = parseInt(targetLineStr, 10);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else if (filteredChildren.length > 0) {
|
|
580
|
+
// If we're appending at the end, get the last element's line + 1
|
|
581
|
+
const lastElement = filteredChildren[filteredChildren.length - 1];
|
|
582
|
+
const lastSource = lastElement.getAttribute("data-source");
|
|
583
|
+
if (lastSource) {
|
|
584
|
+
const [lastSourceFile, lastLineStr] = lastSource.split(":");
|
|
585
|
+
targetFile = lastSourceFile; // Set the target file from the last element
|
|
586
|
+
toLine = parseInt(lastLineStr, 10) + 1;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
// If there are no other children, try to get file info from the parent
|
|
591
|
+
const parentSource = parentEl.getAttribute("data-source");
|
|
592
|
+
if (parentSource) {
|
|
593
|
+
const [parentSourceFile] = parentSource.split(":");
|
|
594
|
+
targetFile = parentSourceFile; // Use the parent's file
|
|
595
|
+
toLine = 1; // Default to line 1 if we can't determine
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
// Check if this is a cross-file move
|
|
599
|
+
const isCrossFileMove = targetFile !== sourceFile;
|
|
600
|
+
// Create and add a component move change
|
|
601
|
+
const moveChange = createComponentMoveChange(result.child.type, sourceFile, fromLine, toLine, result.parent.type, result.parent.id, isCrossFileMove ? targetFile : undefined);
|
|
602
|
+
// Add the change
|
|
603
|
+
addComponentMoveChange(moveChange);
|
|
604
|
+
// Apply the change immediately instead of waiting for save button
|
|
605
|
+
try {
|
|
606
|
+
// Get all move changes
|
|
607
|
+
const moveChanges = getComponentMoveChanges();
|
|
608
|
+
if (moveChanges.length > 0) {
|
|
609
|
+
// Show the loader before applying changes
|
|
610
|
+
if (showDragLoader) {
|
|
611
|
+
showDragLoader("Applying change...");
|
|
612
|
+
}
|
|
613
|
+
// Send the changes to the API
|
|
614
|
+
const response = await fetch("http://localhost:3000/api/chat/canvas/change", {
|
|
615
|
+
method: "POST",
|
|
616
|
+
headers: {
|
|
617
|
+
"Content-Type": "application/json",
|
|
618
|
+
},
|
|
619
|
+
body: JSON.stringify(moveChanges),
|
|
620
|
+
});
|
|
621
|
+
if (!response.ok) {
|
|
622
|
+
console.error("Error applying drag changes:", response.status, response.statusText);
|
|
623
|
+
// Hide loader on error
|
|
624
|
+
if (hideDragLoader) {
|
|
625
|
+
hideDragLoader();
|
|
626
|
+
}
|
|
627
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
628
|
+
}
|
|
629
|
+
await response.json();
|
|
630
|
+
// Clear the move changes since they've been applied
|
|
631
|
+
clearComponentMoveChanges();
|
|
632
|
+
// Note: Don't hide the loader here
|
|
633
|
+
// The HMR detection will handle hiding the loader and reloading the page
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
console.error("Error applying drag changes:", error);
|
|
638
|
+
// Hide loader on error
|
|
639
|
+
if (hideDragLoader) {
|
|
640
|
+
hideDragLoader();
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
// Log the move
|
|
644
|
+
console.log(`Component ${result.child.type} moved ${isCrossFileMove ? `from ${sourceFile} to ${targetFile}` : `in ${sourceFile}`} from line ${fromLine} to line ${toLine}`);
|
|
645
|
+
// Re-highlight the element to restore selection UI
|
|
646
|
+
if (onHighlight) {
|
|
647
|
+
// Slight delay to ensure DOM is updated
|
|
648
|
+
setTimeout(() => {
|
|
649
|
+
onHighlight(childEl);
|
|
650
|
+
// Explicitly update the element label position
|
|
651
|
+
const elementLabel = document.querySelector('.element-label');
|
|
652
|
+
if (elementLabel) {
|
|
653
|
+
const rect = childEl.getBoundingClientRect();
|
|
654
|
+
elementLabel.style.position = "absolute";
|
|
655
|
+
elementLabel.style.left = `${window.scrollX + rect.left}px`;
|
|
656
|
+
elementLabel.style.top = `${window.scrollY + rect.top - 20}px`;
|
|
657
|
+
elementLabel.style.zIndex = "";
|
|
658
|
+
}
|
|
659
|
+
}, 10);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
// Clean up the stored data
|
|
665
|
+
delete draggableEl.dataset["picassoDragMouseOffset"];
|
|
666
|
+
document.removeEventListener("mousemove", handleMove);
|
|
667
|
+
document.removeEventListener("mouseup", handleUp);
|
|
668
|
+
};
|
|
669
|
+
document.addEventListener("mousemove", handleMove);
|
|
670
|
+
document.addEventListener("mouseup", handleUp);
|
|
671
|
+
}
|
|
672
|
+
return (React.createElement(React.Fragment, null,
|
|
673
|
+
React.createElement("button", { className: `drag-button`, onMouseDown: onDrag },
|
|
674
|
+
React.createElement("i", { className: dragButtonClassNames })),
|
|
675
|
+
!showDragOnly && (React.createElement(React.Fragment, null,
|
|
676
|
+
React.createElement("button", { className: "duplicate-button", onClick: onDuplicate }, "Duplicate"),
|
|
677
|
+
React.createElement("button", { className: "delete-button", onClick: onDelete }, "Delete")))));
|
|
678
|
+
}
|
|
679
|
+
// Add function to update visual indicators
|
|
680
|
+
function updateDropTargetVisuals(draggingElement) {
|
|
681
|
+
// Only proceed if the element is bound
|
|
682
|
+
const isBound = draggingElement.getAttribute('data-binding-same-as-rendering-component') === 'true';
|
|
683
|
+
if (!isBound) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
// Get the rendering component value of the dragging element
|
|
687
|
+
const draggingRendering = draggingElement.getAttribute('data-picasso-rendering-comp');
|
|
688
|
+
// Get all potential drop targets
|
|
689
|
+
const allDropTargets = findValidDropTargets();
|
|
690
|
+
// First, clear any existing visual indicators
|
|
691
|
+
clearDropTargetVisuals();
|
|
692
|
+
// Only highlight valid drop targets
|
|
693
|
+
allDropTargets.forEach(target => {
|
|
694
|
+
const targetRendering = target.getAttribute('data-picasso-rendering-comp');
|
|
695
|
+
// Only add visual indicator for compatible targets
|
|
696
|
+
if (draggingRendering === targetRendering) {
|
|
697
|
+
target.classList.add(VALID_DROP_TARGET_CLASS);
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
// Add function to clean up visuals
|
|
702
|
+
function clearDropTargetVisuals() {
|
|
703
|
+
// Remove visual indicators from all elements
|
|
704
|
+
document.querySelectorAll(`.${VALID_DROP_TARGET_CLASS}, .${INVALID_DROP_TARGET_CLASS}`).forEach(el => {
|
|
705
|
+
el.classList.remove(VALID_DROP_TARGET_CLASS, INVALID_DROP_TARGET_CLASS);
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
// Modify startDrag to allow panel elements
|
|
709
|
+
export function startDrag(domId) {
|
|
710
|
+
const el = elementFromDomId(domId);
|
|
711
|
+
if (!el) {
|
|
712
|
+
console.warn(`Start drag element not found: ${domId}`);
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
/* // Allow panel elements to be dragged without edit mode
|
|
716
|
+
if (!isFromPanel(el)) {
|
|
717
|
+
// Keep existing edit mode check for non-panel elements
|
|
718
|
+
const isEditMode = document.documentElement.hasAttribute('data-picasso-edit');
|
|
719
|
+
if (!isEditMode) {
|
|
720
|
+
console.warn('Not in edit mode');
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
} */
|
|
724
|
+
const parent = el.parentElement;
|
|
725
|
+
if (!parent) {
|
|
726
|
+
console.warn("Start drag parent not found");
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
// Store the original parent for reference
|
|
730
|
+
el.setAttribute(EditorAttributes.DATA_PICASSO_ORIGINAL_PARENT, getOrAssignDomId(parent));
|
|
731
|
+
const htmlChildren = Array.from(parent.children).filter(isValidHtmlElement);
|
|
732
|
+
const originalIndex = htmlChildren.indexOf(el);
|
|
733
|
+
prepareElementForDragging(el);
|
|
734
|
+
createStub(el);
|
|
735
|
+
// Store the element's initial position and dimensions for reference
|
|
736
|
+
const rect = el.getBoundingClientRect();
|
|
737
|
+
const pos = {
|
|
738
|
+
left: rect.left + window.scrollX,
|
|
739
|
+
top: rect.top + window.scrollY,
|
|
740
|
+
width: rect.width,
|
|
741
|
+
height: rect.height,
|
|
742
|
+
};
|
|
743
|
+
el.setAttribute(EditorAttributes.DATA_PICASSO_DRAG_START_POSITION, JSON.stringify(pos));
|
|
744
|
+
// Add visual indicators if element is bound
|
|
745
|
+
updateDropTargetVisuals(el);
|
|
746
|
+
return originalIndex;
|
|
747
|
+
}
|
|
748
|
+
// Add panel element handling to drag function
|
|
749
|
+
export function drag(domId, x, y) {
|
|
750
|
+
const el = elementFromDomId(domId);
|
|
751
|
+
if (!el) {
|
|
752
|
+
console.warn("Dragging element not found");
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
// Special handling for panel elements
|
|
756
|
+
/*if (isFromPanel(el)) {
|
|
757
|
+
el.style.position = "fixed";
|
|
758
|
+
el.style.pointerEvents = "none";
|
|
759
|
+
el.style.zIndex = "9999";
|
|
760
|
+
el.style.opacity = "0.8";
|
|
761
|
+
el.style.boxShadow = "0 5px 10px rgba(0,0,0,0.2)";
|
|
762
|
+
el.style.left = `${x}px`;
|
|
763
|
+
el.style.top = `${y}px`;
|
|
764
|
+
moveStub(el, x, y);
|
|
765
|
+
return;
|
|
766
|
+
}*/
|
|
767
|
+
try {
|
|
768
|
+
// Visual styling for dragged element
|
|
769
|
+
const styles = window.getComputedStyle(el);
|
|
770
|
+
// Get the stored mouse offset
|
|
771
|
+
let offsetX = 20, offsetY = 20; // Default offsets
|
|
772
|
+
try {
|
|
773
|
+
const dragData = el.dataset["picassoDragMouseOffset"];
|
|
774
|
+
if (dragData) {
|
|
775
|
+
const mouseOffset = JSON.parse(dragData);
|
|
776
|
+
offsetX = mouseOffset.x || offsetX;
|
|
777
|
+
offsetY = mouseOffset.y || offsetY;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch (e) {
|
|
781
|
+
console.error("Error parsing drag data:", e);
|
|
782
|
+
}
|
|
783
|
+
// Position the element precisely at the mouse position with offset
|
|
784
|
+
el.style.left = `${x - offsetX}px`;
|
|
785
|
+
el.style.top = `${y - offsetY}px`;
|
|
786
|
+
el.style.width = styles.width;
|
|
787
|
+
el.style.height = styles.height;
|
|
788
|
+
el.style.position = "fixed";
|
|
789
|
+
el.style.pointerEvents = "none";
|
|
790
|
+
el.style.zIndex = "9999";
|
|
791
|
+
el.style.opacity = "0.8";
|
|
792
|
+
el.style.boxShadow = "0 5px 10px rgba(0,0,0,0.2)";
|
|
793
|
+
// Remove transition to ensure instant response
|
|
794
|
+
el.style.transition = "";
|
|
795
|
+
// Update the element-label position if it exists
|
|
796
|
+
const elementLabel = document.querySelector('.element-label');
|
|
797
|
+
if (elementLabel && el.dataset["selected"] === "true") {
|
|
798
|
+
elementLabel.style.left = `${x - offsetX}px`;
|
|
799
|
+
elementLabel.style.top = `${Math.max(0, y - offsetY - 20)}px`;
|
|
800
|
+
elementLabel.style.position = "fixed";
|
|
801
|
+
elementLabel.style.zIndex = "10000"; // Ensure it's above the dragged element
|
|
802
|
+
}
|
|
803
|
+
// Calculate smoothed positions for stub positioning only
|
|
804
|
+
let smoothX = x;
|
|
805
|
+
let smoothY = y;
|
|
806
|
+
// Apply smoothing only for stub positioning to reduce jitter
|
|
807
|
+
if (lastDragX !== 0 || lastDragY !== 0) {
|
|
808
|
+
smoothX = x * MOVEMENT_SMOOTHING + lastDragX * (1 - MOVEMENT_SMOOTHING);
|
|
809
|
+
smoothY = y * MOVEMENT_SMOOTHING + lastDragY * (1 - MOVEMENT_SMOOTHING);
|
|
810
|
+
}
|
|
811
|
+
// Update last positions
|
|
812
|
+
lastDragX = smoothX;
|
|
813
|
+
lastDragY = smoothY;
|
|
814
|
+
// Try to move the stub - wrap in try/catch to prevent errors from crashing the app
|
|
815
|
+
try {
|
|
816
|
+
moveStub(el, smoothX, smoothY);
|
|
817
|
+
}
|
|
818
|
+
catch (e) {
|
|
819
|
+
console.error("Error moving stub:", e);
|
|
820
|
+
// Clean up and abort drag if there's an error
|
|
821
|
+
removeStub();
|
|
822
|
+
cleanUpElementAfterDragging(el);
|
|
823
|
+
}
|
|
824
|
+
// Update visual indicators if element is bound
|
|
825
|
+
updateDropTargetVisuals(el);
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
console.error("Error in drag function:", error);
|
|
829
|
+
// Clean up and abort if anything goes wrong
|
|
830
|
+
endAllDrag();
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
// Modify endDrag and endAllDrag to clean up visuals
|
|
834
|
+
export function endDrag(domId) {
|
|
835
|
+
// Clear visual indicators
|
|
836
|
+
clearDropTargetVisuals();
|
|
837
|
+
// Reset smoothing variables
|
|
838
|
+
lastDragX = 0;
|
|
839
|
+
lastDragY = 0;
|
|
840
|
+
const el = elementFromDomId(domId);
|
|
841
|
+
if (!el) {
|
|
842
|
+
console.warn("End drag element not found");
|
|
843
|
+
endAllDrag();
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
846
|
+
// Remove transition before cleanup to prevent visual glitches
|
|
847
|
+
if (el.style.transition) {
|
|
848
|
+
el.style.transition = "";
|
|
849
|
+
}
|
|
850
|
+
// Get the original parent ID
|
|
851
|
+
const originalParentId = el.getAttribute(EditorAttributes.DATA_PICASSO_ORIGINAL_PARENT);
|
|
852
|
+
const originalParent = originalParentId ? elementFromDomId(originalParentId) : null;
|
|
853
|
+
// Get the stub
|
|
854
|
+
const stub = document.getElementById("drag-stub");
|
|
855
|
+
if (!stub) {
|
|
856
|
+
console.warn("Stub not found");
|
|
857
|
+
cleanUpElementAfterDragging(el);
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
// Get the stub's parent (this could be different from the original parent)
|
|
861
|
+
const stubParent = stub.parentElement;
|
|
862
|
+
if (!stubParent) {
|
|
863
|
+
console.warn("Stub parent not found");
|
|
864
|
+
cleanUpElementAfterDragging(el);
|
|
865
|
+
removeStub();
|
|
866
|
+
return null;
|
|
867
|
+
}
|
|
868
|
+
// Get the stub index in its current parent
|
|
869
|
+
const stubIndex = getCurrentStubIndex(stubParent, el);
|
|
870
|
+
console.log("End drag with stub at index:", stubIndex);
|
|
871
|
+
// Clean up elements after recording the position
|
|
872
|
+
cleanUpElementAfterDragging(el);
|
|
873
|
+
if (stubIndex === -1) {
|
|
874
|
+
console.warn("Stub not found in parent element");
|
|
875
|
+
removeStub();
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
// Determine if this is a cross-container move
|
|
879
|
+
const isCrossContainerMove = originalParent !== stubParent;
|
|
880
|
+
// Get source file information from data-source attribute
|
|
881
|
+
let sourceFile;
|
|
882
|
+
let fromLine;
|
|
883
|
+
const sourceAttr = el.getAttribute("data-source");
|
|
884
|
+
if (sourceAttr) {
|
|
885
|
+
const [file, lineStr] = sourceAttr.split(":");
|
|
886
|
+
sourceFile = file;
|
|
887
|
+
fromLine = parseInt(lineStr, 10);
|
|
888
|
+
}
|
|
889
|
+
// Create result with appropriate parent information
|
|
890
|
+
const result = {
|
|
891
|
+
newIndex: stubIndex,
|
|
892
|
+
child: getDomElement(el, false),
|
|
893
|
+
parent: getDomElement(stubParent, false),
|
|
894
|
+
sourceFile,
|
|
895
|
+
fromLine
|
|
896
|
+
};
|
|
897
|
+
// Add original parent info for cross-container moves
|
|
898
|
+
if (isCrossContainerMove && originalParent) {
|
|
899
|
+
result.originalParent = getDomElement(originalParent, false);
|
|
900
|
+
}
|
|
901
|
+
// Clean up the stub
|
|
902
|
+
removeStub();
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
function prepareElementForDragging(el) {
|
|
906
|
+
const saved = el.getAttribute(EditorAttributes.DATA_PICASSO_DRAG_SAVED_STYLE);
|
|
907
|
+
if (saved) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
// Store more style properties to ensure complete restoration
|
|
911
|
+
const style = {
|
|
912
|
+
position: el.style.position,
|
|
913
|
+
transform: el.style.transform,
|
|
914
|
+
width: el.style.width,
|
|
915
|
+
height: el.style.height,
|
|
916
|
+
left: el.style.left,
|
|
917
|
+
top: el.style.top,
|
|
918
|
+
zIndex: el.style.zIndex,
|
|
919
|
+
opacity: el.style.opacity,
|
|
920
|
+
pointerEvents: el.style.pointerEvents,
|
|
921
|
+
boxShadow: el.style.boxShadow,
|
|
922
|
+
transition: el.style.transition,
|
|
923
|
+
outline: el.style.outline,
|
|
924
|
+
};
|
|
925
|
+
// Store if the element was selected
|
|
926
|
+
const wasSelected = el.dataset["selected"] === "true";
|
|
927
|
+
el.setAttribute(EditorAttributes.DATA_PICASSO_DRAG_SAVED_STYLE, JSON.stringify(style));
|
|
928
|
+
el.setAttribute(EditorAttributes.DATA_PICASSO_DRAGGING, "true");
|
|
929
|
+
// Preserve the selected state if it was selected
|
|
930
|
+
if (wasSelected) {
|
|
931
|
+
el.dataset["selected"] = "true";
|
|
932
|
+
}
|
|
933
|
+
if (el.getAttribute(EditorAttributes.DATA_PICASSO_DRAG_DIRECTION) !== null) {
|
|
934
|
+
const parent = el.parentElement;
|
|
935
|
+
if (parent) {
|
|
936
|
+
const displayDirection = getDisplayDirection(parent);
|
|
937
|
+
el.setAttribute(EditorAttributes.DATA_PICASSO_DRAG_DIRECTION, displayDirection);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function cleanUpElementAfterDragging(el) {
|
|
942
|
+
console.log("Cleaning up element after dragging:", el);
|
|
943
|
+
// Make sure to restore the original position type
|
|
944
|
+
const computedStyle = window.getComputedStyle(el);
|
|
945
|
+
// First restore saved style
|
|
946
|
+
restoreElementStyle(el);
|
|
947
|
+
// Remove drag attributes
|
|
948
|
+
removeDragAttributes(el);
|
|
949
|
+
// Remove panel ID if element is from panel
|
|
950
|
+
/*if (isFromPanel(el)) {
|
|
951
|
+
console.log("Element is from panel, removing ID");
|
|
952
|
+
// Store the ID value for the result object
|
|
953
|
+
const panelId = el.id;
|
|
954
|
+
// Remove the ID to generate a new one in the page
|
|
955
|
+
el.removeAttribute('id');
|
|
956
|
+
console.log("Removed panel ID:", panelId);
|
|
957
|
+
}*/
|
|
958
|
+
// Ensure pointerEvents is enabled again
|
|
959
|
+
el.style.pointerEvents = "";
|
|
960
|
+
// Make sure the element is properly positioned
|
|
961
|
+
// If it was static and we made it relative, leave it as relative to maintain highlighting
|
|
962
|
+
if (el.style.position === "fixed") {
|
|
963
|
+
// If we moved to fixed, restore to original or relative
|
|
964
|
+
const originalPos = computedStyle.position === "static" ? "relative" : computedStyle.position;
|
|
965
|
+
el.style.position = originalPos;
|
|
966
|
+
}
|
|
967
|
+
// Reset the element-label position if it exists
|
|
968
|
+
const elementLabel = document.querySelector('.element-label');
|
|
969
|
+
if (elementLabel && el.dataset["selected"] === "true") {
|
|
970
|
+
// Get the new position of the element after it's been positioned
|
|
971
|
+
setTimeout(() => {
|
|
972
|
+
const rect = el.getBoundingClientRect();
|
|
973
|
+
elementLabel.style.position = "absolute";
|
|
974
|
+
elementLabel.style.left = `${window.scrollX + rect.left}px`;
|
|
975
|
+
elementLabel.style.top = `${window.scrollY + rect.top - 20}px`;
|
|
976
|
+
elementLabel.style.zIndex = "";
|
|
977
|
+
}, 0);
|
|
978
|
+
}
|
|
979
|
+
// Ensure ID is still assigned
|
|
980
|
+
getOrAssignDomId(el);
|
|
981
|
+
}
|
|
982
|
+
function removeDragAttributes(el) {
|
|
983
|
+
el.removeAttribute(EditorAttributes.DATA_PICASSO_DRAG_SAVED_STYLE);
|
|
984
|
+
el.removeAttribute(EditorAttributes.DATA_PICASSO_DRAGGING);
|
|
985
|
+
el.removeAttribute(EditorAttributes.DATA_PICASSO_DRAG_DIRECTION);
|
|
986
|
+
el.removeAttribute(EditorAttributes.DATA_PICASSO_DRAG_START_POSITION);
|
|
987
|
+
el.removeAttribute(EditorAttributes.DATA_PICASSO_ORIGINAL_PARENT);
|
|
988
|
+
// Clean up any additional drag-related data attributes
|
|
989
|
+
delete el.dataset["picassoDragMouseOffset"];
|
|
990
|
+
delete el.dataset["picassoCurrentDirection"];
|
|
991
|
+
}
|
|
992
|
+
export function endAllDrag() {
|
|
993
|
+
// Clear visual indicators
|
|
994
|
+
clearDropTargetVisuals();
|
|
995
|
+
// Reset all smoothing and position tracking
|
|
996
|
+
lastDragX = 0;
|
|
997
|
+
lastDragY = 0;
|
|
998
|
+
lastInsertionTarget = null;
|
|
999
|
+
lastUpdateTime = 0;
|
|
1000
|
+
lastStableIndex = -1;
|
|
1001
|
+
stablePositionCount = 0;
|
|
1002
|
+
const draggingElements = document.querySelectorAll(`[${EditorAttributes.DATA_PICASSO_DRAGGING}]`);
|
|
1003
|
+
// Collect elements that need their position updated
|
|
1004
|
+
const elementsToUpdate = [];
|
|
1005
|
+
for (const el of draggingElements) {
|
|
1006
|
+
// Remove transitions before cleanup
|
|
1007
|
+
el.style.transition = "";
|
|
1008
|
+
cleanUpElementAfterDragging(el);
|
|
1009
|
+
// Extra safety - make sure critical styles are reset
|
|
1010
|
+
el.style.position =
|
|
1011
|
+
el.style.position === "fixed"
|
|
1012
|
+
? "relative"
|
|
1013
|
+
: el.style.position;
|
|
1014
|
+
el.style.pointerEvents = "";
|
|
1015
|
+
el.style.zIndex = "";
|
|
1016
|
+
el.style.top = "";
|
|
1017
|
+
el.style.left = "";
|
|
1018
|
+
// Add to list for updating element label position
|
|
1019
|
+
if (el.dataset['selected'] === "true") {
|
|
1020
|
+
elementsToUpdate.push(el);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
// Reset element label positions
|
|
1024
|
+
setTimeout(() => {
|
|
1025
|
+
// Reset any element-label that might be in fixed position
|
|
1026
|
+
const elementLabel = document.querySelector('.element-label');
|
|
1027
|
+
if (elementLabel && elementsToUpdate.length > 0) {
|
|
1028
|
+
const el = elementsToUpdate[0]; // Use the first selected element
|
|
1029
|
+
const rect = el.getBoundingClientRect();
|
|
1030
|
+
elementLabel.style.position = "absolute";
|
|
1031
|
+
elementLabel.style.left = `${window.scrollX + rect.left}px`;
|
|
1032
|
+
elementLabel.style.top = `${window.scrollY + rect.top - 20}px`;
|
|
1033
|
+
elementLabel.style.zIndex = "";
|
|
1034
|
+
}
|
|
1035
|
+
}, 0);
|
|
1036
|
+
removeStub();
|
|
1037
|
+
}
|
|
1038
|
+
// Find valid drop targets (containers that can accept dragged elements)
|
|
1039
|
+
function findValidDropTargets() {
|
|
1040
|
+
// Get the stub element
|
|
1041
|
+
const stub = document.getElementById("drag-stub");
|
|
1042
|
+
// Only consider elements with a data-source attribute as valid drop targets
|
|
1043
|
+
const potentialTargets = Array.from(document.querySelectorAll("[data-source]"));
|
|
1044
|
+
// Filter out elements that are too small or invalid
|
|
1045
|
+
return potentialTargets.filter((el) => {
|
|
1046
|
+
const element = el;
|
|
1047
|
+
// Explicitly exclude the stub from valid drop targets
|
|
1048
|
+
if (stub && element === stub) {
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
// Exclude any element inside or related to button bar or element controls
|
|
1052
|
+
if (element.classList.contains("drag-button") ||
|
|
1053
|
+
element.classList.contains("duplicate-button") ||
|
|
1054
|
+
element.classList.contains("delete-button") ||
|
|
1055
|
+
element.closest(".element-controls") !== null ||
|
|
1056
|
+
element.classList.contains("ButtonBar") ||
|
|
1057
|
+
element.tagName.toLowerCase() === "buttonbar" ||
|
|
1058
|
+
// Check if the element is a direct parent of control buttons
|
|
1059
|
+
Array.from(element.children).some(child => child.classList?.contains("drag-button") ||
|
|
1060
|
+
child.classList?.contains("duplicate-button") ||
|
|
1061
|
+
child.classList?.contains("delete-button"))) {
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
// Check if the element is a button and print its children types
|
|
1065
|
+
if (element.tagName.toLowerCase() === "button") {
|
|
1066
|
+
console.log("Button children types:");
|
|
1067
|
+
Array.from(element.childNodes).forEach((child, index) => {
|
|
1068
|
+
let nodeType = "Unknown";
|
|
1069
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
1070
|
+
nodeType = "Text";
|
|
1071
|
+
}
|
|
1072
|
+
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
1073
|
+
nodeType = `Element (${child.tagName})`;
|
|
1074
|
+
}
|
|
1075
|
+
else if (child.nodeType === Node.COMMENT_NODE) {
|
|
1076
|
+
nodeType = "Comment";
|
|
1077
|
+
}
|
|
1078
|
+
console.log(`Child ${index}: ${nodeType}`);
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
// Check if the element is already a parent with at least one non-text child
|
|
1082
|
+
const hasNonTextChild = Array.from(element.children).some((child) => isValidHtmlElement(child) && child.nodeType === Node.ELEMENT_NODE);
|
|
1083
|
+
const rect = element.getBoundingClientRect();
|
|
1084
|
+
// Ensure it's a reasonable size (not too small) and has at least one non-text child
|
|
1085
|
+
return (rect.width > 10 &&
|
|
1086
|
+
rect.height > 10 &&
|
|
1087
|
+
isValidHtmlElement(element) &&
|
|
1088
|
+
hasNonTextChild);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
// Check if an element is a child of another element
|
|
1092
|
+
function isChildOf(child, parent) {
|
|
1093
|
+
let node = child.parentElement;
|
|
1094
|
+
while (node) {
|
|
1095
|
+
if (node === parent)
|
|
1096
|
+
return true;
|
|
1097
|
+
node = node.parentElement;
|
|
1098
|
+
}
|
|
1099
|
+
return false;
|
|
1100
|
+
}
|
|
1101
|
+
// Helper function to check binding compatibility
|
|
1102
|
+
function isBindingCompatible(draggingElement, dropTarget) {
|
|
1103
|
+
// Check if element is bound to its rendering component
|
|
1104
|
+
const isBound = draggingElement.getAttribute('data-binding-same-as-rendering-component') === 'true';
|
|
1105
|
+
if (!isBound) {
|
|
1106
|
+
return true; // If not bound, can be dropped anywhere
|
|
1107
|
+
}
|
|
1108
|
+
// Get rendering component values
|
|
1109
|
+
const draggingRendering = draggingElement.getAttribute('data-picasso-rendering-comp');
|
|
1110
|
+
const targetRendering = dropTarget.getAttribute('data-picasso-rendering-comp');
|
|
1111
|
+
// If bound, only allow dropping into targets with matching rendering component
|
|
1112
|
+
return draggingRendering === targetRendering;
|
|
1113
|
+
}
|
|
1114
|
+
// Get element at point, checking for valid drop targets
|
|
1115
|
+
function getDropTargetAt(x, y, draggingElement) {
|
|
1116
|
+
// Get all elements at the given point
|
|
1117
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1118
|
+
// Get valid drop targets
|
|
1119
|
+
const validDropTargets = findValidDropTargets();
|
|
1120
|
+
// Find the first valid drop target at this point
|
|
1121
|
+
for (const el of elements) {
|
|
1122
|
+
if (isValidHtmlElement(el) && el !== draggingElement && !isChildOf(el, draggingElement)) {
|
|
1123
|
+
const htmlEl = el;
|
|
1124
|
+
// Check if this element is in our valid drop targets list
|
|
1125
|
+
if (validDropTargets.includes(htmlEl)) {
|
|
1126
|
+
// Don't allow dropping into panel elements
|
|
1127
|
+
if (htmlEl.id?.startsWith('panel') || isInPanel(htmlEl)) {
|
|
1128
|
+
console.warn("Can't drop elements into the panel");
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
// Check binding compatibility
|
|
1132
|
+
if (!isBindingCompatible(draggingElement, htmlEl)) {
|
|
1133
|
+
console.warn("Drop target rejected due to binding constraints");
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
// Also check if the drop target is a descendant of the dragging element
|
|
1137
|
+
// This prevents the "Failed to execute 'appendChild' on 'Node': The new child element contains the parent" error
|
|
1138
|
+
if (!isChildOf(draggingElement, htmlEl)) {
|
|
1139
|
+
return htmlEl;
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
console.warn("Prevented dropping into descendant element to avoid circular reference");
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
// Add a helper function to check if an element is inside the panel
|
|
1150
|
+
function isInPanel(el) {
|
|
1151
|
+
// Check if the element itself or any parent has an ID starting with 'panel'
|
|
1152
|
+
let current = el;
|
|
1153
|
+
while (current && current !== document.body) {
|
|
1154
|
+
if (current.id?.startsWith('panel')) {
|
|
1155
|
+
return true;
|
|
1156
|
+
}
|
|
1157
|
+
current = current.parentElement;
|
|
1158
|
+
}
|
|
1159
|
+
return false;
|
|
1160
|
+
}
|
|
1161
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2Rldi10b29sYmFyL0VkaXRvci9kbmQudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsK0NBQStDO0FBQy9DLElBQUksY0FBYyxHQUF1QyxJQUFJLENBQUM7QUFDOUQsSUFBSSxjQUFjLEdBQXdCLElBQUksQ0FBQztBQUUvQywwQ0FBMEM7QUFDMUMsTUFBTSxVQUFVLGlCQUFpQjtJQUMvQixNQUFNLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLEdBQUcsYUFBYSxFQUFFLENBQUM7SUFFdkUsK0JBQStCO0lBQy9CLGNBQWMsR0FBRyxJQUFJLENBQUM7SUFDdEIsY0FBYyxHQUFHLElBQUksQ0FBQztBQUN4QixDQUFDO0FBT0QsWUFBWTtBQUNaLElBQUssZ0JBTUo7QUFORCxXQUFLLGdCQUFnQjtJQUNuQixtRUFBK0MsQ0FBQTtJQUMvQyxtRkFBK0QsQ0FBQTtJQUMvRCwrRUFBMkQsQ0FBQTtJQUMzRCx5RkFBcUUsQ0FBQTtJQUNyRSxpRkFBNkQsQ0FBQTtBQUMvRCxDQUFDLEVBTkksZ0JBQWdCLEtBQWhCLGdCQUFnQixRQU1wQjtBQUVELDZDQUE2QztBQUM3QyxNQUFNLHVCQUF1QixHQUFHLDJCQUEyQixDQUFDO0FBQzVELE1BQU0seUJBQXlCLEdBQUcsNkJBQTZCLENBQUM7QUFhaEUsK0NBQStDO0FBQy9DLElBQUkseUJBQXlCLEdBSXZCLEVBQUUsQ0FBQztBQUVULGtEQUFrRDtBQUNsRCxTQUFTLHlCQUF5QixDQUNoQyxTQUFpQixFQUNqQixVQUFrQixFQUNsQixRQUFnQixFQUNoQixNQUFjLEVBQ2QsVUFBa0IsRUFDbEIsUUFBdUIsRUFDdkIsTUFBZSxFQUNmLGtCQUEyQixFQUMzQixnQkFBZ0M7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
|