@nyaruka/temba-components 0.130.4 → 0.131.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +10 -13
  2. package/demo/sortable-rules-demo.html +155 -0
  3. package/dist/temba-components.js +150 -159
  4. package/dist/temba-components.js.map +1 -1
  5. package/out-tsc/src/events.js.map +1 -1
  6. package/out-tsc/src/flow/CanvasNode.js +13 -7
  7. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  8. package/out-tsc/src/flow/actions/send_msg.js +1 -0
  9. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  10. package/out-tsc/src/flow/nodes/split_by_groups.js +149 -1
  11. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  12. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +1 -0
  13. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  14. package/out-tsc/src/flow/nodes/split_by_random.js +1 -0
  15. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  16. package/out-tsc/src/flow/nodes/wait_for_response.js +332 -137
  17. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  18. package/out-tsc/src/form/ArrayEditor.js +301 -30
  19. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  20. package/out-tsc/src/form/select/Omnibox.js +4 -0
  21. package/out-tsc/src/form/select/Omnibox.js.map +1 -1
  22. package/out-tsc/src/form/select/Select.js +21 -25
  23. package/out-tsc/src/form/select/Select.js.map +1 -1
  24. package/out-tsc/src/list/SortableList.js +214 -140
  25. package/out-tsc/src/list/SortableList.js.map +1 -1
  26. package/out-tsc/src/live/ContactChat.js +9 -5
  27. package/out-tsc/src/live/ContactChat.js.map +1 -1
  28. package/out-tsc/test/nodes/split_by_groups.test.js +130 -0
  29. package/out-tsc/test/nodes/split_by_groups.test.js.map +1 -0
  30. package/out-tsc/test/nodes/wait_for_response.test.js +522 -8
  31. package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
  32. package/out-tsc/test/temba-field-config.test.js +56 -0
  33. package/out-tsc/test/temba-field-config.test.js.map +1 -1
  34. package/package.json +1 -1
  35. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  36. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  37. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  38. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  39. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  40. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  41. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  42. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  43. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  44. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  45. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  46. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  47. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  48. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  49. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  50. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  51. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  52. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  53. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  54. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  55. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  56. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  57. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  58. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  59. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  60. package/screenshots/truth/editor/wait.png +0 -0
  61. package/screenshots/truth/field-renderer/select-with-label.png +0 -0
  62. package/screenshots/truth/list/fields-dragging.png +0 -0
  63. package/screenshots/truth/list/sortable-dragging.png +0 -0
  64. package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
  65. package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
  66. package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
  67. package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
  68. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  69. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  70. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  71. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  72. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  73. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  74. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  75. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  76. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  77. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  78. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  79. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  80. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  81. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  82. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  83. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  84. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  85. package/screenshots/truth/select/search-enabled.png +0 -0
  86. package/screenshots/truth/select/search-selected-focus.png +0 -0
  87. package/screenshots/truth/select/search-selected.png +0 -0
  88. package/screenshots/truth/templates/default.png +0 -0
  89. package/screenshots/truth/templates/unapproved.png +0 -0
  90. package/src/events.ts +6 -6
  91. package/src/flow/CanvasNode.ts +15 -13
  92. package/src/flow/actions/send_msg.ts +1 -0
  93. package/src/flow/nodes/split_by_groups.ts +190 -1
  94. package/src/flow/nodes/split_by_llm_categorize.ts +1 -0
  95. package/src/flow/nodes/split_by_random.ts +1 -0
  96. package/src/flow/nodes/wait_for_response.ts +424 -145
  97. package/src/form/ArrayEditor.ts +372 -30
  98. package/src/form/select/Omnibox.ts +3 -0
  99. package/src/form/select/Select.ts +24 -25
  100. package/src/list/SortableList.ts +250 -149
  101. package/src/live/ContactChat.ts +11 -5
  102. package/test/nodes/split_by_groups.test.ts +165 -0
  103. package/test/nodes/wait_for_response.test.ts +608 -8
  104. package/test/temba-field-config.test.ts +69 -0
@@ -150,5 +150,74 @@ describe('Field Configuration System', () => {
150
150
  // Expects 3 items: 2 initial items + 1 auto-generated empty item
151
151
  expect(items?.length).to.equal(3);
152
152
  });
153
+
154
+ it('should render with sortable list when sortable=true', async () => {
155
+ const itemConfig = {
156
+ operator: { type: 'text', label: 'Operator' },
157
+ value: { type: 'text', label: 'Value' }
158
+ };
159
+
160
+ const initialValue = [
161
+ { operator: 'equals', value: 'test' },
162
+ { operator: 'contains', value: 'example' }
163
+ ];
164
+
165
+ const el = await fixture(html`
166
+ <temba-array-editor
167
+ .value=${initialValue}
168
+ .itemConfig=${itemConfig}
169
+ .sortable=${true}
170
+ itemLabel="Rule"
171
+ ></temba-array-editor>
172
+ `);
173
+
174
+ await (el as any).updateComplete;
175
+
176
+ expect(el).to.exist;
177
+
178
+ // Should have a sortable list component
179
+ const sortableList = el.shadowRoot?.querySelector('temba-sortable-list');
180
+ expect(sortableList).to.exist;
181
+
182
+ // Should have sortable items with proper classes and IDs
183
+ const sortableItems = el.shadowRoot?.querySelectorAll('.sortable');
184
+ expect(sortableItems?.length).to.equal(2); // Only non-empty items should be sortable
185
+
186
+ // Each sortable item should have a unique ID
187
+ const firstItem = sortableItems?.[0] as HTMLElement;
188
+ const secondItem = sortableItems?.[1] as HTMLElement;
189
+ expect(firstItem?.id).to.equal('array-item-0');
190
+ expect(secondItem?.id).to.equal('array-item-1');
191
+ });
192
+
193
+ it('should not render sortable list when sortable=false', async () => {
194
+ const itemConfig = {
195
+ operator: { type: 'text', label: 'Operator' },
196
+ value: { type: 'text', label: 'Value' }
197
+ };
198
+
199
+ const initialValue = [{ operator: 'equals', value: 'test' }];
200
+
201
+ const el = await fixture(html`
202
+ <temba-array-editor
203
+ .value=${initialValue}
204
+ .itemConfig=${itemConfig}
205
+ .sortable=${false}
206
+ itemLabel="Rule"
207
+ ></temba-array-editor>
208
+ `);
209
+
210
+ await (el as any).updateComplete;
211
+
212
+ expect(el).to.exist;
213
+
214
+ // Should not have a sortable list component
215
+ const sortableList = el.shadowRoot?.querySelector('temba-sortable-list');
216
+ expect(sortableList).to.not.exist;
217
+
218
+ // Should have regular list container instead
219
+ const listContainer = el.shadowRoot?.querySelector('.list-items');
220
+ expect(listContainer).to.exist;
221
+ });
153
222
  });
154
223
  });