@nyaruka/temba-components 0.129.3 → 0.129.5
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/.eslintrc.js +1 -0
- package/.github/workflows/build.yml +135 -3
- package/CHANGELOG.md +19 -0
- package/demo/data/flows/sample-flow.json +110 -87
- package/demo/field-config-demo.html +135 -0
- package/dist/temba-components.js +1257 -675
- package/dist/temba-components.js.map +1 -1
- package/docs/ActionEditor-Migration.md +118 -0
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/{EditorNode.js → CanvasNode.js} +345 -42
- package/out-tsc/src/flow/CanvasNode.js.map +1 -0
- package/out-tsc/src/flow/Editor.js +107 -3
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +1211 -0
- package/out-tsc/src/flow/NodeEditor.js.map +1 -0
- package/out-tsc/src/flow/Plumber.js +0 -6
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +40 -0
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -0
- package/out-tsc/src/flow/actions/add_contact_urn.js +16 -0
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -0
- package/out-tsc/src/flow/actions/add_input_labels.js +11 -0
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -0
- package/out-tsc/src/flow/actions/call_classifier.js +11 -0
- package/out-tsc/src/flow/actions/call_classifier.js.map +1 -0
- package/out-tsc/src/flow/actions/call_llm.js +11 -0
- package/out-tsc/src/flow/actions/call_llm.js.map +1 -0
- package/out-tsc/src/flow/actions/call_resthook.js +11 -0
- package/out-tsc/src/flow/actions/call_resthook.js.map +1 -0
- package/out-tsc/src/flow/actions/call_webhook.js +122 -0
- package/out-tsc/src/flow/actions/call_webhook.js.map +1 -0
- package/out-tsc/src/flow/actions/enter_flow.js +14 -0
- package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
- package/out-tsc/src/flow/actions/open_ticket.js +11 -0
- package/out-tsc/src/flow/actions/open_ticket.js.map +1 -0
- package/out-tsc/src/flow/actions/play_audio.js +11 -0
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -0
- package/out-tsc/src/flow/actions/remove_contact_groups.js +62 -0
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -0
- package/out-tsc/src/flow/actions/request_optin.js +11 -0
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -0
- package/out-tsc/src/flow/actions/say_msg.js +11 -0
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -0
- package/out-tsc/src/flow/actions/send_broadcast.js +33 -0
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -0
- package/out-tsc/src/flow/actions/send_email.js +56 -0
- package/out-tsc/src/flow/actions/send_email.js.map +1 -0
- package/out-tsc/src/flow/actions/send_msg.js +55 -0
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_channel.js +12 -0
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_field.js +12 -0
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_language.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_name.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_status.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -0
- package/out-tsc/src/flow/actions/set_run_result.js +10 -0
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -0
- package/out-tsc/src/flow/actions/split_by_expression_example.js +77 -0
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -0
- package/out-tsc/src/flow/actions/start_session.js +11 -0
- package/out-tsc/src/flow/actions/start_session.js.map +1 -0
- package/out-tsc/src/flow/actions/transfer_airtime.js +11 -0
- package/out-tsc/src/flow/actions/transfer_airtime.js.map +1 -0
- package/out-tsc/src/flow/config.js +88 -193
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/execute_actions.js +4 -0
- package/out-tsc/src/flow/nodes/execute_actions.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_expression.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_groups.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_random.js +10 -0
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_scheme.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_subflow.js +9 -0
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_webhook.js +18 -0
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_image.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_location.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_menu.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_video.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -0
- package/out-tsc/src/flow/types.js +79 -0
- package/out-tsc/src/flow/types.js.map +1 -0
- package/out-tsc/src/flow/utils.js +65 -0
- package/out-tsc/src/flow/utils.js.map +1 -0
- package/out-tsc/src/form/ArrayEditor.js +199 -0
- package/out-tsc/src/form/ArrayEditor.js.map +1 -0
- package/out-tsc/src/form/BaseListEditor.js +128 -0
- package/out-tsc/src/form/BaseListEditor.js.map +1 -0
- package/out-tsc/src/form/Checkbox.js +17 -2
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/Completion.js +6 -0
- package/out-tsc/src/form/Completion.js.map +1 -1
- package/out-tsc/src/form/FormField.js +110 -11
- package/out-tsc/src/form/FormField.js.map +1 -1
- package/out-tsc/src/form/KeyValueEditor.js +223 -0
- package/out-tsc/src/form/KeyValueEditor.js.map +1 -0
- package/out-tsc/src/form/select/Select.js +92 -32
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/interfaces.js +6 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +2 -76
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/temba-modules.js +9 -2
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +116 -0
- package/out-tsc/test/ActionHelper.js.map +1 -0
- package/out-tsc/test/actions/add_contact_groups.test.js +66 -0
- package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js +226 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -0
- package/out-tsc/test/actions/send_email.test.js +160 -0
- package/out-tsc/test/actions/send_email.test.js.map +1 -0
- package/out-tsc/test/actions/send_msg.test.js +95 -0
- package/out-tsc/test/actions/send_msg.test.js.map +1 -0
- package/out-tsc/test/temba-action-editing-integration.test.js +183 -0
- package/out-tsc/test/temba-action-editing-integration.test.js.map +1 -0
- package/out-tsc/test/temba-checkbox.test.js +1 -1
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-field-config.test.js +133 -0
- package/out-tsc/test/temba-field-config.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +14 -14
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +283 -0
- package/out-tsc/test/temba-node-editor.test.js.map +1 -0
- package/out-tsc/test/temba-select.test.js +158 -0
- package/out-tsc/test/temba-select.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_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/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_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/editor/router.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/formfield/markdown-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/integration/checkbox-markdown-errors.png +0 -0
- package/src/events.ts +1 -40
- package/src/flow/{EditorNode.ts → CanvasNode.ts} +424 -48
- package/src/flow/Editor.ts +140 -4
- package/src/flow/NodeEditor.ts +1454 -0
- package/src/flow/Plumber.ts +0 -9
- package/src/flow/actions/add_contact_groups.ts +42 -0
- package/src/flow/actions/add_contact_urn.ts +17 -0
- package/src/flow/actions/add_input_labels.ts +12 -0
- package/src/flow/actions/call_classifier.ts +12 -0
- package/src/flow/actions/call_llm.ts +12 -0
- package/src/flow/actions/call_resthook.ts +12 -0
- package/src/flow/actions/call_webhook.ts +133 -0
- package/src/flow/actions/enter_flow.ts +15 -0
- package/src/flow/actions/open_ticket.ts +12 -0
- package/src/flow/actions/play_audio.ts +12 -0
- package/src/flow/actions/remove_contact_groups.ts +66 -0
- package/src/flow/actions/request_optin.ts +12 -0
- package/src/flow/actions/say_msg.ts +12 -0
- package/src/flow/actions/send_broadcast.ts +35 -0
- package/src/flow/actions/send_email.ts +60 -0
- package/src/flow/actions/send_msg.ts +58 -0
- package/src/flow/actions/set_contact_channel.ts +13 -0
- package/src/flow/actions/set_contact_field.ts +13 -0
- package/src/flow/actions/set_contact_language.ts +11 -0
- package/src/flow/actions/set_contact_name.ts +11 -0
- package/src/flow/actions/set_contact_status.ts +11 -0
- package/src/flow/actions/set_run_result.ts +11 -0
- package/src/flow/actions/split_by_expression_example.ts +88 -0
- package/src/flow/actions/start_session.ts +12 -0
- package/src/flow/actions/transfer_airtime.ts +12 -0
- package/src/flow/config.ts +93 -232
- package/src/flow/nodes/execute_actions.ts +5 -0
- package/src/flow/nodes/split_by_airtime.ts +9 -0
- package/src/flow/nodes/split_by_contact_field.ts +7 -0
- package/src/flow/nodes/split_by_expression.ts +7 -0
- package/src/flow/nodes/split_by_groups.ts +7 -0
- package/src/flow/nodes/split_by_random.ts +10 -0
- package/src/flow/nodes/split_by_run_result.ts +7 -0
- package/src/flow/nodes/split_by_scheme.ts +7 -0
- package/src/flow/nodes/split_by_subflow.ts +9 -0
- package/src/flow/nodes/split_by_webhook.ts +19 -0
- package/src/flow/nodes/wait_for_audio.ts +7 -0
- package/src/flow/nodes/wait_for_digits.ts +7 -0
- package/src/flow/nodes/wait_for_image.ts +7 -0
- package/src/flow/nodes/wait_for_location.ts +7 -0
- package/src/flow/nodes/wait_for_menu.ts +7 -0
- package/src/flow/nodes/wait_for_response.ts +7 -0
- package/src/flow/nodes/wait_for_video.ts +7 -0
- package/src/flow/types.ts +352 -0
- package/src/flow/utils.ts +76 -0
- package/src/form/ArrayEditor.ts +240 -0
- package/src/form/BaseListEditor.ts +177 -0
- package/src/form/Checkbox.ts +22 -3
- package/src/form/Completion.ts +6 -0
- package/src/form/FormField.ts +115 -11
- package/src/form/KeyValueEditor.ts +251 -0
- package/src/form/select/Select.ts +105 -32
- package/src/interfaces.ts +7 -2
- package/src/live/ContactChat.ts +3 -97
- package/src/store/flow-definition.d.ts +6 -1
- package/static/api/contacts.json +30 -0
- package/static/api/groups.json +4 -426
- package/static/api/locations.json +24 -0
- package/static/api/media.json +5 -0
- package/static/api/optins.json +16 -0
- package/static/api/orgs.json +13 -0
- package/static/api/topics.json +21 -0
- package/static/api/users.json +26 -0
- package/static/css/temba-components.css +3 -6
- package/temba-modules.ts +9 -2
- package/test/ActionHelper.ts +142 -0
- package/test/actions/add_contact_groups.test.ts +89 -0
- package/test/actions/remove_contact_groups.test.ts +265 -0
- package/test/actions/send_email.test.ts +214 -0
- package/test/actions/send_msg.test.ts +130 -0
- package/test/temba-action-editing-integration.test.ts +240 -0
- package/test/temba-checkbox.test.ts +1 -1
- package/test/temba-field-config.test.ts +152 -0
- package/test/temba-flow-editor-node.test.ts +18 -18
- package/test/temba-node-editor.test.ts +353 -0
- package/test/temba-select.test.ts +234 -0
- package/test-assets/contacts/history.json +11 -33
- package/web-dev-server.config.mjs +34 -0
- package/.github/workflows/coverage.yml +0 -80
- package/demo/sticky-note-demo.html +0 -155
- package/out-tsc/src/flow/EditorNode.js.map +0 -1
- package/out-tsc/src/flow/render.js +0 -358
- package/out-tsc/src/flow/render.js.map +0 -1
- package/out-tsc/test/temba-flow-render.test.js +0 -794
- package/out-tsc/test/temba-flow-render.test.js.map +0 -1
- package/src/flow/render.ts +0 -443
- package/test/temba-flow-render.test.ts +0 -1003
|
@@ -31,6 +31,10 @@ export class Select extends FormElement {
|
|
|
31
31
|
--temba-options-font-size: var(--temba-select-selected-font-size);
|
|
32
32
|
--icon-color: var(--color-text-dark);
|
|
33
33
|
--color-options-bg: #fff;
|
|
34
|
+
/* Always use normal border colors for options popup, even when select is in error state */
|
|
35
|
+
--color-widget-border: #ddd;
|
|
36
|
+
--color-focus: #007bff;
|
|
37
|
+
--widget-box-shadow-focused: 0 0 0 3px rgba(0, 123, 255, 0.25);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
:host:focus {
|
|
@@ -354,6 +358,7 @@ export class Select extends FormElement {
|
|
|
354
358
|
this.selectedIndex = -1;
|
|
355
359
|
this.anchorPosition = { left: 0, top: 0 };
|
|
356
360
|
this.tags = false;
|
|
361
|
+
this.emails = false;
|
|
357
362
|
this.flavor = 'default';
|
|
358
363
|
this.infoText = '';
|
|
359
364
|
this.values = [];
|
|
@@ -419,7 +424,7 @@ export class Select extends FormElement {
|
|
|
419
424
|
}
|
|
420
425
|
this.staticOptions.push(option);
|
|
421
426
|
if (selected) {
|
|
422
|
-
if (this.
|
|
427
|
+
if (this.isMultiMode) {
|
|
423
428
|
this.addValue(option);
|
|
424
429
|
}
|
|
425
430
|
else {
|
|
@@ -537,9 +542,11 @@ export class Select extends FormElement {
|
|
|
537
542
|
}
|
|
538
543
|
}
|
|
539
544
|
// remove any arbitrary values
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
545
|
+
for (let i = this.values.length - 1; i >= 0; i--) {
|
|
546
|
+
if (this.values[i].arbitrary) {
|
|
547
|
+
this.values.splice(i, 1);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
543
550
|
// reset our cache
|
|
544
551
|
this.cacheKey = new Date().getTime().toString();
|
|
545
552
|
this.fireEvent('change');
|
|
@@ -639,9 +646,13 @@ export class Select extends FormElement {
|
|
|
639
646
|
else {
|
|
640
647
|
const name = this.getAttribute('name');
|
|
641
648
|
if (name) {
|
|
642
|
-
if (!this.
|
|
649
|
+
if (!this.isMultiMode && this.values.length === 1) {
|
|
643
650
|
this.selection = this.values[0];
|
|
644
651
|
this.value = this.serializeValue(this.values[0]);
|
|
652
|
+
// Ensure FormElement internals are updated
|
|
653
|
+
if (this.internals) {
|
|
654
|
+
this.internals.setFormValue(this.value);
|
|
655
|
+
}
|
|
645
656
|
}
|
|
646
657
|
else {
|
|
647
658
|
if (this.inputRoot.parentElement) {
|
|
@@ -659,13 +670,13 @@ export class Select extends FormElement {
|
|
|
659
670
|
}
|
|
660
671
|
}
|
|
661
672
|
setSelectedOption(option) {
|
|
662
|
-
if (this.
|
|
673
|
+
if (this.isMultiMode) {
|
|
663
674
|
this.addValue(option);
|
|
664
675
|
}
|
|
665
676
|
else {
|
|
666
677
|
this.setValues([option]);
|
|
667
678
|
}
|
|
668
|
-
if (!this.
|
|
679
|
+
if (!this.isMultiMode || !this.searchable) {
|
|
669
680
|
this.blur();
|
|
670
681
|
this.focused = false;
|
|
671
682
|
}
|
|
@@ -682,7 +693,7 @@ export class Select extends FormElement {
|
|
|
682
693
|
(this.cursorIndex || 0) > this.visibleOptions.length - LOOK_AHEAD);
|
|
683
694
|
}
|
|
684
695
|
handleOptionSelection(event) {
|
|
685
|
-
if (this.
|
|
696
|
+
if (this.isMultiMode &&
|
|
686
697
|
this.maxItems > 0 &&
|
|
687
698
|
this.values.length >= this.maxItems) {
|
|
688
699
|
this.infoText = this.maxItemsText;
|
|
@@ -734,9 +745,24 @@ export class Select extends FormElement {
|
|
|
734
745
|
this.removeValue(selectionToRemove);
|
|
735
746
|
this.visibleOptions = [];
|
|
736
747
|
}
|
|
737
|
-
createArbitraryOptionDefault() {
|
|
748
|
+
createArbitraryOptionDefault(input, _options) {
|
|
749
|
+
if (this.emails && input && this.isValidEmail(input)) {
|
|
750
|
+
return { name: input, value: input };
|
|
751
|
+
}
|
|
752
|
+
if (this.tags && input) {
|
|
753
|
+
return { name: input, value: input };
|
|
754
|
+
}
|
|
738
755
|
return null;
|
|
739
756
|
}
|
|
757
|
+
isValidEmail(email) {
|
|
758
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
759
|
+
return emailRegex.test(email);
|
|
760
|
+
}
|
|
761
|
+
// Helper method to determine if this select should behave as multi-select
|
|
762
|
+
// Returns true if multi is explicitly set OR if emails mode is enabled
|
|
763
|
+
get isMultiMode() {
|
|
764
|
+
return this.multi || this.emails;
|
|
765
|
+
}
|
|
740
766
|
open() {
|
|
741
767
|
this.shadowRoot.querySelector('.select-container').click();
|
|
742
768
|
}
|
|
@@ -788,7 +814,7 @@ export class Select extends FormElement {
|
|
|
788
814
|
// filter out any options already selected by id
|
|
789
815
|
// TODO: should maybe be doing a deep equals here with option to optimize
|
|
790
816
|
if (this.values.length > 0) {
|
|
791
|
-
if (this.
|
|
817
|
+
if (this.isMultiMode) {
|
|
792
818
|
options = options.filter((option) => !this.values.find((selected) => this.getValue(selected) === this.getValue(option)));
|
|
793
819
|
}
|
|
794
820
|
else {
|
|
@@ -802,7 +828,7 @@ export class Select extends FormElement {
|
|
|
802
828
|
this.requestUpdate('cursorIndex');
|
|
803
829
|
}
|
|
804
830
|
}
|
|
805
|
-
if (this.
|
|
831
|
+
if (this.isMultiMode &&
|
|
806
832
|
this.maxItems > 0 &&
|
|
807
833
|
this.values.length >= this.maxItems) {
|
|
808
834
|
options = [];
|
|
@@ -842,6 +868,12 @@ export class Select extends FormElement {
|
|
|
842
868
|
options.splice(0, 0, { name: query, value: query });
|
|
843
869
|
}
|
|
844
870
|
}
|
|
871
|
+
if (this.emails && q) {
|
|
872
|
+
if (this.isValidEmail(q) &&
|
|
873
|
+
!options.find((option) => this.getValue(option) && this.getValue(option).toLowerCase() === q)) {
|
|
874
|
+
options.splice(0, 0, { name: query, value: query });
|
|
875
|
+
}
|
|
876
|
+
}
|
|
845
877
|
if (this.endpoint) {
|
|
846
878
|
let url = this.endpoint;
|
|
847
879
|
if (next) {
|
|
@@ -868,7 +900,7 @@ export class Select extends FormElement {
|
|
|
868
900
|
}
|
|
869
901
|
}
|
|
870
902
|
const cache = this.lruCache.get(url);
|
|
871
|
-
if (this.cache && !this.tags && cache) {
|
|
903
|
+
if (this.cache && !this.tags && !this.emails && cache) {
|
|
872
904
|
if (page === 0 && !this.next) {
|
|
873
905
|
this.cursorIndex = 0;
|
|
874
906
|
this.setVisibleOptions([...options, ...cache.options]);
|
|
@@ -885,7 +917,7 @@ export class Select extends FormElement {
|
|
|
885
917
|
if (this.searchable && !this.queryParam) {
|
|
886
918
|
fetchResults(url).then((results) => {
|
|
887
919
|
results = this.prepareOptions(results);
|
|
888
|
-
if (this.cache && !this.tags) {
|
|
920
|
+
if (this.cache && !this.tags && !this.emails) {
|
|
889
921
|
this.lruCache.set(url, {
|
|
890
922
|
options: results,
|
|
891
923
|
complete: true,
|
|
@@ -922,7 +954,7 @@ export class Select extends FormElement {
|
|
|
922
954
|
}
|
|
923
955
|
this.complete = this.isComplete(results, response);
|
|
924
956
|
}
|
|
925
|
-
if (this.cache && !this.tags) {
|
|
957
|
+
if (this.cache && !this.tags && !this.emails) {
|
|
926
958
|
this.lruCache.set(url, {
|
|
927
959
|
options: results,
|
|
928
960
|
complete: this.complete,
|
|
@@ -960,7 +992,7 @@ export class Select extends FormElement {
|
|
|
960
992
|
this.visibleOptions = [];
|
|
961
993
|
this.cursorIndex = 0;
|
|
962
994
|
}
|
|
963
|
-
if (this.
|
|
995
|
+
if (this.isMultiMode &&
|
|
964
996
|
this.maxItems > 0 &&
|
|
965
997
|
this.values.length >= this.maxItems) {
|
|
966
998
|
this.infoText = '';
|
|
@@ -977,7 +1009,7 @@ export class Select extends FormElement {
|
|
|
977
1009
|
value: ele.value,
|
|
978
1010
|
expression: true
|
|
979
1011
|
};
|
|
980
|
-
if (this.
|
|
1012
|
+
if (this.isMultiMode) {
|
|
981
1013
|
if (!this.values.find((option) => {
|
|
982
1014
|
return (option.expression &&
|
|
983
1015
|
option.value &&
|
|
@@ -992,7 +1024,7 @@ export class Select extends FormElement {
|
|
|
992
1024
|
this.setValues([expression]);
|
|
993
1025
|
}
|
|
994
1026
|
this.input = '';
|
|
995
|
-
if (!this.
|
|
1027
|
+
if (!this.isMultiMode) {
|
|
996
1028
|
this.blur();
|
|
997
1029
|
}
|
|
998
1030
|
}
|
|
@@ -1003,6 +1035,18 @@ export class Select extends FormElement {
|
|
|
1003
1035
|
this.completionOptions.length === 0 &&
|
|
1004
1036
|
this.input.indexOf('@') > -1) {
|
|
1005
1037
|
this.addInputAsValue();
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
// if we are in email mode and have a valid email, add it
|
|
1041
|
+
if (evt.key === 'Enter' &&
|
|
1042
|
+
this.emails &&
|
|
1043
|
+
this.input &&
|
|
1044
|
+
this.isValidEmail(this.input.trim()) &&
|
|
1045
|
+
this.visibleOptions.length === 0) {
|
|
1046
|
+
evt.preventDefault();
|
|
1047
|
+
const emailOption = { name: this.input.trim(), value: this.input.trim() };
|
|
1048
|
+
this.setSelectedOption(emailOption);
|
|
1049
|
+
return;
|
|
1006
1050
|
}
|
|
1007
1051
|
// see if we should open our options on a key event
|
|
1008
1052
|
if (evt.key === 'Enter' ||
|
|
@@ -1017,7 +1061,7 @@ export class Select extends FormElement {
|
|
|
1017
1061
|
}
|
|
1018
1062
|
}
|
|
1019
1063
|
// focus our last item on delete
|
|
1020
|
-
if (this.
|
|
1064
|
+
if (this.isMultiMode && evt.key === 'Backspace' && !this.input) {
|
|
1021
1065
|
if (this.visibleOptions.length > 0) {
|
|
1022
1066
|
this.visibleOptions = [];
|
|
1023
1067
|
return;
|
|
@@ -1130,7 +1174,8 @@ export class Select extends FormElement {
|
|
|
1130
1174
|
}
|
|
1131
1175
|
serializeValue(value) {
|
|
1132
1176
|
// static options just use their value
|
|
1133
|
-
if (!this.jsonValue &&
|
|
1177
|
+
if (!this.jsonValue &&
|
|
1178
|
+
(this.staticOptions.length > 0 || this.isMultiMode)) {
|
|
1134
1179
|
return value.value;
|
|
1135
1180
|
}
|
|
1136
1181
|
return super.serializeValue(value);
|
|
@@ -1159,13 +1204,17 @@ export class Select extends FormElement {
|
|
|
1159
1204
|
}
|
|
1160
1205
|
setValues(values) {
|
|
1161
1206
|
const oldValues = this.values;
|
|
1162
|
-
this.values
|
|
1207
|
+
this.values.splice(0, this.values.length, ...values);
|
|
1163
1208
|
this.requestUpdate('values', oldValues);
|
|
1209
|
+
this.updateInputs();
|
|
1210
|
+
this.fireEvent('change');
|
|
1164
1211
|
}
|
|
1165
1212
|
addValue(value) {
|
|
1166
1213
|
const oldValues = [...this.values];
|
|
1167
1214
|
this.values.push(value);
|
|
1168
1215
|
this.requestUpdate('values', oldValues);
|
|
1216
|
+
this.updateInputs();
|
|
1217
|
+
this.fireEvent('change');
|
|
1169
1218
|
}
|
|
1170
1219
|
removeValue(valueToRemove) {
|
|
1171
1220
|
const oldValues = [...this.values];
|
|
@@ -1186,17 +1235,23 @@ export class Select extends FormElement {
|
|
|
1186
1235
|
}
|
|
1187
1236
|
this.requestUpdate('values', oldValues);
|
|
1188
1237
|
this.infoText = '';
|
|
1238
|
+
this.updateInputs();
|
|
1239
|
+
this.fireEvent('change');
|
|
1189
1240
|
}
|
|
1190
1241
|
popValue() {
|
|
1191
1242
|
const oldValues = [...this.values];
|
|
1192
1243
|
this.values.pop();
|
|
1193
1244
|
this.requestUpdate('values', oldValues);
|
|
1194
1245
|
this.infoText = '';
|
|
1246
|
+
this.updateInputs();
|
|
1247
|
+
this.fireEvent('change');
|
|
1195
1248
|
}
|
|
1196
1249
|
clear() {
|
|
1197
1250
|
const oldValues = this.values;
|
|
1198
|
-
this.values
|
|
1251
|
+
this.values.splice(0, this.values.length);
|
|
1199
1252
|
this.requestUpdate('values', oldValues);
|
|
1253
|
+
this.updateInputs();
|
|
1254
|
+
this.fireEvent('change');
|
|
1200
1255
|
}
|
|
1201
1256
|
shouldShowEmptyMessage() {
|
|
1202
1257
|
return (this.attemptedOpen &&
|
|
@@ -1218,10 +1273,12 @@ export class Select extends FormElement {
|
|
|
1218
1273
|
fromIdx < this.values.length &&
|
|
1219
1274
|
toIdx < this.values.length) {
|
|
1220
1275
|
const oldValues = [...this.values];
|
|
1221
|
-
// Move the item
|
|
1276
|
+
// Move the item using splice operations directly on this.values
|
|
1222
1277
|
const movedItem = this.values.splice(fromIdx, 1)[0];
|
|
1223
1278
|
this.values.splice(toIdx, 0, movedItem);
|
|
1224
1279
|
this.requestUpdate('values', oldValues);
|
|
1280
|
+
this.updateInputs();
|
|
1281
|
+
this.fireEvent('change');
|
|
1225
1282
|
}
|
|
1226
1283
|
}
|
|
1227
1284
|
}
|
|
@@ -1230,7 +1287,7 @@ export class Select extends FormElement {
|
|
|
1230
1287
|
const placeholderDiv = html `
|
|
1231
1288
|
<div class="placeholder">${placeholder}</div>
|
|
1232
1289
|
`;
|
|
1233
|
-
const clear = this.clearable && this.values.length > 0 && !this.
|
|
1290
|
+
const clear = this.clearable && this.values.length > 0 && !this.isMultiMode
|
|
1234
1291
|
? html `<temba-icon
|
|
1235
1292
|
name="${Icon.select_clear}"
|
|
1236
1293
|
size="1.1"
|
|
@@ -1239,8 +1296,8 @@ export class Select extends FormElement {
|
|
|
1239
1296
|
/>`
|
|
1240
1297
|
: null;
|
|
1241
1298
|
const classes = getClasses({
|
|
1242
|
-
multi: this.
|
|
1243
|
-
single: !this.
|
|
1299
|
+
multi: this.isMultiMode,
|
|
1300
|
+
single: !this.isMultiMode,
|
|
1244
1301
|
searchable: this.searchable,
|
|
1245
1302
|
empty: this.values.length === 0,
|
|
1246
1303
|
options: this.visibleOptions.length > 0,
|
|
@@ -1273,8 +1330,8 @@ export class Select extends FormElement {
|
|
|
1273
1330
|
</div>
|
|
1274
1331
|
`
|
|
1275
1332
|
: placeholderDiv;
|
|
1276
|
-
const items = html `${!this.
|
|
1277
|
-
${this.
|
|
1333
|
+
const items = html `${!this.isMultiMode && !this.resolving ? input : null}
|
|
1334
|
+
${this.isMultiMode && this.values.length > 1
|
|
1278
1335
|
? html `
|
|
1279
1336
|
<temba-sortable-list
|
|
1280
1337
|
horizontal
|
|
@@ -1314,7 +1371,7 @@ export class Select extends FormElement {
|
|
|
1314
1371
|
: ''}
|
|
1315
1372
|
"
|
|
1316
1373
|
>
|
|
1317
|
-
${this.
|
|
1374
|
+
${this.isMultiMode
|
|
1318
1375
|
? html `
|
|
1319
1376
|
<div
|
|
1320
1377
|
class="remove-item"
|
|
@@ -1361,7 +1418,7 @@ export class Select extends FormElement {
|
|
|
1361
1418
|
: ''}
|
|
1362
1419
|
"
|
|
1363
1420
|
>
|
|
1364
|
-
${this.
|
|
1421
|
+
${this.isMultiMode
|
|
1365
1422
|
? html `
|
|
1366
1423
|
<div
|
|
1367
1424
|
class="remove-item"
|
|
@@ -1387,12 +1444,12 @@ export class Select extends FormElement {
|
|
|
1387
1444
|
</div>
|
|
1388
1445
|
`
|
|
1389
1446
|
: null}
|
|
1390
|
-
${!this.input || this.
|
|
1447
|
+
${!this.input || this.isMultiMode
|
|
1391
1448
|
? this.renderSelectedItem(selected)
|
|
1392
1449
|
: null}
|
|
1393
1450
|
</div>
|
|
1394
1451
|
`)}
|
|
1395
|
-
${this.
|
|
1452
|
+
${this.isMultiMode ? input : null}`;
|
|
1396
1453
|
return html `
|
|
1397
1454
|
|
|
1398
1455
|
<temba-field
|
|
@@ -1428,7 +1485,7 @@ export class Select extends FormElement {
|
|
|
1428
1485
|
${clear}
|
|
1429
1486
|
|
|
1430
1487
|
<slot name="right"></slot>
|
|
1431
|
-
${!this.tags
|
|
1488
|
+
${!this.tags && !this.emails
|
|
1432
1489
|
? html `<div
|
|
1433
1490
|
class="right-side arrow"
|
|
1434
1491
|
style="display:block;margin-right:5px"
|
|
@@ -1587,6 +1644,9 @@ __decorate([
|
|
|
1587
1644
|
__decorate([
|
|
1588
1645
|
property({ type: Boolean })
|
|
1589
1646
|
], Select.prototype, "tags", void 0);
|
|
1647
|
+
__decorate([
|
|
1648
|
+
property({ type: Boolean })
|
|
1649
|
+
], Select.prototype, "emails", void 0);
|
|
1590
1650
|
__decorate([
|
|
1591
1651
|
property({ type: Boolean, attribute: 'space_select' })
|
|
1592
1652
|
], Select.prototype, "spaceSelect", void 0);
|