@nyaruka/temba-components 0.133.0 → 0.134.1
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 +17 -0
- package/demo/components/webchat/example.html +1 -1
- 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 +307 -259
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +223 -90
- package/out-tsc/src/display/Chat.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 +8 -0
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +117 -28
- 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/live/ContactChat.js +122 -170
- 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 +3 -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/webchat/WebChat.js +22 -9
- package/out-tsc/src/webchat/WebChat.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-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 +128 -42
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/package.json +1 -1
- 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/src/display/Chat.ts +303 -129
- package/src/display/TembaUser.ts +3 -2
- package/src/events.ts +11 -8
- package/src/flow/CanvasNode.ts +10 -0
- package/src/flow/Editor.ts +156 -28
- package/src/flow/utils.ts +207 -1
- package/src/interfaces.ts +7 -0
- package/src/live/ContactChat.ts +129 -180
- 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 +2 -0
- package/src/store/Store.ts +5 -5
- package/src/webchat/WebChat.ts +24 -10
- package/test/actions/send_broadcast.test.ts +2 -1
- package/test/temba-flow-collision.test.ts +833 -0
- package/test/temba-flow-editor-node.test.ts +142 -47
|
@@ -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"]}
|