@nyaruka/temba-components 0.129.8 → 0.129.10
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 +37 -3
- package/demo/data/flows/sample-flow.json +186 -96
- package/demo/test-colorpicker.html +30 -0
- package/dist/temba-components.js +1126 -1111
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/excellent/helpers.js +2 -2
- package/out-tsc/src/excellent/helpers.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +25 -7
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +11 -1
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +133 -290
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +40 -0
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/call_llm.js +56 -3
- package/out-tsc/src/flow/actions/call_llm.js.map +1 -1
- package/out-tsc/src/flow/actions/call_webhook.js +1 -1
- package/out-tsc/src/flow/actions/call_webhook.js.map +1 -1
- package/out-tsc/src/flow/actions/open_ticket.js +65 -3
- package/out-tsc/src/flow/actions/open_ticket.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +75 -0
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/config.js +4 -0
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +227 -0
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_ticket.js +18 -0
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js +27 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +0 -65
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +63 -117
- 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} +81 -53
- package/out-tsc/src/form/FieldElement.js.map +1 -0
- package/out-tsc/src/form/FieldRenderer.js +306 -0
- package/out-tsc/src/form/FieldRenderer.js.map +1 -0
- 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 +23 -27
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +57 -35
- 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 +62 -44
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/live/ContactFieldEditor.js.map +1 -1
- package/out-tsc/src/markdown.js +13 -11
- package/out-tsc/src/markdown.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/ActionHelper.js +2 -0
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +148 -0
- package/out-tsc/test/NodeHelper.js.map +1 -0
- package/out-tsc/test/actions/call_llm.test.js +103 -0
- package/out-tsc/test/actions/call_llm.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js +532 -0
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +150 -0
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +150 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_response.test.js +171 -0
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -0
- package/out-tsc/test/temba-add-input-labels.test.js +70 -0
- package/out-tsc/test/temba-add-input-labels.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-field-renderer.test.js +296 -0
- package/out-tsc/test/temba-field-renderer.test.js.map +1 -0
- 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-markdown.test.js +1 -1
- package/out-tsc/test/temba-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +400 -0
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +6 -3
- package/out-tsc/test/temba-select.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/out-tsc/test/temba-webchat.test.js +1 -1
- package/out-tsc/test/temba-webchat.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/call_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/actions/call_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/render/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/render/translation-task.png +0 -0
- package/screenshots/truth/actions/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/multiple-recipients.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-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/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/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/screenshots/truth/omnibox/selected.png +0 -0
- package/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/search-enabled.png +0 -0
- package/src/events.ts +12 -6
- package/src/excellent/helpers.ts +2 -2
- package/src/flow/CanvasNode.ts +22 -1
- package/src/flow/Editor.ts +12 -1
- package/src/flow/NodeEditor.ts +186 -374
- package/src/flow/actions/add_input_labels.ts +45 -0
- package/src/flow/actions/call_llm.ts +57 -3
- package/src/flow/actions/call_webhook.ts +1 -1
- package/src/flow/actions/open_ticket.ts +74 -3
- package/src/flow/actions/set_run_result.ts +83 -0
- package/src/flow/config.ts +4 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +277 -0
- package/src/flow/nodes/split_by_ticket.ts +19 -0
- package/src/flow/nodes/wait_for_response.ts +28 -1
- package/src/flow/types.ts +26 -127
- package/src/form/ArrayEditor.ts +79 -139
- 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} +108 -55
- package/src/form/FieldRenderer.ts +466 -0
- 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 +26 -29
- package/src/form/select/Select.ts +63 -37
- package/src/form/select/UserSelect.ts +10 -11
- package/src/form/select/WorkspaceSelect.ts +9 -10
- package/src/live/ContactChat.ts +62 -47
- package/src/live/ContactFieldEditor.ts +2 -2
- package/src/markdown.ts +19 -11
- package/src/store/flow-definition.d.ts +5 -2
- package/static/api/labels.json +31 -0
- package/static/api/topics.json +24 -9
- package/static/api/users.json +35 -16
- package/static/css/temba-components.css +3 -3
- package/stress-test.js +18 -13
- package/temba-modules.ts +3 -2
- package/test/ActionHelper.ts +2 -0
- package/test/NodeHelper.ts +184 -0
- package/test/actions/call_llm.test.ts +137 -0
- package/test/nodes/README.md +78 -0
- package/test/nodes/split_by_llm_categorize.test.ts +698 -0
- package/test/nodes/split_by_random.test.ts +177 -0
- package/test/nodes/wait_for_digits.test.ts +176 -0
- package/test/nodes/wait_for_response.test.ts +206 -0
- package/test/temba-add-input-labels.test.ts +87 -0
- package/test/temba-checkbox.test.ts +26 -0
- package/test/temba-field-renderer.test.ts +482 -0
- package/test/temba-integration-markdown.test.ts +2 -4
- package/test/temba-markdown.test.ts +1 -1
- package/test/temba-node-editor.test.ts +496 -0
- package/test/temba-select.test.ts +6 -6
- package/test/temba-slider.test.ts +0 -1
- package/test/temba-webchat.test.ts +1 -1
- package/test-assets/contacts/history.json +7 -20
- package/test-assets/select/llms.json +18 -0
- package/web-dev-mock.mjs +96 -6
- package/web-dev-server.config.mjs +29 -7
- 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/temba-formfield.test.js +0 -94
- package/out-tsc/test/temba-formfield.test.js.map +0 -1
- package/src/form/FormElement.ts +0 -69
- package/test/temba-flow-editor.test.ts.backup +0 -563
- package/test/temba-formfield.test.ts +0 -121
- package/test/temba-utils-index.test.ts.backup +0 -1737
package/src/form/ColorPicker.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { html, css, PropertyValueMap } from 'lit';
|
|
2
|
-
import {
|
|
2
|
+
import { FieldElement } from './FieldElement';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { getClasses, hslToHex } from '../utils';
|
|
5
5
|
import { TextInput } from './TextInput';
|
|
6
6
|
|
|
7
|
-
export class ColorPicker extends
|
|
7
|
+
export class ColorPicker extends FieldElement {
|
|
8
8
|
@property({ type: Boolean })
|
|
9
9
|
expanded = false;
|
|
10
10
|
|
|
@@ -24,6 +24,8 @@ export class ColorPicker extends FormElement {
|
|
|
24
24
|
|
|
25
25
|
static get styles() {
|
|
26
26
|
return css`
|
|
27
|
+
${super.styles}
|
|
28
|
+
|
|
27
29
|
:host {
|
|
28
30
|
color: var(--color-text);
|
|
29
31
|
display: inline-block;
|
|
@@ -38,11 +40,6 @@ export class ColorPicker extends FormElement {
|
|
|
38
40
|
width: 5em;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
temba-field {
|
|
42
|
-
display: block;
|
|
43
|
-
width: 100%;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
43
|
.wrapper {
|
|
47
44
|
border: 1px solid var(--color-widget-border);
|
|
48
45
|
padding: calc(var(--curvature) / 2);
|
|
@@ -221,46 +218,37 @@ export class ColorPicker extends FormElement {
|
|
|
221
218
|
return value;
|
|
222
219
|
}
|
|
223
220
|
|
|
224
|
-
|
|
221
|
+
protected renderWidget() {
|
|
225
222
|
return html`
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
class=${getClasses({
|
|
239
|
-
preview: true,
|
|
240
|
-
selecting: this.selecting
|
|
241
|
-
})}
|
|
242
|
-
style="color:${this.labelColor};background:${this.previewColor}"
|
|
243
|
-
@click=${this.handlePreviewClick}
|
|
244
|
-
>
|
|
245
|
-
${this.label}
|
|
246
|
-
</div>
|
|
247
|
-
<div
|
|
248
|
-
class="color-picker"
|
|
249
|
-
tabindex="0"
|
|
250
|
-
@blur=${this.handleBlur}
|
|
251
|
-
@mousemove=${this.handleMouseMove}
|
|
252
|
-
@mouseout=${this.handleMouseOut}
|
|
253
|
-
@click=${this.handleColorClick}
|
|
254
|
-
></div>
|
|
223
|
+
<div style="display:flex" tabindex="0">
|
|
224
|
+
<div class=${getClasses({ wrapper: true, expanded: this.expanded })}>
|
|
225
|
+
<div class=${getClasses({ 'picker-wrapper': true })}>
|
|
226
|
+
<div
|
|
227
|
+
class=${getClasses({
|
|
228
|
+
preview: true,
|
|
229
|
+
selecting: this.selecting
|
|
230
|
+
})}
|
|
231
|
+
style="color:${this.labelColor};background:${this.previewColor}"
|
|
232
|
+
@click=${this.handlePreviewClick}
|
|
233
|
+
>
|
|
234
|
+
${this.label}
|
|
255
235
|
</div>
|
|
256
|
-
<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
236
|
+
<div
|
|
237
|
+
class="color-picker"
|
|
238
|
+
tabindex="0"
|
|
239
|
+
@blur=${this.handleBlur}
|
|
240
|
+
@mousemove=${this.handleMouseMove}
|
|
241
|
+
@mouseout=${this.handleMouseOut}
|
|
242
|
+
@click=${this.handleColorClick}
|
|
243
|
+
></div>
|
|
261
244
|
</div>
|
|
245
|
+
<temba-textinput
|
|
246
|
+
value=${this.hex}
|
|
247
|
+
@input=${this.handleHexInput}
|
|
248
|
+
placeholder="#000000"
|
|
249
|
+
></temba-textinput>
|
|
262
250
|
</div>
|
|
263
|
-
</
|
|
251
|
+
</div>
|
|
264
252
|
`;
|
|
265
253
|
}
|
|
266
254
|
}
|
package/src/form/Completion.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
executeCompletionQuery
|
|
9
9
|
} from '../excellent/helpers';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { FieldElement } from './FieldElement';
|
|
12
12
|
import { CompletionOption, Position } from '../interfaces';
|
|
13
13
|
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
14
14
|
import { msg } from '@lit/localize';
|
|
@@ -16,9 +16,10 @@ import { msg } from '@lit/localize';
|
|
|
16
16
|
/**
|
|
17
17
|
* Completion is a text input that handles excellent completion options in a popup
|
|
18
18
|
*/
|
|
19
|
-
export class Completion extends
|
|
19
|
+
export class Completion extends FieldElement {
|
|
20
20
|
static get styles() {
|
|
21
21
|
return css`
|
|
22
|
+
${super.styles}
|
|
22
23
|
:host {
|
|
23
24
|
display: block;
|
|
24
25
|
}
|
|
@@ -69,7 +70,6 @@ export class Completion extends FormElement {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
code {
|
|
72
|
-
background: rgba(0, 0, 0, 0.1);
|
|
73
73
|
padding: 1px 5px;
|
|
74
74
|
border-radius: var(--curvature);
|
|
75
75
|
}
|
|
@@ -106,9 +106,6 @@ export class Completion extends FormElement {
|
|
|
106
106
|
@property({ type: String })
|
|
107
107
|
name = '';
|
|
108
108
|
|
|
109
|
-
@property({ type: String })
|
|
110
|
-
value = '';
|
|
111
|
-
|
|
112
109
|
@property({ type: Boolean })
|
|
113
110
|
textarea: boolean;
|
|
114
111
|
|
|
@@ -259,7 +256,7 @@ export class Completion extends FormElement {
|
|
|
259
256
|
}
|
|
260
257
|
}
|
|
261
258
|
|
|
262
|
-
|
|
259
|
+
protected renderWidget(): TemplateResult {
|
|
263
260
|
const anchorStyles = this.anchorPosition
|
|
264
261
|
? {
|
|
265
262
|
top: `${this.anchorPosition.top}px`,
|
|
@@ -270,55 +267,51 @@ export class Completion extends FormElement {
|
|
|
270
267
|
const visible = this.options && this.options.length > 0;
|
|
271
268
|
|
|
272
269
|
return html`
|
|
273
|
-
<
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
`
|
|
315
|
-
: null}
|
|
316
|
-
<div class="footer" style="${!visible ? 'display:none' : null}">
|
|
317
|
-
${msg('Tab to complete, enter to select')}
|
|
318
|
-
</div>
|
|
319
|
-
</temba-options>
|
|
320
|
-
</div>
|
|
321
|
-
</temba-field>
|
|
270
|
+
<div class="comp-container">
|
|
271
|
+
<div id="anchor" style=${styleMap(anchorStyles)}></div>
|
|
272
|
+
<temba-textinput
|
|
273
|
+
name=${this.name}
|
|
274
|
+
placeholder=${this.placeholder}
|
|
275
|
+
gsm=${this.gsm}
|
|
276
|
+
counter=${ifDefined(this.counter)}
|
|
277
|
+
@keyup=${this.handleKeyUp}
|
|
278
|
+
@click=${this.handleClick}
|
|
279
|
+
@input=${this.handleInput}
|
|
280
|
+
@blur=${this.handleOptionCanceled}
|
|
281
|
+
maxlength="${ifDefined(this.maxLength)}"
|
|
282
|
+
.value=${this.value}
|
|
283
|
+
?autogrow=${this.autogrow}
|
|
284
|
+
?textarea=${this.textarea}
|
|
285
|
+
?submitOnEnter=${this.submitOnEnter}
|
|
286
|
+
style=${this.minHeight
|
|
287
|
+
? `--textarea-min-height: ${this.minHeight}px`
|
|
288
|
+
: ''}
|
|
289
|
+
>
|
|
290
|
+
</temba-textinput>
|
|
291
|
+
<temba-options
|
|
292
|
+
@temba-selection=${this.handleOptionSelection}
|
|
293
|
+
@temba-canceled=${this.handleOptionCanceled}
|
|
294
|
+
.renderOption=${renderCompletionOption}
|
|
295
|
+
.anchorTo=${this.anchorElement}
|
|
296
|
+
.options=${this.options}
|
|
297
|
+
?visible=${visible}
|
|
298
|
+
>
|
|
299
|
+
${this.currentFunction
|
|
300
|
+
? html`
|
|
301
|
+
<div class="current-fn">
|
|
302
|
+
${renderCompletionOption(this.currentFunction, true)}
|
|
303
|
+
</div>
|
|
304
|
+
`
|
|
305
|
+
: null}
|
|
306
|
+
<div class="footer" style="${!visible ? 'display:none' : null}">
|
|
307
|
+
${msg('Tab to complete, enter to select')}
|
|
308
|
+
</div>
|
|
309
|
+
</temba-options>
|
|
310
|
+
</div>
|
|
322
311
|
`;
|
|
323
312
|
}
|
|
313
|
+
|
|
314
|
+
public render(): TemplateResult {
|
|
315
|
+
return this.renderField();
|
|
316
|
+
}
|
|
324
317
|
}
|
package/src/form/Compose.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TemplateResult, html, css } from 'lit';
|
|
2
|
-
import {
|
|
2
|
+
import { FieldElement } from './FieldElement';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { Attachment, CustomEventType, Language, Shortcut } from '../interfaces';
|
|
5
5
|
import { DEFAULT_MEDIA_ENDPOINT, getClasses } from '../utils';
|
|
@@ -20,7 +20,7 @@ export interface ComposeValue {
|
|
|
20
20
|
variables: string[];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export class Compose extends
|
|
23
|
+
export class Compose extends FieldElement {
|
|
24
24
|
static get styles() {
|
|
25
25
|
return css`
|
|
26
26
|
:host {
|
|
@@ -544,12 +544,12 @@ export class Compose extends FormElement {
|
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
public render(): TemplateResult {
|
|
547
|
+
return this.renderField();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
protected renderWidget(): TemplateResult {
|
|
547
551
|
return html`
|
|
548
|
-
<
|
|
549
|
-
name=${this.name}
|
|
550
|
-
.errors=${this.errors}
|
|
551
|
-
.widgetOnly=${this.widgetOnly}
|
|
552
|
-
.value=${this.value}
|
|
552
|
+
<div
|
|
553
553
|
class=${getClasses({
|
|
554
554
|
'active-template':
|
|
555
555
|
!!this.currentTemplate &&
|
|
@@ -570,7 +570,7 @@ export class Compose extends FormElement {
|
|
|
570
570
|
<div class="container">
|
|
571
571
|
<div class="items actions">${this.getActions()}</div>
|
|
572
572
|
</div>
|
|
573
|
-
</
|
|
573
|
+
</div>
|
|
574
574
|
`;
|
|
575
575
|
}
|
|
576
576
|
|
|
@@ -5,7 +5,7 @@ import { getClasses, postJSON, stopEvent, WebResponse } from '../utils';
|
|
|
5
5
|
import { TextInput } from './TextInput';
|
|
6
6
|
import '../display/Alert';
|
|
7
7
|
import { Contact, CustomEventType } from '../interfaces';
|
|
8
|
-
import {
|
|
8
|
+
import { FieldElement } from './FieldElement';
|
|
9
9
|
import { Checkbox } from './Checkbox';
|
|
10
10
|
import { msg } from '@lit/localize';
|
|
11
11
|
import { OmniOption } from './select/Omnibox';
|
|
@@ -23,7 +23,7 @@ interface SummaryResponse {
|
|
|
23
23
|
blockers: string[];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export class ContactSearch extends
|
|
26
|
+
export class ContactSearch extends FieldElement {
|
|
27
27
|
static get styles() {
|
|
28
28
|
return css`
|
|
29
29
|
:host {
|
|
@@ -475,7 +475,7 @@ export class ContactSearch extends FormElement {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
-
public
|
|
478
|
+
public renderWidget(): TemplateResult {
|
|
479
479
|
let summary: TemplateResult;
|
|
480
480
|
if (this.summary) {
|
|
481
481
|
if (!this.summary.error) {
|
|
@@ -539,7 +539,6 @@ export class ContactSearch extends FormElement {
|
|
|
539
539
|
this.advanced
|
|
540
540
|
? html`<div class="query">
|
|
541
541
|
<temba-textinput
|
|
542
|
-
.label=${this.label}
|
|
543
542
|
.helpText=${this.helpText}
|
|
544
543
|
.widgetOnly=${this.widgetOnly}
|
|
545
544
|
.errors=${this.errors}
|
package/src/form/DatePicker.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { TemplateResult, html, css, PropertyValueMap } from 'lit';
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
|
-
import {
|
|
3
|
+
import { FieldElement } from './FieldElement';
|
|
4
4
|
import { getClasses } from '../utils';
|
|
5
5
|
import { DateTime } from 'luxon';
|
|
6
6
|
|
|
7
|
-
export class DatePicker extends
|
|
7
|
+
export class DatePicker extends FieldElement {
|
|
8
8
|
static get styles() {
|
|
9
9
|
return css`
|
|
10
|
+
${super.styles}
|
|
10
11
|
:host {
|
|
11
12
|
display: block;
|
|
12
13
|
}
|
|
@@ -205,7 +206,7 @@ export class DatePicker extends FormElement {
|
|
|
205
206
|
this.shadowRoot.querySelector('input').focus();
|
|
206
207
|
}
|
|
207
208
|
|
|
208
|
-
|
|
209
|
+
protected renderWidget(): TemplateResult {
|
|
209
210
|
const classes = getClasses({ unset: !this.value });
|
|
210
211
|
|
|
211
212
|
let dateWidgetValue = null;
|
|
@@ -216,42 +217,35 @@ export class DatePicker extends FormElement {
|
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
return html`
|
|
219
|
-
<
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
<div class="input-wrapper">
|
|
232
|
-
<input
|
|
233
|
-
class=${classes}
|
|
234
|
-
name=${this.label}
|
|
235
|
-
value=${dateWidgetValue}
|
|
236
|
-
type="${this.time ? 'datetime-local' : 'date'}"
|
|
237
|
-
@change=${this.handleChange}
|
|
238
|
-
min=${this.min || undefined}
|
|
239
|
-
max=${this.max || undefined}
|
|
240
|
-
/>
|
|
241
|
-
</div>
|
|
242
|
-
${this.time
|
|
243
|
-
? html`
|
|
244
|
-
<div class="tz-wrapper">
|
|
245
|
-
<div class="tz">
|
|
246
|
-
<div class="label">Time Zone</div>
|
|
247
|
-
<div class="zone">${this.timezoneFriendly}</div>
|
|
248
|
-
</div>
|
|
249
|
-
</div>
|
|
250
|
-
`
|
|
251
|
-
: null}
|
|
252
|
-
<slot name="postfix"></slot>
|
|
220
|
+
<div class="container" @click=${this.handleClicked}>
|
|
221
|
+
<slot name="prefix"></slot>
|
|
222
|
+
<div class="input-wrapper">
|
|
223
|
+
<input
|
|
224
|
+
class=${classes}
|
|
225
|
+
name=${this.label}
|
|
226
|
+
value=${dateWidgetValue}
|
|
227
|
+
type="${this.time ? 'datetime-local' : 'date'}"
|
|
228
|
+
@change=${this.handleChange}
|
|
229
|
+
min=${this.min || undefined}
|
|
230
|
+
max=${this.max || undefined}
|
|
231
|
+
/>
|
|
253
232
|
</div>
|
|
254
|
-
|
|
233
|
+
${this.time
|
|
234
|
+
? html`
|
|
235
|
+
<div class="tz-wrapper">
|
|
236
|
+
<div class="tz">
|
|
237
|
+
<div class="label">Time Zone</div>
|
|
238
|
+
<div class="zone">${this.timezoneFriendly}</div>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
`
|
|
242
|
+
: null}
|
|
243
|
+
<slot name="postfix"></slot>
|
|
244
|
+
</div>
|
|
255
245
|
`;
|
|
256
246
|
}
|
|
247
|
+
|
|
248
|
+
public render(): TemplateResult {
|
|
249
|
+
return this.renderField();
|
|
250
|
+
}
|
|
257
251
|
}
|
|
@@ -1,12 +1,65 @@
|
|
|
1
|
-
import { TemplateResult, html, css
|
|
1
|
+
import { TemplateResult, html, css } from 'lit';
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
|
-
import {
|
|
3
|
+
import { RapidElement } from '../RapidElement';
|
|
4
|
+
import { renderMarkdownInline } from '../markdown';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* FieldElement is a base class for form components that provides built-in
|
|
8
|
+
* field wrapper functionality, eliminating the need for manual temba-field embedding.
|
|
9
|
+
*
|
|
10
|
+
* Components extending this class only need to implement renderWidget() with their
|
|
11
|
+
* specific widget content, and the field wrapper (label, errors, help text) is
|
|
12
|
+
* automatically handled.
|
|
8
13
|
*/
|
|
9
|
-
export class
|
|
14
|
+
export abstract class FieldElement extends RapidElement {
|
|
15
|
+
@property({ type: String })
|
|
16
|
+
name = '';
|
|
17
|
+
|
|
18
|
+
@property({ type: String, attribute: 'help_text' })
|
|
19
|
+
helpText: string;
|
|
20
|
+
|
|
21
|
+
@property({ type: Boolean, attribute: 'widget_only' })
|
|
22
|
+
widgetOnly: boolean;
|
|
23
|
+
|
|
24
|
+
@property({ type: Array })
|
|
25
|
+
errors: string[];
|
|
26
|
+
|
|
27
|
+
// Use @property with custom getter/setter to handle both attribute and programmatic access
|
|
28
|
+
private _value: any = '';
|
|
29
|
+
|
|
30
|
+
@property({ type: String })
|
|
31
|
+
public get value() {
|
|
32
|
+
return this._value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public set value(value) {
|
|
36
|
+
this._value = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@property({ attribute: false })
|
|
40
|
+
inputRoot: HTMLElement = this;
|
|
41
|
+
|
|
42
|
+
@property({ type: Boolean })
|
|
43
|
+
disabled = false;
|
|
44
|
+
|
|
45
|
+
static formAssociated = true;
|
|
46
|
+
|
|
47
|
+
protected internals: ElementInternals;
|
|
48
|
+
|
|
49
|
+
@property({ type: Boolean })
|
|
50
|
+
hideErrors = false;
|
|
51
|
+
|
|
52
|
+
@property({ type: Boolean, attribute: 'hide_label' })
|
|
53
|
+
hideLabel: boolean;
|
|
54
|
+
|
|
55
|
+
@property({ type: String })
|
|
56
|
+
label: string;
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
super();
|
|
60
|
+
this.internals = this.attachInternals();
|
|
61
|
+
}
|
|
62
|
+
|
|
10
63
|
static get styles() {
|
|
11
64
|
return css`
|
|
12
65
|
:host {
|
|
@@ -29,19 +82,6 @@ export class FormField extends LitElement {
|
|
|
29
82
|
line-height: normal;
|
|
30
83
|
color: var(--color-text-help);
|
|
31
84
|
margin-left: var(--help-text-margin-left);
|
|
32
|
-
margin-top: -16px;
|
|
33
|
-
opacity: 0;
|
|
34
|
-
transition: opacity ease-in-out 100ms, margin-top ease-in-out 200ms;
|
|
35
|
-
pointer-events: none;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.help-text.help-always {
|
|
39
|
-
opacity: 1;
|
|
40
|
-
margin-top: 6px;
|
|
41
|
-
margin-left: var(--help-text-margin-left);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.field:focus-within .help-text {
|
|
45
85
|
margin-top: 6px;
|
|
46
86
|
opacity: 1;
|
|
47
87
|
}
|
|
@@ -151,36 +191,13 @@ export class FormField extends LitElement {
|
|
|
151
191
|
`;
|
|
152
192
|
}
|
|
153
193
|
|
|
154
|
-
|
|
155
|
-
hideLabel = false;
|
|
156
|
-
|
|
157
|
-
@property({ type: Boolean, attribute: 'widget_only' })
|
|
158
|
-
widgetOnly = false;
|
|
159
|
-
|
|
160
|
-
@property({ type: Array, attribute: false })
|
|
161
|
-
errors: string[] = [];
|
|
162
|
-
|
|
163
|
-
@property({ type: Boolean })
|
|
164
|
-
hideErrors = false;
|
|
165
|
-
|
|
166
|
-
@property({ type: String, attribute: 'help_text' })
|
|
167
|
-
helpText = '';
|
|
168
|
-
|
|
169
|
-
@property({ type: Boolean, attribute: 'help_always' })
|
|
170
|
-
helpAlways = true;
|
|
171
|
-
|
|
172
|
-
@property({ type: String })
|
|
173
|
-
label = '';
|
|
174
|
-
|
|
175
|
-
@property({ type: String })
|
|
176
|
-
name = '';
|
|
177
|
-
|
|
178
|
-
@property({ type: Boolean })
|
|
179
|
-
disabled = false;
|
|
180
|
-
|
|
181
|
-
updated(changedProperties: Map<string | number | symbol, unknown>): void {
|
|
194
|
+
updated(changedProperties: Map<string, any>): void {
|
|
182
195
|
super.updated(changedProperties);
|
|
183
196
|
|
|
197
|
+
if (changedProperties.has('value')) {
|
|
198
|
+
this.internals.setFormValue(this.value);
|
|
199
|
+
}
|
|
200
|
+
|
|
184
201
|
if (
|
|
185
202
|
changedProperties.has('errors') ||
|
|
186
203
|
changedProperties.has('hideErrors')
|
|
@@ -191,19 +208,50 @@ export class FormField extends LitElement {
|
|
|
191
208
|
}
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
|
|
211
|
+
get form() {
|
|
212
|
+
return this.internals.form;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public setValue(value: any) {
|
|
216
|
+
this.value = this.serializeValue(value);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public getDeserializedValue(): any {
|
|
220
|
+
if (!this.value || this.value === '') {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
return JSON.parse(this.value);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public serializeValue(value: any): string {
|
|
227
|
+
return JSON.stringify(value);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Abstract method that components must implement to render their specific widget content.
|
|
232
|
+
* This replaces the need to manually embed temba-field.
|
|
233
|
+
*/
|
|
234
|
+
protected abstract renderWidget(): TemplateResult;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Renders the complete field including label, widget, errors, and help text.
|
|
238
|
+
* Components can override this for custom layouts, but typically should just implement renderWidget().
|
|
239
|
+
*/
|
|
240
|
+
protected renderField(): TemplateResult {
|
|
195
241
|
const hasErrors = !this.hideErrors && this.errors && this.errors.length > 0;
|
|
196
242
|
const errors = hasErrors
|
|
197
243
|
? this.errors.map((error: string) => {
|
|
198
244
|
return html`
|
|
199
|
-
<div class="alert-error">${
|
|
245
|
+
<div class="alert-error">${renderMarkdownInline(error)}</div>
|
|
200
246
|
`;
|
|
201
247
|
})
|
|
202
248
|
: [];
|
|
203
249
|
|
|
204
250
|
if (this.widgetOnly) {
|
|
205
251
|
return html`
|
|
206
|
-
<div class="${this.disabled ? 'disabled' : ''}"
|
|
252
|
+
<div class="${this.disabled ? 'disabled' : ''}">
|
|
253
|
+
${this.renderWidget()}
|
|
254
|
+
</div>
|
|
207
255
|
${errors}
|
|
208
256
|
`;
|
|
209
257
|
}
|
|
@@ -221,18 +269,23 @@ export class FormField extends LitElement {
|
|
|
221
269
|
>
|
|
222
270
|
`
|
|
223
271
|
: null}
|
|
224
|
-
<div class="widget">
|
|
225
|
-
<slot></slot>
|
|
226
|
-
${errors}
|
|
227
|
-
</div>
|
|
272
|
+
<div class="widget">${this.renderWidget()} ${errors}</div>
|
|
228
273
|
${this.helpText && this.helpText !== 'None'
|
|
229
274
|
? html`
|
|
230
|
-
<div class="help-text
|
|
231
|
-
${this.helpText}
|
|
275
|
+
<div class="help-text">
|
|
276
|
+
${renderMarkdownInline(this.helpText)}
|
|
232
277
|
</div>
|
|
233
278
|
`
|
|
234
279
|
: null}
|
|
235
280
|
</div>
|
|
236
281
|
`;
|
|
237
282
|
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Main render method that automatically provides field wrapper functionality.
|
|
286
|
+
* Components extending FieldElement should not override this unless they need custom field layouts.
|
|
287
|
+
*/
|
|
288
|
+
public render(): TemplateResult {
|
|
289
|
+
return this.renderField();
|
|
290
|
+
}
|
|
238
291
|
}
|