@nyaruka/temba-components 0.169.0 → 0.170.1

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 (40) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/locales/es.js +1 -0
  3. package/dist/locales/es.js.map +1 -1
  4. package/dist/locales/fr.js +1 -0
  5. package/dist/locales/fr.js.map +1 -1
  6. package/dist/locales/pt.js +1 -0
  7. package/dist/locales/pt.js.map +1 -1
  8. package/dist/temba-components.js +501 -173
  9. package/dist/temba-components.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/display/Button.ts +14 -2
  12. package/src/display/Chat.ts +43 -24
  13. package/src/display/Dropdown.ts +11 -7
  14. package/src/display/Label.ts +18 -3
  15. package/src/display/Options.ts +27 -14
  16. package/src/display/TembaDate.ts +9 -2
  17. package/src/form/Compose.ts +37 -28
  18. package/src/form/select/Select.ts +15 -2
  19. package/src/interfaces.ts +13 -3
  20. package/src/list/BroadcastList.ts +20 -7
  21. package/src/list/ContactList.ts +113 -9
  22. package/src/list/ContentList.ts +380 -21
  23. package/src/list/ContentMenu.ts +12 -6
  24. package/src/list/FieldList.ts +8 -1
  25. package/src/list/TembaList.ts +99 -29
  26. package/src/list/TicketList.ts +87 -18
  27. package/src/live/CampaignEvents.ts +31 -11
  28. package/src/live/ContactChat.ts +36 -7
  29. package/src/live/ContactTimeline.ts +46 -24
  30. package/src/locales/es.ts +1 -0
  31. package/src/locales/fr.ts +1 -0
  32. package/src/locales/pt.ts +1 -0
  33. package/src/simulator/Simulator.ts +1 -0
  34. package/src/styles/designTokens.ts +57 -17
  35. package/src/styles/pillVariants.ts +42 -10
  36. package/static/css/design-system.css +47 -12
  37. package/static/css/temba-components.css +31 -9
  38. package/xliff/es.xlf +3 -0
  39. package/xliff/fr.xlf +3 -0
  40. package/xliff/pt.xlf +3 -0
@@ -20,16 +20,21 @@ export const designTokens = css`
20
20
  Fallback matches the design-system.css default so component-
21
21
  only test harnesses pick up the same brand colour. */
22
22
  --accent: rgb(var(--primary-rgb, 73, 127, 206));
23
- --accent-50: color-mix(in srgb, var(--accent) 6%, white);
24
- --accent-100: color-mix(in srgb, var(--accent) 16%, white);
25
- --accent-200: color-mix(in srgb, var(--accent) 32%, white);
26
- --accent-300: color-mix(in srgb, var(--accent) 60%, white);
23
+ /* Static ramp values are pre-mixed from the default anchor for
24
+ browsers without color-mix() (pre-Chrome 111, e.g. the last
25
+ Chrome available on Windows 7/8.1). The @supports block below
26
+ re-derives them from --accent so host re-theming still works
27
+ where color-mix() is available. */
28
+ --accent-50: #f4f7fc;
29
+ --accent-100: #e2ebf7;
30
+ --accent-200: #c5d6ef;
31
+ --accent-300: #92b2e2;
27
32
  --accent-400: var(--accent);
28
- --accent-500: color-mix(in srgb, var(--accent) 90%, black);
29
- --accent-600: color-mix(in srgb, var(--accent) 80%, black);
30
- --accent-700: color-mix(in srgb, var(--accent) 65%, black);
31
- --accent-800: color-mix(in srgb, var(--accent) 50%, black);
32
- --accent-900: color-mix(in srgb, var(--accent) 35%, black);
33
+ --accent-500: #4272b9;
34
+ --accent-600: #3a66a5;
35
+ --accent-700: #2f5386;
36
+ --accent-800: #244067;
37
+ --accent-900: #1a2c48;
33
38
 
34
39
  /* neutrals */
35
40
  --bg: #f6f7f9;
@@ -124,14 +129,19 @@ export const designTokens = css`
124
129
  error state (e.g. the dropdown popup) reference --focus-muted
125
130
  / --focus-halo directly to skip that override. */
126
131
  --focus: rgb(var(--focus-rgb, 91, 156, 229));
127
- --focus-50: color-mix(in srgb, var(--focus) 12%, white);
128
- --focus-100: color-mix(in srgb, var(--focus) 24%, white);
129
- --focus-200: color-mix(in srgb, var(--focus) 40%, white);
130
- --focus-300: color-mix(in srgb, var(--focus) 60%, white);
131
- --focus-600: color-mix(in srgb, var(--focus) 60%, black);
132
- --focus-700: color-mix(in srgb, var(--focus) 45%, black);
133
- --focus-muted: color-mix(in srgb, var(--focus) 60%, white);
134
- --focus-halo: 0 0 0 3px color-mix(in srgb, var(--focus) 30%, transparent);
132
+ /* Static values pre-mixed from the default focus hue for browsers
133
+ without color-mix(); re-derived in the @supports block below. */
134
+ --focus-50: #ebf3fc;
135
+ --focus-100: #d8e7f9;
136
+ --focus-200: #bdd7f5;
137
+ --focus-300: #9dc4ef;
138
+ --focus-600: #375e89;
139
+ --focus-700: #294667;
140
+ --focus-muted: #9dc4ef;
141
+ /* The halo is a translucent wash, so unlike the opaque ramp steps
142
+ it can keep tracking the theme without color-mix() — rgba(var())
143
+ substitution works wherever custom properties do. */
144
+ --focus-halo: 0 0 0 3px rgba(var(--focus-rgb, 91, 156, 229), 0.3);
135
145
  --color-focus: var(--focus-muted);
136
146
  --widget-box-shadow-focused: var(--focus-halo);
137
147
 
@@ -160,4 +170,34 @@ export const designTokens = css`
160
170
  --temba-select-selected-font-size: 13.5px;
161
171
  --temba-select-min-height: var(--input-h);
162
172
  }
173
+
174
+ /* Where color-mix() is supported, derive the accent / focus ramps
175
+ from their anchors so host pages can re-theme by overriding just
176
+ --primary-rgb / --focus-rgb. Browsers without color-mix() keep the
177
+ static pre-mixed values above. Note the static values can't act as
178
+ per-declaration fallbacks — a custom property is never invalid at
179
+ parse time, so the last declaration always wins — hence the
180
+ @supports gate. */
181
+ @supports (color: color-mix(in srgb, red, red)) {
182
+ :host {
183
+ --accent-50: color-mix(in srgb, var(--accent) 6%, white);
184
+ --accent-100: color-mix(in srgb, var(--accent) 16%, white);
185
+ --accent-200: color-mix(in srgb, var(--accent) 32%, white);
186
+ --accent-300: color-mix(in srgb, var(--accent) 60%, white);
187
+ --accent-500: color-mix(in srgb, var(--accent) 90%, black);
188
+ --accent-600: color-mix(in srgb, var(--accent) 80%, black);
189
+ --accent-700: color-mix(in srgb, var(--accent) 65%, black);
190
+ --accent-800: color-mix(in srgb, var(--accent) 50%, black);
191
+ --accent-900: color-mix(in srgb, var(--accent) 35%, black);
192
+
193
+ --focus-50: color-mix(in srgb, var(--focus) 12%, white);
194
+ --focus-100: color-mix(in srgb, var(--focus) 24%, white);
195
+ --focus-200: color-mix(in srgb, var(--focus) 40%, white);
196
+ --focus-300: color-mix(in srgb, var(--focus) 60%, white);
197
+ --focus-600: color-mix(in srgb, var(--focus) 60%, black);
198
+ --focus-700: color-mix(in srgb, var(--focus) 45%, black);
199
+ --focus-muted: color-mix(in srgb, var(--focus) 60%, white);
200
+ --focus-halo: 0 0 0 3px color-mix(in srgb, var(--focus) 30%, transparent);
201
+ }
202
+ }
163
203
  `;
@@ -100,10 +100,14 @@ export const pillVariants = css`
100
100
  border-color: var(--pill-border, var(--border));
101
101
  --icon-color: var(--text-2);
102
102
  }
103
+ /* Anchor-derived variants carry static pre-mixed bg/border values
104
+ for browsers without color-mix() (pre-Chrome 111); the @supports
105
+ block at the bottom re-derives them from the anchors so host
106
+ re-theming still works where color-mix() is available. */
103
107
  .pill-flow {
104
- background: color-mix(in srgb, var(--flow) 12%, white);
108
+ background: #e3f4e9;
105
109
  color: var(--flow);
106
- border-color: color-mix(in srgb, var(--flow) 25%, white);
110
+ border-color: #c5e8d2;
107
111
  --icon-color: var(--flow);
108
112
  }
109
113
  /* Recipient color — shared by contacts and groups. Anchored to
@@ -111,27 +115,27 @@ export const pillVariants = css`
111
115
  identity even when the host page re-themes via --primary-rgb. */
112
116
  .pill-contact,
113
117
  .pill-group {
114
- background: color-mix(in srgb, var(--recipient) 12%, white);
118
+ background: #e5eef6;
115
119
  color: var(--recipient);
116
- border-color: color-mix(in srgb, var(--recipient) 25%, white);
120
+ border-color: #cadbec;
117
121
  --icon-color: var(--recipient);
118
122
  }
119
123
  .pill-channel {
120
- background: color-mix(in srgb, var(--channel) 12%, white);
124
+ background: #ede4f5;
121
125
  color: var(--channel);
122
- border-color: color-mix(in srgb, var(--channel) 25%, white);
126
+ border-color: #dac8e9;
123
127
  --icon-color: var(--channel);
124
128
  }
125
129
  .pill-topic {
126
- background: color-mix(in srgb, var(--topic) 12%, white);
130
+ background: #faefe1;
127
131
  color: var(--topic);
128
- border-color: color-mix(in srgb, var(--topic) 25%, white);
132
+ border-color: #f6ddc1;
129
133
  --icon-color: var(--topic);
130
134
  }
131
135
  .pill-campaign {
132
- background: color-mix(in srgb, var(--campaign) 12%, white);
136
+ background: #e1f2f6;
133
137
  color: var(--campaign);
134
- border-color: color-mix(in srgb, var(--campaign) 25%, white);
138
+ border-color: #c1e4ec;
135
139
  --icon-color: var(--campaign);
136
140
  }
137
141
  .pill-field {
@@ -171,4 +175,32 @@ export const pillVariants = css`
171
175
  border-color: var(--pill-border, var(--border));
172
176
  --icon-color: var(--text-2);
173
177
  }
178
+
179
+ /* Anchor-derived bg/border for browsers with color-mix(). These
180
+ can't be simple same-rule fallbacks: a declaration containing
181
+ var() isn't dropped at parse time, it goes invalid at
182
+ computed-value time and takes the earlier declaration with it. */
183
+ @supports (color: color-mix(in srgb, red, red)) {
184
+ .pill-flow {
185
+ background: color-mix(in srgb, var(--flow) 12%, white);
186
+ border-color: color-mix(in srgb, var(--flow) 25%, white);
187
+ }
188
+ .pill-contact,
189
+ .pill-group {
190
+ background: color-mix(in srgb, var(--recipient) 12%, white);
191
+ border-color: color-mix(in srgb, var(--recipient) 25%, white);
192
+ }
193
+ .pill-channel {
194
+ background: color-mix(in srgb, var(--channel) 12%, white);
195
+ border-color: color-mix(in srgb, var(--channel) 25%, white);
196
+ }
197
+ .pill-topic {
198
+ background: color-mix(in srgb, var(--topic) 12%, white);
199
+ border-color: color-mix(in srgb, var(--topic) 25%, white);
200
+ }
201
+ .pill-campaign {
202
+ background: color-mix(in srgb, var(--campaign) 12%, white);
203
+ border-color: color-mix(in srgb, var(--campaign) 25%, white);
204
+ }
205
+ }
174
206
  `;
@@ -20,18 +20,22 @@
20
20
  --primary-rgb: 73, 127, 206;
21
21
 
22
22
  /* accent ramp — derived from --primary-rgb via sRGB mixing.
23
- 400 == primary; the ramp computes outward in both directions. */
23
+ 400 == primary; the ramp computes outward in both directions.
24
+ Static values pre-mixed from the default anchor come first for
25
+ browsers without color-mix() (pre-Chrome 111); the @supports
26
+ block below re-derives them from --accent so re-theming via
27
+ --primary-rgb still works where color-mix() is available. */
24
28
  --accent: rgb(var(--primary-rgb));
25
- --accent-50: color-mix(in srgb, var(--accent) 6%, white);
26
- --accent-100: color-mix(in srgb, var(--accent) 16%, white);
27
- --accent-200: color-mix(in srgb, var(--accent) 32%, white);
28
- --accent-300: color-mix(in srgb, var(--accent) 60%, white);
29
+ --accent-50: #f4f7fc;
30
+ --accent-100: #e2ebf7;
31
+ --accent-200: #c5d6ef;
32
+ --accent-300: #92b2e2;
29
33
  --accent-400: var(--accent);
30
- --accent-500: color-mix(in srgb, var(--accent) 90%, black);
31
- --accent-600: color-mix(in srgb, var(--accent) 80%, black);
32
- --accent-700: color-mix(in srgb, var(--accent) 65%, black);
33
- --accent-800: color-mix(in srgb, var(--accent) 50%, black);
34
- --accent-900: color-mix(in srgb, var(--accent) 35%, black);
34
+ --accent-500: #4272b9;
35
+ --accent-600: #3a66a5;
36
+ --accent-700: #2f5386;
37
+ --accent-800: #244067;
38
+ --accent-900: #1a2c48;
35
39
 
36
40
  /* neutrals */
37
41
  --bg: #F6F7F9;
@@ -94,6 +98,24 @@
94
98
  --section-w-collapsed: 56px;
95
99
  }
96
100
 
101
+ /* Where color-mix() is supported, derive the accent ramp from --accent
102
+ so re-theming via --primary-rgb works without design-system.js.
103
+ Custom properties can't fall back per-declaration (they're never
104
+ invalid at parse time), hence the @supports gate. */
105
+ @supports (color: color-mix(in srgb, red, red)) {
106
+ :root {
107
+ --accent-50: color-mix(in srgb, var(--accent) 6%, white);
108
+ --accent-100: color-mix(in srgb, var(--accent) 16%, white);
109
+ --accent-200: color-mix(in srgb, var(--accent) 32%, white);
110
+ --accent-300: color-mix(in srgb, var(--accent) 60%, white);
111
+ --accent-500: color-mix(in srgb, var(--accent) 90%, black);
112
+ --accent-600: color-mix(in srgb, var(--accent) 80%, black);
113
+ --accent-700: color-mix(in srgb, var(--accent) 65%, black);
114
+ --accent-800: color-mix(in srgb, var(--accent) 50%, black);
115
+ --accent-900: color-mix(in srgb, var(--accent) 35%, black);
116
+ }
117
+ }
118
+
97
119
  /* ─── base ───────────────────────────────────────────────────────────── */
98
120
  .ds * { box-sizing: border-box; }
99
121
  .ds {
@@ -364,7 +386,13 @@
364
386
  color: white;
365
387
  }
366
388
  .ds .btn-danger:hover {
367
- background: color-mix(in srgb, var(--danger) 88%, black);
389
+ /* pre-mixed fallback for browsers without color-mix() */
390
+ background: #b73737;
391
+ }
392
+ @supports (color: color-mix(in srgb, red, red)) {
393
+ .ds .btn-danger:hover {
394
+ background: color-mix(in srgb, var(--danger) 88%, black);
395
+ }
368
396
  }
369
397
  .ds .btn.is-disabled,
370
398
  .ds .btn:disabled { opacity: 0.45; cursor: not-allowed; }
@@ -533,7 +561,14 @@
533
561
  .ds .input:focus-within {
534
562
  outline: 0;
535
563
  border-color: var(--accent-300);
536
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
564
+ /* translucent-ring fallback for browsers without color-mix() */
565
+ box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.25);
566
+ }
567
+ @supports (color: color-mix(in srgb, red, red)) {
568
+ .ds .input:focus,
569
+ .ds .input:focus-within {
570
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
571
+ }
537
572
  }
538
573
 
539
574
  .ds .input-tokens {
@@ -41,15 +41,19 @@
41
41
  --curvature: 6px;
42
42
  --curvature-widget: 6px;
43
43
  --focus: rgb(var(--focus-rgb, 91, 156, 229));
44
- --focus-50: color-mix(in srgb, var(--focus) 12%, white);
45
- --focus-100: color-mix(in srgb, var(--focus) 24%, white);
46
- --focus-200: color-mix(in srgb, var(--focus) 40%, white);
47
- --focus-300: color-mix(in srgb, var(--focus) 60%, white);
48
- --focus-600: color-mix(in srgb, var(--focus) 60%, black);
49
- --focus-700: color-mix(in srgb, var(--focus) 45%, black);
50
- --focus-muted: color-mix(in srgb, var(--focus) 60%, white);
51
- --focus-halo: 0 0 0 3px
52
- color-mix(in srgb, var(--focus) 30%, transparent);
44
+ /* Static values pre-mixed from the default focus hue for browsers
45
+ without color-mix(); re-derived in the @supports block below. */
46
+ --focus-50: #ebf3fc;
47
+ --focus-100: #d8e7f9;
48
+ --focus-200: #bdd7f5;
49
+ --focus-300: #9dc4ef;
50
+ --focus-600: #375e89;
51
+ --focus-700: #294667;
52
+ --focus-muted: #9dc4ef;
53
+ /* The halo is a translucent wash, so unlike the opaque ramp steps
54
+ it can keep tracking the theme without color-mix() — rgba(var())
55
+ substitution works wherever custom properties do. */
56
+ --focus-halo: 0 0 0 3px rgba(var(--focus-rgb, 91, 156, 229), 0.3);
53
57
  --color-focus: #a4cafe;
54
58
  --color-widget-bg: #fff;
55
59
  --color-widget-bg-focused: #fff;
@@ -201,6 +205,24 @@
201
205
 
202
206
  }
203
207
 
208
+ /* Where color-mix() is supported, derive the focus ramp from --focus
209
+ so re-theming via --focus-rgb works. Custom properties can't fall
210
+ back per-declaration (they're never invalid at parse time), hence
211
+ the @supports gate. */
212
+ @supports (color: color-mix(in srgb, red, red)) {
213
+ html {
214
+ --focus-50: color-mix(in srgb, var(--focus) 12%, white);
215
+ --focus-100: color-mix(in srgb, var(--focus) 24%, white);
216
+ --focus-200: color-mix(in srgb, var(--focus) 40%, white);
217
+ --focus-300: color-mix(in srgb, var(--focus) 60%, white);
218
+ --focus-600: color-mix(in srgb, var(--focus) 60%, black);
219
+ --focus-700: color-mix(in srgb, var(--focus) 45%, black);
220
+ --focus-muted: color-mix(in srgb, var(--focus) 60%, white);
221
+ --focus-halo: 0 0 0 3px
222
+ color-mix(in srgb, var(--focus) 30%, transparent);
223
+ }
224
+ }
225
+
204
226
  temba-button {
205
227
  --button-bg: var(--accent-500);
206
228
  --button-text: var(--color-text-light);
package/xliff/es.xlf CHANGED
@@ -42,6 +42,9 @@
42
42
  <trans-unit id="s7722a91d3a512442">
43
43
  <source>Last seen <x id="0" equiv-text="${lastSeen.duration}"/></source>
44
44
  </trans-unit>
45
+ <trans-unit id="s6dbbe2646b239ca5">
46
+ <source>Closed</source>
47
+ </trans-unit>
45
48
  </body>
46
49
  </file>
47
50
  </xliff>
package/xliff/fr.xlf CHANGED
@@ -41,6 +41,9 @@
41
41
  <trans-unit id="s7722a91d3a512442">
42
42
  <source>Last seen <x id="0" equiv-text="${lastSeen.duration}"/></source>
43
43
  </trans-unit>
44
+ <trans-unit id="s6dbbe2646b239ca5">
45
+ <source>Closed</source>
46
+ </trans-unit>
44
47
  </body>
45
48
  </file>
46
49
  </xliff>
package/xliff/pt.xlf CHANGED
@@ -41,6 +41,9 @@
41
41
  <trans-unit id="s7722a91d3a512442">
42
42
  <source>Last seen <x id="0" equiv-text="${lastSeen.duration}"/></source>
43
43
  </trans-unit>
44
+ <trans-unit id="s6dbbe2646b239ca5">
45
+ <source>Closed</source>
46
+ </trans-unit>
44
47
  </body>
45
48
  </file>
46
49
  </xliff>