@nyaruka/temba-components 0.157.1 → 0.158.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.
- package/CHANGELOG.md +9 -0
- package/dist/temba-components.js +184 -237
- package/dist/temba-components.js.map +1 -1
- package/orca/setup.sh +81 -0
- package/orca.yaml +3 -0
- package/package.json +1 -1
- package/src/events/eventRenderers.ts +4 -9
- package/src/flow/CanvasNode.ts +14 -6
- package/src/flow/DragManager.ts +4 -2
- package/src/flow/utils.ts +1 -0
- package/src/form/DatePicker.ts +2 -1
- package/src/layout/Tab.ts +0 -15
- package/src/layout/TabPane.ts +73 -163
- package/src/live/ContactChat.ts +6 -2
- package/src/live/ContactDetails.ts +40 -35
- package/src/live/ContactFieldEditor.ts +35 -55
- package/src/live/ContactFields.ts +1 -2
- package/src/live/ContactNotepad.ts +9 -1
- package/src/live/ContactPending.ts +1 -0
- package/src/styles/designTokens.ts +2 -0
- package/static/css/temba-components.css +2 -0
package/orca/setup.sh
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Orca setup hook for a temba-components worktree.
|
|
4
|
+
# Symlinks shared utility files from nyaruka/utils, ensures the devcontainer
|
|
5
|
+
# is built/running (recreating it if the bind mounts are stale), and installs
|
|
6
|
+
# pnpm dependencies inside the worktree.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./orca/setup.sh # run directly
|
|
10
|
+
# (orca invokes this via orca.yaml's scripts.setup)
|
|
11
|
+
|
|
12
|
+
set -e
|
|
13
|
+
|
|
14
|
+
CONTAINER_NAME="temba-components"
|
|
15
|
+
|
|
16
|
+
# Orca exports ORCA_WORKTREE_PATH when running this as a hook; otherwise
|
|
17
|
+
# derive the worktree path from the script location.
|
|
18
|
+
if [ -n "${ORCA_WORKTREE_PATH:-}" ]; then
|
|
19
|
+
SCRIPT_DIR="$ORCA_WORKTREE_PATH"
|
|
20
|
+
else
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
22
|
+
fi
|
|
23
|
+
WORKSPACE_NAME="$(basename "$SCRIPT_DIR")"
|
|
24
|
+
|
|
25
|
+
# Pin WORKTREES to the orca workspaces dir so .devcontainer/devcontainer.json
|
|
26
|
+
# (which reads ${localEnv:WORKTREES}) sees the orca tree, not a stale value
|
|
27
|
+
# inherited from the user's shell.
|
|
28
|
+
WORKTREES="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
29
|
+
export WORKTREES
|
|
30
|
+
|
|
31
|
+
# Symlink shared files from nyaruka/utils into the worktree (gitignored).
|
|
32
|
+
UTILS_DIR="${UTILS_PATH:-$HOME/code/nyaruka/utils}/projects/temba-components"
|
|
33
|
+
if [ ! -d "$UTILS_DIR" ]; then
|
|
34
|
+
echo "Error: utils dir not found at $UTILS_DIR (set UTILS_PATH to override)"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
for file in run.sh AGENTS.md; do
|
|
38
|
+
if [ -f "$UTILS_DIR/$file" ] && [ ! -e "$SCRIPT_DIR/$file" ]; then
|
|
39
|
+
ln -s "$UTILS_DIR/$file" "$SCRIPT_DIR/$file"
|
|
40
|
+
fi
|
|
41
|
+
done
|
|
42
|
+
if [ ! -e "$SCRIPT_DIR/CLAUDE.md" ]; then
|
|
43
|
+
ln -s "$UTILS_DIR/AGENTS.md" "$SCRIPT_DIR/CLAUDE.md"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Ensure the devcontainer is running. Bind mounts can't be edited after the
|
|
47
|
+
# container is created, so if an existing container's /workspaces/worktrees
|
|
48
|
+
# mount doesn't match $WORKTREES (e.g. a stale conductor-era container),
|
|
49
|
+
# recreate it to pick up the new mount.
|
|
50
|
+
state="$(docker inspect -f '{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null || true)"
|
|
51
|
+
|
|
52
|
+
if [ -n "$state" ]; then
|
|
53
|
+
current_worktrees="$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/workspaces/worktrees"}}{{.Source}}{{end}}{{end}}' "$CONTAINER_NAME" 2>/dev/null || true)"
|
|
54
|
+
if [ -n "$current_worktrees" ] && [ "$current_worktrees" != "$WORKTREES" ]; then
|
|
55
|
+
echo "Container '$CONTAINER_NAME' has a stale /workspaces/worktrees mount:"
|
|
56
|
+
echo " $current_worktrees (expected $WORKTREES)"
|
|
57
|
+
echo "Removing and recreating the container..."
|
|
58
|
+
docker rm -f "$CONTAINER_NAME" >/dev/null
|
|
59
|
+
state=""
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
case "$state" in
|
|
64
|
+
running) ;;
|
|
65
|
+
"")
|
|
66
|
+
echo "Container '$CONTAINER_NAME' does not exist — building devcontainer..."
|
|
67
|
+
devcontainer up --workspace-folder "$SCRIPT_DIR"
|
|
68
|
+
;;
|
|
69
|
+
*)
|
|
70
|
+
echo "Container '$CONTAINER_NAME' is $state — starting..."
|
|
71
|
+
docker start "$CONTAINER_NAME"
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
|
|
75
|
+
# Install dependencies inside the worktree.
|
|
76
|
+
docker exec "$CONTAINER_NAME" bash -c '
|
|
77
|
+
cd "/workspaces/worktrees/temba-components/'"$WORKSPACE_NAME"'"
|
|
78
|
+
pnpm install
|
|
79
|
+
'
|
|
80
|
+
|
|
81
|
+
echo "Worktree '$WORKSPACE_NAME' ready for development"
|
package/orca.yaml
ADDED
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
UpdateFieldEvent,
|
|
14
14
|
URNsChangedEvent
|
|
15
15
|
} from '../events';
|
|
16
|
+
import { getLanguageName } from '../languages';
|
|
16
17
|
import { oxfordFn } from '../utils';
|
|
17
18
|
|
|
18
19
|
export enum Events {
|
|
@@ -291,9 +292,7 @@ export const renderTicketAssigneeChanged = (
|
|
|
291
292
|
// consistently interactive across open / close / reopen / assigned
|
|
292
293
|
// rows (the contact-history page can show events from any of the
|
|
293
294
|
// contact's tickets, so the jump-to-ticket affordance is useful).
|
|
294
|
-
const ticketLink = html`<a href="/ticket/all/open/${ticketUUID}/"
|
|
295
|
-
>ticket</a
|
|
296
|
-
>`;
|
|
295
|
+
const ticketLink = html`<a href="/ticket/all/open/${ticketUUID}/">ticket</a>`;
|
|
297
296
|
const ticketLinkCapitalized = html`<a href="/ticket/all/open/${ticketUUID}/"
|
|
298
297
|
>This ticket</a
|
|
299
298
|
>`;
|
|
@@ -356,11 +355,7 @@ export const renderContactGroupsEvent = (
|
|
|
356
355
|
if (event.groups_added) {
|
|
357
356
|
return renderInfoList('Added to', 'Added to', event.groups_added);
|
|
358
357
|
} else if (event.groups_removed) {
|
|
359
|
-
return renderInfoList(
|
|
360
|
-
'Removed from',
|
|
361
|
-
'Removed from',
|
|
362
|
-
event.groups_removed
|
|
363
|
-
);
|
|
358
|
+
return renderInfoList('Removed from', 'Removed from', event.groups_removed);
|
|
364
359
|
}
|
|
365
360
|
};
|
|
366
361
|
|
|
@@ -382,7 +377,7 @@ export const renderContactLanguageChangedEvent = (
|
|
|
382
377
|
return html`<div style=${eventLineStyle}>Cleared language</div>`;
|
|
383
378
|
}
|
|
384
379
|
return html`<div style=${eventLineStyle}>
|
|
385
|
-
Language updated to ${valueText(event.language)}
|
|
380
|
+
Language updated to ${valueText(getLanguageName(event.language))}
|
|
386
381
|
</div>`;
|
|
387
382
|
};
|
|
388
383
|
|
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -219,13 +219,18 @@ export class CanvasNode extends RapidElement {
|
|
|
219
219
|
background: repeating-linear-gradient(120deg, tomato, tomato 6px, #ff7056 0, #ff7056 18px) !important;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
/* Disable links on actions/nodes with issues
|
|
222
|
+
/* Disable links on actions/nodes with issues so clicks fall through
|
|
223
|
+
to open the editor instead of navigating. */
|
|
223
224
|
.action-content.has-issues .linked-name div,
|
|
224
225
|
.node.has-issues > .router .linked-name div {
|
|
225
226
|
text-decoration: none !important;
|
|
226
227
|
cursor: default !important;
|
|
227
228
|
pointer-events: none;
|
|
228
229
|
}
|
|
230
|
+
.action-content.has-issues .linked-pill,
|
|
231
|
+
.node.has-issues > .router .linked-pill {
|
|
232
|
+
pointer-events: none;
|
|
233
|
+
}
|
|
229
234
|
|
|
230
235
|
.action.sortable {
|
|
231
236
|
display: flex;
|
|
@@ -1094,13 +1099,16 @@ export class CanvasNode extends RapidElement {
|
|
|
1094
1099
|
}
|
|
1095
1100
|
|
|
1096
1101
|
/**
|
|
1097
|
-
* Returns true if the click target is inside a `.linked-name`
|
|
1098
|
-
*
|
|
1099
|
-
*
|
|
1100
|
-
*
|
|
1102
|
+
* Returns true if the click target is inside a `.linked-name` or
|
|
1103
|
+
* `.linked-pill` whose containing action/node has no issues. Active
|
|
1104
|
+
* links handle their own navigation, so click-vs-drag and node-edit
|
|
1105
|
+
* handlers bail out on them. When the action/node has issues, links are
|
|
1106
|
+
* visually disabled (see CSS) and clicks fall through to open the
|
|
1107
|
+
* editor instead.
|
|
1101
1108
|
*/
|
|
1102
1109
|
private isActiveLink(target: HTMLElement, action?: Action): boolean {
|
|
1103
|
-
if (!target.closest('.linked-name')
|
|
1110
|
+
if (!target.closest('.linked-name') && !target.closest('.linked-pill'))
|
|
1111
|
+
return false;
|
|
1104
1112
|
if (action) return !this.issuesByAction?.has(action.uuid);
|
|
1105
1113
|
return !(
|
|
1106
1114
|
this.issuesByNode?.has(this.node.uuid) ||
|
package/src/flow/DragManager.ts
CHANGED
|
@@ -127,7 +127,8 @@ export class DragManager {
|
|
|
127
127
|
if (
|
|
128
128
|
target.classList.contains('exit') ||
|
|
129
129
|
target.closest('.exit') ||
|
|
130
|
-
target.closest('.linked-name')
|
|
130
|
+
target.closest('.linked-name') ||
|
|
131
|
+
target.closest('.linked-pill')
|
|
131
132
|
) {
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
@@ -186,7 +187,8 @@ export class DragManager {
|
|
|
186
187
|
if (
|
|
187
188
|
target.classList.contains('exit') ||
|
|
188
189
|
target.closest('.exit') ||
|
|
189
|
-
target.closest('.linked-name')
|
|
190
|
+
target.closest('.linked-name') ||
|
|
191
|
+
target.closest('.linked-pill')
|
|
190
192
|
) {
|
|
191
193
|
return;
|
|
192
194
|
}
|
package/src/flow/utils.ts
CHANGED
package/src/form/DatePicker.ts
CHANGED
|
@@ -19,6 +19,7 @@ export class DatePicker extends FieldElement {
|
|
|
19
19
|
.container {
|
|
20
20
|
border-radius: var(--curvature);
|
|
21
21
|
border: 1px solid var(--color-widget-border);
|
|
22
|
+
background: var(--color-widget-bg);
|
|
22
23
|
display: flex;
|
|
23
24
|
cursor: pointer;
|
|
24
25
|
box-shadow: var(--widget-box-shadow);
|
|
@@ -59,7 +60,7 @@ export class DatePicker extends FieldElement {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
.tz-wrapper {
|
|
62
|
-
background:
|
|
63
|
+
background: var(--sunken);
|
|
63
64
|
display: flex;
|
|
64
65
|
flex-direction: row;
|
|
65
66
|
align-items: center;
|
package/src/layout/Tab.ts
CHANGED
|
@@ -27,24 +27,9 @@ export class Tab extends RapidElement {
|
|
|
27
27
|
@property({ type: String })
|
|
28
28
|
icon: string;
|
|
29
29
|
|
|
30
|
-
@property({ type: String })
|
|
31
|
-
selectionColor: string;
|
|
32
|
-
|
|
33
|
-
@property({ type: String })
|
|
34
|
-
selectionBackground: string;
|
|
35
|
-
|
|
36
|
-
@property({ type: String })
|
|
37
|
-
borderColor: string = 'var(--color-widget-border)';
|
|
38
|
-
|
|
39
|
-
@property({ type: String })
|
|
40
|
-
activityColor: string = `var(--color-link-primary)`;
|
|
41
|
-
|
|
42
30
|
@property({ type: Boolean })
|
|
43
31
|
selected = false;
|
|
44
32
|
|
|
45
|
-
@property({ type: Boolean })
|
|
46
|
-
notify = false;
|
|
47
|
-
|
|
48
33
|
@property({ type: Boolean })
|
|
49
34
|
alert = false;
|
|
50
35
|
|
package/src/layout/TabPane.ts
CHANGED
|
@@ -18,43 +18,48 @@ export class TabPane extends RapidElement {
|
|
|
18
18
|
.options {
|
|
19
19
|
display: flex;
|
|
20
20
|
align-items: stretch;
|
|
21
|
-
|
|
22
|
-
border-bottom:
|
|
21
|
+
gap: 4px;
|
|
22
|
+
border-bottom: 1px solid var(--border);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
.option {
|
|
26
26
|
user-select: none;
|
|
27
|
-
padding: 0.5em 0.7em;
|
|
28
|
-
margin: 0em 0em;
|
|
29
|
-
cursor: pointer;
|
|
30
27
|
display: flex;
|
|
31
|
-
font-size: 1.1em;
|
|
32
28
|
align-items: center;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
padding: 8px 14px 10px;
|
|
31
|
+
margin-bottom: -1px;
|
|
32
|
+
background: transparent;
|
|
33
|
+
color: var(--text-2);
|
|
34
|
+
--icon-color: var(--text-2);
|
|
35
|
+
font-size: 13px;
|
|
36
|
+
font-weight: var(--w-medium);
|
|
37
|
+
border-bottom: 2px solid transparent;
|
|
41
38
|
white-space: nowrap;
|
|
42
|
-
transition:
|
|
39
|
+
transition:
|
|
40
|
+
color 100ms linear,
|
|
41
|
+
border-color 100ms linear;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
.
|
|
46
|
-
|
|
44
|
+
.option:hover {
|
|
45
|
+
color: var(--text-1);
|
|
46
|
+
--icon-color: var(--text-1);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
.
|
|
50
|
-
|
|
49
|
+
.option.selected,
|
|
50
|
+
.option.selected:hover {
|
|
51
|
+
cursor: default;
|
|
52
|
+
color: var(--accent-700);
|
|
53
|
+
--icon-color: var(--accent-700);
|
|
54
|
+
border-bottom-color: var(--accent-600);
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
.option.
|
|
54
|
-
|
|
57
|
+
.unselect .option.selected {
|
|
58
|
+
cursor: pointer;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
.option
|
|
61
|
+
.option.hidden {
|
|
62
|
+
display: none;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
.option .name {
|
|
@@ -70,6 +75,9 @@ export class TabPane extends RapidElement {
|
|
|
70
75
|
|
|
71
76
|
.option .badge {
|
|
72
77
|
margin-left: 0.4em;
|
|
78
|
+
margin-right: -6px;
|
|
79
|
+
display: inline-flex;
|
|
80
|
+
align-items: center;
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
@media (max-width: 900px) {
|
|
@@ -85,9 +93,6 @@ export class TabPane extends RapidElement {
|
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
.focusedname .option.selected {
|
|
89
|
-
}
|
|
90
|
-
|
|
91
96
|
.focusedname .option .name {
|
|
92
97
|
max-width: 0px;
|
|
93
98
|
margin: 0;
|
|
@@ -101,137 +106,81 @@ export class TabPane extends RapidElement {
|
|
|
101
106
|
max-width: 200px;
|
|
102
107
|
}
|
|
103
108
|
|
|
104
|
-
.option {
|
|
105
|
-
|
|
106
|
-
--icon-color: rgba(0, 0, 0, 0.5);
|
|
107
|
-
color: rgba(0, 0, 0, 0.5);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.option.selected {
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.option.selected,
|
|
114
|
-
.option.selected:hover {
|
|
115
|
-
cursor: default;
|
|
116
|
-
box-shadow: 0px -3px 3px 1px rgba(0, 0, 0, 0.02);
|
|
117
|
-
|
|
118
|
-
background: var(--focused-tab-color, #fff);
|
|
119
|
-
transform: scale(1) translateY(1px);
|
|
120
|
-
--icon-color: #666;
|
|
121
|
-
color: #666;
|
|
122
|
-
border: 1px inset rgba(0, 0, 0, 0.15);
|
|
123
|
-
border-bottom: 0px;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.option.selected .dot {
|
|
127
|
-
display: none;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.unselect .option.selected {
|
|
131
|
-
cursor: pointer;
|
|
109
|
+
.focusedname .option .name {
|
|
110
|
+
transition: all 0s linear !important;
|
|
132
111
|
}
|
|
133
112
|
|
|
134
|
-
.
|
|
135
|
-
|
|
113
|
+
.focusedname .option.selected .name {
|
|
114
|
+
transition: all 200ms linear !important;
|
|
136
115
|
}
|
|
137
116
|
|
|
138
|
-
.option
|
|
139
|
-
|
|
140
|
-
color: #666;
|
|
141
|
-
background: rgba(0, 0, 0, 0.02);
|
|
117
|
+
.option.dirty {
|
|
118
|
+
font-weight: var(--w-semibold);
|
|
142
119
|
}
|
|
143
120
|
|
|
144
|
-
.option.
|
|
145
|
-
|
|
121
|
+
.option.alert {
|
|
122
|
+
color: var(--danger);
|
|
123
|
+
--icon-color: var(--danger);
|
|
146
124
|
}
|
|
147
125
|
|
|
148
126
|
.pane {
|
|
149
127
|
display: flex;
|
|
150
128
|
flex-direction: column;
|
|
151
129
|
flex-grow: 1;
|
|
152
|
-
background: var(--focused-tab-color, #fff);
|
|
153
|
-
border-bottom-left-radius: var(--curvature);
|
|
154
|
-
border-bottom-right-radius: var(--curvature);
|
|
155
|
-
overflow: hidden;
|
|
156
|
-
|
|
157
|
-
box-shadow: var(
|
|
158
|
-
--tabs-shadow,
|
|
159
|
-
rgba(0, 0, 0, 0.1) 0px 1px 3px 0px,
|
|
160
|
-
rgba(0, 0, 0, 0.03) 0px 1px 2px 0px
|
|
161
|
-
);
|
|
162
130
|
min-height: 0;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.pane.first {
|
|
166
|
-
border-top-left-radius: 0px;
|
|
167
131
|
overflow: hidden;
|
|
168
132
|
}
|
|
169
133
|
|
|
170
134
|
.count {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
height: 0.5em;
|
|
182
|
-
width: 0.5em;
|
|
183
|
-
margin-left: 0.2em;
|
|
184
|
-
background: var(--color-primary-dark);
|
|
185
|
-
border-radius: 99px;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.notify .count {
|
|
189
|
-
background: var(--color-alert);
|
|
190
|
-
color: #fff;
|
|
135
|
+
display: inline-flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
height: 16px;
|
|
139
|
+
padding: 0 2px;
|
|
140
|
+
color: inherit;
|
|
141
|
+
opacity: 0.6;
|
|
142
|
+
font-size: 11px;
|
|
143
|
+
font-weight: var(--w-medium);
|
|
144
|
+
font-variant-numeric: tabular-nums;
|
|
191
145
|
}
|
|
192
146
|
|
|
193
|
-
.
|
|
194
|
-
|
|
195
|
-
|
|
147
|
+
.option.selected .count,
|
|
148
|
+
.option.alert .count {
|
|
149
|
+
min-width: 16px;
|
|
150
|
+
padding: 0 4px;
|
|
151
|
+
border-radius: 999px;
|
|
152
|
+
opacity: 1;
|
|
196
153
|
}
|
|
197
154
|
|
|
198
|
-
.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
border-right: none !important;
|
|
203
|
-
border-bottom: none !important;
|
|
155
|
+
.option.selected .count {
|
|
156
|
+
background: var(--accent-100);
|
|
157
|
+
color: var(--accent-700);
|
|
158
|
+
font-weight: var(--w-semibold);
|
|
204
159
|
}
|
|
205
160
|
|
|
206
|
-
.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
border-top: none !important;
|
|
161
|
+
.option.alert .count {
|
|
162
|
+
background: var(--danger-bg);
|
|
163
|
+
color: var(--danger);
|
|
210
164
|
}
|
|
211
165
|
|
|
212
|
-
.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
166
|
+
.dot {
|
|
167
|
+
height: 0.5em;
|
|
168
|
+
width: 0.5em;
|
|
169
|
+
margin-left: 0.2em;
|
|
170
|
+
background: var(--accent-600);
|
|
171
|
+
border-radius: 99px;
|
|
216
172
|
}
|
|
217
173
|
|
|
218
|
-
.
|
|
219
|
-
|
|
174
|
+
.option.selected .dot {
|
|
175
|
+
display: none;
|
|
220
176
|
}
|
|
221
177
|
|
|
222
178
|
.check {
|
|
223
179
|
margin-left: 0.4em;
|
|
224
180
|
}
|
|
225
|
-
|
|
226
|
-
.pane {
|
|
227
|
-
display: flex;
|
|
228
|
-
}
|
|
229
181
|
`;
|
|
230
182
|
}
|
|
231
183
|
|
|
232
|
-
@property({ type: Boolean })
|
|
233
|
-
embedded = false;
|
|
234
|
-
|
|
235
184
|
@property({ type: Boolean })
|
|
236
185
|
collapses = false;
|
|
237
186
|
|
|
@@ -367,13 +316,11 @@ export class TabPane extends RapidElement {
|
|
|
367
316
|
}
|
|
368
317
|
|
|
369
318
|
public render(): TemplateResult {
|
|
370
|
-
const activeTab = this.options[this.index];
|
|
371
319
|
return html`
|
|
372
320
|
<div
|
|
373
321
|
class="${getClasses({
|
|
374
322
|
options: true,
|
|
375
323
|
collapses: this.collapses,
|
|
376
|
-
embedded: this.embedded,
|
|
377
324
|
focusedname: this.focusedName,
|
|
378
325
|
unselect: this.unselect
|
|
379
326
|
})}"
|
|
@@ -388,15 +335,9 @@ export class TabPane extends RapidElement {
|
|
|
388
335
|
first: index == 0,
|
|
389
336
|
selected: index == this.index,
|
|
390
337
|
hidden: tab.hidden,
|
|
391
|
-
notify: tab.notify,
|
|
392
338
|
alert: tab.alert,
|
|
393
339
|
dirty: tab.dirty
|
|
394
340
|
})}"
|
|
395
|
-
style="${tab.selectionColor && index == this.index
|
|
396
|
-
? `color:${tab.selectionColor};--icon-color:${tab.selectionColor};`
|
|
397
|
-
: ''} ${tab.selectionBackground && index == this.index
|
|
398
|
-
? `background-color:${tab.selectionBackground};`
|
|
399
|
-
: ''}"
|
|
400
341
|
>
|
|
401
342
|
${tab.icon ? html`<temba-icon name=${tab.icon} />` : null}
|
|
402
343
|
<div class="name">${tab.name} ${tab.dirty ? ` *` : ``}</div>
|
|
@@ -405,14 +346,11 @@ export class TabPane extends RapidElement {
|
|
|
405
346
|
<div class="badge">
|
|
406
347
|
${tab.count > 0 && !tab.activity
|
|
407
348
|
? html`<div class="count">
|
|
408
|
-
${tab.
|
|
349
|
+
${tab.count.toLocaleString()}
|
|
409
350
|
</div>`
|
|
410
351
|
: null}
|
|
411
352
|
${tab.activity && tab.count > 0 && !tab.dirty
|
|
412
|
-
? html`<div
|
|
413
|
-
class="dot"
|
|
414
|
-
style="background:${tab.activityColor}"
|
|
415
|
-
></div>`
|
|
353
|
+
? html`<div class="dot"></div>`
|
|
416
354
|
: null}
|
|
417
355
|
</div>
|
|
418
356
|
`
|
|
@@ -429,35 +367,7 @@ export class TabPane extends RapidElement {
|
|
|
429
367
|
<slot name="tab-right"></slot>
|
|
430
368
|
</div>
|
|
431
369
|
</div>
|
|
432
|
-
<div
|
|
433
|
-
@temba-details-changed=${this.handleTabDetailsChanged}
|
|
434
|
-
style="${activeTab?.borderColor
|
|
435
|
-
? `
|
|
436
|
-
border-top: var(--temba-tabs-border-top, 1px solid ${
|
|
437
|
-
activeTab?.borderColor || 'var(--color-widget-border)'
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
border-left: var(--temba-tabs-border-left, 1px solid ${
|
|
441
|
-
activeTab?.borderColor || 'var(--color-widget-border)'
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
border-bottom: var(--temba-tabs-border-bottom, 1px solid ${
|
|
445
|
-
activeTab?.borderColor || 'var(--color-widget-border)'
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
border-right: var(--temba-tabs-border-right, 1px solid ${
|
|
449
|
-
activeTab?.borderColor || 'var(--color-widget-border)'
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
`
|
|
453
|
-
: ''} ${activeTab?.selectionBackground
|
|
454
|
-
? `background:${activeTab?.selectionBackground};`
|
|
455
|
-
: ``}"
|
|
456
|
-
class="pane ${getClasses({
|
|
457
|
-
first: this.index == 0,
|
|
458
|
-
embedded: this.embedded
|
|
459
|
-
})}"
|
|
460
|
-
>
|
|
370
|
+
<div @temba-details-changed=${this.handleTabDetailsChanged} class="pane">
|
|
461
371
|
<slot></slot>
|
|
462
372
|
<slot name="pane-bottom"></slot>
|
|
463
373
|
</div>
|
package/src/live/ContactChat.ts
CHANGED
|
@@ -64,11 +64,11 @@ export class ContactChat extends ContactStoreElement {
|
|
|
64
64
|
display: flex;
|
|
65
65
|
flex-direction: row;
|
|
66
66
|
min-height: 0;
|
|
67
|
+
margin-top: var(--gap);
|
|
67
68
|
--compose-shadow: none;
|
|
68
69
|
--compose-border: none;
|
|
69
70
|
--compose-padding: 3px;
|
|
70
71
|
--compose-curvature: none;
|
|
71
|
-
border-top: 1px inset rgba(0, 0, 0, 0.05);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
.chat-wrapper {
|
|
@@ -76,7 +76,11 @@ export class ContactChat extends ContactStoreElement {
|
|
|
76
76
|
flex-grow: 1;
|
|
77
77
|
flex-direction: column;
|
|
78
78
|
min-height: 0;
|
|
79
|
-
background:
|
|
79
|
+
background: var(--surface);
|
|
80
|
+
border: 1px solid var(--border-strong);
|
|
81
|
+
border-radius: var(--r-sm);
|
|
82
|
+
box-shadow: var(--shadow-2);
|
|
83
|
+
overflow: hidden;
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
temba-contact-history {
|