@nyaruka/temba-components 0.131.1 → 0.131.3
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/.github/workflows/publish.yml +4 -1
- package/CHANGELOG.md +75 -1
- package/demo/components/floating-tabs/example.html +400 -0
- package/demo/components/flow/index.html +1 -1
- package/demo/data/flows/food-order.json +2 -2
- package/demo/data/flows/sample-flow.json +113 -125
- package/demo/data/flows/voicemail.json +613 -0
- package/demo/index.html +6 -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 +11 -2
- 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/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1773 -662
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +4 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +167 -0
- package/out-tsc/src/display/FloatingTab.js.map +1 -0
- package/out-tsc/src/display/ProgressBar.js +22 -2
- package/out-tsc/src/display/ProgressBar.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +200 -0
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -0
- package/out-tsc/src/flow/CanvasNode.js +489 -47
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1417 -67
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +479 -112
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +540 -0
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
- package/out-tsc/src/flow/StickyNote.js +12 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +4 -3
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +63 -4
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +4 -3
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +3 -2
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +7 -5
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +3 -2
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +3 -2
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +77 -23
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +5 -5
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +101 -21
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +6 -9
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +20 -20
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +3 -12
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +4 -3
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +181 -6
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -23
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/currencies.js +45 -0
- package/out-tsc/src/flow/currencies.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared-rules.js +257 -0
- package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared.js +71 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +211 -5
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +152 -3
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +73 -2
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +18 -10
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +8 -0
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +11 -3
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +10 -4
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +113 -0
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js +211 -3
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_scheme.js +158 -2
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +13 -5
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +38 -568
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +86 -12
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +101 -14
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +2 -4
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +3 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +346 -0
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
- package/out-tsc/src/list/SortableList.js +98 -33
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +6 -25
- 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 +11 -2
- 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 +120 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils.js +254 -13
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +8 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +3 -3
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +6 -3
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/actions/add_contact_urn.test.js +202 -0
- package/out-tsc/test/actions/add_contact_urn.test.js.map +1 -0
- package/out-tsc/test/actions/send_broadcast.test.js +148 -0
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -0
- package/out-tsc/test/actions/send_email.test.js +17 -23
- package/out-tsc/test/actions/send_email.test.js.map +1 -1
- package/out-tsc/test/actions/send_msg.test.js +33 -15
- package/out-tsc/test/actions/send_msg.test.js.map +1 -1
- package/out-tsc/test/actions/start_session.test.js +116 -0
- package/out-tsc/test/actions/start_session.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js +604 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js +387 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_expression.test.js +614 -0
- package/out-tsc/test/nodes/split_by_expression.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +3 -3
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_resthook.test.js +337 -0
- package/out-tsc/test/nodes/split_by_resthook.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js +920 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js +399 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js +333 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +2 -2
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +2 -1
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-action-drag-between-nodes.test.js +252 -0
- package/out-tsc/test/temba-action-drag-between-nodes.test.js.map +1 -0
- package/out-tsc/test/temba-canvas-menu.test.js +122 -0
- package/out-tsc/test/temba-canvas-menu.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +91 -0
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
- package/out-tsc/test/temba-floating-window.test.js +301 -0
- package/out-tsc/test/temba-floating-window.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +202 -2
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +7 -8
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-localization.test.js +471 -0
- package/out-tsc/test/temba-localization.test.js.map +1 -0
- package/out-tsc/test/temba-node-editor.test.js +3 -1
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +265 -0
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -0
- package/out-tsc/test/temba-omnibox.test.js +2 -1
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-sortable-list.test.js +51 -0
- package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
- package/out-tsc/test/temba-utils-index.test.js +1 -27
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +20 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +2 -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_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- 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/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/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/editor/cleanup-groups.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/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.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/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_broadcast/editor/with-attachments.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/editor/complex-business-email.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_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/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/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/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/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/canvas-menu/open.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/wait.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/hidden.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/floating-window/chromeless.png +0 -0
- package/screenshots/truth/floating-window/custom-size.png +0 -0
- package/screenshots/truth/floating-window/default.png +0 -0
- package/screenshots/truth/floating-window/with-header.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/sortable-dragging.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.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/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/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_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/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/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/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.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/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/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/Icons.ts +4 -1
- package/src/display/FloatingTab.ts +174 -0
- package/src/display/ProgressBar.ts +22 -2
- package/src/events.ts +2 -8
- package/src/flow/CanvasMenu.ts +217 -0
- package/src/flow/CanvasNode.ts +596 -40
- package/src/flow/Editor.ts +1721 -45
- package/src/flow/NodeEditor.ts +621 -144
- package/src/flow/NodeTypeSelector.ts +636 -0
- package/src/flow/StickyNote.ts +12 -3
- package/src/flow/actions/add_contact_groups.ts +5 -4
- package/src/flow/actions/add_contact_urn.ts +78 -4
- package/src/flow/actions/add_input_labels.ts +5 -4
- package/src/flow/actions/play_audio.ts +3 -2
- package/src/flow/actions/remove_contact_groups.ts +16 -6
- package/src/flow/actions/request_optin.ts +3 -2
- package/src/flow/actions/say_msg.ts +3 -2
- package/src/flow/actions/send_broadcast.ts +86 -23
- package/src/flow/actions/send_email.ts +12 -6
- package/src/flow/actions/send_msg.ts +155 -34
- package/src/flow/actions/set_contact_channel.ts +6 -11
- package/src/flow/actions/set_contact_field.ts +21 -25
- package/src/flow/actions/set_contact_language.ts +11 -4
- package/src/flow/actions/set_contact_name.ts +4 -15
- package/src/flow/actions/set_contact_status.ts +4 -3
- package/src/flow/actions/set_run_result.ts +5 -4
- package/src/flow/actions/start_session.ts +210 -6
- package/src/flow/config.ts +11 -23
- package/src/flow/currencies.ts +51 -0
- package/src/flow/nodes/shared-rules.ts +301 -0
- package/src/flow/nodes/shared.ts +87 -0
- package/src/flow/nodes/split_by_airtime.ts +255 -5
- package/src/flow/nodes/split_by_contact_field.ts +195 -3
- package/src/flow/nodes/split_by_expression.ts +104 -2
- package/src/flow/nodes/split_by_groups.ts +26 -11
- package/src/flow/nodes/split_by_intent.ts +8 -0
- package/src/flow/nodes/split_by_llm.ts +22 -4
- package/src/flow/nodes/split_by_llm_categorize.ts +22 -5
- package/src/flow/nodes/split_by_random.ts +16 -6
- package/src/flow/nodes/split_by_resthook.ts +140 -0
- package/src/flow/nodes/split_by_run_result.ts +259 -3
- package/src/flow/nodes/split_by_scheme.ts +202 -2
- package/src/flow/nodes/split_by_subflow.ts +17 -5
- package/src/flow/nodes/split_by_ticket.ts +15 -4
- package/src/flow/nodes/split_by_webhook.ts +17 -6
- package/src/flow/nodes/wait_for_digits.ts +3 -2
- package/src/flow/nodes/wait_for_menu.ts +3 -2
- package/src/flow/nodes/wait_for_response.ts +59 -680
- package/src/flow/types.ts +156 -23
- package/src/flow/utils.ts +108 -14
- package/src/form/FieldRenderer.ts +2 -4
- package/src/interfaces.ts +3 -0
- package/src/layout/FloatingWindow.ts +386 -0
- package/src/list/SortableList.ts +109 -34
- package/src/live/ContactChat.ts +7 -25
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/store/AppState.ts +173 -0
- package/src/store/flow-definition.d.ts +2 -5
- package/src/utils.ts +332 -12
- package/static/api/channels.json +46 -0
- package/static/api/llms.json +18 -0
- package/static/api/resthooks.json +31 -0
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/lightning-02.svg +1 -0
- package/static/svg/work/used/lightning-02.svg +3 -0
- package/temba-modules.ts +8 -0
- package/test/ActionHelper.ts +3 -3
- package/test/NodeHelper.ts +6 -3
- package/test/actions/add_contact_urn.test.ts +287 -0
- package/test/actions/send_broadcast.test.ts +190 -0
- package/test/actions/send_email.test.ts +17 -23
- package/test/actions/send_msg.test.ts +39 -15
- package/test/actions/start_session.test.ts +151 -0
- package/test/nodes/split_by_airtime.test.ts +673 -0
- package/test/nodes/split_by_contact_field.test.ts +451 -0
- package/test/nodes/split_by_expression.test.ts +751 -0
- package/test/nodes/split_by_random.test.ts +3 -3
- package/test/nodes/split_by_resthook.test.ts +398 -0
- package/test/nodes/split_by_run_result.test.ts +1109 -0
- package/test/nodes/split_by_scheme.test.ts +486 -0
- package/test/nodes/split_by_subflow.test.ts +381 -0
- package/test/nodes/wait_for_digits.test.ts +2 -2
- package/test/nodes/wait_for_response.test.ts +2 -1
- package/test/temba-action-drag-between-nodes.test.ts +301 -0
- package/test/temba-canvas-menu.test.ts +156 -0
- package/test/temba-floating-tab.test.ts +110 -0
- package/test/temba-floating-window.test.ts +477 -0
- package/test/temba-flow-editor-node.test.ts +246 -2
- package/test/temba-flow-editor.test.ts +7 -8
- package/test/temba-localization.test.ts +611 -0
- package/test/temba-node-editor.test.ts +3 -1
- package/test/temba-node-type-selector.test.ts +355 -0
- package/test/temba-omnibox.test.ts +2 -1
- package/test/temba-sortable-list.test.ts +69 -0
- package/test/temba-utils-index.test.ts +0 -35
- package/test/utils.test.ts +22 -0
- package/test-assets/contacts/history.json +14 -21
- package/test-assets/select/llms.json +2 -2
- package/web-dev-server.config.mjs +49 -1
- package/web-test-runner.config.mjs +0 -1
- package/out-tsc/src/flow/actions/call_classifier.js +0 -11
- package/out-tsc/src/flow/actions/call_classifier.js.map +0 -1
- package/out-tsc/src/flow/actions/call_resthook.js +0 -11
- package/out-tsc/src/flow/actions/call_resthook.js.map +0 -1
- package/out-tsc/src/flow/actions/split_by_expression_example.js +0 -77
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +0 -1
- package/out-tsc/src/flow/actions/transfer_airtime.js +0 -11
- package/out-tsc/src/flow/actions/transfer_airtime.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
- package/src/flow/actions/call_classifier.ts +0 -12
- package/src/flow/actions/call_resthook.ts +0 -12
- package/src/flow/actions/split_by_expression_example.ts +0 -88
- package/src/flow/actions/transfer_airtime.ts +0 -12
- package/src/flow/nodes/wait_for_audio.ts +0 -7
- package/src/flow/nodes/wait_for_image.ts +0 -7
- package/src/flow/nodes/wait_for_location.ts +0 -7
- package/src/flow/nodes/wait_for_video.ts +0 -7
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { css, html, PropertyValueMap, TemplateResult } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import { RapidElement } from '../RapidElement';
|
|
4
|
+
import { CustomEventType } from '../interfaces';
|
|
5
|
+
import { getClasses } from '../utils';
|
|
6
|
+
import { FloatingTab } from '../display/FloatingTab';
|
|
7
|
+
|
|
8
|
+
export class FloatingWindow extends RapidElement {
|
|
9
|
+
static get styles() {
|
|
10
|
+
return css`
|
|
11
|
+
.window.hidden {
|
|
12
|
+
transform: translateX(100%);
|
|
13
|
+
opacity: 0;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.window {
|
|
18
|
+
transition: transform var(--transition-duration, 300ms) ease-in-out,
|
|
19
|
+
opacity var(--transition-duration, 300ms) ease-in-out;
|
|
20
|
+
position: fixed;
|
|
21
|
+
z-index: 9999;
|
|
22
|
+
top: 100px;
|
|
23
|
+
background: white;
|
|
24
|
+
border-radius: 8px;
|
|
25
|
+
box-shadow: -4px 4px 20px rgba(0, 0, 0, 0.3);
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.window.chromeless {
|
|
32
|
+
background: transparent;
|
|
33
|
+
border-radius: 0;
|
|
34
|
+
box-shadow: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.window.dragging {
|
|
38
|
+
user-select: none;
|
|
39
|
+
cursor: move;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.header {
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: space-between;
|
|
46
|
+
padding: 6px 6px;
|
|
47
|
+
background: var(--header-color, var(--color-primary-light, #f3f4f6));
|
|
48
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
49
|
+
cursor: move;
|
|
50
|
+
user-select: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.title {
|
|
54
|
+
font-weight: 600;
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
color: white;
|
|
57
|
+
padding-left: 8px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.close-button {
|
|
61
|
+
background: none;
|
|
62
|
+
border: none;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
padding: 4px;
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
border-radius: 4px;
|
|
69
|
+
transition: background-color calc(var(--transition-duration, 150ms) / 2)
|
|
70
|
+
ease-in-out;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.close-button:hover {
|
|
74
|
+
background-color: rgba(255, 255, 255, 0.2);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.close-button temba-icon {
|
|
78
|
+
--icon-color: white;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.body {
|
|
82
|
+
flex: 1;
|
|
83
|
+
overflow-y: auto;
|
|
84
|
+
padding: 16px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.window.chromeless .body {
|
|
88
|
+
padding: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
::slotted(.drag-handle) {
|
|
92
|
+
cursor: move;
|
|
93
|
+
user-select: none;
|
|
94
|
+
border: 1px solid red;
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@property({ type: String })
|
|
100
|
+
header = '';
|
|
101
|
+
|
|
102
|
+
@property({ type: Number })
|
|
103
|
+
width = 500;
|
|
104
|
+
|
|
105
|
+
@property({ type: Number })
|
|
106
|
+
minHeight = 200;
|
|
107
|
+
|
|
108
|
+
@property({ type: Number })
|
|
109
|
+
maxHeight = 800;
|
|
110
|
+
|
|
111
|
+
@property({ type: Number })
|
|
112
|
+
top = 100;
|
|
113
|
+
|
|
114
|
+
@property({ type: Number })
|
|
115
|
+
left = -1; // -1 means calculate from right side
|
|
116
|
+
|
|
117
|
+
@property({ type: Boolean })
|
|
118
|
+
hidden = true;
|
|
119
|
+
|
|
120
|
+
@property({ type: Boolean })
|
|
121
|
+
dragging = false;
|
|
122
|
+
|
|
123
|
+
@property({ type: Boolean })
|
|
124
|
+
chromeless = false;
|
|
125
|
+
|
|
126
|
+
@property({ type: String })
|
|
127
|
+
color = '#6B7280';
|
|
128
|
+
|
|
129
|
+
private dragStartX = 0;
|
|
130
|
+
private dragStartY = 0;
|
|
131
|
+
private dragOffsetX = 0;
|
|
132
|
+
private dragOffsetY = 0;
|
|
133
|
+
private positionFromRight = false;
|
|
134
|
+
private defaultTop = 100;
|
|
135
|
+
private defaultLeft = -1;
|
|
136
|
+
|
|
137
|
+
public firstUpdated(
|
|
138
|
+
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
|
139
|
+
): void {
|
|
140
|
+
super.firstUpdated(changes);
|
|
141
|
+
|
|
142
|
+
// store the default position from properties
|
|
143
|
+
this.defaultTop = this.top;
|
|
144
|
+
this.defaultLeft = this.left;
|
|
145
|
+
|
|
146
|
+
// determine if we should position from right side
|
|
147
|
+
if (this.left === -1) {
|
|
148
|
+
this.positionFromRight = true;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// set up drag handle listeners for chromeless windows
|
|
152
|
+
if (this.chromeless) {
|
|
153
|
+
this.setupDragHandles();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// listen for window resize to keep window in bounds
|
|
157
|
+
window.addEventListener('resize', this.handleResize);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
disconnectedCallback(): void {
|
|
161
|
+
super.disconnectedCallback();
|
|
162
|
+
window.removeEventListener('resize', this.handleResize);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private setupDragHandles() {
|
|
166
|
+
// listen for mousedown on slotted content
|
|
167
|
+
this.addEventListener('mousedown', this.handleSlotMouseDown);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private handleSlotMouseDown = (event: MouseEvent) => {
|
|
171
|
+
// check if the target or any parent has the drag-handle class
|
|
172
|
+
const target = event.target as HTMLElement;
|
|
173
|
+
const dragHandle = target.closest('.drag-handle');
|
|
174
|
+
|
|
175
|
+
if (!dragHandle) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.dragging = true;
|
|
180
|
+
this.dragStartX = event.clientX;
|
|
181
|
+
this.dragStartY = event.clientY;
|
|
182
|
+
this.dragOffsetX = this.left;
|
|
183
|
+
this.dragOffsetY = this.top;
|
|
184
|
+
|
|
185
|
+
document.addEventListener('mousemove', this.handleMouseMove);
|
|
186
|
+
document.addEventListener('mouseup', this.handleMouseUp);
|
|
187
|
+
|
|
188
|
+
event.preventDefault();
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
public updated(
|
|
192
|
+
changes: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
|
193
|
+
): void {
|
|
194
|
+
super.updated(changes);
|
|
195
|
+
if (changes.has('hidden')) {
|
|
196
|
+
this.classList.toggle('hidden', this.hidden);
|
|
197
|
+
|
|
198
|
+
// when hiding, reset positioning behavior to original
|
|
199
|
+
if (this.hidden && !changes.get('hidden')) {
|
|
200
|
+
if (this.defaultLeft === -1) {
|
|
201
|
+
this.positionFromRight = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// reset to default position when showing
|
|
206
|
+
if (!this.hidden && changes.get('hidden')) {
|
|
207
|
+
// reset top to default
|
|
208
|
+
this.top = this.defaultTop;
|
|
209
|
+
|
|
210
|
+
// if positioned from right, recalculate based on current viewport
|
|
211
|
+
if (this.positionFromRight) {
|
|
212
|
+
this.left = window.innerWidth - this.width - 20;
|
|
213
|
+
} else {
|
|
214
|
+
// reset left to default
|
|
215
|
+
this.left = this.defaultLeft;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// setup drag handles if chromeless changed to true
|
|
221
|
+
if (changes.has('chromeless') && this.chromeless) {
|
|
222
|
+
this.setupDragHandles();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private handleClose() {
|
|
227
|
+
this.hidden = true;
|
|
228
|
+
// show all tabs when window is closed
|
|
229
|
+
FloatingTab.showAllTabs();
|
|
230
|
+
this.fireCustomEvent(CustomEventType.DialogHidden);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private handleHeaderMouseDown(event: MouseEvent) {
|
|
234
|
+
// don't start drag if clicking on close button
|
|
235
|
+
if ((event.target as HTMLElement).closest('.close-button')) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.dragging = true;
|
|
240
|
+
this.dragStartX = event.clientX;
|
|
241
|
+
this.dragStartY = event.clientY;
|
|
242
|
+
this.dragOffsetX = this.left;
|
|
243
|
+
this.dragOffsetY = this.top;
|
|
244
|
+
|
|
245
|
+
document.addEventListener('mousemove', this.handleMouseMove);
|
|
246
|
+
document.addEventListener('mouseup', this.handleMouseUp);
|
|
247
|
+
|
|
248
|
+
event.preventDefault();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private handleMouseMove = (event: MouseEvent) => {
|
|
252
|
+
if (!this.dragging) return;
|
|
253
|
+
|
|
254
|
+
const deltaX = event.clientX - this.dragStartX;
|
|
255
|
+
const deltaY = event.clientY - this.dragStartY;
|
|
256
|
+
|
|
257
|
+
this.left = this.dragOffsetX + deltaX;
|
|
258
|
+
this.top = this.dragOffsetY + deltaY;
|
|
259
|
+
|
|
260
|
+
// keep window within viewport bounds with 20px padding
|
|
261
|
+
const padding = 20;
|
|
262
|
+
this.left = Math.max(
|
|
263
|
+
padding,
|
|
264
|
+
Math.min(this.left, window.innerWidth - this.width - padding)
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// get the actual rendered height of the window element
|
|
268
|
+
const windowElement = this.shadowRoot?.querySelector(
|
|
269
|
+
'.window'
|
|
270
|
+
) as HTMLElement;
|
|
271
|
+
const currentHeight =
|
|
272
|
+
windowElement?.offsetHeight || this.maxHeight || window.innerHeight;
|
|
273
|
+
const maxTop = Math.max(
|
|
274
|
+
padding,
|
|
275
|
+
window.innerHeight - currentHeight - padding
|
|
276
|
+
);
|
|
277
|
+
this.top = Math.max(padding, Math.min(this.top, maxTop));
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
private handleMouseUp = () => {
|
|
281
|
+
this.dragging = false;
|
|
282
|
+
document.removeEventListener('mousemove', this.handleMouseMove);
|
|
283
|
+
document.removeEventListener('mouseup', this.handleMouseUp);
|
|
284
|
+
|
|
285
|
+
// once user drags the window, stop auto-positioning from right
|
|
286
|
+
this.positionFromRight = false;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
private handleResize = () => {
|
|
290
|
+
// only constrain position if window is visible
|
|
291
|
+
if (this.hidden) return;
|
|
292
|
+
|
|
293
|
+
const padding = 20;
|
|
294
|
+
const windowElement = this.shadowRoot?.querySelector(
|
|
295
|
+
'.window'
|
|
296
|
+
) as HTMLElement;
|
|
297
|
+
const currentHeight =
|
|
298
|
+
windowElement?.offsetHeight || this.maxHeight || window.innerHeight;
|
|
299
|
+
|
|
300
|
+
// if positioned from right, always recalculate from right edge
|
|
301
|
+
if (this.positionFromRight) {
|
|
302
|
+
this.left = window.innerWidth - this.width - padding;
|
|
303
|
+
} else {
|
|
304
|
+
// only adjust left if out of bounds
|
|
305
|
+
const minLeft = padding;
|
|
306
|
+
const maxLeft = window.innerWidth - this.width - padding;
|
|
307
|
+
|
|
308
|
+
if (this.left < minLeft) {
|
|
309
|
+
this.left = minLeft;
|
|
310
|
+
} else if (this.left > maxLeft) {
|
|
311
|
+
this.left = maxLeft;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// only adjust top if out of bounds
|
|
316
|
+
const minTop = padding;
|
|
317
|
+
const maxTop = Math.max(
|
|
318
|
+
padding,
|
|
319
|
+
window.innerHeight - currentHeight - padding
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
if (this.top < minTop) {
|
|
323
|
+
this.top = minTop;
|
|
324
|
+
} else if (this.top > maxTop) {
|
|
325
|
+
this.top = maxTop;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
public show() {
|
|
330
|
+
this.hidden = false;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
public hide() {
|
|
334
|
+
this.hidden = true;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
public close() {
|
|
338
|
+
this.hidden = true;
|
|
339
|
+
// show all tabs when window is closed
|
|
340
|
+
FloatingTab.showAllTabs();
|
|
341
|
+
this.fireCustomEvent(CustomEventType.DialogHidden);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
public render(): TemplateResult {
|
|
345
|
+
const minHeightStyle = this.minHeight
|
|
346
|
+
? `min-height: ${this.minHeight}px;`
|
|
347
|
+
: '';
|
|
348
|
+
const maxHeightStyle = this.maxHeight
|
|
349
|
+
? `max-height: ${this.maxHeight}px;`
|
|
350
|
+
: '';
|
|
351
|
+
|
|
352
|
+
const windowStyle = `
|
|
353
|
+
width: ${this.width}px;
|
|
354
|
+
${minHeightStyle}
|
|
355
|
+
${maxHeightStyle}
|
|
356
|
+
top: ${this.top}px;
|
|
357
|
+
left: ${this.left}px;
|
|
358
|
+
--header-color: ${this.color};
|
|
359
|
+
`;
|
|
360
|
+
|
|
361
|
+
const windowClasses = getClasses({
|
|
362
|
+
window: true,
|
|
363
|
+
dragging: this.dragging,
|
|
364
|
+
hidden: this.hidden,
|
|
365
|
+
chromeless: this.chromeless
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
return html`
|
|
369
|
+
<div class="${windowClasses}" style="${windowStyle}">
|
|
370
|
+
${!this.chromeless
|
|
371
|
+
? html`
|
|
372
|
+
<div class="header" @mousedown=${this.handleHeaderMouseDown}>
|
|
373
|
+
<div class="title">${this.header}</div>
|
|
374
|
+
<button class="close-button" @click=${this.handleClose}>
|
|
375
|
+
<temba-icon name="close" size="1.5"></temba-icon>
|
|
376
|
+
</button>
|
|
377
|
+
</div>
|
|
378
|
+
`
|
|
379
|
+
: ''}
|
|
380
|
+
<div class="body">
|
|
381
|
+
<slot></slot>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
`;
|
|
385
|
+
}
|
|
386
|
+
}
|
package/src/list/SortableList.ts
CHANGED
|
@@ -9,6 +9,10 @@ import { RapidElement } from '../RapidElement';
|
|
|
9
9
|
|
|
10
10
|
// how far we have to drag before it starts
|
|
11
11
|
const DRAG_THRESHOLD = 2;
|
|
12
|
+
|
|
13
|
+
// padding around container for external drag detection
|
|
14
|
+
const EXTERNAL_DRAG_PADDING = 50;
|
|
15
|
+
|
|
12
16
|
export class SortableList extends RapidElement {
|
|
13
17
|
originalDownDisplay: string;
|
|
14
18
|
static get styles() {
|
|
@@ -65,6 +69,9 @@ export class SortableList extends RapidElement {
|
|
|
65
69
|
@property({ type: String })
|
|
66
70
|
gap: string = '0em';
|
|
67
71
|
|
|
72
|
+
@property({ type: Boolean })
|
|
73
|
+
externalDrag: boolean = false;
|
|
74
|
+
|
|
68
75
|
/**
|
|
69
76
|
* Optional callback to allow parent components to customize the ghost node.
|
|
70
77
|
* Called after the ghost node is cloned but before it is appended to the DOM.
|
|
@@ -86,6 +93,7 @@ export class SortableList extends RapidElement {
|
|
|
86
93
|
dropPlaceholder: HTMLDivElement = null;
|
|
87
94
|
pendingDropIndex = -1;
|
|
88
95
|
pendingTargetElement: HTMLElement = null;
|
|
96
|
+
isExternalDrag = false;
|
|
89
97
|
|
|
90
98
|
private clickBlocker: ((e: MouseEvent) => void) | null = null;
|
|
91
99
|
|
|
@@ -108,6 +116,20 @@ export class SortableList extends RapidElement {
|
|
|
108
116
|
return eles;
|
|
109
117
|
}
|
|
110
118
|
|
|
119
|
+
private isMouseOverContainer(mouseX: number, mouseY: number): boolean {
|
|
120
|
+
const container = this.shadowRoot.querySelector('.container');
|
|
121
|
+
if (!container) return false;
|
|
122
|
+
|
|
123
|
+
const rect = container.getBoundingClientRect();
|
|
124
|
+
// add some padding to make it easier to stay within the container
|
|
125
|
+
return (
|
|
126
|
+
mouseX >= rect.left - EXTERNAL_DRAG_PADDING &&
|
|
127
|
+
mouseX <= rect.right + EXTERNAL_DRAG_PADDING &&
|
|
128
|
+
mouseY >= rect.top - EXTERNAL_DRAG_PADDING &&
|
|
129
|
+
mouseY <= rect.bottom + EXTERNAL_DRAG_PADDING
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
111
133
|
private cloneElementWithState(element: HTMLElement): HTMLElement {
|
|
112
134
|
// First create a basic clone
|
|
113
135
|
const clone = element.cloneNode(true) as HTMLElement;
|
|
@@ -305,6 +327,8 @@ export class SortableList extends RapidElement {
|
|
|
305
327
|
this.dropPlaceholder.style.minHeight = rect.height + 'px';
|
|
306
328
|
this.dropPlaceholder.style.borderRadius = 'var(--curvature)';
|
|
307
329
|
this.dropPlaceholder.style.flexShrink = '0';
|
|
330
|
+
this.dropPlaceholder.style.background = '#f3f4f6';
|
|
331
|
+
this.dropPlaceholder.style.border = '2px dashed #d1d5db';
|
|
308
332
|
}
|
|
309
333
|
|
|
310
334
|
// Insert the placeholder in the correct position in the DOM
|
|
@@ -335,10 +359,8 @@ export class SortableList extends RapidElement {
|
|
|
335
359
|
this.dropPlaceholder.style.minHeight = rect.height + 'px';
|
|
336
360
|
this.dropPlaceholder.style.borderRadius = 'var(--curvature)';
|
|
337
361
|
this.dropPlaceholder.style.flexShrink = '0';
|
|
338
|
-
this.dropPlaceholder.style.background =
|
|
339
|
-
|
|
340
|
-
this.dropPlaceholder.style.border =
|
|
341
|
-
'2px dashed rgba(var(--color-primary-rgb), 0.3)';
|
|
362
|
+
this.dropPlaceholder.style.background = '#f3f4f6';
|
|
363
|
+
this.dropPlaceholder.style.border = '2px dashed #d1d5db';
|
|
342
364
|
|
|
343
365
|
// Insert the placeholder right after the hidden original element
|
|
344
366
|
this.downEle.insertAdjacentElement('afterend', this.dropPlaceholder);
|
|
@@ -440,41 +462,86 @@ export class SortableList extends RapidElement {
|
|
|
440
462
|
this.ghostElement.style.left = event.clientX - this.xOffset + 'px';
|
|
441
463
|
this.ghostElement.style.top = event.clientY - this.yOffset + 'px';
|
|
442
464
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
465
|
+
// check if the drag is over the container (only if external dragging is allowed)
|
|
466
|
+
const isOverContainer = this.externalDrag
|
|
467
|
+
? this.isMouseOverContainer(event.clientX, event.clientY)
|
|
468
|
+
: true; // always consider "over container" if external drag is disabled
|
|
447
469
|
|
|
448
|
-
|
|
449
|
-
|
|
470
|
+
// detect transition between internal and external drag (only if allowed)
|
|
471
|
+
if (this.externalDrag && !isOverContainer && !this.isExternalDrag) {
|
|
472
|
+
// transitioning to external drag
|
|
473
|
+
this.isExternalDrag = true;
|
|
474
|
+
this.hideDropPlaceholder();
|
|
450
475
|
|
|
451
|
-
//
|
|
452
|
-
|
|
476
|
+
// hide the ghost element when dragging externally
|
|
477
|
+
if (this.ghostElement) {
|
|
478
|
+
this.ghostElement.style.display = 'none';
|
|
479
|
+
}
|
|
453
480
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
481
|
+
this.fireCustomEvent(CustomEventType.DragExternal, {
|
|
482
|
+
id: this.downEle.id,
|
|
483
|
+
mouseX: event.clientX,
|
|
484
|
+
mouseY: event.clientY
|
|
485
|
+
});
|
|
486
|
+
} else if (this.externalDrag && isOverContainer && this.isExternalDrag) {
|
|
487
|
+
// transitioning back to internal drag
|
|
488
|
+
this.isExternalDrag = false;
|
|
489
|
+
|
|
490
|
+
// show the ghost element again when dragging internally
|
|
491
|
+
if (this.ghostElement) {
|
|
492
|
+
this.ghostElement.style.display = 'block';
|
|
464
493
|
}
|
|
465
494
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
495
|
+
this.fireCustomEvent(CustomEventType.DragInternal, {
|
|
496
|
+
id: this.downEle.id
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// only show drop placeholder and calculate drop position if internal drag
|
|
501
|
+
if (!this.isExternalDrag) {
|
|
502
|
+
const targetInfo = this.getDropTargetInfo(event.clientX, event.clientY);
|
|
503
|
+
if (targetInfo) {
|
|
504
|
+
const { element: targetElement, insertAfter } = targetInfo;
|
|
505
|
+
const targetIdx = this.getRowIndex(targetElement.id);
|
|
506
|
+
|
|
507
|
+
// Use the original drag index we captured before moving the element
|
|
508
|
+
const originalDragIdx = this.originalDragIndex;
|
|
509
|
+
|
|
510
|
+
// Calculate where the dragged element will end up in the final array
|
|
511
|
+
// targetIdx is the position of target element in current DOM (missing dragged element)
|
|
512
|
+
|
|
513
|
+
let dropIdx;
|
|
514
|
+
if (targetIdx < originalDragIdx) {
|
|
515
|
+
// Target is before the original drag position - moving backward
|
|
516
|
+
dropIdx = insertAfter ? targetIdx + 1 : targetIdx;
|
|
517
|
+
} else {
|
|
518
|
+
// Target was originally after the drag position - moving forward
|
|
519
|
+
// When moving the dragged element forward (i.e., to a higher index), the targetIdx is based on the current DOM,
|
|
520
|
+
// which no longer includes the dragged element. This means all elements after the original position have shifted left by one,
|
|
521
|
+
// so we need to subtract 1 from targetIdx to get the correct insertion index. If inserting after the target, we use targetIdx as is.
|
|
522
|
+
dropIdx = insertAfter ? targetIdx : targetIdx - 1;
|
|
523
|
+
}
|
|
470
524
|
|
|
471
|
-
|
|
472
|
-
|
|
525
|
+
// Store pending drop info but don't fire event yet
|
|
526
|
+
this.dropTargetId = targetElement.id;
|
|
527
|
+
this.pendingDropIndex = dropIdx;
|
|
528
|
+
this.pendingTargetElement = targetElement;
|
|
529
|
+
|
|
530
|
+
// Show drop placeholder
|
|
531
|
+
this.showDropPlaceholder(targetElement, insertAfter);
|
|
532
|
+
} else {
|
|
533
|
+
this.hideDropPlaceholder();
|
|
534
|
+
this.dropTargetId = null;
|
|
535
|
+
this.pendingDropIndex = -1;
|
|
536
|
+
this.pendingTargetElement = null;
|
|
537
|
+
}
|
|
473
538
|
} else {
|
|
474
|
-
|
|
475
|
-
this.
|
|
476
|
-
|
|
477
|
-
|
|
539
|
+
// external drag - continue firing external drag events with updated position
|
|
540
|
+
this.fireCustomEvent(CustomEventType.DragExternal, {
|
|
541
|
+
id: this.downEle.id,
|
|
542
|
+
mouseX: event.clientX,
|
|
543
|
+
mouseY: event.clientY
|
|
544
|
+
});
|
|
478
545
|
}
|
|
479
546
|
}
|
|
480
547
|
}
|
|
@@ -498,7 +565,11 @@ export class SortableList extends RapidElement {
|
|
|
498
565
|
this.hideDropPlaceholder();
|
|
499
566
|
|
|
500
567
|
// fire the order changed event only when dropped if we have a valid drop position
|
|
501
|
-
if (
|
|
568
|
+
if (
|
|
569
|
+
!this.isExternalDrag &&
|
|
570
|
+
this.pendingDropIndex >= 0 &&
|
|
571
|
+
this.pendingTargetElement
|
|
572
|
+
) {
|
|
502
573
|
// Use the original drag index we captured before hiding the element
|
|
503
574
|
const originalDragIdx = this.originalDragIndex;
|
|
504
575
|
|
|
@@ -515,7 +586,10 @@ export class SortableList extends RapidElement {
|
|
|
515
586
|
}
|
|
516
587
|
|
|
517
588
|
this.fireCustomEvent(CustomEventType.DragStop, {
|
|
518
|
-
id: this.draggingId
|
|
589
|
+
id: this.draggingId,
|
|
590
|
+
isExternal: this.isExternalDrag,
|
|
591
|
+
mouseX: evt.clientX,
|
|
592
|
+
mouseY: evt.clientY
|
|
519
593
|
});
|
|
520
594
|
|
|
521
595
|
this.draggingId = null;
|
|
@@ -525,6 +599,7 @@ export class SortableList extends RapidElement {
|
|
|
525
599
|
this.originalDragIndex = -1;
|
|
526
600
|
this.pendingDropIndex = -1;
|
|
527
601
|
this.pendingTargetElement = null;
|
|
602
|
+
this.isExternalDrag = false;
|
|
528
603
|
|
|
529
604
|
// Clear the ghost reference since we removed it
|
|
530
605
|
this.ghostElement = null;
|
package/src/live/ContactChat.ts
CHANGED
|
@@ -808,12 +808,6 @@ export class ContactChat extends ContactStoreElement {
|
|
|
808
808
|
};
|
|
809
809
|
} else if (event._user) {
|
|
810
810
|
return event._user;
|
|
811
|
-
} else if (event.created_by) {
|
|
812
|
-
return {
|
|
813
|
-
email: event.created_by.email,
|
|
814
|
-
name: `${event.created_by.first_name} ${event.created_by.last_name}`.trim(),
|
|
815
|
-
avatar: event.created_by.avatar
|
|
816
|
-
};
|
|
817
811
|
}
|
|
818
812
|
return null;
|
|
819
813
|
}
|
|
@@ -852,13 +846,9 @@ export class ContactChat extends ContactStoreElement {
|
|
|
852
846
|
} else if (
|
|
853
847
|
event.type === 'msg_created' ||
|
|
854
848
|
event.type === 'msg_received' ||
|
|
855
|
-
event.type === 'ivr_created'
|
|
856
|
-
event.type === 'broadcast_created'
|
|
849
|
+
event.type === 'ivr_created'
|
|
857
850
|
) {
|
|
858
851
|
const msgEvent = event as MsgEvent;
|
|
859
|
-
const status = msgEvent.status || msgEvent._status;
|
|
860
|
-
const failedReason =
|
|
861
|
-
msgEvent.failed_reason_display || msgEvent._failed_reason;
|
|
862
852
|
|
|
863
853
|
messages.push({
|
|
864
854
|
id: event.uuid,
|
|
@@ -867,7 +857,10 @@ export class ContactChat extends ContactStoreElement {
|
|
|
867
857
|
date: new Date(msgEvent.created_on),
|
|
868
858
|
attachments: msgEvent.msg.attachments,
|
|
869
859
|
text: msgEvent.msg.text,
|
|
870
|
-
sendError:
|
|
860
|
+
sendError:
|
|
861
|
+
msgEvent._status &&
|
|
862
|
+
(msgEvent._status.status === 'errored' ||
|
|
863
|
+
msgEvent._status.status === 'failed'),
|
|
871
864
|
popup: html`<div
|
|
872
865
|
style="display: flex; flex-direction: row; align-items:center; justify-content: space-between;font-size:0.9em;line-height:1em;min-width:10em"
|
|
873
866
|
>
|
|
@@ -882,20 +875,9 @@ export class ContactChat extends ContactStoreElement {
|
|
|
882
875
|
${msgEvent.optin.name}
|
|
883
876
|
</div>`
|
|
884
877
|
: null}
|
|
885
|
-
${failedReason
|
|
886
|
-
? html`
|
|
887
|
-
<div
|
|
888
|
-
style="margin-top:0.2em;margin-right: 0.5em;min-width:10em;max-width:15em;color:var(--color-error);font-size:0.9em"
|
|
889
|
-
>
|
|
890
|
-
${failedReason}
|
|
891
|
-
</div>
|
|
892
|
-
`
|
|
893
|
-
: null}
|
|
894
878
|
</div>
|
|
895
|
-
${msgEvent.
|
|
896
|
-
? html`<a
|
|
897
|
-
style="margin-left:0.5em"
|
|
898
|
-
href="${msgEvent.logs_url || msgEvent._logs_url}"
|
|
879
|
+
${msgEvent._logs_url
|
|
880
|
+
? html`<a style="margin-left:0.5em" href="${msgEvent._logs_url}"
|
|
899
881
|
><temba-icon name="log"></temba-icon
|
|
900
882
|
></a>`
|
|
901
883
|
: null}
|
package/src/locales/es.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
|
|
2
|
+
// Do not modify this file by hand!
|
|
3
|
+
// Re-generate this file by running lit-localize
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/* eslint-disable no-irregular-whitespace */
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
10
|
+
|
|
11
|
+
export const templates = {
|
|
12
|
+
'scf1453991c986b25': `Tab para completar, enter para seleccionar`,
|
|
13
|
+
's73b4d70c02f4b4e0': `No options`,
|
|
14
|
+
's8f02e3a18ffc083a': `Are not currently in a flow`,
|
|
15
|
+
's638236250662c6b3': `Have sent a message in the last`,
|
|
16
|
+
's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
|
|
17
|
+
};
|
|
18
|
+
|