@nyaruka/temba-components 0.131.2 → 0.132.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 (232) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/demo/components/floating-tabs/example.html +400 -0
  3. package/demo/components/flow/index.html +1 -1
  4. package/demo/data/flows/sample-flow.json +41 -2
  5. package/demo/data/flows/voicemail.json +613 -0
  6. package/demo/index.html +6 -0
  7. package/dist/locales/es.js +5 -5
  8. package/dist/locales/es.js.map +1 -1
  9. package/dist/locales/fr.js +5 -5
  10. package/dist/locales/fr.js.map +1 -1
  11. package/dist/locales/locale-codes.js +11 -2
  12. package/dist/locales/locale-codes.js.map +1 -1
  13. package/dist/locales/pt.js +5 -5
  14. package/dist/locales/pt.js.map +1 -1
  15. package/dist/temba-components.js +1122 -548
  16. package/dist/temba-components.js.map +1 -1
  17. package/out-tsc/src/display/FloatingTab.js +167 -0
  18. package/out-tsc/src/display/FloatingTab.js.map +1 -0
  19. package/out-tsc/src/display/ProgressBar.js +22 -2
  20. package/out-tsc/src/display/ProgressBar.js.map +1 -1
  21. package/out-tsc/src/events.js.map +1 -1
  22. package/out-tsc/src/flow/CanvasNode.js +165 -31
  23. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  24. package/out-tsc/src/flow/Editor.js +870 -3
  25. package/out-tsc/src/flow/Editor.js.map +1 -1
  26. package/out-tsc/src/flow/NodeEditor.js +239 -19
  27. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  28. package/out-tsc/src/flow/NodeTypeSelector.js +51 -4
  29. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
  30. package/out-tsc/src/flow/StickyNote.js +12 -3
  31. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  32. package/out-tsc/src/flow/actions/add_contact_groups.js +2 -1
  33. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  34. package/out-tsc/src/flow/actions/add_contact_urn.js +2 -1
  35. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  36. package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
  37. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  38. package/out-tsc/src/flow/actions/play_audio.js +2 -1
  39. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  40. package/out-tsc/src/flow/actions/remove_contact_groups.js +2 -1
  41. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  42. package/out-tsc/src/flow/actions/request_optin.js +1 -0
  43. package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
  44. package/out-tsc/src/flow/actions/say_msg.js +2 -1
  45. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  46. package/out-tsc/src/flow/actions/send_broadcast.js +2 -1
  47. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  48. package/out-tsc/src/flow/actions/send_email.js +2 -1
  49. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  50. package/out-tsc/src/flow/actions/send_msg.js +93 -3
  51. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  52. package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
  53. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  54. package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
  55. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  56. package/out-tsc/src/flow/actions/set_contact_language.js +2 -1
  57. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  58. package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
  59. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  60. package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
  61. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  62. package/out-tsc/src/flow/actions/set_run_result.js +2 -1
  63. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  64. package/out-tsc/src/flow/actions/start_session.js +2 -1
  65. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  66. package/out-tsc/src/flow/config.js +19 -14
  67. package/out-tsc/src/flow/config.js.map +1 -1
  68. package/out-tsc/src/flow/nodes/shared.js +54 -0
  69. package/out-tsc/src/flow/nodes/shared.js.map +1 -1
  70. package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -3
  71. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
  72. package/out-tsc/src/flow/nodes/split_by_contact_field.js +8 -3
  73. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  74. package/out-tsc/src/flow/nodes/split_by_expression.js +8 -3
  75. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  76. package/out-tsc/src/flow/nodes/split_by_groups.js +8 -3
  77. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  78. package/out-tsc/src/flow/nodes/split_by_intent.js +3 -2
  79. package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -1
  80. package/out-tsc/src/flow/nodes/split_by_llm.js +9 -2
  81. package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
  82. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +9 -2
  83. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  84. package/out-tsc/src/flow/nodes/split_by_random.js +8 -2
  85. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  86. package/out-tsc/src/flow/nodes/split_by_resthook.js +8 -3
  87. package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
  88. package/out-tsc/src/flow/nodes/split_by_run_result.js +14 -3
  89. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  90. package/out-tsc/src/flow/nodes/split_by_scheme.js +8 -3
  91. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
  92. package/out-tsc/src/flow/nodes/split_by_subflow.js +8 -2
  93. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  94. package/out-tsc/src/flow/nodes/split_by_ticket.js +8 -2
  95. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  96. package/out-tsc/src/flow/nodes/split_by_webhook.js +8 -2
  97. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  98. package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
  99. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  100. package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
  101. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  102. package/out-tsc/src/flow/nodes/wait_for_response.js +8 -3
  103. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  104. package/out-tsc/src/flow/types.js +15 -0
  105. package/out-tsc/src/flow/types.js.map +1 -1
  106. package/out-tsc/src/layout/FloatingWindow.js +346 -0
  107. package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
  108. package/out-tsc/src/live/ContactChat.js +41 -49
  109. package/out-tsc/src/live/ContactChat.js.map +1 -1
  110. package/out-tsc/src/locales/es.js +5 -5
  111. package/out-tsc/src/locales/es.js.map +1 -1
  112. package/out-tsc/src/locales/fr.js +5 -5
  113. package/out-tsc/src/locales/fr.js.map +1 -1
  114. package/out-tsc/src/locales/locale-codes.js +11 -2
  115. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  116. package/out-tsc/src/locales/pt.js +5 -5
  117. package/out-tsc/src/locales/pt.js.map +1 -1
  118. package/out-tsc/src/store/AppState.js +75 -1
  119. package/out-tsc/src/store/AppState.js.map +1 -1
  120. package/out-tsc/temba-modules.js +4 -0
  121. package/out-tsc/temba-modules.js.map +1 -1
  122. package/out-tsc/test/nodes/split_by_run_result.test.js +83 -0
  123. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
  124. package/out-tsc/test/temba-backwards-compatibility.test.js +30 -0
  125. package/out-tsc/test/temba-backwards-compatibility.test.js.map +1 -0
  126. package/out-tsc/test/temba-contact-chat.test.js +27 -12
  127. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  128. package/out-tsc/test/temba-floating-tab.test.js +91 -0
  129. package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
  130. package/out-tsc/test/temba-floating-window.test.js +301 -0
  131. package/out-tsc/test/temba-floating-window.test.js.map +1 -0
  132. package/out-tsc/test/temba-flow-editor-node.test.js +117 -0
  133. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  134. package/out-tsc/test/temba-localization.test.js +490 -0
  135. package/out-tsc/test/temba-localization.test.js.map +1 -0
  136. package/out-tsc/test/temba-node-type-selector.test.js +217 -0
  137. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  138. package/out-tsc/test/utils.test.js +18 -0
  139. package/out-tsc/test/utils.test.js.map +1 -1
  140. package/package.json +1 -1
  141. package/screenshots/truth/floating-tab/default.png +0 -0
  142. package/screenshots/truth/floating-tab/gray.png +0 -0
  143. package/screenshots/truth/floating-tab/green.png +0 -0
  144. package/screenshots/truth/floating-tab/hidden.png +0 -0
  145. package/screenshots/truth/floating-tab/hover.png +0 -0
  146. package/screenshots/truth/floating-tab/purple.png +0 -0
  147. package/screenshots/truth/floating-window/chromeless.png +0 -0
  148. package/screenshots/truth/floating-window/custom-size.png +0 -0
  149. package/screenshots/truth/floating-window/default.png +0 -0
  150. package/screenshots/truth/floating-window/with-header.png +0 -0
  151. package/screenshots/truth/node-type-selector/action-mode.png +0 -0
  152. package/screenshots/truth/node-type-selector/split-mode.png +0 -0
  153. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  154. package/src/display/FloatingTab.ts +174 -0
  155. package/src/display/ProgressBar.ts +22 -2
  156. package/src/events.ts +2 -4
  157. package/src/flow/CanvasNode.ts +190 -32
  158. package/src/flow/Editor.ts +1054 -4
  159. package/src/flow/NodeEditor.ts +317 -19
  160. package/src/flow/NodeTypeSelector.ts +54 -4
  161. package/src/flow/StickyNote.ts +12 -3
  162. package/src/flow/actions/add_contact_groups.ts +2 -1
  163. package/src/flow/actions/add_contact_urn.ts +3 -1
  164. package/src/flow/actions/add_input_labels.ts +2 -1
  165. package/src/flow/actions/play_audio.ts +2 -1
  166. package/src/flow/actions/remove_contact_groups.ts +3 -1
  167. package/src/flow/actions/request_optin.ts +1 -0
  168. package/src/flow/actions/say_msg.ts +2 -1
  169. package/src/flow/actions/send_broadcast.ts +2 -1
  170. package/src/flow/actions/send_email.ts +3 -1
  171. package/src/flow/actions/send_msg.ts +134 -3
  172. package/src/flow/actions/set_contact_channel.ts +2 -1
  173. package/src/flow/actions/set_contact_field.ts +2 -1
  174. package/src/flow/actions/set_contact_language.ts +3 -1
  175. package/src/flow/actions/set_contact_name.ts +2 -1
  176. package/src/flow/actions/set_contact_status.ts +2 -1
  177. package/src/flow/actions/set_run_result.ts +2 -1
  178. package/src/flow/actions/start_session.ts +3 -1
  179. package/src/flow/config.ts +24 -16
  180. package/src/flow/nodes/shared.ts +70 -1
  181. package/src/flow/nodes/split_by_airtime.ts +20 -3
  182. package/src/flow/nodes/split_by_contact_field.ts +13 -3
  183. package/src/flow/nodes/split_by_expression.ts +13 -3
  184. package/src/flow/nodes/split_by_groups.ts +13 -3
  185. package/src/flow/nodes/split_by_intent.ts +3 -2
  186. package/src/flow/nodes/split_by_llm.ts +19 -2
  187. package/src/flow/nodes/split_by_llm_categorize.ts +13 -2
  188. package/src/flow/nodes/split_by_random.ts +12 -2
  189. package/src/flow/nodes/split_by_resthook.ts +13 -3
  190. package/src/flow/nodes/split_by_run_result.ts +20 -3
  191. package/src/flow/nodes/split_by_scheme.ts +13 -3
  192. package/src/flow/nodes/split_by_subflow.ts +12 -2
  193. package/src/flow/nodes/split_by_ticket.ts +12 -2
  194. package/src/flow/nodes/split_by_webhook.ts +12 -2
  195. package/src/flow/nodes/wait_for_digits.ts +3 -2
  196. package/src/flow/nodes/wait_for_menu.ts +3 -2
  197. package/src/flow/nodes/wait_for_response.ts +13 -3
  198. package/src/flow/types.ts +49 -0
  199. package/src/layout/FloatingWindow.ts +386 -0
  200. package/src/live/ContactChat.ts +42 -49
  201. package/src/locales/es.ts +18 -13
  202. package/src/locales/fr.ts +18 -13
  203. package/src/locales/locale-codes.ts +11 -2
  204. package/src/locales/pt.ts +18 -13
  205. package/src/store/AppState.ts +116 -1
  206. package/static/api/llms.json +18 -0
  207. package/temba-modules.ts +4 -0
  208. package/test/nodes/split_by_run_result.test.ts +99 -0
  209. package/test/temba-backwards-compatibility.test.ts +37 -0
  210. package/test/temba-contact-chat.test.ts +27 -12
  211. package/test/temba-floating-tab.test.ts +110 -0
  212. package/test/temba-floating-window.test.ts +477 -0
  213. package/test/temba-flow-editor-node.test.ts +144 -0
  214. package/test/temba-localization.test.ts +635 -0
  215. package/test/temba-node-type-selector.test.ts +289 -0
  216. package/test/utils.test.ts +20 -0
  217. package/test-assets/contacts/history.json +5 -6
  218. package/test-assets/select/llms.json +2 -2
  219. package/web-dev-server.config.mjs +47 -1
  220. package/web-test-runner.config.mjs +0 -1
  221. package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
  222. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
  223. package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
  224. package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
  225. package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
  226. package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
  227. package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
  228. package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
  229. package/src/flow/nodes/wait_for_audio.ts +0 -7
  230. package/src/flow/nodes/wait_for_image.ts +0 -7
  231. package/src/flow/nodes/wait_for_location.ts +0 -7
  232. package/src/flow/nodes/wait_for_video.ts +0 -7
package/CHANGELOG.md CHANGED
@@ -4,8 +4,25 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ #### [v0.132.0](https://github.com/nyaruka/temba-components/compare/v0.131.2...v0.132.0)
8
+
9
+ - Add send response directly to chat [`#758`](https://github.com/nyaruka/temba-components/pull/758)
10
+ - Workspace languages [`#757`](https://github.com/nyaruka/temba-components/pull/757)
11
+ - Config aliases [`#756`](https://github.com/nyaruka/temba-components/pull/756)
12
+ - Chat history tweaks [`#754`](https://github.com/nyaruka/temba-components/pull/754)
13
+ - Localization tab [`#753`](https://github.com/nyaruka/temba-components/pull/753)
14
+ - Add localization editing framework for flow actions and router categories [`#747`](https://github.com/nyaruka/temba-components/pull/747)
15
+ - Bump min-document from 2.19.0 to 2.19.2 [`#752`](https://github.com/nyaruka/temba-components/pull/752)
16
+ - [WIP] Add a generic tab and floating window component [`#751`](https://github.com/nyaruka/temba-components/pull/751)
17
+ - Add flow type and feature filtering to NodeTypeSelector [`#749`](https://github.com/nyaruka/temba-components/pull/749)
18
+ - Add auto translate and category toggles [`cb1257c`](https://github.com/nyaruka/temba-components/commit/cb1257c2044ec8e5b7072274bdc0183811059229)
19
+ - Add voice example file and improve filtering [`a00a21d`](https://github.com/nyaruka/temba-components/commit/a00a21dfeeb553da8f88ba2643792eb6c058a890)
20
+ - Add FloatingTab and FloatingWindow components with tests [`38b3b13`](https://github.com/nyaruka/temba-components/commit/38b3b13bad1a961cd672ae2c246bd06e9adc7b51)
21
+
7
22
  #### [v0.131.2](https://github.com/nyaruka/temba-components/compare/v0.131.1...v0.131.2)
8
23
 
24
+ > 14 November 2025
25
+
9
26
  - Support `_status` fields on msg events that are objects [`#745`](https://github.com/nyaruka/temba-components/pull/745)
10
27
  - Fix validate methods to use FormData instead of action types [`#742`](https://github.com/nyaruka/temba-components/pull/742)
11
28
  - Add mock channels endpoint for demo environment [`#744`](https://github.com/nyaruka/temba-components/pull/744)
@@ -0,0 +1,400 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-GB">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Floating Tab & Window Examples</title>
6
+ <link
7
+ href="/static/css/temba-components.css"
8
+ rel="stylesheet"
9
+ type="text/css"
10
+ />
11
+ <link
12
+ href="https://fonts.googleapis.com/css?family=Roboto+Mono:300|Roboto:300,400,500"
13
+ rel="stylesheet"
14
+ />
15
+ <link href="/demo/static/css/styles.css" rel="stylesheet" type="text/css" />
16
+ <style>
17
+ body {
18
+ min-height: 100vh;
19
+ position: relative;
20
+ }
21
+ .content {
22
+ padding: 20px;
23
+ max-width: 800px;
24
+
25
+ }
26
+ .phone-simulator {
27
+ padding: 30px;
28
+ position: relative;
29
+ }
30
+ .phone-frame {
31
+ border-radius: 40px;
32
+ border: 8px solid #1f2937;
33
+ box-shadow: 0 0px 30px rgba(0, 0, 0, 0.4);
34
+ background: #000;
35
+ position: relative;
36
+ overflow:hidden;
37
+
38
+ }
39
+ .phone-top {
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ right: 0;
44
+ z-index: 10;
45
+ cursor: grab;
46
+ }
47
+ .phone-notch {
48
+ background: transparent;
49
+ height: 50px;
50
+ position: relative;
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: space-between;
54
+ padding: 0 20px;
55
+ }
56
+ .phone-notch::before {
57
+ content: '';
58
+ position: absolute;
59
+ top: 0;
60
+ left: 0;
61
+ right: 0;
62
+ height: 100%;
63
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.3) 50%, transparent 100%);
64
+ z-index: -1;
65
+ }
66
+ .dynamic-island {
67
+
68
+ top: 10px;
69
+ left: 50%;
70
+
71
+ width: 120px;
72
+ height: 30px;
73
+ background: #000;
74
+ border-radius: 20px;
75
+ z-index: 1;
76
+ }
77
+ .phone-notch .time {
78
+ color: #000;
79
+ font-size: 14px;
80
+ font-weight: 600;
81
+
82
+ }
83
+ .phone-notch .status-icons {
84
+ display: flex;
85
+ gap: 4px;
86
+ align-items: center;
87
+ }
88
+ .phone-notch .status-icons span {
89
+ color: #000;
90
+ font-size: 14px;
91
+ }
92
+ .phone-header {
93
+ background: transparent;
94
+ padding: 10px 15px;
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: flex-end;
98
+ cursor: move;
99
+ user-select: none;
100
+ border-bottom: none;
101
+ pointer-events: all;
102
+ }
103
+ .close-btn {
104
+ background: rgba(0, 0, 0, 0.5);
105
+ border-radius: 50%;
106
+ color: #fff;
107
+ border: none;
108
+ cursor: pointer;
109
+ padding: 0;
110
+ display: flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ width:29px;
114
+ }
115
+
116
+ .close-btn:hover {
117
+ color: rgba(0, 0, 0, 0.7);
118
+ }
119
+ .phone-screen {
120
+ background: white;
121
+ padding: 15px;
122
+ padding-top: 75px;
123
+ padding-bottom: 60px;
124
+ height:470px;
125
+ overflow-y: auto;
126
+ flex-direction: column-reverse;
127
+ display: flex;
128
+ }
129
+
130
+
131
+ .message {
132
+ padding: 10px 14px;
133
+ margin-bottom: 8px;
134
+ border-radius: 18px;
135
+ max-width: 70%;
136
+ font-size: 15px;
137
+ line-height: 1.4;
138
+ }
139
+ .message.incoming {
140
+ background: #e5e5ea;
141
+ color: #000;
142
+ margin-right: auto;
143
+ border-bottom-left-radius: 4px;
144
+ }
145
+ .message.outgoing {
146
+ background: #007aff;
147
+ color: white;
148
+ margin-left: auto;
149
+ text-align: left;
150
+ border-bottom-right-radius: 4px;
151
+ }
152
+ .message-input {
153
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.05) 70%, transparent 100%);
154
+ padding: 8px 16px;
155
+ border-top: none;
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 8px;
159
+ position: absolute;
160
+ bottom: 0px;
161
+ left: 0px;
162
+ right: 0px;
163
+ z-index: 10;
164
+ }
165
+ .message-input input {
166
+ flex: 1;
167
+ border: 1px solid #c6c6c8;
168
+ border-radius: 20px;
169
+ padding: 8px 15px;
170
+ font-size: 15px;
171
+ margin-bottom:5px;
172
+ background: white;
173
+ border: none;
174
+ outline:none;
175
+ }
176
+ .message-input input::placeholder {
177
+ color: #8e8e93;
178
+ }
179
+ </style>
180
+ </head>
181
+ <body>
182
+ <div class="content">
183
+ <h1>Floating Tab & Window Examples</h1>
184
+ <p><a href="/demo/index.html">← Back to main demo</a></p>
185
+
186
+ <div class="example">
187
+ <h3>Phone Simulator</h3>
188
+ <p>
189
+ Click the green phone icon on the right to open a phone simulator
190
+ window. The window can be dragged around the screen.
191
+ </p>
192
+ <p>
193
+ Hover over the tab to see the label animate in. Click again to close
194
+ the window.
195
+ </p>
196
+ </div>
197
+
198
+ <div class="example">
199
+ <h3>Multiple Tabs</h3>
200
+ <p>
201
+ Multiple floating tabs can be displayed at once, each with different
202
+ colors and purposes.
203
+ </p>
204
+ <ul>
205
+ <li><strong>Phone (Green):</strong> Phone simulator window</li>
206
+ <li><strong>Clock (Purple):</strong> Revision history window</li>
207
+ <li><strong>Globe (Gray):</strong> Translation/localization window</li>
208
+ </ul>
209
+ </div>
210
+
211
+ <div class="example">
212
+ <h3>Usage</h3>
213
+ <pre><code>&lt;!-- Floating Tab --&gt;
214
+ &lt;temba-floating-tab
215
+ id="phone-tab"
216
+ icon="phone"
217
+ label="Phone Simulator"
218
+ color="#10b981"
219
+ top="100"
220
+ &gt;&lt;/temba-floating-tab&gt;
221
+
222
+ &lt;!-- Floating Window --&gt;
223
+ &lt;temba-floating-window
224
+ id="phone-window"
225
+ title="Phone Simulator"
226
+ width="250"
227
+ height="700"
228
+ top="100"
229
+ &gt;
230
+ &lt;!-- Your content here --&gt;
231
+ &lt;/temba-floating-window&gt;</code></pre>
232
+ </div>
233
+ </div>
234
+
235
+
236
+ <!-- Phone Simulator Tab & Window -->
237
+ <temba-floating-window
238
+ id="translation-window"
239
+ header="Flow Translation"
240
+ width="350"
241
+ height="600"
242
+ top="100"
243
+ color="#6b7280"
244
+ >
245
+ <div style="padding: 20px">
246
+ <h4 style="margin-top: 0">Translate Flow</h4>
247
+ <div style="display: flex; flex-direction: column; gap: 15px">
248
+ <div>
249
+ <label style="display: block; margin-bottom: 5px; font-weight: 500"
250
+ >Language</label
251
+ >
252
+ <select style="width: 100%; padding: 8px; border-radius: 4px; border: 1px solid #d1d5db">
253
+ <option>English</option>
254
+ <option>Spanish</option>
255
+ <option>French</option>
256
+ <option>Portuguese</option>
257
+ </select>
258
+ </div>
259
+ </div>
260
+ </div>
261
+ </temba-floating-window>
262
+
263
+ <temba-floating-window
264
+ id="phone-window"
265
+ width="375"
266
+ height="720"
267
+ top="60"
268
+ chromeless
269
+ >
270
+ <div class="phone-simulator">
271
+
272
+ <div class="phone-frame">
273
+ <div class="phone-top drag-handle">
274
+
275
+ <div class="phone-notch">
276
+ <div style="width:29px;"></div>
277
+ <div class="dynamic-island"></div>
278
+ <button class="close-btn" onclick="document.getElementById('phone-window').close()">
279
+ <temba-icon name="x" clickable size="2"></temba-icon>
280
+ </button>
281
+ </div>
282
+
283
+ </div>
284
+ <div class="phone-screen">
285
+ <div class="message outgoing">Always do!</div>
286
+ <div class="message incoming">Drive safe!</div>
287
+ <div class="message outgoing">Can't wait!</div>
288
+ <div class="message incoming">See you soon!</div>
289
+ <div class="message outgoing">On it!</div>
290
+ <div class="message incoming">Don't forget the salad dressing!</div>
291
+ <div class="message outgoing">Sure thing, see you soon!</div>
292
+ <div class="message incoming">Great! Also need some tomatoes.</div>
293
+ <div class="message outgoing">I got broccoli and asparagus</div>
294
+ <div class="message incoming">Can you buy some veggies on your way home?</div>
295
+ </div>
296
+ <div class="message-input">
297
+ <input type="text" placeholder="Enter Message"/>
298
+ </div>
299
+ </div>
300
+ </div>
301
+ </temba-floating-window>
302
+
303
+ <temba-floating-window
304
+ id="history-window"
305
+ header="Revision History"
306
+ width="300"
307
+ height="500"
308
+ top="100"
309
+ color="#8b5cf6"
310
+ >
311
+ <div style="padding: 20px">
312
+ <h4 style="margin-top: 0">Recent Changes</h4>
313
+ <ul style="list-style: none; padding: 0">
314
+ <li style="margin-bottom: 15px; padding: 10px; background: #f3f4f6; border-radius: 8px">
315
+ <strong>2 hours ago</strong><br />
316
+ Updated flow configuration
317
+ </li>
318
+ <li style="margin-bottom: 15px; padding: 10px; background: #f3f4f6; border-radius: 8px">
319
+ <strong>Yesterday</strong><br />
320
+ Added new message template
321
+ </li>
322
+ <li style="margin-bottom: 15px; padding: 10px; background: #f3f4f6; border-radius: 8px">
323
+ <strong>3 days ago</strong><br />
324
+ Modified contact fields
325
+ </li>
326
+ </ul>
327
+ </div>
328
+ </temba-floating-window>
329
+
330
+ <temba-floating-tab
331
+ id="phone-tab"
332
+ icon="simulator"
333
+ label="Phone Simulator"
334
+ color="#10b981"
335
+ ></temba-floating-tab>
336
+
337
+
338
+
339
+ <!-- History Tab & Window -->
340
+ <temba-floating-tab
341
+ id="history-tab"
342
+ icon="revisions"
343
+ label="Revision History"
344
+ color="#8b5cf6"
345
+ ></temba-floating-tab>
346
+
347
+
348
+
349
+ <!-- Translation Tab & Window -->
350
+ <temba-floating-tab
351
+ id="translation-tab"
352
+ icon="language"
353
+ label="Flow Translation"
354
+ color="#6b7280"
355
+ ></temba-floating-tab>
356
+
357
+
358
+
359
+ <script type="module">
360
+ import '/out-tsc/temba-modules.js';
361
+
362
+ // connect tabs to windows
363
+ const phoneTab = document.getElementById('phone-tab');
364
+ const phoneWindow = document.getElementById('phone-window');
365
+
366
+ const historyTab = document.getElementById('history-tab');
367
+ const historyWindow = document.getElementById('history-window');
368
+
369
+ const translationTab = document.getElementById('translation-tab');
370
+ const translationWindow = document.getElementById('translation-window');
371
+
372
+ // phone tab/window interaction
373
+ phoneTab.addEventListener('temba-button-clicked', () => {
374
+ phoneWindow.show();
375
+ });
376
+
377
+ phoneWindow.addEventListener('temba-dialog-hidden', () => {
378
+ phoneWindow.hide();
379
+ });
380
+
381
+ // history tab/window interaction
382
+ historyTab.addEventListener('temba-button-clicked', () => {
383
+ historyWindow.show();
384
+ });
385
+
386
+ historyWindow.addEventListener('temba-dialog-hidden', () => {
387
+ historyWindow.hide();
388
+ });
389
+
390
+ // translation tab/window interaction
391
+ translationTab.addEventListener('temba-button-clicked', () => {
392
+ translationWindow.show();
393
+ });
394
+
395
+ translationWindow.addEventListener('temba-dialog-hidden', () => {
396
+ translationWindow.hide();
397
+ });
398
+ </script>
399
+ </body>
400
+ </html>
@@ -144,7 +144,7 @@
144
144
 
145
145
  // Fallback function for known flows
146
146
  async function loadKnownFlows(container) {
147
- const knownFlows = ['sample-flow', 'food-order'];
147
+ const knownFlows = ['sample-flow', 'food-order', 'voicemail'];
148
148
  const flows = [];
149
149
 
150
150
  for (const flowId of knownFlows) {
@@ -1122,6 +1122,45 @@
1122
1122
  },
1123
1123
  "revision": 69,
1124
1124
  "expire_after_minutes": 4320,
1125
- "localization": {}
1125
+ "localization": {
1126
+ "esp": {
1127
+ "3d56e4cf-1e88-499a-b0b4-ff48385fc9a5": {
1128
+ "text": [
1129
+ "¿Cuál es tu color favorito?! @contact.uuid. Funciona."
1130
+ ],
1131
+ "quick_replies": [
1132
+ "Rojo",
1133
+ "Verde",
1134
+ "Azul",
1135
+ "Amarillo",
1136
+ "Morado"
1137
+ ]
1138
+ },
1139
+ "9963160a-a007-4c7b-8c9e-7325e1b69ed8": {
1140
+ "text": [
1141
+ "Excelentes opciones."
1142
+ ],
1143
+ "quick_replies": [
1144
+ "Rojo",
1145
+ "Verde",
1146
+ "Azul"
1147
+ ]
1148
+ }
1149
+ },
1150
+ "fra": {
1151
+ "3d56e4cf-1e88-499a-b0b4-ff48385fc9a5": {
1152
+ "text": [
1153
+ "Quelle est votre couleur préférée?! @contact.uuid. Ça marche."
1154
+ ],
1155
+ "quick_replies": [
1156
+ "Rouge",
1157
+ "Vert",
1158
+ "Bleu",
1159
+ "Jaune",
1160
+ "Violet"
1161
+ ]
1162
+ }
1163
+ }
1164
+ }
1126
1165
  }
1127
- }
1166
+ }