@nyaruka/temba-components 0.131.2 → 0.131.3

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 (223) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/demo/components/floating-tabs/example.html +400 -0
  3. package/demo/components/flow/index.html +1 -1
  4. package/demo/data/flows/sample-flow.json +41 -2
  5. package/demo/data/flows/voicemail.json +613 -0
  6. package/demo/index.html +6 -0
  7. package/dist/locales/es.js +5 -5
  8. package/dist/locales/es.js.map +1 -1
  9. package/dist/locales/fr.js +5 -5
  10. package/dist/locales/fr.js.map +1 -1
  11. package/dist/locales/locale-codes.js +11 -2
  12. package/dist/locales/locale-codes.js.map +1 -1
  13. package/dist/locales/pt.js +5 -5
  14. package/dist/locales/pt.js.map +1 -1
  15. package/dist/temba-components.js +1109 -535
  16. package/dist/temba-components.js.map +1 -1
  17. package/out-tsc/src/display/FloatingTab.js +167 -0
  18. package/out-tsc/src/display/FloatingTab.js.map +1 -0
  19. package/out-tsc/src/display/ProgressBar.js +22 -2
  20. package/out-tsc/src/display/ProgressBar.js.map +1 -1
  21. package/out-tsc/src/events.js.map +1 -1
  22. package/out-tsc/src/flow/CanvasNode.js +165 -31
  23. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  24. package/out-tsc/src/flow/Editor.js +857 -3
  25. package/out-tsc/src/flow/Editor.js.map +1 -1
  26. package/out-tsc/src/flow/NodeEditor.js +239 -19
  27. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  28. package/out-tsc/src/flow/NodeTypeSelector.js +44 -3
  29. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
  30. package/out-tsc/src/flow/StickyNote.js +12 -3
  31. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  32. package/out-tsc/src/flow/actions/add_contact_groups.js +2 -1
  33. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  34. package/out-tsc/src/flow/actions/add_contact_urn.js +2 -1
  35. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  36. package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
  37. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  38. package/out-tsc/src/flow/actions/play_audio.js +2 -1
  39. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  40. package/out-tsc/src/flow/actions/remove_contact_groups.js +2 -1
  41. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  42. package/out-tsc/src/flow/actions/request_optin.js +1 -0
  43. package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
  44. package/out-tsc/src/flow/actions/say_msg.js +2 -1
  45. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  46. package/out-tsc/src/flow/actions/send_broadcast.js +2 -1
  47. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  48. package/out-tsc/src/flow/actions/send_email.js +2 -1
  49. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  50. package/out-tsc/src/flow/actions/send_msg.js +93 -3
  51. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  52. package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
  53. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  54. package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
  55. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  56. package/out-tsc/src/flow/actions/set_contact_language.js +2 -1
  57. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  58. package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
  59. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  60. package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
  61. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  62. package/out-tsc/src/flow/actions/set_run_result.js +2 -1
  63. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  64. package/out-tsc/src/flow/actions/start_session.js +2 -1
  65. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  66. package/out-tsc/src/flow/config.js +2 -10
  67. package/out-tsc/src/flow/config.js.map +1 -1
  68. package/out-tsc/src/flow/nodes/shared.js +54 -0
  69. package/out-tsc/src/flow/nodes/shared.js.map +1 -1
  70. package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -3
  71. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
  72. package/out-tsc/src/flow/nodes/split_by_contact_field.js +8 -3
  73. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  74. package/out-tsc/src/flow/nodes/split_by_expression.js +8 -3
  75. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  76. package/out-tsc/src/flow/nodes/split_by_groups.js +8 -3
  77. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  78. package/out-tsc/src/flow/nodes/split_by_intent.js +3 -2
  79. package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -1
  80. package/out-tsc/src/flow/nodes/split_by_llm.js +9 -2
  81. package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
  82. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +9 -2
  83. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  84. package/out-tsc/src/flow/nodes/split_by_random.js +8 -2
  85. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  86. package/out-tsc/src/flow/nodes/split_by_resthook.js +8 -3
  87. package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
  88. package/out-tsc/src/flow/nodes/split_by_run_result.js +8 -3
  89. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  90. package/out-tsc/src/flow/nodes/split_by_scheme.js +8 -3
  91. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
  92. package/out-tsc/src/flow/nodes/split_by_subflow.js +8 -2
  93. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  94. package/out-tsc/src/flow/nodes/split_by_ticket.js +8 -2
  95. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  96. package/out-tsc/src/flow/nodes/split_by_webhook.js +8 -2
  97. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  98. package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
  99. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  100. package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
  101. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  102. package/out-tsc/src/flow/nodes/wait_for_response.js +8 -3
  103. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  104. package/out-tsc/src/flow/types.js +15 -0
  105. package/out-tsc/src/flow/types.js.map +1 -1
  106. package/out-tsc/src/layout/FloatingWindow.js +346 -0
  107. package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
  108. package/out-tsc/src/live/ContactChat.js +3 -19
  109. package/out-tsc/src/live/ContactChat.js.map +1 -1
  110. package/out-tsc/src/locales/es.js +5 -5
  111. package/out-tsc/src/locales/es.js.map +1 -1
  112. package/out-tsc/src/locales/fr.js +5 -5
  113. package/out-tsc/src/locales/fr.js.map +1 -1
  114. package/out-tsc/src/locales/locale-codes.js +11 -2
  115. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  116. package/out-tsc/src/locales/pt.js +5 -5
  117. package/out-tsc/src/locales/pt.js.map +1 -1
  118. package/out-tsc/src/store/AppState.js +67 -0
  119. package/out-tsc/src/store/AppState.js.map +1 -1
  120. package/out-tsc/temba-modules.js +4 -0
  121. package/out-tsc/temba-modules.js.map +1 -1
  122. package/out-tsc/test/temba-floating-tab.test.js +91 -0
  123. package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
  124. package/out-tsc/test/temba-floating-window.test.js +301 -0
  125. package/out-tsc/test/temba-floating-window.test.js.map +1 -0
  126. package/out-tsc/test/temba-flow-editor-node.test.js +117 -0
  127. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  128. package/out-tsc/test/temba-localization.test.js +471 -0
  129. package/out-tsc/test/temba-localization.test.js.map +1 -0
  130. package/out-tsc/test/temba-node-type-selector.test.js +150 -0
  131. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  132. package/out-tsc/test/utils.test.js +18 -0
  133. package/out-tsc/test/utils.test.js.map +1 -1
  134. package/package.json +1 -1
  135. package/screenshots/truth/floating-tab/default.png +0 -0
  136. package/screenshots/truth/floating-tab/gray.png +0 -0
  137. package/screenshots/truth/floating-tab/green.png +0 -0
  138. package/screenshots/truth/floating-tab/hidden.png +0 -0
  139. package/screenshots/truth/floating-tab/hover.png +0 -0
  140. package/screenshots/truth/floating-tab/purple.png +0 -0
  141. package/screenshots/truth/floating-window/chromeless.png +0 -0
  142. package/screenshots/truth/floating-window/custom-size.png +0 -0
  143. package/screenshots/truth/floating-window/default.png +0 -0
  144. package/screenshots/truth/floating-window/with-header.png +0 -0
  145. package/screenshots/truth/node-type-selector/action-mode.png +0 -0
  146. package/screenshots/truth/node-type-selector/split-mode.png +0 -0
  147. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  148. package/src/display/FloatingTab.ts +174 -0
  149. package/src/display/ProgressBar.ts +22 -2
  150. package/src/events.ts +2 -4
  151. package/src/flow/CanvasNode.ts +190 -32
  152. package/src/flow/Editor.ts +1040 -3
  153. package/src/flow/NodeEditor.ts +317 -19
  154. package/src/flow/NodeTypeSelector.ts +47 -3
  155. package/src/flow/StickyNote.ts +12 -3
  156. package/src/flow/actions/add_contact_groups.ts +2 -1
  157. package/src/flow/actions/add_contact_urn.ts +3 -1
  158. package/src/flow/actions/add_input_labels.ts +2 -1
  159. package/src/flow/actions/play_audio.ts +2 -1
  160. package/src/flow/actions/remove_contact_groups.ts +3 -1
  161. package/src/flow/actions/request_optin.ts +1 -0
  162. package/src/flow/actions/say_msg.ts +2 -1
  163. package/src/flow/actions/send_broadcast.ts +2 -1
  164. package/src/flow/actions/send_email.ts +3 -1
  165. package/src/flow/actions/send_msg.ts +134 -3
  166. package/src/flow/actions/set_contact_channel.ts +2 -1
  167. package/src/flow/actions/set_contact_field.ts +2 -1
  168. package/src/flow/actions/set_contact_language.ts +3 -1
  169. package/src/flow/actions/set_contact_name.ts +2 -1
  170. package/src/flow/actions/set_contact_status.ts +2 -1
  171. package/src/flow/actions/set_run_result.ts +2 -1
  172. package/src/flow/actions/start_session.ts +3 -1
  173. package/src/flow/config.ts +2 -12
  174. package/src/flow/nodes/shared.ts +70 -1
  175. package/src/flow/nodes/split_by_airtime.ts +20 -3
  176. package/src/flow/nodes/split_by_contact_field.ts +13 -3
  177. package/src/flow/nodes/split_by_expression.ts +13 -3
  178. package/src/flow/nodes/split_by_groups.ts +13 -3
  179. package/src/flow/nodes/split_by_intent.ts +3 -2
  180. package/src/flow/nodes/split_by_llm.ts +19 -2
  181. package/src/flow/nodes/split_by_llm_categorize.ts +19 -2
  182. package/src/flow/nodes/split_by_random.ts +12 -2
  183. package/src/flow/nodes/split_by_resthook.ts +13 -3
  184. package/src/flow/nodes/split_by_run_result.ts +13 -3
  185. package/src/flow/nodes/split_by_scheme.ts +13 -3
  186. package/src/flow/nodes/split_by_subflow.ts +12 -2
  187. package/src/flow/nodes/split_by_ticket.ts +12 -2
  188. package/src/flow/nodes/split_by_webhook.ts +12 -2
  189. package/src/flow/nodes/wait_for_digits.ts +3 -2
  190. package/src/flow/nodes/wait_for_menu.ts +3 -2
  191. package/src/flow/nodes/wait_for_response.ts +13 -3
  192. package/src/flow/types.ts +47 -0
  193. package/src/layout/FloatingWindow.ts +386 -0
  194. package/src/live/ContactChat.ts +4 -19
  195. package/src/locales/es.ts +18 -13
  196. package/src/locales/fr.ts +18 -13
  197. package/src/locales/locale-codes.ts +11 -2
  198. package/src/locales/pt.ts +18 -13
  199. package/src/store/AppState.ts +104 -0
  200. package/static/api/llms.json +18 -0
  201. package/temba-modules.ts +4 -0
  202. package/test/temba-floating-tab.test.ts +110 -0
  203. package/test/temba-floating-window.test.ts +477 -0
  204. package/test/temba-flow-editor-node.test.ts +144 -0
  205. package/test/temba-localization.test.ts +611 -0
  206. package/test/temba-node-type-selector.test.ts +203 -0
  207. package/test/utils.test.ts +20 -0
  208. package/test-assets/contacts/history.json +5 -6
  209. package/test-assets/select/llms.json +2 -2
  210. package/web-dev-server.config.mjs +47 -1
  211. package/web-test-runner.config.mjs +0 -1
  212. package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
  213. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
  214. package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
  215. package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
  216. package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
  217. package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
  218. package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
  219. package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
  220. package/src/flow/nodes/wait_for_audio.ts +0 -7
  221. package/src/flow/nodes/wait_for_image.ts +0 -7
  222. package/src/flow/nodes/wait_for_location.ts +0 -7
  223. package/src/flow/nodes/wait_for_video.ts +0 -7
@@ -1,12 +1,24 @@
1
- import { FormData, NodeConfig, ACTION_GROUPS } from '../types';
1
+ import {
2
+ FormData,
3
+ NodeConfig,
4
+ ACTION_GROUPS,
5
+ FlowTypes,
6
+ Features
7
+ } from '../types';
2
8
  import { CallLLM, Node } from '../../store/flow-definition';
3
9
  import { generateUUID, createMultiCategoryRouter } from '../../utils';
4
10
  import { html } from 'lit';
11
+ import {
12
+ categoriesToLocalizationFormData,
13
+ localizationFormDataToCategories
14
+ } from './shared';
5
15
 
6
16
  export const split_by_llm_categorize: NodeConfig = {
7
17
  type: 'split_by_llm_categorize',
8
18
  name: 'Split by AI',
9
19
  group: ACTION_GROUPS.services,
20
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
21
+ features: [Features.AI],
10
22
  form: {
11
23
  llm: {
12
24
  type: 'select',
@@ -171,5 +183,10 @@ export const split_by_llm_categorize: NodeConfig = {
171
183
  router: router,
172
184
  exits: exits
173
185
  };
174
- }
186
+ },
187
+
188
+ // Localization support for categories
189
+ localizable: 'categories',
190
+ toLocalizationFormData: categoriesToLocalizationFormData,
191
+ fromLocalizationFormData: localizationFormDataToCategories
175
192
  };
@@ -1,6 +1,10 @@
1
- import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node, Category, Exit } from '../../store/flow-definition.d';
3
3
  import { generateUUID } from '../../utils';
4
+ import {
5
+ categoriesToLocalizationFormData,
6
+ localizationFormDataToCategories
7
+ } from './shared';
4
8
 
5
9
  // Helper function to create a random router with categories
6
10
  const createRandomRouter = (
@@ -49,6 +53,7 @@ export const split_by_random: NodeConfig = {
49
53
  type: 'split_by_random',
50
54
  name: 'Random Split',
51
55
  group: SPLIT_GROUPS.split,
56
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
52
57
  form: {
53
58
  categories: {
54
59
  type: 'array',
@@ -155,5 +160,10 @@ export const split_by_random: NodeConfig = {
155
160
  },
156
161
  router: {
157
162
  type: 'random'
158
- }
163
+ },
164
+
165
+ // Localization support for categories
166
+ localizable: 'categories',
167
+ toLocalizationFormData: categoriesToLocalizationFormData,
168
+ fromLocalizationFormData: localizationFormDataToCategories
159
169
  };
@@ -1,13 +1,18 @@
1
- import { ACTION_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { ACTION_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { CallResthook, Node } from '../../store/flow-definition';
3
3
  import { generateUUID, createSuccessFailureRouter } from '../../utils';
4
4
  import { html } from 'lit';
5
- import { resultNameField } from './shared';
5
+ import {
6
+ resultNameField,
7
+ categoriesToLocalizationFormData,
8
+ localizationFormDataToCategories
9
+ } from './shared';
6
10
 
7
11
  export const split_by_resthook: NodeConfig = {
8
12
  type: 'split_by_resthook',
9
13
  name: 'Call Resthook',
10
14
  group: ACTION_GROUPS.services,
15
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
11
16
  showAsAction: true,
12
17
  form: {
13
18
  resthook: {
@@ -126,5 +131,10 @@ export const split_by_resthook: NodeConfig = {
126
131
  router: finalRouter,
127
132
  exits: exits
128
133
  };
129
- }
134
+ },
135
+
136
+ // Localization support for categories
137
+ localizable: 'categories',
138
+ toLocalizationFormData: categoriesToLocalizationFormData,
139
+ fromLocalizationFormData: localizationFormDataToCategories
130
140
  };
@@ -1,4 +1,4 @@
1
- import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node } from '../../store/flow-definition';
3
3
  import { createRulesRouter } from '../../utils';
4
4
  import {
@@ -6,7 +6,11 @@ import {
6
6
  operatorsToSelectOptions,
7
7
  getOperatorConfig
8
8
  } from '../operators';
9
- import { resultNameField } from './shared';
9
+ import {
10
+ resultNameField,
11
+ categoriesToLocalizationFormData,
12
+ localizationFormDataToCategories
13
+ } from './shared';
10
14
  import {
11
15
  createRulesArrayConfig,
12
16
  extractUserRules,
@@ -50,6 +54,7 @@ export const split_by_run_result: NodeConfig = {
50
54
  type: 'split_by_run_result',
51
55
  name: 'Split by Result',
52
56
  group: SPLIT_GROUPS.split,
57
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
53
58
  dialogSize: 'large',
54
59
  form: {
55
60
  result: {
@@ -249,5 +254,10 @@ export const split_by_run_result: NodeConfig = {
249
254
  }
250
255
 
251
256
  return config;
252
- }
257
+ },
258
+
259
+ // Localization support for categories
260
+ localizable: 'categories',
261
+ toLocalizationFormData: categoriesToLocalizationFormData,
262
+ fromLocalizationFormData: localizationFormDataToCategories
253
263
  };
@@ -1,8 +1,12 @@
1
- import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node, Category, Exit, Case } from '../../store/flow-definition.d';
3
3
  import { generateUUID } from '../../utils';
4
4
  import { SCHEMES } from '../utils';
5
- import { resultNameField } from './shared';
5
+ import {
6
+ resultNameField,
7
+ categoriesToLocalizationFormData,
8
+ localizationFormDataToCategories
9
+ } from './shared';
6
10
 
7
11
  // Helper function to get scheme options for the select dropdown
8
12
  const getSchemeOptions = () => {
@@ -106,6 +110,7 @@ export const split_by_scheme: NodeConfig = {
106
110
  type: 'split_by_scheme',
107
111
  name: 'Split by URN Type',
108
112
  group: SPLIT_GROUPS.split,
113
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
109
114
  form: {
110
115
  schemes: {
111
116
  type: 'select',
@@ -193,5 +198,10 @@ export const split_by_scheme: NodeConfig = {
193
198
  router: {
194
199
  type: 'switch',
195
200
  operand: '@(urn_parts(contact.urn).scheme)'
196
- }
201
+ },
202
+
203
+ // Localization support for categories
204
+ localizable: 'categories',
205
+ toLocalizationFormData: categoriesToLocalizationFormData,
206
+ fromLocalizationFormData: localizationFormDataToCategories
197
207
  };
@@ -1,13 +1,18 @@
1
- import { ACTION_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { ACTION_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node } from '../../store/flow-definition';
3
3
  import { generateUUID } from '../../utils';
4
4
  import { html } from 'lit';
5
5
  import { renderNamedObjects } from '../utils';
6
+ import {
7
+ categoriesToLocalizationFormData,
8
+ localizationFormDataToCategories
9
+ } from './shared';
6
10
 
7
11
  export const split_by_subflow: NodeConfig = {
8
12
  type: 'split_by_subflow',
9
13
  name: 'Enter a Flow',
10
14
  group: ACTION_GROUPS.trigger,
15
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
11
16
  showAsAction: true,
12
17
  form: {
13
18
  flow: {
@@ -157,5 +162,10 @@ export const split_by_subflow: NodeConfig = {
157
162
  router: router,
158
163
  exits: exits
159
164
  };
160
- }
165
+ },
166
+
167
+ // Localization support for categories
168
+ localizable: 'categories',
169
+ toLocalizationFormData: categoriesToLocalizationFormData,
170
+ fromLocalizationFormData: localizationFormDataToCategories
161
171
  };
@@ -1,12 +1,17 @@
1
- import { ACTION_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { ACTION_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node, OpenTicket } from '../../store/flow-definition';
3
3
  import { generateUUID, createSuccessFailureRouter } from '../../utils';
4
4
  import { html } from 'lit';
5
+ import {
6
+ categoriesToLocalizationFormData,
7
+ localizationFormDataToCategories
8
+ } from './shared';
5
9
 
6
10
  export const split_by_ticket: NodeConfig = {
7
11
  type: 'split_by_ticket',
8
12
  name: 'Open Ticket',
9
13
  group: ACTION_GROUPS.trigger,
14
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
10
15
  showAsAction: true,
11
16
  form: {
12
17
  topic: {
@@ -138,5 +143,10 @@ export const split_by_ticket: NodeConfig = {
138
143
  router: router,
139
144
  exits: exits
140
145
  };
141
- }
146
+ },
147
+
148
+ // Localization support for categories
149
+ localizable: 'categories',
150
+ toLocalizationFormData: categoriesToLocalizationFormData,
151
+ fromLocalizationFormData: localizationFormDataToCategories
142
152
  };
@@ -1,7 +1,11 @@
1
- import { ACTION_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { ACTION_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { CallWebhook, Node } from '../../store/flow-definition';
3
3
  import { generateUUID, createSuccessFailureRouter } from '../../utils';
4
4
  import { html } from 'lit';
5
+ import {
6
+ categoriesToLocalizationFormData,
7
+ localizationFormDataToCategories
8
+ } from './shared';
5
9
 
6
10
  const defaultPost = `@(json(object(
7
11
  "contact", object(
@@ -20,6 +24,7 @@ export const split_by_webhook: NodeConfig = {
20
24
  type: 'split_by_webhook',
21
25
  name: 'Call Webhook',
22
26
  group: ACTION_GROUPS.services,
27
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
23
28
  showAsAction: true,
24
29
  form: {
25
30
  method: {
@@ -189,5 +194,10 @@ export const split_by_webhook: NodeConfig = {
189
194
  router: router,
190
195
  exits: exits
191
196
  };
192
- }
197
+ },
198
+
199
+ // Localization support for categories
200
+ localizable: 'categories',
201
+ toLocalizationFormData: categoriesToLocalizationFormData,
202
+ fromLocalizationFormData: localizationFormDataToCategories
193
203
  };
@@ -1,7 +1,8 @@
1
- import { SPLIT_GROUPS, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, NodeConfig, FlowTypes } from '../types';
2
2
 
3
3
  export const wait_for_digits: NodeConfig = {
4
4
  type: 'wait_for_digits',
5
5
  name: 'Wait for Digits',
6
- group: SPLIT_GROUPS.wait
6
+ group: SPLIT_GROUPS.wait,
7
+ flowTypes: [FlowTypes.VOICE]
7
8
  };
@@ -1,7 +1,8 @@
1
- import { SPLIT_GROUPS, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, NodeConfig, FlowTypes } from '../types';
2
2
 
3
3
  export const wait_for_menu: NodeConfig = {
4
4
  type: 'wait_for_menu',
5
5
  name: 'Wait for Menu Selection',
6
- group: SPLIT_GROUPS.wait
6
+ group: SPLIT_GROUPS.wait,
7
+ flowTypes: [FlowTypes.VOICE]
7
8
  };
@@ -1,4 +1,4 @@
1
- import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
1
+ import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
2
2
  import { Node, Category, Exit, Case } from '../../store/flow-definition';
3
3
  import { generateUUID, createRulesRouter } from '../../utils';
4
4
  import {
@@ -6,7 +6,11 @@ import {
6
6
  operatorsToSelectOptions,
7
7
  getOperatorConfig
8
8
  } from '../operators';
9
- import { resultNameField } from './shared';
9
+ import {
10
+ resultNameField,
11
+ categoriesToLocalizationFormData,
12
+ localizationFormDataToCategories
13
+ } from './shared';
10
14
  import {
11
15
  createRulesArrayConfig,
12
16
  extractUserRules,
@@ -77,6 +81,7 @@ export const wait_for_response: NodeConfig = {
77
81
  type: 'wait_for_response',
78
82
  name: 'Wait for Response',
79
83
  group: SPLIT_GROUPS.wait,
84
+ flowTypes: [FlowTypes.MESSAGE],
80
85
  dialogSize: 'large',
81
86
  form: {
82
87
  rules: createRulesArrayConfig(
@@ -390,5 +395,10 @@ export const wait_for_response: NodeConfig = {
390
395
  router: finalRouter,
391
396
  exits: exits
392
397
  };
393
- }
398
+ },
399
+
400
+ // Localization support for categories
401
+ localizable: 'categories',
402
+ toLocalizationFormData: categoriesToLocalizationFormData,
403
+ fromLocalizationFormData: localizationFormDataToCategories
394
404
  };
package/src/flow/types.ts CHANGED
@@ -6,6 +6,27 @@ export interface ValidationResult {
6
6
  errors: { [key: string]: string };
7
7
  }
8
8
 
9
+ /**
10
+ * Flow types - defines the type of flow being edited
11
+ */
12
+ export const FlowTypes = {
13
+ MESSAGE: 'message',
14
+ VOICE: 'voice',
15
+ BACKGROUND: 'background'
16
+ } as const;
17
+
18
+ export type FlowType = (typeof FlowTypes)[keyof typeof FlowTypes];
19
+
20
+ /**
21
+ * Features - defines the features available in the account
22
+ */
23
+ export const Features = {
24
+ AI: 'ai',
25
+ AIRTIME: 'airtime'
26
+ } as const;
27
+
28
+ export type Feature = (typeof Features)[keyof typeof Features];
29
+
9
30
  // Component attribute interfaces - these define what's allowed for each component type
10
31
  export interface TextInputAttributes {
11
32
  type?: 'text' | 'email' | 'number' | 'url' | 'tel';
@@ -82,6 +103,8 @@ export interface NodeConfig extends FormConfig {
82
103
  dialogSize?: 'small' | 'medium' | 'large' | 'xlarge';
83
104
  action?: ActionConfig;
84
105
  showAsAction?: boolean; // if true, show in action dialog instead of splits (default: false - nodes show in splits)
106
+ flowTypes?: FlowType[]; // which flow types this node is available for (defaults to all if not specified)
107
+ features?: Feature[]; // which features are required for this node (all must be present)
85
108
  router?: {
86
109
  type: 'switch' | 'random';
87
110
  defaultCategory?: string;
@@ -104,6 +127,17 @@ export interface NodeConfig extends FormConfig {
104
127
  toUIConfig?: (formData: FormData) => Record<string, any>;
105
128
  render?: (node: Node, nodeUI?: any) => TemplateResult;
106
129
  renderTitle?: (node: Node, nodeUI?: NodeUI) => TemplateResult;
130
+
131
+ // Localization support for router categories
132
+ localizable?: 'categories'; // Only categories are localizable for routers
133
+ toLocalizationFormData?: (
134
+ node: Node,
135
+ localization: Record<string, any>
136
+ ) => FormData;
137
+ fromLocalizationFormData?: (
138
+ formData: FormData,
139
+ node: Node
140
+ ) => Record<string, any>;
107
141
  }
108
142
 
109
143
  // New field configuration system for generic form generation
@@ -354,6 +388,8 @@ export interface ActionConfig extends FormConfig {
354
388
  dialogSize?: 'small' | 'medium' | 'large' | 'xlarge';
355
389
  evaluated?: string[];
356
390
  hideFromActions?: boolean; // if true, don't show in action dialog (default: false - actions show in actions)
391
+ flowTypes?: FlowType[]; // which flow types this action is available for (defaults to all if not specified)
392
+ features?: Feature[]; // which features are required for this action (all must be present)
357
393
  render?: (node: any, action: any) => TemplateResult;
358
394
 
359
395
  form?: Record<string, FieldConfig>;
@@ -362,4 +398,15 @@ export interface ActionConfig extends FormConfig {
362
398
 
363
399
  toFormData?: (action: Action) => FormData;
364
400
  fromFormData?: (formData: FormData) => Action;
401
+
402
+ // Localization support
403
+ localizable?: string[]; // array of field names that can be localized
404
+ toLocalizationFormData?: (
405
+ action: Action,
406
+ localization: Record<string, any>
407
+ ) => FormData;
408
+ fromLocalizationFormData?: (
409
+ formData: FormData,
410
+ action: Action
411
+ ) => Record<string, any>;
365
412
  }