@nyaruka/temba-components 0.156.17 → 0.157.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 (39) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/temba-components.js +1189 -767
  3. package/dist/temba-components.js.map +1 -1
  4. package/package.json +1 -1
  5. package/src/display/Chat.ts +14 -0
  6. package/src/display/Label.ts +156 -2
  7. package/src/display/Options.ts +71 -16
  8. package/src/display/TembaUser.ts +23 -5
  9. package/src/events/eventRenderers.ts +104 -41
  10. package/src/excellent/caret-utils.ts +0 -1
  11. package/src/flow/RevisionsWindow.ts +53 -9
  12. package/src/flow/nodes/shared.ts +14 -0
  13. package/src/flow/nodes/split_by_llm_categorize.ts +33 -8
  14. package/src/flow/revision-summary.ts +25 -0
  15. package/src/flow/utils.ts +38 -40
  16. package/src/form/ArrayEditor.ts +9 -11
  17. package/src/form/Checkbox.ts +2 -2
  18. package/src/form/Compose.ts +1 -1
  19. package/src/form/FieldElement.ts +8 -8
  20. package/src/form/KeyValueEditor.ts +4 -4
  21. package/src/form/MessageEditor.ts +2 -3
  22. package/src/form/RangePicker.ts +17 -17
  23. package/src/form/TembaSlider.ts +10 -10
  24. package/src/form/TemplateEditor.ts +4 -4
  25. package/src/form/TextInput.ts +19 -1
  26. package/src/form/select/Omnibox.ts +22 -19
  27. package/src/form/select/Select.ts +379 -171
  28. package/src/form/select/WorkspaceSelect.ts +7 -1
  29. package/src/layout/Accordion.ts +2 -2
  30. package/src/layout/Modax.ts +1 -1
  31. package/src/list/SortableList.ts +159 -0
  32. package/src/live/ContactChat.ts +46 -44
  33. package/src/live/ContactDetails.ts +1 -0
  34. package/src/live/ContactFieldEditor.ts +38 -31
  35. package/src/live/FieldManager.ts +4 -4
  36. package/src/styles/designTokens.ts +145 -0
  37. package/src/styles/pillVariants.ts +136 -0
  38. package/static/css/temba-components.css +106 -28
  39. package/web-test-runner.config.mjs +98 -0
@@ -13,9 +13,9 @@ export class TembaSlider extends FieldElement {
13
13
 
14
14
  .track {
15
15
  height: 2px;
16
- border-top: 0.5em solid #fff;
17
- border-bottom: 0.5em solid #fff;
18
- background: #ddd;
16
+ border-top: 0.5em solid var(--surface);
17
+ border-bottom: 0.5em solid var(--surface);
18
+ background: var(--border-strong);
19
19
  flex-grow: 1;
20
20
  }
21
21
 
@@ -24,11 +24,11 @@ export class TembaSlider extends FieldElement {
24
24
  margin-left: -0.5em;
25
25
  width: 0.75em;
26
26
  height: 0.75em;
27
- border: 2px solid #999;
27
+ border: 2px solid var(--border-strong);
28
28
  border-radius: 999px;
29
29
  position: relative;
30
- background: #fff;
31
- box-shadow: 0 0 0 4px rgb(255, 255, 255);
30
+ background: var(--surface);
31
+ box-shadow: 0 0 0 4px var(--surface);
32
32
  transition: transform 200ms ease-in-out;
33
33
  }
34
34
 
@@ -37,13 +37,13 @@ export class TembaSlider extends FieldElement {
37
37
  }
38
38
 
39
39
  :hover .circle {
40
- border-color: #777;
40
+ border-color: var(--text-2);
41
41
  cursor: pointer;
42
42
  }
43
43
 
44
44
  .grabbed .circle {
45
- border-color: var(--color-primary-dark);
46
- background: #fff;
45
+ border-color: var(--accent);
46
+ background: var(--surface);
47
47
  }
48
48
 
49
49
  .grabbed .circle {
@@ -58,7 +58,7 @@ export class TembaSlider extends FieldElement {
58
58
  .pre,
59
59
  .post {
60
60
  font-size: 0.9em;
61
- color: #999;
61
+ color: var(--text-3);
62
62
  padding: 0em 1em;
63
63
  }
64
64
  `;
@@ -99,9 +99,9 @@ export class TemplateEditor extends FieldElement {
99
99
  }
100
100
 
101
101
  .button {
102
- background: #fff;
102
+ background: var(--surface);
103
103
  padding: 0.3em 1em;
104
- border: 1px solid #e6e6e6;
104
+ border: 1px solid var(--color-widget-border);
105
105
  border-radius: var(--curvature);
106
106
  min-height: 23px;
107
107
  display: flex;
@@ -118,7 +118,7 @@ export class TemplateEditor extends FieldElement {
118
118
 
119
119
  .button .display {
120
120
  margin-right: 0.5em;
121
- background: #f9f9f9;
121
+ background: var(--sunken);
122
122
  padding: 0.25em 1em;
123
123
  border-radius: var(--curvature);
124
124
  }
@@ -130,7 +130,7 @@ export class TemplateEditor extends FieldElement {
130
130
  }
131
131
 
132
132
  .template {
133
- background: #fff;
133
+ background: var(--surface);
134
134
  border-radius: var(--curvature);
135
135
  border: 1px solid var(--color-widget-border);
136
136
  padding: 1em;
@@ -26,13 +26,32 @@ export class TextInput extends FieldElement {
26
26
  display: flex;
27
27
  flex-direction: row;
28
28
  align-items: stretch;
29
+ min-height: var(--temba-textinput-min-height, var(--input-h));
29
30
  box-shadow: var(--widget-box-shadow);
30
31
  caret-color: var(--input-caret);
32
+ /* Establish a stable containing block for slotted absolutely-
33
+ positioned children (e.g. ContactFieldEditor's embedded
34
+ prefix label). Setting position: relative only on
35
+ :focus-within would re-anchor the prefix when focused,
36
+ visually shifting the label. */
37
+ position: relative;
38
+ }
39
+
40
+ .input-container.textarea,
41
+ .input-container:has(textarea) {
42
+ min-height: 0;
31
43
  }
32
44
 
33
45
  .xsmall {
34
46
  --temba-textinput-padding: 6px 8px;
35
47
  --temba-textinput-font-size: 13px;
48
+ /* Opt out of the 34px --input-h floor so an xsmall textinput
49
+ lines up with RichEditor xsmall (the "evaluated" argument
50
+ input in rule editor rows) and with Select xsmall, neither
51
+ of which carry the floor. Without this, a [operator select
52
+ | rich-edit argument | textinput category] row renders the
53
+ category ~4px taller than its neighbors. */
54
+ --temba-textinput-min-height: 0;
36
55
  }
37
56
 
38
57
  .small {
@@ -66,7 +85,6 @@ export class TextInput extends FieldElement {
66
85
  border-color: var(--color-focus);
67
86
  background: var(--color-widget-bg-focused);
68
87
  box-shadow: var(--widget-box-shadow-focused);
69
- position: relative;
70
88
  }
71
89
 
72
90
  .input-container:hover {
@@ -105,28 +105,31 @@ export class Omnibox extends Select<OmniOption> {
105
105
  return null;
106
106
  }
107
107
 
108
- /** Selection in the multi-select select box */
108
+ /**
109
+ * Chip rendering — icon + name, plus the group count when the option
110
+ * is a Group. Counts are intentionally suppressed in the base Select
111
+ * chip (noise for action editors like Add to Group), but Omnibox is
112
+ * the start-flow recipients picker where group size is a key part
113
+ * of the chip's identity. Contacts skip the post-name URN that the
114
+ * dropdown shows — chips already have a tight footprint.
115
+ */
109
116
  public renderSelectedItemDefault(option: OmniOption): TemplateResult {
110
- return html`
111
- <div
112
- style="flex:1 1 auto; text-overflow:ellipsis; overflow:hidden; white-space:nowrap; display: flex; align-items: stretch; color: var(--color-text-dark); font-size: 12px;"
117
+ const base = super.renderOptionDefault(option);
118
+ if (
119
+ option.type === OmniType.Group &&
120
+ option.count !== undefined &&
121
+ option.count !== null
122
+ ) {
123
+ return html`<div
124
+ style="display:flex; align-items:center; gap:6px;"
113
125
  >
114
- <div style="align-self: center; padding: 0px 7px; color: #bbb">
115
- ${this.getIcon(option)}
116
- </div>
117
- <div
118
- class="name"
119
- style="align-self: center; padding: 0px; font-size: 12px;"
126
+ ${base}<span
127
+ style="opacity:0.7; font-size:11px; font-variant-numeric: tabular-nums; font-weight: var(--w-medium);"
128
+ >${option.count.toLocaleString()}</span
120
129
  >
121
- ${option.name}
122
- </div>
123
- <div
124
- style="background: rgba(100, 100, 100, 0.05); border-left: 1px solid rgba(100, 100, 100, 0.1); margin-left: 12px; display: flex; align-items: center"
125
- >
126
- ${this.getPostName(option)}
127
- </div>
128
- </div>
129
- `;
130
+ </div>`;
131
+ }
132
+ return base;
130
133
  }
131
134
 
132
135
  private getIcon(option: OmniOption): TemplateResult {