@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.
Files changed (282) hide show
  1. package/CHANGELOG.md +37 -3
  2. package/demo/data/flows/sample-flow.json +186 -96
  3. package/demo/test-colorpicker.html +30 -0
  4. package/dist/temba-components.js +1126 -1111
  5. package/dist/temba-components.js.map +1 -1
  6. package/out-tsc/src/events.js.map +1 -1
  7. package/out-tsc/src/excellent/helpers.js +2 -2
  8. package/out-tsc/src/excellent/helpers.js.map +1 -1
  9. package/out-tsc/src/flow/CanvasNode.js +25 -7
  10. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  11. package/out-tsc/src/flow/Editor.js +11 -1
  12. package/out-tsc/src/flow/Editor.js.map +1 -1
  13. package/out-tsc/src/flow/NodeEditor.js +133 -290
  14. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  15. package/out-tsc/src/flow/actions/add_input_labels.js +40 -0
  16. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  17. package/out-tsc/src/flow/actions/call_llm.js +56 -3
  18. package/out-tsc/src/flow/actions/call_llm.js.map +1 -1
  19. package/out-tsc/src/flow/actions/call_webhook.js +1 -1
  20. package/out-tsc/src/flow/actions/call_webhook.js.map +1 -1
  21. package/out-tsc/src/flow/actions/open_ticket.js +65 -3
  22. package/out-tsc/src/flow/actions/open_ticket.js.map +1 -1
  23. package/out-tsc/src/flow/actions/set_run_result.js +75 -0
  24. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  25. package/out-tsc/src/flow/config.js +4 -0
  26. package/out-tsc/src/flow/config.js.map +1 -1
  27. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +227 -0
  28. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -0
  29. package/out-tsc/src/flow/nodes/split_by_ticket.js +18 -0
  30. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -0
  31. package/out-tsc/src/flow/nodes/wait_for_response.js +27 -1
  32. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  33. package/out-tsc/src/flow/types.js +0 -65
  34. package/out-tsc/src/flow/types.js.map +1 -1
  35. package/out-tsc/src/form/ArrayEditor.js +63 -117
  36. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  37. package/out-tsc/src/form/BaseListEditor.js +4 -3
  38. package/out-tsc/src/form/BaseListEditor.js.map +1 -1
  39. package/out-tsc/src/form/Checkbox.js +77 -24
  40. package/out-tsc/src/form/Checkbox.js.map +1 -1
  41. package/out-tsc/src/form/ColorPicker.js +28 -40
  42. package/out-tsc/src/form/ColorPicker.js.map +1 -1
  43. package/out-tsc/src/form/Completion.js +44 -53
  44. package/out-tsc/src/form/Completion.js.map +1 -1
  45. package/out-tsc/src/form/Compose.js +7 -8
  46. package/out-tsc/src/form/Compose.js.map +1 -1
  47. package/out-tsc/src/form/ContactSearch.js +3 -4
  48. package/out-tsc/src/form/ContactSearch.js.map +1 -1
  49. package/out-tsc/src/form/DatePicker.js +29 -36
  50. package/out-tsc/src/form/DatePicker.js.map +1 -1
  51. package/out-tsc/src/form/{FormField.js → FieldElement.js} +81 -53
  52. package/out-tsc/src/form/FieldElement.js.map +1 -0
  53. package/out-tsc/src/form/FieldRenderer.js +306 -0
  54. package/out-tsc/src/form/FieldRenderer.js.map +1 -0
  55. package/out-tsc/src/form/ImagePicker.js +122 -126
  56. package/out-tsc/src/form/ImagePicker.js.map +1 -1
  57. package/out-tsc/src/form/KeyValueEditor.js +41 -37
  58. package/out-tsc/src/form/KeyValueEditor.js.map +1 -1
  59. package/out-tsc/src/form/MessageEditor.js +55 -63
  60. package/out-tsc/src/form/MessageEditor.js.map +1 -1
  61. package/out-tsc/src/form/TembaSlider.js +3 -3
  62. package/out-tsc/src/form/TembaSlider.js.map +1 -1
  63. package/out-tsc/src/form/TemplateEditor.js +3 -3
  64. package/out-tsc/src/form/TemplateEditor.js.map +1 -1
  65. package/out-tsc/src/form/TextInput.js +23 -27
  66. package/out-tsc/src/form/TextInput.js.map +1 -1
  67. package/out-tsc/src/form/select/Select.js +57 -35
  68. package/out-tsc/src/form/select/Select.js.map +1 -1
  69. package/out-tsc/src/form/select/UserSelect.js +8 -9
  70. package/out-tsc/src/form/select/UserSelect.js.map +1 -1
  71. package/out-tsc/src/form/select/WorkspaceSelect.js +7 -8
  72. package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -1
  73. package/out-tsc/src/live/ContactChat.js +62 -44
  74. package/out-tsc/src/live/ContactChat.js.map +1 -1
  75. package/out-tsc/src/live/ContactFieldEditor.js.map +1 -1
  76. package/out-tsc/src/markdown.js +13 -11
  77. package/out-tsc/src/markdown.js.map +1 -1
  78. package/out-tsc/temba-modules.js +3 -2
  79. package/out-tsc/temba-modules.js.map +1 -1
  80. package/out-tsc/test/ActionHelper.js +2 -0
  81. package/out-tsc/test/ActionHelper.js.map +1 -1
  82. package/out-tsc/test/NodeHelper.js +148 -0
  83. package/out-tsc/test/NodeHelper.js.map +1 -0
  84. package/out-tsc/test/actions/call_llm.test.js +103 -0
  85. package/out-tsc/test/actions/call_llm.test.js.map +1 -0
  86. package/out-tsc/test/nodes/split_by_llm_categorize.test.js +532 -0
  87. package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -0
  88. package/out-tsc/test/nodes/split_by_random.test.js +150 -0
  89. package/out-tsc/test/nodes/split_by_random.test.js.map +1 -0
  90. package/out-tsc/test/nodes/wait_for_digits.test.js +150 -0
  91. package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -0
  92. package/out-tsc/test/nodes/wait_for_response.test.js +171 -0
  93. package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -0
  94. package/out-tsc/test/temba-add-input-labels.test.js +70 -0
  95. package/out-tsc/test/temba-add-input-labels.test.js.map +1 -0
  96. package/out-tsc/test/temba-checkbox.test.js +16 -0
  97. package/out-tsc/test/temba-checkbox.test.js.map +1 -1
  98. package/out-tsc/test/temba-field-renderer.test.js +296 -0
  99. package/out-tsc/test/temba-field-renderer.test.js.map +1 -0
  100. package/out-tsc/test/temba-integration-markdown.test.js +2 -4
  101. package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
  102. package/out-tsc/test/temba-markdown.test.js +1 -1
  103. package/out-tsc/test/temba-markdown.test.js.map +1 -1
  104. package/out-tsc/test/temba-node-editor.test.js +400 -0
  105. package/out-tsc/test/temba-node-editor.test.js.map +1 -1
  106. package/out-tsc/test/temba-select.test.js +6 -3
  107. package/out-tsc/test/temba-select.test.js.map +1 -1
  108. package/out-tsc/test/temba-slider.test.js +0 -1
  109. package/out-tsc/test/temba-slider.test.js.map +1 -1
  110. package/out-tsc/test/temba-webchat.test.js +1 -1
  111. package/out-tsc/test/temba-webchat.test.js.map +1 -1
  112. package/package.json +1 -1
  113. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  114. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  115. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  116. package/screenshots/truth/actions/call_llm/editor/information-extraction.png +0 -0
  117. package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
  118. package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
  119. package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
  120. package/screenshots/truth/actions/call_llm/render/information-extraction.png +0 -0
  121. package/screenshots/truth/actions/call_llm/render/sentiment-analysis.png +0 -0
  122. package/screenshots/truth/actions/call_llm/render/summarization.png +0 -0
  123. package/screenshots/truth/actions/call_llm/render/translation-task.png +0 -0
  124. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  125. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  126. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  127. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  128. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  129. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  130. package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
  131. package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
  132. package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
  133. package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
  134. package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
  135. package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
  136. package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
  137. package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
  138. package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
  139. package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
  140. package/screenshots/truth/checkbox/checkbox-no-label-no-background-hover.png +0 -0
  141. package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
  142. package/screenshots/truth/checkbox/checked.png +0 -0
  143. package/screenshots/truth/checkbox/default.png +0 -0
  144. package/screenshots/truth/colorpicker/default.png +0 -0
  145. package/screenshots/truth/colorpicker/focused.png +0 -0
  146. package/screenshots/truth/colorpicker/initialized.png +0 -0
  147. package/screenshots/truth/colorpicker/selected.png +0 -0
  148. package/screenshots/truth/editor/router.png +0 -0
  149. package/screenshots/truth/editor/send_msg.png +0 -0
  150. package/screenshots/truth/editor/set_contact_language.png +0 -0
  151. package/screenshots/truth/editor/set_contact_name.png +0 -0
  152. package/screenshots/truth/editor/set_run_result.png +0 -0
  153. package/screenshots/truth/editor/wait.png +0 -0
  154. package/screenshots/truth/field-renderer/checkbox-checked.png +0 -0
  155. package/screenshots/truth/field-renderer/checkbox-unchecked.png +0 -0
  156. package/screenshots/truth/field-renderer/checkbox-with-errors.png +0 -0
  157. package/screenshots/truth/field-renderer/context-comparison.png +0 -0
  158. package/screenshots/truth/field-renderer/key-value-with-label.png +0 -0
  159. package/screenshots/truth/field-renderer/message-editor-with-label.png +0 -0
  160. package/screenshots/truth/field-renderer/select-multi.png +0 -0
  161. package/screenshots/truth/field-renderer/select-no-label.png +0 -0
  162. package/screenshots/truth/field-renderer/select-with-label.png +0 -0
  163. package/screenshots/truth/field-renderer/text-evaluated.png +0 -0
  164. package/screenshots/truth/field-renderer/text-no-label.png +0 -0
  165. package/screenshots/truth/field-renderer/text-with-errors.png +0 -0
  166. package/screenshots/truth/field-renderer/text-with-label.png +0 -0
  167. package/screenshots/truth/field-renderer/textarea-evaluated.png +0 -0
  168. package/screenshots/truth/field-renderer/textarea-with-label.png +0 -0
  169. package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
  170. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  171. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  172. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  173. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  174. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  175. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  176. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  177. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  178. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  179. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  180. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  181. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  182. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  183. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  184. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  185. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  186. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  187. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  188. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  189. package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
  190. package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
  191. package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
  192. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  193. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  194. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  195. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
  196. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  197. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  198. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  199. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  200. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  201. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  202. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  203. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  204. package/screenshots/truth/omnibox/selected.png +0 -0
  205. package/screenshots/truth/run-list/basic.png +0 -0
  206. package/screenshots/truth/select/functions.png +0 -0
  207. package/screenshots/truth/select/multi-with-endpoint.png +0 -0
  208. package/screenshots/truth/select/search-enabled.png +0 -0
  209. package/src/events.ts +12 -6
  210. package/src/excellent/helpers.ts +2 -2
  211. package/src/flow/CanvasNode.ts +22 -1
  212. package/src/flow/Editor.ts +12 -1
  213. package/src/flow/NodeEditor.ts +186 -374
  214. package/src/flow/actions/add_input_labels.ts +45 -0
  215. package/src/flow/actions/call_llm.ts +57 -3
  216. package/src/flow/actions/call_webhook.ts +1 -1
  217. package/src/flow/actions/open_ticket.ts +74 -3
  218. package/src/flow/actions/set_run_result.ts +83 -0
  219. package/src/flow/config.ts +4 -0
  220. package/src/flow/nodes/split_by_llm_categorize.ts +277 -0
  221. package/src/flow/nodes/split_by_ticket.ts +19 -0
  222. package/src/flow/nodes/wait_for_response.ts +28 -1
  223. package/src/flow/types.ts +26 -127
  224. package/src/form/ArrayEditor.ts +79 -139
  225. package/src/form/BaseListEditor.ts +4 -4
  226. package/src/form/Checkbox.ts +81 -24
  227. package/src/form/ColorPicker.ts +31 -43
  228. package/src/form/Completion.ts +49 -56
  229. package/src/form/Compose.ts +8 -8
  230. package/src/form/ContactSearch.ts +3 -4
  231. package/src/form/DatePicker.ts +32 -38
  232. package/src/form/{FormField.ts → FieldElement.ts} +108 -55
  233. package/src/form/FieldRenderer.ts +466 -0
  234. package/src/form/ImagePicker.ts +107 -110
  235. package/src/form/KeyValueEditor.ts +43 -39
  236. package/src/form/MessageEditor.ts +61 -67
  237. package/src/form/TembaSlider.ts +3 -3
  238. package/src/form/TemplateEditor.ts +3 -3
  239. package/src/form/TextInput.ts +26 -29
  240. package/src/form/select/Select.ts +63 -37
  241. package/src/form/select/UserSelect.ts +10 -11
  242. package/src/form/select/WorkspaceSelect.ts +9 -10
  243. package/src/live/ContactChat.ts +62 -47
  244. package/src/live/ContactFieldEditor.ts +2 -2
  245. package/src/markdown.ts +19 -11
  246. package/src/store/flow-definition.d.ts +5 -2
  247. package/static/api/labels.json +31 -0
  248. package/static/api/topics.json +24 -9
  249. package/static/api/users.json +35 -16
  250. package/static/css/temba-components.css +3 -3
  251. package/stress-test.js +18 -13
  252. package/temba-modules.ts +3 -2
  253. package/test/ActionHelper.ts +2 -0
  254. package/test/NodeHelper.ts +184 -0
  255. package/test/actions/call_llm.test.ts +137 -0
  256. package/test/nodes/README.md +78 -0
  257. package/test/nodes/split_by_llm_categorize.test.ts +698 -0
  258. package/test/nodes/split_by_random.test.ts +177 -0
  259. package/test/nodes/wait_for_digits.test.ts +176 -0
  260. package/test/nodes/wait_for_response.test.ts +206 -0
  261. package/test/temba-add-input-labels.test.ts +87 -0
  262. package/test/temba-checkbox.test.ts +26 -0
  263. package/test/temba-field-renderer.test.ts +482 -0
  264. package/test/temba-integration-markdown.test.ts +2 -4
  265. package/test/temba-markdown.test.ts +1 -1
  266. package/test/temba-node-editor.test.ts +496 -0
  267. package/test/temba-select.test.ts +6 -6
  268. package/test/temba-slider.test.ts +0 -1
  269. package/test/temba-webchat.test.ts +1 -1
  270. package/test-assets/contacts/history.json +7 -20
  271. package/test-assets/select/llms.json +18 -0
  272. package/web-dev-mock.mjs +96 -6
  273. package/web-dev-server.config.mjs +29 -7
  274. package/out-tsc/src/form/FormElement.js +0 -67
  275. package/out-tsc/src/form/FormElement.js.map +0 -1
  276. package/out-tsc/src/form/FormField.js.map +0 -1
  277. package/out-tsc/test/temba-formfield.test.js +0 -94
  278. package/out-tsc/test/temba-formfield.test.js.map +0 -1
  279. package/src/form/FormElement.ts +0 -69
  280. package/test/temba-flow-editor.test.ts.backup +0 -563
  281. package/test/temba-formfield.test.ts +0 -121
  282. package/test/temba-utils-index.test.ts.backup +0 -1737
@@ -5,7 +5,7 @@ import { property, state } from 'lit/decorators.js';
5
5
  import { getUrl, getClasses, fetchResults, postJSON } from '../../utils';
6
6
  import '../../display/Options';
7
7
  import '../../list/SortableList';
8
- import { FormElement } from '../../form/FormElement';
8
+ import { FieldElement } from '../../form/FieldElement';
9
9
  import { lru } from 'tiny-lru';
10
10
  import { CustomEventType } from '../../interfaces';
11
11
  import { renderCompletionOption, updateInputElementWithCompletion, executeCompletionQuery } from '../../excellent/helpers';
@@ -13,9 +13,11 @@ import { styleMap } from 'lit-html/directives/style-map.js';
13
13
  import { Icon } from '../../Icons';
14
14
  import { msg } from '@lit/localize';
15
15
  const LOOK_AHEAD = 20;
16
- export class Select extends FormElement {
16
+ export class Select extends FieldElement {
17
17
  static get styles() {
18
18
  return css `
19
+ ${super.styles}
20
+
19
21
  :host {
20
22
  --transition-speed: 0;
21
23
  font-family: var(--font-family);
@@ -198,6 +200,7 @@ export class Select extends FormElement {
198
200
 
199
201
  .multi temba-sortable-list {
200
202
  margin: 0 !important;
203
+ flex-grow: 1;
201
204
  }
202
205
 
203
206
  input {
@@ -231,6 +234,12 @@ export class Select extends FormElement {
231
234
 
232
235
  .multi .input-wrapper {
233
236
  margin-left: 2px !important;
237
+ margin-right: 2px !important;
238
+ margin-top: 2px;
239
+ margin-bottom: 2px;
240
+ flex-shrink: 0;
241
+ min-width: 100px;
242
+ align-self: center;
234
243
  }
235
244
 
236
245
  .input-wrapper:focus-within .placeholder {
@@ -266,11 +275,6 @@ export class Select extends FormElement {
266
275
  box-shadow: none !important;
267
276
  }
268
277
 
269
- .multi .input-wrapper {
270
- flex-shrink: 0;
271
- min-width: 100px;
272
- }
273
-
274
278
  .input-wrapper .searchbox {
275
279
  }
276
280
 
@@ -286,6 +290,17 @@ export class Select extends FormElement {
286
290
  margin-left: 6px;
287
291
  }
288
292
 
293
+ .empty .placeholder {
294
+ display: block;
295
+ }
296
+
297
+ .multi .placeholder {
298
+ display: block;
299
+ margin: 2px 2px;
300
+ padding: 2px 8px;
301
+ align-self: center;
302
+ }
303
+
289
304
  .footer {
290
305
  padding: 5px 10px;
291
306
  background: var(--color-primary-light);
@@ -298,7 +313,7 @@ export class Select extends FormElement {
298
313
  .small {
299
314
  --temba-select-selected-padding: 6px;
300
315
  --temba-select-selected-line-height: 12px;
301
- --temba-select-selected-font-size: 12px;
316
+ --temba-select-selected-font-size: 14px;
302
317
  --temba-select-min-height: 2.28em;
303
318
  }
304
319
 
@@ -331,6 +346,14 @@ export class Select extends FormElement {
331
346
  }
332
347
  `;
333
348
  }
349
+ // Override the setter to ensure values is always an array
350
+ set values(newValues) {
351
+ this._values = Array.isArray(newValues) ? newValues : [];
352
+ this.requestUpdate('values');
353
+ }
354
+ get values() {
355
+ return this._values || [];
356
+ }
334
357
  constructor() {
335
358
  super();
336
359
  this.hiddenInputs = [];
@@ -361,8 +384,10 @@ export class Select extends FormElement {
361
384
  this.emails = false;
362
385
  this.flavor = 'default';
363
386
  this.infoText = '';
364
- this.values = [];
365
- this.getName = (option) => option[this.nameKey || 'name'];
387
+ this._values = [];
388
+ this.getName = (option) => {
389
+ return option[this.nameKey || 'name'];
390
+ };
366
391
  this.isMatch = this.isMatchDefault;
367
392
  this.getValue = (option) => option[this.valueKey || 'value'] || option.id;
368
393
  this.sortFunction = null;
@@ -377,14 +402,16 @@ export class Select extends FormElement {
377
402
  this.alphaSort = (a, b) => {
378
403
  // by default, all endpoint values are sorted by name
379
404
  if (this.endpoint) {
380
- return this.getName(a).localeCompare(this.getName(b));
405
+ return this.getNameInternal(a).localeCompare(this.getNameInternal(b));
381
406
  }
382
407
  return 0;
383
408
  };
384
409
  this.next = null;
385
410
  this.lruCache = lru(20, 60000);
386
411
  this.getNameInternal = (option) => {
387
- return this.getName(option);
412
+ return this.getName
413
+ ? this.getName(option)
414
+ : option[this.nameKey || 'name'] || '';
388
415
  };
389
416
  this.renderOptionDefault = this.renderOptionDefault.bind(this);
390
417
  this.renderSelectedItemDefault = this.renderSelectedItemDefault.bind(this);
@@ -396,7 +423,7 @@ export class Select extends FormElement {
396
423
  return options;
397
424
  }
398
425
  isMatchDefault(option, q) {
399
- const name = this.getName(option) || '';
426
+ const name = this.getNameInternal(option) || '';
400
427
  return name.toLowerCase().indexOf(q) > -1;
401
428
  }
402
429
  handleSlotChange() {
@@ -1164,7 +1191,7 @@ export class Select extends FormElement {
1164
1191
  name="${icon}"
1165
1192
  style="margin-right:0.5em;"
1166
1193
  ></temba-icon>`
1167
- : null}<span>${this.getName(option)}</span>
1194
+ : null}<span>${this.getNameInternal(option)}</span>
1168
1195
  </div>
1169
1196
  `;
1170
1197
  }
@@ -1282,11 +1309,13 @@ export class Select extends FormElement {
1282
1309
  }
1283
1310
  }
1284
1311
  }
1285
- render() {
1312
+ renderWidget() {
1286
1313
  const placeholder = this.values.length === 0 ? this.placeholder : '';
1287
- const placeholderDiv = html `
1288
- <div class="placeholder">${placeholder}</div>
1289
- `;
1314
+ // Single unified placeholder - shows when empty and (not focused OR not searchable)
1315
+ const shouldShowPlaceholder = this.values.length === 0 && (!this.focused || !this.searchable);
1316
+ const placeholderElement = shouldShowPlaceholder
1317
+ ? html `<div class="placeholder">${placeholder}</div>`
1318
+ : null;
1290
1319
  const clear = this.clearable && this.values.length > 0 && !this.isMultiMode
1291
1320
  ? html `<temba-icon
1292
1321
  name="${Icon.select_clear}"
@@ -1326,10 +1355,9 @@ export class Select extends FormElement {
1326
1355
  .value=${this.input}
1327
1356
  />
1328
1357
  <div id="anchor" style=${styleMap(anchorStyles)}></div>
1329
- ${placeholderDiv}
1330
1358
  </div>
1331
1359
  `
1332
- : placeholderDiv;
1360
+ : null;
1333
1361
  const items = html `${!this.isMultiMode && !this.resolving ? input : null}
1334
1362
  ${this.isMultiMode && this.values.length > 1
1335
1363
  ? html `
@@ -1400,9 +1428,10 @@ export class Select extends FormElement {
1400
1428
  ${this.renderSelectedItem(selected)}
1401
1429
  </div>
1402
1430
  `)}
1431
+ ${this.searchable && this.focused ? input : null}
1403
1432
  </temba-sortable-list>
1404
1433
  `
1405
- : this.values.map((selected, index) => html `
1434
+ : html `${this.values.map((selected, index) => html `
1406
1435
  <div
1407
1436
  class="selected-item ${index === this.selectedIndex
1408
1437
  ? 'focused'
@@ -1449,18 +1478,9 @@ export class Select extends FormElement {
1449
1478
  : null}
1450
1479
  </div>
1451
1480
  `)}
1452
- ${this.isMultiMode ? input : null}`;
1481
+ ${this.isMultiMode && this.searchable && this.focused ? input : null}
1482
+ ${placeholderElement}`}`;
1453
1483
  return html `
1454
-
1455
- <temba-field
1456
- name=${this.name}
1457
- .label=${this.label}
1458
- .helpText=${this.helpText}
1459
- .errors=${this.errors}
1460
- .widgetOnly=${this.widgetOnly}
1461
- .hideErrors=${this.hideErrors}
1462
- ?disabled=${this.disabled}
1463
- >
1464
1484
  <slot></slot>
1465
1485
  <div class="wrapper-bg">
1466
1486
 
@@ -1544,8 +1564,10 @@ export class Select extends FormElement {
1544
1564
  </div>`
1545
1565
  : null}
1546
1566
  </temba-options>
1547
- </temba-field>
1548
- `;
1567
+ `;
1568
+ }
1569
+ render() {
1570
+ return this.renderField();
1549
1571
  }
1550
1572
  }
1551
1573
  __decorate([
@@ -1670,7 +1692,7 @@ __decorate([
1670
1692
  ], Select.prototype, "infoText", void 0);
1671
1693
  __decorate([
1672
1694
  property({ type: Array })
1673
- ], Select.prototype, "values", void 0);
1695
+ ], Select.prototype, "values", null);
1674
1696
  __decorate([
1675
1697
  property({ type: Object })
1676
1698
  ], Select.prototype, "selection", void 0);