@nyaruka/temba-components 0.140.0 → 0.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/.lintstagedrc.js +10 -0
  2. package/CHANGELOG.md +15 -0
  3. package/dist/locales/es.js +5 -5
  4. package/dist/locales/es.js.map +1 -1
  5. package/dist/locales/fr.js +5 -5
  6. package/dist/locales/fr.js.map +1 -1
  7. package/dist/locales/locale-codes.js +11 -2
  8. package/dist/locales/locale-codes.js.map +1 -1
  9. package/dist/locales/pt.js +5 -5
  10. package/dist/locales/pt.js.map +1 -1
  11. package/dist/temba-components.js +189 -91
  12. package/dist/temba-components.js.map +1 -1
  13. package/out-tsc/src/display/FloatingTab.js +1 -1
  14. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  15. package/out-tsc/src/flow/CanvasNode.js +1 -1
  16. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  17. package/out-tsc/src/flow/Editor.js +228 -42
  18. package/out-tsc/src/flow/Editor.js.map +1 -1
  19. package/out-tsc/src/flow/Plumber.js +61 -14
  20. package/out-tsc/src/flow/Plumber.js.map +1 -1
  21. package/out-tsc/src/flow/actions/add_contact_groups.js +4 -1
  22. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  23. package/out-tsc/src/flow/actions/add_input_labels.js +4 -1
  24. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  25. package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -1
  26. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  27. package/out-tsc/src/flow/actions/send_broadcast.js +6 -2
  28. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  29. package/out-tsc/src/flow/actions/set_contact_channel.js +13 -0
  30. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  31. package/out-tsc/src/flow/actions/set_contact_status.js +7 -5
  32. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  33. package/out-tsc/src/flow/actions/start_session.js +10 -3
  34. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  35. package/out-tsc/src/flow/nodes/split_by_contact_field.js +18 -5
  36. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  37. package/out-tsc/src/flow/nodes/split_by_expression.js +1 -1
  38. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  39. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +0 -1
  40. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  41. package/out-tsc/src/flow/nodes/split_by_random.js +0 -1
  42. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  43. package/out-tsc/src/flow/nodes/split_by_run_result.js +10 -4
  44. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  45. package/out-tsc/src/flow/nodes/wait_for_digits.js +1 -1
  46. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  47. package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
  48. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  49. package/out-tsc/src/form/FieldRenderer.js +7 -0
  50. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  51. package/out-tsc/src/layout/Dialog.js +0 -1
  52. package/out-tsc/src/layout/Dialog.js.map +1 -1
  53. package/out-tsc/src/layout/Modax.js +20 -2
  54. package/out-tsc/src/layout/Modax.js.map +1 -1
  55. package/out-tsc/src/list/ContentMenu.js +14 -1
  56. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  57. package/out-tsc/src/live/TembaChart.js.map +1 -1
  58. package/out-tsc/src/locales/es.js +5 -5
  59. package/out-tsc/src/locales/es.js.map +1 -1
  60. package/out-tsc/src/locales/fr.js +5 -5
  61. package/out-tsc/src/locales/fr.js.map +1 -1
  62. package/out-tsc/src/locales/locale-codes.js +11 -2
  63. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  64. package/out-tsc/src/locales/pt.js +5 -5
  65. package/out-tsc/src/locales/pt.js.map +1 -1
  66. package/out-tsc/src/simulator/Simulator.js +11 -0
  67. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  68. package/out-tsc/src/store/AppState.js +13 -0
  69. package/out-tsc/src/store/AppState.js.map +1 -1
  70. package/out-tsc/test/actions/add_contact_groups.test.js +35 -0
  71. package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -1
  72. package/out-tsc/test/actions/add_input_labels.test.js +53 -0
  73. package/out-tsc/test/actions/add_input_labels.test.js.map +1 -0
  74. package/out-tsc/test/actions/enter_flow.test.js +71 -0
  75. package/out-tsc/test/actions/enter_flow.test.js.map +1 -0
  76. package/out-tsc/test/actions/remove_contact_groups.test.js +24 -0
  77. package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -1
  78. package/out-tsc/test/actions/send_broadcast.test.js +41 -0
  79. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  80. package/out-tsc/test/actions/set_contact_channel.test.js +67 -0
  81. package/out-tsc/test/actions/set_contact_channel.test.js.map +1 -0
  82. package/out-tsc/test/actions/set_contact_field.test.js +52 -0
  83. package/out-tsc/test/actions/set_contact_field.test.js.map +1 -0
  84. package/out-tsc/test/actions/set_contact_language.test.js +39 -0
  85. package/out-tsc/test/actions/set_contact_language.test.js.map +1 -0
  86. package/out-tsc/test/actions/set_contact_name.test.js +28 -0
  87. package/out-tsc/test/actions/set_contact_name.test.js.map +1 -0
  88. package/out-tsc/test/actions/set_contact_status.test.js +44 -0
  89. package/out-tsc/test/actions/set_contact_status.test.js.map +1 -0
  90. package/out-tsc/test/actions/set_run_result.test.js +47 -0
  91. package/out-tsc/test/actions/set_run_result.test.js.map +1 -0
  92. package/out-tsc/test/actions/start_session.test.js +76 -0
  93. package/out-tsc/test/actions/start_session.test.js.map +1 -1
  94. package/out-tsc/test/nodes/split_by_contact_field.test.js +50 -0
  95. package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -1
  96. package/out-tsc/test/nodes/split_by_run_result.test.js +82 -0
  97. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
  98. package/out-tsc/test/nodes/split_by_ticket.test.js +139 -0
  99. package/out-tsc/test/nodes/split_by_ticket.test.js.map +1 -0
  100. package/out-tsc/test/nodes/split_by_webhook.test.js +111 -0
  101. package/out-tsc/test/nodes/split_by_webhook.test.js.map +1 -0
  102. package/out-tsc/test/temba-flow-editor.test.js +187 -0
  103. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  104. package/out-tsc/test/temba-flow-plumber.test.js +19 -0
  105. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  106. package/out-tsc/test/temba-select.test.js +4 -1
  107. package/out-tsc/test/temba-select.test.js.map +1 -1
  108. package/out-tsc/test/utils.test.js +4 -2
  109. package/out-tsc/test/utils.test.js.map +1 -1
  110. package/package.json +3 -9
  111. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  112. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  113. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  114. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  115. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  116. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  117. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  118. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  119. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  120. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  121. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  122. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  123. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  124. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  125. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  126. package/screenshots/truth/actions/add_input_labels/editor/multiple-labels.png +0 -0
  127. package/screenshots/truth/actions/add_input_labels/editor/single-label.png +0 -0
  128. package/screenshots/truth/actions/add_input_labels/render/multiple-labels.png +0 -0
  129. package/screenshots/truth/actions/add_input_labels/render/single-label.png +0 -0
  130. package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
  131. package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
  132. package/screenshots/truth/actions/enter_flow/render/basic-flow.png +0 -0
  133. package/screenshots/truth/actions/enter_flow/render/long-flow-name.png +0 -0
  134. package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
  135. package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
  136. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  137. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  138. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  139. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  140. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  141. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  142. package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
  143. package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
  144. package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
  145. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  146. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  147. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  148. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  149. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  150. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  151. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  152. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  153. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  154. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  155. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  156. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  157. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  158. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  159. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  160. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  161. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  162. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  163. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  164. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  165. package/screenshots/truth/actions/set_contact_channel/editor/sms-channel.png +0 -0
  166. package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
  167. package/screenshots/truth/actions/set_contact_channel/render/sms-channel.png +0 -0
  168. package/screenshots/truth/actions/set_contact_channel/render/whatsapp-channel.png +0 -0
  169. package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
  170. package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
  171. package/screenshots/truth/actions/set_contact_field/render/clear-value.png +0 -0
  172. package/screenshots/truth/actions/set_contact_field/render/set-value.png +0 -0
  173. package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
  174. package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
  175. package/screenshots/truth/actions/set_contact_language/render/english.png +0 -0
  176. package/screenshots/truth/actions/set_contact_language/render/french.png +0 -0
  177. package/screenshots/truth/actions/set_contact_name/editor/expression-name.png +0 -0
  178. package/screenshots/truth/actions/set_contact_name/editor/static-name.png +0 -0
  179. package/screenshots/truth/actions/set_contact_name/render/expression-name.png +0 -0
  180. package/screenshots/truth/actions/set_contact_name/render/static-name.png +0 -0
  181. package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
  182. package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
  183. package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
  184. package/screenshots/truth/actions/set_contact_status/render/active.png +0 -0
  185. package/screenshots/truth/actions/set_contact_status/render/archived.png +0 -0
  186. package/screenshots/truth/actions/set_contact_status/render/blocked.png +0 -0
  187. package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
  188. package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
  189. package/screenshots/truth/actions/set_run_result/render/expression-value.png +0 -0
  190. package/screenshots/truth/actions/set_run_result/render/with-category.png +0 -0
  191. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  192. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  193. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  194. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  195. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  196. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  197. package/screenshots/truth/editor/wait.png +0 -0
  198. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  199. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  200. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  201. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  202. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  203. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  204. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  205. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  206. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  207. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  208. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  209. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  210. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  211. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  212. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  213. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  214. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  215. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  216. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  217. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  218. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  219. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  220. package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
  221. package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
  222. package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.png +0 -0
  223. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  224. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  225. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  226. package/screenshots/truth/nodes/wait_for_digits/render/digits-with-rules.png +0 -0
  227. package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
  228. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  229. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  230. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  231. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  232. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  233. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  234. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  235. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  236. package/src/display/FloatingTab.ts +1 -1
  237. package/src/flow/CanvasNode.ts +1 -1
  238. package/src/flow/Editor.ts +285 -87
  239. package/src/flow/Plumber.ts +89 -14
  240. package/src/flow/actions/add_contact_groups.ts +4 -1
  241. package/src/flow/actions/add_input_labels.ts +4 -1
  242. package/src/flow/actions/remove_contact_groups.ts +6 -1
  243. package/src/flow/actions/send_broadcast.ts +6 -2
  244. package/src/flow/actions/set_contact_channel.ts +13 -1
  245. package/src/flow/actions/set_contact_status.ts +7 -5
  246. package/src/flow/actions/start_session.ts +10 -3
  247. package/src/flow/nodes/split_by_contact_field.ts +16 -5
  248. package/src/flow/nodes/split_by_expression.ts +1 -1
  249. package/src/flow/nodes/split_by_llm_categorize.ts +0 -1
  250. package/src/flow/nodes/split_by_random.ts +0 -1
  251. package/src/flow/nodes/split_by_run_result.ts +10 -4
  252. package/src/flow/nodes/wait_for_digits.ts +2 -1
  253. package/src/flow/nodes/wait_for_response.ts +1 -1
  254. package/src/form/FieldRenderer.ts +7 -0
  255. package/src/layout/Dialog.ts +0 -1
  256. package/src/layout/Modax.ts +19 -2
  257. package/src/list/ContentMenu.ts +15 -1
  258. package/src/live/TembaChart.ts +1 -1
  259. package/src/locales/es.ts +18 -13
  260. package/src/locales/fr.ts +18 -13
  261. package/src/locales/locale-codes.ts +11 -2
  262. package/src/locales/pt.ts +18 -13
  263. package/src/simulator/Simulator.ts +12 -0
  264. package/src/store/AppState.ts +15 -0
  265. package/test/actions/add_contact_groups.test.ts +38 -0
  266. package/test/actions/add_input_labels.test.ts +67 -0
  267. package/test/actions/enter_flow.test.ts +88 -0
  268. package/test/actions/remove_contact_groups.test.ts +29 -0
  269. package/test/actions/send_broadcast.test.ts +44 -0
  270. package/test/actions/set_contact_channel.test.ts +88 -0
  271. package/test/actions/set_contact_field.test.ts +68 -0
  272. package/test/actions/set_contact_language.test.ts +55 -0
  273. package/test/actions/set_contact_name.test.ts +39 -0
  274. package/test/actions/set_contact_status.test.ts +64 -0
  275. package/test/actions/set_run_result.test.ts +61 -0
  276. package/test/actions/start_session.test.ts +82 -0
  277. package/test/nodes/split_by_contact_field.test.ts +59 -0
  278. package/test/nodes/split_by_run_result.test.ts +100 -0
  279. package/test/nodes/split_by_ticket.test.ts +157 -0
  280. package/test/nodes/split_by_webhook.test.ts +131 -0
  281. package/test/temba-flow-editor.test.ts +240 -0
  282. package/test/temba-flow-plumber.test.ts +62 -0
  283. package/test/temba-select.test.ts +6 -1
  284. package/test/utils.test.ts +4 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../src/simulator/Simulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { RapidElement } from '../RapidElement';\nimport { FloatingWindow } from '../layout/FloatingWindow';\nimport { css, PropertyValueMap } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { postJSON, fromCookie, generateUUIDv7 } from '../utils';\nimport { getStore } from '../store/Store';\nimport { CustomEventType } from '../interfaces';\nimport { Chat, ContactEvent, MessageType } from '../display/Chat';\nimport { Events, renderEvent } from '../events/eventRenderers';\n\n// test attachment URLs\nconst TEST_IMAGES = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_a.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_b.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_c.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_d.jpg'\n];\n\nconst TEST_VIDEOS = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_video_a.mp4'\n];\n\nconst TEST_AUDIO = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_audio_a.mp3'\n];\n\nconst TEST_LOCATIONS = [\n 'geo:47.6062,-122.3321', // Seattle\n 'geo:-0.1807,-78.4678', // Quito\n 'geo:-2.9001,-79.0059', // Cuenca\n 'geo:-1.9536,30.0606' // Kigali\n];\n\ninterface Contact {\n uuid: string;\n name?: string;\n urns: string[];\n fields?: { [key: string]: any };\n groups?: any[];\n language?: string;\n status?: string;\n created_on?: string;\n}\n\ninterface Session {\n environment: any;\n runs: any[];\n status: string;\n trigger: any;\n wait?: any;\n}\n\ninterface Message {\n uuid: string;\n text?: string;\n urn: string;\n attachments?: string[];\n quick_replies?: any[];\n}\n\ninterface Event {\n type: string;\n created_on: string;\n msg?: Message;\n [key: string]: any;\n}\n\ninterface RunContext {\n session: Session;\n events: Event[];\n context?: any;\n contact?: Contact;\n}\n\ninterface SimulatorSize {\n phoneWidth: number;\n phoneTotalHeight: number;\n phoneScreenHeight: number;\n contextWidth: number;\n contextHeight: number;\n contextOffset: number;\n optionPaneWidth: number;\n optionPaneGap: number;\n windowPadding: number;\n cutoutHeight: number;\n cutoutPadding: number;\n cutoutFontSize: number;\n cutoutIslandWidth: number;\n cutoutIslandHeight: number;\n cutoutIslandTop: number;\n}\n\nconst SIMULATOR_SIZES: Record<string, SimulatorSize> = {\n small: {\n phoneWidth: 270,\n phoneTotalHeight: 530,\n phoneScreenHeight: 376,\n contextWidth: 336,\n contextHeight: 416,\n contextOffset: 48,\n optionPaneWidth: 44,\n optionPaneGap: 10,\n windowPadding: 24,\n cutoutHeight: 32,\n cutoutPadding: 12,\n cutoutFontSize: 10,\n cutoutIslandWidth: 80,\n cutoutIslandHeight: 20,\n cutoutIslandTop: 6\n },\n medium: {\n phoneWidth: 300,\n phoneTotalHeight: 600,\n phoneScreenHeight: 470,\n contextWidth: 420,\n contextHeight: 520,\n contextOffset: 60,\n optionPaneWidth: 44,\n optionPaneGap: 12,\n windowPadding: 30,\n cutoutHeight: 40,\n cutoutPadding: 16,\n cutoutFontSize: 12,\n cutoutIslandWidth: 100,\n cutoutIslandHeight: 24,\n cutoutIslandTop: 8\n },\n large: {\n phoneWidth: 360,\n phoneTotalHeight: 700,\n phoneScreenHeight: 564,\n contextWidth: 504,\n contextHeight: 624,\n contextOffset: 72,\n optionPaneWidth: 44,\n optionPaneGap: 14,\n windowPadding: 36,\n cutoutHeight: 50,\n cutoutPadding: 20,\n cutoutFontSize: 14,\n cutoutIslandWidth: 120,\n cutoutIslandHeight: 30,\n cutoutIslandTop: 10\n }\n};\n\nexport class Simulator extends RapidElement {\n static get styles() {\n return css`\n temba-floating-tab {\n --floating-tab-right: 15px;\n }\n\n :host {\n /* size-specific dimensions are set dynamically via inline styles */\n --phone-width: 300px;\n --phone-total-height: 720px;\n --context-width: 420px;\n --context-offset: 60px;\n --option-pane-width: 44px;\n --option-pane-gap: 12px;\n --window-padding: 30px;\n --phone-screen-height: 470px;\n --context-height: 520px;\n --context-closed-left: 332px;\n --animation-time: 200ms;\n }\n\n .phone-simulator {\n padding-left: calc(var(--context-width) + var(--context-offset));\n padding-top: var(--window-padding);\n padding-bottom: var(--window-padding);\n position: relative;\n display: flex;\n align-items: flex-start;\n }\n\n .option-pane {\n margin-top: var(--window-padding);\n margin-left: var(--option-pane-gap);\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n border-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n }\n .option-btn {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 12px;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all var(--animation-time) ease;\n color: white;\n }\n .option-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n transform: scale(1.05);\n }\n .option-btn:active {\n transform: scale(0.95);\n }\n .option-btn.active {\n background: var(--color-primary-dark);\n color: white;\n }\n .option-btn.active:hover {\n background: var(--color-primary-dark);\n }\n\n .phone-frame {\n width: var(--phone-width);\n height: var(--phone-total-height);\n border-radius: 40px;\n border: 6px solid #1f2937;\n box-shadow: 0 0px 30px rgba(0, 0, 0, 0.4);\n background: #000;\n position: relative;\n overflow: hidden;\n z-index: 2;\n }\n\n .context-explorer {\n width: var(--context-width);\n height: var(--context-height);\n border-top-left-radius: 16px;\n border-bottom-left-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n position: absolute;\n left: var(--context-closed-left);\n top: calc(var(--window-padding) + 40px);\n z-index: 1;\n font-size: 13px;\n color: #374151;\n transition: left calc(var(--animation-time) * 1.5) ease-out,\n opacity calc(var(--animation-time) * 1.5) ease-out;\n opacity: 0;\n pointer-events: none;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n display: flex;\n flex-direction: column;\n padding: 12px;\n }\n\n .context-gutter {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 6px;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 4px;\n margin-right: 32px;\n margin-top: 8px;\n flex-shrink: 0;\n }\n\n .context-gutter-btn {\n width: 14px;\n height: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border-radius: 6px;\n transition: background var(--animation-time) ease;\n color: rgba(255, 255, 255, 0.6);\n padding: 4px;\n }\n\n .context-gutter-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.9);\n }\n\n .context-gutter-btn.active {\n color: #c084fc;\n }\n\n .context-gutter-spacer {\n flex: 1;\n }\n\n .context-explorer-scroll {\n scrollbar-color: rgba(255, 255, 255, 0.3) #4a4a4a;\n scrollbar-width: thin;\n height: 100%;\n overflow-y: scroll;\n padding-right: 10px;\n margin-right: 30px;\n flex-grow: 1;\n }\n\n .context-explorer-bleed {\n height: 100%;\n width: 0px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar {\n width: 18px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n }\n\n /* Custom scrollbar for chat area to allow content to flow behind input */\n .custom-scrollbar-container {\n position: absolute;\n top: 40px;\n bottom: var(--bottom-input-height, 60px);\n right: 4px;\n width: 10px;\n z-index: 20;\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar {\n width: 6px;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.4);\n }\n\n .custom-scrollbar-content {\n width: 100%;\n }\n\n .context-explorer.open {\n left: var(--context-offset);\n opacity: 1;\n pointer-events: auto;\n }\n\n .context-explorer.hidden {\n pointer-events: none !important;\n }\n\n .context-item {\n display: flex;\n align-items: flex-start;\n padding: 2px 4px;\n cursor: pointer;\n user-select: none;\n }\n\n .context-item:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n .context-item-expandable {\n display: flex;\n align-items: center;\n }\n\n .context-expand-icon {\n width: 16px;\n display: inline-block;\n text-align: center;\n flex-shrink: 0;\n transition: transform var(--animation-time) ease;\n color: #ffffff;\n }\n\n .context-expand-icon.expanded {\n transform: rotate(90deg);\n }\n\n .context-key {\n color: #ffffff;\n flex-shrink: 0;\n margin-right: 8px;\n display: flex;\n }\n\n .context-key.has-value {\n color: #e8b5e8;\n }\n\n .context-value {\n color: #aaa;\n flex: 1;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .context-children {\n margin-left: 16px;\n }\n\n .context-copy-icon {\n opacity: 0;\n margin-left: 4px;\n transition: opacity var(--animation-time) ease;\n cursor: pointer;\n color: #ccc;\n }\n\n .context-item:hover .context-copy-icon {\n opacity: 1;\n }\n\n .context-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n background: #666;\n color: white;\n padding: 12px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n font-size: 13px;\n z-index: 10;\n animation: slideInUp var(--animation-time) ease-out;\n }\n\n .context-toast .expression {\n color: #e8b5e8;\n font-weight: 600;\n }\n\n @keyframes slideInUp {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .phone-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 10;\n cursor: grab;\n }\n .phone-notch {\n background: transparent;\n height: var(--cutout-height);\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 var(--cutout-padding);\n }\n .phone-notch::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: linear-gradient(\n to bottom,\n rgba(0, 0, 0, 0.3) 0%,\n rgba(0, 0, 0, 0.2) 50%,\n transparent 100%\n );\n z-index: -1;\n }\n .dynamic-island {\n top: var(--cutout-island-top);\n left: 50%;\n\n width: var(--cutout-island-width);\n height: var(--cutout-island-height);\n background: #000;\n border-radius: calc(var(--cutout-island-height) / 1.5);\n z-index: 1;\n }\n .phone-notch .time {\n color: #000;\n font-size: var(--cutout-font-size);\n font-weight: 600;\n }\n .phone-notch .status-icons {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n .phone-notch .status-icons span {\n color: #000;\n font-size: var(--cutout-font-size);\n }\n .phone-header {\n background: transparent;\n padding: 10px 15px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n cursor: move;\n user-select: none;\n border-bottom: none;\n pointer-events: all;\n }\n\n .phone-screen {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: white;\n display: flex;\n flex-direction: column;\n }\n\n temba-chat {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n --color-chat-in: #e5e5ea;\n --color-chat-out: #007aff;\n --chat-top-padding: calc(var(--cutout-height));\n --chat-bottom-padding: calc(var(--bottom-input-height, 80px) - 10px);\n }\n\n .bottom-input-container {\n position: absolute;\n bottom: 0px;\n left: 0px;\n right: 0px;\n z-index: 10;\n }\n\n .bottom-input-container::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.45);\n backdrop-filter: blur(10px);\n -webkit-mask-image: linear-gradient(to bottom, transparent, black 20px);\n mask-image: linear-gradient(to bottom, transparent, black 20px);\n z-index: -1;\n }\n\n .quick-replies-container {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 6px;\n z-index: 9;\n }\n\n .quick-reply-btn {\n padding: 4px 8px;\n border-radius: 18px;\n border: 1px solid var(--color-primary, #007aff);\n background: white;\n color: var(--color-primary, #007aff);\n font-size: 11px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .quick-reply-btn:hover:not(:disabled) {\n background: var(--color-primary, #007aff);\n color: white;\n }\n\n .quick-reply-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .message-input {\n padding: 8px 12px;\n border-top: none;\n display: flex;\n align-items: center;\n gap: 8px;\n z-index: 10;\n }\n .message-input input {\n flex: 1;\n border: 1px solid #c6c6c857;\n border-radius: 20px;\n padding: 8px 15px;\n font-size: 15px;\n margin-bottom: 5px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n outline: none;\n }\n .message-input input::placeholder {\n color: #8e8e93;\n }\n .attachment-button {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n border: 1px solid #c6c6c857;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n flex-shrink: 0;\n margin-bottom: 5px;\n transition: all var(--animation-time) ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n color: #000;\n }\n .attachment-button:hover {\n background: #f8f8f8ff;\n transform: scale(1.05);\n }\n .attachment-button:active {\n transform: scale(0.95);\n }\n .attachment-menu {\n position: absolute;\n bottom: 55px;\n left: 12px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n opacity: 0;\n pointer-events: none;\n transform: translateY(10px);\n transition: opacity var(--animation-time) ease, transform 0.2s ease;\n z-index: 20;\n }\n .attachment-menu.open {\n opacity: 1;\n pointer-events: all;\n transform: translateY(0);\n }\n .attachment-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background var(--animation-time) ease;\n white-space: nowrap;\n font-size: 14px;\n color: #1f2937;\n }\n .attachment-menu-item:hover {\n background: #f3f4f6;\n }\n .attachment-menu-item temba-icon {\n color: #007aff;\n }\n `;\n }\n\n @property({ type: String })\n flow = '';\n\n @property({ type: String })\n endpoint = '';\n\n @property({ type: Number })\n animationTime = 200;\n\n @fromCookie('simulator-size', 'small')\n size: 'small' | 'medium' | 'large';\n\n @property({ type: Array })\n private events: ContactEvent[] = [];\n\n private previousEventCount = 0;\n private chat: Chat = null;\n\n @property({ type: Object })\n private session: Session | null = null;\n\n @property({ type: Object })\n private context: any = null;\n\n @property({ type: Object })\n private contact: Contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n @property({ type: Boolean })\n private sprinting = false;\n\n @property({ type: String })\n private inputValue = '';\n\n @fromCookie('simulator-follow', true)\n private following: boolean;\n\n @fromCookie('simulator-context-open', false)\n private contextExplorerOpen: boolean;\n\n @property({ type: Object })\n private expandedPaths: Set<string> = new Set();\n\n @property({ type: String })\n private copiedExpression = '';\n\n @property({ type: String })\n private toastMessage = '';\n\n @property({ type: Boolean })\n private showAllKeys = true;\n\n private previousWindowWidth = 0;\n\n @property({ type: Array })\n private currentQuickReplies: any[] = [];\n\n @property({ type: Boolean })\n private isVisible = false;\n\n @property({ type: Boolean })\n private attachmentMenuOpen = false;\n\n private boundClickOutsideHandler: ((event: MouseEvent) => void) | null = null;\n\n // attachment cycling indices - initialized randomly\n private imageIndex = Math.floor(Math.random() * TEST_IMAGES.length);\n private videoIndex = Math.floor(Math.random() * TEST_VIDEOS.length);\n private audioIndex = Math.floor(Math.random() * TEST_AUDIO.length);\n private locationIndex = Math.floor(Math.random() * TEST_LOCATIONS.length);\n\n // method to reset attachment indices for testing\n public resetAttachmentIndices() {\n this.imageIndex = 2;\n this.videoIndex = 0;\n this.audioIndex = 0;\n this.locationIndex = 0;\n }\n\n private get sizeConfig(): SimulatorSize {\n return SIMULATOR_SIZES[this.size] || SIMULATOR_SIZES.medium;\n }\n\n private get windowWidth(): number {\n const config = this.sizeConfig;\n return (\n config.contextWidth +\n config.phoneWidth +\n config.optionPaneWidth +\n config.optionPaneGap +\n config.contextOffset\n );\n }\n\n private get leftBoundaryMargin(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset;\n }\n\n private get contextClosedLeft(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset - config.phoneWidth;\n }\n\n public connectedCallback() {\n super.connectedCallback();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.chat = this.shadowRoot.querySelector('temba-chat');\n\n // if we have events that were collected before chat was ready, add them now\n if (this.chat && this.events.length > 0) {\n this.chat.addMessages(this.events, null, true);\n }\n\n this.setupCustomScrollbar();\n }\n\n private setupCustomScrollbar() {\n const chat = this.shadowRoot?.querySelector('temba-chat') as Chat;\n const scrollContainer = this.shadowRoot?.querySelector(\n '.custom-scrollbar-container'\n ) as HTMLElement;\n const scrollContent = this.shadowRoot?.querySelector(\n '.custom-scrollbar-content'\n ) as HTMLElement;\n\n if (!chat || !scrollContainer || !scrollContent) return;\n\n chat.updateComplete.then(() => {\n const chatScroll = chat.shadowRoot?.querySelector(\n '.scroll'\n ) as HTMLElement;\n if (!chatScroll) return;\n\n let ignoreScroll = false;\n\n // Sync from chat to custom scrollbar\n chatScroll.addEventListener('scroll', () => {\n if (!ignoreScroll) {\n ignoreScroll = true;\n // Chat: 0 (bottom) ... -Max (top) (Negative scrolling)\n // Custom: Max (bottom) ... 0 (top) (Positive scrolling)\n\n const maxScroll =\n scrollContainer.scrollHeight - scrollContainer.clientHeight;\n // Math.abs to handle negative scrollTop\n const distanceFromBottom = Math.abs(chatScroll.scrollTop);\n const newCustomScrollTop = maxScroll - distanceFromBottom;\n\n scrollContainer.scrollTop = newCustomScrollTop;\n\n requestAnimationFrame(() => (ignoreScroll = false));\n }\n });\n\n // Sync from custom scrollbar to chat\n scrollContainer.addEventListener('scroll', () => {\n if (!ignoreScroll) {\n ignoreScroll = true;\n\n const maxScroll =\n scrollContainer.scrollHeight - scrollContainer.clientHeight;\n const distanceFromBottom = maxScroll - scrollContainer.scrollTop;\n\n // chat scrollTop should be -distanceFromBottom\n chatScroll.scrollTop = -distanceFromBottom;\n\n requestAnimationFrame(() => (ignoreScroll = false));\n }\n });\n\n // Sync height\n const syncHeight = () => {\n const chatMaxScroll = chatScroll.scrollHeight - chatScroll.clientHeight;\n const customClientHeight = scrollContainer.clientHeight;\n\n // ensure minimum height\n if (chatMaxScroll <= 0) {\n scrollContent.style.height = '100%';\n return;\n }\n\n const newHeight = chatMaxScroll + customClientHeight;\n scrollContent.style.height = `${newHeight}px`;\n\n // If we were effectively at the bottom, stay at the bottom\n // This is a heuristic, assuming if we're close enough we're \"at bottom\"\n // But the Chat component handles scrollToBottom on new messages, which fires scroll event,\n // which updates us. So we might not need to force it here unless resize happens without message.\n if (Math.abs(chatScroll.scrollTop) < 5) {\n scrollContainer.scrollTop = scrollContainer.scrollHeight;\n }\n };\n\n // Observe changes\n const observer = new MutationObserver(syncHeight);\n observer.observe(chatScroll, {\n childList: true,\n subtree: true,\n attributes: true\n });\n\n const resizeObserver = new ResizeObserver(syncHeight);\n resizeObserver.observe(chatScroll);\n\n // Initial sync\n syncHeight();\n });\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (\n changes.has('currentQuickReplies') ||\n changes.has('keyboardVisible') ||\n changes.has('attachmentMenuOpen')\n ) {\n this.updateBottomInputHeight();\n }\n\n if (changes.has('flow') && this.flow) {\n this.endpoint = `/flow/simulate/${this.flow}/`;\n }\n\n // handle attachment menu click outside listener\n if (changes.has('attachmentMenuOpen')) {\n if (this.attachmentMenuOpen) {\n // create bound handler if it doesn't exist\n if (!this.boundClickOutsideHandler) {\n this.boundClickOutsideHandler =\n this.handleClickOutsideAttachmentMenu.bind(this);\n }\n // add listener when menu opens\n setTimeout(() => {\n document.addEventListener('click', this.boundClickOutsideHandler);\n }, 0);\n } else {\n // remove listener when menu closes\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n }\n\n // update floating window boundaries when size changes\n if (changes.has('size')) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n // use the stored previous width since phoneWindow.width has already been updated\n const oldWidth = this.previousWindowWidth || phoneWindow.width;\n const oldRight = phoneWindow.left + oldWidth;\n\n const config = this.sizeConfig;\n const newWidth = this.windowWidth;\n\n // store current width for next size change\n this.previousWindowWidth = newWidth;\n\n // update dimensions and boundaries\n phoneWindow.width = newWidth;\n phoneWindow.leftBoundaryMargin = this.leftBoundaryMargin;\n phoneWindow.topBoundaryMargin = config.windowPadding;\n phoneWindow.bottomBoundaryMargin = config.windowPadding;\n\n // keep right edge in same position by adjusting left\n let newLeft = oldRight - newWidth;\n\n // apply same boundary logic as FloatingWindow.handleMouseMove\n const padding = 20;\n const minLeft = padding - this.leftBoundaryMargin;\n const maxLeft =\n window.innerWidth -\n newWidth -\n padding +\n phoneWindow.rightBoundaryMargin;\n\n // clamp to boundaries\n newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft));\n\n phoneWindow.left = newLeft;\n\n // adjust vertical position if needed\n const windowElement = phoneWindow.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || config.phoneTotalHeight;\n const maxTop = Math.max(\n padding - config.windowPadding,\n window.innerHeight - currentHeight - padding + config.windowPadding\n );\n\n phoneWindow.top = Math.max(\n padding - config.windowPadding,\n Math.min(phoneWindow.top, maxTop)\n );\n }\n });\n } else {\n // store initial width when first rendered\n if (!this.previousWindowWidth) {\n this.previousWindowWidth = this.windowWidth;\n }\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n // clean up event listener when component is removed\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n\n private handleShow() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n phoneWindow.show();\n this.isVisible = true;\n getStore().getState().setSimulatorActive(true);\n\n // ensure chat component is available\n if (!this.chat) {\n this.chat = this.shadowRoot.querySelector('temba-chat');\n }\n\n // start the simulation if we haven't already\n if (!this.session) {\n this.startFlow();\n }\n }\n\n private async startFlow() {\n const now = new Date().toISOString();\n\n // set created_on to simulation start time\n this.contact = { ...this.contact, created_on: now };\n\n const body = {\n contact: this.contact,\n trigger: {\n type: 'manual',\n triggered_on: now,\n flow: { uuid: this.flow, name: 'New Chat' },\n params: {}\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n this.updateRunContext(response.json as RunContext);\n } catch (error) {\n console.error('Failed to start simulation:', error);\n const errorEvent = {\n uuid: generateUUIDv7(),\n type: 'error',\n created_on: new Date(now),\n _rendered: {\n html: html`<p>Failed to start simulation</p>`,\n type: MessageType.Error\n }\n } as ContactEvent;\n if (this.chat) {\n this.chat.addMessages([errorEvent], null, true);\n } else {\n this.events = [...this.events, errorEvent];\n }\n }\n }\n\n private updateRunContext(runContext: RunContext, msgInEvt?: ContactEvent) {\n const newEvents: ContactEvent[] = [];\n\n // add the user's message if provided\n if (msgInEvt) {\n // ensure it has a UUID\n if (!msgInEvt.uuid) {\n msgInEvt.uuid = generateUUIDv7();\n }\n // ensure created_on is a Date object\n if (typeof msgInEvt.created_on === 'string') {\n msgInEvt.created_on = new Date(msgInEvt.created_on);\n }\n newEvents.push(msgInEvt);\n }\n\n if (runContext.session) {\n this.session = runContext.session;\n\n // update our contact with the latest from the session\n if (runContext.contact) {\n this.contact = runContext.contact;\n }\n }\n\n // store the context from the response\n if (runContext.context) {\n this.context = runContext.context;\n }\n\n // extract quick replies from the most recent sprint\n this.currentQuickReplies = [];\n\n if (runContext.events && runContext.events.length > 0) {\n for (const rawEvent of runContext.events) {\n // skip msg_received events from the server since we already added the user's message\n if (rawEvent.type === 'msg_received') {\n continue;\n }\n\n // skip msg_created/ivr_created events without a proper msg property\n if (\n (rawEvent.type === 'msg_created' ||\n rawEvent.type === 'ivr_created') &&\n !(rawEvent as any).msg\n ) {\n continue;\n }\n\n // convert to ContactEvent\n const event: ContactEvent = {\n ...rawEvent,\n uuid: rawEvent.uuid || generateUUIDv7(),\n created_on:\n typeof rawEvent.created_on === 'string'\n ? new Date(rawEvent.created_on)\n : rawEvent.created_on\n } as ContactEvent;\n\n // pre-render non-message events\n this.prerenderEvent(event);\n\n // extract quick replies from msg_created events\n if (event.type === 'msg_created' && (event as any).msg?.quick_replies) {\n this.currentQuickReplies = (event as any).msg.quick_replies;\n }\n\n const isMessage =\n event.type === 'msg_created' || event.type === 'ivr_created';\n const msg = (event as any).msg;\n\n // Check if the event should be displayed.\n // 1. If it's a message, it must have text or attachments\n if (isMessage) {\n const hasText = msg.text && msg.text.trim().length > 0;\n const hasAttachments = msg.attachments && msg.attachments.length > 0;\n if (!hasText && !hasAttachments) {\n continue;\n }\n }\n // 2. If it's not a message, it must have been rendered by prerenderEvent\n else if (!event._rendered) {\n continue;\n }\n\n newEvents.push(event);\n }\n }\n\n // add all new events to chat component if it exists\n if (this.chat) {\n this.chat.addMessages(newEvents, null, true);\n } else {\n // fallback: store events and add them once chat is ready\n this.events = [...this.events, ...newEvents];\n }\n\n this.sprinting = false;\n this.requestUpdate(); // trigger re-render for quick replies\n this.scrollToBottom();\n this.updateActivity();\n }\n\n private updateActivity() {\n if (!this.session) {\n return;\n }\n\n const pathCounts: { [key: string]: number } = {};\n const nodeCounts: { [nodeUUID: string]: number } = {};\n\n // iterate through all runs to get path segment counts\n for (const run of this.session.runs) {\n if (run.path) {\n for (let i = 0; i < run.path.length - 1; i++) {\n const step = run.path[i];\n const nextStep = run.path[i + 1];\n if (step.exit_uuid && nextStep.node_uuid) {\n const key = step.exit_uuid + ':' + nextStep.node_uuid;\n pathCounts[key] = (pathCounts[key] || 0) + 1;\n }\n }\n }\n\n // set node counts on the last step of any active/waiting runs\n if (run.status === 'active' || run.status === 'waiting') {\n if (run.path && run.path.length > 0) {\n const finalStep = run.path[run.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n nodeCounts[finalStep.node_uuid] =\n (nodeCounts[finalStep.node_uuid] || 0) + 1;\n }\n }\n }\n }\n\n // Update simulator activity in the store\n getStore().getState().updateSimulatorActivity({\n segments: pathCounts,\n nodes: nodeCounts\n });\n\n // Fire follow event if following is enabled\n if (this.following) {\n this.fireFollowEvent();\n }\n }\n\n private fireFollowEvent() {\n if (!this.session || !this.session.runs || this.session.runs.length === 0) {\n return;\n }\n\n // Find the first active or waiting run\n let activeRun = this.session.runs.find(\n (run: any) => run.status === 'active' || run.status === 'waiting'\n );\n\n // If no active/waiting run and simulation has ended, use the first completed run\n if (!activeRun) {\n activeRun = this.session.runs.find(\n (run: any) => run.status === 'completed'\n );\n }\n\n if (activeRun && activeRun.path && activeRun.path.length > 0) {\n const finalStep = activeRun.path[activeRun.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n this.fireCustomEvent(CustomEventType.FollowSimulation, {\n flowUuid: activeRun.flow?.uuid || this.flow,\n nodeUuid: finalStep.node_uuid\n });\n }\n }\n }\n\n private scrollToBottom() {\n if (this.chat) {\n // chat component handles scrolling, but we still need to focus input\n this.chat.scrollToBottom();\n setTimeout(() => {\n const input = this.shadowRoot?.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n if (input) {\n input.focus();\n }\n }, 50);\n return;\n }\n // wait for render, then scroll to bottom\n setTimeout(() => {\n const screen = this.shadowRoot?.querySelector('.phone-screen');\n if (screen) {\n screen.scrollTop = screen.scrollHeight;\n }\n // update previous count after animation completes\n this.previousEventCount = this.events.length;\n\n // return focus to input\n const input = this.shadowRoot?.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n if (input) {\n input.focus();\n }\n }, 50);\n }\n\n private prerenderEvent(event: ContactEvent) {\n // skip if already rendered or is a message event\n if (\n event._rendered ||\n event.type === Events.MSG_CREATED ||\n event.type === Events.MSG_RECEIVED\n ) {\n return;\n }\n\n // handle simulator-specific events (errors, warnings, failures)\n if (event.type === 'error' || event.type === 'failure') {\n event._rendered = {\n html: renderEvent(event, true),\n type: MessageType.Error\n };\n return;\n }\n\n if (event.type === 'warning') {\n event._rendered = {\n html: renderEvent(event, true),\n type: MessageType.Note\n };\n return;\n }\n\n // try to render as a standard event\n const rendered = renderEvent(event, true);\n if (rendered) {\n event._rendered = {\n html: rendered,\n type: MessageType.Inline\n };\n }\n }\n\n private handleClose() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n phoneWindow.handleClose();\n this.isVisible = false;\n getStore().getState().setSimulatorActive(false);\n }\n\n private handleReset() {\n // reset simulation state\n this.events = [];\n this.session = null;\n this.context = null;\n this.inputValue = '';\n this.sprinting = false;\n this.previousEventCount = 0;\n this.currentQuickReplies = [];\n\n // reset chat component\n if (this.chat) {\n this.chat.reset();\n }\n\n // Clear simulator activity data\n getStore().getState().updateSimulatorActivity({\n segments: {},\n nodes: {}\n });\n\n // reset contact to initial state\n this.contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n // restart the flow\n this.startFlow();\n }\n\n private handleToggleFollow() {\n this.following = !this.following;\n }\n\n private handleCycleSize() {\n const sizes: Array<'small' | 'medium' | 'large'> = [\n 'small',\n 'medium',\n 'large'\n ];\n const currentIndex = sizes.indexOf(this.size);\n const nextIndex = (currentIndex + 1) % sizes.length;\n this.size = sizes[nextIndex];\n }\n\n private handleToggleContextExplorer() {\n this.contextExplorerOpen = !this.contextExplorerOpen;\n\n // if opening the context explorer, ensure it's not off-screen\n if (this.contextExplorerOpen) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n const padding = 20;\n const contextExplorerLeft = this.sizeConfig.contextOffset;\n const minWindowLeft = padding - contextExplorerLeft;\n\n if (phoneWindow.left < minWindowLeft) {\n phoneWindow.left = minWindowLeft;\n }\n }\n });\n }\n }\n\n private togglePath(path: string) {\n if (this.expandedPaths.has(path)) {\n this.expandedPaths.delete(path);\n } else {\n this.expandedPaths.add(path);\n }\n this.requestUpdate();\n }\n\n private isExpandable(value: any): boolean {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n\n // check if object has keys other than __default__\n const keys = Object.keys(value).filter((key) => key !== '__default__');\n return keys.length > 0;\n }\n\n private renderContextValue(value: any): TemplateResult | string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'boolean')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'number')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'string')\n return html`<span class=\"context-value\">${value}</span>`;\n if (Array.isArray(value))\n return html`<span class=\"context-value\">[${value.length}]</span>`;\n return '';\n }\n\n private buildExpression(path: string): string {\n return `@${path}`;\n }\n\n private async handleCopyExpression(\n path: string,\n event: Event\n ): Promise<void> {\n event.stopPropagation();\n const expression = this.buildExpression(path);\n try {\n await navigator.clipboard.writeText(expression);\n this.copiedExpression = expression;\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.copiedExpression = '';\n }, 2000);\n } catch (err) {\n console.error('Failed to copy expression:', err);\n }\n }\n\n private handleToggleShowAllKeys() {\n this.showAllKeys = !this.showAllKeys;\n this.toastMessage = this.showAllKeys\n ? 'Showing all keys'\n : 'Filtering out keys without values';\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.toastMessage = '';\n }, 2000);\n }\n\n private renderContextTree(\n obj: any,\n path: string = ''\n ): TemplateResult | TemplateResult[] {\n if (!obj || typeof obj !== 'object') {\n return html``;\n }\n\n let entries = Array.isArray(obj)\n ? obj.map((v, i) => [String(i), v])\n : Object.entries(obj).filter(([key]) => key !== '__default__');\n\n // filter out keys without values if showAllKeys is false\n if (!this.showAllKeys) {\n entries = entries.filter(([, value]) => {\n // keep if expandable (has children)\n if (this.isExpandable(value)) return true;\n // keep if it has a displayable value (not null/undefined)\n if (value === null || value === undefined) return false;\n // keep primitives with values\n return (\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string' ||\n Array.isArray(value)\n );\n });\n }\n\n return html`${entries.map(([key, value]) => {\n const currentPath = path ? `${path}.${key}` : key;\n const isExpanded = this.expandedPaths.has(currentPath);\n const expandable = this.isExpandable(value);\n\n // check if this object has a __default__ value\n let displayValue = value;\n\n if (\n expandable &&\n !Array.isArray(value) &&\n value !== null &&\n typeof value === 'object' &&\n '__default__' in value\n ) {\n displayValue = value.__default__;\n }\n\n return html`\n <div>\n <div\n class=\"context-item ${expandable ? 'context-item-expandable' : ''}\"\n @click=${() => expandable && this.togglePath(currentPath)}\n >\n ${expandable\n ? html`<span\n class=\"context-expand-icon ${isExpanded ? 'expanded' : ''}\"\n >›</span\n >`\n : html`<span class=\"context-expand-icon\"></span>`}\n <span class=\"context-key ${expandable ? 'has-value' : ''}\"\n >${key}\n <temba-icon\n class=\"context-copy-icon\"\n name=\"copy\"\n size=\"0.9\"\n @click=${(e: Event) =>\n this.handleCopyExpression(currentPath, e)}\n ></temba-icon>\n </span>\n ${!isExpanded ? this.renderContextValue(displayValue) : html``}\n </div>\n ${isExpanded\n ? html`<div class=\"context-children\">\n ${this.renderContextTree(value, currentPath)}\n </div>`\n : html``}\n </div>\n `;\n })}`;\n }\n\n private async resume(text: string, attachment?: string) {\n if ((!text && !attachment) || !this.session) {\n return;\n }\n\n this.sprinting = true;\n this.inputValue = '';\n this.currentQuickReplies = [];\n this.attachmentMenuOpen = false;\n\n const now = new Date().toISOString();\n\n // create the event for the API (with ISO string date)\n const msgInEvtForAPI = {\n uuid: generateUUIDv7(),\n type: 'msg_received',\n created_on: now,\n msg: {\n uuid: generateUUIDv7(),\n text: text || '',\n urn: this.contact.urns[0],\n direction: 'in',\n type: 'text',\n attachments: attachment ? [attachment] : [],\n quick_replies: [],\n channel: { uuid: generateUUIDv7(), name: 'Simulator' }\n }\n };\n\n // create the ContactEvent for display (with Date object)\n const msgInEvt = {\n ...msgInEvtForAPI,\n created_on: new Date(now)\n } as ContactEvent;\n\n // show user's message immediately via chat component\n if (this.chat) {\n this.chat.addMessages([msgInEvt], null, true);\n } else {\n this.events = [...this.events, msgInEvt];\n }\n this.requestUpdate();\n this.scrollToBottom();\n\n const body = {\n session: this.session,\n contact: this.contact,\n resume: {\n type: 'msg',\n event: msgInEvtForAPI,\n resumed_on: now\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n\n // add a small delay before showing the reply to simulate typing\n await new Promise((resolve) => setTimeout(resolve, 400));\n\n // pass null for msgInEvt since we already added it\n this.updateRunContext(response.json as RunContext, null);\n } catch (error) {\n console.error('Failed to resume simulation:', error);\n const errorEvent = {\n uuid: generateUUIDv7(),\n type: 'error',\n created_on: new Date(now),\n _rendered: {\n html: html`<p>Failed to send message</p>`,\n type: MessageType.Error\n }\n } as ContactEvent;\n if (this.chat) {\n this.chat.addMessages([errorEvent], null, true);\n } else {\n this.events = [...this.events, errorEvent];\n }\n this.sprinting = false;\n }\n }\n\n private handleKeyUp(evt: KeyboardEvent) {\n if (evt.key === 'Enter') {\n const input = evt.target as HTMLInputElement;\n const text = input.value.trim();\n if (text) {\n this.resume(text);\n }\n }\n }\n\n private handleInput(evt: Event) {\n const input = evt.target as HTMLInputElement;\n this.inputValue = input.value;\n }\n\n private handleQuickReplyClick(text: string) {\n if (!this.sprinting && text) {\n this.resume(text);\n }\n }\n\n private handleToggleAttachmentMenu() {\n this.attachmentMenuOpen = !this.attachmentMenuOpen;\n }\n\n private handleClickOutsideAttachmentMenu(event: MouseEvent) {\n if (!this.attachmentMenuOpen) {\n return;\n }\n\n const menu = this.shadowRoot?.querySelector('.attachment-menu');\n const button = this.shadowRoot?.querySelector('.attachment-button');\n\n if (!menu || !button) {\n return;\n }\n\n // check if click is outside both menu and button\n const clickedInsideMenu = menu.contains(event.target as Node);\n const clickedInsideButton = button.contains(event.target as Node);\n\n if (!clickedInsideMenu && !clickedInsideButton) {\n this.attachmentMenuOpen = false;\n }\n }\n\n private handleSendAttachment(attachmentType: string) {\n let attachment = '';\n switch (attachmentType) {\n case 'image':\n attachment = `image/jpeg:${TEST_IMAGES[this.imageIndex]}`;\n this.imageIndex = (this.imageIndex + 1) % TEST_IMAGES.length;\n break;\n case 'video':\n attachment = `video/mp4:${TEST_VIDEOS[this.videoIndex]}`;\n this.videoIndex = (this.videoIndex + 1) % TEST_VIDEOS.length;\n break;\n case 'audio':\n attachment = `audio/mp3:${TEST_AUDIO[this.audioIndex]}`;\n this.audioIndex = (this.audioIndex + 1) % TEST_AUDIO.length;\n break;\n case 'location':\n attachment = TEST_LOCATIONS[this.locationIndex];\n this.locationIndex = (this.locationIndex + 1) % TEST_LOCATIONS.length;\n break;\n }\n\n if (attachment) {\n this.resume('', attachment);\n }\n }\n\n private updateBottomInputHeight() {\n requestAnimationFrame(() => {\n const bottomContainer = this.shadowRoot?.querySelector(\n '.bottom-input-container'\n ) as HTMLElement;\n if (bottomContainer) {\n const height = bottomContainer.offsetHeight;\n this.style.setProperty('--bottom-input-height', `${height}px`);\n }\n });\n }\n\n protected render(): TemplateResult {\n const config = this.sizeConfig;\n\n // set CSS custom properties dynamically based on size\n const styleVars = `\n --phone-width: ${config.phoneWidth}px;\n --phone-total-height: ${config.phoneTotalHeight}px;\n --context-width: ${config.contextWidth}px;\n --context-offset: ${config.contextOffset}px;\n --option-pane-width: ${config.optionPaneWidth}px;\n --option-pane-gap: ${config.optionPaneGap}px;\n --window-padding: ${config.windowPadding}px;\n --phone-screen-height: ${config.phoneScreenHeight}px;\n --context-height: ${config.contextHeight}px;\n --context-closed-left: ${this.contextClosedLeft}px;\n --cutout-height: ${config.cutoutHeight}px;\n --cutout-padding: ${config.cutoutPadding}px;\n --cutout-font-size: ${config.cutoutFontSize}px;\n --cutout-island-width: ${config.cutoutIslandWidth}px;\n --cutout-island-height: ${config.cutoutIslandHeight}px;\n --cutout-island-top: ${config.cutoutIslandTop}px;\n --animation-time: ${this.animationTime}ms;\n `;\n\n return html`\n <temba-floating-window\n style=\"--transition-duration: ${this.animationTime}ms\"\n id=\"phone-window\"\n width=\"${this.windowWidth}\"\n leftBoundaryMargin=\"${this.leftBoundaryMargin}\"\n bottomBoundaryMargin=\"${config.windowPadding}\"\n topBoundaryMargin=\"${config.windowPadding}\"\n height=\"${config.phoneTotalHeight}\"\n top=\"0\"\n chromeless\n >\n <div class=\"phone-simulator\" style=\"${styleVars}\">\n <div\n class=\"context-explorer ${this.contextExplorerOpen\n ? 'open'\n : ''} ${this.isVisible ? 'visible' : 'hidden'}\"\n >\n <div class=\"context-explorer-scroll\">\n ${this.context\n ? this.renderContextTree(this.context)\n : html`<div\n style=\"color: #9ca3af; padding: 8px; text-align: center;\"\n >\n No context available\n </div>`}\n </div>\n <div class=\"context-gutter\">\n <div\n class=\"context-gutter-btn ${this.showAllKeys ? '' : 'active'}\"\n @click=${this.handleToggleShowAllKeys}\n title=\"${this.showAllKeys\n ? 'Show keys with values only'\n : 'Show all keys'}\"\n >\n <temba-icon\n name=\"${this.showAllKeys ? 'filter' : 'filter'}\"\n size=\"1\"\n ></temba-icon>\n </div>\n <div class=\"context-gutter-spacer\"></div>\n <div\n class=\"context-gutter-btn\"\n @click=${this.handleToggleContextExplorer}\n title=\"Close\"\n >\n <temba-icon name=\"x\" size=\"1\"></temba-icon>\n </div>\n </div>\n ${this.copiedExpression\n ? html`<div class=\"context-toast\">\n Copied\n <span class=\"expression\">${this.copiedExpression}</span>\n to the clipboard\n </div>`\n : this.toastMessage\n ? html`<div class=\"context-toast\">${this.toastMessage}</div>`\n : html``}\n </div>\n\n <div\n class=\"phone-frame\"\n style=\"pointer-events: ${this.isVisible ? 'all' : 'none'}\"\n >\n <div class=\"phone-top drag-handle\">\n <div class=\"phone-notch\">\n <div class=\"dynamic-island\"></div>\n </div>\n </div>\n <temba-chat class=\"phone-screen\" .showTimestamps=${false}>\n </temba-chat>\n <div class=\"custom-scrollbar-container\">\n <div class=\"custom-scrollbar-content\"></div>\n </div>\n\n <div class=\"bottom-input-container\">\n ${this.currentQuickReplies.length > 0\n ? html`<div class=\"quick-replies-container\">\n ${this.currentQuickReplies.map(\n (qr) => html`\n <button\n class=\"quick-reply-btn\"\n @click=${() => this.handleQuickReplyClick(qr.text)}\n ?disabled=${this.sprinting}\n >\n ${qr.text}\n </button>\n `\n )}\n </div>`\n : null}\n <div class=\"message-input\">\n <button\n class=\"attachment-button\"\n @click=${this.handleToggleAttachmentMenu}\n ?disabled=${this.sprinting}\n >\n <temba-icon name=\"plus\" size=\"1.5\"></temba-icon>\n </button>\n <input\n type=\"text\"\n placeholder=\"Enter Message\"\n .value=${this.inputValue}\n @input=${this.handleInput}\n @keyup=${this.handleKeyUp}\n ?disabled=${this.sprinting}\n />\n <div\n class=\"attachment-menu ${this.attachmentMenuOpen\n ? 'open'\n : ''}\"\n >\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('image')}\n >\n <temba-icon name=\"attachment_image\" size=\"1.2\"></temba-icon>\n <span>Image</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('video')}\n >\n <temba-icon name=\"attachment_video\" size=\"1.2\"></temba-icon>\n <span>Video</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('audio')}\n >\n <temba-icon name=\"attachment_audio\" size=\"1.2\"></temba-icon>\n <span>Audio</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('location')}\n >\n <temba-icon\n name=\"attachment_location\"\n size=\"1.2\"\n ></temba-icon>\n <span>Location</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"option-pane\"\n style=\"pointer-events:${this.isVisible ? 'all' : 'none'}\"\n >\n <button class=\"option-btn\" @click=${this.handleClose} title=\"Close\">\n <temba-icon name=\"x\" size=\"1.5\"></temba-icon>\n </button>\n <button\n class=\"option-btn ${this.following ? 'active' : ''}\"\n @click=${this.handleToggleFollow}\n title=\"${this.following ? 'Following' : 'Follow'}\"\n >\n <temba-icon name=\"follow\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn ${this.contextExplorerOpen ? 'active' : ''}\"\n @click=${this.handleToggleContextExplorer}\n title=\"Context Explorer\"\n >\n <temba-icon name=\"expressions\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn\"\n @click=${this.handleCycleSize}\n title=\"Size: ${this.size}\"\n >\n ${this.size === 'small'\n ? 'S'\n : this.size === 'medium'\n ? 'M'\n : 'L'}\n </button>\n\n <button class=\"option-btn\" @click=${this.handleReset} title=\"Reset\">\n <temba-icon name=\"delete\" size=\"1.5\"></temba-icon>\n </button>\n </div>\n </div>\n </temba-floating-window>\n\n <temba-floating-tab\n id=\"phone-tab\"\n icon=\"simulator\"\n label=\"Phone Simulator\"\n color=\"#10b981\"\n order=\"4\"\n .hidden=${this.isVisible}\n @temba-button-clicked=${this.handleShow}\n ></temba-floating-tab>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../src/simulator/Simulator.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,GAAG,EAAoB,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAY,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAsB,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE/D,uBAAuB;AACvB,MAAM,WAAW,GAAG;IAClB,+EAA+E;IAC/E,+EAA+E;IAC/E,+EAA+E;IAC/E,+EAA+E;CAChF,CAAC;AAEF,MAAM,WAAW,GAAG;IAClB,+EAA+E;CAChF,CAAC;AAEF,MAAM,UAAU,GAAG;IACjB,+EAA+E;CAChF,CAAC;AAEF,MAAM,cAAc,GAAG;IACrB,uBAAuB,EAAE,UAAU;IACnC,sBAAsB,EAAE,QAAQ;IAChC,sBAAsB,EAAE,SAAS;IACjC,qBAAqB,CAAC,SAAS;CAChC,CAAC;AA6DF,MAAM,eAAe,GAAkC;IACrD,KAAK,EAAE;QACL,UAAU,EAAE,GAAG;QACf,gBAAgB,EAAE,GAAG;QACrB,iBAAiB,EAAE,GAAG;QACtB,YAAY,EAAE,GAAG;QACjB,aAAa,EAAE,GAAG;QAClB,aAAa,EAAE,EAAE;QACjB,eAAe,EAAE,EAAE;QACnB,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,EAAE;QACrB,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,CAAC;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,GAAG;QACf,gBAAgB,EAAE,GAAG;QACrB,iBAAiB,EAAE,GAAG;QACtB,YAAY,EAAE,GAAG;QACjB,aAAa,EAAE,GAAG;QAClB,aAAa,EAAE,EAAE;QACjB,eAAe,EAAE,EAAE;QACnB,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,GAAG;QACtB,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,CAAC;KACnB;IACD,KAAK,EAAE;QACL,UAAU,EAAE,GAAG;QACf,gBAAgB,EAAE,GAAG;QACrB,iBAAiB,EAAE,GAAG;QACtB,YAAY,EAAE,GAAG;QACjB,aAAa,EAAE,GAAG;QAClB,aAAa,EAAE,EAAE;QACjB,eAAe,EAAE,EAAE;QACnB,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,GAAG;QACtB,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,EAAE;KACpB;CACF,CAAC;AAEF,MAAM,OAAO,SAAU,SAAQ,YAAY;IAA3C;;QA0iBE,SAAI,GAAG,EAAE,CAAC;QAGV,aAAQ,GAAG,EAAE,CAAC;QAGd,kBAAa,GAAG,GAAG,CAAC;QAMZ,WAAM,GAAmB,EAAE,CAAC;QAE5B,uBAAkB,GAAG,CAAC,CAAC;QACvB,SAAI,GAAS,IAAI,CAAC;QAGlB,YAAO,GAAmB,IAAI,CAAC;QAG/B,YAAO,GAAQ,IAAI,CAAC;QAGpB,YAAO,GAAY;YACzB,IAAI,EAAE,sCAAsC;YAC5C,IAAI,EAAE,CAAC,kBAAkB,CAAC;YAC1B,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;QAGM,cAAS,GAAG,KAAK,CAAC;QAGlB,eAAU,GAAG,EAAE,CAAC;QAShB,kBAAa,GAAgB,IAAI,GAAG,EAAE,CAAC;QAGvC,qBAAgB,GAAG,EAAE,CAAC;QAGtB,iBAAY,GAAG,EAAE,CAAC;QAGlB,gBAAW,GAAG,IAAI,CAAC;QAEnB,wBAAmB,GAAG,CAAC,CAAC;QAGxB,wBAAmB,GAAU,EAAE,CAAC;QAGhC,cAAS,GAAG,KAAK,CAAC;QAGlB,uBAAkB,GAAG,KAAK,CAAC;QAE3B,6BAAwB,GAAyC,IAAI,CAAC;QAE9E,oDAAoD;QAC5C,eAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5D,eAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5D,eAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC3D,kBAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAiqC5E,CAAC;IArxDC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8hBT,CAAC;IACJ,CAAC;IAsFD,iDAAiD;IAC1C,sBAAsB;QAC3B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC;IAC9D,CAAC;IAED,IAAY,WAAW;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/B,OAAO,CACL,MAAM,CAAC,YAAY;YACnB,MAAM,CAAC,UAAU;YACjB,MAAM,CAAC,eAAe;YACtB,MAAM,CAAC,aAAa;YACpB,MAAM,CAAC,aAAa,CACrB,CAAC;IACJ,CAAC;IAED,IAAY,kBAAkB;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/B,OAAO,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC;IACpD,CAAC;IAED,IAAY,iBAAiB;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/B,OAAO,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC;IACxE,CAAC;IAEM,iBAAiB;QACtB,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAC5B,CAAC;IAES,YAAY,CACpB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAExD,4EAA4E;QAC5E,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAEO,oBAAoB;;QAC1B,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,YAAY,CAAS,CAAC;QAClE,MAAM,eAAe,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CACpD,6BAA6B,CACf,CAAC;QACjB,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAClD,2BAA2B,CACb,CAAC;QAEjB,IAAI,CAAC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,aAAa;YAAE,OAAO;QAExD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE;;YAC5B,MAAM,UAAU,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAC/C,SAAS,CACK,CAAC;YACjB,IAAI,CAAC,UAAU;gBAAE,OAAO;YAExB,IAAI,YAAY,GAAG,KAAK,CAAC;YAEzB,qCAAqC;YACrC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACzC,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,YAAY,GAAG,IAAI,CAAC;oBACpB,uDAAuD;oBACvD,wDAAwD;oBAExD,MAAM,SAAS,GACb,eAAe,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC;oBAC9D,wCAAwC;oBACxC,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;oBAC1D,MAAM,kBAAkB,GAAG,SAAS,GAAG,kBAAkB,CAAC;oBAE1D,eAAe,CAAC,SAAS,GAAG,kBAAkB,CAAC;oBAE/C,qBAAqB,CAAC,GAAG,EAAE,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,qCAAqC;YACrC,eAAe,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;gBAC9C,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,YAAY,GAAG,IAAI,CAAC;oBAEpB,MAAM,SAAS,GACb,eAAe,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC;oBAC9D,MAAM,kBAAkB,GAAG,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC;oBAEjE,+CAA+C;oBAC/C,UAAU,CAAC,SAAS,GAAG,CAAC,kBAAkB,CAAC;oBAE3C,qBAAqB,CAAC,GAAG,EAAE,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,cAAc;YACd,MAAM,UAAU,GAAG,GAAG,EAAE;gBACtB,MAAM,aAAa,GAAG,UAAU,CAAC,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC;gBACxE,MAAM,kBAAkB,GAAG,eAAe,CAAC,YAAY,CAAC;gBAExD,wBAAwB;gBACxB,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;oBACvB,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;oBACpC,OAAO;gBACT,CAAC;gBAED,MAAM,SAAS,GAAG,aAAa,GAAG,kBAAkB,CAAC;gBACrD,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC;gBAE9C,2DAA2D;gBAC3D,wEAAwE;gBACxE,2FAA2F;gBAC3F,iGAAiG;gBACjG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvC,eAAe,CAAC,SAAS,GAAG,eAAe,CAAC,YAAY,CAAC;gBAC3D,CAAC;YACH,CAAC,CAAC;YAEF,kBAAkB;YAClB,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAClD,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE;gBAC3B,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;YAEH,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;YACtD,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAEnC,eAAe;YACf,UAAU,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAES,OAAO,CACf,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEvB,IACE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EACjC,CAAC;YACD,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,QAAQ,GAAG,kBAAkB,IAAI,CAAC,IAAI,GAAG,CAAC;QACjD,CAAC;QAED,gDAAgD;QAChD,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC5B,2CAA2C;gBAC3C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC;oBACnC,IAAI,CAAC,wBAAwB;wBAC3B,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrD,CAAC;gBACD,+BAA+B;gBAC/B,UAAU,CAAC,GAAG,EAAE;oBACd,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;gBACpE,CAAC,EAAE,CAAC,CAAC,CAAC;YACR,CAAC;iBAAM,CAAC;gBACN,mCAAmC;gBACnC,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;oBAClC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,qBAAqB,CAAC,GAAG,EAAE;;gBACzB,MAAM,WAAW,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,cAAc,CACjD,cAAc,CACG,CAAC;gBACpB,IAAI,WAAW,EAAE,CAAC;oBAChB,iFAAiF;oBACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,IAAI,WAAW,CAAC,KAAK,CAAC;oBAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,GAAG,QAAQ,CAAC;oBAE7C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;oBAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC;oBAElC,2CAA2C;oBAC3C,IAAI,CAAC,mBAAmB,GAAG,QAAQ,CAAC;oBAEpC,mCAAmC;oBACnC,WAAW,CAAC,KAAK,GAAG,QAAQ,CAAC;oBAC7B,WAAW,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC;oBACzD,WAAW,CAAC,iBAAiB,GAAG,MAAM,CAAC,aAAa,CAAC;oBACrD,WAAW,CAAC,oBAAoB,GAAG,MAAM,CAAC,aAAa,CAAC;oBAExD,qDAAqD;oBACrD,IAAI,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;oBAElC,8DAA8D;oBAC9D,MAAM,OAAO,GAAG,EAAE,CAAC;oBACnB,MAAM,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;oBAClD,MAAM,OAAO,GACX,MAAM,CAAC,UAAU;wBACjB,QAAQ;wBACR,OAAO;wBACP,WAAW,CAAC,mBAAmB,CAAC;oBAElC,sBAAsB;oBACtB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;oBAExD,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC;oBAE3B,qCAAqC;oBACrC,MAAM,aAAa,GAAG,MAAA,WAAW,CAAC,UAAU,0CAAE,aAAa,CACzD,SAAS,CACK,CAAC;oBACjB,MAAM,aAAa,GACjB,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,YAAY,KAAI,MAAM,CAAC,gBAAgB,CAAC;oBACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,OAAO,GAAG,MAAM,CAAC,aAAa,EAC9B,MAAM,CAAC,WAAW,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC,aAAa,CACpE,CAAC;oBAEF,WAAW,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CACxB,OAAO,GAAG,MAAM,CAAC,aAAa,EAC9B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAClC,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC9B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,WAAW,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC7B,oDAAoD;QACpD,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAClC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAEO,UAAU;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAChD,cAAc,CACG,CAAC;QACpB,WAAW,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAE/C,qCAAqC;QACrC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC1D,CAAC;QAED,6CAA6C;QAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,0CAA0C;QAC1C,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;QAEpD,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,YAAY,EAAE,GAAG;gBACjB,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC3C,MAAM,EAAE,EAAE;aACX;SACF,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAkB,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACpD,MAAM,UAAU,GAAG;gBACjB,IAAI,EAAE,cAAc,EAAE;gBACtB,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC;gBACzB,SAAS,EAAE;oBACT,IAAI,EAAE,IAAI,CAAA,mCAAmC;oBAC7C,IAAI,EAAE,WAAW,CAAC,KAAK;iBACxB;aACc,CAAC;YAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,UAAsB,EAAE,QAAuB;;QACtE,MAAM,SAAS,GAAmB,EAAE,CAAC;QAErC,qCAAqC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,uBAAuB;YACvB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;YACnC,CAAC;YACD,qCAAqC;YACrC,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC5C,QAAQ,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YACtD,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;YAElC,sDAAsD;YACtD,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;YACpC,CAAC;QACH,CAAC;QAED,sCAAsC;QACtC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QACpC,CAAC;QAED,oDAAoD;QACpD,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;QAE9B,IAAI,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtD,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;gBACzC,qFAAqF;gBACrF,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACrC,SAAS;gBACX,CAAC;gBAED,oEAAoE;gBACpE,IACE,CAAC,QAAQ,CAAC,IAAI,KAAK,aAAa;oBAC9B,QAAQ,CAAC,IAAI,KAAK,aAAa,CAAC;oBAClC,CAAE,QAAgB,CAAC,GAAG,EACtB,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,0BAA0B;gBAC1B,MAAM,KAAK,GAAiB;oBAC1B,GAAG,QAAQ;oBACX,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,cAAc,EAAE;oBACvC,UAAU,EACR,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ;wBACrC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;wBAC/B,CAAC,CAAC,QAAQ,CAAC,UAAU;iBACV,CAAC;gBAElB,gCAAgC;gBAChC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBAE3B,gDAAgD;gBAChD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,KAAI,MAAC,KAAa,CAAC,GAAG,0CAAE,aAAa,CAAA,EAAE,CAAC;oBACtE,IAAI,CAAC,mBAAmB,GAAI,KAAa,CAAC,GAAG,CAAC,aAAa,CAAC;gBAC9D,CAAC;gBAED,MAAM,SAAS,GACb,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;gBAC/D,MAAM,GAAG,GAAI,KAAa,CAAC,GAAG,CAAC;gBAE/B,0CAA0C;gBAC1C,yDAAyD;gBACzD,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;oBACvD,MAAM,cAAc,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;oBACrE,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;wBAChC,SAAS;oBACX,CAAC;gBACH,CAAC;gBACD,yEAAyE;qBACpE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;oBAC1B,SAAS;gBACX,CAAC;gBAED,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,yDAAyD;YACzD,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,sCAAsC;QAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAA8B,EAAE,CAAC;QACjD,MAAM,UAAU,GAAmC,EAAE,CAAC;QAEtD,sDAAsD;QACtD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACzB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBACjC,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;wBACzC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC;wBACtD,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;YACH,CAAC;YAED,8DAA8D;YAC9D,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACxD,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpC,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBAChD,IAAI,SAAS,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;wBACrC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC;4BAC7B,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,yCAAyC;QACzC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,uBAAuB,CAAC;YAC5C,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,UAAU;SAClB,CAAC,CAAC;QAEH,4CAA4C;QAC5C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,eAAe;;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1E,OAAO;QACT,CAAC;QAED,uCAAuC;QACvC,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CACpC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAClE,CAAC;QAEF,iFAAiF;QACjF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAChC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,WAAW,CACzC,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7D,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC5D,IAAI,SAAS,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACrC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,gBAAgB,EAAE;oBACrD,QAAQ,EAAE,CAAA,MAAA,SAAS,CAAC,IAAI,0CAAE,IAAI,KAAI,IAAI,CAAC,IAAI;oBAC3C,QAAQ,EAAE,SAAS,CAAC,SAAS;iBAC9B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,qEAAqE;YACrE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3B,UAAU,CAAC,GAAG,EAAE;;gBACd,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAC1C,sBAAsB,CACH,CAAC;gBACtB,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,CAAC;YACH,CAAC,EAAE,EAAE,CAAC,CAAC;YACP,OAAO;QACT,CAAC;QACD,yCAAyC;QACzC,UAAU,CAAC,GAAG,EAAE;;YACd,MAAM,MAAM,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAC;YAC/D,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC;YACzC,CAAC;YACD,kDAAkD;YAClD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAE7C,wBAAwB;YACxB,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAC1C,sBAAsB,CACH,CAAC;YACtB,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC;QACH,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAEO,cAAc,CAAC,KAAmB;QACxC,iDAAiD;QACjD,IACE,KAAK,CAAC,SAAS;YACf,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,WAAW;YACjC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,YAAY,EAClC,CAAC;YACD,OAAO;QACT,CAAC;QAED,gEAAgE;QAChE,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACvD,KAAK,CAAC,SAAS,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;gBAC9B,IAAI,EAAE,WAAW,CAAC,KAAK;aACxB,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,CAAC,SAAS,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;gBAC9B,IAAI,EAAE,WAAW,CAAC,IAAI;aACvB,CAAC;YACF,OAAO;QACT,CAAC;QAED,oCAAoC;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,SAAS,GAAG;gBAChB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,WAAW,CAAC,MAAM;aACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAChD,cAAc,CACG,CAAC;QACpB,WAAW,CAAC,WAAW,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAEO,WAAW;QACjB,yBAAyB;QACzB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;QAE9B,uBAAuB;QACvB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAED,gCAAgC;QAChC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,uBAAuB,CAAC;YAC5C,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;QAEH,iCAAiC;QACjC,IAAI,CAAC,OAAO,GAAG;YACb,IAAI,EAAE,sCAAsC;YAC5C,IAAI,EAAE,CAAC,kBAAkB,CAAC;YAC1B,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;QAEF,mBAAmB;QACnB,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;IACnC,CAAC;IAEO,eAAe;QACrB,MAAM,KAAK,GAAwC;YACjD,OAAO;YACP,QAAQ;YACR,OAAO;SACR,CAAC;QACF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAEO,2BAA2B;QACjC,IAAI,CAAC,mBAAmB,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC;QAErD,8DAA8D;QAC9D,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,qBAAqB,CAAC,GAAG,EAAE;;gBACzB,MAAM,WAAW,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,cAAc,CACjD,cAAc,CACG,CAAC;gBACpB,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,OAAO,GAAG,EAAE,CAAC;oBACnB,MAAM,mBAAmB,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;oBAC1D,MAAM,aAAa,GAAG,OAAO,GAAG,mBAAmB,CAAC;oBAEpD,IAAI,WAAW,CAAC,IAAI,GAAG,aAAa,EAAE,CAAC;wBACrC,WAAW,CAAC,IAAI,GAAG,aAAa,CAAC;oBACnC,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,IAAY;QAC7B,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEO,YAAY,CAAC,KAAU;QAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,kDAAkD;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAEO,kBAAkB,CAAC,KAAU;QACnC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QACrD,IAAI,OAAO,KAAK,KAAK,SAAS;YAC5B,OAAO,IAAI,CAAA,+BAA+B,KAAK,SAAS,CAAC;QAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,OAAO,IAAI,CAAA,+BAA+B,KAAK,SAAS,CAAC;QAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,OAAO,IAAI,CAAA,+BAA+B,KAAK,SAAS,CAAC;QAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACtB,OAAO,IAAI,CAAA,gCAAgC,KAAK,CAAC,MAAM,UAAU,CAAC;QACpE,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,eAAe,CAAC,IAAY;QAClC,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,IAAY,EACZ,KAAY;QAEZ,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC;YACnC,kCAAkC;YAClC,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;YAC7B,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,uBAAuB;QAC7B,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW;YAClC,CAAC,CAAC,kBAAkB;YACpB,CAAC,CAAC,mCAAmC,CAAC;QACxC,kCAAkC;QAClC,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACzB,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAEO,iBAAiB,CACvB,GAAQ,EACR,OAAe,EAAE;QAEjB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,IAAI,CAAA,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAC9B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC;QAEjE,yDAAyD;QACzD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE;gBACrC,oCAAoC;gBACpC,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC1C,0DAA0D;gBAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO,KAAK,CAAC;gBACxD,8BAA8B;gBAC9B,OAAO,CACL,OAAO,KAAK,KAAK,SAAS;oBAC1B,OAAO,KAAK,KAAK,QAAQ;oBACzB,OAAO,KAAK,KAAK,QAAQ;oBACzB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CACrB,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAA,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACzC,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YAClD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACvD,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAE5C,+CAA+C;YAC/C,IAAI,YAAY,GAAG,KAAK,CAAC;YAEzB,IACE,UAAU;gBACV,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACrB,KAAK,KAAK,IAAI;gBACd,OAAO,KAAK,KAAK,QAAQ;gBACzB,aAAa,IAAI,KAAK,EACtB,CAAC;gBACD,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;YACnC,CAAC;YAED,OAAO,IAAI,CAAA;;;kCAGiB,UAAU,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE;qBACxD,GAAG,EAAE,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;;cAEvD,UAAU;gBACV,CAAC,CAAC,IAAI,CAAA;+CAC2B,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;;kBAEzD;gBACJ,CAAC,CAAC,IAAI,CAAA,2CAA2C;uCACxB,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;iBACnD,GAAG;;;;;yBAKK,CAAC,CAAQ,EAAE,EAAE,CACpB,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,CAAC,CAAC;;;cAG7C,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;;YAE9D,UAAU;gBACV,CAAC,CAAC,IAAI,CAAA;kBACA,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC;qBACvC;gBACT,CAAC,CAAC,IAAI,CAAA,EAAE;;OAEb,CAAC;QACJ,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,UAAmB;QACpD,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;QAC9B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAEhC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,sDAAsD;QACtD,MAAM,cAAc,GAAG;YACrB,IAAI,EAAE,cAAc,EAAE;YACtB,IAAI,EAAE,cAAc;YACpB,UAAU,EAAE,GAAG;YACf,GAAG,EAAE;gBACH,IAAI,EAAE,cAAc,EAAE;gBACtB,IAAI,EAAE,IAAI,IAAI,EAAE;gBAChB,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzB,SAAS,EAAE,IAAI;gBACf,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC3C,aAAa,EAAE,EAAE;gBACjB,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;aACvD;SACF,CAAC;QAEF,yDAAyD;QACzD,MAAM,QAAQ,GAAG;YACf,GAAG,cAAc;YACjB,UAAU,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC;SACV,CAAC;QAElB,qDAAqD;QACrD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE;gBACN,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,cAAc;gBACrB,UAAU,EAAE,GAAG;aAChB;SACF,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAErD,gEAAgE;YAChE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAEzD,mDAAmD;YACnD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAkB,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,MAAM,UAAU,GAAG;gBACjB,IAAI,EAAE,cAAc,EAAE;gBACtB,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC;gBACzB,SAAS,EAAE;oBACT,IAAI,EAAE,IAAI,CAAA,+BAA+B;oBACzC,IAAI,EAAE,WAAW,CAAC,KAAK;iBACxB;aACc,CAAC;YAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAAkB;QACpC,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,GAAG,CAAC,MAA0B,CAAC;YAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChC,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAAU;QAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,MAA0B,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;IAChC,CAAC;IAEO,qBAAqB,CAAC,IAAY;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,0BAA0B;QAChC,IAAI,CAAC,kBAAkB,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC;IACrD,CAAC;IAEO,gCAAgC,CAAC,KAAiB;;QACxD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;QAEpE,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,iDAAiD;QACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAc,CAAC,CAAC;QAC9D,MAAM,mBAAmB,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAc,CAAC,CAAC;QAElE,IAAI,CAAC,iBAAiB,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC/C,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAClC,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,cAAsB;QACjD,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,QAAQ,cAAc,EAAE,CAAC;YACvB,KAAK,OAAO;gBACV,UAAU,GAAG,cAAc,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC1D,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;gBAC7D,MAAM;YACR,KAAK,OAAO;gBACV,UAAU,GAAG,aAAa,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACzD,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;gBAC7D,MAAM;YACR,KAAK,OAAO;gBACV,UAAU,GAAG,aAAa,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxD,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC;gBAC5D,MAAM;YACR,KAAK,UAAU;gBACb,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAChD,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;gBACtE,MAAM;QACV,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAEO,uBAAuB;QAC7B,qBAAqB,CAAC,GAAG,EAAE;;YACzB,MAAM,eAAe,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CACpD,yBAAyB,CACX,CAAC;YACjB,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,MAAM,GAAG,eAAe,CAAC,YAAY,CAAC;gBAC5C,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAES,MAAM;;QACd,IAAI,IAAI,CAAC,eAAe,IAAI,CAAA,MAAA,IAAI,CAAC,UAAU,0CAAE,KAAK,CAAC,MAAM,MAAK,CAAC,EAAE,CAAC;YAChE,OAAO,IAAI,CAAA,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAE/B,sDAAsD;QACtD,MAAM,SAAS,GAAG;uBACC,MAAM,CAAC,UAAU;8BACV,MAAM,CAAC,gBAAgB;yBAC5B,MAAM,CAAC,YAAY;0BAClB,MAAM,CAAC,aAAa;6BACjB,MAAM,CAAC,eAAe;2BACxB,MAAM,CAAC,aAAa;0BACrB,MAAM,CAAC,aAAa;+BACf,MAAM,CAAC,iBAAiB;0BAC7B,MAAM,CAAC,aAAa;+BACf,IAAI,CAAC,iBAAiB;yBAC5B,MAAM,CAAC,YAAY;0BAClB,MAAM,CAAC,aAAa;4BAClB,MAAM,CAAC,cAAc;+BAClB,MAAM,CAAC,iBAAiB;gCACvB,MAAM,CAAC,kBAAkB;6BAC5B,MAAM,CAAC,eAAe;0BACzB,IAAI,CAAC,aAAa;KACvC,CAAC;QAEF,OAAO,IAAI,CAAA;;wCAEyB,IAAI,CAAC,aAAa;;iBAEzC,IAAI,CAAC,WAAW;8BACH,IAAI,CAAC,kBAAkB;gCACrB,MAAM,CAAC,aAAa;6BACvB,MAAM,CAAC,aAAa;kBAC/B,MAAM,CAAC,gBAAgB;;;;8CAIK,SAAS;;sCAEjB,IAAI,CAAC,mBAAmB;YAChD,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;;;gBAG3C,IAAI,CAAC,OAAO;YACZ,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;YACtC,CAAC,CAAC,IAAI,CAAA;;;;yBAIG;;;;4CAImB,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ;yBACnD,IAAI,CAAC,uBAAuB;yBAC5B,IAAI,CAAC,WAAW;YACvB,CAAC,CAAC,4BAA4B;YAC9B,CAAC,CAAC,eAAe;;;0BAGT,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;;;;;;;yBAOvC,IAAI,CAAC,2BAA2B;;;;;;cAM3C,IAAI,CAAC,gBAAgB;YACrB,CAAC,CAAC,IAAI,CAAA;;6CAEyB,IAAI,CAAC,gBAAgB;;uBAE3C;YACT,CAAC,CAAC,IAAI,CAAC,YAAY;gBACnB,CAAC,CAAC,IAAI,CAAA,8BAA8B,IAAI,CAAC,YAAY,QAAQ;gBAC7D,CAAC,CAAC,IAAI,CAAA,EAAE;;;;;qCAKe,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;;;;;;;+DAOL,KAAK;;;;;;;gBAOpD,IAAI,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;YACnC,CAAC,CAAC,IAAI,CAAA;sBACA,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAC5B,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAA;;;mCAGC,GAAG,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,IAAI,CAAC;sCACtC,IAAI,CAAC,SAAS;;4BAExB,EAAE,CAAC,IAAI;;uBAEZ,CACF;yBACI;YACT,CAAC,CAAC,IAAI;;;;2BAIK,IAAI,CAAC,0BAA0B;8BAC5B,IAAI,CAAC,SAAS;;;;;;;2BAOjB,IAAI,CAAC,UAAU;2BACf,IAAI,CAAC,WAAW;2BAChB,IAAI,CAAC,WAAW;8BACb,IAAI,CAAC,SAAS;;;2CAGD,IAAI,CAAC,kBAAkB;YAC9C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,EAAE;;;;6BAIK,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;;;;;;;6BAOxC,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;;;;;;;6BAOxC,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;;;;;;;6BAOxC,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC;;;;;;;;;;;;;;oCAcpC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;;gDAEnB,IAAI,CAAC,WAAW;;;;kCAI9B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;uBACzC,IAAI,CAAC,kBAAkB;uBACvB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;;;;;;kCAM5B,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;uBACnD,IAAI,CAAC,2BAA2B;;;;;;;;uBAQhC,IAAI,CAAC,eAAe;6BACd,IAAI,CAAC,IAAI;;gBAEtB,IAAI,CAAC,IAAI,KAAK,OAAO;YACrB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACxB,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,GAAG;;;gDAG2B,IAAI,CAAC,WAAW;;;;;;;;;;;;;kBAa9C,IAAI,CAAC,SAAS;gCACA,IAAI,CAAC,UAAU;;KAE1C,CAAC;IACJ,CAAC;CACF;AAlvCS;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;6CAC1B;AAG5B;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC;kDAC7B;AAGlC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCACjB;AAGV;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;2CACb;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDACP;AAGpB;IADC,UAAU,CAAC,gBAAgB,EAAE,OAAO,CAAC;uCACH;AAG3B;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;yCACU;AAM5B;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CACY;AAG/B;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CACC;AAGpB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CASzB;AAGM;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;4CACF;AAGlB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;6CACH;AAGhB;IADP,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC;4CACV;AAGnB;IADP,UAAU,CAAC,wBAAwB,EAAE,KAAK,CAAC;sDACP;AAG7B;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDACoB;AAGvC;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;mDACG;AAGtB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CACD;AAGlB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;8CACD;AAKnB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;sDACc;AAGhC;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;4CACF;AAGlB;IADP,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qDACO","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { RapidElement } from '../RapidElement';\nimport { FloatingWindow } from '../layout/FloatingWindow';\nimport { css, PropertyValueMap } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { postJSON, fromCookie, generateUUIDv7 } from '../utils';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\nimport { FlowDefinition } from '../store/flow-definition';\nimport { CustomEventType } from '../interfaces';\nimport { Chat, ContactEvent, MessageType } from '../display/Chat';\nimport { Events, renderEvent } from '../events/eventRenderers';\n\n// test attachment URLs\nconst TEST_IMAGES = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_a.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_b.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_c.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_d.jpg'\n];\n\nconst TEST_VIDEOS = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_video_a.mp4'\n];\n\nconst TEST_AUDIO = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_audio_a.mp3'\n];\n\nconst TEST_LOCATIONS = [\n 'geo:47.6062,-122.3321', // Seattle\n 'geo:-0.1807,-78.4678', // Quito\n 'geo:-2.9001,-79.0059', // Cuenca\n 'geo:-1.9536,30.0606' // Kigali\n];\n\ninterface Contact {\n uuid: string;\n name?: string;\n urns: string[];\n fields?: { [key: string]: any };\n groups?: any[];\n language?: string;\n status?: string;\n created_on?: string;\n}\n\ninterface Session {\n environment: any;\n runs: any[];\n status: string;\n trigger: any;\n wait?: any;\n}\n\ninterface Message {\n uuid: string;\n text?: string;\n urn: string;\n attachments?: string[];\n quick_replies?: any[];\n}\n\ninterface Event {\n type: string;\n created_on: string;\n msg?: Message;\n [key: string]: any;\n}\n\ninterface RunContext {\n session: Session;\n events: Event[];\n context?: any;\n contact?: Contact;\n}\n\ninterface SimulatorSize {\n phoneWidth: number;\n phoneTotalHeight: number;\n phoneScreenHeight: number;\n contextWidth: number;\n contextHeight: number;\n contextOffset: number;\n optionPaneWidth: number;\n optionPaneGap: number;\n windowPadding: number;\n cutoutHeight: number;\n cutoutPadding: number;\n cutoutFontSize: number;\n cutoutIslandWidth: number;\n cutoutIslandHeight: number;\n cutoutIslandTop: number;\n}\n\nconst SIMULATOR_SIZES: Record<string, SimulatorSize> = {\n small: {\n phoneWidth: 270,\n phoneTotalHeight: 530,\n phoneScreenHeight: 376,\n contextWidth: 336,\n contextHeight: 416,\n contextOffset: 48,\n optionPaneWidth: 44,\n optionPaneGap: 10,\n windowPadding: 24,\n cutoutHeight: 32,\n cutoutPadding: 12,\n cutoutFontSize: 10,\n cutoutIslandWidth: 80,\n cutoutIslandHeight: 20,\n cutoutIslandTop: 6\n },\n medium: {\n phoneWidth: 300,\n phoneTotalHeight: 600,\n phoneScreenHeight: 470,\n contextWidth: 420,\n contextHeight: 520,\n contextOffset: 60,\n optionPaneWidth: 44,\n optionPaneGap: 12,\n windowPadding: 30,\n cutoutHeight: 40,\n cutoutPadding: 16,\n cutoutFontSize: 12,\n cutoutIslandWidth: 100,\n cutoutIslandHeight: 24,\n cutoutIslandTop: 8\n },\n large: {\n phoneWidth: 360,\n phoneTotalHeight: 700,\n phoneScreenHeight: 564,\n contextWidth: 504,\n contextHeight: 624,\n contextOffset: 72,\n optionPaneWidth: 44,\n optionPaneGap: 14,\n windowPadding: 36,\n cutoutHeight: 50,\n cutoutPadding: 20,\n cutoutFontSize: 14,\n cutoutIslandWidth: 120,\n cutoutIslandHeight: 30,\n cutoutIslandTop: 10\n }\n};\n\nexport class Simulator extends RapidElement {\n static get styles() {\n return css`\n temba-floating-tab {\n --floating-tab-right: 15px;\n }\n\n :host {\n /* size-specific dimensions are set dynamically via inline styles */\n --phone-width: 300px;\n --phone-total-height: 720px;\n --context-width: 420px;\n --context-offset: 60px;\n --option-pane-width: 44px;\n --option-pane-gap: 12px;\n --window-padding: 30px;\n --phone-screen-height: 470px;\n --context-height: 520px;\n --context-closed-left: 332px;\n --animation-time: 200ms;\n }\n\n .phone-simulator {\n padding-left: calc(var(--context-width) + var(--context-offset));\n padding-top: var(--window-padding);\n padding-bottom: var(--window-padding);\n position: relative;\n display: flex;\n align-items: flex-start;\n }\n\n .option-pane {\n margin-top: var(--window-padding);\n margin-left: var(--option-pane-gap);\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n border-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n }\n .option-btn {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 12px;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all var(--animation-time) ease;\n color: white;\n }\n .option-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n transform: scale(1.05);\n }\n .option-btn:active {\n transform: scale(0.95);\n }\n .option-btn.active {\n background: var(--color-primary-dark);\n color: white;\n }\n .option-btn.active:hover {\n background: var(--color-primary-dark);\n }\n\n .phone-frame {\n width: var(--phone-width);\n height: var(--phone-total-height);\n border-radius: 40px;\n border: 6px solid #1f2937;\n box-shadow: 0 0px 30px rgba(0, 0, 0, 0.4);\n background: #000;\n position: relative;\n overflow: hidden;\n z-index: 2;\n }\n\n .context-explorer {\n width: var(--context-width);\n height: var(--context-height);\n border-top-left-radius: 16px;\n border-bottom-left-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n position: absolute;\n left: var(--context-closed-left);\n top: calc(var(--window-padding) + 40px);\n z-index: 1;\n font-size: 13px;\n color: #374151;\n transition: left calc(var(--animation-time) * 1.5) ease-out,\n opacity calc(var(--animation-time) * 1.5) ease-out;\n opacity: 0;\n pointer-events: none;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n display: flex;\n flex-direction: column;\n padding: 12px;\n }\n\n .context-gutter {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 6px;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 4px;\n margin-right: 32px;\n margin-top: 8px;\n flex-shrink: 0;\n }\n\n .context-gutter-btn {\n width: 14px;\n height: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border-radius: 6px;\n transition: background var(--animation-time) ease;\n color: rgba(255, 255, 255, 0.6);\n padding: 4px;\n }\n\n .context-gutter-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.9);\n }\n\n .context-gutter-btn.active {\n color: #c084fc;\n }\n\n .context-gutter-spacer {\n flex: 1;\n }\n\n .context-explorer-scroll {\n scrollbar-color: rgba(255, 255, 255, 0.3) #4a4a4a;\n scrollbar-width: thin;\n height: 100%;\n overflow-y: scroll;\n padding-right: 10px;\n margin-right: 30px;\n flex-grow: 1;\n }\n\n .context-explorer-bleed {\n height: 100%;\n width: 0px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar {\n width: 18px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n }\n\n /* Custom scrollbar for chat area to allow content to flow behind input */\n .custom-scrollbar-container {\n position: absolute;\n top: 40px;\n bottom: var(--bottom-input-height, 60px);\n right: 4px;\n width: 10px;\n z-index: 20;\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar {\n width: 6px;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n }\n\n .custom-scrollbar-container::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.4);\n }\n\n .custom-scrollbar-content {\n width: 100%;\n }\n\n .context-explorer.open {\n left: var(--context-offset);\n opacity: 1;\n pointer-events: auto;\n }\n\n .context-explorer.hidden {\n pointer-events: none !important;\n }\n\n .context-item {\n display: flex;\n align-items: flex-start;\n padding: 2px 4px;\n cursor: pointer;\n user-select: none;\n }\n\n .context-item:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n .context-item-expandable {\n display: flex;\n align-items: center;\n }\n\n .context-expand-icon {\n width: 16px;\n display: inline-block;\n text-align: center;\n flex-shrink: 0;\n transition: transform var(--animation-time) ease;\n color: #ffffff;\n }\n\n .context-expand-icon.expanded {\n transform: rotate(90deg);\n }\n\n .context-key {\n color: #ffffff;\n flex-shrink: 0;\n margin-right: 8px;\n display: flex;\n }\n\n .context-key.has-value {\n color: #e8b5e8;\n }\n\n .context-value {\n color: #aaa;\n flex: 1;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .context-children {\n margin-left: 16px;\n }\n\n .context-copy-icon {\n opacity: 0;\n margin-left: 4px;\n transition: opacity var(--animation-time) ease;\n cursor: pointer;\n color: #ccc;\n }\n\n .context-item:hover .context-copy-icon {\n opacity: 1;\n }\n\n .context-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n background: #666;\n color: white;\n padding: 12px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n font-size: 13px;\n z-index: 10;\n animation: slideInUp var(--animation-time) ease-out;\n }\n\n .context-toast .expression {\n color: #e8b5e8;\n font-weight: 600;\n }\n\n @keyframes slideInUp {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .phone-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 10;\n cursor: grab;\n }\n .phone-notch {\n background: transparent;\n height: var(--cutout-height);\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 var(--cutout-padding);\n }\n .phone-notch::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: linear-gradient(\n to bottom,\n rgba(0, 0, 0, 0.3) 0%,\n rgba(0, 0, 0, 0.2) 50%,\n transparent 100%\n );\n z-index: -1;\n }\n .dynamic-island {\n top: var(--cutout-island-top);\n left: 50%;\n\n width: var(--cutout-island-width);\n height: var(--cutout-island-height);\n background: #000;\n border-radius: calc(var(--cutout-island-height) / 1.5);\n z-index: 1;\n }\n .phone-notch .time {\n color: #000;\n font-size: var(--cutout-font-size);\n font-weight: 600;\n }\n .phone-notch .status-icons {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n .phone-notch .status-icons span {\n color: #000;\n font-size: var(--cutout-font-size);\n }\n .phone-header {\n background: transparent;\n padding: 10px 15px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n cursor: move;\n user-select: none;\n border-bottom: none;\n pointer-events: all;\n }\n\n .phone-screen {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: white;\n display: flex;\n flex-direction: column;\n }\n\n temba-chat {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n --color-chat-in: #e5e5ea;\n --color-chat-out: #007aff;\n --chat-top-padding: calc(var(--cutout-height));\n --chat-bottom-padding: calc(var(--bottom-input-height, 80px) - 10px);\n }\n\n .bottom-input-container {\n position: absolute;\n bottom: 0px;\n left: 0px;\n right: 0px;\n z-index: 10;\n }\n\n .bottom-input-container::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.45);\n backdrop-filter: blur(10px);\n -webkit-mask-image: linear-gradient(to bottom, transparent, black 20px);\n mask-image: linear-gradient(to bottom, transparent, black 20px);\n z-index: -1;\n }\n\n .quick-replies-container {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 6px;\n z-index: 9;\n }\n\n .quick-reply-btn {\n padding: 4px 8px;\n border-radius: 18px;\n border: 1px solid var(--color-primary, #007aff);\n background: white;\n color: var(--color-primary, #007aff);\n font-size: 11px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .quick-reply-btn:hover:not(:disabled) {\n background: var(--color-primary, #007aff);\n color: white;\n }\n\n .quick-reply-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .message-input {\n padding: 8px 12px;\n border-top: none;\n display: flex;\n align-items: center;\n gap: 8px;\n z-index: 10;\n }\n .message-input input {\n flex: 1;\n border: 1px solid #c6c6c857;\n border-radius: 20px;\n padding: 8px 15px;\n font-size: 15px;\n margin-bottom: 5px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n outline: none;\n }\n .message-input input::placeholder {\n color: #8e8e93;\n }\n .attachment-button {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n border: 1px solid #c6c6c857;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n flex-shrink: 0;\n margin-bottom: 5px;\n transition: all var(--animation-time) ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n color: #000;\n }\n .attachment-button:hover {\n background: #f8f8f8ff;\n transform: scale(1.05);\n }\n .attachment-button:active {\n transform: scale(0.95);\n }\n .attachment-menu {\n position: absolute;\n bottom: 55px;\n left: 12px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n opacity: 0;\n pointer-events: none;\n transform: translateY(10px);\n transition: opacity var(--animation-time) ease, transform 0.2s ease;\n z-index: 20;\n }\n .attachment-menu.open {\n opacity: 1;\n pointer-events: all;\n transform: translateY(0);\n }\n .attachment-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background var(--animation-time) ease;\n white-space: nowrap;\n font-size: 14px;\n color: #1f2937;\n }\n .attachment-menu-item:hover {\n background: #f3f4f6;\n }\n .attachment-menu-item temba-icon {\n color: #007aff;\n }\n `;\n }\n\n @fromStore(zustand, (state: AppState) => state.flowDefinition)\n private definition!: FlowDefinition;\n\n @fromStore(zustand, (state: AppState) => state.viewingRevision)\n private viewingRevision!: boolean;\n\n @property({ type: String })\n flow = '';\n\n @property({ type: String })\n endpoint = '';\n\n @property({ type: Number })\n animationTime = 200;\n\n @fromCookie('simulator-size', 'small')\n size: 'small' | 'medium' | 'large';\n\n @property({ type: Array })\n private events: ContactEvent[] = [];\n\n private previousEventCount = 0;\n private chat: Chat = null;\n\n @property({ type: Object })\n private session: Session | null = null;\n\n @property({ type: Object })\n private context: any = null;\n\n @property({ type: Object })\n private contact: Contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n @property({ type: Boolean })\n private sprinting = false;\n\n @property({ type: String })\n private inputValue = '';\n\n @fromCookie('simulator-follow', true)\n private following: boolean;\n\n @fromCookie('simulator-context-open', false)\n private contextExplorerOpen: boolean;\n\n @property({ type: Object })\n private expandedPaths: Set<string> = new Set();\n\n @property({ type: String })\n private copiedExpression = '';\n\n @property({ type: String })\n private toastMessage = '';\n\n @property({ type: Boolean })\n private showAllKeys = true;\n\n private previousWindowWidth = 0;\n\n @property({ type: Array })\n private currentQuickReplies: any[] = [];\n\n @property({ type: Boolean })\n private isVisible = false;\n\n @property({ type: Boolean })\n private attachmentMenuOpen = false;\n\n private boundClickOutsideHandler: ((event: MouseEvent) => void) | null = null;\n\n // attachment cycling indices - initialized randomly\n private imageIndex = Math.floor(Math.random() * TEST_IMAGES.length);\n private videoIndex = Math.floor(Math.random() * TEST_VIDEOS.length);\n private audioIndex = Math.floor(Math.random() * TEST_AUDIO.length);\n private locationIndex = Math.floor(Math.random() * TEST_LOCATIONS.length);\n\n // method to reset attachment indices for testing\n public resetAttachmentIndices() {\n this.imageIndex = 2;\n this.videoIndex = 0;\n this.audioIndex = 0;\n this.locationIndex = 0;\n }\n\n private get sizeConfig(): SimulatorSize {\n return SIMULATOR_SIZES[this.size] || SIMULATOR_SIZES.medium;\n }\n\n private get windowWidth(): number {\n const config = this.sizeConfig;\n return (\n config.contextWidth +\n config.phoneWidth +\n config.optionPaneWidth +\n config.optionPaneGap +\n config.contextOffset\n );\n }\n\n private get leftBoundaryMargin(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset;\n }\n\n private get contextClosedLeft(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset - config.phoneWidth;\n }\n\n public connectedCallback() {\n super.connectedCallback();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.chat = this.shadowRoot.querySelector('temba-chat');\n\n // if we have events that were collected before chat was ready, add them now\n if (this.chat && this.events.length > 0) {\n this.chat.addMessages(this.events, null, true);\n }\n\n this.setupCustomScrollbar();\n }\n\n private setupCustomScrollbar() {\n const chat = this.shadowRoot?.querySelector('temba-chat') as Chat;\n const scrollContainer = this.shadowRoot?.querySelector(\n '.custom-scrollbar-container'\n ) as HTMLElement;\n const scrollContent = this.shadowRoot?.querySelector(\n '.custom-scrollbar-content'\n ) as HTMLElement;\n\n if (!chat || !scrollContainer || !scrollContent) return;\n\n chat.updateComplete.then(() => {\n const chatScroll = chat.shadowRoot?.querySelector(\n '.scroll'\n ) as HTMLElement;\n if (!chatScroll) return;\n\n let ignoreScroll = false;\n\n // Sync from chat to custom scrollbar\n chatScroll.addEventListener('scroll', () => {\n if (!ignoreScroll) {\n ignoreScroll = true;\n // Chat: 0 (bottom) ... -Max (top) (Negative scrolling)\n // Custom: Max (bottom) ... 0 (top) (Positive scrolling)\n\n const maxScroll =\n scrollContainer.scrollHeight - scrollContainer.clientHeight;\n // Math.abs to handle negative scrollTop\n const distanceFromBottom = Math.abs(chatScroll.scrollTop);\n const newCustomScrollTop = maxScroll - distanceFromBottom;\n\n scrollContainer.scrollTop = newCustomScrollTop;\n\n requestAnimationFrame(() => (ignoreScroll = false));\n }\n });\n\n // Sync from custom scrollbar to chat\n scrollContainer.addEventListener('scroll', () => {\n if (!ignoreScroll) {\n ignoreScroll = true;\n\n const maxScroll =\n scrollContainer.scrollHeight - scrollContainer.clientHeight;\n const distanceFromBottom = maxScroll - scrollContainer.scrollTop;\n\n // chat scrollTop should be -distanceFromBottom\n chatScroll.scrollTop = -distanceFromBottom;\n\n requestAnimationFrame(() => (ignoreScroll = false));\n }\n });\n\n // Sync height\n const syncHeight = () => {\n const chatMaxScroll = chatScroll.scrollHeight - chatScroll.clientHeight;\n const customClientHeight = scrollContainer.clientHeight;\n\n // ensure minimum height\n if (chatMaxScroll <= 0) {\n scrollContent.style.height = '100%';\n return;\n }\n\n const newHeight = chatMaxScroll + customClientHeight;\n scrollContent.style.height = `${newHeight}px`;\n\n // If we were effectively at the bottom, stay at the bottom\n // This is a heuristic, assuming if we're close enough we're \"at bottom\"\n // But the Chat component handles scrollToBottom on new messages, which fires scroll event,\n // which updates us. So we might not need to force it here unless resize happens without message.\n if (Math.abs(chatScroll.scrollTop) < 5) {\n scrollContainer.scrollTop = scrollContainer.scrollHeight;\n }\n };\n\n // Observe changes\n const observer = new MutationObserver(syncHeight);\n observer.observe(chatScroll, {\n childList: true,\n subtree: true,\n attributes: true\n });\n\n const resizeObserver = new ResizeObserver(syncHeight);\n resizeObserver.observe(chatScroll);\n\n // Initial sync\n syncHeight();\n });\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (\n changes.has('currentQuickReplies') ||\n changes.has('keyboardVisible') ||\n changes.has('attachmentMenuOpen')\n ) {\n this.updateBottomInputHeight();\n }\n\n if (changes.has('flow') && this.flow) {\n this.endpoint = `/flow/simulate/${this.flow}/`;\n }\n\n // handle attachment menu click outside listener\n if (changes.has('attachmentMenuOpen')) {\n if (this.attachmentMenuOpen) {\n // create bound handler if it doesn't exist\n if (!this.boundClickOutsideHandler) {\n this.boundClickOutsideHandler =\n this.handleClickOutsideAttachmentMenu.bind(this);\n }\n // add listener when menu opens\n setTimeout(() => {\n document.addEventListener('click', this.boundClickOutsideHandler);\n }, 0);\n } else {\n // remove listener when menu closes\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n }\n\n // update floating window boundaries when size changes\n if (changes.has('size')) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n // use the stored previous width since phoneWindow.width has already been updated\n const oldWidth = this.previousWindowWidth || phoneWindow.width;\n const oldRight = phoneWindow.left + oldWidth;\n\n const config = this.sizeConfig;\n const newWidth = this.windowWidth;\n\n // store current width for next size change\n this.previousWindowWidth = newWidth;\n\n // update dimensions and boundaries\n phoneWindow.width = newWidth;\n phoneWindow.leftBoundaryMargin = this.leftBoundaryMargin;\n phoneWindow.topBoundaryMargin = config.windowPadding;\n phoneWindow.bottomBoundaryMargin = config.windowPadding;\n\n // keep right edge in same position by adjusting left\n let newLeft = oldRight - newWidth;\n\n // apply same boundary logic as FloatingWindow.handleMouseMove\n const padding = 20;\n const minLeft = padding - this.leftBoundaryMargin;\n const maxLeft =\n window.innerWidth -\n newWidth -\n padding +\n phoneWindow.rightBoundaryMargin;\n\n // clamp to boundaries\n newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft));\n\n phoneWindow.left = newLeft;\n\n // adjust vertical position if needed\n const windowElement = phoneWindow.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || config.phoneTotalHeight;\n const maxTop = Math.max(\n padding - config.windowPadding,\n window.innerHeight - currentHeight - padding + config.windowPadding\n );\n\n phoneWindow.top = Math.max(\n padding - config.windowPadding,\n Math.min(phoneWindow.top, maxTop)\n );\n }\n });\n } else {\n // store initial width when first rendered\n if (!this.previousWindowWidth) {\n this.previousWindowWidth = this.windowWidth;\n }\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n // clean up event listener when component is removed\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n\n private handleShow() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n phoneWindow.show();\n this.isVisible = true;\n getStore().getState().setSimulatorActive(true);\n\n // ensure chat component is available\n if (!this.chat) {\n this.chat = this.shadowRoot.querySelector('temba-chat');\n }\n\n // start the simulation if we haven't already\n if (!this.session) {\n this.startFlow();\n }\n }\n\n private async startFlow() {\n const now = new Date().toISOString();\n\n // set created_on to simulation start time\n this.contact = { ...this.contact, created_on: now };\n\n const body = {\n contact: this.contact,\n trigger: {\n type: 'manual',\n triggered_on: now,\n flow: { uuid: this.flow, name: 'New Chat' },\n params: {}\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n this.updateRunContext(response.json as RunContext);\n } catch (error) {\n console.error('Failed to start simulation:', error);\n const errorEvent = {\n uuid: generateUUIDv7(),\n type: 'error',\n created_on: new Date(now),\n _rendered: {\n html: html`<p>Failed to start simulation</p>`,\n type: MessageType.Error\n }\n } as ContactEvent;\n if (this.chat) {\n this.chat.addMessages([errorEvent], null, true);\n } else {\n this.events = [...this.events, errorEvent];\n }\n }\n }\n\n private updateRunContext(runContext: RunContext, msgInEvt?: ContactEvent) {\n const newEvents: ContactEvent[] = [];\n\n // add the user's message if provided\n if (msgInEvt) {\n // ensure it has a UUID\n if (!msgInEvt.uuid) {\n msgInEvt.uuid = generateUUIDv7();\n }\n // ensure created_on is a Date object\n if (typeof msgInEvt.created_on === 'string') {\n msgInEvt.created_on = new Date(msgInEvt.created_on);\n }\n newEvents.push(msgInEvt);\n }\n\n if (runContext.session) {\n this.session = runContext.session;\n\n // update our contact with the latest from the session\n if (runContext.contact) {\n this.contact = runContext.contact;\n }\n }\n\n // store the context from the response\n if (runContext.context) {\n this.context = runContext.context;\n }\n\n // extract quick replies from the most recent sprint\n this.currentQuickReplies = [];\n\n if (runContext.events && runContext.events.length > 0) {\n for (const rawEvent of runContext.events) {\n // skip msg_received events from the server since we already added the user's message\n if (rawEvent.type === 'msg_received') {\n continue;\n }\n\n // skip msg_created/ivr_created events without a proper msg property\n if (\n (rawEvent.type === 'msg_created' ||\n rawEvent.type === 'ivr_created') &&\n !(rawEvent as any).msg\n ) {\n continue;\n }\n\n // convert to ContactEvent\n const event: ContactEvent = {\n ...rawEvent,\n uuid: rawEvent.uuid || generateUUIDv7(),\n created_on:\n typeof rawEvent.created_on === 'string'\n ? new Date(rawEvent.created_on)\n : rawEvent.created_on\n } as ContactEvent;\n\n // pre-render non-message events\n this.prerenderEvent(event);\n\n // extract quick replies from msg_created events\n if (event.type === 'msg_created' && (event as any).msg?.quick_replies) {\n this.currentQuickReplies = (event as any).msg.quick_replies;\n }\n\n const isMessage =\n event.type === 'msg_created' || event.type === 'ivr_created';\n const msg = (event as any).msg;\n\n // Check if the event should be displayed.\n // 1. If it's a message, it must have text or attachments\n if (isMessage) {\n const hasText = msg.text && msg.text.trim().length > 0;\n const hasAttachments = msg.attachments && msg.attachments.length > 0;\n if (!hasText && !hasAttachments) {\n continue;\n }\n }\n // 2. If it's not a message, it must have been rendered by prerenderEvent\n else if (!event._rendered) {\n continue;\n }\n\n newEvents.push(event);\n }\n }\n\n // add all new events to chat component if it exists\n if (this.chat) {\n this.chat.addMessages(newEvents, null, true);\n } else {\n // fallback: store events and add them once chat is ready\n this.events = [...this.events, ...newEvents];\n }\n\n this.sprinting = false;\n this.requestUpdate(); // trigger re-render for quick replies\n this.scrollToBottom();\n this.updateActivity();\n }\n\n private updateActivity() {\n if (!this.session) {\n return;\n }\n\n const pathCounts: { [key: string]: number } = {};\n const nodeCounts: { [nodeUUID: string]: number } = {};\n\n // iterate through all runs to get path segment counts\n for (const run of this.session.runs) {\n if (run.path) {\n for (let i = 0; i < run.path.length - 1; i++) {\n const step = run.path[i];\n const nextStep = run.path[i + 1];\n if (step.exit_uuid && nextStep.node_uuid) {\n const key = step.exit_uuid + ':' + nextStep.node_uuid;\n pathCounts[key] = (pathCounts[key] || 0) + 1;\n }\n }\n }\n\n // set node counts on the last step of any active/waiting runs\n if (run.status === 'active' || run.status === 'waiting') {\n if (run.path && run.path.length > 0) {\n const finalStep = run.path[run.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n nodeCounts[finalStep.node_uuid] =\n (nodeCounts[finalStep.node_uuid] || 0) + 1;\n }\n }\n }\n }\n\n // Update simulator activity in the store\n getStore().getState().updateSimulatorActivity({\n segments: pathCounts,\n nodes: nodeCounts\n });\n\n // Fire follow event if following is enabled\n if (this.following) {\n this.fireFollowEvent();\n }\n }\n\n private fireFollowEvent() {\n if (!this.session || !this.session.runs || this.session.runs.length === 0) {\n return;\n }\n\n // Find the first active or waiting run\n let activeRun = this.session.runs.find(\n (run: any) => run.status === 'active' || run.status === 'waiting'\n );\n\n // If no active/waiting run and simulation has ended, use the first completed run\n if (!activeRun) {\n activeRun = this.session.runs.find(\n (run: any) => run.status === 'completed'\n );\n }\n\n if (activeRun && activeRun.path && activeRun.path.length > 0) {\n const finalStep = activeRun.path[activeRun.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n this.fireCustomEvent(CustomEventType.FollowSimulation, {\n flowUuid: activeRun.flow?.uuid || this.flow,\n nodeUuid: finalStep.node_uuid\n });\n }\n }\n }\n\n private scrollToBottom() {\n if (this.chat) {\n // chat component handles scrolling, but we still need to focus input\n this.chat.scrollToBottom();\n setTimeout(() => {\n const input = this.shadowRoot?.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n if (input) {\n input.focus();\n }\n }, 50);\n return;\n }\n // wait for render, then scroll to bottom\n setTimeout(() => {\n const screen = this.shadowRoot?.querySelector('.phone-screen');\n if (screen) {\n screen.scrollTop = screen.scrollHeight;\n }\n // update previous count after animation completes\n this.previousEventCount = this.events.length;\n\n // return focus to input\n const input = this.shadowRoot?.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n if (input) {\n input.focus();\n }\n }, 50);\n }\n\n private prerenderEvent(event: ContactEvent) {\n // skip if already rendered or is a message event\n if (\n event._rendered ||\n event.type === Events.MSG_CREATED ||\n event.type === Events.MSG_RECEIVED\n ) {\n return;\n }\n\n // handle simulator-specific events (errors, warnings, failures)\n if (event.type === 'error' || event.type === 'failure') {\n event._rendered = {\n html: renderEvent(event, true),\n type: MessageType.Error\n };\n return;\n }\n\n if (event.type === 'warning') {\n event._rendered = {\n html: renderEvent(event, true),\n type: MessageType.Note\n };\n return;\n }\n\n // try to render as a standard event\n const rendered = renderEvent(event, true);\n if (rendered) {\n event._rendered = {\n html: rendered,\n type: MessageType.Inline\n };\n }\n }\n\n private handleClose() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n phoneWindow.handleClose();\n this.isVisible = false;\n getStore().getState().setSimulatorActive(false);\n }\n\n private handleReset() {\n // reset simulation state\n this.events = [];\n this.session = null;\n this.context = null;\n this.inputValue = '';\n this.sprinting = false;\n this.previousEventCount = 0;\n this.currentQuickReplies = [];\n\n // reset chat component\n if (this.chat) {\n this.chat.reset();\n }\n\n // Clear simulator activity data\n getStore().getState().updateSimulatorActivity({\n segments: {},\n nodes: {}\n });\n\n // reset contact to initial state\n this.contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n // restart the flow\n this.startFlow();\n }\n\n private handleToggleFollow() {\n this.following = !this.following;\n }\n\n private handleCycleSize() {\n const sizes: Array<'small' | 'medium' | 'large'> = [\n 'small',\n 'medium',\n 'large'\n ];\n const currentIndex = sizes.indexOf(this.size);\n const nextIndex = (currentIndex + 1) % sizes.length;\n this.size = sizes[nextIndex];\n }\n\n private handleToggleContextExplorer() {\n this.contextExplorerOpen = !this.contextExplorerOpen;\n\n // if opening the context explorer, ensure it's not off-screen\n if (this.contextExplorerOpen) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n const padding = 20;\n const contextExplorerLeft = this.sizeConfig.contextOffset;\n const minWindowLeft = padding - contextExplorerLeft;\n\n if (phoneWindow.left < minWindowLeft) {\n phoneWindow.left = minWindowLeft;\n }\n }\n });\n }\n }\n\n private togglePath(path: string) {\n if (this.expandedPaths.has(path)) {\n this.expandedPaths.delete(path);\n } else {\n this.expandedPaths.add(path);\n }\n this.requestUpdate();\n }\n\n private isExpandable(value: any): boolean {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n\n // check if object has keys other than __default__\n const keys = Object.keys(value).filter((key) => key !== '__default__');\n return keys.length > 0;\n }\n\n private renderContextValue(value: any): TemplateResult | string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'boolean')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'number')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'string')\n return html`<span class=\"context-value\">${value}</span>`;\n if (Array.isArray(value))\n return html`<span class=\"context-value\">[${value.length}]</span>`;\n return '';\n }\n\n private buildExpression(path: string): string {\n return `@${path}`;\n }\n\n private async handleCopyExpression(\n path: string,\n event: Event\n ): Promise<void> {\n event.stopPropagation();\n const expression = this.buildExpression(path);\n try {\n await navigator.clipboard.writeText(expression);\n this.copiedExpression = expression;\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.copiedExpression = '';\n }, 2000);\n } catch (err) {\n console.error('Failed to copy expression:', err);\n }\n }\n\n private handleToggleShowAllKeys() {\n this.showAllKeys = !this.showAllKeys;\n this.toastMessage = this.showAllKeys\n ? 'Showing all keys'\n : 'Filtering out keys without values';\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.toastMessage = '';\n }, 2000);\n }\n\n private renderContextTree(\n obj: any,\n path: string = ''\n ): TemplateResult | TemplateResult[] {\n if (!obj || typeof obj !== 'object') {\n return html``;\n }\n\n let entries = Array.isArray(obj)\n ? obj.map((v, i) => [String(i), v])\n : Object.entries(obj).filter(([key]) => key !== '__default__');\n\n // filter out keys without values if showAllKeys is false\n if (!this.showAllKeys) {\n entries = entries.filter(([, value]) => {\n // keep if expandable (has children)\n if (this.isExpandable(value)) return true;\n // keep if it has a displayable value (not null/undefined)\n if (value === null || value === undefined) return false;\n // keep primitives with values\n return (\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string' ||\n Array.isArray(value)\n );\n });\n }\n\n return html`${entries.map(([key, value]) => {\n const currentPath = path ? `${path}.${key}` : key;\n const isExpanded = this.expandedPaths.has(currentPath);\n const expandable = this.isExpandable(value);\n\n // check if this object has a __default__ value\n let displayValue = value;\n\n if (\n expandable &&\n !Array.isArray(value) &&\n value !== null &&\n typeof value === 'object' &&\n '__default__' in value\n ) {\n displayValue = value.__default__;\n }\n\n return html`\n <div>\n <div\n class=\"context-item ${expandable ? 'context-item-expandable' : ''}\"\n @click=${() => expandable && this.togglePath(currentPath)}\n >\n ${expandable\n ? html`<span\n class=\"context-expand-icon ${isExpanded ? 'expanded' : ''}\"\n >›</span\n >`\n : html`<span class=\"context-expand-icon\"></span>`}\n <span class=\"context-key ${expandable ? 'has-value' : ''}\"\n >${key}\n <temba-icon\n class=\"context-copy-icon\"\n name=\"copy\"\n size=\"0.9\"\n @click=${(e: Event) =>\n this.handleCopyExpression(currentPath, e)}\n ></temba-icon>\n </span>\n ${!isExpanded ? this.renderContextValue(displayValue) : html``}\n </div>\n ${isExpanded\n ? html`<div class=\"context-children\">\n ${this.renderContextTree(value, currentPath)}\n </div>`\n : html``}\n </div>\n `;\n })}`;\n }\n\n private async resume(text: string, attachment?: string) {\n if ((!text && !attachment) || !this.session) {\n return;\n }\n\n this.sprinting = true;\n this.inputValue = '';\n this.currentQuickReplies = [];\n this.attachmentMenuOpen = false;\n\n const now = new Date().toISOString();\n\n // create the event for the API (with ISO string date)\n const msgInEvtForAPI = {\n uuid: generateUUIDv7(),\n type: 'msg_received',\n created_on: now,\n msg: {\n uuid: generateUUIDv7(),\n text: text || '',\n urn: this.contact.urns[0],\n direction: 'in',\n type: 'text',\n attachments: attachment ? [attachment] : [],\n quick_replies: [],\n channel: { uuid: generateUUIDv7(), name: 'Simulator' }\n }\n };\n\n // create the ContactEvent for display (with Date object)\n const msgInEvt = {\n ...msgInEvtForAPI,\n created_on: new Date(now)\n } as ContactEvent;\n\n // show user's message immediately via chat component\n if (this.chat) {\n this.chat.addMessages([msgInEvt], null, true);\n } else {\n this.events = [...this.events, msgInEvt];\n }\n this.requestUpdate();\n this.scrollToBottom();\n\n const body = {\n session: this.session,\n contact: this.contact,\n resume: {\n type: 'msg',\n event: msgInEvtForAPI,\n resumed_on: now\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n\n // add a small delay before showing the reply to simulate typing\n await new Promise((resolve) => setTimeout(resolve, 400));\n\n // pass null for msgInEvt since we already added it\n this.updateRunContext(response.json as RunContext, null);\n } catch (error) {\n console.error('Failed to resume simulation:', error);\n const errorEvent = {\n uuid: generateUUIDv7(),\n type: 'error',\n created_on: new Date(now),\n _rendered: {\n html: html`<p>Failed to send message</p>`,\n type: MessageType.Error\n }\n } as ContactEvent;\n if (this.chat) {\n this.chat.addMessages([errorEvent], null, true);\n } else {\n this.events = [...this.events, errorEvent];\n }\n this.sprinting = false;\n }\n }\n\n private handleKeyUp(evt: KeyboardEvent) {\n if (evt.key === 'Enter') {\n const input = evt.target as HTMLInputElement;\n const text = input.value.trim();\n if (text) {\n this.resume(text);\n }\n }\n }\n\n private handleInput(evt: Event) {\n const input = evt.target as HTMLInputElement;\n this.inputValue = input.value;\n }\n\n private handleQuickReplyClick(text: string) {\n if (!this.sprinting && text) {\n this.resume(text);\n }\n }\n\n private handleToggleAttachmentMenu() {\n this.attachmentMenuOpen = !this.attachmentMenuOpen;\n }\n\n private handleClickOutsideAttachmentMenu(event: MouseEvent) {\n if (!this.attachmentMenuOpen) {\n return;\n }\n\n const menu = this.shadowRoot?.querySelector('.attachment-menu');\n const button = this.shadowRoot?.querySelector('.attachment-button');\n\n if (!menu || !button) {\n return;\n }\n\n // check if click is outside both menu and button\n const clickedInsideMenu = menu.contains(event.target as Node);\n const clickedInsideButton = button.contains(event.target as Node);\n\n if (!clickedInsideMenu && !clickedInsideButton) {\n this.attachmentMenuOpen = false;\n }\n }\n\n private handleSendAttachment(attachmentType: string) {\n let attachment = '';\n switch (attachmentType) {\n case 'image':\n attachment = `image/jpeg:${TEST_IMAGES[this.imageIndex]}`;\n this.imageIndex = (this.imageIndex + 1) % TEST_IMAGES.length;\n break;\n case 'video':\n attachment = `video/mp4:${TEST_VIDEOS[this.videoIndex]}`;\n this.videoIndex = (this.videoIndex + 1) % TEST_VIDEOS.length;\n break;\n case 'audio':\n attachment = `audio/mp3:${TEST_AUDIO[this.audioIndex]}`;\n this.audioIndex = (this.audioIndex + 1) % TEST_AUDIO.length;\n break;\n case 'location':\n attachment = TEST_LOCATIONS[this.locationIndex];\n this.locationIndex = (this.locationIndex + 1) % TEST_LOCATIONS.length;\n break;\n }\n\n if (attachment) {\n this.resume('', attachment);\n }\n }\n\n private updateBottomInputHeight() {\n requestAnimationFrame(() => {\n const bottomContainer = this.shadowRoot?.querySelector(\n '.bottom-input-container'\n ) as HTMLElement;\n if (bottomContainer) {\n const height = bottomContainer.offsetHeight;\n this.style.setProperty('--bottom-input-height', `${height}px`);\n }\n });\n }\n\n protected render(): TemplateResult {\n if (this.viewingRevision || this.definition?.nodes.length === 0) {\n return html``;\n }\n\n const config = this.sizeConfig;\n\n // set CSS custom properties dynamically based on size\n const styleVars = `\n --phone-width: ${config.phoneWidth}px;\n --phone-total-height: ${config.phoneTotalHeight}px;\n --context-width: ${config.contextWidth}px;\n --context-offset: ${config.contextOffset}px;\n --option-pane-width: ${config.optionPaneWidth}px;\n --option-pane-gap: ${config.optionPaneGap}px;\n --window-padding: ${config.windowPadding}px;\n --phone-screen-height: ${config.phoneScreenHeight}px;\n --context-height: ${config.contextHeight}px;\n --context-closed-left: ${this.contextClosedLeft}px;\n --cutout-height: ${config.cutoutHeight}px;\n --cutout-padding: ${config.cutoutPadding}px;\n --cutout-font-size: ${config.cutoutFontSize}px;\n --cutout-island-width: ${config.cutoutIslandWidth}px;\n --cutout-island-height: ${config.cutoutIslandHeight}px;\n --cutout-island-top: ${config.cutoutIslandTop}px;\n --animation-time: ${this.animationTime}ms;\n `;\n\n return html`\n <temba-floating-window\n style=\"--transition-duration: ${this.animationTime}ms\"\n id=\"phone-window\"\n width=\"${this.windowWidth}\"\n leftBoundaryMargin=\"${this.leftBoundaryMargin}\"\n bottomBoundaryMargin=\"${config.windowPadding}\"\n topBoundaryMargin=\"${config.windowPadding}\"\n height=\"${config.phoneTotalHeight}\"\n top=\"0\"\n chromeless\n >\n <div class=\"phone-simulator\" style=\"${styleVars}\">\n <div\n class=\"context-explorer ${this.contextExplorerOpen\n ? 'open'\n : ''} ${this.isVisible ? 'visible' : 'hidden'}\"\n >\n <div class=\"context-explorer-scroll\">\n ${this.context\n ? this.renderContextTree(this.context)\n : html`<div\n style=\"color: #9ca3af; padding: 8px; text-align: center;\"\n >\n No context available\n </div>`}\n </div>\n <div class=\"context-gutter\">\n <div\n class=\"context-gutter-btn ${this.showAllKeys ? '' : 'active'}\"\n @click=${this.handleToggleShowAllKeys}\n title=\"${this.showAllKeys\n ? 'Show keys with values only'\n : 'Show all keys'}\"\n >\n <temba-icon\n name=\"${this.showAllKeys ? 'filter' : 'filter'}\"\n size=\"1\"\n ></temba-icon>\n </div>\n <div class=\"context-gutter-spacer\"></div>\n <div\n class=\"context-gutter-btn\"\n @click=${this.handleToggleContextExplorer}\n title=\"Close\"\n >\n <temba-icon name=\"x\" size=\"1\"></temba-icon>\n </div>\n </div>\n ${this.copiedExpression\n ? html`<div class=\"context-toast\">\n Copied\n <span class=\"expression\">${this.copiedExpression}</span>\n to the clipboard\n </div>`\n : this.toastMessage\n ? html`<div class=\"context-toast\">${this.toastMessage}</div>`\n : html``}\n </div>\n\n <div\n class=\"phone-frame\"\n style=\"pointer-events: ${this.isVisible ? 'all' : 'none'}\"\n >\n <div class=\"phone-top drag-handle\">\n <div class=\"phone-notch\">\n <div class=\"dynamic-island\"></div>\n </div>\n </div>\n <temba-chat class=\"phone-screen\" .showTimestamps=${false}>\n </temba-chat>\n <div class=\"custom-scrollbar-container\">\n <div class=\"custom-scrollbar-content\"></div>\n </div>\n\n <div class=\"bottom-input-container\">\n ${this.currentQuickReplies.length > 0\n ? html`<div class=\"quick-replies-container\">\n ${this.currentQuickReplies.map(\n (qr) => html`\n <button\n class=\"quick-reply-btn\"\n @click=${() => this.handleQuickReplyClick(qr.text)}\n ?disabled=${this.sprinting}\n >\n ${qr.text}\n </button>\n `\n )}\n </div>`\n : null}\n <div class=\"message-input\">\n <button\n class=\"attachment-button\"\n @click=${this.handleToggleAttachmentMenu}\n ?disabled=${this.sprinting}\n >\n <temba-icon name=\"plus\" size=\"1.5\"></temba-icon>\n </button>\n <input\n type=\"text\"\n placeholder=\"Enter Message\"\n .value=${this.inputValue}\n @input=${this.handleInput}\n @keyup=${this.handleKeyUp}\n ?disabled=${this.sprinting}\n />\n <div\n class=\"attachment-menu ${this.attachmentMenuOpen\n ? 'open'\n : ''}\"\n >\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('image')}\n >\n <temba-icon name=\"attachment_image\" size=\"1.2\"></temba-icon>\n <span>Image</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('video')}\n >\n <temba-icon name=\"attachment_video\" size=\"1.2\"></temba-icon>\n <span>Video</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('audio')}\n >\n <temba-icon name=\"attachment_audio\" size=\"1.2\"></temba-icon>\n <span>Audio</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('location')}\n >\n <temba-icon\n name=\"attachment_location\"\n size=\"1.2\"\n ></temba-icon>\n <span>Location</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"option-pane\"\n style=\"pointer-events:${this.isVisible ? 'all' : 'none'}\"\n >\n <button class=\"option-btn\" @click=${this.handleClose} title=\"Close\">\n <temba-icon name=\"x\" size=\"1.5\"></temba-icon>\n </button>\n <button\n class=\"option-btn ${this.following ? 'active' : ''}\"\n @click=${this.handleToggleFollow}\n title=\"${this.following ? 'Following' : 'Follow'}\"\n >\n <temba-icon name=\"follow\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn ${this.contextExplorerOpen ? 'active' : ''}\"\n @click=${this.handleToggleContextExplorer}\n title=\"Context Explorer\"\n >\n <temba-icon name=\"expressions\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn\"\n @click=${this.handleCycleSize}\n title=\"Size: ${this.size}\"\n >\n ${this.size === 'small'\n ? 'S'\n : this.size === 'medium'\n ? 'M'\n : 'L'}\n </button>\n\n <button class=\"option-btn\" @click=${this.handleReset} title=\"Reset\">\n <temba-icon name=\"delete\" size=\"1.5\"></temba-icon>\n </button>\n </div>\n </div>\n </temba-floating-window>\n\n <temba-floating-tab\n id=\"phone-tab\"\n icon=\"simulator\"\n label=\"Phone Simulator\"\n color=\"#10b981\"\n order=\"4\"\n .hidden=${this.isVisible}\n @temba-button-clicked=${this.handleShow}\n ></temba-floating-tab>\n `;\n }\n}\n"]}
@@ -200,6 +200,19 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
200
200
  const languageNames = state.languageNames;
201
201
  return { name: languageNames[languageCode], code: languageCode };
202
202
  },
203
+ clearFlowData: () => {
204
+ set({
205
+ flowDefinition: null,
206
+ flowInfo: null,
207
+ issuesByNode: new Map(),
208
+ issuesByAction: new Map(),
209
+ activity: null,
210
+ simulatorActivity: null,
211
+ simulatorActive: false,
212
+ dirtyDate: null,
213
+ viewingRevision: false
214
+ });
215
+ },
203
216
  // todo: eventually we should be doing the fetching
204
217
  setFlowContents: (flow) => {
205
218
  set((state) => {