@nyaruka/temba-components 0.132.0 → 0.134.0
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/CHANGELOG.md +31 -1
- package/demo/components/flow/example.html +1 -0
- package/demo/components/webchat/example.html +1 -1
- package/demo/static/css/tailwind.css +30019 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +2 -11
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +555 -476
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +248 -95
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +4 -4
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/display/TembaUser.js +3 -3
- package/out-tsc/src/display/TembaUser.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +132 -58
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +183 -58
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/utils.js +141 -0
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +1 -2
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -1
- package/out-tsc/src/list/ContentMenu.js +1 -0
- package/out-tsc/src/list/ContentMenu.js.map +1 -1
- package/out-tsc/src/list/SortableList.js +3 -2
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +184 -205
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +2 -11
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/store/AppState.js +34 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/store/Store.js +5 -5
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/utils.js +3 -3
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/src/webchat/WebChat.js +22 -9
- package/out-tsc/src/webchat/WebChat.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +6 -5
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/actions/send_broadcast.test.js +9 -4
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +1 -1
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-floating-window.test.js +0 -2
- package/out-tsc/test/temba-floating-window.test.js.map +1 -1
- package/out-tsc/test/temba-flow-collision.test.js +673 -0
- package/out-tsc/test/temba-flow-collision.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +195 -0
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-utils-uuid.test.js +45 -1
- package/out-tsc/test/temba-utils-uuid.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -2
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/screenshots/truth/floating-tab/default.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/src/display/Chat.ts +331 -135
- package/src/display/FloatingTab.ts +4 -4
- package/src/display/TembaUser.ts +3 -2
- package/src/events.ts +12 -12
- package/src/flow/CanvasNode.ts +140 -57
- package/src/flow/Editor.ts +240 -58
- package/src/flow/utils.ts +207 -1
- package/src/interfaces.ts +7 -0
- package/src/layout/FloatingWindow.ts +1 -3
- package/src/list/ContentMenu.ts +1 -0
- package/src/list/SortableList.ts +3 -2
- package/src/live/ContactChat.ts +195 -221
- package/src/locales/es.ts +13 -18
- package/src/locales/fr.ts +13 -18
- package/src/locales/locale-codes.ts +2 -11
- package/src/locales/pt.ts +13 -18
- package/src/store/AppState.ts +43 -0
- package/src/store/Store.ts +5 -5
- package/src/utils.ts +3 -3
- package/src/webchat/WebChat.ts +24 -10
- package/test/ActionHelper.ts +13 -5
- package/test/actions/send_broadcast.test.ts +4 -2
- package/test/temba-contact-chat.test.ts +1 -1
- package/test/temba-floating-window.test.ts +0 -2
- package/test/temba-flow-collision.test.ts +833 -0
- package/test/temba-flow-editor-node.test.ts +224 -0
- package/test/temba-utils-uuid.test.ts +61 -1
- package/test/utils.test.ts +7 -2
- package/test-assets/contacts/history.json +22 -9
- package/web-test-runner.config.mjs +3 -3
|
@@ -149,4 +149,145 @@ export const SCHEMES = [
|
|
|
149
149
|
path: 'External ID'
|
|
150
150
|
}
|
|
151
151
|
];
|
|
152
|
+
/**
|
|
153
|
+
* Minimum vertical spacing between nodes (in pixels)
|
|
154
|
+
*/
|
|
155
|
+
const MIN_NODE_SPACING = 30;
|
|
156
|
+
/**
|
|
157
|
+
* Small buffer to avoid floating point precision issues in overlap detection (in pixels)
|
|
158
|
+
* This prevents false positives when nodes are exactly adjacent (e.g., bottom of one node
|
|
159
|
+
* at exactly the same position as top of another)
|
|
160
|
+
*/
|
|
161
|
+
const OVERLAP_BUFFER = 10;
|
|
162
|
+
/**
|
|
163
|
+
* Gets the bounding box for a node from the DOM
|
|
164
|
+
*
|
|
165
|
+
* @param nodeUuid - The UUID of the node
|
|
166
|
+
* @param position - The current position of the node
|
|
167
|
+
* @param element - Optional pre-fetched DOM element (recommended for performance when checking multiple nodes)
|
|
168
|
+
* @returns NodeBounds object or null if element not found
|
|
169
|
+
*
|
|
170
|
+
* Note: When element is not provided, performs a DOM query which may impact performance
|
|
171
|
+
* during bulk collision detection. Consider fetching elements beforehand when possible.
|
|
172
|
+
*/
|
|
173
|
+
export const getNodeBounds = (nodeUuid, position, element) => {
|
|
174
|
+
// If element is provided, use it; otherwise try to find it in DOM
|
|
175
|
+
const nodeElement = element || document.querySelector(`[id="${nodeUuid}"]`);
|
|
176
|
+
if (!nodeElement) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
const rect = nodeElement.getBoundingClientRect();
|
|
180
|
+
const width = rect.width;
|
|
181
|
+
const height = rect.height;
|
|
182
|
+
return {
|
|
183
|
+
uuid: nodeUuid,
|
|
184
|
+
left: position.left,
|
|
185
|
+
top: position.top,
|
|
186
|
+
right: position.left + width,
|
|
187
|
+
bottom: position.top + height,
|
|
188
|
+
width,
|
|
189
|
+
height
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Checks if two node bounding boxes overlap
|
|
194
|
+
*/
|
|
195
|
+
export const nodesOverlap = (bounds1, bounds2) => {
|
|
196
|
+
// Use a small buffer to avoid floating point precision issues
|
|
197
|
+
const buffer = OVERLAP_BUFFER;
|
|
198
|
+
return !(bounds1.right <= bounds2.left - buffer ||
|
|
199
|
+
bounds1.left >= bounds2.right + buffer ||
|
|
200
|
+
bounds1.bottom <= bounds2.top - buffer ||
|
|
201
|
+
bounds1.top >= bounds2.bottom + buffer);
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Detects all collisions between a node and other nodes
|
|
205
|
+
*/
|
|
206
|
+
export const detectCollisions = (targetBounds, allBounds) => {
|
|
207
|
+
return allBounds.filter((bounds) => bounds.uuid !== targetBounds.uuid && nodesOverlap(targetBounds, bounds));
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Calculates the new positions needed to resolve all collisions
|
|
211
|
+
* Nodes are only moved downward, never up, left, or right
|
|
212
|
+
* Returns a map of node UUIDs to their new positions
|
|
213
|
+
*/
|
|
214
|
+
export const calculateReflowPositions = (movedNodeUuid, movedNodeBounds, allBounds, droppedBelowMidpoint = false) => {
|
|
215
|
+
const newPositions = new Map();
|
|
216
|
+
// If dropped below midpoint, the moved node should move down instead
|
|
217
|
+
if (droppedBelowMidpoint) {
|
|
218
|
+
// Find all nodes that collide with the moved node
|
|
219
|
+
const collisions = detectCollisions(movedNodeBounds, allBounds);
|
|
220
|
+
if (collisions.length > 0) {
|
|
221
|
+
// Find the highest bottom position of all colliding nodes
|
|
222
|
+
const maxBottom = Math.max(...collisions.map((b) => b.bottom));
|
|
223
|
+
// Move the dropped node below all colliding nodes
|
|
224
|
+
const newTop = maxBottom + MIN_NODE_SPACING;
|
|
225
|
+
newPositions.set(movedNodeUuid, {
|
|
226
|
+
left: movedNodeBounds.left,
|
|
227
|
+
top: newTop
|
|
228
|
+
});
|
|
229
|
+
// Update the moved node bounds for further collision checks
|
|
230
|
+
movedNodeBounds = {
|
|
231
|
+
...movedNodeBounds,
|
|
232
|
+
top: newTop,
|
|
233
|
+
bottom: newTop + movedNodeBounds.height
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Now check for any remaining collisions and move other nodes down
|
|
238
|
+
const processedNodes = new Set();
|
|
239
|
+
processedNodes.add(movedNodeUuid);
|
|
240
|
+
// Keep checking for collisions until none remain
|
|
241
|
+
let hasCollisions = true;
|
|
242
|
+
let iterations = 0;
|
|
243
|
+
const maxIterations = 100; // Prevent infinite loops
|
|
244
|
+
while (hasCollisions && iterations < maxIterations) {
|
|
245
|
+
hasCollisions = false;
|
|
246
|
+
iterations++;
|
|
247
|
+
// Check all nodes for collisions
|
|
248
|
+
for (const bounds of allBounds) {
|
|
249
|
+
if (processedNodes.has(bounds.uuid)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
// Use original bounds since we skip already processed nodes
|
|
253
|
+
const currentBounds = bounds;
|
|
254
|
+
// Check if this node collides with the moved node or any already repositioned nodes
|
|
255
|
+
let collisionFound = false;
|
|
256
|
+
let maxCollisionBottom = 0;
|
|
257
|
+
// Check against moved node
|
|
258
|
+
if (nodesOverlap(currentBounds, movedNodeBounds)) {
|
|
259
|
+
collisionFound = true;
|
|
260
|
+
maxCollisionBottom = Math.max(maxCollisionBottom, movedNodeBounds.bottom);
|
|
261
|
+
}
|
|
262
|
+
// Check against other repositioned nodes
|
|
263
|
+
for (const [otherUuid, otherPosition] of newPositions.entries()) {
|
|
264
|
+
if (otherUuid === bounds.uuid)
|
|
265
|
+
continue;
|
|
266
|
+
const otherBounds = allBounds.find((b) => b.uuid === otherUuid);
|
|
267
|
+
if (!otherBounds)
|
|
268
|
+
continue;
|
|
269
|
+
const otherUpdatedBounds = {
|
|
270
|
+
...otherBounds,
|
|
271
|
+
top: otherPosition.top,
|
|
272
|
+
bottom: otherPosition.top + otherBounds.height
|
|
273
|
+
};
|
|
274
|
+
if (nodesOverlap(currentBounds, otherUpdatedBounds)) {
|
|
275
|
+
collisionFound = true;
|
|
276
|
+
maxCollisionBottom = Math.max(maxCollisionBottom, otherUpdatedBounds.bottom);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (collisionFound) {
|
|
280
|
+
// Move this node down below the collision
|
|
281
|
+
const newTop = maxCollisionBottom + MIN_NODE_SPACING;
|
|
282
|
+
newPositions.set(bounds.uuid, {
|
|
283
|
+
left: bounds.left,
|
|
284
|
+
top: newTop
|
|
285
|
+
});
|
|
286
|
+
hasCollisions = true;
|
|
287
|
+
processedNodes.add(bounds.uuid);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return newPositions;
|
|
292
|
+
};
|
|
152
293
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/flow/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { NamedObject } from '../store/flow-definition';\n\n/**\n * Renders a single line item with optional icon\n */\nexport const renderLineItem = (name: string, icon?: string) => {\n return html`<div style=\"display:flex;items-align:center;\">\n ${icon\n ? html`<temba-icon name=${icon} style=\"margin-right:0.5em\"></temba-icon>`\n : null}\n <div\n style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 250px;\"\n >\n ${name}\n </div>\n </div>`;\n};\n\n/**\n * Renders a list of named objects with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderNamedObjects = (assets: NamedObject[], icon?: string) => {\n return renderStringList(\n assets.map((asset) => asset.name),\n icon\n );\n};\n\n/**\n * Renders a list of strings with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderStringList = (items: string[], icon?: string) => {\n const itemElements = [];\n const maxDisplay = 3;\n\n // Show up to 3 items, or all 4 if exactly 4 items\n const displayCount =\n items.length === 4 ? 4 : Math.min(maxDisplay, items.length);\n\n for (let i = 0; i < displayCount; i++) {\n const item = items[i];\n itemElements.push(renderLineItem(item, icon));\n }\n\n // Add \"+X more\" if there are more than 3 items (and not exactly 4)\n if (items.length > maxDisplay && items.length !== 4) {\n const remainingCount = items.length - maxDisplay;\n itemElements.push(html`<div\n style=\"display:flex;items-align:center;margin-top:0.2em;\"\n >\n ${icon\n ? html`<div style=\"margin-right:0.4em; width: 1em;\"></div>` // spacing placeholder\n : null}\n <div style=\"font-size:0.8em\">+${remainingCount} more</div>\n </div>`);\n }\n return itemElements;\n};\n\nexport interface Scheme {\n scheme: string;\n name: string;\n path: string;\n excludeFromSplit?: boolean;\n}\n\nexport const SCHEMES: Scheme[] = [\n {\n scheme: 'tel',\n name: 'SMS',\n path: 'Phone Number'\n },\n {\n scheme: 'whatsapp',\n name: 'WhatsApp',\n path: 'WhatsApp Number'\n },\n {\n scheme: 'facebook',\n name: 'Facebook',\n path: 'Facebook ID'\n },\n {\n scheme: 'instagram',\n name: 'Instagram',\n path: 'Instagram ID'\n },\n {\n scheme: 'twitterid',\n name: 'Twitter',\n path: 'Twitter ID',\n excludeFromSplit: true\n },\n {\n scheme: 'telegram',\n name: 'Telegram',\n path: 'Telegram ID'\n },\n {\n scheme: 'viber',\n name: 'Viber',\n path: 'Viber ID'\n },\n {\n scheme: 'line',\n name: 'Line',\n path: 'Line ID'\n },\n {\n scheme: 'wechat',\n name: 'WeChat',\n path: 'WeChat ID'\n },\n {\n scheme: 'fcm',\n name: 'Firebase',\n path: 'Firebase ID'\n },\n {\n scheme: 'jiochat',\n name: 'JioChat',\n path: 'JioChat ID'\n },\n {\n scheme: 'freshchat',\n name: 'Freshchat',\n path: 'Freshchat ID'\n },\n {\n scheme: 'mailto',\n name: 'Email',\n path: 'Email Address',\n excludeFromSplit: true\n },\n {\n scheme: 'twitter',\n name: 'Twitter',\n path: 'Twitter Handle',\n excludeFromSplit: true\n },\n {\n scheme: 'vk',\n name: 'VK',\n path: 'VK ID'\n },\n {\n scheme: 'discord',\n name: 'Discord',\n path: 'Discord ID'\n },\n {\n scheme: 'webchat',\n name: 'Webchat',\n path: 'Webchat ID',\n excludeFromSplit: true\n },\n {\n scheme: 'rocketchat',\n name: 'RocketChat',\n path: 'RocketChat ID'\n },\n {\n scheme: 'ext',\n name: 'External',\n path: 'External ID'\n }\n];\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/flow/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { NamedObject, FlowPosition } from '../store/flow-definition';\n\n/**\n * Renders a single line item with optional icon\n */\nexport const renderLineItem = (name: string, icon?: string) => {\n return html`<div style=\"display:flex;items-align:center;\">\n ${icon\n ? html`<temba-icon name=${icon} style=\"margin-right:0.5em\"></temba-icon>`\n : null}\n <div\n style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 250px;\"\n >\n ${name}\n </div>\n </div>`;\n};\n\n/**\n * Renders a list of named objects with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderNamedObjects = (assets: NamedObject[], icon?: string) => {\n return renderStringList(\n assets.map((asset) => asset.name),\n icon\n );\n};\n\n/**\n * Renders a list of strings with optional icon, showing up to 3 items\n * with a \"+X more\" indicator if there are more items\n */\nexport const renderStringList = (items: string[], icon?: string) => {\n const itemElements = [];\n const maxDisplay = 3;\n\n // Show up to 3 items, or all 4 if exactly 4 items\n const displayCount =\n items.length === 4 ? 4 : Math.min(maxDisplay, items.length);\n\n for (let i = 0; i < displayCount; i++) {\n const item = items[i];\n itemElements.push(renderLineItem(item, icon));\n }\n\n // Add \"+X more\" if there are more than 3 items (and not exactly 4)\n if (items.length > maxDisplay && items.length !== 4) {\n const remainingCount = items.length - maxDisplay;\n itemElements.push(html`<div\n style=\"display:flex;items-align:center;margin-top:0.2em;\"\n >\n ${icon\n ? html`<div style=\"margin-right:0.4em; width: 1em;\"></div>` // spacing placeholder\n : null}\n <div style=\"font-size:0.8em\">+${remainingCount} more</div>\n </div>`);\n }\n return itemElements;\n};\n\nexport interface Scheme {\n scheme: string;\n name: string;\n path: string;\n excludeFromSplit?: boolean;\n}\n\nexport const SCHEMES: Scheme[] = [\n {\n scheme: 'tel',\n name: 'SMS',\n path: 'Phone Number'\n },\n {\n scheme: 'whatsapp',\n name: 'WhatsApp',\n path: 'WhatsApp Number'\n },\n {\n scheme: 'facebook',\n name: 'Facebook',\n path: 'Facebook ID'\n },\n {\n scheme: 'instagram',\n name: 'Instagram',\n path: 'Instagram ID'\n },\n {\n scheme: 'twitterid',\n name: 'Twitter',\n path: 'Twitter ID',\n excludeFromSplit: true\n },\n {\n scheme: 'telegram',\n name: 'Telegram',\n path: 'Telegram ID'\n },\n {\n scheme: 'viber',\n name: 'Viber',\n path: 'Viber ID'\n },\n {\n scheme: 'line',\n name: 'Line',\n path: 'Line ID'\n },\n {\n scheme: 'wechat',\n name: 'WeChat',\n path: 'WeChat ID'\n },\n {\n scheme: 'fcm',\n name: 'Firebase',\n path: 'Firebase ID'\n },\n {\n scheme: 'jiochat',\n name: 'JioChat',\n path: 'JioChat ID'\n },\n {\n scheme: 'freshchat',\n name: 'Freshchat',\n path: 'Freshchat ID'\n },\n {\n scheme: 'mailto',\n name: 'Email',\n path: 'Email Address',\n excludeFromSplit: true\n },\n {\n scheme: 'twitter',\n name: 'Twitter',\n path: 'Twitter Handle',\n excludeFromSplit: true\n },\n {\n scheme: 'vk',\n name: 'VK',\n path: 'VK ID'\n },\n {\n scheme: 'discord',\n name: 'Discord',\n path: 'Discord ID'\n },\n {\n scheme: 'webchat',\n name: 'Webchat',\n path: 'Webchat ID',\n excludeFromSplit: true\n },\n {\n scheme: 'rocketchat',\n name: 'RocketChat',\n path: 'RocketChat ID'\n },\n {\n scheme: 'ext',\n name: 'External',\n path: 'External ID'\n }\n];\n\n/**\n * Represents the bounding box of a node on the canvas\n */\nexport interface NodeBounds {\n uuid: string;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\n/**\n * Minimum vertical spacing between nodes (in pixels)\n */\nconst MIN_NODE_SPACING = 30;\n\n/**\n * Small buffer to avoid floating point precision issues in overlap detection (in pixels)\n * This prevents false positives when nodes are exactly adjacent (e.g., bottom of one node\n * at exactly the same position as top of another)\n */\nconst OVERLAP_BUFFER = 10;\n\n/**\n * Gets the bounding box for a node from the DOM\n *\n * @param nodeUuid - The UUID of the node\n * @param position - The current position of the node\n * @param element - Optional pre-fetched DOM element (recommended for performance when checking multiple nodes)\n * @returns NodeBounds object or null if element not found\n *\n * Note: When element is not provided, performs a DOM query which may impact performance\n * during bulk collision detection. Consider fetching elements beforehand when possible.\n */\nexport const getNodeBounds = (\n nodeUuid: string,\n position: FlowPosition,\n element?: HTMLElement\n): NodeBounds | null => {\n // If element is provided, use it; otherwise try to find it in DOM\n const nodeElement =\n element || (document.querySelector(`[id=\"${nodeUuid}\"]`) as HTMLElement);\n\n if (!nodeElement) {\n return null;\n }\n\n const rect = nodeElement.getBoundingClientRect();\n const width = rect.width;\n const height = rect.height;\n\n return {\n uuid: nodeUuid,\n left: position.left,\n top: position.top,\n right: position.left + width,\n bottom: position.top + height,\n width,\n height\n };\n};\n\n/**\n * Checks if two node bounding boxes overlap\n */\nexport const nodesOverlap = (\n bounds1: NodeBounds,\n bounds2: NodeBounds\n): boolean => {\n // Use a small buffer to avoid floating point precision issues\n const buffer = OVERLAP_BUFFER;\n\n return !(\n bounds1.right <= bounds2.left - buffer ||\n bounds1.left >= bounds2.right + buffer ||\n bounds1.bottom <= bounds2.top - buffer ||\n bounds1.top >= bounds2.bottom + buffer\n );\n};\n\n/**\n * Detects all collisions between a node and other nodes\n */\nexport const detectCollisions = (\n targetBounds: NodeBounds,\n allBounds: NodeBounds[]\n): NodeBounds[] => {\n return allBounds.filter(\n (bounds) =>\n bounds.uuid !== targetBounds.uuid && nodesOverlap(targetBounds, bounds)\n );\n};\n\n/**\n * Calculates the new positions needed to resolve all collisions\n * Nodes are only moved downward, never up, left, or right\n * Returns a map of node UUIDs to their new positions\n */\nexport const calculateReflowPositions = (\n movedNodeUuid: string,\n movedNodeBounds: NodeBounds,\n allBounds: NodeBounds[],\n droppedBelowMidpoint: boolean = false\n): Map<string, FlowPosition> => {\n const newPositions = new Map<string, FlowPosition>();\n\n // If dropped below midpoint, the moved node should move down instead\n if (droppedBelowMidpoint) {\n // Find all nodes that collide with the moved node\n const collisions = detectCollisions(movedNodeBounds, allBounds);\n\n if (collisions.length > 0) {\n // Find the highest bottom position of all colliding nodes\n const maxBottom = Math.max(...collisions.map((b) => b.bottom));\n\n // Move the dropped node below all colliding nodes\n const newTop = maxBottom + MIN_NODE_SPACING;\n newPositions.set(movedNodeUuid, {\n left: movedNodeBounds.left,\n top: newTop\n });\n\n // Update the moved node bounds for further collision checks\n movedNodeBounds = {\n ...movedNodeBounds,\n top: newTop,\n bottom: newTop + movedNodeBounds.height\n };\n }\n }\n\n // Now check for any remaining collisions and move other nodes down\n const processedNodes = new Set<string>();\n processedNodes.add(movedNodeUuid);\n\n // Keep checking for collisions until none remain\n let hasCollisions = true;\n let iterations = 0;\n const maxIterations = 100; // Prevent infinite loops\n\n while (hasCollisions && iterations < maxIterations) {\n hasCollisions = false;\n iterations++;\n\n // Check all nodes for collisions\n for (const bounds of allBounds) {\n if (processedNodes.has(bounds.uuid)) {\n continue;\n }\n\n // Use original bounds since we skip already processed nodes\n const currentBounds = bounds;\n\n // Check if this node collides with the moved node or any already repositioned nodes\n let collisionFound = false;\n let maxCollisionBottom = 0;\n\n // Check against moved node\n if (nodesOverlap(currentBounds, movedNodeBounds)) {\n collisionFound = true;\n maxCollisionBottom = Math.max(\n maxCollisionBottom,\n movedNodeBounds.bottom\n );\n }\n\n // Check against other repositioned nodes\n for (const [otherUuid, otherPosition] of newPositions.entries()) {\n if (otherUuid === bounds.uuid) continue;\n\n const otherBounds = allBounds.find((b) => b.uuid === otherUuid);\n if (!otherBounds) continue;\n\n const otherUpdatedBounds = {\n ...otherBounds,\n top: otherPosition.top,\n bottom: otherPosition.top + otherBounds.height\n };\n\n if (nodesOverlap(currentBounds, otherUpdatedBounds)) {\n collisionFound = true;\n maxCollisionBottom = Math.max(\n maxCollisionBottom,\n otherUpdatedBounds.bottom\n );\n }\n }\n\n if (collisionFound) {\n // Move this node down below the collision\n const newTop = maxCollisionBottom + MIN_NODE_SPACING;\n newPositions.set(bounds.uuid, {\n left: bounds.left,\n top: newTop\n });\n hasCollisions = true;\n processedNodes.add(bounds.uuid);\n }\n }\n }\n\n return newPositions;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,mCAAsB,CAAA;IACtB,uCAA0B,CAAA;IAC1B,qCAAwB,CAAA;AAC1B,CAAC,EAJW,SAAS,KAAT,SAAS,QAIpB;AAED,MAAM,CAAN,IAAY,kBAIX;AAJD,WAAY,kBAAkB;IAC5B,sDAAgC,CAAA;IAChC,gEAA0C,CAAA;IAC1C,4DAAsC,CAAA;AACxC,CAAC,EAJW,kBAAkB,KAAlB,kBAAkB,QAI7B;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACnB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,mCAAsB,CAAA;IACtB,uCAA0B,CAAA;IAC1B,qCAAwB,CAAA;AAC1B,CAAC,EAJW,SAAS,KAAT,SAAS,QAIpB;AAED,MAAM,CAAN,IAAY,kBAIX;AAJD,WAAY,kBAAkB;IAC5B,sDAAgC,CAAA;IAChC,gEAA0C,CAAA;IAC1C,4DAAsC,CAAA;AACxC,CAAC,EAJW,kBAAkB,KAAlB,kBAAkB,QAI7B;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACnB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AAkOD,MAAM,CAAN,IAAY,eAwCX;AAxCD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,8CAA2B,CAAA;IAC3B,yDAAsC,CAAA;IACtC,gDAA6B,CAAA;IAC7B,gDAA6B,CAAA;IAC7B,yDAAsC,CAAA;IACtC,uDAAoC,CAAA;IACpC,6DAA0C,CAAA;IAC1C,2DAAwC,CAAA;IACxC,2DAAwC,CAAA;IACxC,yDAAsC,CAAA;IACtC,qDAAkC,CAAA;IAClC,gDAA6B,CAAA;IAC7B,kDAA+B,CAAA;IAC/B,2CAAwB,CAAA;IACxB,uDAAoC,CAAA;IACpC,wCAAqB,CAAA;IACrB,uDAAoC,CAAA;IACpC,iDAA8B,CAAA;IAC9B,+CAA4B,CAAA;IAC5B,uDAAoC,CAAA;IACpC,uDAAoC,CAAA;IACpC,4CAAyB,CAAA;IACzB,2DAAwC,CAAA;IACxC,wCAAqB,CAAA;IACrB,gDAA6B,CAAA;IAC7B,0CAAuB,CAAA;IACvB,yDAAsC,CAAA;IACtC,wCAAqB,CAAA;IACrB,gEAA6C,CAAA;IAC7C,qDAAkC,CAAA;IAClC,sEAAmD,CAAA;IACnD,oEAAiD,CAAA;IACjD,qDAAkC,CAAA;IAClC,oEAAiD,CAAA;IACjD,kEAA+C,CAAA;IAC/C,iDAA8B,CAAA;IAC9B,kEAA+C,CAAA;AACjD,CAAC,EAxCW,eAAe,KAAf,eAAe,QAwC1B","sourcesContent":["export interface Workspace {\n uuid: string;\n name: string;\n country: string;\n languages: string[];\n timezone: string;\n date_style: DateStyle;\n anon: boolean;\n}\n\nexport interface Language {\n iso: string;\n name: string;\n}\n\nexport interface Attachment {\n uuid: string;\n content_type: string;\n url: string;\n filename: string;\n size: number;\n error: string;\n}\n\nexport enum DateStyle {\n DayFirst = 'day_first',\n MonthFirst = 'month_first',\n YearFirst = 'year_first'\n}\n\nexport enum ScheduledEventType {\n CampaignEvent = 'campaign_event',\n ScheduledBroadcast = 'scheduled_broadcast',\n ScheduledTrigger = 'scheduled_trigger'\n}\n\nexport enum TicketStatus {\n Open = 'open',\n Closed = 'closed'\n}\n\nexport interface ScheduledEvent {\n type: ScheduledEventType;\n scheduled: string;\n repeat_period: string;\n campaign?: ObjectReference;\n flow?: ObjectReference;\n message?: string;\n}\n\nexport interface NamedUser extends User {\n name: string;\n}\n\nexport interface User {\n id?: number;\n first_name?: string;\n last_name?: string;\n name?: string;\n email?: string;\n role?: string;\n created_on?: string;\n avatar?: string;\n}\n\nexport interface Ticket {\n uuid: string;\n subject: string;\n body?: string;\n closed_on: string;\n opened_on: string;\n status: string;\n contact: ObjectReference;\n topic: ObjectReference;\n assignee?: { email: string; name: string; avatar?: string };\n}\n\nexport interface FlowResult {\n key: string;\n name: string;\n categories: string[];\n node_uuids: string[];\n}\n\nexport interface FlowDetails {\n name: string;\n results: FlowResult[];\n modified_on: string;\n runs: {\n active: number;\n completed: number;\n expired: number;\n interrupted: number;\n };\n}\n\nexport interface Msg {\n text: string;\n status: string;\n channel: ObjectReference;\n quick_replies: string[];\n urn: string;\n direction: string;\n type: string;\n attachments: string[];\n unsendable_reason?:\n | 'no_route'\n | 'contact_blocked'\n | 'contact_stopped'\n | 'contact_archived'\n | 'org_suspended'\n | 'looping';\n}\n\nexport interface ObjectReference {\n uuid: string;\n name: string;\n}\n\nexport interface Shortcut {\n uuid: string;\n name: string;\n text: string;\n modified_on: string;\n}\n\nexport interface ContactField {\n key: string;\n label: string;\n value_type: string;\n featured: boolean;\n priority: number;\n agent_access: string;\n type: string;\n usages: { campaign_events: number; flows: number; groups: number };\n}\n\nexport interface ContactGroup {\n uuid: string;\n count: number;\n name: string;\n query?: string;\n status: string;\n}\n\nexport interface URN {\n scheme: string;\n path: string;\n}\n\nexport interface Group {\n name: string;\n uuid: string;\n is_dynamic?: boolean;\n}\n\nexport interface ContactNote {\n text: string;\n created_on: string;\n created_by: NamedUser;\n}\n\nexport interface ContactTicket {\n name: string;\n uuid: string;\n status: string;\n\n contact: {\n uuid: string;\n name: string;\n created_on: Date;\n last_seen_on: Date;\n };\n}\n\nexport interface Contact {\n name: string;\n uuid: string;\n stopped: boolean;\n blocked: boolean;\n urns: string[];\n language?: string;\n fields: { [key: string]: string };\n groups: Group[];\n notes: ContactNote[];\n modified_on: string;\n created_on: string;\n last_seen_on: string;\n status: string;\n\n ref?: string; // only returned for anon workspaces\n flow?: ObjectReference;\n last_msg?: Msg;\n direction?: string;\n ticket: {\n uuid: string;\n subject: string;\n closed_on?: string;\n last_activity_on: string;\n assignee?: User;\n topic?: ObjectReference;\n };\n}\n\nexport interface FeatureProperties {\n name: string;\n osm_id: string;\n level: number;\n children?: FeatureProperties[];\n has_children?: boolean;\n aliases?: string;\n parent_osm_id?: string;\n id?: number;\n path?: string;\n}\n\nexport interface Position {\n top: number;\n left: number;\n}\n\nexport interface FunctionExample {\n template: string;\n output: string;\n}\n\nexport interface CompletionOption {\n name?: string;\n summary: string;\n\n // functions\n signature?: string;\n detail?: string;\n examples?: FunctionExample[];\n}\n\nexport interface CompletionResult {\n anchorPosition: Position;\n query: string;\n options: CompletionOption[];\n currentFunction: CompletionOption;\n}\n\nexport interface CompletionProperty {\n key: string;\n help: string;\n type: string;\n}\n\nexport interface CompletionType {\n name: string;\n\n key_source?: string;\n property_template?: CompletionProperty;\n properties?: CompletionProperty[];\n}\n\nexport interface CompletionSchema {\n types: CompletionType[];\n root: CompletionProperty[];\n root_no_session: CompletionProperty[];\n}\n\nexport type KeyedAssets = { [assetType: string]: string[] };\n\nexport enum CustomEventType {\n Loaded = 'temba-loaded',\n Loading = 'temba-loading',\n Canceled = 'temba-canceled',\n CursorChanged = 'temba-cursor-changed',\n Refreshed = 'temba-refreshed',\n Selection = 'temba-selection',\n ButtonClicked = 'temba-button-clicked',\n DialogHidden = 'temba-dialog-hidden',\n ScrollThreshold = 'temba-scroll-threshold',\n ContentChanged = 'temba-content-changed',\n ContextChanged = 'temba-context-changed',\n FetchComplete = 'temba-fetch-complete',\n MessageSent = 'temba-message-sent',\n Submitted = 'temba-submitted',\n Redirected = 'temba-redirected',\n NoPath = 'temba-no-path',\n StoreUpdated = 'temba-store-updated',\n Ready = 'temba-ready',\n OrderChanged = 'temba-order-changed',\n DragStart = 'temba-drag-start',\n DragStop = 'temba-drag-stop',\n DragExternal = 'temba-drag-external',\n DragInternal = 'temba-drag-internal',\n Resized = 'temba-resized',\n DetailsChanged = 'temba-details-changed',\n Error = 'temba-error',\n Interrupt = 'temba-interrupt',\n Opened = 'temba-opened',\n TicketUpdated = 'temba-ticket-updated',\n Moved = 'temba-moved',\n DateRangeChanged = 'temba-date-range-changed',\n NodeDeleted = 'temba-node-deleted',\n ActionEditRequested = 'temba-action-edit-requested',\n AddActionRequested = 'temba-add-action-requested',\n ActionSaved = 'temba-action-saved',\n ActionEditCanceled = 'temba-action-edit-canceled',\n NodeEditRequested = 'temba-node-edit-requested',\n NodeSaved = 'temba-node-saved',\n NodeEditCancelled = 'temba-node-edit-cancelled'\n}\n"]}
|
|
@@ -111,7 +111,7 @@ export class FloatingWindow extends RapidElement {
|
|
|
111
111
|
transition: transform var(--transition-duration, 300ms) ease-in-out,
|
|
112
112
|
opacity var(--transition-duration, 300ms) ease-in-out;
|
|
113
113
|
position: fixed;
|
|
114
|
-
z-index:
|
|
114
|
+
z-index: 5000;
|
|
115
115
|
top: 100px;
|
|
116
116
|
background: white;
|
|
117
117
|
border-radius: 8px;
|
|
@@ -215,7 +215,6 @@ export class FloatingWindow extends RapidElement {
|
|
|
215
215
|
updated(changes) {
|
|
216
216
|
super.updated(changes);
|
|
217
217
|
if (changes.has('hidden')) {
|
|
218
|
-
this.classList.toggle('hidden', this.hidden);
|
|
219
218
|
// when hiding, reset positioning behavior to original
|
|
220
219
|
if (this.hidden && !changes.get('hidden')) {
|
|
221
220
|
if (this.defaultLeft === -1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingWindow.js","sourceRoot":"","sources":["../../../src/layout/FloatingWindow.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { getClasses } from '../utils';\nimport { FloatingTab } from '../display/FloatingTab';\n\nexport class FloatingWindow extends RapidElement {\n static get styles() {\n return css`\n .window.hidden {\n transform: translateX(100%);\n opacity: 0;\n pointer-events: none;\n }\n\n .window {\n transition: transform var(--transition-duration, 300ms) ease-in-out,\n opacity var(--transition-duration, 300ms) ease-in-out;\n position: fixed;\n z-index: 9999;\n top: 100px;\n background: white;\n border-radius: 8px;\n box-shadow: -4px 4px 20px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .window.chromeless {\n background: transparent;\n border-radius: 0;\n box-shadow: none;\n }\n\n .window.dragging {\n user-select: none;\n cursor: move;\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 6px;\n background: var(--header-color, var(--color-primary-light, #f3f4f6));\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n cursor: move;\n user-select: none;\n }\n\n .title {\n font-weight: 600;\n font-size: 16px;\n color: white;\n padding-left: 8px;\n }\n\n .close-button {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color calc(var(--transition-duration, 150ms) / 2)\n ease-in-out;\n }\n\n .close-button:hover {\n background-color: rgba(255, 255, 255, 0.2);\n }\n\n .close-button temba-icon {\n --icon-color: white;\n }\n\n .body {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n }\n\n .window.chromeless .body {\n padding: 0;\n }\n\n ::slotted(.drag-handle) {\n cursor: move;\n user-select: none;\n border: 1px solid red;\n }\n `;\n }\n\n @property({ type: String })\n header = '';\n\n @property({ type: Number })\n width = 500;\n\n @property({ type: Number })\n minHeight = 200;\n\n @property({ type: Number })\n maxHeight = 800;\n\n @property({ type: Number })\n top = 100;\n\n @property({ type: Number })\n left = -1; // -1 means calculate from right side\n\n @property({ type: Boolean })\n hidden = true;\n\n @property({ type: Boolean })\n dragging = false;\n\n @property({ type: Boolean })\n chromeless = false;\n\n @property({ type: String })\n color = '#6B7280';\n\n private dragStartX = 0;\n private dragStartY = 0;\n private dragOffsetX = 0;\n private dragOffsetY = 0;\n private positionFromRight = false;\n private defaultTop = 100;\n private defaultLeft = -1;\n\n public firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n\n // store the default position from properties\n this.defaultTop = this.top;\n this.defaultLeft = this.left;\n\n // determine if we should position from right side\n if (this.left === -1) {\n this.positionFromRight = true;\n }\n\n // set up drag handle listeners for chromeless windows\n if (this.chromeless) {\n this.setupDragHandles();\n }\n\n // listen for window resize to keep window in bounds\n window.addEventListener('resize', this.handleResize);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n window.removeEventListener('resize', this.handleResize);\n }\n\n private setupDragHandles() {\n // listen for mousedown on slotted content\n this.addEventListener('mousedown', this.handleSlotMouseDown);\n }\n\n private handleSlotMouseDown = (event: MouseEvent) => {\n // check if the target or any parent has the drag-handle class\n const target = event.target as HTMLElement;\n const dragHandle = target.closest('.drag-handle');\n\n if (!dragHandle) {\n return;\n }\n\n this.dragging = true;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragOffsetX = this.left;\n this.dragOffsetY = this.top;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n\n event.preventDefault();\n };\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('hidden')) {\n this.classList.toggle('hidden', this.hidden);\n\n // when hiding, reset positioning behavior to original\n if (this.hidden && !changes.get('hidden')) {\n if (this.defaultLeft === -1) {\n this.positionFromRight = true;\n }\n }\n\n // reset to default position when showing\n if (!this.hidden && changes.get('hidden')) {\n // reset top to default\n this.top = this.defaultTop;\n\n // if positioned from right, recalculate based on current viewport\n if (this.positionFromRight) {\n this.left = window.innerWidth - this.width - 20;\n } else {\n // reset left to default\n this.left = this.defaultLeft;\n }\n }\n }\n\n // setup drag handles if chromeless changed to true\n if (changes.has('chromeless') && this.chromeless) {\n this.setupDragHandles();\n }\n }\n\n private handleClose() {\n this.hidden = true;\n // show all tabs when window is closed\n FloatingTab.showAllTabs();\n this.fireCustomEvent(CustomEventType.DialogHidden);\n }\n\n private handleHeaderMouseDown(event: MouseEvent) {\n // don't start drag if clicking on close button\n if ((event.target as HTMLElement).closest('.close-button')) {\n return;\n }\n\n this.dragging = true;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragOffsetX = this.left;\n this.dragOffsetY = this.top;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n\n event.preventDefault();\n }\n\n private handleMouseMove = (event: MouseEvent) => {\n if (!this.dragging) return;\n\n const deltaX = event.clientX - this.dragStartX;\n const deltaY = event.clientY - this.dragStartY;\n\n this.left = this.dragOffsetX + deltaX;\n this.top = this.dragOffsetY + deltaY;\n\n // keep window within viewport bounds with 20px padding\n const padding = 20;\n this.left = Math.max(\n padding,\n Math.min(this.left, window.innerWidth - this.width - padding)\n );\n\n // get the actual rendered height of the window element\n const windowElement = this.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || this.maxHeight || window.innerHeight;\n const maxTop = Math.max(\n padding,\n window.innerHeight - currentHeight - padding\n );\n this.top = Math.max(padding, Math.min(this.top, maxTop));\n };\n\n private handleMouseUp = () => {\n this.dragging = false;\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n\n // once user drags the window, stop auto-positioning from right\n this.positionFromRight = false;\n };\n\n private handleResize = () => {\n // only constrain position if window is visible\n if (this.hidden) return;\n\n const padding = 20;\n const windowElement = this.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || this.maxHeight || window.innerHeight;\n\n // if positioned from right, always recalculate from right edge\n if (this.positionFromRight) {\n this.left = window.innerWidth - this.width - padding;\n } else {\n // only adjust left if out of bounds\n const minLeft = padding;\n const maxLeft = window.innerWidth - this.width - padding;\n\n if (this.left < minLeft) {\n this.left = minLeft;\n } else if (this.left > maxLeft) {\n this.left = maxLeft;\n }\n }\n\n // only adjust top if out of bounds\n const minTop = padding;\n const maxTop = Math.max(\n padding,\n window.innerHeight - currentHeight - padding\n );\n\n if (this.top < minTop) {\n this.top = minTop;\n } else if (this.top > maxTop) {\n this.top = maxTop;\n }\n };\n\n public show() {\n this.hidden = false;\n }\n\n public hide() {\n this.hidden = true;\n }\n\n public close() {\n this.hidden = true;\n // show all tabs when window is closed\n FloatingTab.showAllTabs();\n this.fireCustomEvent(CustomEventType.DialogHidden);\n }\n\n public render(): TemplateResult {\n const minHeightStyle = this.minHeight\n ? `min-height: ${this.minHeight}px;`\n : '';\n const maxHeightStyle = this.maxHeight\n ? `max-height: ${this.maxHeight}px;`\n : '';\n\n const windowStyle = `\n width: ${this.width}px;\n ${minHeightStyle}\n ${maxHeightStyle}\n top: ${this.top}px;\n left: ${this.left}px;\n --header-color: ${this.color};\n `;\n\n const windowClasses = getClasses({\n window: true,\n dragging: this.dragging,\n hidden: this.hidden,\n chromeless: this.chromeless\n });\n\n return html`\n <div class=\"${windowClasses}\" style=\"${windowStyle}\">\n ${!this.chromeless\n ? html`\n <div class=\"header\" @mousedown=${this.handleHeaderMouseDown}>\n <div class=\"title\">${this.header}</div>\n <button class=\"close-button\" @click=${this.handleClose}>\n <temba-icon name=\"close\" size=\"1.5\"></temba-icon>\n </button>\n </div>\n `\n : ''}\n <div class=\"body\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FloatingWindow.js","sourceRoot":"","sources":["../../../src/layout/FloatingWindow.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { getClasses } from '../utils';\nimport { FloatingTab } from '../display/FloatingTab';\n\nexport class FloatingWindow extends RapidElement {\n static get styles() {\n return css`\n .window.hidden {\n transform: translateX(100%);\n opacity: 0;\n pointer-events: none;\n }\n\n .window {\n transition: transform var(--transition-duration, 300ms) ease-in-out,\n opacity var(--transition-duration, 300ms) ease-in-out;\n position: fixed;\n z-index: 5000;\n top: 100px;\n background: white;\n border-radius: 8px;\n box-shadow: -4px 4px 20px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .window.chromeless {\n background: transparent;\n border-radius: 0;\n box-shadow: none;\n }\n\n .window.dragging {\n user-select: none;\n cursor: move;\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 6px;\n background: var(--header-color, var(--color-primary-light, #f3f4f6));\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n cursor: move;\n user-select: none;\n }\n\n .title {\n font-weight: 600;\n font-size: 16px;\n color: white;\n padding-left: 8px;\n }\n\n .close-button {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color calc(var(--transition-duration, 150ms) / 2)\n ease-in-out;\n }\n\n .close-button:hover {\n background-color: rgba(255, 255, 255, 0.2);\n }\n\n .close-button temba-icon {\n --icon-color: white;\n }\n\n .body {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n }\n\n .window.chromeless .body {\n padding: 0;\n }\n\n ::slotted(.drag-handle) {\n cursor: move;\n user-select: none;\n border: 1px solid red;\n }\n `;\n }\n\n @property({ type: String })\n header = '';\n\n @property({ type: Number })\n width = 500;\n\n @property({ type: Number })\n minHeight = 200;\n\n @property({ type: Number })\n maxHeight = 800;\n\n @property({ type: Number })\n top = 100;\n\n @property({ type: Number })\n left = -1; // -1 means calculate from right side\n\n @property({ type: Boolean })\n hidden = true;\n\n @property({ type: Boolean })\n dragging = false;\n\n @property({ type: Boolean })\n chromeless = false;\n\n @property({ type: String })\n color = '#6B7280';\n\n private dragStartX = 0;\n private dragStartY = 0;\n private dragOffsetX = 0;\n private dragOffsetY = 0;\n private positionFromRight = false;\n private defaultTop = 100;\n private defaultLeft = -1;\n\n public firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n\n // store the default position from properties\n this.defaultTop = this.top;\n this.defaultLeft = this.left;\n\n // determine if we should position from right side\n if (this.left === -1) {\n this.positionFromRight = true;\n }\n\n // set up drag handle listeners for chromeless windows\n if (this.chromeless) {\n this.setupDragHandles();\n }\n\n // listen for window resize to keep window in bounds\n window.addEventListener('resize', this.handleResize);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n window.removeEventListener('resize', this.handleResize);\n }\n\n private setupDragHandles() {\n // listen for mousedown on slotted content\n this.addEventListener('mousedown', this.handleSlotMouseDown);\n }\n\n private handleSlotMouseDown = (event: MouseEvent) => {\n // check if the target or any parent has the drag-handle class\n const target = event.target as HTMLElement;\n const dragHandle = target.closest('.drag-handle');\n\n if (!dragHandle) {\n return;\n }\n\n this.dragging = true;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragOffsetX = this.left;\n this.dragOffsetY = this.top;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n\n event.preventDefault();\n };\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('hidden')) {\n // when hiding, reset positioning behavior to original\n if (this.hidden && !changes.get('hidden')) {\n if (this.defaultLeft === -1) {\n this.positionFromRight = true;\n }\n }\n\n // reset to default position when showing\n if (!this.hidden && changes.get('hidden')) {\n // reset top to default\n this.top = this.defaultTop;\n\n // if positioned from right, recalculate based on current viewport\n if (this.positionFromRight) {\n this.left = window.innerWidth - this.width - 20;\n } else {\n // reset left to default\n this.left = this.defaultLeft;\n }\n }\n }\n\n // setup drag handles if chromeless changed to true\n if (changes.has('chromeless') && this.chromeless) {\n this.setupDragHandles();\n }\n }\n\n private handleClose() {\n this.hidden = true;\n // show all tabs when window is closed\n FloatingTab.showAllTabs();\n this.fireCustomEvent(CustomEventType.DialogHidden);\n }\n\n private handleHeaderMouseDown(event: MouseEvent) {\n // don't start drag if clicking on close button\n if ((event.target as HTMLElement).closest('.close-button')) {\n return;\n }\n\n this.dragging = true;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragOffsetX = this.left;\n this.dragOffsetY = this.top;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n\n event.preventDefault();\n }\n\n private handleMouseMove = (event: MouseEvent) => {\n if (!this.dragging) return;\n\n const deltaX = event.clientX - this.dragStartX;\n const deltaY = event.clientY - this.dragStartY;\n\n this.left = this.dragOffsetX + deltaX;\n this.top = this.dragOffsetY + deltaY;\n\n // keep window within viewport bounds with 20px padding\n const padding = 20;\n this.left = Math.max(\n padding,\n Math.min(this.left, window.innerWidth - this.width - padding)\n );\n\n // get the actual rendered height of the window element\n const windowElement = this.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || this.maxHeight || window.innerHeight;\n const maxTop = Math.max(\n padding,\n window.innerHeight - currentHeight - padding\n );\n this.top = Math.max(padding, Math.min(this.top, maxTop));\n };\n\n private handleMouseUp = () => {\n this.dragging = false;\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n\n // once user drags the window, stop auto-positioning from right\n this.positionFromRight = false;\n };\n\n private handleResize = () => {\n // only constrain position if window is visible\n if (this.hidden) return;\n\n const padding = 20;\n const windowElement = this.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || this.maxHeight || window.innerHeight;\n\n // if positioned from right, always recalculate from right edge\n if (this.positionFromRight) {\n this.left = window.innerWidth - this.width - padding;\n } else {\n // only adjust left if out of bounds\n const minLeft = padding;\n const maxLeft = window.innerWidth - this.width - padding;\n\n if (this.left < minLeft) {\n this.left = minLeft;\n } else if (this.left > maxLeft) {\n this.left = maxLeft;\n }\n }\n\n // only adjust top if out of bounds\n const minTop = padding;\n const maxTop = Math.max(\n padding,\n window.innerHeight - currentHeight - padding\n );\n\n if (this.top < minTop) {\n this.top = minTop;\n } else if (this.top > maxTop) {\n this.top = maxTop;\n }\n };\n\n public show() {\n this.hidden = false;\n }\n\n public hide() {\n this.hidden = true;\n }\n\n public close() {\n this.hidden = true;\n // show all tabs when window is closed\n FloatingTab.showAllTabs();\n this.fireCustomEvent(CustomEventType.DialogHidden);\n }\n\n public render(): TemplateResult {\n const minHeightStyle = this.minHeight\n ? `min-height: ${this.minHeight}px;`\n : '';\n const maxHeightStyle = this.maxHeight\n ? `max-height: ${this.maxHeight}px;`\n : '';\n\n const windowStyle = `\n width: ${this.width}px;\n ${minHeightStyle}\n ${maxHeightStyle}\n top: ${this.top}px;\n left: ${this.left}px;\n --header-color: ${this.color};\n `;\n\n const windowClasses = getClasses({\n window: true,\n dragging: this.dragging,\n hidden: this.hidden,\n chromeless: this.chromeless\n });\n\n return html`\n <div class=\"${windowClasses}\" style=\"${windowStyle}\">\n ${!this.chromeless\n ? html`\n <div class=\"header\" @mousedown=${this.handleHeaderMouseDown}>\n <div class=\"title\">${this.header}</div>\n <button class=\"close-button\" @click=${this.handleClose}>\n <temba-icon name=\"close\" size=\"1.5\"></temba-icon>\n </button>\n </div>\n `\n : ''}\n <div class=\"body\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentMenu.js","sourceRoot":"","sources":["../../../src/list/ContentMenu.ts"],"names":[],"mappings":";AAAA,OAAO,EAAkB,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAe,MAAM,UAAU,CAAC;AAE/C,MAAM,OAAO,GAAG;IACd,sBAAsB,EAAE,GAAG;IAC3B,aAAa,EAAE,GAAG;CACnB,CAAC;AAeF,MAAM,CAAN,IAAY,mBAMX;AAND,WAAY,mBAAmB;IAC7B,oCAAa,CAAA;IACb,gCAAS,CAAA;IACT,4CAAqB,CAAA;IACrB,sCAAe,CAAA;IACf,0CAAmB,CAAA;AACrB,CAAC,EANW,mBAAmB,KAAnB,mBAAmB,QAM9B;AAED,MAAM,OAAO,WAAY,SAAQ,YAAY;IAA7C;;
|
|
1
|
+
{"version":3,"file":"ContentMenu.js","sourceRoot":"","sources":["../../../src/list/ContentMenu.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, html, css } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { CustomEventType } from '../interfaces';\n\nimport { RapidElement } from '../RapidElement';\nimport { getUrl, WebResponse } from '../utils';\n\nconst HEADERS = {\n 'X-Temba-Content-Menu': '1',\n 'X-Temba-Spa': '1'\n};\nexport interface ContentMenuItem {\n type: string;\n as_button: boolean;\n label: string;\n url: string;\n disabled: boolean;\n modal_id: string;\n on_submit: string;\n primary: boolean;\n title: string;\n on_click: null;\n link_class: string;\n}\n\nexport enum ContentMenuItemType {\n LINK = 'link',\n JS = 'js',\n URL_POST = 'url_post',\n MODAX = 'modax',\n DIVIDER = 'divider'\n}\n\nexport class ContentMenu extends RapidElement {\n static get styles() {\n return css`\n :host {\n tabindex: 0;\n z-index: 5000;\n }\n .container {\n --button-y: 0.4em;\n --button-x: 1em;\n display: flex;\n align-items: center;\n }\n\n .button_item,\n .primary_button_item {\n margin-left: 1rem;\n }\n\n temba-button {\n margin-right: 0.5rem;\n }\n .toggle {\n --icon-color: rgb(102, 102, 102);\n padding: 0.4em;\n }\n\n .toggle:hover {\n background: rgba(0, 0, 0, 0.05);\n border-radius: var(--curvature);\n --icon-color: rgb(136, 136, 136);\n }\n\n .dropdown {\n padding: 1rem 1.5rem;\n color: rgb(45, 45, 45);\n z-index: 50;\n min-width: 200px;\n tabindex: 0;\n }\n\n .divider {\n border-bottom: 1px solid rgb(237, 237, 237);\n margin: 1rem -1.5em;\n }\n\n .item {\n white-space: nowrap;\n margin: 0.2em 0em;\n font-size: 1.1rem;\n cursor: pointer;\n font-weight: 400;\n tabindex: 0;\n }\n\n .item:hover {\n color: var(--color-link-primary);\n }\n `;\n }\n\n @property({ type: String })\n endpoint: string;\n\n @property({ type: Number })\n legacy: number;\n\n @property({ type: Array, attribute: false })\n buttons: ContentMenuItem[] = [];\n\n @property({ type: Array, attribute: false })\n items: ContentMenuItem[] = [];\n\n @property({ type: Boolean })\n arrowTopLeft: boolean;\n\n private fetchContentMenu() {\n const url = this.endpoint;\n if (url) {\n const legacy = this.legacy;\n const headers = HEADERS;\n if (legacy) {\n delete headers['Temba-Spa'];\n }\n\n //ok, fetch the content menu\n getUrl(url, null, headers)\n .then((response: WebResponse) => {\n const json = response.json;\n const contentMenu = json.items as ContentMenuItem[];\n\n //populate (or initialize) the buttons and items\n if (contentMenu) {\n this.buttons = contentMenu.filter((item) => item.as_button);\n this.items = contentMenu.filter((item) => !item.as_button);\n } else {\n this.buttons = [];\n this.items = [];\n }\n\n //fire custom loaded event type when we're finished\n this.fireCustomEvent(CustomEventType.Loaded, {\n buttons: this.buttons,\n items: this.items\n });\n })\n .catch((error: any) => {\n this.fireCustomEvent(CustomEventType.Loaded, {\n buttons: this.buttons,\n items: this.items\n });\n\n console.error(error);\n });\n }\n }\n\n public refresh() {\n this.fetchContentMenu();\n }\n\n protected updated(changes: Map<string, any>) {\n super.updated(changes);\n if (changes.has('endpoint') || changes.has('legacy')) {\n this.fetchContentMenu();\n }\n }\n\n private handleItemClicked(item: ContentMenuItem, event: MouseEvent) {\n this.fireCustomEvent(CustomEventType.Selection, { item, event });\n }\n\n public render(): TemplateResult {\n return html`\n <div class=\"container\">\n ${this.buttons.map((button) => {\n return html`<temba-button\n class=\"${button.primary ? 'primary_button_item' : 'button_item'}\"\n name=${button.label}\n @click=${(event) => this.handleItemClicked(button, event)}\n >\n ${button.label}\n </temba-button>`;\n })}\n ${this.items && this.items.length > 0\n ? html`<temba-dropdown>\n <div slot=\"toggle\" class=\"toggle\">\n <temba-icon name=\"menu\" size=\"1.5\"></temba-icon>\n </div>\n <div slot=\"dropdown\" class=\"dropdown\">\n ${this.items.map((item) => {\n if (item.type === ContentMenuItemType.DIVIDER) {\n return html` <div class=\"divider\"></div>`;\n } else {\n return html` <div\n class=\"item\"\n name=${item.label}\n @click=${(event) => this.handleItemClicked(item, event)}\n >\n ${item.label}\n </div>`;\n }\n })}\n </div>\n </temba-dropdown>`\n : null}\n </div>\n `;\n }\n}\n"]}
|
|
@@ -464,8 +464,9 @@ export class SortableList extends RapidElement {
|
|
|
464
464
|
// use swap-based logic - report which indexes need to be swapped
|
|
465
465
|
const fromIdx = originalDragIdx;
|
|
466
466
|
const toIdx = this.pendingDropIndex;
|
|
467
|
-
// only fire if the position actually changed
|
|
468
|
-
|
|
467
|
+
// only fire if the position actually changed AND this is not an external drag
|
|
468
|
+
// External drags are handled by external drop handlers
|
|
469
|
+
if (fromIdx !== toIdx && !this.isExternalDrag) {
|
|
469
470
|
this.fireCustomEvent(CustomEventType.OrderChanged, {
|
|
470
471
|
swap: [fromIdx, toIdx]
|
|
471
472
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortableList.js","sourceRoot":"","sources":["../../../src/list/SortableList.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { CustomEventType } from '../interfaces';\nimport { RapidElement } from '../RapidElement';\n\n/**\n * A simple list that can be sorted by dragging\n */\n\n// how far we have to drag before it starts\nconst DRAG_THRESHOLD = 2;\n\n// padding around container for external drag detection\nconst EXTERNAL_DRAG_PADDING = 50;\n\nexport class SortableList extends RapidElement {\n originalDownDisplay: string;\n static get styles() {\n return css`\n :host {\n margin: auto;\n }\n\n .container {\n user-select: none;\n position: relative;\n display: grid;\n grid-template-columns: 1fr;\n }\n\n .container.horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n }\n\n .dragging {\n background: var(--color-selection);\n }\n\n .slot {\n flex-grow: 1;\n }\n\n slot > * {\n user-select: none;\n }\n\n temba-icon {\n opacity: 0.1;\n padding: 0.2em 0.5em;\n transition: all 300ms ease-in-out;\n }\n `;\n }\n\n @property({ type: String })\n draggingId: string;\n\n @property({ type: Boolean })\n horizontal: boolean = false;\n\n @property({ type: String })\n dropTargetId: string;\n\n @property({ type: String })\n dragHandle: string;\n\n @property({ type: String })\n gap: string = '0em';\n\n @property({ type: Boolean })\n externalDrag: boolean = false;\n\n /**\n * Optional callback to allow parent components to customize the ghost node.\n * Called after the ghost node is cloned but before it is appended to the DOM.\n */\n @property({ attribute: false })\n prepareGhost?: (ghost: HTMLElement) => void;\n\n ghostElement: HTMLDivElement = null;\n downEle: HTMLDivElement = null;\n originalElementRect: DOMRect = null; // Store original dimensions\n originalDragIndex: number = -1; // Store original index before moving element\n xOffset = 0;\n yOffset = 0;\n yDown = 0;\n xDown = 0;\n\n draggingIdx = -1;\n draggingEle = null;\n dropPlaceholder: HTMLDivElement = null;\n pendingDropIndex = -1;\n pendingTargetElement: HTMLElement = null;\n isExternalDrag = false;\n\n private clickBlocker: ((e: MouseEvent) => void) | null = null;\n\n public constructor() {\n super();\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseUp = this.handleMouseUp.bind(this);\n this.handleMouseDown = this.handleMouseDown.bind(this);\n }\n\n private getSortableElements(): Element[] {\n const eles = this.shadowRoot\n .querySelector('slot')\n .assignedElements()\n .filter(\n (ele) =>\n ele.classList.contains('sortable') &&\n !ele.classList.contains('drop-placeholder')\n );\n return eles;\n }\n\n private isMouseOverContainer(mouseX: number, mouseY: number): boolean {\n const container = this.shadowRoot.querySelector('.container');\n if (!container) return false;\n\n const rect = container.getBoundingClientRect();\n // add some padding to make it easier to stay within the container\n return (\n mouseX >= rect.left - EXTERNAL_DRAG_PADDING &&\n mouseX <= rect.right + EXTERNAL_DRAG_PADDING &&\n mouseY >= rect.top - EXTERNAL_DRAG_PADDING &&\n mouseY <= rect.bottom + EXTERNAL_DRAG_PADDING\n );\n }\n\n private cloneElementWithState(element: HTMLElement): HTMLElement {\n // First create a basic clone\n const clone = element.cloneNode(true) as HTMLElement;\n\n // Helper function to copy form element values recursively\n const copyFormValues = (original: HTMLElement, cloned: HTMLElement) => {\n try {\n // Copy input values\n const originalInputs = original.querySelectorAll(\n 'input, textarea, select'\n );\n const clonedInputs = cloned.querySelectorAll('input, textarea, select');\n\n originalInputs.forEach((originalInput, index) => {\n const clonedInput = clonedInputs[index] as\n | HTMLInputElement\n | HTMLTextAreaElement\n | HTMLSelectElement;\n if (clonedInput) {\n if (originalInput instanceof HTMLInputElement) {\n const originalHtmlInput = originalInput as HTMLInputElement;\n const clonedHtmlInput = clonedInput as HTMLInputElement;\n\n if (\n originalHtmlInput.type === 'checkbox' ||\n originalHtmlInput.type === 'radio'\n ) {\n clonedHtmlInput.checked = originalHtmlInput.checked;\n } else {\n clonedHtmlInput.value = originalHtmlInput.value;\n }\n } else if (originalInput instanceof HTMLTextAreaElement) {\n (clonedInput as HTMLTextAreaElement).value = originalInput.value;\n } else if (originalInput instanceof HTMLSelectElement) {\n (clonedInput as HTMLSelectElement).selectedIndex =\n originalInput.selectedIndex;\n }\n }\n });\n\n // Copy properties from all custom elements that might have a value property\n const allOriginalElements = Array.from(original.querySelectorAll('*'));\n const allClonedElements = Array.from(cloned.querySelectorAll('*'));\n\n allOriginalElements.forEach((originalEl, index) => {\n const clonedEl = allClonedElements[index];\n if (clonedEl && originalEl) {\n // Special handling for temba components\n if (\n originalEl.tagName &&\n originalEl.tagName.toLowerCase().startsWith('temba-')\n ) {\n try {\n // Copy common temba component properties\n const tembaProps = [\n 'value',\n 'values',\n 'selectedValue',\n 'checked',\n 'selected',\n 'textContent'\n ];\n tembaProps.forEach((prop) => {\n if (\n prop in originalEl &&\n (originalEl as any)[prop] !== undefined\n ) {\n (clonedEl as any)[prop] = (originalEl as any)[prop];\n }\n });\n\n // Copy all attributes for temba components to preserve state\n Array.from(originalEl.attributes).forEach((attr) => {\n clonedEl.setAttribute(attr.name, attr.value);\n });\n } catch (e) {\n // Ignore errors when copying temba properties\n }\n } else {\n // Try to copy value property for other elements\n try {\n if (\n 'value' in originalEl &&\n (originalEl as any).value !== undefined\n ) {\n (clonedEl as any).value = (originalEl as any).value;\n }\n } catch (e) {\n // Ignore errors when copying properties\n }\n\n // Copy data attributes that might contain state\n try {\n Array.from(originalEl.attributes).forEach((attr) => {\n if (\n attr.name.startsWith('data-') ||\n attr.name.startsWith('aria-')\n ) {\n clonedEl.setAttribute(attr.name, attr.value);\n }\n });\n } catch (e) {\n // Ignore errors when copying attributes\n }\n }\n }\n });\n } catch (e) {\n // If anything fails, just return the basic clone\n console.warn('Failed to copy form values in cloneElementWithState:', e);\n }\n };\n\n // Copy form values for the root element and all descendants\n copyFormValues(element, clone);\n\n return clone;\n }\n\n public getIds() {\n return this.getSortableElements().map((ele) => ele.id);\n }\n\n private getRowIndex(id: string): number {\n return this.getSortableElements().findIndex((ele) => ele.id === id);\n }\n\n private getDropTargetInfo(\n mouseX: number,\n mouseY: number\n ): { element: HTMLDivElement; insertAfter: boolean } | null {\n const elements = this.getSortableElements().filter(\n (ele) => ele.id !== this.draggingEle?.id\n );\n\n if (elements.length === 0) return null;\n\n if (this.horizontal) {\n // For horizontal layout, find the insertion point based on mouse X position\n for (let i = 0; i < elements.length; i++) {\n const ele = elements[i];\n const rect = ele.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n\n if (mouseX < centerX) {\n // Insert before this element\n return { element: ele as HTMLDivElement, insertAfter: false };\n }\n }\n // If we're past all elements, insert after the last one\n return {\n element: elements[elements.length - 1] as HTMLDivElement,\n insertAfter: true\n };\n } else {\n // For vertical layout, find the insertion point based on mouse Y position\n for (let i = 0; i < elements.length; i++) {\n const ele = elements[i];\n const rect = ele.getBoundingClientRect();\n const centerY = rect.top + rect.height / 2;\n\n if (mouseY < centerY) {\n // Insert before this element\n return { element: ele as HTMLDivElement, insertAfter: false };\n }\n }\n // If we're past all elements, insert after the last one\n return {\n element: elements[elements.length - 1] as HTMLDivElement,\n insertAfter: true\n };\n }\n }\n\n private showDropPlaceholder(\n targetElement: HTMLElement,\n insertAfter: boolean\n ) {\n this.hideDropPlaceholder();\n\n if (!targetElement || !this.draggingEle) return;\n\n // Don't show placeholder if we're targeting the dragging element itself\n if (targetElement === this.draggingEle) return;\n\n this.dropPlaceholder = document.createElement('div');\n\n this.dropPlaceholder.className = 'drop-placeholder sortable';\n\n // Copy dimensions from the original element (before it was hidden)\n if (this.originalElementRect) {\n const rect = this.originalElementRect;\n this.dropPlaceholder.style.width = rect.width + 'px';\n this.dropPlaceholder.style.height = rect.height + 'px';\n this.dropPlaceholder.style.minHeight = rect.height + 'px';\n this.dropPlaceholder.style.borderRadius = 'var(--curvature)';\n this.dropPlaceholder.style.flexShrink = '0';\n this.dropPlaceholder.style.background = '#f3f4f6';\n this.dropPlaceholder.style.border = '2px dashed #d1d5db';\n }\n\n // Insert the placeholder in the correct position in the DOM\n if (insertAfter) {\n targetElement.insertAdjacentElement('afterend', this.dropPlaceholder);\n } else {\n targetElement.insertAdjacentElement('beforebegin', this.dropPlaceholder);\n }\n }\n\n private hideDropPlaceholder() {\n if (this.dropPlaceholder) {\n this.dropPlaceholder.remove();\n this.dropPlaceholder = null;\n }\n }\n\n private showInitialPlaceholder() {\n if (!this.downEle || !this.originalElementRect) return;\n\n this.dropPlaceholder = document.createElement('div');\n this.dropPlaceholder.className = 'drop-placeholder sortable';\n\n // Copy dimensions from the original element\n const rect = this.originalElementRect;\n this.dropPlaceholder.style.width = rect.width + 'px';\n this.dropPlaceholder.style.height = rect.height + 'px';\n this.dropPlaceholder.style.minHeight = rect.height + 'px';\n this.dropPlaceholder.style.borderRadius = 'var(--curvature)';\n this.dropPlaceholder.style.flexShrink = '0';\n this.dropPlaceholder.style.background = '#f3f4f6';\n this.dropPlaceholder.style.border = '2px dashed #d1d5db';\n\n // Insert the placeholder right after the hidden original element\n this.downEle.insertAdjacentElement('afterend', this.dropPlaceholder);\n }\n\n private handleMouseDown(event: MouseEvent) {\n let ele = event.target as HTMLDivElement;\n\n // if we have a drag handle, only allow dragging from that element\n if (this.dragHandle) {\n if (!ele.classList.contains(this.dragHandle)) {\n return;\n }\n }\n\n ele = ele.closest('.sortable');\n if (ele) {\n event.preventDefault();\n event.stopPropagation();\n this.downEle = ele;\n this.draggingId = ele.id;\n this.draggingIdx = this.getRowIndex(ele.id);\n this.draggingEle = ele;\n\n // Use getBoundingClientRect for accurate offsets and store original dimensions\n const rect = ele.getBoundingClientRect();\n this.originalElementRect = rect; // Store the original rect before hiding\n this.xOffset = event.clientX - rect.left;\n this.yOffset = event.clientY - rect.top;\n this.yDown = event.clientY;\n this.xDown = event.clientX;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n }\n }\n\n private handleMouseMove(event: MouseEvent) {\n if (\n !this.ghostElement &&\n this.downEle &&\n (Math.abs(event.clientY - this.yDown) > DRAG_THRESHOLD ||\n Math.abs(event.clientX - this.xDown) > DRAG_THRESHOLD)\n ) {\n this.fireCustomEvent(CustomEventType.DragStart, {\n id: this.downEle.id\n });\n\n // Capture the original index BEFORE hiding the element\n this.originalDragIndex = this.getRowIndex(this.downEle.id);\n\n // Create a clone of the element to use as the ghost\n this.ghostElement = this.cloneElementWithState(\n this.downEle\n ) as HTMLDivElement;\n\n // Hide the original element during dragging using inline styles\n this.originalDownDisplay = this.downEle.style.display;\n this.downEle.style.display = 'none';\n\n // Style the clone as a ghost\n this.ghostElement.classList.add('ghost');\n\n // Use the stored original dimensions for positioning\n const rect = this.originalElementRect;\n\n this.ghostElement.style.position = 'fixed';\n this.ghostElement.style.left = event.clientX - this.xOffset + 'px';\n this.ghostElement.style.top = event.clientY - this.yOffset + 'px';\n this.ghostElement.style.width = rect.width + 'px';\n this.ghostElement.style.height = rect.height + 'px';\n this.ghostElement.style.zIndex = '99999';\n this.ghostElement.style.opacity = '0.8';\n this.ghostElement.style.transform = 'scale(1.03)';\n\n // allow component to customize the ghost node\n if (this.prepareGhost) {\n this.prepareGhost(this.ghostElement);\n }\n\n // Add the clone to document.body for dragging\n document.body.appendChild(this.ghostElement);\n\n // Show initial placeholder in the original position to maintain layout\n this.showInitialPlaceholder();\n\n // Add global click blocker when drag starts\n if (!this.clickBlocker) {\n this.clickBlocker = (e: MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n };\n // Use capture phase to intercept clicks before they reach any elements\n document.addEventListener('click', this.clickBlocker, true);\n }\n }\n\n if (this.ghostElement) {\n this.ghostElement.style.left = event.clientX - this.xOffset + 'px';\n this.ghostElement.style.top = event.clientY - this.yOffset + 'px';\n\n // check if the drag is over the container (only if external dragging is allowed)\n const isOverContainer = this.externalDrag\n ? this.isMouseOverContainer(event.clientX, event.clientY)\n : true; // always consider \"over container\" if external drag is disabled\n\n // detect transition between internal and external drag (only if allowed)\n if (this.externalDrag && !isOverContainer && !this.isExternalDrag) {\n // transitioning to external drag\n this.isExternalDrag = true;\n this.hideDropPlaceholder();\n\n // hide the ghost element when dragging externally\n if (this.ghostElement) {\n this.ghostElement.style.display = 'none';\n }\n\n this.fireCustomEvent(CustomEventType.DragExternal, {\n id: this.downEle.id,\n mouseX: event.clientX,\n mouseY: event.clientY\n });\n } else if (this.externalDrag && isOverContainer && this.isExternalDrag) {\n // transitioning back to internal drag\n this.isExternalDrag = false;\n\n // show the ghost element again when dragging internally\n if (this.ghostElement) {\n this.ghostElement.style.display = 'block';\n }\n\n this.fireCustomEvent(CustomEventType.DragInternal, {\n id: this.downEle.id\n });\n }\n\n // only show drop placeholder and calculate drop position if internal drag\n if (!this.isExternalDrag) {\n const targetInfo = this.getDropTargetInfo(event.clientX, event.clientY);\n if (targetInfo) {\n const { element: targetElement, insertAfter } = targetInfo;\n const targetIdx = this.getRowIndex(targetElement.id);\n\n // Use the original drag index we captured before moving the element\n const originalDragIdx = this.originalDragIndex;\n\n // Calculate where the dragged element will end up in the final array\n // targetIdx is the position of target element in current DOM (missing dragged element)\n\n let dropIdx;\n if (targetIdx < originalDragIdx) {\n // Target is before the original drag position - moving backward\n dropIdx = insertAfter ? targetIdx + 1 : targetIdx;\n } else {\n // Target was originally after the drag position - moving forward\n // When moving the dragged element forward (i.e., to a higher index), the targetIdx is based on the current DOM,\n // which no longer includes the dragged element. This means all elements after the original position have shifted left by one,\n // so we need to subtract 1 from targetIdx to get the correct insertion index. If inserting after the target, we use targetIdx as is.\n dropIdx = insertAfter ? targetIdx : targetIdx - 1;\n }\n\n // Store pending drop info but don't fire event yet\n this.dropTargetId = targetElement.id;\n this.pendingDropIndex = dropIdx;\n this.pendingTargetElement = targetElement;\n\n // Show drop placeholder\n this.showDropPlaceholder(targetElement, insertAfter);\n } else {\n this.hideDropPlaceholder();\n this.dropTargetId = null;\n this.pendingDropIndex = -1;\n this.pendingTargetElement = null;\n }\n } else {\n // external drag - continue firing external drag events with updated position\n this.fireCustomEvent(CustomEventType.DragExternal, {\n id: this.downEle.id,\n mouseX: event.clientX,\n mouseY: event.clientY\n });\n }\n }\n }\n\n private handleMouseUp(evt: MouseEvent) {\n if (this.draggingId && this.ghostElement) {\n evt.preventDefault();\n evt.stopPropagation();\n\n // Remove the ghost clone from document.body\n if (this.ghostElement) {\n this.ghostElement.remove();\n }\n\n // Restore visibility of the original element by clearing inline styles\n if (this.downEle) {\n this.downEle.style.display = this.originalDownDisplay;\n }\n\n // Clear visual effects before firing events\n this.hideDropPlaceholder();\n\n // fire the order changed event only when dropped if we have a valid drop position\n if (\n !this.isExternalDrag &&\n this.pendingDropIndex >= 0 &&\n this.pendingTargetElement\n ) {\n // Use the original drag index we captured before hiding the element\n const originalDragIdx = this.originalDragIndex;\n\n // use swap-based logic - report which indexes need to be swapped\n const fromIdx = originalDragIdx;\n const toIdx = this.pendingDropIndex;\n\n // only fire if the position actually changed\n if (fromIdx !== toIdx) {\n this.fireCustomEvent(CustomEventType.OrderChanged, {\n swap: [fromIdx, toIdx]\n });\n }\n }\n\n this.fireCustomEvent(CustomEventType.DragStop, {\n id: this.draggingId,\n isExternal: this.isExternalDrag,\n mouseX: evt.clientX,\n mouseY: evt.clientY\n });\n\n this.draggingId = null;\n this.dropTargetId = null;\n this.downEle = null;\n this.originalElementRect = null;\n this.originalDragIndex = -1;\n this.pendingDropIndex = -1;\n this.pendingTargetElement = null;\n this.isExternalDrag = false;\n\n // Clear the ghost reference since we removed it\n this.ghostElement = null;\n\n this.hideDropPlaceholder();\n\n // Keep the click blocker active for a short time after drop\n if (this.clickBlocker) {\n // We'll clean it up after a timeout\n setTimeout(() => {\n if (this.clickBlocker) {\n document.removeEventListener('click', this.clickBlocker, true);\n this.clickBlocker = null;\n }\n }, 100);\n }\n }\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n this.dispatchEvent(new Event('change'));\n }\n\n public render(): TemplateResult {\n return html`\n <div\n class=\"container ${this.horizontal ? 'horizontal' : ''}\"\n style=\"gap: ${this.gap}\"\n >\n <slot @mousedown=${this.handleMouseDown}></slot>\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SortableList.js","sourceRoot":"","sources":["../../../src/list/SortableList.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { CustomEventType } from '../interfaces';\nimport { RapidElement } from '../RapidElement';\n\n/**\n * A simple list that can be sorted by dragging\n */\n\n// how far we have to drag before it starts\nconst DRAG_THRESHOLD = 2;\n\n// padding around container for external drag detection\nconst EXTERNAL_DRAG_PADDING = 50;\n\nexport class SortableList extends RapidElement {\n originalDownDisplay: string;\n static get styles() {\n return css`\n :host {\n margin: auto;\n }\n\n .container {\n user-select: none;\n position: relative;\n display: grid;\n grid-template-columns: 1fr;\n }\n\n .container.horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n }\n\n .dragging {\n background: var(--color-selection);\n }\n\n .slot {\n flex-grow: 1;\n }\n\n slot > * {\n user-select: none;\n }\n\n temba-icon {\n opacity: 0.1;\n padding: 0.2em 0.5em;\n transition: all 300ms ease-in-out;\n }\n `;\n }\n\n @property({ type: String })\n draggingId: string;\n\n @property({ type: Boolean })\n horizontal: boolean = false;\n\n @property({ type: String })\n dropTargetId: string;\n\n @property({ type: String })\n dragHandle: string;\n\n @property({ type: String })\n gap: string = '0em';\n\n @property({ type: Boolean })\n externalDrag: boolean = false;\n\n /**\n * Optional callback to allow parent components to customize the ghost node.\n * Called after the ghost node is cloned but before it is appended to the DOM.\n */\n @property({ attribute: false })\n prepareGhost?: (ghost: HTMLElement) => void;\n\n ghostElement: HTMLDivElement = null;\n downEle: HTMLDivElement = null;\n originalElementRect: DOMRect = null; // Store original dimensions\n originalDragIndex: number = -1; // Store original index before moving element\n xOffset = 0;\n yOffset = 0;\n yDown = 0;\n xDown = 0;\n\n draggingIdx = -1;\n draggingEle = null;\n dropPlaceholder: HTMLDivElement = null;\n pendingDropIndex = -1;\n pendingTargetElement: HTMLElement = null;\n isExternalDrag = false;\n\n private clickBlocker: ((e: MouseEvent) => void) | null = null;\n\n public constructor() {\n super();\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseUp = this.handleMouseUp.bind(this);\n this.handleMouseDown = this.handleMouseDown.bind(this);\n }\n\n private getSortableElements(): Element[] {\n const eles = this.shadowRoot\n .querySelector('slot')\n .assignedElements()\n .filter(\n (ele) =>\n ele.classList.contains('sortable') &&\n !ele.classList.contains('drop-placeholder')\n );\n return eles;\n }\n\n private isMouseOverContainer(mouseX: number, mouseY: number): boolean {\n const container = this.shadowRoot.querySelector('.container');\n if (!container) return false;\n\n const rect = container.getBoundingClientRect();\n // add some padding to make it easier to stay within the container\n return (\n mouseX >= rect.left - EXTERNAL_DRAG_PADDING &&\n mouseX <= rect.right + EXTERNAL_DRAG_PADDING &&\n mouseY >= rect.top - EXTERNAL_DRAG_PADDING &&\n mouseY <= rect.bottom + EXTERNAL_DRAG_PADDING\n );\n }\n\n private cloneElementWithState(element: HTMLElement): HTMLElement {\n // First create a basic clone\n const clone = element.cloneNode(true) as HTMLElement;\n\n // Helper function to copy form element values recursively\n const copyFormValues = (original: HTMLElement, cloned: HTMLElement) => {\n try {\n // Copy input values\n const originalInputs = original.querySelectorAll(\n 'input, textarea, select'\n );\n const clonedInputs = cloned.querySelectorAll('input, textarea, select');\n\n originalInputs.forEach((originalInput, index) => {\n const clonedInput = clonedInputs[index] as\n | HTMLInputElement\n | HTMLTextAreaElement\n | HTMLSelectElement;\n if (clonedInput) {\n if (originalInput instanceof HTMLInputElement) {\n const originalHtmlInput = originalInput as HTMLInputElement;\n const clonedHtmlInput = clonedInput as HTMLInputElement;\n\n if (\n originalHtmlInput.type === 'checkbox' ||\n originalHtmlInput.type === 'radio'\n ) {\n clonedHtmlInput.checked = originalHtmlInput.checked;\n } else {\n clonedHtmlInput.value = originalHtmlInput.value;\n }\n } else if (originalInput instanceof HTMLTextAreaElement) {\n (clonedInput as HTMLTextAreaElement).value = originalInput.value;\n } else if (originalInput instanceof HTMLSelectElement) {\n (clonedInput as HTMLSelectElement).selectedIndex =\n originalInput.selectedIndex;\n }\n }\n });\n\n // Copy properties from all custom elements that might have a value property\n const allOriginalElements = Array.from(original.querySelectorAll('*'));\n const allClonedElements = Array.from(cloned.querySelectorAll('*'));\n\n allOriginalElements.forEach((originalEl, index) => {\n const clonedEl = allClonedElements[index];\n if (clonedEl && originalEl) {\n // Special handling for temba components\n if (\n originalEl.tagName &&\n originalEl.tagName.toLowerCase().startsWith('temba-')\n ) {\n try {\n // Copy common temba component properties\n const tembaProps = [\n 'value',\n 'values',\n 'selectedValue',\n 'checked',\n 'selected',\n 'textContent'\n ];\n tembaProps.forEach((prop) => {\n if (\n prop in originalEl &&\n (originalEl as any)[prop] !== undefined\n ) {\n (clonedEl as any)[prop] = (originalEl as any)[prop];\n }\n });\n\n // Copy all attributes for temba components to preserve state\n Array.from(originalEl.attributes).forEach((attr) => {\n clonedEl.setAttribute(attr.name, attr.value);\n });\n } catch (e) {\n // Ignore errors when copying temba properties\n }\n } else {\n // Try to copy value property for other elements\n try {\n if (\n 'value' in originalEl &&\n (originalEl as any).value !== undefined\n ) {\n (clonedEl as any).value = (originalEl as any).value;\n }\n } catch (e) {\n // Ignore errors when copying properties\n }\n\n // Copy data attributes that might contain state\n try {\n Array.from(originalEl.attributes).forEach((attr) => {\n if (\n attr.name.startsWith('data-') ||\n attr.name.startsWith('aria-')\n ) {\n clonedEl.setAttribute(attr.name, attr.value);\n }\n });\n } catch (e) {\n // Ignore errors when copying attributes\n }\n }\n }\n });\n } catch (e) {\n // If anything fails, just return the basic clone\n console.warn('Failed to copy form values in cloneElementWithState:', e);\n }\n };\n\n // Copy form values for the root element and all descendants\n copyFormValues(element, clone);\n\n return clone;\n }\n\n public getIds() {\n return this.getSortableElements().map((ele) => ele.id);\n }\n\n private getRowIndex(id: string): number {\n return this.getSortableElements().findIndex((ele) => ele.id === id);\n }\n\n private getDropTargetInfo(\n mouseX: number,\n mouseY: number\n ): { element: HTMLDivElement; insertAfter: boolean } | null {\n const elements = this.getSortableElements().filter(\n (ele) => ele.id !== this.draggingEle?.id\n );\n\n if (elements.length === 0) return null;\n\n if (this.horizontal) {\n // For horizontal layout, find the insertion point based on mouse X position\n for (let i = 0; i < elements.length; i++) {\n const ele = elements[i];\n const rect = ele.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n\n if (mouseX < centerX) {\n // Insert before this element\n return { element: ele as HTMLDivElement, insertAfter: false };\n }\n }\n // If we're past all elements, insert after the last one\n return {\n element: elements[elements.length - 1] as HTMLDivElement,\n insertAfter: true\n };\n } else {\n // For vertical layout, find the insertion point based on mouse Y position\n for (let i = 0; i < elements.length; i++) {\n const ele = elements[i];\n const rect = ele.getBoundingClientRect();\n const centerY = rect.top + rect.height / 2;\n\n if (mouseY < centerY) {\n // Insert before this element\n return { element: ele as HTMLDivElement, insertAfter: false };\n }\n }\n // If we're past all elements, insert after the last one\n return {\n element: elements[elements.length - 1] as HTMLDivElement,\n insertAfter: true\n };\n }\n }\n\n private showDropPlaceholder(\n targetElement: HTMLElement,\n insertAfter: boolean\n ) {\n this.hideDropPlaceholder();\n\n if (!targetElement || !this.draggingEle) return;\n\n // Don't show placeholder if we're targeting the dragging element itself\n if (targetElement === this.draggingEle) return;\n\n this.dropPlaceholder = document.createElement('div');\n\n this.dropPlaceholder.className = 'drop-placeholder sortable';\n\n // Copy dimensions from the original element (before it was hidden)\n if (this.originalElementRect) {\n const rect = this.originalElementRect;\n this.dropPlaceholder.style.width = rect.width + 'px';\n this.dropPlaceholder.style.height = rect.height + 'px';\n this.dropPlaceholder.style.minHeight = rect.height + 'px';\n this.dropPlaceholder.style.borderRadius = 'var(--curvature)';\n this.dropPlaceholder.style.flexShrink = '0';\n this.dropPlaceholder.style.background = '#f3f4f6';\n this.dropPlaceholder.style.border = '2px dashed #d1d5db';\n }\n\n // Insert the placeholder in the correct position in the DOM\n if (insertAfter) {\n targetElement.insertAdjacentElement('afterend', this.dropPlaceholder);\n } else {\n targetElement.insertAdjacentElement('beforebegin', this.dropPlaceholder);\n }\n }\n\n private hideDropPlaceholder() {\n if (this.dropPlaceholder) {\n this.dropPlaceholder.remove();\n this.dropPlaceholder = null;\n }\n }\n\n private showInitialPlaceholder() {\n if (!this.downEle || !this.originalElementRect) return;\n\n this.dropPlaceholder = document.createElement('div');\n this.dropPlaceholder.className = 'drop-placeholder sortable';\n\n // Copy dimensions from the original element\n const rect = this.originalElementRect;\n this.dropPlaceholder.style.width = rect.width + 'px';\n this.dropPlaceholder.style.height = rect.height + 'px';\n this.dropPlaceholder.style.minHeight = rect.height + 'px';\n this.dropPlaceholder.style.borderRadius = 'var(--curvature)';\n this.dropPlaceholder.style.flexShrink = '0';\n this.dropPlaceholder.style.background = '#f3f4f6';\n this.dropPlaceholder.style.border = '2px dashed #d1d5db';\n\n // Insert the placeholder right after the hidden original element\n this.downEle.insertAdjacentElement('afterend', this.dropPlaceholder);\n }\n\n private handleMouseDown(event: MouseEvent) {\n let ele = event.target as HTMLDivElement;\n\n // if we have a drag handle, only allow dragging from that element\n if (this.dragHandle) {\n if (!ele.classList.contains(this.dragHandle)) {\n return;\n }\n }\n\n ele = ele.closest('.sortable');\n if (ele) {\n event.preventDefault();\n event.stopPropagation();\n this.downEle = ele;\n this.draggingId = ele.id;\n this.draggingIdx = this.getRowIndex(ele.id);\n this.draggingEle = ele;\n\n // Use getBoundingClientRect for accurate offsets and store original dimensions\n const rect = ele.getBoundingClientRect();\n this.originalElementRect = rect; // Store the original rect before hiding\n this.xOffset = event.clientX - rect.left;\n this.yOffset = event.clientY - rect.top;\n this.yDown = event.clientY;\n this.xDown = event.clientX;\n\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n }\n }\n\n private handleMouseMove(event: MouseEvent) {\n if (\n !this.ghostElement &&\n this.downEle &&\n (Math.abs(event.clientY - this.yDown) > DRAG_THRESHOLD ||\n Math.abs(event.clientX - this.xDown) > DRAG_THRESHOLD)\n ) {\n this.fireCustomEvent(CustomEventType.DragStart, {\n id: this.downEle.id\n });\n\n // Capture the original index BEFORE hiding the element\n this.originalDragIndex = this.getRowIndex(this.downEle.id);\n\n // Create a clone of the element to use as the ghost\n this.ghostElement = this.cloneElementWithState(\n this.downEle\n ) as HTMLDivElement;\n\n // Hide the original element during dragging using inline styles\n this.originalDownDisplay = this.downEle.style.display;\n this.downEle.style.display = 'none';\n\n // Style the clone as a ghost\n this.ghostElement.classList.add('ghost');\n\n // Use the stored original dimensions for positioning\n const rect = this.originalElementRect;\n\n this.ghostElement.style.position = 'fixed';\n this.ghostElement.style.left = event.clientX - this.xOffset + 'px';\n this.ghostElement.style.top = event.clientY - this.yOffset + 'px';\n this.ghostElement.style.width = rect.width + 'px';\n this.ghostElement.style.height = rect.height + 'px';\n this.ghostElement.style.zIndex = '99999';\n this.ghostElement.style.opacity = '0.8';\n this.ghostElement.style.transform = 'scale(1.03)';\n\n // allow component to customize the ghost node\n if (this.prepareGhost) {\n this.prepareGhost(this.ghostElement);\n }\n\n // Add the clone to document.body for dragging\n document.body.appendChild(this.ghostElement);\n\n // Show initial placeholder in the original position to maintain layout\n this.showInitialPlaceholder();\n\n // Add global click blocker when drag starts\n if (!this.clickBlocker) {\n this.clickBlocker = (e: MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n };\n // Use capture phase to intercept clicks before they reach any elements\n document.addEventListener('click', this.clickBlocker, true);\n }\n }\n\n if (this.ghostElement) {\n this.ghostElement.style.left = event.clientX - this.xOffset + 'px';\n this.ghostElement.style.top = event.clientY - this.yOffset + 'px';\n\n // check if the drag is over the container (only if external dragging is allowed)\n const isOverContainer = this.externalDrag\n ? this.isMouseOverContainer(event.clientX, event.clientY)\n : true; // always consider \"over container\" if external drag is disabled\n\n // detect transition between internal and external drag (only if allowed)\n if (this.externalDrag && !isOverContainer && !this.isExternalDrag) {\n // transitioning to external drag\n this.isExternalDrag = true;\n this.hideDropPlaceholder();\n\n // hide the ghost element when dragging externally\n if (this.ghostElement) {\n this.ghostElement.style.display = 'none';\n }\n\n this.fireCustomEvent(CustomEventType.DragExternal, {\n id: this.downEle.id,\n mouseX: event.clientX,\n mouseY: event.clientY\n });\n } else if (this.externalDrag && isOverContainer && this.isExternalDrag) {\n // transitioning back to internal drag\n this.isExternalDrag = false;\n\n // show the ghost element again when dragging internally\n if (this.ghostElement) {\n this.ghostElement.style.display = 'block';\n }\n\n this.fireCustomEvent(CustomEventType.DragInternal, {\n id: this.downEle.id\n });\n }\n\n // only show drop placeholder and calculate drop position if internal drag\n if (!this.isExternalDrag) {\n const targetInfo = this.getDropTargetInfo(event.clientX, event.clientY);\n if (targetInfo) {\n const { element: targetElement, insertAfter } = targetInfo;\n const targetIdx = this.getRowIndex(targetElement.id);\n\n // Use the original drag index we captured before moving the element\n const originalDragIdx = this.originalDragIndex;\n\n // Calculate where the dragged element will end up in the final array\n // targetIdx is the position of target element in current DOM (missing dragged element)\n\n let dropIdx;\n if (targetIdx < originalDragIdx) {\n // Target is before the original drag position - moving backward\n dropIdx = insertAfter ? targetIdx + 1 : targetIdx;\n } else {\n // Target was originally after the drag position - moving forward\n // When moving the dragged element forward (i.e., to a higher index), the targetIdx is based on the current DOM,\n // which no longer includes the dragged element. This means all elements after the original position have shifted left by one,\n // so we need to subtract 1 from targetIdx to get the correct insertion index. If inserting after the target, we use targetIdx as is.\n dropIdx = insertAfter ? targetIdx : targetIdx - 1;\n }\n\n // Store pending drop info but don't fire event yet\n this.dropTargetId = targetElement.id;\n this.pendingDropIndex = dropIdx;\n this.pendingTargetElement = targetElement;\n\n // Show drop placeholder\n this.showDropPlaceholder(targetElement, insertAfter);\n } else {\n this.hideDropPlaceholder();\n this.dropTargetId = null;\n this.pendingDropIndex = -1;\n this.pendingTargetElement = null;\n }\n } else {\n // external drag - continue firing external drag events with updated position\n this.fireCustomEvent(CustomEventType.DragExternal, {\n id: this.downEle.id,\n mouseX: event.clientX,\n mouseY: event.clientY\n });\n }\n }\n }\n\n private handleMouseUp(evt: MouseEvent) {\n if (this.draggingId && this.ghostElement) {\n evt.preventDefault();\n evt.stopPropagation();\n\n // Remove the ghost clone from document.body\n if (this.ghostElement) {\n this.ghostElement.remove();\n }\n\n // Restore visibility of the original element by clearing inline styles\n if (this.downEle) {\n this.downEle.style.display = this.originalDownDisplay;\n }\n\n // Clear visual effects before firing events\n this.hideDropPlaceholder();\n\n // fire the order changed event only when dropped if we have a valid drop position\n if (\n !this.isExternalDrag &&\n this.pendingDropIndex >= 0 &&\n this.pendingTargetElement\n ) {\n // Use the original drag index we captured before hiding the element\n const originalDragIdx = this.originalDragIndex;\n\n // use swap-based logic - report which indexes need to be swapped\n const fromIdx = originalDragIdx;\n const toIdx = this.pendingDropIndex;\n\n // only fire if the position actually changed AND this is not an external drag\n // External drags are handled by external drop handlers\n if (fromIdx !== toIdx && !this.isExternalDrag) {\n this.fireCustomEvent(CustomEventType.OrderChanged, {\n swap: [fromIdx, toIdx]\n });\n }\n }\n\n this.fireCustomEvent(CustomEventType.DragStop, {\n id: this.draggingId,\n isExternal: this.isExternalDrag,\n mouseX: evt.clientX,\n mouseY: evt.clientY\n });\n\n this.draggingId = null;\n this.dropTargetId = null;\n this.downEle = null;\n this.originalElementRect = null;\n this.originalDragIndex = -1;\n this.pendingDropIndex = -1;\n this.pendingTargetElement = null;\n this.isExternalDrag = false;\n\n // Clear the ghost reference since we removed it\n this.ghostElement = null;\n\n this.hideDropPlaceholder();\n\n // Keep the click blocker active for a short time after drop\n if (this.clickBlocker) {\n // We'll clean it up after a timeout\n setTimeout(() => {\n if (this.clickBlocker) {\n document.removeEventListener('click', this.clickBlocker, true);\n this.clickBlocker = null;\n }\n }, 100);\n }\n }\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n this.dispatchEvent(new Event('change'));\n }\n\n public render(): TemplateResult {\n return html`\n <div\n class=\"container ${this.horizontal ? 'horizontal' : ''}\"\n style=\"gap: ${this.gap}\"\n >\n <slot @mousedown=${this.handleMouseDown}></slot>\n </div>\n `;\n }\n}\n"]}
|