@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.
Files changed (262) hide show
  1. package/.github/copilot-instructions.md +181 -0
  2. package/.github/workflows/build.yml +3 -3
  3. package/.github/workflows/cla.yml +6 -6
  4. package/.github/workflows/copilot-setup-steps.yml +86 -0
  5. package/CHANGELOG.md +44 -0
  6. package/demo/drag-drop-demo.html +141 -0
  7. package/demo/index.html +57 -0
  8. package/demo/test-drag-drop.html +94 -0
  9. package/dist/locales/es.js +1 -0
  10. package/dist/locales/es.js.map +1 -1
  11. package/dist/locales/fr.js +1 -0
  12. package/dist/locales/fr.js.map +1 -1
  13. package/dist/locales/pt.js +1 -0
  14. package/dist/locales/pt.js.map +1 -1
  15. package/dist/temba-components.js +366 -247
  16. package/dist/temba-components.js.map +1 -1
  17. package/out-tsc/src/chart/TembaChart.js +81 -14
  18. package/out-tsc/src/chart/TembaChart.js.map +1 -1
  19. package/out-tsc/src/fields/FieldManager.js +27 -34
  20. package/out-tsc/src/fields/FieldManager.js.map +1 -1
  21. package/out-tsc/src/list/RunList.js +13 -8
  22. package/out-tsc/src/list/RunList.js.map +1 -1
  23. package/out-tsc/src/list/SortableList.js +257 -60
  24. package/out-tsc/src/list/SortableList.js.map +1 -1
  25. package/out-tsc/src/locales/es.js +1 -0
  26. package/out-tsc/src/locales/es.js.map +1 -1
  27. package/out-tsc/src/locales/fr.js +1 -0
  28. package/out-tsc/src/locales/fr.js.map +1 -1
  29. package/out-tsc/src/locales/pt.js +1 -0
  30. package/out-tsc/src/locales/pt.js.map +1 -1
  31. package/out-tsc/src/omnibox/Omnibox.js +1 -1
  32. package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
  33. package/out-tsc/src/options/Options.js +36 -13
  34. package/out-tsc/src/options/Options.js.map +1 -1
  35. package/out-tsc/src/select/Select.js +226 -43
  36. package/out-tsc/src/select/Select.js.map +1 -1
  37. package/out-tsc/src/store/AppState.js +3 -3
  38. package/out-tsc/src/store/AppState.js.map +1 -1
  39. package/out-tsc/src/utils/index.js +6 -1
  40. package/out-tsc/src/utils/index.js.map +1 -1
  41. package/out-tsc/src/vectoricon/VectorIcon.js +2 -1
  42. package/out-tsc/src/vectoricon/VectorIcon.js.map +1 -1
  43. package/out-tsc/src/webchat/WebChat.js +5 -2
  44. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  45. package/out-tsc/temba-modules.js +0 -2
  46. package/out-tsc/temba-modules.js.map +1 -1
  47. package/out-tsc/test/temba-appstate-language.test.js +176 -0
  48. package/out-tsc/test/temba-appstate-language.test.js.map +1 -0
  49. package/out-tsc/test/temba-chart.test.js +125 -0
  50. package/out-tsc/test/temba-chart.test.js.map +1 -1
  51. package/out-tsc/test/temba-dropdown.test.js +317 -0
  52. package/out-tsc/test/temba-dropdown.test.js.map +1 -0
  53. package/out-tsc/test/temba-flow-editor-node.test.js +273 -0
  54. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -0
  55. package/out-tsc/test/temba-flow-editor.test.js +244 -0
  56. package/out-tsc/test/temba-flow-editor.test.js.map +1 -0
  57. package/out-tsc/test/temba-flow-plumber.test.js +145 -0
  58. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -0
  59. package/out-tsc/test/temba-flow-render.test.js +171 -0
  60. package/out-tsc/test/temba-flow-render.test.js.map +1 -0
  61. package/out-tsc/test/temba-omnibox.test.js +2 -3
  62. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  63. package/out-tsc/test/temba-run-list.test.js +588 -0
  64. package/out-tsc/test/temba-run-list.test.js.map +1 -0
  65. package/out-tsc/test/temba-select.test.js +149 -52
  66. package/out-tsc/test/temba-select.test.js.map +1 -1
  67. package/out-tsc/test/temba-sortable-list.test.js +91 -15
  68. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  69. package/out-tsc/test/temba-toast.test.js +299 -0
  70. package/out-tsc/test/temba-toast.test.js.map +1 -0
  71. package/out-tsc/test/temba-utils-index.test.js +1178 -0
  72. package/out-tsc/test/temba-utils-index.test.js.map +1 -0
  73. package/out-tsc/test/temba-webchat-lightbox-fix.test.js +42 -0
  74. package/out-tsc/test/temba-webchat-lightbox-fix.test.js.map +1 -0
  75. package/out-tsc/test/temba-webchat.test.js +816 -0
  76. package/out-tsc/test/temba-webchat.test.js.map +1 -0
  77. package/out-tsc/test/utils.test.js +33 -1
  78. package/out-tsc/test/utils.test.js.map +1 -1
  79. package/package.json +6 -8
  80. package/screenshots/truth/alert/error.png +0 -0
  81. package/screenshots/truth/alert/info.png +0 -0
  82. package/screenshots/truth/alert/warning.png +0 -0
  83. package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
  84. package/screenshots/truth/checkbox/checked.png +0 -0
  85. package/screenshots/truth/checkbox/default.png +0 -0
  86. package/screenshots/truth/colorpicker/default.png +0 -0
  87. package/screenshots/truth/colorpicker/focused.png +0 -0
  88. package/screenshots/truth/colorpicker/initialized.png +0 -0
  89. package/screenshots/truth/colorpicker/selected.png +0 -0
  90. package/screenshots/truth/compose/attachments-tab.png +0 -0
  91. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  92. package/screenshots/truth/compose/attachments-with-files.png +0 -0
  93. package/screenshots/truth/compose/intial-text.png +0 -0
  94. package/screenshots/truth/compose/no-counter.png +0 -0
  95. package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
  96. package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
  97. package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
  98. package/screenshots/truth/contacts/badges.png +0 -0
  99. package/screenshots/truth/contacts/chat-failure.png +0 -0
  100. package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
  101. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  102. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  103. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  104. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  105. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  106. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  107. package/screenshots/truth/content-menu/button-no-items.png +0 -0
  108. package/screenshots/truth/content-menu/items-and-buttons.png +0 -0
  109. package/screenshots/truth/counter/summary.png +0 -0
  110. package/screenshots/truth/counter/text.png +0 -0
  111. package/screenshots/truth/counter/unicode-variables.png +0 -0
  112. package/screenshots/truth/counter/unicode.png +0 -0
  113. package/screenshots/truth/counter/variable.png +0 -0
  114. package/screenshots/truth/date/date-inline.png +0 -0
  115. package/screenshots/truth/date/date.png +0 -0
  116. package/screenshots/truth/date/datetime.png +0 -0
  117. package/screenshots/truth/date/duration.png +0 -0
  118. package/screenshots/truth/date/timedate.png +0 -0
  119. package/screenshots/truth/datepicker/date-truncated-time.png +0 -0
  120. package/screenshots/truth/datepicker/date.png +0 -0
  121. package/screenshots/truth/datepicker/initial-timezone.png +0 -0
  122. package/screenshots/truth/datepicker/updated-keyboard-date.png +0 -0
  123. package/screenshots/truth/dialog/focused.png +0 -0
  124. package/screenshots/truth/dropdown/after-blur.png +0 -0
  125. package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
  126. package/screenshots/truth/dropdown/custom-arrow-size.png +0 -0
  127. package/screenshots/truth/dropdown/default.png +0 -0
  128. package/screenshots/truth/dropdown/narrow-toggle.png +0 -0
  129. package/screenshots/truth/dropdown/no-mask.png +0 -0
  130. package/screenshots/truth/dropdown/opened.png +0 -0
  131. package/screenshots/truth/dropdown/positioned.png +0 -0
  132. package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
  133. package/screenshots/truth/dropdown/with-mask.png +0 -0
  134. package/screenshots/truth/flow/editor-basic.png +0 -0
  135. package/screenshots/truth/label/custom.png +0 -0
  136. package/screenshots/truth/label/danger.png +0 -0
  137. package/screenshots/truth/label/dark.png +0 -0
  138. package/screenshots/truth/label/default-icon.png +0 -0
  139. package/screenshots/truth/label/no-icon.png +0 -0
  140. package/screenshots/truth/label/primary.png +0 -0
  141. package/screenshots/truth/label/secondary.png +0 -0
  142. package/screenshots/truth/label/shadow.png +0 -0
  143. package/screenshots/truth/label/tertiary.png +0 -0
  144. package/screenshots/truth/lightbox/img-zoomed.png +0 -0
  145. package/screenshots/truth/list/fields-dragging.png +0 -0
  146. package/screenshots/truth/list/fields-filtered.png +0 -0
  147. package/screenshots/truth/list/fields-hovered.png +0 -0
  148. package/screenshots/truth/list/fields.png +0 -0
  149. package/screenshots/truth/list/items-selected.png +0 -0
  150. package/screenshots/truth/list/items-updated.png +0 -0
  151. package/screenshots/truth/list/items.png +0 -0
  152. package/screenshots/truth/list/sortable-dragging.png +0 -0
  153. package/screenshots/truth/list/sortable-dropped.png +0 -0
  154. package/screenshots/truth/list/sortable.png +0 -0
  155. package/screenshots/truth/menu/menu-focused-with items.png +0 -0
  156. package/screenshots/truth/menu/menu-refresh-1.png +0 -0
  157. package/screenshots/truth/menu/menu-refresh-2.png +0 -0
  158. package/screenshots/truth/menu/menu-root.png +0 -0
  159. package/screenshots/truth/menu/menu-submenu.png +0 -0
  160. package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
  161. package/screenshots/truth/menu/menu-tasks.png +0 -0
  162. package/screenshots/truth/modax/form.png +0 -0
  163. package/screenshots/truth/modax/simple.png +0 -0
  164. package/screenshots/truth/omnibox/selected.png +0 -0
  165. package/screenshots/truth/options/block.png +0 -0
  166. package/screenshots/truth/run-list/basic.png +0 -0
  167. package/screenshots/truth/select/disabled-multi-selection.png +0 -0
  168. package/screenshots/truth/select/disabled-selection.png +0 -0
  169. package/screenshots/truth/select/disabled.png +0 -0
  170. package/screenshots/truth/select/embedded.png +0 -0
  171. package/screenshots/truth/select/empty-options.png +0 -0
  172. package/screenshots/truth/select/expression-selected.png +0 -0
  173. package/screenshots/truth/select/expressions.png +0 -0
  174. package/screenshots/truth/select/functions.png +0 -0
  175. package/screenshots/truth/select/local-options.png +0 -0
  176. package/screenshots/truth/select/multi-reorder-final.png +0 -0
  177. package/screenshots/truth/select/multi-reorder-initial.png +0 -0
  178. package/screenshots/truth/select/multi-with-endpoint.png +0 -0
  179. package/screenshots/truth/select/multiple-initial-values.png +0 -0
  180. package/screenshots/truth/select/remote-options.png +0 -0
  181. package/screenshots/truth/select/search-enabled.png +0 -0
  182. package/screenshots/truth/select/search-multi-no-matches.png +0 -0
  183. package/screenshots/truth/select/search-selected-focus.png +0 -0
  184. package/screenshots/truth/select/search-selected.png +0 -0
  185. package/screenshots/truth/select/search-with-selected.png +0 -0
  186. package/screenshots/truth/select/searching.png +0 -0
  187. package/screenshots/truth/select/selected-multi-maxitems-reached.png +0 -0
  188. package/screenshots/truth/select/selected-multi.png +0 -0
  189. package/screenshots/truth/select/selected-single.png +0 -0
  190. package/screenshots/truth/select/selection-clearable.png +0 -0
  191. package/screenshots/truth/select/static-initial-value.png +0 -0
  192. package/screenshots/truth/select/static-initial-via-selected.png +0 -0
  193. package/screenshots/truth/select/truncated-selection.png +0 -0
  194. package/screenshots/truth/select/with-placeholder.png +0 -0
  195. package/screenshots/truth/select/without-placeholder.png +0 -0
  196. package/screenshots/truth/slider/custom-min-custom-max-valid-value.png +0 -0
  197. package/screenshots/truth/slider/custom-min-default-max-no-value.png +0 -0
  198. package/screenshots/truth/slider/default-min-custom-max-no-value.png +0 -0
  199. package/screenshots/truth/slider/default-min-default-max-invalid-value.png +0 -0
  200. package/screenshots/truth/slider/default-min-default-max-valid-value.png +0 -0
  201. package/screenshots/truth/slider/update-slider-on-value-change.png +0 -0
  202. package/screenshots/truth/templates/default.png +0 -0
  203. package/screenshots/truth/templates/unapproved.png +0 -0
  204. package/screenshots/truth/textinput/input-disabled.png +0 -0
  205. package/screenshots/truth/textinput/input-focused.png +0 -0
  206. package/screenshots/truth/textinput/input-form.png +0 -0
  207. package/screenshots/truth/textinput/input-inserted.png +0 -0
  208. package/screenshots/truth/textinput/input-placeholder.png +0 -0
  209. package/screenshots/truth/textinput/input-updated.png +0 -0
  210. package/screenshots/truth/textinput/input.png +0 -0
  211. package/screenshots/truth/textinput/textarea-focused.png +0 -0
  212. package/screenshots/truth/textinput/textarea.png +0 -0
  213. package/screenshots/truth/tip/bottom.png +0 -0
  214. package/screenshots/truth/tip/left.png +0 -0
  215. package/screenshots/truth/tip/right.png +0 -0
  216. package/screenshots/truth/tip/top.png +0 -0
  217. package/screenshots/truth/webchat/closed-widget.png +0 -0
  218. package/screenshots/truth/webchat/connected-state.png +0 -0
  219. package/screenshots/truth/webchat/connecting-state.png +0 -0
  220. package/screenshots/truth/webchat/disconnected-state.png +0 -0
  221. package/screenshots/truth/webchat/opened-widget.png +0 -0
  222. package/src/chart/TembaChart.ts +86 -15
  223. package/src/fields/FieldManager.ts +30 -38
  224. package/src/list/RunList.ts +11 -8
  225. package/src/list/SortableList.ts +291 -67
  226. package/src/locales/es.ts +1 -0
  227. package/src/locales/fr.ts +1 -0
  228. package/src/locales/pt.ts +1 -0
  229. package/src/omnibox/Omnibox.ts +1 -1
  230. package/src/options/Options.ts +38 -13
  231. package/src/select/Select.ts +245 -47
  232. package/src/store/AppState.ts +3 -3
  233. package/src/utils/index.ts +17 -5
  234. package/src/vectoricon/VectorIcon.ts +2 -1
  235. package/src/webchat/WebChat.ts +5 -2
  236. package/temba-modules.ts +0 -2
  237. package/test/temba-appstate-language.test.ts +218 -0
  238. package/test/temba-chart.test.ts +161 -1
  239. package/test/temba-dropdown.test.ts +444 -0
  240. package/test/temba-flow-editor-node.test.ts +344 -0
  241. package/test/temba-flow-editor.test.ts +301 -0
  242. package/test/temba-flow-plumber.test.ts +189 -0
  243. package/test/temba-flow-render.test.ts +220 -0
  244. package/test/temba-omnibox.test.ts +2 -3
  245. package/test/temba-run-list.test.ts +774 -0
  246. package/test/temba-select.test.ts +206 -78
  247. package/test/temba-sortable-list.test.ts +108 -15
  248. package/test/temba-toast.test.ts +386 -0
  249. package/test/temba-utils-index.test.ts +1547 -0
  250. package/test/temba-webchat-lightbox-fix.test.ts +57 -0
  251. package/test/temba-webchat.test.ts +1095 -0
  252. package/test/utils.test.ts +56 -2
  253. package/test-assets/list/flow-results.json +17 -0
  254. package/test-assets/list/runs.json +126 -0
  255. package/test-assets/style.css +23 -0
  256. package/web-test-runner.config.mjs +33 -7
  257. package/xliff/es.xlf +3 -0
  258. package/xliff/fr.xlf +3 -0
  259. package/xliff/pt.xlf +3 -0
  260. package/out-tsc/src/outboxmonitor/OutboxMonitor.js +0 -136
  261. package/out-tsc/src/outboxmonitor/OutboxMonitor.js.map +0 -1
  262. package/src/outboxmonitor/OutboxMonitor.ts +0 -148
@@ -0,0 +1,181 @@
1
+ # Copilot Development Instructions
2
+
3
+ ## Package Management
4
+
5
+ We use **yarn** for package management. Always use yarn commands instead of npm:
6
+
7
+ ```bash
8
+ # Install dependencies
9
+ yarn install
10
+
11
+ # Add new dependencies
12
+ yarn add <package-name>
13
+
14
+ # Add dev dependencies
15
+ yarn add -D <package-name>
16
+ ```
17
+
18
+ ## Testing
19
+
20
+ All tests are run using:
21
+
22
+ ```bash
23
+ yarn test
24
+ ```
25
+
26
+ To check for coverage, use:
27
+
28
+ ```bash
29
+ yarn test --coverage
30
+ ```
31
+
32
+
33
+ ### Isolating Tests for Quicker Development ###
34
+ You also can run an idividual test file to speed up development:
35
+
36
+ ```bash
37
+ yarn test test/temba-textinput.test.ts
38
+ ```
39
+
40
+ You can isolate a specific test within a file you are working to speed things up by updating the method in the file from it(...) to it.only(...)
41
+
42
+ For example:
43
+ ```typescript
44
+ it('can select a single option', async () => {...});
45
+ ```
46
+ becomes..
47
+ ```typescript
48
+ it.only('can select a single option', async () => {...});
49
+ ```
50
+
51
+ By doing this and only running the individual test file, you can drastically speed up iteration while running tests.
52
+
53
+ ### Validation ###
54
+
55
+ Before a PR is ready it must pass validation checks for linting, formatting, and tests. This will also report coverage and you need to manually verify coverage does not drop.
56
+
57
+ ```bash
58
+ yarn validate
59
+ ```
60
+
61
+ ### Making commits
62
+
63
+ Before committing always run `yarn precommit` and include any changes it makes.
64
+
65
+ ### Test Coverage Requirements
66
+
67
+ - **100% code coverage** is expected for all code we touch
68
+ - The aim is to maintain complete test coverage across the codebase
69
+ - When modifying existing code, ensure all changed lines are covered by tests
70
+ - When adding new features, write comprehensive tests that cover all reachable code paths
71
+ - Never add tests to try to test unreachable or dead code, instead make a comment in the dead scope that it is unreachable
72
+
73
+ ### Test Structure
74
+
75
+ Tests live under the `/test` directory and follow these patterns:
76
+
77
+ 1. **Import required testing utilities:**
78
+
79
+ ```typescript
80
+ import { fixture, assert } from '@open-wc/testing';
81
+ import { assertScreenshot, getClip, getComponent } from './utils.test';
82
+ ```
83
+
84
+ 2. **Test file naming:** Use the pattern `temba-{component}.test.ts`
85
+
86
+ 3. **Test organization:** Use `describe()` blocks for component grouping and `it()` for individual test cases
87
+
88
+ 4. **Test methodology:** These are ui based tests, so whenever possbile, the test should be written from the user's perspective. In other words, you should instrument a click in the browser to test behavior as a user would instead of calling instance methods on components. Instance method calling can be appropriate at times but should be used sparingly. For example, use the mouseClickElement() test method or the methods in src/untyped.d.ts for pressing keys, typing, using the mouse, etc.
89
+
90
+ 5. **Example Test:** A good example test to model after is `temba-textinput.test.ts`
91
+
92
+ ### Screenshot Testing
93
+
94
+ This project includes visual regression testing through screenshot comparison:
95
+
96
+ #### How Screenshot Tests Work
97
+
98
+ - Screenshots are captured during test execution using Puppeteer/Chromium
99
+ - "Truth" images are stored in `/screenshots/truth/` directory
100
+ - Test screenshots are compared pixel-by-pixel against truth images
101
+ - Failed comparisons generate diff images showing visual changes
102
+
103
+ #### Screenshot Test Implementation
104
+
105
+ ```typescript
106
+ // Take a screenshot of a component
107
+ await assertScreenshot('component/state-name', clipRegion);
108
+
109
+ // Get clipping region for a component
110
+ const clip = getClip(element);
111
+
112
+ // Custom clip adjustments if needed
113
+ const customClip = getClip(element);
114
+ customClip.width += 20;
115
+ customClip.height += 10;
116
+ ```
117
+
118
+ #### Critical Test Ordering
119
+
120
+ **Tests must validate expected values FIRST, then screenshots:**
121
+
122
+ ```typescript
123
+ it('validates component behavior', async () => {
124
+ const component = await getComponent('temba-example', { prop: 'value' });
125
+
126
+ // 1. FIRST: Test expected values and behavior
127
+ assert.instanceOf(component, ExampleComponent);
128
+ expect(component.prop).to.equal('value');
129
+ expect(component.textContent).to.contain('expected text');
130
+
131
+ // 2. SECOND: Take screenshot for visual verification
132
+ await assertScreenshot('example/state', getClip(component));
133
+ });
134
+ ```
135
+
136
+ This ordering ensures:
137
+
138
+ - Functional correctness is verified before visual verification
139
+ - Failed functional tests provide clearer debugging information
140
+ - Screenshot tests serve as additional visual regression protection
141
+
142
+ #### Screenshot Test Best Practices
143
+
144
+ - Use descriptive names: `'component/specific-state'` not `'test1'`
145
+ - Include sufficient context in clip regions to show component state
146
+ - Adjust clip regions when components have dynamic sizing
147
+ - Group related screenshots in subdirectories (e.g., `tip/left`, `tip/right`)
148
+
149
+ ## Development Workflow
150
+
151
+ 1. **Install dependencies:** `yarn install`
152
+ 2. **Start development server:** `yarn start`
153
+ 3. **Run tests during development:** `yarn test`
154
+ 4. **Pre-commit checks before committing:** `yarn pre-commit`
155
+ 5. **Validate changes:** `yarn validate`
156
+ 6. **Check Coverage:** Once validated, check for 100% coverage
157
+
158
+ ## Code Quality
159
+
160
+ - Follow existing TypeScript patterns in the codebase
161
+ - Use ESLint and Prettier configurations (automatically enforced)
162
+ - Write descriptive test names and clear assertions
163
+ - Ensure all modified code paths have corresponding test coverage
164
+
165
+ ## Formatting
166
+
167
+ - We use prettier for formatting, review the settings in .prettierrc
168
+ - When commmenting, if it is more than one sentence use standard case and punctuation, however for short comments, all lowercase is preferred
169
+
170
+ ## Component Development
171
+
172
+ When creating or modifying components:
173
+
174
+ 1. Create/update the component implementation
175
+ 2. Write comprehensive unit tests covering all functionality
176
+ 3. Add screenshot tests for visual states
177
+ 4. Verify 100% coverage of modified code
178
+ 5. Run full test suite to ensure no regressions
179
+ 6. Make sure building for production yields no errors
180
+
181
+ Remember: The goal is robust, well-tested components with both functional and visual verification.
@@ -1,4 +1,4 @@
1
- name: 'build'
1
+ name: 'build'
2
2
 
3
3
  on: [push]
4
4
 
@@ -9,14 +9,14 @@ jobs:
9
9
  - name: Set Timezone
10
10
  uses: szenius/set-timezone@v2.0
11
11
  with:
12
- timezoneLinux: "UTC"
12
+ timezoneLinux: 'UTC'
13
13
  - name: Checkout (GitHub)
14
14
  uses: actions/checkout@v4
15
15
  - run: docker network create --driver bridge textit_default
16
16
  - name: Build and run dev container task
17
17
  uses: devcontainers/ci@v0.3
18
18
  with:
19
- runCmd: yarn test
19
+ runCmd: yarn validate
20
20
  push: never
21
21
  env: |
22
22
  CI=true
@@ -1,25 +1,25 @@
1
- name: "CLA Assistant"
1
+ name: 'CLA Assistant'
2
2
  on:
3
3
  issue_comment:
4
4
  types: [created]
5
5
  pull_request_target:
6
- types: [opened,closed,synchronize]
6
+ types: [opened, closed, synchronize]
7
7
 
8
8
  jobs:
9
9
  CLAssistant:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - name: "CLA Assistant"
12
+ - name: 'CLA Assistant'
13
13
  if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
14
14
  # Beta Release
15
- uses: contributor-assistant/github-action@v2.2.0
15
+ uses: contributor-assistant/github-action@v2.6.1
16
16
  env:
17
17
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18
- PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_TOKEN }}
18
+ PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_TOKEN }}
19
19
  with:
20
20
  path-to-signatures: 'signatures/version1/cla.json'
21
21
  path-to-document: 'https://github.com/nyaruka/license/blob/main/TextIt_CLA.md'
22
22
  branch: 'main'
23
- allowlist: bot*
23
+ allowlist: bot*,*copilot*,*github*
24
24
  remote-organization-name: 'nyaruka'
25
25
  remote-repository-name: 'legal'
@@ -0,0 +1,86 @@
1
+ name: 'Copilot Setup Steps'
2
+
3
+ # Triggers: Run on pull requests and pushes to prepare environment for agent tasks
4
+ on:
5
+ pull_request:
6
+ push:
7
+
8
+ jobs:
9
+ copilot-setup-steps:
10
+ # Only run when push is initiated by the Copilot agent (GitHub Actions bot)
11
+ # This avoids unnecessary runs on regular developer pushes
12
+ if: github.actor == 'github-actions[bot]'
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ # Checkout the repository code
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ # Setup Node.js environment with version matching the project (Node.js 20)
21
+ - name: Setup Node.js
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: '20'
25
+
26
+ # Setup Chrome browser for Puppeteer tests to avoid firewall issues
27
+ # This uses the official Chrome setup that handles firewall restrictions
28
+ - name: Setup Chrome
29
+ uses: browser-actions/setup-chrome@latest
30
+ with:
31
+ chrome-version: stable
32
+
33
+ # Cache yarn dependencies to speed up future runs
34
+ # Uses yarn.lock as the cache key for dependency consistency
35
+ - name: Cache yarn dependencies
36
+ uses: actions/cache@v4
37
+ with:
38
+ path: |
39
+ ~/.yarn
40
+ node_modules
41
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
42
+ restore-keys: |
43
+ ${{ runner.os }}-yarn-
44
+
45
+ # Cache Puppeteer browsers to avoid repeated downloads
46
+ - name: Cache Puppeteer browsers
47
+ uses: actions/cache@v4
48
+ with:
49
+ path: |
50
+ ~/.cache/puppeteer
51
+ node_modules/.cache/puppeteer
52
+ key: ${{ runner.os }}-puppeteer-${{ hashFiles('**/yarn.lock') }}
53
+ restore-keys: |
54
+ ${{ runner.os }}-puppeteer-
55
+
56
+ # Install project dependencies including Puppeteer with Chromium
57
+ # Now allows Puppeteer to download Chromium since we handle firewall issues
58
+ - name: Install dependencies
59
+ run: yarn install
60
+ env:
61
+ # Set Puppeteer to use system Chrome if available to avoid downloads
62
+ PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
63
+
64
+ # Pre-build the project to warm up the environment
65
+ # This compiles TypeScript, processes SVG icons, and creates distribution files
66
+ # - name: Build project
67
+ # run: yarn build
68
+
69
+ # Run tests to ensure Puppeteer setup works correctly
70
+ # This validates that the browser dependencies are properly configured
71
+ # - name: Validate Puppeteer setup
72
+ # run: yarn test --reporter=summary
73
+ # env:
74
+ # PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
75
+
76
+ # Cache the built output to speed up subsequent operations
77
+ # - name: Cache build output
78
+ # uses: actions/cache@v4
79
+ # with:
80
+ # path: |
81
+ # dist
82
+ # out-tsc
83
+ # static/svg/index.svg
84
+ # key: ${{ runner.os }}-build-${{ github.sha }}
85
+ # restore-keys: |
86
+ # ${{ runner.os }}-build-
package/CHANGELOG.md CHANGED
@@ -4,8 +4,52 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ #### [v0.124.0](https://github.com/nyaruka/temba-components/compare/v0.123.0...v0.124.0)
8
+
9
+ - Add drag and drop reordering to multi-select components [`#546`](https://github.com/nyaruka/temba-components/pull/546)
10
+ - Add comprehensive test coverage for flow components [`#548`](https://github.com/nyaruka/temba-components/pull/548)
11
+ - Not sure this addresses the intermittent WebChat test failure, but I fundamentally agree with the changes anyways. [`#544`](https://github.com/nyaruka/temba-components/pull/544)
12
+ - Add comprehensive tests for flow components achieving 93.97% coverage [`3261100`](https://github.com/nyaruka/temba-components/commit/32611005a53f5ccac36b88cd50d88ed507605b6b)
13
+ - Implement new drag and drop behavior as requested - hide dragged items and fire events on drop only [`f7daecf`](https://github.com/nyaruka/temba-components/commit/f7daecf0c6737ddbecf85a4f3f726d94ffee08b8)
14
+ - Refactor SortableList to fix drag and drop reordering logic [`4b0a901`](https://github.com/nyaruka/temba-components/commit/4b0a901c7223dcefbed9eec888493b8e322c561f)
15
+
16
+ #### [v0.123.0](https://github.com/nyaruka/temba-components/compare/v0.122.0...v0.123.0)
17
+
18
+ > 4 June 2025
19
+
20
+ - Update commands for test and validate [`#543`](https://github.com/nyaruka/temba-components/pull/543)
21
+ - Add comprehensive test coverage for RunList component [`#531`](https://github.com/nyaruka/temba-components/pull/531)
22
+ - Fix screenshot tests for Copilot environment with adaptive threshold [`#538`](https://github.com/nyaruka/temba-components/pull/538)
23
+ - Fix language setting persistence when opening new flows [`#541`](https://github.com/nyaruka/temba-components/pull/541)
24
+ - Fix ESLint TypeScript version compatibility warning [`#536`](https://github.com/nyaruka/temba-components/pull/536)
25
+ - Switch format command [`#534`](https://github.com/nyaruka/temba-components/pull/534)
26
+ - Fix typescript errors, enforce build and linting for tests [`#532`](https://github.com/nyaruka/temba-components/pull/532)
27
+ - Update copilot-instructions.md [`#533`](https://github.com/nyaruka/temba-components/pull/533)
28
+ - Add comprehensive test coverage for utils/index.ts - achieve 100% function coverage [`#525`](https://github.com/nyaruka/temba-components/pull/525)
29
+ - Update copilot-instructions.md [`#529`](https://github.com/nyaruka/temba-components/pull/529)
30
+ - Update copilot-instructions.md [`#528`](https://github.com/nyaruka/temba-components/pull/528)
31
+ - Add comprehensive test suite for Dropdown component to achieve 100% coverage [`#523`](https://github.com/nyaruka/temba-components/pull/523)
32
+ - Remove OutboxMonitor component [`#522`](https://github.com/nyaruka/temba-components/pull/522)
33
+ - Bump image-size from 1.1.1 to 1.2.1 [`#483`](https://github.com/nyaruka/temba-components/pull/483)
34
+ - Bump koa from 2.15.4 to 2.16.1 [`#485`](https://github.com/nyaruka/temba-components/pull/485)
35
+ - Add comprehensive test coverage for Toast component [`#521`](https://github.com/nyaruka/temba-components/pull/521)
36
+ - Show "No options" message when opening select with empty options [`#505`](https://github.com/nyaruka/temba-components/pull/505)
37
+ - Fix GitHub Actions job name: rename 'setup' to 'copilot-setup-steps' [`#520`](https://github.com/nyaruka/temba-components/pull/520)
38
+ - Add duration formatting option to TembaChart for y-axis and tooltips [`#513`](https://github.com/nyaruka/temba-components/pull/513)
39
+ - Add chart options for color index start and legend [`#503`](https://github.com/nyaruka/temba-components/pull/503)
40
+ - Exclude github-copilot[bot] from CLA Assistant workflow [`#515`](https://github.com/nyaruka/temba-components/pull/515)
41
+ - Restrict copilot-setup-steps workflow to run only on GitHub Actions bot pushes [`#514`](https://github.com/nyaruka/temba-components/pull/514)
42
+ - Add copilot-instructions.md with comprehensive development guidelines [`#512`](https://github.com/nyaruka/temba-components/pull/512)
43
+ - Add Copilot to CLA allowlist to ignore GitHub Copilot PRs [`#509`](https://github.com/nyaruka/temba-components/pull/509)
44
+ - Add GitHub Actions workflow for Copilot environment setup [`#508`](https://github.com/nyaruka/temba-components/pull/508)
45
+ - Add pre-commit [`a4d2c29`](https://github.com/nyaruka/temba-components/commit/a4d2c295bbd113a9310421547a35af553971b8c6)
46
+ - merge [`76161ae`](https://github.com/nyaruka/temba-components/commit/76161ae9aeaa2dcc28f09ed127661395fea87e28)
47
+ - Add comprehensive test coverage for utils/index.ts functions [`389a84b`](https://github.com/nyaruka/temba-components/commit/389a84ba68785b783fff2a1bdc276443f6b3f12c)
48
+
7
49
  #### [v0.122.0](https://github.com/nyaruka/temba-components/compare/v0.121.7...v0.122.0)
8
50
 
51
+ > 28 May 2025
52
+
9
53
  - Basic chart with auto-summing of unsplit data [`#501`](https://github.com/nyaruka/temba-components/pull/501)
10
54
  - Add temba-chart [`fe311df`](https://github.com/nyaruka/temba-components/commit/fe311df264ad5c57f58c87c5a67e2d0b4e3edd37)
11
55
  - Fix bad merge [`f10e475`](https://github.com/nyaruka/temba-components/commit/f10e475fcc3dc316708340686b0d7f235cf918e7)
@@ -0,0 +1,141 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-GB">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Multi-Select Drag and Drop Demo</title>
6
+ <link
7
+ href="/static/css/temba-components.css"
8
+ rel="stylesheet"
9
+ type="text/css"
10
+ />
11
+ <style>
12
+ body {
13
+ font-family: sans-serif;
14
+ padding: 20px;
15
+ max-width: 800px;
16
+ margin: 0 auto;
17
+ }
18
+ .example {
19
+ margin: 30px 0;
20
+ padding: 20px;
21
+ border: 1px solid #ddd;
22
+ border-radius: 8px;
23
+ }
24
+ .example h3 {
25
+ margin-top: 0;
26
+ color: #333;
27
+ }
28
+ .example p {
29
+ color: #666;
30
+ margin-bottom: 15px;
31
+ }
32
+ .expected {
33
+ background-color: #f0f8ff;
34
+ padding: 10px;
35
+ border-radius: 4px;
36
+ margin-top: 10px;
37
+ }
38
+ .expected strong {
39
+ color: #006400;
40
+ }
41
+ </style>
42
+ </head>
43
+ <body>
44
+ <h1>Multi-Select Drag and Drop Demo</h1>
45
+ <p>This demo shows the drag and drop reordering functionality for multi-select components.</p>
46
+
47
+ <div class="example">
48
+ <h3>With 3 items (drag and drop enabled)</h3>
49
+ <p>This multi-select has 3 pre-selected items. You should be able to drag and drop to reorder them.</p>
50
+ <temba-select multi searchable id="test3" placeholder="Select colors">
51
+ <temba-option name="Red" value="0" selected></temba-option>
52
+ <temba-option name="Green" value="1" selected></temba-option>
53
+ <temba-option name="Blue" value="2" selected></temba-option>
54
+ </temba-select>
55
+ <div class="expected">
56
+ <strong>Expected behavior:</strong>
57
+ <ul>
58
+ <li>Items should be wrapped in a sortable container</li>
59
+ <li>Drag an item to see a ghost element following the mouse</li>
60
+ <li>Drop on another item to swap their positions</li>
61
+ <li>Drop outside to cancel the operation</li>
62
+ <li>Items should maintain cursor style when hovering</li>
63
+ </ul>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="example">
68
+ <h3>With 2 items (drag and drop enabled)</h3>
69
+ <p>This multi-select has 2 pre-selected items. You should be able to drag and drop to reorder them.</p>
70
+ <temba-select multi id="test2" placeholder="Select fruits">
71
+ <temba-option name="Apple" value="apple" selected></temba-option>
72
+ <temba-option name="Banana" value="banana" selected></temba-option>
73
+ </temba-select>
74
+ <div class="expected">
75
+ <strong>Expected behavior:</strong>
76
+ <ul>
77
+ <li>Same drag and drop functionality as above</li>
78
+ <li>Swapping the two items should work</li>
79
+ </ul>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="example">
84
+ <h3>With 1 item (no drag and drop)</h3>
85
+ <p>This multi-select has only 1 pre-selected item. Drag and drop should not be enabled.</p>
86
+ <temba-select multi id="test1" placeholder="Select an item">
87
+ <temba-option name="Solo" value="solo" selected></temba-option>
88
+ </temba-select>
89
+ <div class="expected">
90
+ <strong>Expected behavior:</strong>
91
+ <ul>
92
+ <li>No sortable container should be present</li>
93
+ <li>Normal multi-select appearance and behavior</li>
94
+ </ul>
95
+ </div>
96
+ </div>
97
+
98
+ <div class="example">
99
+ <h3>Regular single select (no drag and drop)</h3>
100
+ <p>This is a regular single-select. Drag and drop should not be enabled.</p>
101
+ <temba-select id="single">
102
+ <temba-option name="Option 1" value="1" selected></temba-option>
103
+ </temba-select>
104
+ <div class="expected">
105
+ <strong>Expected behavior:</strong>
106
+ <ul>
107
+ <li>Normal single-select appearance and behavior</li>
108
+ <li>No sortable functionality</li>
109
+ </ul>
110
+ </div>
111
+ </div>
112
+
113
+ <script>
114
+ // Add event listeners to monitor changes
115
+ document.querySelectorAll('temba-select[multi]').forEach(select => {
116
+ select.addEventListener('change', () => {
117
+ console.log(`${select.id} values changed:`, select.values);
118
+ });
119
+ });
120
+
121
+ // Log initial state after components load
122
+ window.addEventListener('load', () => {
123
+ setTimeout(() => {
124
+ console.log('=== Initial State ===');
125
+ document.querySelectorAll('temba-select').forEach(select => {
126
+ const sortableList = select.shadowRoot?.querySelector('temba-sortable-list');
127
+ console.log(`${select.id}:`, {
128
+ values: select.values,
129
+ hasSortableList: !!sortableList,
130
+ isMulti: select.hasAttribute('multi')
131
+ });
132
+ });
133
+ }, 500);
134
+ });
135
+ </script>
136
+
137
+ <script type="module">
138
+ import '../out-tsc/temba-modules.js';
139
+ </script>
140
+ </body>
141
+ </html>
package/demo/index.html CHANGED
@@ -138,6 +138,23 @@
138
138
  </head>
139
139
 
140
140
  <body>
141
+ <script>
142
+ // Initialize duration chart when DOM is loaded
143
+ document.addEventListener('DOMContentLoaded', function() {
144
+ const durationChart = document.getElementById('duration-chart');
145
+ if (durationChart) {
146
+ // Sample data with durations in seconds from the issue examples
147
+ durationChart.data = {
148
+ labels: ['Process A', 'Process B', 'Process C', 'Process D', 'Process E'],
149
+ datasets: [{
150
+ label: 'Processing Time',
151
+ data: [68787, 958000, 3661, 120, 86400] // seconds: 19h6m, 11d2h, 1h1m, 2m, 1d
152
+ }]
153
+ };
154
+ console.log('Duration chart initialized with formatDuration:', durationChart.formatDuration);
155
+ }
156
+ });
157
+ </script>
141
158
  <temba-webchat
142
159
  channel="967cd415-8616-4b11-b38f-60f70e0999f4"
143
160
  ></temba-webchat>
@@ -177,6 +194,13 @@
177
194
  <temba-tabs collapses index="0">
178
195
  <temba-tab name="Overview" icon="default">
179
196
  <temba-chart style="margin-bottom:8px"></temba-chart>
197
+
198
+ <!-- Chart with duration formatting -->
199
+ <div style="margin: 20px 0;">
200
+ <h3>Duration Formatted Chart</h3>
201
+ <temba-chart id="duration-chart" style="margin-bottom:8px" format-duration header="Process Times"></temba-chart>
202
+ </div>
203
+
180
204
  <temba-progress style="margin-bottom:8px" total="100" current="25" eta="2030-09-17T07:00:00.000Z"></temba-progress>
181
205
  <temba-checkbox label="Check this out" checked></temba-checkbox>
182
206
  <temba-select placeholder="Select a color" clearable>
@@ -348,6 +372,21 @@
348
372
  </temba-select>
349
373
  </div>
350
374
 
375
+ <div class="example">
376
+ <h3>Multi-select with 3 items (Drag and Drop Test)</h3>
377
+ <temba-select
378
+ placeholder="Select colors"
379
+ values='[{"name":"Red","value":"0"},{"name":"Green","value":"1"},{"name":"Blue","value":"2"}]'
380
+ multi
381
+ >
382
+ <temba-option name="Red" value="0"></temba-option>
383
+ <temba-option name="Green" value="1"></temba-option>
384
+ <temba-option name="Blue" value="2"></temba-option>
385
+ <temba-option name="Yellow" value="3"></temba-option>
386
+ <temba-option name="Purple" value="4"></temba-option>
387
+ </temba-select>
388
+ </div>
389
+
351
390
  <div class="example">
352
391
  <script>
353
392
  function toggleSelect(evt) {
@@ -372,6 +411,24 @@
372
411
  </temba-select>
373
412
  </div>
374
413
  </div>
414
+
415
+ <div class="example">
416
+ <label style="display: block; margin-bottom: 5px; font-weight: bold;">Empty Select (No Options)</label>
417
+ <temba-select placeholder="Click to see empty state">
418
+ </temba-select>
419
+ </div>
420
+
421
+ <div class="example">
422
+ <label style="display: block; margin-bottom: 5px; font-weight: bold;">Empty Searchable Select</label>
423
+ <temba-select placeholder="Search for options" searchable>
424
+ </temba-select>
425
+ </div>
426
+
427
+ <div class="example">
428
+ <label style="display: block; margin-bottom: 5px; font-weight: bold;">Empty Multi Select</label>
429
+ <temba-select placeholder="Select multiple options" multi>
430
+ </temba-select>
431
+ </div>
375
432
  </temba-tab>
376
433
 
377
434
  <temba-tab name="textinput" icon="edit-05">