@nyaruka/temba-components 0.129.9 → 0.129.11
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 +23 -0
- package/demo/data/flows/sample-flow.json +96 -56
- package/demo/test-colorpicker.html +30 -0
- package/dist/temba-components.js +896 -934
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +9 -6
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/config.js +2 -8
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +101 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +4 -89
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +123 -3
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +115 -13
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +160 -12
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +45 -56
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/BaseListEditor.js +4 -3
- package/out-tsc/src/form/BaseListEditor.js.map +1 -1
- package/out-tsc/src/form/Checkbox.js +77 -24
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/ColorPicker.js +28 -40
- package/out-tsc/src/form/ColorPicker.js.map +1 -1
- package/out-tsc/src/form/Completion.js +44 -53
- package/out-tsc/src/form/Completion.js.map +1 -1
- package/out-tsc/src/form/Compose.js +7 -8
- package/out-tsc/src/form/Compose.js.map +1 -1
- package/out-tsc/src/form/ContactSearch.js +3 -4
- package/out-tsc/src/form/ContactSearch.js.map +1 -1
- package/out-tsc/src/form/DatePicker.js +29 -36
- package/out-tsc/src/form/DatePicker.js.map +1 -1
- package/out-tsc/src/form/{FormField.js → FieldElement.js} +78 -50
- package/out-tsc/src/form/FieldElement.js.map +1 -0
- package/out-tsc/src/form/FieldRenderer.js +2 -1
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/ImagePicker.js +122 -126
- package/out-tsc/src/form/ImagePicker.js.map +1 -1
- package/out-tsc/src/form/KeyValueEditor.js +41 -37
- package/out-tsc/src/form/KeyValueEditor.js.map +1 -1
- package/out-tsc/src/form/MessageEditor.js +55 -63
- package/out-tsc/src/form/MessageEditor.js.map +1 -1
- package/out-tsc/src/form/TembaSlider.js +3 -3
- package/out-tsc/src/form/TembaSlider.js.map +1 -1
- package/out-tsc/src/form/TemplateEditor.js +3 -3
- package/out-tsc/src/form/TemplateEditor.js.map +1 -1
- package/out-tsc/src/form/TextInput.js +22 -26
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +9 -15
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/form/select/UserSelect.js +8 -9
- package/out-tsc/src/form/select/UserSelect.js.map +1 -1
- package/out-tsc/src/form/select/WorkspaceSelect.js +7 -8
- package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +73 -99
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/live/ContactFieldEditor.js.map +1 -1
- package/out-tsc/src/utils.js +115 -0
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +3 -2
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +174 -0
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -0
- package/out-tsc/test/temba-checkbox.test.js +16 -0
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-integration-markdown.test.js +2 -4
- package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-slider.test.js +0 -1
- package/out-tsc/test/temba-slider.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/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/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/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_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/checkbox/checkbox-label-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-no-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-whitespace-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
- package/screenshots/truth/checkbox/checked.png +0 -0
- package/screenshots/truth/checkbox/default.png +0 -0
- package/screenshots/truth/colorpicker/default.png +0 -0
- package/screenshots/truth/colorpicker/focused.png +0 -0
- package/screenshots/truth/colorpicker/initialized.png +0 -0
- package/screenshots/truth/colorpicker/selected.png +0 -0
- package/screenshots/truth/compose/attachments-tab.png +0 -0
- package/screenshots/truth/compose/attachments-with-files.png +0 -0
- package/screenshots/truth/compose/intial-text.png +0 -0
- package/screenshots/truth/compose/no-counter.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
- package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/screenshots/truth/counter/summary.png +0 -0
- package/screenshots/truth/counter/text.png +0 -0
- package/screenshots/truth/counter/unicode-variables.png +0 -0
- package/screenshots/truth/counter/unicode.png +0 -0
- package/screenshots/truth/counter/variable.png +0 -0
- package/screenshots/truth/datepicker/date-truncated-time.png +0 -0
- package/screenshots/truth/datepicker/date.png +0 -0
- package/screenshots/truth/datepicker/initial-timezone.png +0 -0
- package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
- package/screenshots/truth/datepicker/updated-keyboard-date.png +0 -0
- package/screenshots/truth/dialog/focused.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.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/field-renderer/checkbox-checked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-unchecked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/context-comparison.png +0 -0
- package/screenshots/truth/field-renderer/key-value-with-label.png +0 -0
- package/screenshots/truth/field-renderer/message-editor-with-label.png +0 -0
- package/screenshots/truth/field-renderer/select-multi.png +0 -0
- package/screenshots/truth/field-renderer/select-no-label.png +0 -0
- package/screenshots/truth/field-renderer/select-with-label.png +0 -0
- package/screenshots/truth/field-renderer/text-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/text-no-label.png +0 -0
- package/screenshots/truth/field-renderer/text-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/text-with-label.png +0 -0
- package/screenshots/truth/field-renderer/textarea-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/textarea-with-label.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/fields-filtered.png +0 -0
- package/screenshots/truth/list/fields-hovered.png +0 -0
- package/screenshots/truth/list/fields.png +0 -0
- package/screenshots/truth/list/items-selected.png +0 -0
- package/screenshots/truth/list/items-updated.png +0 -0
- package/screenshots/truth/list/items.png +0 -0
- package/screenshots/truth/menu/menu-focused-with items.png +0 -0
- package/screenshots/truth/menu/menu-refresh-1.png +0 -0
- package/screenshots/truth/menu/menu-refresh-2.png +0 -0
- package/screenshots/truth/menu/menu-submenu.png +0 -0
- package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
- package/screenshots/truth/menu/menu-tasks.png +0 -0
- package/screenshots/truth/message-editor/autogrow-initial-content.png +0 -0
- package/screenshots/truth/message-editor/default.png +0 -0
- package/screenshots/truth/message-editor/drag-highlight.png +0 -0
- package/screenshots/truth/message-editor/filtered-attachments.png +0 -0
- package/screenshots/truth/message-editor/with-completion.png +0 -0
- package/screenshots/truth/message-editor/with-properties.png +0 -0
- package/screenshots/truth/modax/form.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/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_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_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_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/omnibox/selected.png +0 -0
- package/screenshots/truth/options/block.png +0 -0
- package/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/select/disabled-multi-selection.png +0 -0
- package/screenshots/truth/select/disabled-selection.png +0 -0
- package/screenshots/truth/select/disabled.png +0 -0
- package/screenshots/truth/select/embedded.png +0 -0
- package/screenshots/truth/select/empty-options.png +0 -0
- package/screenshots/truth/select/expression-selected.png +0 -0
- package/screenshots/truth/select/expressions.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/local-options.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/multiple-initial-values.png +0 -0
- package/screenshots/truth/select/remote-options.png +0 -0
- package/screenshots/truth/select/search-enabled.png +0 -0
- package/screenshots/truth/select/search-multi-no-matches.png +0 -0
- package/screenshots/truth/select/search-selected-focus.png +0 -0
- package/screenshots/truth/select/search-selected.png +0 -0
- package/screenshots/truth/select/search-with-selected.png +0 -0
- package/screenshots/truth/select/searching.png +0 -0
- package/screenshots/truth/select/selected-multi-maxitems-reached.png +0 -0
- package/screenshots/truth/select/selected-multi.png +0 -0
- package/screenshots/truth/select/selected-single.png +0 -0
- package/screenshots/truth/select/selection-clearable.png +0 -0
- package/screenshots/truth/select/static-initial-value.png +0 -0
- package/screenshots/truth/select/static-initial-via-selected.png +0 -0
- package/screenshots/truth/select/truncated-selection.png +0 -0
- package/screenshots/truth/select/with-placeholder.png +0 -0
- package/screenshots/truth/select/without-placeholder.png +0 -0
- package/screenshots/truth/slider/update-slider-on-circle-dragged.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/templates/unapproved.png +0 -0
- package/screenshots/truth/textinput/autogrow-initial.png +0 -0
- package/screenshots/truth/textinput/input-disabled.png +0 -0
- package/screenshots/truth/textinput/input-focused.png +0 -0
- package/screenshots/truth/textinput/input-form.png +0 -0
- package/screenshots/truth/textinput/input-inserted.png +0 -0
- package/screenshots/truth/textinput/input-placeholder.png +0 -0
- package/screenshots/truth/textinput/input-updated.png +0 -0
- package/screenshots/truth/textinput/input.png +0 -0
- package/screenshots/truth/textinput/textarea-focused.png +0 -0
- package/screenshots/truth/textinput/textarea.png +0 -0
- package/src/events.ts +9 -8
- package/src/flow/Editor.ts +6 -3
- package/src/flow/actions/set_contact_channel.ts +1 -1
- package/src/flow/actions/set_contact_field.ts +1 -1
- package/src/flow/actions/set_contact_language.ts +1 -1
- package/src/flow/actions/set_contact_status.ts +1 -1
- package/src/flow/config.ts +2 -8
- package/src/flow/nodes/split_by_llm.ts +119 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +13 -116
- package/src/flow/nodes/split_by_subflow.ts +153 -3
- package/src/flow/nodes/split_by_ticket.ts +135 -12
- package/src/flow/nodes/split_by_webhook.ts +187 -12
- package/src/form/ArrayEditor.ts +45 -57
- package/src/form/BaseListEditor.ts +4 -4
- package/src/form/Checkbox.ts +81 -24
- package/src/form/ColorPicker.ts +31 -43
- package/src/form/Completion.ts +49 -56
- package/src/form/Compose.ts +8 -8
- package/src/form/ContactSearch.ts +3 -4
- package/src/form/DatePicker.ts +32 -38
- package/src/form/{FormField.ts → FieldElement.ts} +105 -52
- package/src/form/FieldRenderer.ts +2 -1
- package/src/form/ImagePicker.ts +107 -110
- package/src/form/KeyValueEditor.ts +43 -39
- package/src/form/MessageEditor.ts +61 -67
- package/src/form/TembaSlider.ts +3 -3
- package/src/form/TemplateEditor.ts +3 -3
- package/src/form/TextInput.ts +25 -28
- package/src/form/select/Select.ts +12 -17
- package/src/form/select/UserSelect.ts +10 -11
- package/src/form/select/WorkspaceSelect.ts +9 -10
- package/src/live/ContactChat.ts +81 -92
- package/src/live/ContactFieldEditor.ts +2 -2
- package/src/store/flow-definition.d.ts +2 -1
- package/src/utils.ts +192 -0
- package/temba-modules.ts +3 -2
- package/test/nodes/split_by_llm.test.ts +232 -0
- package/test/temba-checkbox.test.ts +26 -0
- package/test/temba-integration-markdown.test.ts +2 -4
- package/test/temba-slider.test.ts +0 -1
- package/test-assets/contacts/history.json +7 -20
- package/test-assets/style.css +36 -234
- package/web-dev-server.config.mjs +26 -0
- package/web-test-runner.config.mjs +1 -1
- package/out-tsc/src/flow/actions/call_llm.js +0 -64
- package/out-tsc/src/flow/actions/call_llm.js.map +0 -1
- package/out-tsc/src/flow/actions/call_webhook.js +0 -131
- package/out-tsc/src/flow/actions/call_webhook.js.map +0 -1
- package/out-tsc/src/flow/actions/enter_flow.js +0 -14
- package/out-tsc/src/flow/actions/enter_flow.js.map +0 -1
- package/out-tsc/src/flow/actions/open_ticket.js +0 -73
- package/out-tsc/src/flow/actions/open_ticket.js.map +0 -1
- package/out-tsc/src/form/FormElement.js +0 -67
- package/out-tsc/src/form/FormElement.js.map +0 -1
- package/out-tsc/src/form/FormField.js.map +0 -1
- package/out-tsc/test/actions/call_llm.test.js +0 -103
- package/out-tsc/test/actions/call_llm.test.js.map +0 -1
- package/out-tsc/test/temba-formfield.test.js +0 -94
- package/out-tsc/test/temba-formfield.test.js.map +0 -1
- package/src/flow/actions/call_llm.ts +0 -66
- package/src/flow/actions/call_webhook.ts +0 -143
- package/src/flow/actions/enter_flow.ts +0 -15
- package/src/flow/actions/open_ticket.ts +0 -83
- package/src/form/FormElement.ts +0 -69
- package/test/actions/call_llm.test.ts +0 -137
- package/test/temba-formfield.test.ts +0 -121
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImagePicker.js","sourceRoot":"","sources":["../../../src/form/ImagePicker.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-this-alias */\nimport { html, css, PropertyValueMap } from 'lit';\nimport { CroppieCSS } from './CroppieCSS';\nimport { property } from 'lit/decorators.js';\nimport { Icon } from '../Icons';\nimport { FormElement } from './FormElement';\n\nexport class ImagePicker extends FormElement {\n static styles = css`\n ${CroppieCSS}\n\n .croppie {\n max-width: 400px;\n border: 0px solid #ccc;\n border-radius: 0.5em;\n overflow: hidden;\n background: #fff;\n margin-top: -20%;\n box-shadow: 0 0 15px 5px rgba(0, 0, 0, 0.1);\n }\n\n .croppie .controls {\n display: flex;\n align-items: center;\n flex-direction: row;\n justify-content: center;\n position: absolute;\n z-index: 1;\n width: 400px;\n margin-top: -42px;\n }\n\n .toggle {\n height: 110px;\n width: 110px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .circle .toggle {\n border-radius: 50%;\n }\n\n .toggle.set {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, inset 0 0 0 5px rgba(0, 0, 0, 0.1);\n }\n\n .toggle.set:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, inset 0 0 0 5px rgba(0, 0, 0, 0.2);\n }\n\n .toggle temba-icon {\n color: rgba(0, 0, 0, 0.2);\n padding: 5px;\n }\n\n toggle:hover temba-icon {\n color: rgba(0, 0, 0, 0.8);\n }\n\n .toggle.set temba-icon {\n border-radius: 50%;\n margin-right: -90%;\n margin-bottom: -50%;\n background: rgba(240, 240, 240, 1);\n box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n }\n\n .toggle.set:hover temba-icon {\n background: #fff;\n color: var(--color-primary-dark);\n }\n\n .circle .toggle.set temba-icon {\n margin-right: -70%;\n margin-bottom: -70%;\n }\n\n .hidden {\n display: none;\n }\n\n .controls temba-icon {\n margin: 0em 0.75em;\n background: rgba(255, 255, 255, 0.8);\n border-radius: 50%;\n padding: 6px;\n transition: all 0.1s ease-in-out;\n }\n\n .controls {\n pointer-events: none;\n display: flex;\n }\n\n .controls temba-icon {\n pointer-events: all;\n }\n\n .controls temba-icon.close {\n color: rgba(0, 0, 0, 0.2);\n background: rgba(255, 255, 255, 0.2);\n }\n\n .controls temba-icon.submit {\n color: rgba(0, 0, 0, 0.2);\n box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.1);\n }\n\n .controls temba-icon:hover {\n color: white;\n cursor: pointer;\n background: var(--color-primary-dark);\n }\n `;\n\n @property({ type: String })\n tempImage: string;\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n shape = 'square';\n\n @property({ type: Boolean, attribute: false })\n showCroppie = false;\n\n uploadReader = new FileReader();\n croppie: any;\n\n protected firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const picker = this;\n\n this.uploadReader.onload = function () {\n picker.launchCroppie(picker.uploadReader.result as any);\n };\n }\n\n public updated(changed: Map<string, any>): void {\n super.updated(changed);\n if (changed.has('url')) {\n this.setAttribute('url', this.url);\n }\n }\n\n private closeCroppie() {\n this.showCroppie = false;\n const wrapper = this.shadowRoot.querySelector('.croppie .embed');\n if (wrapper.firstChild) {\n wrapper.removeChild(wrapper.firstChild);\n }\n }\n\n private launchCroppie(url: string) {\n const wrapper = this.shadowRoot.querySelector('.croppie .embed');\n if (wrapper.firstChild) {\n wrapper.removeChild(wrapper.firstChild);\n }\n this.showCroppie = true;\n const ele = document.createElement('div');\n wrapper.appendChild(ele);\n\n const Croppie = (window as any).Croppie;\n this.croppie = new Croppie(ele, {\n enableExif: true,\n viewport: {\n width: 300,\n height: 300,\n type: this.shape\n },\n boundary: {\n width: 400,\n height: 400\n }\n });\n\n this.croppie.bind({ url });\n }\n\n private saveResult() {\n const picker = this;\n this.croppie\n .result({\n type: 'blob',\n size: 'viewport',\n format: 'webp',\n quality: 1,\n circle: false\n })\n .then(function (resp: any) {\n const blob = resp;\n picker.url = URL.createObjectURL(blob);\n\n // const blob = dataURItoBlob(resp);\n const fd = new FormData();\n fd.append(picker.name, blob, 'filename.webp');\n\n picker.value = fd;\n picker.closeCroppie();\n });\n }\n\n private handleToggleClicked() {\n const fileInput = this.shadowRoot.querySelector('#file');\n (fileInput as any).click();\n }\n\n private handleFileChanged(e: Event) {\n const input = e.target as any;\n if (input.files.length > 0) {\n this.uploadReader.readAsDataURL(input.files[0]);\n }\n input.value = '';\n }\n\n protected render() {\n return html`\n <div class=\"wrapper ${this.shape} ${this.label ? 'label' : ''}\">\n <temba-field\n name=${this.name}\n label=${this.label}\n .helpText=${this.helpText}\n .errors=${this.errors}\n .widgetOnly=${this.widgetOnly}\n .helpAlways=${true}\n ?disabled=${this.disabled}\n >\n <input class='hidden' type=\"file\" accept=\"image/*\" capture=\"camera\" id=\"file\" name=\"file\" @change=${\n this.handleFileChanged\n }/>\n <div class='toggle ${this.url ? 'set' : ''} ${\n this.showCroppie ? 'hidden' : ''\n }' @click=${this.handleToggleClicked} style=\"background: ${\n this.url\n ? `url('${this.url}') center / contain no-repeat`\n : 'rgba(0, 0, 0, 0.1)'\n }\">\n <temba-icon name=${Icon.upload_image} size=\"1.5\"></temba-icon>\n </div>\n \n <temba-mask ?show=${this.showCroppie} class=\"${\n this.showCroppie ? 'editing' : ''\n }\">\n <div class='croppie'>\n <div class='embed'></div>\n <div class='controls'>\n <temba-icon class=\"close\" size=\"1\" name=${Icon.close} @click=${\n this.closeCroppie\n }></temba-icon>\n <div style=\"flex-grow:1\"></div>\n <temba-icon class=\"submit\" size=\"1\" name=${Icon.submit} @click=${\n this.saveResult\n }></temba-icon>\n </div>\n </temba-mask>\n </temba-field>\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ImagePicker.js","sourceRoot":"","sources":["../../../src/form/ImagePicker.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-this-alias */\nimport { html, css, PropertyValueMap } from 'lit';\nimport { CroppieCSS } from './CroppieCSS';\nimport { property } from 'lit/decorators.js';\nimport { Icon } from '../Icons';\nimport { FieldElement } from './FieldElement';\n\nexport class ImagePicker extends FieldElement {\n static get styles() {\n return css`\n ${super.styles}\n ${CroppieCSS}\n\n .croppie {\n max-width: 400px;\n border: 0px solid #ccc;\n border-radius: 0.5em;\n overflow: hidden;\n background: #fff;\n margin-top: -20%;\n box-shadow: 0 0 15px 5px rgba(0, 0, 0, 0.1);\n }\n\n .croppie .controls {\n display: flex;\n align-items: center;\n flex-direction: row;\n justify-content: center;\n position: absolute;\n z-index: 1;\n width: 400px;\n margin-top: -42px;\n }\n\n .toggle {\n height: 110px;\n width: 110px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .circle .toggle {\n border-radius: 50%;\n }\n\n .toggle.set {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, inset 0 0 0 5px rgba(0, 0, 0, 0.1);\n }\n\n .toggle.set:hover {\n box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 7px 0px,\n rgba(0, 0, 0, 0.2) 0px 1px 2px 0px, inset 0 0 0 5px rgba(0, 0, 0, 0.2);\n }\n\n .toggle temba-icon {\n color: rgba(0, 0, 0, 0.2);\n padding: 5px;\n }\n\n toggle:hover temba-icon {\n color: rgba(0, 0, 0, 0.8);\n }\n\n .toggle.set temba-icon {\n border-radius: 50%;\n margin-right: -90%;\n margin-bottom: -50%;\n background: rgba(240, 240, 240, 1);\n box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px 0px;\n }\n\n .toggle.set:hover temba-icon {\n background: #fff;\n color: var(--color-primary-dark);\n }\n\n .circle .toggle.set temba-icon {\n margin-right: -70%;\n margin-bottom: -70%;\n }\n\n .hidden {\n display: none;\n }\n\n .controls temba-icon {\n margin: 0em 0.75em;\n background: rgba(255, 255, 255, 0.8);\n border-radius: 50%;\n padding: 6px;\n transition: all 0.1s ease-in-out;\n }\n\n .controls {\n pointer-events: none;\n display: flex;\n }\n\n .controls temba-icon {\n pointer-events: all;\n }\n\n .controls temba-icon.close {\n color: rgba(0, 0, 0, 0.2);\n background: rgba(255, 255, 255, 0.2);\n }\n\n .controls temba-icon.submit {\n color: rgba(0, 0, 0, 0.2);\n box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.1);\n }\n\n .controls temba-icon:hover {\n color: white;\n cursor: pointer;\n background: var(--color-primary-dark);\n }\n `;\n }\n\n @property({ type: String })\n tempImage: string;\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n shape = 'square';\n\n @property({ type: Boolean, attribute: false })\n showCroppie = false;\n\n uploadReader = new FileReader();\n croppie: any;\n\n protected firstUpdated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changed);\n const picker = this;\n\n this.uploadReader.onload = function () {\n picker.launchCroppie(picker.uploadReader.result as any);\n };\n }\n\n public updated(changed: Map<string, any>): void {\n super.updated(changed);\n if (changed.has('url')) {\n this.setAttribute('url', this.url);\n }\n }\n\n private closeCroppie() {\n this.showCroppie = false;\n const wrapper = this.shadowRoot.querySelector('.croppie .embed');\n if (wrapper.firstChild) {\n wrapper.removeChild(wrapper.firstChild);\n }\n }\n\n private launchCroppie(url: string) {\n const wrapper = this.shadowRoot.querySelector('.croppie .embed');\n if (wrapper.firstChild) {\n wrapper.removeChild(wrapper.firstChild);\n }\n this.showCroppie = true;\n const ele = document.createElement('div');\n wrapper.appendChild(ele);\n\n const Croppie = (window as any).Croppie;\n this.croppie = new Croppie(ele, {\n enableExif: true,\n viewport: {\n width: 300,\n height: 300,\n type: this.shape\n },\n boundary: {\n width: 400,\n height: 400\n }\n });\n\n this.croppie.bind({ url });\n }\n\n private saveResult() {\n const picker = this;\n this.croppie\n .result({\n type: 'blob',\n size: 'viewport',\n format: 'webp',\n quality: 1,\n circle: false\n })\n .then(function (resp: any) {\n const blob = resp;\n picker.url = URL.createObjectURL(blob);\n\n // const blob = dataURItoBlob(resp);\n const fd = new FormData();\n fd.append(picker.name, blob, 'filename.webp');\n\n picker.value = fd;\n picker.closeCroppie();\n });\n }\n\n private handleToggleClicked() {\n const fileInput = this.shadowRoot.querySelector('#file');\n (fileInput as any).click();\n }\n\n private handleFileChanged(e: Event) {\n const input = e.target as any;\n if (input.files.length > 0) {\n this.uploadReader.readAsDataURL(input.files[0]);\n }\n input.value = '';\n }\n\n protected renderWidget() {\n return html`\n <div class=\"wrapper ${this.shape} ${this.label ? 'label' : ''}\">\n <input class='hidden' type=\"file\" accept=\"image/*\" capture=\"camera\" id=\"file\" name=\"file\" @change=${\n this.handleFileChanged\n }/>\n <div class='toggle ${this.url ? 'set' : ''} ${\n this.showCroppie ? 'hidden' : ''\n }' @click=${this.handleToggleClicked} style=\"background: ${\n this.url\n ? `url('${this.url}') center / contain no-repeat`\n : 'rgba(0, 0, 0, 0.1)'\n }\">\n <temba-icon name=${Icon.upload_image} size=\"1.5\"></temba-icon>\n </div>\n \n <temba-mask ?show=${this.showCroppie} class=\"${\n this.showCroppie ? 'editing' : ''\n }\">\n <div class='croppie'>\n <div class='embed'></div>\n <div class='controls'>\n <temba-icon class=\"close\" size=\"1\" name=${Icon.close} @click=${\n this.closeCroppie\n }></temba-icon>\n <div style=\"flex-grow:1\"></div>\n <temba-icon class=\"submit\" size=\"1\" name=${Icon.submit} @click=${\n this.saveResult\n }></temba-icon>\n </div>\n </temba-mask>\n </div>\n `;\n }\n\n public render() {\n return this.renderField();\n }\n}\n"]}
|
|
@@ -158,49 +158,53 @@ let KeyValueEditor = class KeyValueEditor extends BaseListEditor {
|
|
|
158
158
|
getContainerClass() {
|
|
159
159
|
return 'key-value-editor';
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
display: flex;
|
|
165
|
-
flex-direction: column;
|
|
166
|
-
gap: 8px;
|
|
167
|
-
}
|
|
161
|
+
static get styles() {
|
|
162
|
+
return css `
|
|
163
|
+
${super.styles}
|
|
168
164
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
165
|
+
.key-value-editor {
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-direction: column;
|
|
168
|
+
gap: 8px;
|
|
169
|
+
}
|
|
175
170
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
color: #666;
|
|
183
|
-
cursor: pointer;
|
|
184
|
-
display: flex;
|
|
185
|
-
align-items: center;
|
|
186
|
-
justify-content: center;
|
|
187
|
-
font-size: 18px;
|
|
188
|
-
}
|
|
171
|
+
.row {
|
|
172
|
+
display: grid;
|
|
173
|
+
grid-template-columns: 1fr 1fr auto;
|
|
174
|
+
align-items: center;
|
|
175
|
+
column-gap: 6px;
|
|
176
|
+
}
|
|
189
177
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
178
|
+
.remove-btn {
|
|
179
|
+
width: 32px;
|
|
180
|
+
height: 32px;
|
|
181
|
+
border: 1px solid #ccc;
|
|
182
|
+
border-radius: 4px;
|
|
183
|
+
background: #f8f8f8;
|
|
184
|
+
color: #666;
|
|
185
|
+
cursor: pointer;
|
|
186
|
+
display: flex;
|
|
187
|
+
align-items: center;
|
|
188
|
+
justify-content: center;
|
|
189
|
+
font-size: 18px;
|
|
190
|
+
}
|
|
193
191
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
.remove-btn:hover:not(:disabled) {
|
|
193
|
+
background: #f0f0f0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.remove-btn:disabled {
|
|
197
|
+
opacity: 0.5;
|
|
198
|
+
cursor: not-allowed;
|
|
199
|
+
}
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
201
|
+
.remove-btn-spacer {
|
|
202
|
+
width: 32px;
|
|
203
|
+
height: 32px;
|
|
204
|
+
}
|
|
205
|
+
`;
|
|
202
206
|
}
|
|
203
|
-
|
|
207
|
+
};
|
|
204
208
|
__decorate([
|
|
205
209
|
property({ type: String })
|
|
206
210
|
], KeyValueEditor.prototype, "keyPlaceholder", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyValueEditor.js","sourceRoot":"","sources":["../../../src/form/KeyValueEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, TemplateResult } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { BaseListEditor, ListItem } from './BaseListEditor';\n\ninterface KeyValueItem extends ListItem {\n key: string;\n value: string;\n}\n\n@customElement('temba-key-value-editor')\nexport class KeyValueEditor extends BaseListEditor<KeyValueItem> {\n @property({ type: String })\n keyPlaceholder = 'Key';\n\n @property({ type: String })\n valuePlaceholder = 'Value';\n\n @property({ type: Boolean })\n showValidation = true;\n\n @state()\n private keyErrors: { [index: number]: string } = {};\n\n // Configure to maintain empty items\n maintainEmptyItem = true;\n\n constructor() {\n super();\n this._items = [];\n }\n\n // External API uses array format to preserve duplicate keys\n @property({ type: Array })\n get value(): KeyValueItem[] {\n return this._items.filter(\n ({ key, value }) => key.trim() !== '' || value.trim() !== ''\n );\n }\n\n set value(newValue: KeyValueItem[] | Record<string, string>) {\n if (Array.isArray(newValue)) {\n this._items = [...newValue];\n } else {\n // Convert Record to array format\n this._items = Object.entries(newValue || {}).map(([key, value]) => ({\n key,\n value: typeof value === 'string' ? value : String(value)\n }));\n }\n this.requestUpdate();\n }\n\n // Implement abstract methods\n isEmptyItem(item: KeyValueItem): boolean {\n return item.key.trim() === '' && item.value.trim() === '';\n }\n\n createEmptyItem(): KeyValueItem {\n return { key: '', value: '' };\n }\n\n // Override cleanItems to return array format to preserve duplicate keys\n protected cleanItems(items: KeyValueItem[]): KeyValueItem[] {\n return items.filter(\n ({ key, value }) => key.trim() !== '' || value.trim() !== ''\n );\n }\n\n // Method to convert to Record format for final form submission\n toRecord(): Record<string, string> {\n const result: Record<string, string> = {};\n this._items.forEach(({ key, value }) => {\n if (key.trim() !== '' || value.trim() !== '') {\n result[key] = value;\n }\n });\n return result;\n }\n\n // Method to validate and set key errors for duplicates and empty keys with values\n validateKeys(): boolean {\n const newKeyErrors: { [index: number]: string } = {};\n\n // Check for empty keys with values\n this._items.forEach(({ key, value }, index) => {\n if (key.trim() === '' && value.trim() !== '') {\n newKeyErrors[index] = 'Key is required when value is provided';\n }\n });\n\n // Check for duplicate keys (only non-empty ones)\n const nonEmptyKeys = this._items\n .map(({ key }, index) => ({ key: key.trim(), index }))\n .filter(({ key }) => key !== '');\n\n const keyCount = new Map<string, number[]>();\n nonEmptyKeys.forEach(({ key, index }) => {\n if (!keyCount.has(key)) {\n keyCount.set(key, []);\n }\n keyCount.get(key)!.push(index);\n });\n\n // Mark duplicate keys with errors\n keyCount.forEach((indices, key) => {\n if (indices.length > 1) {\n indices.forEach((index) => {\n // Only show duplicate error if there's no empty key error already\n if (!newKeyErrors[index]) {\n newKeyErrors[index] = `Duplicate key \"${key}\"`;\n }\n });\n }\n });\n\n this.keyErrors = newKeyErrors;\n return Object.keys(newKeyErrors).length === 0;\n }\n\n // Clear key errors\n clearKeyErrors(): void {\n this.keyErrors = {};\n }\n\n // Override updateValue to emit array format and validate keys\n protected updateValue(newValue: KeyValueItem[]) {\n this._items = newValue;\n\n // Clear errors and re-validate when items change\n this.clearKeyErrors();\n this.validateKeys();\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: { value: this.cleanItems(newValue) },\n bubbles: true\n })\n );\n this.requestUpdate();\n }\n\n private handleKeyChange(index: number, newKey: string) {\n const items = this.displayItems;\n const currentItem = items[index];\n\n // Clear any existing error for this key when it's modified\n if (this.keyErrors[index]) {\n const newKeyErrors = { ...this.keyErrors };\n delete newKeyErrors[index];\n this.keyErrors = newKeyErrors;\n }\n\n this.handleItemChange(index, {\n key: newKey,\n value: currentItem.value\n });\n }\n\n private handleValueChange(index: number, newValue: string) {\n const items = this.displayItems;\n const currentItem = items[index];\n\n // Clear any existing error for this key when value is modified\n if (this.keyErrors[index]) {\n const newKeyErrors = { ...this.keyErrors };\n delete newKeyErrors[index];\n this.keyErrors = newKeyErrors;\n }\n\n this.handleItemChange(index, {\n key: currentItem.key,\n value: newValue\n });\n }\n\n renderItem(item: KeyValueItem, index: number): TemplateResult {\n const canRemove = this.canRemoveItem(index);\n const keyError =\n this.showValidation && this.keyErrors[index] ? this.keyErrors[index] : '';\n\n return html`\n <div class=\"row\">\n <temba-textinput\n .value=${item.key}\n .placeholder=${this.keyPlaceholder}\n .errors=${keyError ? [keyError] : []}\n @change=${(e: any) => this.handleKeyChange(index, e.target.value)}\n ></temba-textinput>\n <temba-textinput\n .value=${item.value}\n .placeholder=${this.valuePlaceholder}\n @change=${(e: any) => this.handleValueChange(index, e.target.value)}\n ></temba-textinput>\n ${canRemove\n ? html`\n <button class=\"remove-btn\" @click=${() => this.removeItem(index)}>\n ×\n </button>\n `\n : html`<div class=\"remove-btn-spacer\"></div>`}\n </div>\n `;\n }\n\n protected getContainerClass(): string {\n return 'key-value-editor';\n }\n\n static styles = css`\n .key-value-editor {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .row {\n display: grid;\n grid-template-columns: 1fr 1fr auto;\n align-items: center;\n column-gap: 6px;\n }\n\n .remove-btn {\n width: 32px;\n height: 32px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: #f8f8f8;\n color: #666;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n }\n\n .remove-btn:hover:not(:disabled) {\n background: #f0f0f0;\n }\n\n .remove-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .remove-btn-spacer {\n width: 32px;\n height: 32px;\n }\n `;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"KeyValueEditor.js","sourceRoot":"","sources":["../../../src/form/KeyValueEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, TemplateResult } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { BaseListEditor, ListItem } from './BaseListEditor';\n\ninterface KeyValueItem extends ListItem {\n key: string;\n value: string;\n}\n\n@customElement('temba-key-value-editor')\nexport class KeyValueEditor extends BaseListEditor<KeyValueItem> {\n @property({ type: String })\n keyPlaceholder = 'Key';\n\n @property({ type: String })\n valuePlaceholder = 'Value';\n\n @property({ type: Boolean })\n showValidation = true;\n\n @state()\n private keyErrors: { [index: number]: string } = {};\n\n // Configure to maintain empty items\n maintainEmptyItem = true;\n\n constructor() {\n super();\n this._items = [];\n }\n\n // External API uses array format to preserve duplicate keys\n @property({ type: Array })\n get value(): KeyValueItem[] | any[] {\n return this._items.filter(\n ({ key, value }) => key.trim() !== '' || value.trim() !== ''\n );\n }\n\n set value(newValue: KeyValueItem[] | Record<string, string> | any) {\n if (Array.isArray(newValue)) {\n this._items = [...newValue];\n } else {\n // Convert Record to array format\n this._items = Object.entries(newValue || {}).map(([key, value]) => ({\n key,\n value: typeof value === 'string' ? value : String(value)\n }));\n }\n this.requestUpdate();\n }\n\n // Implement abstract methods\n isEmptyItem(item: KeyValueItem): boolean {\n return item.key.trim() === '' && item.value.trim() === '';\n }\n\n createEmptyItem(): KeyValueItem {\n return { key: '', value: '' };\n }\n\n // Override cleanItems to return array format to preserve duplicate keys\n protected cleanItems(items: KeyValueItem[]): KeyValueItem[] {\n return items.filter(\n ({ key, value }) => key.trim() !== '' || value.trim() !== ''\n );\n }\n\n // Method to convert to Record format for final form submission\n toRecord(): Record<string, string> {\n const result: Record<string, string> = {};\n this._items.forEach(({ key, value }) => {\n if (key.trim() !== '' || value.trim() !== '') {\n result[key] = value;\n }\n });\n return result;\n }\n\n // Method to validate and set key errors for duplicates and empty keys with values\n validateKeys(): boolean {\n const newKeyErrors: { [index: number]: string } = {};\n\n // Check for empty keys with values\n this._items.forEach(({ key, value }, index) => {\n if (key.trim() === '' && value.trim() !== '') {\n newKeyErrors[index] = 'Key is required when value is provided';\n }\n });\n\n // Check for duplicate keys (only non-empty ones)\n const nonEmptyKeys = this._items\n .map(({ key }, index) => ({ key: key.trim(), index }))\n .filter(({ key }) => key !== '');\n\n const keyCount = new Map<string, number[]>();\n nonEmptyKeys.forEach(({ key, index }) => {\n if (!keyCount.has(key)) {\n keyCount.set(key, []);\n }\n keyCount.get(key)!.push(index);\n });\n\n // Mark duplicate keys with errors\n keyCount.forEach((indices, key) => {\n if (indices.length > 1) {\n indices.forEach((index) => {\n // Only show duplicate error if there's no empty key error already\n if (!newKeyErrors[index]) {\n newKeyErrors[index] = `Duplicate key \"${key}\"`;\n }\n });\n }\n });\n\n this.keyErrors = newKeyErrors;\n return Object.keys(newKeyErrors).length === 0;\n }\n\n // Clear key errors\n clearKeyErrors(): void {\n this.keyErrors = {};\n }\n\n // Override updateValue to emit array format and validate keys\n protected updateValue(newValue: KeyValueItem[]) {\n this._items = newValue;\n\n // Clear errors and re-validate when items change\n this.clearKeyErrors();\n this.validateKeys();\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: { value: this.cleanItems(newValue) },\n bubbles: true\n })\n );\n this.requestUpdate();\n }\n\n private handleKeyChange(index: number, newKey: string) {\n const items = this.displayItems;\n const currentItem = items[index];\n\n // Clear any existing error for this key when it's modified\n if (this.keyErrors[index]) {\n const newKeyErrors = { ...this.keyErrors };\n delete newKeyErrors[index];\n this.keyErrors = newKeyErrors;\n }\n\n this.handleItemChange(index, {\n key: newKey,\n value: currentItem.value\n });\n }\n\n private handleValueChange(index: number, newValue: string) {\n const items = this.displayItems;\n const currentItem = items[index];\n\n // Clear any existing error for this key when value is modified\n if (this.keyErrors[index]) {\n const newKeyErrors = { ...this.keyErrors };\n delete newKeyErrors[index];\n this.keyErrors = newKeyErrors;\n }\n\n this.handleItemChange(index, {\n key: currentItem.key,\n value: newValue\n });\n }\n\n renderItem(item: KeyValueItem, index: number): TemplateResult {\n const canRemove = this.canRemoveItem(index);\n const keyError =\n this.showValidation && this.keyErrors[index] ? this.keyErrors[index] : '';\n\n return html`\n <div class=\"row\">\n <temba-textinput\n .value=${item.key}\n .placeholder=${this.keyPlaceholder}\n .errors=${keyError ? [keyError] : []}\n @change=${(e: any) => this.handleKeyChange(index, e.target.value)}\n ></temba-textinput>\n <temba-textinput\n .value=${item.value}\n .placeholder=${this.valuePlaceholder}\n @change=${(e: any) => this.handleValueChange(index, e.target.value)}\n ></temba-textinput>\n ${canRemove\n ? html`\n <button class=\"remove-btn\" @click=${() => this.removeItem(index)}>\n ×\n </button>\n `\n : html`<div class=\"remove-btn-spacer\"></div>`}\n </div>\n `;\n }\n\n protected getContainerClass(): string {\n return 'key-value-editor';\n }\n\n static get styles() {\n return css`\n ${super.styles}\n\n .key-value-editor {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .row {\n display: grid;\n grid-template-columns: 1fr 1fr auto;\n align-items: center;\n column-gap: 6px;\n }\n\n .remove-btn {\n width: 32px;\n height: 32px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: #f8f8f8;\n color: #666;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n }\n\n .remove-btn:hover:not(:disabled) {\n background: #f0f0f0;\n }\n\n .remove-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .remove-btn-spacer {\n width: 32px;\n height: 32px;\n }\n `;\n }\n}\n"]}
|
|
@@ -2,18 +2,17 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { css, html } from 'lit';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
5
|
-
import {
|
|
5
|
+
import { FieldElement } from './FieldElement';
|
|
6
6
|
import { getClasses } from '../utils';
|
|
7
7
|
import { Icon } from '../Icons';
|
|
8
8
|
/**
|
|
9
9
|
* MessageEditor is a composed component that combines temba-completion and temba-media-picker
|
|
10
10
|
* for editing messages with text completion and file attachments
|
|
11
11
|
*/
|
|
12
|
-
export class MessageEditor extends
|
|
12
|
+
export class MessageEditor extends FieldElement {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.name = '';
|
|
16
|
-
this.value = '';
|
|
17
16
|
this.placeholder = '';
|
|
18
17
|
this.textarea = true;
|
|
19
18
|
this.autogrow = true;
|
|
@@ -28,6 +27,7 @@ export class MessageEditor extends FormElement {
|
|
|
28
27
|
}
|
|
29
28
|
static get styles() {
|
|
30
29
|
return css `
|
|
30
|
+
${super.styles}
|
|
31
31
|
:host {
|
|
32
32
|
display: block;
|
|
33
33
|
}
|
|
@@ -292,85 +292,77 @@ export class MessageEditor extends FormElement {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
render() {
|
|
295
|
+
return this.renderField();
|
|
296
|
+
}
|
|
297
|
+
renderWidget() {
|
|
295
298
|
const hasAttachments = this.hasStaticAttachments();
|
|
296
299
|
return html `
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
.label=${this.label}
|
|
300
|
-
.helpText=${this.helpText}
|
|
301
|
-
.errors=${this.errors}
|
|
302
|
-
.widgetOnly=${this.widgetOnly}
|
|
303
|
-
>
|
|
304
|
-
<div
|
|
305
|
-
class=${getClasses({
|
|
300
|
+
<div
|
|
301
|
+
class=${getClasses({
|
|
306
302
|
'message-editor-container': true,
|
|
307
303
|
highlight: this.pendingDrop,
|
|
308
304
|
'has-attachments': hasAttachments
|
|
309
305
|
})}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
306
|
+
@dragenter=${this.handleDragEnter}
|
|
307
|
+
@dragover=${this.handleDragOver}
|
|
308
|
+
@dragleave=${this.handleDragLeave}
|
|
309
|
+
@drop=${this.handleDrop}
|
|
310
|
+
>
|
|
311
|
+
<div class="completion-wrapper">
|
|
312
|
+
<temba-completion
|
|
313
|
+
name=${this.name}
|
|
314
|
+
.value=${this.value}
|
|
315
|
+
placeholder=${this.placeholder}
|
|
316
|
+
?textarea=${this.textarea}
|
|
317
|
+
?autogrow=${this.autogrow}
|
|
318
|
+
?session=${this.session}
|
|
319
|
+
?submitOnEnter=${this.submitOnEnter}
|
|
320
|
+
?gsm=${this.gsm}
|
|
321
|
+
?disableCompletion=${this.disableCompletion}
|
|
322
|
+
maxlength=${ifDefined(this.maxLength)}
|
|
323
|
+
counter=${ifDefined(this.counter)}
|
|
324
|
+
minHeight=${ifDefined(this.minHeight)}
|
|
325
|
+
widgetOnly
|
|
326
|
+
@change=${this.handleCompletionChange}
|
|
327
|
+
></temba-completion>
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
<div class="media-wrapper ">
|
|
331
|
+
<temba-media-picker
|
|
332
|
+
.accept=${this.accept}
|
|
333
|
+
.max=${this.maxAttachments}
|
|
334
|
+
.endpoint=${this.endpoint}
|
|
335
|
+
@change=${this.handleMediaChange}
|
|
336
|
+
ignoreDrops
|
|
337
|
+
></temba-media-picker>
|
|
338
|
+
</div>
|
|
339
|
+
<temba-icon
|
|
340
|
+
class="attachment-icon"
|
|
341
|
+
name=${Icon.attachment}
|
|
342
|
+
size="1.2"
|
|
343
|
+
@click=${this.handleAttachmentIconClick}
|
|
344
|
+
></temba-icon>
|
|
345
|
+
|
|
346
|
+
<div class="drop-overlay"></div>
|
|
333
347
|
|
|
334
|
-
|
|
335
|
-
|
|
348
|
+
<!-- Hidden media picker for handling uploads when no attachments are shown -->
|
|
349
|
+
${!hasAttachments
|
|
350
|
+
? html `<temba-media-picker
|
|
351
|
+
style="display: none;"
|
|
336
352
|
.accept=${this.accept}
|
|
337
353
|
.max=${this.maxAttachments}
|
|
338
354
|
.endpoint=${this.endpoint}
|
|
339
355
|
@change=${this.handleMediaChange}
|
|
340
356
|
ignoreDrops
|
|
341
|
-
></temba-media-picker
|
|
342
|
-
</div>
|
|
343
|
-
<temba-icon
|
|
344
|
-
class="attachment-icon"
|
|
345
|
-
name=${Icon.attachment}
|
|
346
|
-
size="1.2"
|
|
347
|
-
@click=${this.handleAttachmentIconClick}
|
|
348
|
-
></temba-icon>
|
|
349
|
-
|
|
350
|
-
<div class="drop-overlay"></div>
|
|
351
|
-
|
|
352
|
-
<!-- Hidden media picker for handling uploads when no attachments are shown -->
|
|
353
|
-
${!hasAttachments
|
|
354
|
-
? html `<temba-media-picker
|
|
355
|
-
style="display: none;"
|
|
356
|
-
.accept=${this.accept}
|
|
357
|
-
.max=${this.maxAttachments}
|
|
358
|
-
.endpoint=${this.endpoint}
|
|
359
|
-
@change=${this.handleMediaChange}
|
|
360
|
-
ignoreDrops
|
|
361
|
-
></temba-media-picker>`
|
|
357
|
+
></temba-media-picker>`
|
|
362
358
|
: ''}
|
|
363
|
-
|
|
364
|
-
</temba-field>
|
|
359
|
+
</div>
|
|
365
360
|
`;
|
|
366
361
|
}
|
|
367
362
|
}
|
|
368
363
|
__decorate([
|
|
369
364
|
property({ type: String })
|
|
370
365
|
], MessageEditor.prototype, "name", void 0);
|
|
371
|
-
__decorate([
|
|
372
|
-
property({ type: String })
|
|
373
|
-
], MessageEditor.prototype, "value", void 0);
|
|
374
366
|
__decorate([
|
|
375
367
|
property({ type: String })
|
|
376
368
|
], MessageEditor.prototype, "placeholder", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageEditor.js","sourceRoot":"","sources":["../../../src/form/MessageEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { ifDefined } from 'lit-html/directives/if-defined.js';\nimport { FormElement } from './FormElement';\nimport { Completion } from './Completion';\nimport { MediaPicker } from './MediaPicker';\nimport { Attachment } from '../interfaces';\nimport { getClasses } from '../utils';\nimport { Icon } from '../Icons';\n\n/**\n * MessageEditor is a composed component that combines temba-completion and temba-media-picker\n * for editing messages with text completion and file attachments\n */\nexport class MessageEditor extends FormElement {\n static get styles() {\n return css`\n :host {\n display: block;\n }\n\n .message-editor-container {\n border: 1px solid var(--color-widget-border);\n border-radius: var(--curvature-widget);\n background: #fff;\n position: relative;\n transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;\n }\n\n .message-editor-container:focus-within {\n border-color: var(--color-focus);\n box-shadow: var(--widget-box-shadow-focused);\n }\n\n .message-editor-container.highlight {\n border-color: rgba(156, 222, 106, 0.88);\n }\n\n /* Hide the completion field border since we draw our own */\n .message-editor-container temba-completion::part(field) {\n border: none;\n box-shadow: none;\n border-radius: 0;\n }\n\n .message-editor-container temba-completion {\n --widget-box-shadow: none;\n --widget-box-shadow-focused: none;\n --widget-box-shadow-focused: none;\n --color-widget-border: transparent;\n --color-focus: transparent;\n }\n\n .completion-wrapper {\n }\n\n .media-wrapper {\n padding: 4px 8px;\n background: rgba(0, 0, 0, 0.03);\n border-top: 1px solid var(--color-widget-border);\n border-radius: 0 0 var(--curvature-widget) var(--curvature-widget);\n box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.05);\n margin-top: 3px;\n display: none;\n }\n .has-attachments .media-wrapper {\n display: flex;\n }\n\n /* Override media picker styles to integrate better */\n .media-wrapper temba-media-picker {\n --color-widget-border: transparent;\n }\n\n .media-wrapper .attachments-list {\n padding: 0.2em 0;\n }\n\n .drop-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(210, 243, 184, 0.5);\n border-radius: var(--curvature-widget);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s ease-in-out;\n z-index: 10;\n }\n\n .message-editor-container.highlight .drop-overlay {\n opacity: 1;\n }\n\n .drop-message {\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 12px 24px;\n border-radius: var(--curvature);\n font-weight: 500;\n }\n\n .attachment-icon {\n position: absolute;\n bottom: 4px;\n right: 4px;\n color: var(--color-text-dark);\n cursor: pointer;\n padding: 6px;\n border-radius: var(--curvature);\n transition: background-color 0.2s ease-in-out;\n display: block;\n }\n\n .has-attachments .attachment-icon {\n display: none;\n }\n\n .attachment-icon:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n `;\n }\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Boolean })\n textarea = true;\n\n @property({ type: Boolean })\n autogrow = true;\n\n @property({ type: Number })\n minHeight = 60;\n\n @property({ type: Number })\n maxLength: number;\n\n @property({ type: Boolean })\n session: boolean;\n\n @property({ type: Boolean })\n submitOnEnter = false;\n\n @property({ type: Boolean })\n gsm: boolean;\n\n @property({ type: Boolean })\n disableCompletion: boolean;\n\n @property({ type: String })\n counter: string;\n\n @property({ type: Array })\n attachments: (Attachment | string)[] = [];\n\n @property({ type: String })\n accept = '';\n\n @property({ type: Number, attribute: 'max-attachments' })\n maxAttachments = 3;\n\n @property({ type: String })\n endpoint = '';\n\n @property({ type: Boolean, attribute: false })\n pendingDrop = false;\n\n @property({ type: Boolean, attribute: false })\n uploading = false;\n\n private completionElement: Completion;\n private mediaPickerElement: MediaPicker;\n\n public firstUpdated(changes: Map<string, any>) {\n super.firstUpdated(changes);\n\n this.completionElement = this.shadowRoot.querySelector(\n 'temba-completion'\n ) as Completion;\n\n // Get the visible media picker (either in media-wrapper or the hidden one)\n this.mediaPickerElement = this.shadowRoot.querySelector(\n 'temba-media-picker'\n ) as MediaPicker;\n\n // Set up proper attachment filtering and parsing\n this.parseAndFilterAttachments();\n }\n\n /**\n * Parse attachments and filter out runtime attachments for media picker\n */\n private parseAndFilterAttachments() {\n if (!this.attachments) return;\n\n // Filter out runtime attachments (those without '/' in content type)\n const staticAttachments = this.attachments.filter((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return contentType.includes('/');\n }\n return true;\n });\n\n // Convert string attachments to Attachment objects for media picker\n const mediaAttachments = staticAttachments.map((attachment) => {\n if (typeof attachment === 'string') {\n // split into content type and URL\n // e.g. \"image/jpeg:http://example.com/image.jpg\"\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const url = attachment.substring(colonIndex + 1);\n return {\n content_type: contentType,\n url: url,\n filename: this.getFilenameFromUrl(url),\n size: 0\n } as Attachment;\n }\n return attachment;\n });\n\n if (this.mediaPickerElement) {\n this.mediaPickerElement.attachments = mediaAttachments;\n }\n }\n\n /**\n * Check if there are any static attachments (excluding runtime attachments)\n */\n private hasStaticAttachments(): boolean {\n if (!this.attachments || this.attachments.length === 0) return false;\n\n return this.attachments.some((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return contentType.includes('/');\n }\n return true;\n });\n }\n\n private getFilenameFromUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n return pathname.substring(pathname.lastIndexOf('/') + 1) || 'attachment';\n } catch {\n return 'attachment';\n }\n }\n\n private handleCompletionChange(event: Event) {\n event.stopPropagation();\n const completion = event.target as Completion;\n this.value = completion.value;\n this.fireEvent('change');\n }\n\n private handleMediaChange(event: Event) {\n event.stopPropagation();\n const mediaPicker = event.target as MediaPicker;\n // Convert media picker attachments back to the format expected by the form\n const formattedAttachments = mediaPicker.attachments.map((attachment) => {\n return `${attachment.content_type}:${attachment.url}`;\n });\n\n // Merge with any runtime attachments that were filtered out\n const runtimeAttachments = (this.attachments || []).filter((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return !contentType.includes('/');\n }\n return false;\n }) as string[];\n\n this.attachments = [...runtimeAttachments, ...formattedAttachments];\n this.fireEvent('change');\n }\n\n private handleDragEnter(evt: DragEvent): void {\n this.highlight(evt);\n }\n\n private handleDragOver(evt: DragEvent): void {\n this.highlight(evt);\n }\n\n private handleDragLeave(evt: DragEvent): void {\n this.unhighlight(evt);\n }\n\n private handleDrop(evt: DragEvent): void {\n this.unhighlight(evt);\n\n // Forward to media picker\n if (this.mediaPickerElement) {\n const files = [...evt.dataTransfer.files];\n this.mediaPickerElement.uploadFiles(files);\n }\n }\n\n private handleAttachmentIconClick(): void {\n // Trigger the file picker on the media picker\n if (this.mediaPickerElement) {\n const uploadInput = this.mediaPickerElement.shadowRoot.querySelector(\n '#upload-input'\n ) as HTMLInputElement;\n if (uploadInput) {\n uploadInput.click();\n }\n }\n }\n\n private highlight(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n\n // Always allow highlight for testing purposes, but in real usage check media picker\n this.pendingDrop = true;\n }\n\n private unhighlight(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n this.pendingDrop = false;\n }\n\n public updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('attachments')) {\n // Re-query media picker since the DOM structure may have changed\n this.mediaPickerElement = this.shadowRoot.querySelector(\n 'temba-media-picker'\n ) as MediaPicker;\n }\n\n if (changedProperties.has('uploading')) {\n this.dispatchEvent(\n new CustomEvent('loading', {\n detail: { loading: this.uploading }\n })\n );\n }\n }\n\n public focus() {\n super.focus();\n if (this.completionElement) {\n this.completionElement.focus();\n }\n }\n\n public click() {\n super.click();\n if (this.completionElement) {\n this.completionElement.click();\n }\n }\n\n public render(): TemplateResult {\n const hasAttachments = this.hasStaticAttachments();\n\n return html`\n <temba-field\n name=${this.name}\n .label=${this.label}\n .helpText=${this.helpText}\n .errors=${this.errors}\n .widgetOnly=${this.widgetOnly}\n >\n <div\n class=${getClasses({\n 'message-editor-container': true,\n highlight: this.pendingDrop,\n 'has-attachments': hasAttachments\n })}\n @dragenter=${this.handleDragEnter}\n @dragover=${this.handleDragOver}\n @dragleave=${this.handleDragLeave}\n @drop=${this.handleDrop}\n >\n <div class=\"completion-wrapper\">\n <temba-completion\n name=${this.name}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?textarea=${this.textarea}\n ?autogrow=${this.autogrow}\n ?session=${this.session}\n ?submitOnEnter=${this.submitOnEnter}\n ?gsm=${this.gsm}\n ?disableCompletion=${this.disableCompletion}\n maxlength=${ifDefined(this.maxLength)}\n counter=${ifDefined(this.counter)}\n minHeight=${ifDefined(this.minHeight)}\n widgetOnly\n @change=${this.handleCompletionChange}\n ></temba-completion>\n </div>\n\n <div class=\"media-wrapper \">\n <temba-media-picker\n .accept=${this.accept}\n .max=${this.maxAttachments}\n .endpoint=${this.endpoint}\n @change=${this.handleMediaChange}\n ignoreDrops\n ></temba-media-picker>\n </div>\n <temba-icon\n class=\"attachment-icon\"\n name=${Icon.attachment}\n size=\"1.2\"\n @click=${this.handleAttachmentIconClick}\n ></temba-icon>\n\n <div class=\"drop-overlay\"></div>\n\n <!-- Hidden media picker for handling uploads when no attachments are shown -->\n ${!hasAttachments\n ? html`<temba-media-picker\n style=\"display: none;\"\n .accept=${this.accept}\n .max=${this.maxAttachments}\n .endpoint=${this.endpoint}\n @change=${this.handleMediaChange}\n ignoreDrops\n ></temba-media-picker>`\n : ''}\n </div>\n </temba-field>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MessageEditor.js","sourceRoot":"","sources":["../../../src/form/MessageEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { TemplateResult, css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { ifDefined } from 'lit-html/directives/if-defined.js';\nimport { FieldElement } from './FieldElement';\nimport { Completion } from './Completion';\nimport { MediaPicker } from './MediaPicker';\nimport { Attachment } from '../interfaces';\nimport { getClasses } from '../utils';\nimport { Icon } from '../Icons';\n\n/**\n * MessageEditor is a composed component that combines temba-completion and temba-media-picker\n * for editing messages with text completion and file attachments\n */\nexport class MessageEditor extends FieldElement {\n static get styles() {\n return css`\n ${super.styles}\n :host {\n display: block;\n }\n\n .message-editor-container {\n border: 1px solid var(--color-widget-border);\n border-radius: var(--curvature-widget);\n background: #fff;\n position: relative;\n transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;\n }\n\n .message-editor-container:focus-within {\n border-color: var(--color-focus);\n box-shadow: var(--widget-box-shadow-focused);\n }\n\n .message-editor-container.highlight {\n border-color: rgba(156, 222, 106, 0.88);\n }\n\n /* Hide the completion field border since we draw our own */\n .message-editor-container temba-completion::part(field) {\n border: none;\n box-shadow: none;\n border-radius: 0;\n }\n\n .message-editor-container temba-completion {\n --widget-box-shadow: none;\n --widget-box-shadow-focused: none;\n --widget-box-shadow-focused: none;\n --color-widget-border: transparent;\n --color-focus: transparent;\n }\n\n .completion-wrapper {\n }\n\n .media-wrapper {\n padding: 4px 8px;\n background: rgba(0, 0, 0, 0.03);\n border-top: 1px solid var(--color-widget-border);\n border-radius: 0 0 var(--curvature-widget) var(--curvature-widget);\n box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.05);\n margin-top: 3px;\n display: none;\n }\n .has-attachments .media-wrapper {\n display: flex;\n }\n\n /* Override media picker styles to integrate better */\n .media-wrapper temba-media-picker {\n --color-widget-border: transparent;\n }\n\n .media-wrapper .attachments-list {\n padding: 0.2em 0;\n }\n\n .drop-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(210, 243, 184, 0.5);\n border-radius: var(--curvature-widget);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s ease-in-out;\n z-index: 10;\n }\n\n .message-editor-container.highlight .drop-overlay {\n opacity: 1;\n }\n\n .drop-message {\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 12px 24px;\n border-radius: var(--curvature);\n font-weight: 500;\n }\n\n .attachment-icon {\n position: absolute;\n bottom: 4px;\n right: 4px;\n color: var(--color-text-dark);\n cursor: pointer;\n padding: 6px;\n border-radius: var(--curvature);\n transition: background-color 0.2s ease-in-out;\n display: block;\n }\n\n .has-attachments .attachment-icon {\n display: none;\n }\n\n .attachment-icon:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n `;\n }\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Boolean })\n textarea = true;\n\n @property({ type: Boolean })\n autogrow = true;\n\n @property({ type: Number })\n minHeight = 60;\n\n @property({ type: Number })\n maxLength: number;\n\n @property({ type: Boolean })\n session: boolean;\n\n @property({ type: Boolean })\n submitOnEnter = false;\n\n @property({ type: Boolean })\n gsm: boolean;\n\n @property({ type: Boolean })\n disableCompletion: boolean;\n\n @property({ type: String })\n counter: string;\n\n @property({ type: Array })\n attachments: (Attachment | string)[] = [];\n\n @property({ type: String })\n accept = '';\n\n @property({ type: Number, attribute: 'max-attachments' })\n maxAttachments = 3;\n\n @property({ type: String })\n endpoint = '';\n\n @property({ type: Boolean, attribute: false })\n pendingDrop = false;\n\n @property({ type: Boolean, attribute: false })\n uploading = false;\n\n private completionElement: Completion;\n private mediaPickerElement: MediaPicker;\n\n public firstUpdated(changes: Map<string, any>) {\n super.firstUpdated(changes);\n\n this.completionElement = this.shadowRoot.querySelector(\n 'temba-completion'\n ) as Completion;\n\n // Get the visible media picker (either in media-wrapper or the hidden one)\n this.mediaPickerElement = this.shadowRoot.querySelector(\n 'temba-media-picker'\n ) as MediaPicker;\n\n // Set up proper attachment filtering and parsing\n this.parseAndFilterAttachments();\n }\n\n /**\n * Parse attachments and filter out runtime attachments for media picker\n */\n private parseAndFilterAttachments() {\n if (!this.attachments) return;\n\n // Filter out runtime attachments (those without '/' in content type)\n const staticAttachments = this.attachments.filter((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return contentType.includes('/');\n }\n return true;\n });\n\n // Convert string attachments to Attachment objects for media picker\n const mediaAttachments = staticAttachments.map((attachment) => {\n if (typeof attachment === 'string') {\n // split into content type and URL\n // e.g. \"image/jpeg:http://example.com/image.jpg\"\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const url = attachment.substring(colonIndex + 1);\n return {\n content_type: contentType,\n url: url,\n filename: this.getFilenameFromUrl(url),\n size: 0\n } as Attachment;\n }\n return attachment;\n });\n\n if (this.mediaPickerElement) {\n this.mediaPickerElement.attachments = mediaAttachments;\n }\n }\n\n /**\n * Check if there are any static attachments (excluding runtime attachments)\n */\n private hasStaticAttachments(): boolean {\n if (!this.attachments || this.attachments.length === 0) return false;\n\n return this.attachments.some((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return contentType.includes('/');\n }\n return true;\n });\n }\n\n private getFilenameFromUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n return pathname.substring(pathname.lastIndexOf('/') + 1) || 'attachment';\n } catch {\n return 'attachment';\n }\n }\n\n private handleCompletionChange(event: Event) {\n event.stopPropagation();\n const completion = event.target as Completion;\n this.value = completion.value;\n this.fireEvent('change');\n }\n\n private handleMediaChange(event: Event) {\n event.stopPropagation();\n const mediaPicker = event.target as MediaPicker;\n // Convert media picker attachments back to the format expected by the form\n const formattedAttachments = mediaPicker.attachments.map((attachment) => {\n return `${attachment.content_type}:${attachment.url}`;\n });\n\n // Merge with any runtime attachments that were filtered out\n const runtimeAttachments = (this.attachments || []).filter((attachment) => {\n if (typeof attachment === 'string') {\n const [contentType] = attachment.split(':');\n return !contentType.includes('/');\n }\n return false;\n }) as string[];\n\n this.attachments = [...runtimeAttachments, ...formattedAttachments];\n this.fireEvent('change');\n }\n\n private handleDragEnter(evt: DragEvent): void {\n this.highlight(evt);\n }\n\n private handleDragOver(evt: DragEvent): void {\n this.highlight(evt);\n }\n\n private handleDragLeave(evt: DragEvent): void {\n this.unhighlight(evt);\n }\n\n private handleDrop(evt: DragEvent): void {\n this.unhighlight(evt);\n\n // Forward to media picker\n if (this.mediaPickerElement) {\n const files = [...evt.dataTransfer.files];\n this.mediaPickerElement.uploadFiles(files);\n }\n }\n\n private handleAttachmentIconClick(): void {\n // Trigger the file picker on the media picker\n if (this.mediaPickerElement) {\n const uploadInput = this.mediaPickerElement.shadowRoot.querySelector(\n '#upload-input'\n ) as HTMLInputElement;\n if (uploadInput) {\n uploadInput.click();\n }\n }\n }\n\n private highlight(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n\n // Always allow highlight for testing purposes, but in real usage check media picker\n this.pendingDrop = true;\n }\n\n private unhighlight(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n this.pendingDrop = false;\n }\n\n public updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('attachments')) {\n // Re-query media picker since the DOM structure may have changed\n this.mediaPickerElement = this.shadowRoot.querySelector(\n 'temba-media-picker'\n ) as MediaPicker;\n }\n\n if (changedProperties.has('uploading')) {\n this.dispatchEvent(\n new CustomEvent('loading', {\n detail: { loading: this.uploading }\n })\n );\n }\n }\n\n public focus() {\n super.focus();\n if (this.completionElement) {\n this.completionElement.focus();\n }\n }\n\n public click() {\n super.click();\n if (this.completionElement) {\n this.completionElement.click();\n }\n }\n\n public render(): TemplateResult {\n return this.renderField();\n }\n\n protected renderWidget(): TemplateResult {\n const hasAttachments = this.hasStaticAttachments();\n\n return html`\n <div\n class=${getClasses({\n 'message-editor-container': true,\n highlight: this.pendingDrop,\n 'has-attachments': hasAttachments\n })}\n @dragenter=${this.handleDragEnter}\n @dragover=${this.handleDragOver}\n @dragleave=${this.handleDragLeave}\n @drop=${this.handleDrop}\n >\n <div class=\"completion-wrapper\">\n <temba-completion\n name=${this.name}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?textarea=${this.textarea}\n ?autogrow=${this.autogrow}\n ?session=${this.session}\n ?submitOnEnter=${this.submitOnEnter}\n ?gsm=${this.gsm}\n ?disableCompletion=${this.disableCompletion}\n maxlength=${ifDefined(this.maxLength)}\n counter=${ifDefined(this.counter)}\n minHeight=${ifDefined(this.minHeight)}\n widgetOnly\n @change=${this.handleCompletionChange}\n ></temba-completion>\n </div>\n\n <div class=\"media-wrapper \">\n <temba-media-picker\n .accept=${this.accept}\n .max=${this.maxAttachments}\n .endpoint=${this.endpoint}\n @change=${this.handleMediaChange}\n ignoreDrops\n ></temba-media-picker>\n </div>\n <temba-icon\n class=\"attachment-icon\"\n name=${Icon.attachment}\n size=\"1.2\"\n @click=${this.handleAttachmentIconClick}\n ></temba-icon>\n\n <div class=\"drop-overlay\"></div>\n\n <!-- Hidden media picker for handling uploads when no attachments are shown -->\n ${!hasAttachments\n ? html`<temba-media-picker\n style=\"display: none;\"\n .accept=${this.accept}\n .max=${this.maxAttachments}\n .endpoint=${this.endpoint}\n @change=${this.handleMediaChange}\n ignoreDrops\n ></temba-media-picker>`\n : ''}\n </div>\n `;\n }\n}\n"]}
|
|
@@ -2,9 +2,9 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { css, html } from 'lit';
|
|
3
3
|
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
4
4
|
import { property } from 'lit/decorators.js';
|
|
5
|
-
import {
|
|
5
|
+
import { FieldElement } from './FieldElement';
|
|
6
6
|
import { getClasses } from '../utils';
|
|
7
|
-
export class TembaSlider extends
|
|
7
|
+
export class TembaSlider extends FieldElement {
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments);
|
|
10
10
|
this.range = false;
|
|
@@ -128,7 +128,7 @@ export class TembaSlider extends FormElement {
|
|
|
128
128
|
this.circleX = pctAsPixels + (pre ? pre.offsetWidth : 0);
|
|
129
129
|
this.requestUpdate();
|
|
130
130
|
}
|
|
131
|
-
|
|
131
|
+
renderWidget() {
|
|
132
132
|
return html ` <div class="${getClasses({ grabbed: this.grabbed })}">
|
|
133
133
|
<div
|
|
134
134
|
style=${styleMap({ left: this.circleX + 'px' })}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TembaSlider.js","sourceRoot":"","sources":["../../../src/form/TembaSlider.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"TembaSlider.js","sourceRoot":"","sources":["../../../src/form/TembaSlider.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,WAAY,SAAQ,YAAY;IAA7C;;QA6DE,UAAK,GAAG,KAAK,CAAC;QAGd,QAAG,GAAG,CAAC,CAAC;QAGR,QAAG,GAAG,GAAG,CAAC;QAEV,YAAO,GAAG,CAAC,CAAC;QACZ,YAAO,GAAG,KAAK,CAAC;IAkFlB,CAAC;IAvJC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuDT,CAAC;IACJ,CAAC;IAcM,YAAY,CAAC,OAAyB;QAC3C,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IAEM,OAAO,CAAC,iBAAmC;QAChD,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAEM,WAAW,CAAC,GAAe;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAmB,CAAC;QACxE,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC;QAErC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAClC,MAAM,UAAU,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAC1C,IAAI,CAAC,KAAK;YACR,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC;IAEM,eAAe,CAAC,GAAe;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAEM,eAAe,CAAC,GAAe;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEM,aAAa,CAAC,GAAe;QAClC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAChE,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;IAEM,YAAY;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAmB,CAAC;QACxE,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM,CAAmB,CAAC;QACpE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAClC,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,CAAC;aAAM,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,MAAM,CAAC;QACzB,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACxC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;QAE5C,IAAI,CAAC,OAAO,GAAG,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEM,YAAY;QACjB,OAAO,IAAI,CAAA,gBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;;gBAEpD,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;;qBAElC,IAAI,CAAC,eAAe;;;UAG/B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,oBAAoB,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI;wCAC9B,IAAI,CAAC,eAAe;UAClD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,qBAAqB,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI;;WAE5D,CAAC;IACV,CAAC;CACF;AA3FC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;0CACd;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACnB;AAGR;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCACjB","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { styleMap } from 'lit-html/directives/style-map.js';\nimport { property } from 'lit/decorators.js';\nimport { FieldElement } from './FieldElement';\nimport { getClasses } from '../utils';\n\nexport class TembaSlider extends FieldElement {\n static get styles() {\n return css`\n :host {\n display: block;\n }\n\n .track {\n height: 2px;\n border-top: 0.5em solid #fff;\n border-bottom: 0.5em solid #fff;\n background: #ddd;\n flex-grow: 1;\n }\n\n .circle {\n margin-bottom: -1.05em;\n margin-left: -0.5em;\n width: 0.75em;\n height: 0.75em;\n border: 2px solid #999;\n border-radius: 999px;\n position: relative;\n background: #fff;\n box-shadow: 0 0 0 4px rgb(255, 255, 255);\n transition: transform 200ms ease-in-out;\n }\n\n .grabbed .track {\n cursor: pointer;\n }\n\n :hover .circle {\n border-color: #777;\n cursor: pointer;\n }\n\n .grabbed .circle {\n border-color: var(--color-primary-dark);\n background: #fff;\n }\n\n .grabbed .circle {\n transform: scale(1.2);\n }\n\n .wrapper {\n display: flex;\n align-items: center;\n }\n\n .pre,\n .post {\n font-size: 0.9em;\n color: #999;\n padding: 0em 1em;\n }\n `;\n }\n\n @property({ type: Boolean })\n range = false;\n\n @property({ type: Number })\n min = 0;\n\n @property({ type: Number })\n max = 100;\n\n circleX = 0;\n grabbed = false;\n\n public firstUpdated(changes: Map<string, any>) {\n super.firstUpdated(changes);\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleMouseUp = this.handleMouseUp.bind(this);\n }\n\n public updated(changedProperties: Map<string, any>): void {\n if (changedProperties.has('value')) {\n this.updateCircle();\n }\n }\n\n public updateValue(evt: MouseEvent) {\n const track = this.shadowRoot.querySelector('.track') as HTMLDivElement;\n const left = evt.pageX - track.offsetLeft;\n const pct = left / track.offsetWidth;\n\n const range = this.max - this.min;\n const pctAsValue = range * pct + this.min;\n this.value =\n '' + Math.max(this.min, Math.min(Math.round(pctAsValue), this.max));\n }\n\n public handleMouseMove(evt: MouseEvent) {\n if (this.grabbed) {\n this.updateValue(evt);\n }\n }\n\n public handleTrackDown(evt: MouseEvent) {\n this.grabbed = true;\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n document.querySelector('html').classList.add('dragging');\n this.updateValue(evt);\n this.requestUpdate();\n }\n\n public handleMouseUp(evt: MouseEvent) {\n this.grabbed = false;\n this.updateValue(evt);\n this.requestUpdate();\n\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n document.querySelector('html').classList.remove('dragging');\n }\n\n public updateCircle() {\n const track = this.shadowRoot.querySelector('.track') as HTMLDivElement;\n const pre = this.shadowRoot.querySelector('.pre') as HTMLDivElement;\n const range = this.max - this.min;\n let cValue = parseInt(this.value);\n if (!cValue || cValue < this.min) {\n cValue = this.min;\n } else if (cValue > this.max) {\n cValue = this.max;\n }\n this.value = '' + cValue;\n const pct = (cValue - this.min) / range;\n const pctAsPixels = track.offsetWidth * pct;\n\n this.circleX = pctAsPixels + (pre ? pre.offsetWidth : 0);\n this.requestUpdate();\n }\n\n public renderWidget(): TemplateResult {\n return html` <div class=\"${getClasses({ grabbed: this.grabbed })}\">\n <div\n style=${styleMap({ left: this.circleX + 'px' })}\n class=\"circle\"\n @mousedown=${this.handleTrackDown}\n ></div>\n <div class=\"wrapper\">\n ${this.range ? html`<div class=\"pre\">${this.min}</div>` : null}\n <div class=\"track\" @mousedown=${this.handleTrackDown}></div>\n ${this.range ? html`<div class=\"post\">${this.max}</div>` : null}\n </div>\n </div>`;\n }\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
|
-
import { FormElement } from './FormElement';
|
|
4
3
|
import { html, css, LitElement } from 'lit';
|
|
5
4
|
import { CustomEventType } from '../interfaces';
|
|
6
5
|
import { getClasses } from '../utils';
|
|
7
|
-
|
|
6
|
+
import { FieldElement } from './FieldElement';
|
|
7
|
+
export class TemplateEditor extends FieldElement {
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments);
|
|
10
10
|
this.pickersLoading = {};
|
|
@@ -373,7 +373,7 @@ export class TemplateEditor extends FormElement {
|
|
|
373
373
|
<div class="buttons">${buttons}</div>
|
|
374
374
|
</div>`;
|
|
375
375
|
}
|
|
376
|
-
|
|
376
|
+
renderWidget() {
|
|
377
377
|
let content = null;
|
|
378
378
|
if (this.translation) {
|
|
379
379
|
content = this.renderComponents(this.translation.components);
|