@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 +1 @@
1
- {"version":3,"file":"NodeTypeSelector.js","sourceRoot":"","sources":["../../../src/flow/NodeTypeSelector.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { NODE_CONFIG, ACTION_CONFIG } from './config';\nimport {\n NodeConfig,\n ActionConfig,\n ACTION_GROUPS,\n SPLIT_GROUPS,\n ACTION_GROUP_METADATA,\n SPLIT_GROUP_METADATA\n} from './types';\n\n/**\n * Event detail for node type selection\n */\nexport interface NodeTypeSelection {\n nodeType: string;\n position: { x: number; y: number };\n}\n\n/**\n * Categorizes node types for display\n */\ninterface NodeCategory {\n name: string;\n description: string;\n color: string;\n items: Array<{ type: string; config: NodeConfig | ActionConfig }>;\n isBranching?: boolean; // true if this category contains actions that branch/split\n}\n\n/**\n * NodeTypeSelector - A dialog for selecting which type of node to create\n * Shows categorized lists of available actions and splits\n */\nexport class NodeTypeSelector extends RapidElement {\n static get styles() {\n return css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10001;\n display: none;\n }\n\n :host([open]) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .dialog {\n position: relative;\n background: white;\n border-radius: var(--curvature);\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n max-width: 700px;\n max-height: 80vh;\n width: 90%;\n display: flex;\n flex-direction: column;\n }\n\n .header {\n padding: 1.5em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .header h2 {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--color-text-dark);\n }\n\n .content {\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n padding: 0;\n }\n\n .section-regular {\n padding: 1.5em;\n }\n\n .section-branching {\n background: linear-gradient(\n 135deg,\n rgba(170, 170, 170, 0.12),\n rgba(170, 170, 170, 0.08)\n );\n padding: 1.5em;\n margin: 0 -1.5em;\n padding-left: 3em;\n padding-right: 3em;\n }\n\n .section-header {\n margin-bottom: 1.5em;\n padding-top: 1em;\n }\n\n .section-title {\n font-weight: 700;\n font-size: 1.1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.35em;\n display: flex;\n align-items: center;\n }\n\n .section-title::before {\n content: '';\n display: inline-block;\n height: 1.2em;\n background: linear-gradient(\n 135deg,\n var(--color-primary-dark),\n var(--color-primary)\n );\n border-radius: 2px;\n }\n\n .section-description {\n font-size: 0.9rem;\n color: var(--color-text);\n opacity: 0.7;\n margin-left: 0em;\n padding-bottom: 1em;\n }\n\n .category {\n margin-bottom: 2em;\n }\n\n .category:last-child {\n margin-bottom: 0;\n }\n\n .category-title {\n font-weight: 600;\n color: var(--color-text-dark);\n margin-bottom: 0.5em;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.9rem;\n opacity: 0.7;\n }\n\n .category-description {\n font-size: 0.85rem;\n color: var(--color-text);\n opacity: 0.6;\n margin-bottom: 0.75em;\n line-height: 1.4;\n }\n\n .items-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 0.75em;\n }\n\n .node-item {\n padding: 1em;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: calc(var(--curvature) * 0.75);\n cursor: pointer;\n transition: all 0.15s ease;\n background: white;\n position: relative;\n overflow: hidden;\n }\n\n .node-item::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--item-color, rgba(0, 0, 0, 0.1));\n }\n\n .node-item:hover {\n border-color: var(--item-color, var(--color-primary));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n transform: translateY(-1px);\n }\n\n .node-item:hover::before {\n width: 6px;\n }\n\n .node-item-title {\n font-weight: 500;\n font-size: 1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.25em;\n }\n\n .node-item-type {\n font-size: 0.75rem;\n color: var(--color-text);\n opacity: 0.6;\n font-family: monospace;\n }\n\n .footer {\n padding: 1em 1.5em;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n display: flex;\n justify-content: flex-end;\n }\n\n temba-button {\n --button-y: 0.5em;\n --button-x: 1.25em;\n }\n `;\n }\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: String })\n public mode: 'action' | 'split' | 'action-no-branching' = 'action';\n\n @state()\n private clickPosition = { x: 0, y: 0 };\n\n public show(\n mode: 'action' | 'split' | 'action-no-branching',\n position: { x: number; y: number }\n ) {\n this.mode = mode;\n this.clickPosition = position;\n this.open = true;\n }\n\n public close() {\n this.open = false;\n }\n\n private handleNodeTypeClick(nodeType: string) {\n this.fireCustomEvent(CustomEventType.Selection, {\n nodeType,\n position: this.clickPosition\n } as NodeTypeSelection);\n this.close();\n }\n\n private handleOverlayClick() {\n this.close();\n }\n\n private getCategories(): NodeCategory[] {\n if (this.mode === 'action' || this.mode === 'action-no-branching') {\n // Group actions by group\n const actionsByGroup = new Map<\n string,\n Array<{ type: string; config: ActionConfig }>\n >();\n const splitsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n // Collect regular actions (from ACTION_CONFIG, unless hideFromActions is true)\n Object.entries(ACTION_CONFIG)\n .filter(([_, config]) => {\n return config.name && !config.hideFromActions && config.group;\n })\n .forEach(([type, config]) => {\n const group = config.group;\n if (!actionsByGroup.has(group)) {\n actionsByGroup.set(group, []);\n }\n actionsByGroup.get(group)!.push({ type, config });\n });\n\n // Collect nodes that have showAsAction=true (these appear as \"with split\" actions)\n // Only if we're not in 'action-no-branching' mode\n if (this.mode === 'action') {\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n return (\n type !== 'execute_actions' &&\n config.name &&\n config.showAsAction &&\n config.group\n );\n })\n .forEach(([type, config]) => {\n const group = config.group!;\n if (!splitsByGroup.has(group)) {\n splitsByGroup.set(group, []);\n }\n splitsByGroup.get(group)!.push({ type, config });\n });\n }\n\n // Build categories - first regular actions, then splitting actions\n const categories: NodeCategory[] = [];\n\n // Get the implicit order from ACTION_GROUPS object\n const actionGroupOrder = Object.keys(ACTION_GROUPS);\n // Get the implicit order of actions from ACTION_CONFIG\n const actionConfigOrder = Object.keys(ACTION_CONFIG);\n\n // Add regular action categories sorted by implicit order\n const sortedActionCategories = Array.from(actionsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedActionCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in ACTION_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = actionConfigOrder.indexOf(a.type);\n const orderB = actionConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: false\n });\n });\n\n // Add splitting action categories (with modified description to indicate they split)\n // Also sorted by implicit order\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n const sortedSplitCategories = Array.from(splitsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedSplitCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: true\n });\n });\n\n return categories;\n } else {\n // Group splits by group\n const itemsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n // exclude execute_actions (it's the default action-only node)\n // exclude nodes that have showAsAction=true (they appear in action mode)\n return (\n type !== 'execute_actions' && config.name && !config.showAsAction\n );\n })\n .forEach(([type, config]) => {\n const group = config.group || SPLIT_GROUPS.split;\n if (!itemsByGroup.has(group)) {\n itemsByGroup.set(group, []);\n }\n itemsByGroup.get(group)!.push({ type, config });\n });\n\n // Convert to categories using group metadata, sorted by implicit order from SPLIT_GROUPS\n const splitGroupOrder = Object.keys(SPLIT_GROUPS);\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n return Array.from(itemsByGroup.entries())\n .map(([group, items]) => {\n const metadata =\n SPLIT_GROUP_METADATA[group] || ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n return {\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems\n };\n })\n .sort((a, b) => {\n // Find the group key by looking up metadata by title\n const groupA = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === a.name\n )!;\n const groupB = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === b.name\n )!;\n const orderA = splitGroupOrder.indexOf(groupA);\n const orderB = splitGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n }\n }\n\n public render(): TemplateResult {\n if (!this.open) {\n return html``;\n }\n\n const categories = this.getCategories();\n const title =\n this.mode === 'split'\n ? 'Select a Split'\n : this.mode === 'action-no-branching'\n ? 'Add Action'\n : 'Select an Action';\n\n // Separate regular and branching categories for action mode\n const regularCategories = categories.filter((c) => !c.isBranching);\n const branchingCategories = categories.filter((c) => c.isBranching);\n const hasBranchingSection = branchingCategories.length > 0;\n\n return html`\n <div class=\"overlay\" @click=${this.handleOverlayClick}></div>\n <div class=\"dialog\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"header\">\n <h2>${title}</h2>\n </div>\n <div class=\"content\">\n ${this.mode === 'action' || this.mode === 'action-no-branching'\n ? html`\n <div class=\"section-regular\">\n ${regularCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n ${hasBranchingSection\n ? html`\n <div class=\"section-branching\">\n <div class=\"section-header\">\n <div class=\"section-title\">Actions that Branch</div>\n <div class=\"section-description\">\n These actions also split the flow based on their\n outcome\n </div>\n </div>\n ${branchingCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">\n ${item.type}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n `\n : html`\n <div class=\"section-regular\">\n ${categories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `}\n </div>\n <div class=\"footer\">\n <temba-button @click=${this.close} secondary>Cancel</temba-button>\n </div>\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"NodeTypeSelector.js","sourceRoot":"","sources":["../../../src/flow/NodeTypeSelector.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAGL,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAqBjB;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAAlD;;QAyMS,SAAI,GAAG,KAAK,CAAC;QAGb,SAAI,GAA+C,QAAQ,CAAC;QAG5D,aAAQ,GAAW,SAAS,CAAC;QAG7B,aAAQ,GAAa,EAAE,CAAC;QAGvB,kBAAa,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAiYzC,CAAC;IArlBC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmMT,CAAC;IACJ,CAAC;IAiBM,IAAI,CACT,IAAgD,EAChD,QAAkC;QAElC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,MAAiC;QACzD,yBAAyB;QACzB,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,gEAAgE;YAChE,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,+DAA+D;YAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAe,CAAC,EAAE,CAAC;gBACrD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,8DAA8D;QAE9D,gEAAgE;QAChE,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,KAAK,MAAM,eAAe,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC9C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBAC7C,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,mBAAmB,CAAC,QAAgB;QAC1C,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9C,QAAQ;YACR,QAAQ,EAAE,IAAI,CAAC,aAAa;SACR,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YAClE,yBAAyB;YACzB,MAAM,cAAc,GAAG,IAAI,GAAG,EAG3B,CAAC;YACJ,MAAM,aAAa,GAAG,IAAI,GAAG,EAG1B,CAAC;YAEJ,+EAA+E;YAC/E,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;iBAC1B,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE;gBACtB,OAAO,CACL,MAAM,CAAC,IAAI;oBACX,CAAC,MAAM,CAAC,eAAe;oBACvB,MAAM,CAAC,KAAK;oBACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;YACJ,CAAC,CAAC;iBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;gBAC3B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAChC,CAAC;gBACD,cAAc,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEL,mFAAmF;YACnF,kDAAkD;YAClD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;qBACxB,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;oBACzB,OAAO,CACL,IAAI,KAAK,iBAAiB;wBAC1B,MAAM,CAAC,IAAI;wBACX,MAAM,CAAC,YAAY;wBACnB,MAAM,CAAC,KAAK;wBACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;gBACJ,CAAC,CAAC;qBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;oBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAM,CAAC;oBAC5B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC9B,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC/B,CAAC;oBACD,aAAa,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnD,CAAC,CAAC,CAAC;YACP,CAAC;YAED,mEAAmE;YACnE,MAAM,UAAU,GAAmB,EAAE,CAAC;YAEtC,mDAAmD;YACnD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACpD,uDAAuD;YACvD,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAErD,yDAAyD;YACzD,MAAM,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACtE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;gBACrB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CACF,CAAC;YAEF,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBAChD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,iEAAiE;gBACjE,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACjD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACjD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;oBAClB,WAAW,EAAE,KAAK;iBACnB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,qFAAqF;YACrF,gCAAgC;YAChC,mDAAmD;YACnD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEjD,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACpE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;gBACrB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CACF,CAAC;YAEF,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBAC/C,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,+DAA+D;gBAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;oBAClB,WAAW,EAAE,IAAI;iBAClB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,OAAO,UAAU,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,wBAAwB;YACxB,MAAM,YAAY,GAAG,IAAI,GAAG,EAGzB,CAAC;YAEJ,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;iBACxB,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,8DAA8D;gBAC9D,yEAAyE;gBACzE,OAAO,CACL,IAAI,KAAK,iBAAiB;oBAC1B,MAAM,CAAC,IAAI;oBACX,CAAC,MAAM,CAAC,YAAY;oBACpB,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;YACJ,CAAC,CAAC;iBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC;gBACjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7B,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC9B,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC;YAEL,yFAAyF;YACzF,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAClD,mDAAmD;YACnD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEjD,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBACtB,MAAM,QAAQ,GACZ,oBAAoB,CAAC,KAAK,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9D,+DAA+D;gBAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,OAAO;oBACL,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;iBACnB,CAAC;YACJ,CAAC,CAAC;iBACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACb,qDAAqD;gBACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACnD,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CACnD,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACnD,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CACnD,CAAC;gBACH,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC;IAEM,MAAM;QACX,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAA,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,OAAO;YACnB,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,qBAAqB;gBACrC,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,kBAAkB,CAAC;QAEzB,4DAA4D;QAC5D,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACpE,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAA;oCACqB,IAAI,CAAC,kBAAkB;mCACxB,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;;gBAEpD,KAAK;;;YAGT,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;YAC7D,CAAC,CAAC,IAAI,CAAA;;oBAEE,iBAAiB,CAAC,GAAG,CACrB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;sDAEgB,QAAQ,CAAC,IAAI;;4BAEvC,QAAQ,CAAC,WAAW;;;4BAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;uDAGa,QAAQ,CAAC,KAAK;yCAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;oCAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;8DAEU,IAAI,CAAC,IAAI;;6BAE1C,CACF;;;qBAGN,CACF;;kBAED,mBAAmB;gBACnB,CAAC,CAAC,IAAI,CAAA;;;;;;;;;0BASE,mBAAmB,CAAC,GAAG,CACvB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;4DAEgB,QAAQ,CAAC,IAAI;;kCAEvC,QAAQ,CAAC,WAAW;;;kCAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;6DAGa,QAAQ,CAAC,KAAK;+CAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;0CAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;;0CAGhB,IAAI,CAAC,IAAI;;;mCAGhB,CACF;;;2BAGN,CACF;;qBAEJ;gBACH,CAAC,CAAC,EAAE;eACP;YACH,CAAC,CAAC,IAAI,CAAA;;oBAEE,UAAU,CAAC,GAAG,CACd,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;sDAEgB,QAAQ,CAAC,IAAI;;4BAEvC,QAAQ,CAAC,WAAW;;;4BAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;uDAGa,QAAQ,CAAC,KAAK;yCAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;oCAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;8DAEU,IAAI,CAAC,IAAI;;6BAE1C,CACF;;;qBAGN,CACF;;eAEJ;;;iCAGkB,IAAI,CAAC,KAAK;;;KAGtC,CAAC;IACJ,CAAC;CACF;AA7YQ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8CACvB;AAGb;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CACwC;AAG5D;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDACS;AAG7B;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;kDACK;AAGvB;IADP,KAAK,EAAE;uDAC+B","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { NODE_CONFIG, ACTION_CONFIG } from './config';\nimport {\n NodeConfig,\n ActionConfig,\n ACTION_GROUPS,\n SPLIT_GROUPS,\n ACTION_GROUP_METADATA,\n SPLIT_GROUP_METADATA\n} from './types';\n\n/**\n * Event detail for node type selection\n */\nexport interface NodeTypeSelection {\n nodeType: string;\n position: { x: number; y: number };\n}\n\n/**\n * Categorizes node types for display\n */\ninterface NodeCategory {\n name: string;\n description: string;\n color: string;\n items: Array<{ type: string; config: NodeConfig | ActionConfig }>;\n isBranching?: boolean; // true if this category contains actions that branch/split\n}\n\n/**\n * NodeTypeSelector - A dialog for selecting which type of node to create\n * Shows categorized lists of available actions and splits\n */\nexport class NodeTypeSelector extends RapidElement {\n static get styles() {\n return css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10001;\n display: none;\n }\n\n :host([open]) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .dialog {\n position: relative;\n background: white;\n border-radius: var(--curvature);\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n max-width: 700px;\n max-height: 80vh;\n width: 90%;\n display: flex;\n flex-direction: column;\n }\n\n .header {\n padding: 1.5em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .header h2 {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--color-text-dark);\n }\n\n .content {\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n padding: 0;\n }\n\n .section-regular {\n padding: 1.5em;\n }\n\n .section-branching {\n background: linear-gradient(\n 135deg,\n rgba(170, 170, 170, 0.12),\n rgba(170, 170, 170, 0.08)\n );\n padding: 1.5em;\n margin: 0 -1.5em;\n padding-left: 3em;\n padding-right: 3em;\n }\n\n .section-header {\n margin-bottom: 1.5em;\n padding-top: 1em;\n }\n\n .section-title {\n font-weight: 700;\n font-size: 1.1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.35em;\n display: flex;\n align-items: center;\n }\n\n .section-title::before {\n content: '';\n display: inline-block;\n height: 1.2em;\n background: linear-gradient(\n 135deg,\n var(--color-primary-dark),\n var(--color-primary)\n );\n border-radius: 2px;\n }\n\n .section-description {\n font-size: 0.9rem;\n color: var(--color-text);\n opacity: 0.7;\n margin-left: 0em;\n padding-bottom: 1em;\n }\n\n .category {\n margin-bottom: 2em;\n }\n\n .category:last-child {\n margin-bottom: 0;\n }\n\n .category-title {\n font-weight: 600;\n color: var(--color-text-dark);\n margin-bottom: 0.5em;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.9rem;\n opacity: 0.7;\n }\n\n .category-description {\n font-size: 0.85rem;\n color: var(--color-text);\n opacity: 0.6;\n margin-bottom: 0.75em;\n line-height: 1.4;\n }\n\n .items-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 0.75em;\n }\n\n .node-item {\n padding: 1em;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: calc(var(--curvature) * 0.75);\n cursor: pointer;\n transition: all 0.15s ease;\n background: white;\n position: relative;\n overflow: hidden;\n }\n\n .node-item::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--item-color, rgba(0, 0, 0, 0.1));\n }\n\n .node-item:hover {\n border-color: var(--item-color, var(--color-primary));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n transform: translateY(-1px);\n }\n\n .node-item:hover::before {\n width: 6px;\n }\n\n .node-item-title {\n font-weight: 500;\n font-size: 1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.25em;\n }\n\n .node-item-type {\n font-size: 0.75rem;\n color: var(--color-text);\n opacity: 0.6;\n font-family: monospace;\n }\n\n .footer {\n padding: 1em 1.5em;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n display: flex;\n justify-content: flex-end;\n }\n\n temba-button {\n --button-y: 0.5em;\n --button-x: 1.25em;\n }\n `;\n }\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: String })\n public mode: 'action' | 'split' | 'action-no-branching' = 'action';\n\n @property({ type: String })\n public flowType: string = 'message';\n\n @property({ type: Array })\n public features: string[] = [];\n\n @state()\n private clickPosition = { x: 0, y: 0 };\n\n public show(\n mode: 'action' | 'split' | 'action-no-branching',\n position: { x: number; y: number }\n ) {\n this.mode = mode;\n this.clickPosition = position;\n this.open = true;\n }\n\n public close() {\n this.open = false;\n }\n\n /**\n * Check if a config is available for the current flow type and features\n */\n private isConfigAvailable(config: NodeConfig | ActionConfig): boolean {\n // Check flow type filter\n if (config.flowTypes !== undefined) {\n // Empty array means not available for any flow type in selector\n if (config.flowTypes.length === 0) {\n return false;\n }\n // Non-empty array means check if current flow type is included\n if (!config.flowTypes.includes(this.flowType as any)) {\n return false;\n }\n }\n // undefined/null flowTypes means available for all flow types\n\n // Check features filter - all required features must be present\n if (config.features && config.features.length > 0) {\n for (const requiredFeature of config.features) {\n if (!this.features.includes(requiredFeature)) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n private handleNodeTypeClick(nodeType: string) {\n this.fireCustomEvent(CustomEventType.Selection, {\n nodeType,\n position: this.clickPosition\n } as NodeTypeSelection);\n this.close();\n }\n\n private handleOverlayClick() {\n this.close();\n }\n\n private getCategories(): NodeCategory[] {\n if (this.mode === 'action' || this.mode === 'action-no-branching') {\n // Group actions by group\n const actionsByGroup = new Map<\n string,\n Array<{ type: string; config: ActionConfig }>\n >();\n const splitsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n // Collect regular actions (from ACTION_CONFIG, unless hideFromActions is true)\n Object.entries(ACTION_CONFIG)\n .filter(([_, config]) => {\n return (\n config.name &&\n !config.hideFromActions &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group;\n if (!actionsByGroup.has(group)) {\n actionsByGroup.set(group, []);\n }\n actionsByGroup.get(group)!.push({ type, config });\n });\n\n // Collect nodes that have showAsAction=true (these appear as \"with split\" actions)\n // Only if we're not in 'action-no-branching' mode\n if (this.mode === 'action') {\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n return (\n type !== 'execute_actions' &&\n config.name &&\n config.showAsAction &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group!;\n if (!splitsByGroup.has(group)) {\n splitsByGroup.set(group, []);\n }\n splitsByGroup.get(group)!.push({ type, config });\n });\n }\n\n // Build categories - first regular actions, then splitting actions\n const categories: NodeCategory[] = [];\n\n // Get the implicit order from ACTION_GROUPS object\n const actionGroupOrder = Object.keys(ACTION_GROUPS);\n // Get the implicit order of actions from ACTION_CONFIG\n const actionConfigOrder = Object.keys(ACTION_CONFIG);\n\n // Add regular action categories sorted by implicit order\n const sortedActionCategories = Array.from(actionsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedActionCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in ACTION_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = actionConfigOrder.indexOf(a.type);\n const orderB = actionConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: false\n });\n });\n\n // Add splitting action categories (with modified description to indicate they split)\n // Also sorted by implicit order\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n const sortedSplitCategories = Array.from(splitsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedSplitCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: true\n });\n });\n\n return categories;\n } else {\n // Group splits by group\n const itemsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n // exclude execute_actions (it's the default action-only node)\n // exclude nodes that have showAsAction=true (they appear in action mode)\n return (\n type !== 'execute_actions' &&\n config.name &&\n !config.showAsAction &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group || SPLIT_GROUPS.split;\n if (!itemsByGroup.has(group)) {\n itemsByGroup.set(group, []);\n }\n itemsByGroup.get(group)!.push({ type, config });\n });\n\n // Convert to categories using group metadata, sorted by implicit order from SPLIT_GROUPS\n const splitGroupOrder = Object.keys(SPLIT_GROUPS);\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n return Array.from(itemsByGroup.entries())\n .map(([group, items]) => {\n const metadata =\n SPLIT_GROUP_METADATA[group] || ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n return {\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems\n };\n })\n .sort((a, b) => {\n // Find the group key by looking up metadata by title\n const groupA = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === a.name\n )!;\n const groupB = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === b.name\n )!;\n const orderA = splitGroupOrder.indexOf(groupA);\n const orderB = splitGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n }\n }\n\n public render(): TemplateResult {\n if (!this.open) {\n return html``;\n }\n\n const categories = this.getCategories();\n const title =\n this.mode === 'split'\n ? 'Select a Split'\n : this.mode === 'action-no-branching'\n ? 'Add Action'\n : 'Select an Action';\n\n // Separate regular and branching categories for action mode\n const regularCategories = categories.filter((c) => !c.isBranching);\n const branchingCategories = categories.filter((c) => c.isBranching);\n const hasBranchingSection = branchingCategories.length > 0;\n\n return html`\n <div class=\"overlay\" @click=${this.handleOverlayClick}></div>\n <div class=\"dialog\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"header\">\n <h2>${title}</h2>\n </div>\n <div class=\"content\">\n ${this.mode === 'action' || this.mode === 'action-no-branching'\n ? html`\n <div class=\"section-regular\">\n ${regularCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n ${hasBranchingSection\n ? html`\n <div class=\"section-branching\">\n <div class=\"section-header\">\n <div class=\"section-title\">Actions that Branch</div>\n <div class=\"section-description\">\n These actions also split the flow based on their\n outcome\n </div>\n </div>\n ${branchingCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">\n ${item.type}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n `\n : html`\n <div class=\"section-regular\">\n ${categories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `}\n </div>\n <div class=\"footer\">\n <temba-button @click=${this.close} secondary>Cancel</temba-button>\n </div>\n </div>\n `;\n }\n}\n"]}
@@ -3,6 +3,7 @@ import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { RapidElement } from '../RapidElement';
5
5
  import { getStore } from '../store/Store';
6
+ import { fromStore, zustand } from '../store/AppState';
6
7
  export class StickyNote extends RapidElement {
7
8
  constructor() {
8
9
  super(...arguments);
@@ -109,6 +110,8 @@ export class StickyNote extends RapidElement {
109
110
  border-top-left-radius: var(--curvature);
110
111
  border-top-right-radius: var(--curvature);
111
112
  flex-grow: 1;
113
+ padding: 4px 8px !important;
114
+ margin: 2px;
112
115
  padding-left: 8px;
113
116
  }
114
117
  .sticky-title:empty::before {
@@ -129,6 +132,7 @@ export class StickyNote extends RapidElement {
129
132
  min-height: 48px;
130
133
  word-wrap: break-word;
131
134
  white-space: pre-wrap;
135
+ margin: 2px;
132
136
  }
133
137
  .sticky-body:empty::before {
134
138
  content: 'Click to add note';
@@ -342,7 +346,7 @@ export class StickyNote extends RapidElement {
342
346
  <temba-icon name="drag" class="drag-handle"></temba-icon>
343
347
  <div
344
348
  class="sticky-title"
345
- contenteditable="true"
349
+ contenteditable="${!this.isTranslating}"
346
350
  @blur="${this.handleTitleBlur}"
347
351
  @keydown="${this.handleKeyDown}"
348
352
  @mousedown="${this.handleContentMouseDown}"
@@ -352,13 +356,15 @@ export class StickyNote extends RapidElement {
352
356
  <div class="sticky-body-container">
353
357
  <div
354
358
  class="sticky-body"
355
- contenteditable="true"
359
+ contenteditable="${!this.isTranslating}"
356
360
  @blur="${this.handleBodyBlur}"
357
361
  @keydown="${this.handleKeyDown}"
358
362
  @mousedown="${this.handleContentMouseDown}"
359
363
  .textContent="${this.data.body}"
360
364
  ></div>
361
- <div class="edit-icon" title="Edit note"></div>
365
+ ${!this.isTranslating
366
+ ? html `<div class="edit-icon" title="Edit note"></div>`
367
+ : ''}
362
368
 
363
369
  <!-- Color picker -->
364
370
  <div
@@ -413,4 +419,7 @@ __decorate([
413
419
  __decorate([
414
420
  property({ type: Boolean })
415
421
  ], StickyNote.prototype, "colorPickerExpanded", void 0);
422
+ __decorate([
423
+ fromStore(zustand, (state) => state.isTranslating)
424
+ ], StickyNote.prototype, "isTranslating", void 0);
416
425
  //# sourceMappingURL=StickyNote.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newBody = target.textContent || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n private handleColorOptionClick(\n event: MouseEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon name=\"drag\" class=\"drag-handle\"></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"true\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"true\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.body}\"\n ></div>\n <div class=\"edit-icon\" title=\"Edit note\"></div>\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"StickyNote.js","sourceRoot":"","sources":["../../../src/flow/StickyNote.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { StickyNote as StickyNoteData } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\n\nexport class StickyNote extends RapidElement {\n @property({ type: String })\n public uuid: string;\n\n @property({ type: Object })\n public data: StickyNoteData;\n\n @property({ type: Boolean })\n private dragging = false;\n\n @property({ type: Boolean })\n public selected = false;\n\n @property({ type: Boolean })\n private colorPickerExpanded = false;\n\n @fromStore(zustand, (state: AppState) => state.isTranslating)\n private isTranslating!: boolean;\n\n static get styles() {\n return css`\n :host {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n --curvature: 8px;\n }\n\n .sticky-note {\n width: 182px;\n background-color: var(--sticky-color);\n border: 1px solid var(--sticky-border-color);\n border-radius: var(--curvature);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n sans-serif;\n font-size: 12px;\n overflow: hidden;\n transition: transform 0.1s ease, box-shadow 0.2s ease;\n color: var(--sticky-text-color);\n opacity: 0.85;\n }\n\n .sticky-note.dragging {\n opacity: 0.7;\n z-index: 1000;\n transform: rotate(0deg);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:hover {\n transform: translateY(0px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n }\n\n /* Color themes */\n .sticky-note.yellow {\n --sticky-color: #fef08a;\n --sticky-border-color: #facc15;\n --sticky-text-color: #451a03;\n }\n .sticky-note.blue {\n --sticky-color: #bfdbfe;\n --sticky-border-color: #3b82f6;\n --sticky-text-color: #1e3a8a;\n }\n .sticky-note.pink {\n --sticky-color: #fce7f3;\n --sticky-border-color: #ec4899;\n --sticky-text-color: #831843;\n }\n .sticky-note.green {\n --sticky-color: #d1fae5;\n --sticky-border-color: #10b981;\n --sticky-text-color: #064e3b;\n }\n .sticky-note.gray {\n --sticky-color: #f3f4f6;\n --sticky-border-color: #6b7280;\n --sticky-text-color: #374151;\n }\n\n /* Title and body containers */\n .sticky-title-container {\n position: relative;\n border-bottom: 1px solid var(--sticky-border-color);\n background-color: rgba(255, 255, 255, 0.5);\n display: flex;\n align-items: center;\n }\n .sticky-body-container {\n position: relative;\n }\n\n /* Editable fields */\n [contenteditable='true'] {\n margin: 2px;\n padding: 4px 8px;\n outline: none;\n border-radius: var(--curvature);\n transition: background 0.2s;\n }\n [contenteditable='true']:focus {\n background-color: rgba(255, 255, 255, 0.8);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n outline-color: var(--sticky-border-color);\n }\n\n /* Title */\n .sticky-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--sticky-text-color);\n min-height: 20px;\n line-height: 20px;\n border-top-left-radius: var(--curvature);\n border-top-right-radius: var(--curvature);\n flex-grow: 1;\n padding: 4px 8px !important;\n margin: 2px;\n padding-left: 8px;\n }\n .sticky-title:empty::before {\n content: 'Click to add title';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-title:focus {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n /* Body */\n .sticky-body {\n padding: 8px 10px;\n color: var(--sticky-text-color);\n line-height: 1.4;\n min-height: 48px;\n word-wrap: break-word;\n white-space: pre-wrap;\n margin: 2px;\n }\n .sticky-body:empty::before {\n content: 'Click to add note';\n opacity: 0.5;\n font-style: italic;\n }\n .sticky-body:focus {\n border-top-left-radius: 0px;\n border-top-right-radius: 0px;\n }\n\n /* Drag icon */\n .sticky-title-container > .drag-handle {\n --icon-color: var(--sticky-border-color);\n cursor: move;\n max-width: 20px;\n padding-left: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .sticky-note:hover .drag-handle {\n }\n\n .sticky-note:focus-within .sticky-title-container > .drag-handle {\n }\n\n /* Focus/active states */\n .sticky-note:focus-within {\n box-shadow: 0 0 0 1px var(--sticky-border-color),\n 0 10px 20px rgba(0, 0, 0, 0.3);\n }\n\n .sticky-note:focus-within .drag-handle {\n max-width: 0px;\n padding-left: 0px;\n }\n\n /* Color picker */\n .color-picker {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 8px;\n height: 8px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n\n border-radius: 3px;\n background-color: var(--sticky-color);\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n\n .color-picker:hover {\n transform: scale(1.1);\n }\n\n .color-options {\n position: absolute;\n bottom: 0;\n right: 0;\n display: flex;\n gap: 4px;\n background-color: rgba(255, 255, 255, 0.9);\n border: 1px solid #ccc;\n border-radius: 6px;\n padding: 3px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform-origin: bottom right;\n transform: scale(0);\n opacity: 0;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: 1000;\n }\n\n .color-options.expanded {\n transform: scale(1);\n opacity: 1;\n }\n\n .color-option {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n cursor: pointer;\n transition: transform 0.15s ease, border-color 0.15s ease;\n }\n\n .color-option:hover {\n transform: scale(1.1);\n border-color: rgba(0, 0, 0, 0.4);\n }\n\n .color-option.yellow {\n background-color: #fef08a;\n }\n\n .color-option.blue {\n background-color: #bfdbfe;\n }\n\n .color-option.pink {\n background-color: #fce7f3;\n }\n\n .color-option.green {\n background-color: #d1fae5;\n }\n\n .color-option.gray {\n background-color: #f3f4f6;\n }\n `;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('uuid')) {\n this.updateCanvasSize();\n }\n }\n\n private updateCanvasSize(): void {\n if (!this.data) {\n return;\n }\n\n const element = this.querySelector('.sticky-note');\n if (element) {\n const rect = element.getBoundingClientRect();\n getStore()\n .getState()\n .expandCanvas(\n this.data.position.left + rect.width,\n this.data.position.top + rect.height\n );\n }\n }\n\n private handleTitleBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newTitle = target.textContent || '';\n\n if (this.data && newTitle !== this.data.title) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n title: newTitle\n });\n }\n this.requestUpdate();\n }\n\n private handleBodyBlur(event: FocusEvent): void {\n const target = event.target as HTMLElement;\n const newBody = target.textContent || '';\n\n if (this.data && newBody !== this.data.body) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n body: newBody\n });\n }\n this.requestUpdate();\n }\n\n private handleContentMouseDown(event: MouseEvent): void {\n // If this sticky note is selected, don't stop propagation\n // so that group dragging can work\n if (this.selected) {\n return;\n }\n // Otherwise, stop propagation to enable editing\n event.stopPropagation();\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n (event.target as HTMLElement).blur();\n }\n if (event.key === 'Escape') {\n (event.target as HTMLElement).blur();\n }\n }\n\n private handleColorPickerMouseEnter(): void {\n this.colorPickerExpanded = true;\n }\n\n private handleColorPickerMouseLeave(): void {\n this.colorPickerExpanded = false;\n }\n\n private handleColorOptionClick(\n event: MouseEvent,\n color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'\n ): void {\n event.stopPropagation();\n\n if (this.data && color !== this.data.color) {\n getStore()\n .getState()\n .updateStickyNote(this.uuid, {\n ...this.data,\n color: color\n });\n }\n\n this.colorPickerExpanded = false;\n this.requestUpdate();\n }\n\n public render(): TemplateResult {\n if (!this.data) {\n return html`<div class=\"sticky-note\" style=\"display: none;\"></div>`;\n }\n\n const style = `left: ${this.data.position.left}px; top: ${this.data.position.top}px;`;\n\n return html`\n <div\n class=\"sticky-note ${this.data.color} ${this.dragging\n ? 'dragging'\n : ''}\"\n style=\"${style}\"\n data-uuid=\"${this.uuid}\"\n >\n <div class=\"sticky-title-container\">\n <temba-icon name=\"drag\" class=\"drag-handle\"></temba-icon>\n <div\n class=\"sticky-title\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleTitleBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.title}\"\n ></div>\n </div>\n <div class=\"sticky-body-container\">\n <div\n class=\"sticky-body\"\n contenteditable=\"${!this.isTranslating}\"\n @blur=\"${this.handleBodyBlur}\"\n @keydown=\"${this.handleKeyDown}\"\n @mousedown=\"${this.handleContentMouseDown}\"\n .textContent=\"${this.data.body}\"\n ></div>\n ${!this.isTranslating\n ? html`<div class=\"edit-icon\" title=\"Edit note\"></div>`\n : ''}\n\n <!-- Color picker -->\n <div\n class=\"color-picker\"\n @mouseenter=\"${this.handleColorPickerMouseEnter}\"\n @mouseleave=\"${this.handleColorPickerMouseLeave}\"\n >\n <div\n class=\"color-options ${this.colorPickerExpanded\n ? 'expanded'\n : ''}\"\n >\n <div\n class=\"color-option yellow\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'yellow')}\"\n ></div>\n <div\n class=\"color-option blue\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'blue')}\"\n ></div>\n <div\n class=\"color-option pink\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'pink')}\"\n ></div>\n <div\n class=\"color-option green\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'green')}\"\n ></div>\n <div\n class=\"color-option gray\"\n @click=\"${(e: MouseEvent) =>\n this.handleColorOptionClick(e, 'gray')}\"\n ></div>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n}\n"]}
@@ -1,9 +1,10 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { renderNamedObjects } from '../utils';
4
4
  export const add_contact_groups = {
5
5
  name: 'Add to Group',
6
6
  group: ACTION_GROUPS.contacts,
7
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
7
8
  render: (_node, action) => {
8
9
  return html `<div>${renderNamedObjects(action.groups, 'group')}</div>`;
9
10
  },
@@ -1 +1 @@
1
- {"version":3,"file":"add_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,MAAM,UAAU,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,MAAM,EAAE,CAAC,KAAW,EAAE,MAAkB,EAAE,EAAE;QAC1C,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IAED,iEAAiE;IACjE,UAAU,EAAE,CAAC,MAAkB,EAAE,EAAE;QACjC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,yCAAyC;YACnD,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,CAAC,KAAa,EAAE,OAAc,EAAE,EAAE;gBACvD,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC3B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAClE,CAAC;gBACF,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC9B,OAAO;wBACL,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;wBAClB,SAAS,EAAE,IAAI;qBAChB,CAAC;gBACJ,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAc,EAAE;QAC/C,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;SAC9B,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData } from '../types';\nimport { Node, AddToGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const add_contact_groups: ActionConfig = {\n name: 'Add to Group',\n group: ACTION_GROUPS.contacts,\n render: (_node: Node, action: AddToGroup) => {\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n\n // Form-level transformations - default 1:1 mapping for this case\n toFormData: (action: AddToGroup) => {\n return {\n groups: action.groups || null,\n uuid: action.uuid\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to add the contact to',\n required: true,\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a label with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n }\n },\n fromFormData: (formData: FormData): AddToGroup => {\n return {\n uuid: formData.uuid,\n type: 'add_contact_groups',\n groups: formData.groups || []\n };\n }\n};\n"]}
1
+ {"version":3,"file":"add_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAkB,EAAE,EAAE;QAC1C,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IAED,iEAAiE;IACjE,UAAU,EAAE,CAAC,MAAkB,EAAE,EAAE;QACjC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,yCAAyC;YACnD,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,CAAC,KAAa,EAAE,OAAc,EAAE,EAAE;gBACvD,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC3B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAClE,CAAC;gBACF,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC9B,OAAO;wBACL,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;wBAClB,SAAS,EAAE,IAAI;qBAChB,CAAC;gBACJ,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAc,EAAE;QAC/C,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;SAC9B,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, AddToGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const add_contact_groups: ActionConfig = {\n name: 'Add to Group',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: AddToGroup) => {\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n\n // Form-level transformations - default 1:1 mapping for this case\n toFormData: (action: AddToGroup) => {\n return {\n groups: action.groups || null,\n uuid: action.uuid\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to add the contact to',\n required: true,\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a label with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n }\n },\n fromFormData: (formData: FormData): AddToGroup => {\n return {\n uuid: formData.uuid,\n type: 'add_contact_groups',\n groups: formData.groups || []\n };\n }\n};\n"]}
@@ -1,9 +1,10 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { SCHEMES } from '../utils';
4
4
  export const add_contact_urn = {
5
5
  name: 'Add URN',
6
6
  group: ACTION_GROUPS.contacts,
7
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
7
8
  render: (_node, action) => {
8
9
  const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);
9
10
  const friendlyScheme = (schemeObj === null || schemeObj === void 0 ? void 0 : schemeObj.path) || action.scheme;
@@ -1 +1 @@
1
- {"version":3,"file":"add_contact_urn.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_urn.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult\n} from '../types';\nimport { Node, AddContactUrn } from '../../store/flow-definition';\nimport { SCHEMES } from '../utils';\n\nexport const add_contact_urn: ActionConfig = {\n name: 'Add URN',\n group: ACTION_GROUPS.contacts,\n render: (_node: Node, action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n const friendlyScheme = schemeObj?.path || action.scheme;\n return html`<div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n Add ${friendlyScheme} <strong>${action.path}</strong>\n </div>`;\n },\n\n toFormData: (action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n return {\n uuid: action.uuid,\n scheme: schemeObj\n ? [{ name: schemeObj.path, value: action.scheme }]\n : null,\n path: action.path || ''\n };\n },\n\n fromFormData: (formData: FormData): AddContactUrn => {\n // Extract scheme value from select format\n const schemeValue =\n Array.isArray(formData.scheme) && formData.scheme.length > 0\n ? formData.scheme[0].value\n : 'tel';\n\n return {\n uuid: formData.uuid,\n type: 'add_contact_urn',\n scheme: schemeValue,\n path: formData.path || ''\n };\n },\n\n form: {\n scheme: {\n type: 'select',\n label: 'URN Type',\n helpText: 'Select the type of URN to add to the contact',\n required: true,\n searchable: false,\n multi: false,\n options: SCHEMES.map((scheme) => ({\n name: scheme.path,\n value: scheme.scheme\n }))\n },\n path: {\n type: 'text',\n label: 'URN Value',\n helpText: 'Enter the URN value (e.g., phone number, Facebook ID, etc.)',\n required: true,\n placeholder: 'Enter the URN value...',\n evaluated: true\n }\n },\n\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.scheme || formData.scheme.length === 0) {\n errors.scheme = 'URN type is required';\n }\n\n if (!formData.path || formData.path.trim() === '') {\n errors.path = 'URN value is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
1
+ {"version":3,"file":"add_contact_urn.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_contact_urn.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, AddContactUrn } from '../../store/flow-definition';\nimport { SCHEMES } from '../utils';\n\nexport const add_contact_urn: ActionConfig = {\n name: 'Add URN',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n const friendlyScheme = schemeObj?.path || action.scheme;\n return html`<div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n Add ${friendlyScheme} <strong>${action.path}</strong>\n </div>`;\n },\n\n toFormData: (action: AddContactUrn) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === action.scheme);\n return {\n uuid: action.uuid,\n scheme: schemeObj\n ? [{ name: schemeObj.path, value: action.scheme }]\n : null,\n path: action.path || ''\n };\n },\n\n fromFormData: (formData: FormData): AddContactUrn => {\n // Extract scheme value from select format\n const schemeValue =\n Array.isArray(formData.scheme) && formData.scheme.length > 0\n ? formData.scheme[0].value\n : 'tel';\n\n return {\n uuid: formData.uuid,\n type: 'add_contact_urn',\n scheme: schemeValue,\n path: formData.path || ''\n };\n },\n\n form: {\n scheme: {\n type: 'select',\n label: 'URN Type',\n helpText: 'Select the type of URN to add to the contact',\n required: true,\n searchable: false,\n multi: false,\n options: SCHEMES.map((scheme) => ({\n name: scheme.path,\n value: scheme.scheme\n }))\n },\n path: {\n type: 'text',\n label: 'URN Value',\n helpText: 'Enter the URN value (e.g., phone number, Facebook ID, etc.)',\n required: true,\n placeholder: 'Enter the URN value...',\n evaluated: true\n }\n },\n\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.scheme || formData.scheme.length === 0) {\n errors.scheme = 'URN type is required';\n }\n\n if (!formData.path || formData.path.trim() === '') {\n errors.path = 'URN value is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
@@ -1,9 +1,10 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { renderNamedObjects } from '../utils';
4
4
  export const add_input_labels = {
5
5
  name: 'Add Input Labels',
6
6
  group: ACTION_GROUPS.save,
7
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
7
8
  render: (_node, action) => {
8
9
  return html `<div>${renderNamedObjects(action.labels, 'label')}</div>`;
9
10
  },
@@ -1 +1 @@
1
- {"version":3,"file":"add_input_labels.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_input_labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,MAAM,UAAU,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAsB,EAAE,EAAE;QAC9C,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IAED,6BAA6B;IAC7B,UAAU,EAAE,CAAC,MAAsB,EAAE,EAAE;QACrC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EACN,wEAAwE;YAC1E,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,iDAAiD;YAC9D,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,CAAC,KAAa,EAAE,OAAc,EAAE,EAAE;gBACvD,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC3B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAClE,CAAC;gBACF,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC9B,OAAO;wBACL,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;wBAClB,SAAS,EAAE,IAAI;qBAChB,CAAC;gBACJ,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAkB,EAAE;QACnD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;SAC9B,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData } from '../types';\nimport { Node, AddInputLabels } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const add_input_labels: ActionConfig = {\n name: 'Add Input Labels',\n group: ACTION_GROUPS.save,\n render: (_node: Node, action: AddInputLabels) => {\n return html`<div>${renderNamedObjects(action.labels, 'label')}</div>`;\n },\n\n // Form-level transformations\n toFormData: (action: AddInputLabels) => {\n return {\n labels: action.labels || null,\n uuid: action.uuid\n };\n },\n form: {\n labels: {\n type: 'select',\n label: 'Labels',\n helpText:\n 'Select labels to add to the input. Type a new label name to create it.',\n required: true,\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/labels.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for labels or type to create new ones...',\n allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a label with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n }\n },\n fromFormData: (formData: FormData): AddInputLabels => {\n return {\n uuid: formData.uuid,\n type: 'add_input_labels',\n labels: formData.labels || []\n };\n }\n};\n"]}
1
+ {"version":3,"file":"add_input_labels.js","sourceRoot":"","sources":["../../../../src/flow/actions/add_input_labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAsB,EAAE,EAAE;QAC9C,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IAED,6BAA6B;IAC7B,UAAU,EAAE,CAAC,MAAsB,EAAE,EAAE;QACrC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EACN,wEAAwE;YAC1E,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,iDAAiD;YAC9D,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,CAAC,KAAa,EAAE,OAAc,EAAE,EAAE;gBACvD,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC3B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAClE,CAAC;gBACF,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC9B,OAAO;wBACL,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;wBAClB,SAAS,EAAE,IAAI;qBAChB,CAAC;gBACJ,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAkB,EAAE;QACnD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;SAC9B,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, AddInputLabels } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const add_input_labels: ActionConfig = {\n name: 'Add Input Labels',\n group: ACTION_GROUPS.save,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: AddInputLabels) => {\n return html`<div>${renderNamedObjects(action.labels, 'label')}</div>`;\n },\n\n // Form-level transformations\n toFormData: (action: AddInputLabels) => {\n return {\n labels: action.labels || null,\n uuid: action.uuid\n };\n },\n form: {\n labels: {\n type: 'select',\n label: 'Labels',\n helpText:\n 'Select labels to add to the input. Type a new label name to create it.',\n required: true,\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/labels.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for labels or type to create new ones...',\n allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a label with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n }\n },\n fromFormData: (formData: FormData): AddInputLabels => {\n return {\n uuid: formData.uuid,\n type: 'add_input_labels',\n labels: formData.labels || []\n };\n }\n};\n"]}
@@ -1,8 +1,9 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  export const play_audio = {
4
4
  name: 'Play Audio',
5
5
  group: ACTION_GROUPS.send,
6
+ flowTypes: [FlowTypes.VOICE],
6
7
  render: (_node, _action) => {
7
8
  // This will need to be implemented based on the actual render logic
8
9
  return html `<div>Play Audio</div>`;
@@ -1 +1 @@
1
- {"version":3,"file":"play_audio.js","sourceRoot":"","sources":["../../../../src/flow/actions/play_audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,MAAM,EAAE,CAAC,KAAW,EAAE,OAAkB,EAAE,EAAE;QAC1C,oEAAoE;QACpE,OAAO,IAAI,CAAA,uBAAuB,CAAC;IACrC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS } from '../types';\nimport { Node, PlayAudio } from '../../store/flow-definition';\n\nexport const play_audio: ActionConfig = {\n name: 'Play Audio',\n group: ACTION_GROUPS.send,\n render: (_node: Node, _action: PlayAudio) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Play Audio</div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"play_audio.js","sourceRoot":"","sources":["../../../../src/flow/actions/play_audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IAC5B,MAAM,EAAE,CAAC,KAAW,EAAE,OAAkB,EAAE,EAAE;QAC1C,oEAAoE;QACpE,OAAO,IAAI,CAAA,uBAAuB,CAAC;IACrC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';\nimport { Node, PlayAudio } from '../../store/flow-definition';\n\nexport const play_audio: ActionConfig = {\n name: 'Play Audio',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE],\n render: (_node: Node, _action: PlayAudio) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Play Audio</div>`;\n }\n};\n"]}
@@ -1,9 +1,10 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { renderNamedObjects } from '../utils';
4
4
  export const remove_contact_groups = {
5
5
  name: 'Remove from Group',
6
6
  group: ACTION_GROUPS.contacts,
7
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
7
8
  render: (_node, action) => {
8
9
  if (action.all_groups) {
9
10
  return html `<div>Remove from all groups</div>`;
@@ -1 +1 @@
1
- {"version":3,"file":"remove_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/remove_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA,mCAAmC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IACD,UAAU,EAAE,CAAC,MAAuB,EAAE,EAAE;QACtC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;SAC9B,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,8CAA8C;YACxD,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,UAAU,EAAE;gBACV,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;aAC5C;SACF;QACD,UAAU,EAAE;YACV,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,wBAAwB;YAC/B,QAAQ,EACN,2EAA2E;SAC9E;KACF;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IACE,CAAC,QAAQ,CAAC,UAAU;YACpB,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAClD,CAAC;YACD,MAAM,CAAC,MAAM;gBACX,uEAAuE,CAAC;QAC5E,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAmB,EAAE;QACpD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE;YACxD,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;SACzC,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult\n} from '../types';\nimport { Node, RemoveFromGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const remove_contact_groups: ActionConfig = {\n name: 'Remove from Group',\n group: ACTION_GROUPS.contacts,\n render: (_node: Node, action: RemoveFromGroup) => {\n if (action.all_groups) {\n return html`<div>Remove from all groups</div>`;\n }\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n toFormData: (action: RemoveFromGroup) => {\n return {\n uuid: action.uuid,\n all_groups: action.all_groups || false,\n groups: action.groups || null\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to remove the contact from',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n conditions: {\n visible: (formData) => !formData.all_groups\n }\n },\n all_groups: {\n type: 'checkbox',\n label: 'Remove from All Groups',\n helpText:\n 'Check this to remove the contact from all groups instead of specific ones'\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.all_groups &&\n (!formData.groups || formData.groups.length === 0)\n ) {\n errors.groups =\n 'At least one group must be selected or check \"Remove from All Groups\"';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n fromFormData: (formData: FormData): RemoveFromGroup => {\n return {\n uuid: formData.uuid,\n type: 'remove_contact_groups',\n groups: formData.all_groups ? [] : formData.groups || [],\n all_groups: formData.all_groups || false\n };\n }\n};\n"]}
1
+ {"version":3,"file":"remove_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/remove_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA,mCAAmC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IACD,UAAU,EAAE,CAAC,MAAuB,EAAE,EAAE;QACtC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;SAC9B,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,8CAA8C;YACxD,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,UAAU,EAAE;gBACV,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;aAC5C;SACF;QACD,UAAU,EAAE;YACV,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,wBAAwB;YAC/B,QAAQ,EACN,2EAA2E;SAC9E;KACF;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IACE,CAAC,QAAQ,CAAC,UAAU;YACpB,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAClD,CAAC;YACD,MAAM,CAAC,MAAM;gBACX,uEAAuE,CAAC;QAC5E,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAmB,EAAE;QACpD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE;YACxD,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;SACzC,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, RemoveFromGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const remove_contact_groups: ActionConfig = {\n name: 'Remove from Group',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: RemoveFromGroup) => {\n if (action.all_groups) {\n return html`<div>Remove from all groups</div>`;\n }\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n toFormData: (action: RemoveFromGroup) => {\n return {\n uuid: action.uuid,\n all_groups: action.all_groups || false,\n groups: action.groups || null\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to remove the contact from',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n conditions: {\n visible: (formData) => !formData.all_groups\n }\n },\n all_groups: {\n type: 'checkbox',\n label: 'Remove from All Groups',\n helpText:\n 'Check this to remove the contact from all groups instead of specific ones'\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.all_groups &&\n (!formData.groups || formData.groups.length === 0)\n ) {\n errors.groups =\n 'At least one group must be selected or check \"Remove from All Groups\"';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n fromFormData: (formData: FormData): RemoveFromGroup => {\n return {\n uuid: formData.uuid,\n type: 'remove_contact_groups',\n groups: formData.all_groups ? [] : formData.groups || [],\n all_groups: formData.all_groups || false\n };\n }\n};\n"]}
@@ -3,6 +3,7 @@ import { ACTION_GROUPS } from '../types';
3
3
  export const request_optin = {
4
4
  name: 'Request Opt-in',
5
5
  group: ACTION_GROUPS.send,
6
+ flowTypes: [],
6
7
  render: (_node, _action) => {
7
8
  // This will need to be implemented based on the actual render logic
8
9
  return html `<div>Request Opt-in</div>`;
@@ -1 +1 @@
1
- {"version":3,"file":"request_optin.js","sourceRoot":"","sources":["../../../../src/flow/actions/request_optin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,MAAM,EAAE,CAAC,KAAW,EAAE,OAAqB,EAAE,EAAE;QAC7C,oEAAoE;QACpE,OAAO,IAAI,CAAA,2BAA2B,CAAC;IACzC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS } from '../types';\nimport { Node, RequestOptin } from '../../store/flow-definition';\n\nexport const request_optin: ActionConfig = {\n name: 'Request Opt-in',\n group: ACTION_GROUPS.send,\n render: (_node: Node, _action: RequestOptin) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Request Opt-in</div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"request_optin.js","sourceRoot":"","sources":["../../../../src/flow/actions/request_optin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,CAAC,KAAW,EAAE,OAAqB,EAAE,EAAE;QAC7C,oEAAoE;QACpE,OAAO,IAAI,CAAA,2BAA2B,CAAC;IACzC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS } from '../types';\nimport { Node, RequestOptin } from '../../store/flow-definition';\n\nexport const request_optin: ActionConfig = {\n name: 'Request Opt-in',\n group: ACTION_GROUPS.send,\n flowTypes: [],\n render: (_node: Node, _action: RequestOptin) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Request Opt-in</div>`;\n }\n};\n"]}
@@ -1,8 +1,9 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  export const say_msg = {
4
4
  name: 'Say Message',
5
5
  group: ACTION_GROUPS.send,
6
+ flowTypes: [FlowTypes.VOICE],
6
7
  render: (_node, _action) => {
7
8
  // This will need to be implemented based on the actual render logic
8
9
  return html `<div>Say Message</div>`;
@@ -1 +1 @@
1
- {"version":3,"file":"say_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/say_msg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,MAAM,EAAE,CAAC,KAAW,EAAE,OAAe,EAAE,EAAE;QACvC,oEAAoE;QACpE,OAAO,IAAI,CAAA,wBAAwB,CAAC;IACtC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS } from '../types';\nimport { Node, SayMsg } from '../../store/flow-definition';\n\nexport const say_msg: ActionConfig = {\n name: 'Say Message',\n group: ACTION_GROUPS.send,\n render: (_node: Node, _action: SayMsg) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Say Message</div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"say_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/say_msg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,aAAa,CAAC,IAAI;IACzB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IAC5B,MAAM,EAAE,CAAC,KAAW,EAAE,OAAe,EAAE,EAAE;QACvC,oEAAoE;QACpE,OAAO,IAAI,CAAA,wBAAwB,CAAC;IACtC,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';\nimport { Node, SayMsg } from '../../store/flow-definition';\n\nexport const say_msg: ActionConfig = {\n name: 'Say Message',\n group: ACTION_GROUPS.send,\n flowTypes: [FlowTypes.VOICE],\n render: (_node: Node, _action: SayMsg) => {\n // This will need to be implemented based on the actual render logic\n return html`<div>Say Message</div>`;\n }\n};\n"]}
@@ -1,10 +1,11 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { renderStringList } from '../utils';
4
4
  import { Icon } from '../../Icons';
5
5
  export const send_broadcast = {
6
6
  name: 'Send Broadcast',
7
7
  group: ACTION_GROUPS.broadcast,
8
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
8
9
  render: (_node, action) => {
9
10
  const recipients = [
10
11
  ...(action.contacts || []).map((c) => c.name),
@@ -1 +1 @@
1
- {"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData } from '../types';\nimport { Node, SendBroadcast } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_broadcast: ActionConfig = {\n name: 'Send Broadcast',\n group: ACTION_GROUPS.broadcast,\n render: (_node: Node, action: SendBroadcast) => {\n const recipients = [\n ...(action.contacts || []).map((c) => c.name),\n ...(action.groups || []).map((g) => g.name)\n ];\n\n return html`<div>\n <div>${renderStringList(recipients, Icon.contacts)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.text}\n </div>\n </div>\n </div>`;\n },\n\n form: {\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select the contacts or groups to receive the broadcast',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n required: true\n },\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n }\n },\n\n layout: ['recipients', 'text'],\n\n toFormData: (action: SendBroadcast) => {\n return {\n uuid: action.uuid,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n text: action.text || '',\n attachments: action.attachments || []\n };\n },\n\n fromFormData: (formData: FormData): SendBroadcast => {\n const recipients = formData.recipients || [];\n const contacts = recipients.filter((r: any) => !r.group);\n const groups = recipients.filter((r: any) => r.group);\n\n const result: SendBroadcast = {\n uuid: formData.uuid,\n type: 'send_broadcast',\n text: formData.text || '',\n contacts,\n groups,\n attachments: formData.attachments || []\n };\n\n // Remove empty attachments array to match original format\n if (result.attachments.length === 0) {\n delete result.attachments;\n }\n\n return result;\n },\n\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n }\n};\n"]}
1
+ {"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SendBroadcast } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_broadcast: ActionConfig = {\n name: 'Send Broadcast',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendBroadcast) => {\n const recipients = [\n ...(action.contacts || []).map((c) => c.name),\n ...(action.groups || []).map((g) => g.name)\n ];\n\n return html`<div>\n <div>${renderStringList(recipients, Icon.contacts)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.text}\n </div>\n </div>\n </div>`;\n },\n\n form: {\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select the contacts or groups to receive the broadcast',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n required: true\n },\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n }\n },\n\n layout: ['recipients', 'text'],\n\n toFormData: (action: SendBroadcast) => {\n return {\n uuid: action.uuid,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n text: action.text || '',\n attachments: action.attachments || []\n };\n },\n\n fromFormData: (formData: FormData): SendBroadcast => {\n const recipients = formData.recipients || [];\n const contacts = recipients.filter((r: any) => !r.group);\n const groups = recipients.filter((r: any) => r.group);\n\n const result: SendBroadcast = {\n uuid: formData.uuid,\n type: 'send_broadcast',\n text: formData.text || '',\n contacts,\n groups,\n attachments: formData.attachments || []\n };\n\n // Remove empty attachments array to match original format\n if (result.attachments.length === 0) {\n delete result.attachments;\n }\n\n return result;\n },\n\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n }\n};\n"]}
@@ -1,10 +1,11 @@
1
1
  import { html } from 'lit-html';
2
- import { ACTION_GROUPS } from '../types';
2
+ import { ACTION_GROUPS, FlowTypes } from '../types';
3
3
  import { renderStringList } from '../utils';
4
4
  import { Icon } from '../../Icons';
5
5
  export const send_email = {
6
6
  name: 'Send Email',
7
7
  group: ACTION_GROUPS.broadcast,
8
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
8
9
  render: (_node, action) => {
9
10
  return html `<div>
10
11
  <div>${renderStringList(action.addresses, Icon.email)}</div>
@@ -1 +1 @@
1
- {"version":3,"file":"send_email.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa,CAAC,SAAS;IAC9B,MAAM,EAAE,CAAC,KAAW,EAAE,MAAiB,EAAE,EAAE;QACzC,OAAO,IAAI,CAAA;aACF,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;;;;;YAK/C,MAAM,CAAC,OAAO;;;WAGf,CAAC;IACV,CAAC;IACD,IAAI,EAAE;QACJ,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,wBAAwB;YACrC,MAAM,EAAE,IAAI;SACb;QACD,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,qBAAqB;YAClC,SAAS,EAAE,GAAG;SACf;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,GAAG;SACf;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAa,EAAE;QAC9C,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAC/B,CAAC,IAAqC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CACtD;YACD,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,SAAS,GAAG,kDAAkD,CAAC;QACxE,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult\n} from '../types';\nimport { Node, SendEmail } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_email: ActionConfig = {\n name: 'Send Email',\n group: ACTION_GROUPS.broadcast,\n render: (_node: Node, action: SendEmail) => {\n return html`<div>\n <div>${renderStringList(action.addresses, Icon.email)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.subject}\n </div>\n </div>\n </div>`;\n },\n form: {\n addresses: {\n type: 'select',\n label: 'Recipients',\n multi: true,\n searchable: true,\n placeholder: 'Search for contacts...',\n emails: true\n },\n subject: {\n type: 'text',\n label: 'Subject',\n required: true,\n placeholder: 'Enter email subject',\n maxLength: 255\n },\n body: {\n type: 'textarea',\n required: true,\n evaluated: true,\n minHeight: 175\n }\n },\n fromFormData: (formData: FormData): SendEmail => {\n return {\n uuid: formData.uuid,\n type: 'send_email',\n addresses: formData.addresses.map(\n (addr: { name: string; value: string }) => addr.value\n ),\n subject: formData.subject,\n body: formData.body\n };\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.addresses || formData.addresses.length === 0) {\n errors.addresses = 'At least one recipient email address is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
1
+ {"version":3,"file":"send_email.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa,CAAC,SAAS;IAC9B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAiB,EAAE,EAAE;QACzC,OAAO,IAAI,CAAA;aACF,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;;;;;YAK/C,MAAM,CAAC,OAAO;;;WAGf,CAAC;IACV,CAAC;IACD,IAAI,EAAE;QACJ,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,wBAAwB;YACrC,MAAM,EAAE,IAAI;SACb;QACD,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,qBAAqB;YAClC,SAAS,EAAE,GAAG;SACf;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,GAAG;SACf;KACF;IACD,YAAY,EAAE,CAAC,QAAkB,EAAa,EAAE;QAC9C,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAC/B,CAAC,IAAqC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CACtD;YACD,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,SAAS,GAAG,kDAAkD,CAAC;QACxE,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, SendEmail } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_email: ActionConfig = {\n name: 'Send Email',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendEmail) => {\n return html`<div>\n <div>${renderStringList(action.addresses, Icon.email)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.subject}\n </div>\n </div>\n </div>`;\n },\n form: {\n addresses: {\n type: 'select',\n label: 'Recipients',\n multi: true,\n searchable: true,\n placeholder: 'Search for contacts...',\n emails: true\n },\n subject: {\n type: 'text',\n label: 'Subject',\n required: true,\n placeholder: 'Enter email subject',\n maxLength: 255\n },\n body: {\n type: 'textarea',\n required: true,\n evaluated: true,\n minHeight: 175\n }\n },\n fromFormData: (formData: FormData): SendEmail => {\n return {\n uuid: formData.uuid,\n type: 'send_email',\n addresses: formData.addresses.map(\n (addr: { name: string; value: string }) => addr.value\n ),\n subject: formData.subject,\n body: formData.body\n };\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.addresses || formData.addresses.length === 0) {\n errors.addresses = 'At least one recipient email address is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}