@nyaruka/temba-components 0.122.0 → 0.124.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +181 -0
- package/.github/workflows/build.yml +3 -3
- package/.github/workflows/cla.yml +6 -6
- package/.github/workflows/copilot-setup-steps.yml +86 -0
- package/CHANGELOG.md +44 -0
- package/demo/drag-drop-demo.html +141 -0
- package/demo/index.html +57 -0
- package/demo/test-drag-drop.html +94 -0
- package/dist/locales/es.js +1 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +1 -0
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/pt.js +1 -0
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +366 -247
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/chart/TembaChart.js +81 -14
- package/out-tsc/src/chart/TembaChart.js.map +1 -1
- package/out-tsc/src/fields/FieldManager.js +27 -34
- package/out-tsc/src/fields/FieldManager.js.map +1 -1
- package/out-tsc/src/list/RunList.js +13 -8
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/list/SortableList.js +257 -60
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/locales/es.js +1 -0
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +1 -0
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/pt.js +1 -0
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/omnibox/Omnibox.js +1 -1
- package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
- package/out-tsc/src/options/Options.js +36 -13
- package/out-tsc/src/options/Options.js.map +1 -1
- package/out-tsc/src/select/Select.js +226 -43
- package/out-tsc/src/select/Select.js.map +1 -1
- package/out-tsc/src/store/AppState.js +3 -3
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils/index.js +6 -1
- package/out-tsc/src/utils/index.js.map +1 -1
- package/out-tsc/src/vectoricon/VectorIcon.js +2 -1
- package/out-tsc/src/vectoricon/VectorIcon.js.map +1 -1
- package/out-tsc/src/webchat/WebChat.js +5 -2
- package/out-tsc/src/webchat/WebChat.js.map +1 -1
- package/out-tsc/temba-modules.js +0 -2
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-appstate-language.test.js +176 -0
- package/out-tsc/test/temba-appstate-language.test.js.map +1 -0
- package/out-tsc/test/temba-chart.test.js +125 -0
- package/out-tsc/test/temba-chart.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +317 -0
- package/out-tsc/test/temba-dropdown.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +273 -0
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor.test.js +244 -0
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -0
- package/out-tsc/test/temba-flow-plumber.test.js +145 -0
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -0
- package/out-tsc/test/temba-flow-render.test.js +171 -0
- package/out-tsc/test/temba-flow-render.test.js.map +1 -0
- package/out-tsc/test/temba-omnibox.test.js +2 -3
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-run-list.test.js +588 -0
- package/out-tsc/test/temba-run-list.test.js.map +1 -0
- package/out-tsc/test/temba-select.test.js +149 -52
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/temba-sortable-list.test.js +91 -15
- package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
- package/out-tsc/test/temba-toast.test.js +299 -0
- package/out-tsc/test/temba-toast.test.js.map +1 -0
- package/out-tsc/test/temba-utils-index.test.js +1178 -0
- package/out-tsc/test/temba-utils-index.test.js.map +1 -0
- package/out-tsc/test/temba-webchat-lightbox-fix.test.js +42 -0
- package/out-tsc/test/temba-webchat-lightbox-fix.test.js.map +1 -0
- package/out-tsc/test/temba-webchat.test.js +816 -0
- package/out-tsc/test/temba-webchat.test.js.map +1 -0
- package/out-tsc/test/utils.test.js +33 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +6 -8
- package/screenshots/truth/alert/error.png +0 -0
- package/screenshots/truth/alert/info.png +0 -0
- package/screenshots/truth/alert/warning.png +0 -0
- package/screenshots/truth/checkbox/checkbox-label-background-hover.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-focused.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/badges.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-for-archived-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-stopped-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/content-menu/button-no-items.png +0 -0
- package/screenshots/truth/content-menu/items-and-buttons.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/date/date-inline.png +0 -0
- package/screenshots/truth/date/date.png +0 -0
- package/screenshots/truth/date/datetime.png +0 -0
- package/screenshots/truth/date/duration.png +0 -0
- package/screenshots/truth/date/timedate.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/updated-keyboard-date.png +0 -0
- package/screenshots/truth/dialog/focused.png +0 -0
- package/screenshots/truth/dropdown/after-blur.png +0 -0
- package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
- package/screenshots/truth/dropdown/custom-arrow-size.png +0 -0
- package/screenshots/truth/dropdown/default.png +0 -0
- package/screenshots/truth/dropdown/narrow-toggle.png +0 -0
- package/screenshots/truth/dropdown/no-mask.png +0 -0
- package/screenshots/truth/dropdown/opened.png +0 -0
- package/screenshots/truth/dropdown/positioned.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
- package/screenshots/truth/dropdown/with-mask.png +0 -0
- package/screenshots/truth/flow/editor-basic.png +0 -0
- package/screenshots/truth/label/custom.png +0 -0
- package/screenshots/truth/label/danger.png +0 -0
- package/screenshots/truth/label/dark.png +0 -0
- package/screenshots/truth/label/default-icon.png +0 -0
- package/screenshots/truth/label/no-icon.png +0 -0
- package/screenshots/truth/label/primary.png +0 -0
- package/screenshots/truth/label/secondary.png +0 -0
- package/screenshots/truth/label/shadow.png +0 -0
- package/screenshots/truth/label/tertiary.png +0 -0
- package/screenshots/truth/lightbox/img-zoomed.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/list/sortable-dragging.png +0 -0
- package/screenshots/truth/list/sortable-dropped.png +0 -0
- package/screenshots/truth/list/sortable.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-root.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/modax/form.png +0 -0
- package/screenshots/truth/modax/simple.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-reorder-final.png +0 -0
- package/screenshots/truth/select/multi-reorder-initial.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/custom-min-custom-max-valid-value.png +0 -0
- package/screenshots/truth/slider/custom-min-default-max-no-value.png +0 -0
- package/screenshots/truth/slider/default-min-custom-max-no-value.png +0 -0
- package/screenshots/truth/slider/default-min-default-max-invalid-value.png +0 -0
- package/screenshots/truth/slider/default-min-default-max-valid-value.png +0 -0
- package/screenshots/truth/slider/update-slider-on-value-change.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/templates/unapproved.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/screenshots/truth/tip/bottom.png +0 -0
- package/screenshots/truth/tip/left.png +0 -0
- package/screenshots/truth/tip/right.png +0 -0
- package/screenshots/truth/tip/top.png +0 -0
- package/screenshots/truth/webchat/closed-widget.png +0 -0
- package/screenshots/truth/webchat/connected-state.png +0 -0
- package/screenshots/truth/webchat/connecting-state.png +0 -0
- package/screenshots/truth/webchat/disconnected-state.png +0 -0
- package/screenshots/truth/webchat/opened-widget.png +0 -0
- package/src/chart/TembaChart.ts +86 -15
- package/src/fields/FieldManager.ts +30 -38
- package/src/list/RunList.ts +11 -8
- package/src/list/SortableList.ts +291 -67
- package/src/locales/es.ts +1 -0
- package/src/locales/fr.ts +1 -0
- package/src/locales/pt.ts +1 -0
- package/src/omnibox/Omnibox.ts +1 -1
- package/src/options/Options.ts +38 -13
- package/src/select/Select.ts +245 -47
- package/src/store/AppState.ts +3 -3
- package/src/utils/index.ts +17 -5
- package/src/vectoricon/VectorIcon.ts +2 -1
- package/src/webchat/WebChat.ts +5 -2
- package/temba-modules.ts +0 -2
- package/test/temba-appstate-language.test.ts +218 -0
- package/test/temba-chart.test.ts +161 -1
- package/test/temba-dropdown.test.ts +444 -0
- package/test/temba-flow-editor-node.test.ts +344 -0
- package/test/temba-flow-editor.test.ts +301 -0
- package/test/temba-flow-plumber.test.ts +189 -0
- package/test/temba-flow-render.test.ts +220 -0
- package/test/temba-omnibox.test.ts +2 -3
- package/test/temba-run-list.test.ts +774 -0
- package/test/temba-select.test.ts +206 -78
- package/test/temba-sortable-list.test.ts +108 -15
- package/test/temba-toast.test.ts +386 -0
- package/test/temba-utils-index.test.ts +1547 -0
- package/test/temba-webchat-lightbox-fix.test.ts +57 -0
- package/test/temba-webchat.test.ts +1095 -0
- package/test/utils.test.ts +56 -2
- package/test-assets/list/flow-results.json +17 -0
- package/test-assets/list/runs.json +126 -0
- package/test-assets/style.css +23 -0
- package/web-test-runner.config.mjs +33 -7
- package/xliff/es.xlf +3 -0
- package/xliff/fr.xlf +3 -0
- package/xliff/pt.xlf +3 -0
- package/out-tsc/src/outboxmonitor/OutboxMonitor.js +0 -136
- package/out-tsc/src/outboxmonitor/OutboxMonitor.js.map +0 -1
- package/src/outboxmonitor/OutboxMonitor.ts +0 -148
package/src/select/Select.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
2
|
import { TemplateResult, html, css, CSSResult, CSSResultArray } from 'lit';
|
|
3
|
-
import { property } from 'lit/decorators.js';
|
|
3
|
+
import { property, state } from 'lit/decorators.js';
|
|
4
4
|
import {
|
|
5
5
|
getUrl,
|
|
6
6
|
getClasses,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
postJSON
|
|
10
10
|
} from '../utils';
|
|
11
11
|
import '../options/Options';
|
|
12
|
+
import '../list/SortableList';
|
|
12
13
|
import { EventHandler } from '../RapidElement';
|
|
13
14
|
import { FormElement } from '../FormElement';
|
|
14
15
|
|
|
@@ -76,7 +77,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
76
77
|
background: rgba(100, 100, 100, 0.05);
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
.selected-item.multi .remove-item {
|
|
80
|
+
. selected-item.multi .remove-item {
|
|
80
81
|
display: none;
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -112,7 +113,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
112
113
|
padding-top: 1px;
|
|
113
114
|
box-shadow: var(--widget-box-shadow);
|
|
114
115
|
position: relative;
|
|
115
|
-
min-height: var(--temba-select-min-height, 2.
|
|
116
|
+
min-height: var(--temba-select-min-height, 2.4em);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
temba-icon.select-open:hover,
|
|
@@ -148,7 +149,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
148
149
|
flex-direction: row;
|
|
149
150
|
align-items: stretch;
|
|
150
151
|
user-select: none;
|
|
151
|
-
padding: var(--temba-select-selected-padding);
|
|
152
|
+
padding: var(--temba-select-selected-padding, 0px 4px);
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
.searchable .selected {
|
|
@@ -207,6 +208,18 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
207
208
|
background: rgba(100, 100, 100, 0.3);
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
.multi .selected-item.sortable {
|
|
212
|
+
cursor: move;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.multi .selected-item.dragging {
|
|
216
|
+
opacity: 0.5;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.multi temba-sortable-list {
|
|
220
|
+
margin: 0 !important;
|
|
221
|
+
}
|
|
222
|
+
|
|
210
223
|
input {
|
|
211
224
|
font-size: 13px;
|
|
212
225
|
width: 0px;
|
|
@@ -225,16 +238,15 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
225
238
|
border: 0px solid purple !important;
|
|
226
239
|
}
|
|
227
240
|
|
|
228
|
-
.input-wrapper {
|
|
229
|
-
min-width: 1px;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
241
|
.input-wrapper:focus-within {
|
|
233
242
|
min-width: 1px;
|
|
234
243
|
}
|
|
235
244
|
|
|
236
245
|
.input-wrapper {
|
|
246
|
+
min-width: 1px;
|
|
237
247
|
margin-left: 6px;
|
|
248
|
+
margin-right: -6px;
|
|
249
|
+
display: flex;
|
|
238
250
|
}
|
|
239
251
|
|
|
240
252
|
.multi .input-wrapper {
|
|
@@ -274,9 +286,9 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
274
286
|
box-shadow: none !important;
|
|
275
287
|
}
|
|
276
288
|
|
|
277
|
-
.input-wrapper {
|
|
278
|
-
|
|
279
|
-
|
|
289
|
+
.multi .input-wrapper {
|
|
290
|
+
flex-shrink: 0;
|
|
291
|
+
min-width: 100px;
|
|
280
292
|
}
|
|
281
293
|
|
|
282
294
|
.input-wrapper .searchbox {
|
|
@@ -291,6 +303,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
291
303
|
color: var(--color-placeholder);
|
|
292
304
|
display: none;
|
|
293
305
|
line-height: var(--temba-select-selected-line-height);
|
|
306
|
+
margin-left: 6px;
|
|
294
307
|
}
|
|
295
308
|
|
|
296
309
|
.footer {
|
|
@@ -332,6 +345,10 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
332
345
|
pointer-events: none;
|
|
333
346
|
padding: 0px;
|
|
334
347
|
}
|
|
348
|
+
|
|
349
|
+
.ghost .remove-item {
|
|
350
|
+
display: none !important;
|
|
351
|
+
}
|
|
335
352
|
`;
|
|
336
353
|
}
|
|
337
354
|
|
|
@@ -410,6 +427,9 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
410
427
|
@property({ type: Boolean })
|
|
411
428
|
disabled = false;
|
|
412
429
|
|
|
430
|
+
@state()
|
|
431
|
+
attemptedOpen = false;
|
|
432
|
+
|
|
413
433
|
@property({ attribute: false })
|
|
414
434
|
selectedIndex = -1;
|
|
415
435
|
|
|
@@ -512,6 +532,9 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
512
532
|
@property({ type: Boolean })
|
|
513
533
|
allowAnchor: boolean = true;
|
|
514
534
|
|
|
535
|
+
@property({ type: String })
|
|
536
|
+
draggingId: string;
|
|
537
|
+
|
|
515
538
|
private alphaSort = (a: any, b: any) => {
|
|
516
539
|
// by default, all endpoint values are sorted by name
|
|
517
540
|
if (this.endpoint) {
|
|
@@ -535,6 +558,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
535
558
|
this.renderSelectedItemDefault = this.renderSelectedItemDefault.bind(this);
|
|
536
559
|
this.prepareOptionsDefault = this.prepareOptionsDefault.bind(this);
|
|
537
560
|
this.isMatchDefault = this.isMatchDefault.bind(this);
|
|
561
|
+
this.handleOrderChanged = this.handleOrderChanged.bind(this);
|
|
538
562
|
}
|
|
539
563
|
|
|
540
564
|
public prepareOptionsDefault(options: T[]): T[] {
|
|
@@ -863,6 +887,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
863
887
|
}
|
|
864
888
|
|
|
865
889
|
this.visibleOptions = [];
|
|
890
|
+
this.attemptedOpen = false;
|
|
866
891
|
this.input = '';
|
|
867
892
|
this.next = null;
|
|
868
893
|
this.complete = true;
|
|
@@ -955,7 +980,9 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
955
980
|
}
|
|
956
981
|
|
|
957
982
|
public isOpen(): boolean {
|
|
958
|
-
return
|
|
983
|
+
return (
|
|
984
|
+
this.visibleOptions.length > 0 || (this.attemptedOpen && this.focused)
|
|
985
|
+
);
|
|
959
986
|
}
|
|
960
987
|
|
|
961
988
|
public setOptions(options: any[]): void {
|
|
@@ -1212,6 +1239,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1212
1239
|
|
|
1213
1240
|
private handleBlur() {
|
|
1214
1241
|
this.focused = false;
|
|
1242
|
+
this.attemptedOpen = false;
|
|
1215
1243
|
if (this.visibleOptions.length > 0) {
|
|
1216
1244
|
this.input = '';
|
|
1217
1245
|
this.next = null;
|
|
@@ -1285,8 +1313,10 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1285
1313
|
) {
|
|
1286
1314
|
if (
|
|
1287
1315
|
this.visibleOptions.length === 0 &&
|
|
1288
|
-
this.completionOptions.length === 0
|
|
1316
|
+
this.completionOptions.length === 0 &&
|
|
1317
|
+
!this.input
|
|
1289
1318
|
) {
|
|
1319
|
+
this.attemptedOpen = true;
|
|
1290
1320
|
this.requestUpdate('input');
|
|
1291
1321
|
return;
|
|
1292
1322
|
}
|
|
@@ -1322,6 +1352,7 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1322
1352
|
|
|
1323
1353
|
private handleCancel() {
|
|
1324
1354
|
this.visibleOptions = [];
|
|
1355
|
+
this.attemptedOpen = false;
|
|
1325
1356
|
}
|
|
1326
1357
|
|
|
1327
1358
|
private handleCursorChanged(event: CustomEvent) {
|
|
@@ -1329,8 +1360,13 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1329
1360
|
}
|
|
1330
1361
|
|
|
1331
1362
|
private handleContainerClick(event: MouseEvent) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1363
|
+
if (this.disabled) {
|
|
1364
|
+
// prevent opening dropdown right after drag-and-drop
|
|
1365
|
+
event.stopPropagation();
|
|
1366
|
+
event.preventDefault();
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1334
1370
|
this.focused = true;
|
|
1335
1371
|
if ((event.target as any).tagName !== 'INPUT') {
|
|
1336
1372
|
const input = this.shadowRoot.querySelector('input');
|
|
@@ -1340,10 +1376,15 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1340
1376
|
return;
|
|
1341
1377
|
}
|
|
1342
1378
|
|
|
1343
|
-
if (
|
|
1379
|
+
// Check if dropdown is currently open (either with options or showing "No options")
|
|
1380
|
+
if (this.isOpen()) {
|
|
1344
1381
|
this.visibleOptions = [];
|
|
1382
|
+
this.attemptedOpen = false;
|
|
1345
1383
|
} else {
|
|
1384
|
+
this.attemptedOpen = true;
|
|
1346
1385
|
this.requestUpdate('input');
|
|
1386
|
+
// Also trigger an immediate update to show empty dropdown
|
|
1387
|
+
this.requestUpdate();
|
|
1347
1388
|
}
|
|
1348
1389
|
}
|
|
1349
1390
|
}
|
|
@@ -1361,6 +1402,9 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1361
1402
|
}
|
|
1362
1403
|
|
|
1363
1404
|
private handleArrowClick(event: MouseEvent): void {
|
|
1405
|
+
if (this.disabled) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1364
1408
|
if (this.isOpen()) {
|
|
1365
1409
|
event.preventDefault();
|
|
1366
1410
|
event.stopPropagation();
|
|
@@ -1376,7 +1420,16 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1376
1420
|
// special case for icons on any option type
|
|
1377
1421
|
const icon = (option as any).icon;
|
|
1378
1422
|
return html`
|
|
1379
|
-
<div
|
|
1423
|
+
<div
|
|
1424
|
+
class="option-name"
|
|
1425
|
+
style="flex: 1 1 auto;
|
|
1426
|
+
align-self: center;
|
|
1427
|
+
white-space: nowrap;
|
|
1428
|
+
overflow: hidden;
|
|
1429
|
+
text-overflow: ellipsis;
|
|
1430
|
+
padding: 2px 8px;
|
|
1431
|
+
display: flex;"
|
|
1432
|
+
>
|
|
1380
1433
|
${icon
|
|
1381
1434
|
? html`<temba-icon
|
|
1382
1435
|
name="${icon}"
|
|
@@ -1443,6 +1496,18 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1443
1496
|
const idx = this.values.indexOf(valueToRemove);
|
|
1444
1497
|
if (idx > -1) {
|
|
1445
1498
|
this.values.splice(idx, 1);
|
|
1499
|
+
|
|
1500
|
+
// Also remove the 'selected' attribute from the corresponding temba-option element
|
|
1501
|
+
const valueToMatch = this.getValue(valueToRemove);
|
|
1502
|
+
for (const child of this.children) {
|
|
1503
|
+
if (child.tagName === 'TEMBA-OPTION') {
|
|
1504
|
+
const childValue = child.getAttribute('value');
|
|
1505
|
+
if (childValue === valueToMatch) {
|
|
1506
|
+
child.removeAttribute('selected');
|
|
1507
|
+
break;
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1446
1511
|
}
|
|
1447
1512
|
this.requestUpdate('values', oldValues);
|
|
1448
1513
|
this.infoText = '';
|
|
@@ -1461,6 +1526,41 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1461
1526
|
this.requestUpdate('values', oldValues);
|
|
1462
1527
|
}
|
|
1463
1528
|
|
|
1529
|
+
private shouldShowEmptyMessage(): boolean {
|
|
1530
|
+
return (
|
|
1531
|
+
this.attemptedOpen &&
|
|
1532
|
+
this.focused &&
|
|
1533
|
+
this.visibleOptions.length === 0 &&
|
|
1534
|
+
!this.input &&
|
|
1535
|
+
this.staticOptions.length === 0 &&
|
|
1536
|
+
!this.endpoint
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
private handleOrderChanged(event: CustomEvent): void {
|
|
1541
|
+
const detail = event.detail;
|
|
1542
|
+
|
|
1543
|
+
// Handle new swap-based format
|
|
1544
|
+
if (detail.swap && Array.isArray(detail.swap) && detail.swap.length === 2) {
|
|
1545
|
+
const [fromIdx, toIdx] = detail.swap;
|
|
1546
|
+
|
|
1547
|
+
// Only reorder if the indexes are different and valid
|
|
1548
|
+
if (
|
|
1549
|
+
fromIdx !== toIdx &&
|
|
1550
|
+
fromIdx >= 0 &&
|
|
1551
|
+
toIdx >= 0 &&
|
|
1552
|
+
fromIdx < this.values.length &&
|
|
1553
|
+
toIdx < this.values.length
|
|
1554
|
+
) {
|
|
1555
|
+
const oldValues = [...this.values];
|
|
1556
|
+
// Move the item from fromIdx to toIdx
|
|
1557
|
+
const movedItem = this.values.splice(fromIdx, 1)[0];
|
|
1558
|
+
this.values.splice(toIdx, 0, movedItem);
|
|
1559
|
+
this.requestUpdate('values', oldValues);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1464
1564
|
public render(): TemplateResult {
|
|
1465
1565
|
const placeholder = this.values.length === 0 ? this.placeholder : '';
|
|
1466
1566
|
const placeholderDiv = html`
|
|
@@ -1545,35 +1645,132 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1545
1645
|
: null
|
|
1546
1646
|
}
|
|
1547
1647
|
${!this.multi && !this.resolving ? input : null}
|
|
1548
|
-
${
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1648
|
+
${
|
|
1649
|
+
this.multi && this.values.length > 1
|
|
1650
|
+
? html`
|
|
1651
|
+
<temba-sortable-list
|
|
1652
|
+
horizontal
|
|
1653
|
+
@temba-order-changed=${this.handleOrderChanged}
|
|
1654
|
+
.prepareGhost=${(item: any) => {
|
|
1655
|
+
item.style.transform = 'scale(1)';
|
|
1656
|
+
item.querySelector('.remove-item').style.display =
|
|
1657
|
+
'none';
|
|
1658
|
+
}}
|
|
1659
|
+
>
|
|
1660
|
+
${this.values.map(
|
|
1661
|
+
(selected: any, index: number) => html`
|
|
1662
|
+
<div
|
|
1663
|
+
class="selected-item sortable ${index ===
|
|
1664
|
+
this.selectedIndex
|
|
1665
|
+
? 'focused'
|
|
1666
|
+
: ''} ${this.draggingId === `selected-${index}`
|
|
1667
|
+
? 'dragging'
|
|
1668
|
+
: ''}"
|
|
1669
|
+
id="selected-${index}"
|
|
1670
|
+
style="
|
|
1671
|
+
vertical-align: middle;
|
|
1672
|
+
background: rgba(100,100,100,0.1);
|
|
1673
|
+
user-select: none;
|
|
1674
|
+
border-radius: 2px;
|
|
1675
|
+
align-items: center;
|
|
1676
|
+
flex-direction: row;
|
|
1677
|
+
flex-wrap: nowrap;
|
|
1678
|
+
margin: 2px 2px;
|
|
1679
|
+
display: flex;
|
|
1680
|
+
overflow: hidden;
|
|
1681
|
+
color: var(--color-widget-text);
|
|
1682
|
+
line-height: var(--temba-select-selected-line-height);
|
|
1683
|
+
--icon-color: var(--color-text-dark);
|
|
1684
|
+
${index === this.selectedIndex
|
|
1685
|
+
? 'background: rgba(100,100,100,0.3);'
|
|
1686
|
+
: ''}
|
|
1687
|
+
${this.draggingId === `selected-${index}`
|
|
1688
|
+
? 'opacity: 0.5;'
|
|
1689
|
+
: ''}
|
|
1690
|
+
"
|
|
1691
|
+
>
|
|
1692
|
+
${this.multi
|
|
1693
|
+
? html`
|
|
1694
|
+
<div
|
|
1695
|
+
class="remove-item"
|
|
1696
|
+
style="
|
|
1697
|
+
cursor: pointer;
|
|
1698
|
+
display: inline-block;
|
|
1699
|
+
padding: 3px 6px;
|
|
1700
|
+
border-right: 1px solid rgba(100,100,100,0.2);
|
|
1701
|
+
margin: 0;
|
|
1702
|
+
background: rgba(100,100,100,0.05);
|
|
1703
|
+
margin-top:1px;
|
|
1704
|
+
"
|
|
1705
|
+
@click=${(evt: MouseEvent) => {
|
|
1706
|
+
evt.preventDefault();
|
|
1707
|
+
evt.stopPropagation();
|
|
1708
|
+
this.handleRemoveSelection(selected);
|
|
1709
|
+
}}
|
|
1710
|
+
>
|
|
1711
|
+
<temba-icon
|
|
1712
|
+
name="${Icon.delete_small}"
|
|
1713
|
+
size="1"
|
|
1714
|
+
></temba-icon>
|
|
1715
|
+
</div>
|
|
1716
|
+
`
|
|
1717
|
+
: null}
|
|
1718
|
+
${this.renderSelectedItem(selected)}
|
|
1719
|
+
</div>
|
|
1720
|
+
`
|
|
1721
|
+
)}
|
|
1722
|
+
</temba-sortable-list>
|
|
1723
|
+
`
|
|
1724
|
+
: this.values.map(
|
|
1725
|
+
(selected: any, index: number) => html`
|
|
1726
|
+
<div
|
|
1727
|
+
class="selected-item ${index === this.selectedIndex
|
|
1728
|
+
? 'focused'
|
|
1729
|
+
: ''}"
|
|
1730
|
+
style="
|
|
1731
|
+
display: flex;
|
|
1732
|
+
overflow: hidden;
|
|
1733
|
+
color: var(--color-widget-text);
|
|
1734
|
+
line-height: var(--temba-select-selected-line-height);
|
|
1735
|
+
--icon-color: var(--color-text-dark);
|
|
1736
|
+
${index === this.selectedIndex
|
|
1737
|
+
? 'background: rgba(100,100,100,0.3);'
|
|
1738
|
+
: ''}
|
|
1739
|
+
"
|
|
1740
|
+
>
|
|
1741
|
+
${this.multi
|
|
1742
|
+
? html`
|
|
1743
|
+
<div
|
|
1744
|
+
class="remove-item"
|
|
1745
|
+
style="
|
|
1746
|
+
cursor: pointer;
|
|
1747
|
+
display: inline-block;
|
|
1748
|
+
padding: 3px 6px;
|
|
1749
|
+
border-right: 1px solid rgba(100,100,100,0.2);
|
|
1750
|
+
margin: 0;
|
|
1751
|
+
background: rgba(100,100,100,0.05);
|
|
1752
|
+
margin-top:1px;
|
|
1753
|
+
"
|
|
1754
|
+
@click=${(evt: MouseEvent) => {
|
|
1755
|
+
evt.preventDefault();
|
|
1756
|
+
evt.stopPropagation();
|
|
1757
|
+
this.handleRemoveSelection(selected);
|
|
1758
|
+
}}
|
|
1759
|
+
>
|
|
1760
|
+
<temba-icon
|
|
1761
|
+
name="${Icon.delete_small}"
|
|
1762
|
+
size="1"
|
|
1763
|
+
></temba-icon>
|
|
1764
|
+
</div>
|
|
1765
|
+
`
|
|
1766
|
+
: null}
|
|
1767
|
+
${!this.input
|
|
1768
|
+
? this.renderSelectedItem(selected)
|
|
1769
|
+
: null}
|
|
1770
|
+
</div>
|
|
1771
|
+
`
|
|
1772
|
+
)
|
|
1773
|
+
}
|
|
1577
1774
|
${this.multi ? input : null}
|
|
1578
1775
|
</div>
|
|
1579
1776
|
|
|
@@ -1620,7 +1817,8 @@ export class Select<T extends SelectOption> extends FormElement {
|
|
|
1620
1817
|
.getName=${this.getNameInternal}
|
|
1621
1818
|
?static-width=${this.optionWidth}
|
|
1622
1819
|
?anchor-right=${this.anchorRight}
|
|
1623
|
-
?visible=${this.visibleOptions.length > 0}
|
|
1820
|
+
?visible=${this.visibleOptions.length > 0 || this.shouldShowEmptyMessage()}
|
|
1821
|
+
?showEmptyMessage=${this.shouldShowEmptyMessage()}
|
|
1624
1822
|
></temba-options>
|
|
1625
1823
|
|
|
1626
1824
|
<temba-options
|
package/src/store/AppState.ts
CHANGED
|
@@ -157,11 +157,11 @@ export const zustand = createStore<AppState>()(
|
|
|
157
157
|
setFlowContents: (flow: FlowContents) => {
|
|
158
158
|
set((state: AppState) => {
|
|
159
159
|
const flowLang = flow.definition.language;
|
|
160
|
-
const languageCode = state.languageCode || flowLang;
|
|
161
160
|
state.flowDefinition = flow.definition;
|
|
162
161
|
state.flowInfo = flow.info;
|
|
163
|
-
|
|
164
|
-
state.languageCode =
|
|
162
|
+
// Reset to the flow's default language when loading a new flow
|
|
163
|
+
state.languageCode = flowLang;
|
|
164
|
+
state.isTranslating = false;
|
|
165
165
|
});
|
|
166
166
|
},
|
|
167
167
|
|
package/src/utils/index.ts
CHANGED
|
@@ -494,7 +494,7 @@ export const getScrollParent = (node: any): any => {
|
|
|
494
494
|
return null;
|
|
495
495
|
};
|
|
496
496
|
|
|
497
|
-
export const isElementVisible = (el: any, holder
|
|
497
|
+
export const isElementVisible = (el: any, holder?: any) => {
|
|
498
498
|
holder = holder || document.body;
|
|
499
499
|
const { top, bottom } = el.getBoundingClientRect();
|
|
500
500
|
const holderRect = holder.getBoundingClientRect();
|
|
@@ -575,7 +575,7 @@ export const timeSince = (
|
|
|
575
575
|
}
|
|
576
576
|
};
|
|
577
577
|
|
|
578
|
-
export const isDate = (value:
|
|
578
|
+
export const isDate = (value: any): boolean => {
|
|
579
579
|
if (toString.call(value) === '[object Date]') {
|
|
580
580
|
return true;
|
|
581
581
|
}
|
|
@@ -635,6 +635,10 @@ export const truncate = (input: string, max: number): string => {
|
|
|
635
635
|
};
|
|
636
636
|
|
|
637
637
|
export const oxford = (items: any[], joiner = 'and'): any => {
|
|
638
|
+
if (items.length === 0) {
|
|
639
|
+
return '';
|
|
640
|
+
}
|
|
641
|
+
|
|
638
642
|
if (items.length === 1) {
|
|
639
643
|
return items[0];
|
|
640
644
|
}
|
|
@@ -657,7 +661,9 @@ export const oxford = (items: any[], joiner = 'and'): any => {
|
|
|
657
661
|
});
|
|
658
662
|
}
|
|
659
663
|
|
|
660
|
-
|
|
664
|
+
const allButLast = items.slice(0, -1);
|
|
665
|
+
const last = items[items.length - 1];
|
|
666
|
+
return allButLast.join(', ') + ', ' + joiner + ' ' + last;
|
|
661
667
|
};
|
|
662
668
|
|
|
663
669
|
export const oxfordFn = (
|
|
@@ -713,13 +719,19 @@ export enum COOKIE_KEYS {
|
|
|
713
719
|
TICKET_SHOW_DETAILS = 'tickets.show-details'
|
|
714
720
|
}
|
|
715
721
|
|
|
716
|
-
export const capitalize = (
|
|
722
|
+
export const capitalize = (
|
|
723
|
+
[first, ...rest]: string[] | string,
|
|
724
|
+
locale = navigator.language
|
|
725
|
+
) =>
|
|
717
726
|
first === undefined ? '' : first.toLocaleUpperCase(locale) + rest.join('');
|
|
718
727
|
|
|
719
728
|
export const formatFileType = (type: string): string => {
|
|
720
729
|
return type.split('/')[1];
|
|
721
730
|
};
|
|
722
|
-
export const formatFileSize = (
|
|
731
|
+
export const formatFileSize = (
|
|
732
|
+
bytes: number,
|
|
733
|
+
decimalPoint?: number
|
|
734
|
+
): string => {
|
|
723
735
|
if (bytes == 0) return '0 KB';
|
|
724
736
|
const k = 1024,
|
|
725
737
|
dm = decimalPoint || 2,
|
|
@@ -127,9 +127,10 @@ export class VectorIcon extends LitElement {
|
|
|
127
127
|
|
|
128
128
|
.spin-forever {
|
|
129
129
|
animation-name: spin;
|
|
130
|
-
animation-duration: 2000ms;
|
|
130
|
+
animation-duration: var(--test-animation-duration, 2000ms);
|
|
131
131
|
animation-iteration-count: infinite;
|
|
132
132
|
animation-timing-function: linear;
|
|
133
|
+
animation-play-state: var(--test-animation-play-state, running);
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
@keyframes spin {
|
package/src/webchat/WebChat.ts
CHANGED
|
@@ -398,8 +398,11 @@ export class WebChat extends LitElement {
|
|
|
398
398
|
super.firstUpdated(changed);
|
|
399
399
|
this.chat = this.shadowRoot.querySelector('temba-chat');
|
|
400
400
|
|
|
401
|
-
|
|
402
|
-
document.querySelector('
|
|
401
|
+
// Only create lightbox if one doesn't already exist
|
|
402
|
+
if (!document.querySelector('temba-lightbox')) {
|
|
403
|
+
const lightbox = document.createElement('temba-lightbox');
|
|
404
|
+
document.querySelector('body').appendChild(lightbox);
|
|
405
|
+
}
|
|
403
406
|
}
|
|
404
407
|
|
|
405
408
|
private handleReconnect() {
|
package/temba-modules.ts
CHANGED
|
@@ -58,7 +58,6 @@ import { MediaPicker } from './src/mediapicker/MediaPicker';
|
|
|
58
58
|
import { Editor } from './src/flow/Editor';
|
|
59
59
|
import { EditorNode } from './src/flow/EditorNode';
|
|
60
60
|
import { ContactNotepad } from './src/contacts/ContactNotepad';
|
|
61
|
-
import { OutboxMonitor } from './src/outboxmonitor/OutboxMonitor';
|
|
62
61
|
import { ProgressBar } from './src/progress/ProgressBar';
|
|
63
62
|
import { StartProgress } from './src/progress/StartProgress';
|
|
64
63
|
import { ShortcutList } from './src/list/ShortcutList';
|
|
@@ -134,7 +133,6 @@ addCustomElement('temba-media-picker', MediaPicker);
|
|
|
134
133
|
addCustomElement('temba-flow-editor', Editor);
|
|
135
134
|
addCustomElement('temba-flow-node', EditorNode);
|
|
136
135
|
addCustomElement('temba-contact-notepad', ContactNotepad);
|
|
137
|
-
addCustomElement('temba-outbox-monitor', OutboxMonitor);
|
|
138
136
|
addCustomElement('temba-progress', ProgressBar);
|
|
139
137
|
addCustomElement('temba-start-progress', StartProgress);
|
|
140
138
|
addCustomElement('temba-shortcuts', ShortcutList);
|