@nyaruka/temba-components 0.141.1 → 0.142.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 +15 -0
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +849 -655
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +3 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/Button.js +2 -2
- package/out-tsc/src/display/Button.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +24 -1
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +7 -2
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +654 -66
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +8 -5
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +40 -28
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +2 -1
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/reflow.js +393 -0
- package/out-tsc/src/flow/reflow.js.map +1 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +18 -3
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/Compose.js +5 -0
- package/out-tsc/src/form/Compose.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +1 -3
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +2 -0
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/list/SortableList.js +39 -19
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/test/temba-canvas-menu.test.js +44 -0
- package/out-tsc/test/temba-canvas-menu.test.js.map +1 -1
- package/out-tsc/test/temba-flow-collision.test.js +25 -0
- package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-zoom.test.js +491 -0
- package/out-tsc/test/temba-flow-editor-zoom.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor.test.js +145 -1
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-node-drag.test.js +123 -0
- package/out-tsc/test/temba-flow-node-drag.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +31 -0
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-flow-reflow.test.js +472 -0
- package/out-tsc/test/temba-flow-reflow.test.js.map +1 -0
- package/out-tsc/test/temba-sortable-list.test.js +93 -0
- package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
- package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
- package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/set_contact_channel/editor/sms-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
- package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
- package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
- package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
- package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
- package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/sortable-dragging.png +0 -0
- package/screenshots/truth/modax/simple.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.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/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
- package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/src/Icons.ts +3 -1
- package/src/display/Button.ts +2 -2
- package/src/display/FloatingTab.ts +1 -1
- package/src/flow/CanvasMenu.ts +28 -3
- package/src/flow/CanvasNode.ts +7 -2
- package/src/flow/Editor.ts +755 -75
- package/src/flow/NodeEditor.ts +8 -4
- package/src/flow/Plumber.ts +65 -35
- package/src/flow/actions/send_msg.ts +2 -1
- package/src/flow/nodes/wait_for_response.ts +1 -1
- package/src/flow/reflow.ts +534 -0
- package/src/flow/types.ts +1 -0
- package/src/flow/utils.ts +19 -3
- package/src/form/Compose.ts +5 -0
- package/src/form/FieldRenderer.ts +1 -3
- package/src/layout/Dialog.ts +2 -0
- package/src/list/SortableList.ts +40 -19
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/expand-06.svg +1 -0
- package/static/svg/work/used/expand-06.svg +3 -0
- package/test/temba-canvas-menu.test.ts +55 -0
- package/test/temba-flow-collision.test.ts +31 -0
- package/test/temba-flow-editor-zoom.test.ts +583 -0
- package/test/temba-flow-editor.test.ts +187 -1
- package/test/temba-flow-node-drag.test.ts +171 -0
- package/test/temba-flow-plumber.test.ts +38 -0
- package/test/temba-flow-reflow.test.ts +703 -0
- package/test/temba-sortable-list.test.ts +120 -0
- package/screenshots/truth/actions/call_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/actions/call_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/render/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/render/translation-task.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
- package/screenshots/truth/compose/attachments-with-failures.png +0 -0
- package/screenshots/truth/compose/attachments-with-files-and-failures.png +0 -0
- package/screenshots/truth/contacts/tickets-assignment.png +0 -0
- package/screenshots/truth/contacts/tickets.png +0 -0
- package/screenshots/truth/flow/editor-basic.png +0 -0
- package/screenshots/truth/formfield/markdown-errors.png +0 -0
- package/screenshots/truth/formfield/no-errors.png +0 -0
- package/screenshots/truth/formfield/plain-text-errors.png +0 -0
- package/screenshots/truth/formfield/widget-only-markdown-errors.png +0 -0
- package/screenshots/truth/omnibox/selected.png +0 -0
- package/screenshots/truth/select/enabled-multi-selection.png +0 -0
- package/screenshots/truth/select/endpoint-initial-value-updated.png +0 -0
- package/screenshots/truth/select/endpoint-initial-value.png +0 -0
- package/screenshots/truth/select/initial-value.png +0 -0
- package/screenshots/truth/select/multi-reorder-final.png +0 -0
- package/screenshots/truth/select/multi-reorder-initial.png +0 -0
- package/screenshots/truth/select/selected-multi-test.png +0 -0
- package/screenshots/truth/select/value-initial.png +0 -0
- package/screenshots/truth/wait-for-response/rules-editor.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor-unchecked.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor.png +0 -0
- package/screenshots/truth/webchat/connecting-state.png +0 -0
package/src/list/SortableList.ts
CHANGED
|
@@ -81,7 +81,8 @@ export class SortableList extends RapidElement {
|
|
|
81
81
|
|
|
82
82
|
ghostElement: HTMLDivElement = null;
|
|
83
83
|
downEle: HTMLDivElement = null;
|
|
84
|
-
originalElementRect: DOMRect = null; // Store
|
|
84
|
+
originalElementRect: DOMRect = null; // Store viewport dimensions for ghost
|
|
85
|
+
originalLayoutSize: { width: number; height: number } = null; // Store layout dimensions for placeholders
|
|
85
86
|
originalDragIndex: number = -1; // Store original index before moving element
|
|
86
87
|
xOffset = 0;
|
|
87
88
|
yOffset = 0;
|
|
@@ -319,16 +320,17 @@ export class SortableList extends RapidElement {
|
|
|
319
320
|
|
|
320
321
|
this.dropPlaceholder.className = 'drop-placeholder sortable';
|
|
321
322
|
|
|
322
|
-
//
|
|
323
|
-
if (this.
|
|
324
|
-
const
|
|
325
|
-
this.dropPlaceholder.style.width =
|
|
326
|
-
this.dropPlaceholder.style.height =
|
|
327
|
-
this.dropPlaceholder.style.minHeight =
|
|
323
|
+
// Use layout-space dimensions for placeholders (unaffected by ancestor transforms)
|
|
324
|
+
if (this.originalLayoutSize) {
|
|
325
|
+
const size = this.originalLayoutSize;
|
|
326
|
+
this.dropPlaceholder.style.width = size.width + 'px';
|
|
327
|
+
this.dropPlaceholder.style.height = size.height + 'px';
|
|
328
|
+
this.dropPlaceholder.style.minHeight = size.height + 'px';
|
|
328
329
|
this.dropPlaceholder.style.borderRadius = 'var(--curvature)';
|
|
329
330
|
this.dropPlaceholder.style.flexShrink = '0';
|
|
330
331
|
this.dropPlaceholder.style.background = '#f3f4f6';
|
|
331
|
-
this.dropPlaceholder.style.
|
|
332
|
+
this.dropPlaceholder.style.outline = '2px dashed #d1d5db';
|
|
333
|
+
this.dropPlaceholder.style.outlineOffset = '-2px';
|
|
332
334
|
}
|
|
333
335
|
|
|
334
336
|
// Insert the placeholder in the correct position in the DOM
|
|
@@ -352,15 +354,16 @@ export class SortableList extends RapidElement {
|
|
|
352
354
|
this.dropPlaceholder = document.createElement('div');
|
|
353
355
|
this.dropPlaceholder.className = 'drop-placeholder sortable';
|
|
354
356
|
|
|
355
|
-
//
|
|
356
|
-
const
|
|
357
|
-
this.dropPlaceholder.style.width =
|
|
358
|
-
this.dropPlaceholder.style.height =
|
|
359
|
-
this.dropPlaceholder.style.minHeight =
|
|
357
|
+
// Use layout-space dimensions for placeholders (unaffected by ancestor transforms)
|
|
358
|
+
const size = this.originalLayoutSize;
|
|
359
|
+
this.dropPlaceholder.style.width = size.width + 'px';
|
|
360
|
+
this.dropPlaceholder.style.height = size.height + 'px';
|
|
361
|
+
this.dropPlaceholder.style.minHeight = size.height + 'px';
|
|
360
362
|
this.dropPlaceholder.style.borderRadius = 'var(--curvature)';
|
|
361
363
|
this.dropPlaceholder.style.flexShrink = '0';
|
|
362
364
|
this.dropPlaceholder.style.background = '#f3f4f6';
|
|
363
|
-
this.dropPlaceholder.style.
|
|
365
|
+
this.dropPlaceholder.style.outline = '2px dashed #d1d5db';
|
|
366
|
+
this.dropPlaceholder.style.outlineOffset = '-2px';
|
|
364
367
|
|
|
365
368
|
// Insert the placeholder right after the hidden original element
|
|
366
369
|
this.downEle.insertAdjacentElement('afterend', this.dropPlaceholder);
|
|
@@ -387,7 +390,11 @@ export class SortableList extends RapidElement {
|
|
|
387
390
|
|
|
388
391
|
// Use getBoundingClientRect for accurate offsets and store original dimensions
|
|
389
392
|
const rect = ele.getBoundingClientRect();
|
|
390
|
-
this.originalElementRect = rect; // Store
|
|
393
|
+
this.originalElementRect = rect; // Store viewport rect for ghost positioning
|
|
394
|
+
this.originalLayoutSize = {
|
|
395
|
+
width: ele.offsetWidth,
|
|
396
|
+
height: ele.offsetHeight
|
|
397
|
+
}; // Store layout dimensions for placeholders
|
|
391
398
|
this.xOffset = event.clientX - rect.left;
|
|
392
399
|
this.yOffset = event.clientY - rect.top;
|
|
393
400
|
this.yDown = event.clientY;
|
|
@@ -424,17 +431,31 @@ export class SortableList extends RapidElement {
|
|
|
424
431
|
// Style the clone as a ghost
|
|
425
432
|
this.ghostElement.classList.add('ghost');
|
|
426
433
|
|
|
427
|
-
//
|
|
434
|
+
// Detect ancestor scale transform (e.g. zoom) by comparing viewport
|
|
435
|
+
// to layout dimensions, so the ghost renders content at the right scale
|
|
428
436
|
const rect = this.originalElementRect;
|
|
437
|
+
const layoutSize = this.originalLayoutSize;
|
|
438
|
+
const ancestorScale =
|
|
439
|
+
layoutSize.width > 0 ? rect.width / layoutSize.width : 1;
|
|
440
|
+
const hasAncestorScale = Math.abs(ancestorScale - 1) > 0.001;
|
|
429
441
|
|
|
430
442
|
this.ghostElement.style.position = 'fixed';
|
|
431
443
|
this.ghostElement.style.left = event.clientX - this.xOffset + 'px';
|
|
432
444
|
this.ghostElement.style.top = event.clientY - this.yOffset + 'px';
|
|
433
|
-
this.ghostElement.style.width = rect.width + 'px';
|
|
434
|
-
this.ghostElement.style.height = rect.height + 'px';
|
|
435
445
|
this.ghostElement.style.zIndex = '99999';
|
|
436
446
|
this.ghostElement.style.opacity = '0.8';
|
|
437
|
-
|
|
447
|
+
|
|
448
|
+
if (hasAncestorScale) {
|
|
449
|
+
// Use layout dimensions with ancestor scale so content renders correctly
|
|
450
|
+
this.ghostElement.style.width = layoutSize.width + 'px';
|
|
451
|
+
this.ghostElement.style.height = layoutSize.height + 'px';
|
|
452
|
+
this.ghostElement.style.transform = `scale(${ancestorScale * 1.03})`;
|
|
453
|
+
this.ghostElement.style.transformOrigin = '0 0';
|
|
454
|
+
} else {
|
|
455
|
+
this.ghostElement.style.width = rect.width + 'px';
|
|
456
|
+
this.ghostElement.style.height = rect.height + 'px';
|
|
457
|
+
this.ghostElement.style.transform = 'scale(1.03)';
|
|
458
|
+
}
|
|
438
459
|
|
|
439
460
|
// allow component to customize the ghost node
|
|
440
461
|
if (this.prepareGhost) {
|