@nyaruka/temba-components 0.26.1 → 0.26.2
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/demo/index.html +32 -13
- package/dist/4f80c187.js +4277 -0
- package/dist/index.js +279 -202
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/contacts/ContactChat.js +99 -85
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/contacts/ContactHistory.js +30 -36
- package/out-tsc/src/contacts/ContactHistory.js.map +1 -1
- package/out-tsc/src/contacts/events.js +61 -74
- package/out-tsc/src/contacts/events.js.map +1 -1
- package/out-tsc/src/list/TembaMenu.js +18 -13
- package/out-tsc/src/list/TembaMenu.js.map +1 -1
- package/out-tsc/src/tabpane/Tab.js +46 -0
- package/out-tsc/src/tabpane/Tab.js.map +1 -0
- package/out-tsc/src/tabpane/TabPane.js +109 -0
- package/out-tsc/src/tabpane/TabPane.js.map +1 -0
- package/out-tsc/temba-modules.js +4 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-contact-history.test.js +9 -7
- package/out-tsc/test/temba-contact-history.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/contacts/history-expanded.png +0 -0
- package/screenshots/truth/contacts/history.png +0 -0
- package/screenshots/truth/list/menu-submenu.png +0 -0
- package/src/contacts/ContactChat.ts +113 -94
- package/src/contacts/ContactHistory.ts +57 -59
- package/src/contacts/events.ts +61 -75
- package/src/list/TembaMenu.ts +19 -14
- package/src/tabpane/Tab.ts +42 -0
- package/src/tabpane/TabPane.ts +113 -0
- package/temba-modules.ts +4 -0
- package/test/temba-contact-history.test.ts +9 -7
- package/test-assets/style.css +6 -0
- package/dist/e477aebd.js +0 -4200
|
@@ -110,22 +110,24 @@ export class ContactHistory extends RapidElement {
|
|
|
110
110
|
return css`
|
|
111
111
|
${getEventStyles()}
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
flex-direction: column;
|
|
113
|
+
.wrapper {
|
|
114
|
+
border: 0px solid green;
|
|
116
115
|
display: flex;
|
|
117
116
|
flex-direction: column;
|
|
118
117
|
align-items: items-stretch;
|
|
118
|
+
flex-grow: 1;
|
|
119
|
+
min-height: 0;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
.events {
|
|
122
|
-
height: 200px;
|
|
123
123
|
overflow-y: scroll;
|
|
124
124
|
overflow-x: hidden;
|
|
125
|
-
flex-grow: 1;
|
|
126
|
-
border-top-left-radius: var(--curvature);
|
|
127
|
-
padding-top: 1em;
|
|
128
125
|
background: #fff;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
flex-grow: 1;
|
|
129
|
+
min-height: 0;
|
|
130
|
+
padding-top: 3em;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
temba-loading {
|
|
@@ -180,12 +182,9 @@ export class ContactHistory extends RapidElement {
|
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
.sticky-bin {
|
|
183
|
-
display: flex;
|
|
184
|
-
flex-direction: column;
|
|
185
|
-
z-index: 2;
|
|
186
185
|
border-top-left-radius: var(--curvature);
|
|
187
|
-
|
|
188
|
-
box-shadow:
|
|
186
|
+
z-index: 2;
|
|
187
|
+
box-shadow: rgb(0 0 0 / 15%) 0px 3px 3px 0px;
|
|
189
188
|
background: rgb(240, 240, 240);
|
|
190
189
|
}
|
|
191
190
|
|
|
@@ -382,7 +381,6 @@ export class ContactHistory extends RapidElement {
|
|
|
382
381
|
if (forceOpen) {
|
|
383
382
|
grouped[grouped.length - 1].open = forceOpen;
|
|
384
383
|
}
|
|
385
|
-
|
|
386
384
|
this.eventGroups = [...previousGroups, ...grouped];
|
|
387
385
|
}
|
|
388
386
|
this.refreshing = false;
|
|
@@ -452,6 +450,7 @@ export class ContactHistory extends RapidElement {
|
|
|
452
450
|
if (changedProperties.has('refreshing') && !this.refreshing) {
|
|
453
451
|
if (this.lastRefreshAdded > 0) {
|
|
454
452
|
const events = this.getEventsPane();
|
|
453
|
+
|
|
455
454
|
// if we are near the bottom, push us to the bottom to show new stuff
|
|
456
455
|
if (this.lastHeight > 0) {
|
|
457
456
|
const addedHeight = events.scrollHeight - this.lastHeight;
|
|
@@ -573,7 +572,6 @@ export class ContactHistory extends RapidElement {
|
|
|
573
572
|
}
|
|
574
573
|
eventGroup = {
|
|
575
574
|
open: false,
|
|
576
|
-
closing: false,
|
|
577
575
|
events: [event],
|
|
578
576
|
type: currentEventGroupType,
|
|
579
577
|
};
|
|
@@ -649,21 +647,17 @@ export class ContactHistory extends RapidElement {
|
|
|
649
647
|
}
|
|
650
648
|
|
|
651
649
|
private handleEventGroupHide(event: MouseEvent) {
|
|
650
|
+
event.preventDefault();
|
|
651
|
+
event.stopPropagation();
|
|
652
|
+
|
|
652
653
|
const grouping = event.currentTarget as HTMLDivElement;
|
|
653
654
|
const groupIndex = parseInt(grouping.getAttribute('data-group-index'));
|
|
654
655
|
const eventGroup =
|
|
655
656
|
this.eventGroups[this.eventGroups.length - groupIndex - 1];
|
|
656
657
|
|
|
657
|
-
|
|
658
|
-
eventGroup.closing = true;
|
|
659
|
-
this.requestUpdate('eventGroups');
|
|
658
|
+
eventGroup.open = false;
|
|
660
659
|
|
|
661
|
-
|
|
662
|
-
setTimeout(() => {
|
|
663
|
-
eventGroup.closing = false;
|
|
664
|
-
eventGroup.open = false;
|
|
665
|
-
this.requestUpdate('eventGroups');
|
|
666
|
-
}, 300);
|
|
660
|
+
this.requestUpdate('eventGroups');
|
|
667
661
|
}
|
|
668
662
|
|
|
669
663
|
private handleScroll() {
|
|
@@ -913,12 +907,16 @@ export class ContactHistory extends RapidElement {
|
|
|
913
907
|
: null;
|
|
914
908
|
|
|
915
909
|
return html`
|
|
916
|
-
${
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
910
|
+
${
|
|
911
|
+
this.ticket
|
|
912
|
+
? html`<div class="sticky-bin">${unfetchedTickets}</div>`
|
|
913
|
+
: null
|
|
914
|
+
}
|
|
915
|
+
${
|
|
916
|
+
this.fetching
|
|
917
|
+
? html`<temba-loading units="5" size="10"></temba-loading>`
|
|
918
|
+
: html`<div style="height:0em"></div>`
|
|
919
|
+
}
|
|
922
920
|
<div class="events" @scroll=${this.handleScroll}>
|
|
923
921
|
${this.eventGroups.map((eventGroup: EventGroup, index: number) => {
|
|
924
922
|
const grouping = getEventGroupType(eventGroup.events[0], this.ticket);
|
|
@@ -928,9 +926,7 @@ export class ContactHistory extends RapidElement {
|
|
|
928
926
|
grouping: true,
|
|
929
927
|
[grouping]: true,
|
|
930
928
|
expanded: eventGroup.open,
|
|
931
|
-
closing: eventGroup.closing,
|
|
932
929
|
});
|
|
933
|
-
|
|
934
930
|
return html`<div class="${classes}">
|
|
935
931
|
${grouping === 'verbose'
|
|
936
932
|
? html`<div
|
|
@@ -938,36 +934,37 @@ export class ContactHistory extends RapidElement {
|
|
|
938
934
|
@click=${this.handleEventGroupShow}
|
|
939
935
|
data-group-index="${groupIndex}"
|
|
940
936
|
>
|
|
941
|
-
${eventGroup.
|
|
942
|
-
|
|
937
|
+
${eventGroup.open
|
|
938
|
+
? html`<temba-icon
|
|
939
|
+
@click=${this.handleEventGroupHide}
|
|
940
|
+
data-group-index="${groupIndex}"
|
|
941
|
+
name="x"
|
|
942
|
+
clickable
|
|
943
|
+
></temba-icon>`
|
|
944
|
+
: html`${eventGroup.events.length}
|
|
945
|
+
${eventGroup.events.length === 1
|
|
946
|
+
? html`event`
|
|
947
|
+
: html`events`} `}
|
|
943
948
|
</div>`
|
|
944
949
|
: null}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return html`${this.renderEventContainer(
|
|
965
|
-
noteEvent
|
|
966
|
-
)}${this.renderEventContainer(event)}`;
|
|
967
|
-
} else {
|
|
968
|
-
return this.renderEventContainer(event);
|
|
969
|
-
}
|
|
970
|
-
})}
|
|
950
|
+
|
|
951
|
+
<div class="items">
|
|
952
|
+
${eventGroup.events.map((event: ContactEvent) => {
|
|
953
|
+
if (
|
|
954
|
+
event.type === Events.TICKET_ASSIGNED &&
|
|
955
|
+
(event as TicketEvent).note
|
|
956
|
+
) {
|
|
957
|
+
const noteEvent = { ...event };
|
|
958
|
+
noteEvent.type = Events.TICKET_NOTE_ADDED;
|
|
959
|
+
|
|
960
|
+
return html`${this.renderEventContainer(
|
|
961
|
+
noteEvent
|
|
962
|
+
)}${this.renderEventContainer(event)}`;
|
|
963
|
+
} else {
|
|
964
|
+
return this.renderEventContainer(event);
|
|
965
|
+
}
|
|
966
|
+
})}
|
|
967
|
+
</div>
|
|
971
968
|
</div>`;
|
|
972
969
|
})}
|
|
973
970
|
</div>
|
|
@@ -984,6 +981,7 @@ export class ContactHistory extends RapidElement {
|
|
|
984
981
|
New Messages
|
|
985
982
|
</div>
|
|
986
983
|
</div>
|
|
984
|
+
</div>
|
|
987
985
|
`;
|
|
988
986
|
}
|
|
989
987
|
}
|
package/src/contacts/events.ts
CHANGED
|
@@ -6,21 +6,54 @@ import { getDisplayName } from './helpers';
|
|
|
6
6
|
export const getEventStyles = () => {
|
|
7
7
|
return css`
|
|
8
8
|
.grouping {
|
|
9
|
-
|
|
10
|
-
margin: 0 -1em;
|
|
9
|
+
margin-top: 1em;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
.grouping.verbose {
|
|
14
13
|
background: #f9f9f9;
|
|
15
|
-
|
|
16
|
-
border-top: 1px solid #f9f9f9;
|
|
17
|
-
padding-top: 0;
|
|
18
|
-
padding-bottom: 0;
|
|
19
|
-
margin-top: 0;
|
|
20
|
-
margin-bottom: 1.5em;
|
|
21
|
-
color: #efefef;
|
|
14
|
+
color: var(--color-dark);
|
|
22
15
|
--color-link-primary: rgba(38, 166, 230, 1);
|
|
23
16
|
pointer-events: none;
|
|
17
|
+
background: #fefefe;
|
|
18
|
+
box-shadow: -8px 0px 8px 1px rgba(0, 0, 0, 0.05) inset;
|
|
19
|
+
margin-right: -16px;
|
|
20
|
+
padding-right: 16px;
|
|
21
|
+
margin-bottom: 1.3em;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.grouping .items {
|
|
25
|
+
display: block;
|
|
26
|
+
user-select: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.grouping.verbose .items {
|
|
30
|
+
opacity: 0;
|
|
31
|
+
max-height: 0;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.grouping.flows .items {
|
|
37
|
+
padding: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.grouping.messages .items {
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
margin: 0em 0.75em;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.grouping.verbose.expanded .items {
|
|
47
|
+
transition: max-height var(--transition-speed) ease-in-out,
|
|
48
|
+
opacity var(--transition-speed) ease-in-out;
|
|
49
|
+
opacity: 1;
|
|
50
|
+
max-height: 1000px;
|
|
51
|
+
padding: 1em 1em;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.grouping.verbose.expanded {
|
|
55
|
+
border-top: 1px solid #f3f3f3;
|
|
56
|
+
border-bottom: 1px solid #f3f3f3;
|
|
24
57
|
}
|
|
25
58
|
|
|
26
59
|
.grouping.verbose.expanded,
|
|
@@ -43,50 +76,37 @@ export const getEventStyles = () => {
|
|
|
43
76
|
}
|
|
44
77
|
|
|
45
78
|
.grouping.verbose .attn {
|
|
46
|
-
color: #
|
|
79
|
+
color: #666;
|
|
47
80
|
}
|
|
48
81
|
|
|
49
82
|
.event-count {
|
|
50
83
|
position: relative;
|
|
51
|
-
top: -1.2em;
|
|
52
84
|
font-size: 0.8em;
|
|
53
85
|
text-align: center;
|
|
54
|
-
border: 2px solid #f9f9f9;
|
|
55
|
-
background: #fff;
|
|
56
86
|
margin: 0 auto;
|
|
57
87
|
display: table;
|
|
58
88
|
padding: 3px 10px;
|
|
59
89
|
font-weight: 400;
|
|
60
|
-
color: #
|
|
61
|
-
border-radius: var(--curvature);
|
|
90
|
+
color: #999;
|
|
62
91
|
cursor: pointer;
|
|
63
|
-
|
|
92
|
+
width: 100%;
|
|
64
93
|
opacity: 1;
|
|
65
|
-
|
|
66
|
-
margin-top 0ms;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.closing .grouping-close-button {
|
|
70
|
-
opacity: 0 !important;
|
|
71
|
-
transition: none !important;
|
|
94
|
+
z-index: 1;
|
|
72
95
|
}
|
|
73
96
|
|
|
74
|
-
.event-count {
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
.event-count temba-icon {
|
|
98
|
+
display: inline-block;
|
|
99
|
+
position: absolute;
|
|
100
|
+
right: 5px;
|
|
101
|
+
top: 5px;
|
|
77
102
|
}
|
|
78
103
|
|
|
79
104
|
.event-count:hover {
|
|
80
|
-
|
|
81
|
-
min-width: 50%;
|
|
82
|
-
background: #f9f9f9;
|
|
83
|
-
color: #333;
|
|
105
|
+
color: var(--color-link-primary-hover);
|
|
84
106
|
}
|
|
85
107
|
|
|
86
108
|
.expanded .event-count {
|
|
87
|
-
|
|
88
|
-
margin-top: -42px;
|
|
89
|
-
z-index: 0;
|
|
109
|
+
padding: 0;
|
|
90
110
|
pointer-events: none;
|
|
91
111
|
}
|
|
92
112
|
|
|
@@ -114,54 +134,18 @@ export const getEventStyles = () => {
|
|
|
114
134
|
word-wrap: break-word;
|
|
115
135
|
}
|
|
116
136
|
|
|
117
|
-
.grouping.verbose.closing {
|
|
118
|
-
opacity: 0 !important;
|
|
119
|
-
padding: 0 !important;
|
|
120
|
-
background: #f9f9f9 !important;
|
|
121
|
-
max-height: 1px !important;
|
|
122
|
-
border-top: 1px solid #f9f9f9 !important;
|
|
123
|
-
padding-top: 0 !important;
|
|
124
|
-
padding-bottom: 0 !important;
|
|
125
|
-
margin-top: 0 !important;
|
|
126
|
-
margin-bottom: 0 !important;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.grouping.verbose.closing .event,
|
|
130
|
-
.grouping.verbose.closing pre {
|
|
131
|
-
max-height: 0px;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.grouping.verbose.expanded {
|
|
135
|
-
transition: all var(--transition-speed)
|
|
136
|
-
cubic-bezier(0.68, -0.55, 0.265, 1.05),
|
|
137
|
-
color 0.1ms;
|
|
138
|
-
background: #444;
|
|
139
|
-
color: #efefef;
|
|
140
|
-
max-height: 1000px;
|
|
141
|
-
border-top: 1px solid #f1f1f1;
|
|
142
|
-
padding: 2em;
|
|
143
|
-
margin-left: 1em;
|
|
144
|
-
margin-right: 1em;
|
|
145
|
-
border-radius: var(--curvature);
|
|
146
|
-
padding-bottom: 1em;
|
|
147
|
-
box-shadow: inset 0px 11px 4px -15px #000, inset 0px -11px 4px -15px #000;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
137
|
.grouping.verbose.expanded .event,
|
|
151
138
|
.grouping.verbose.expanded pre {
|
|
152
139
|
max-height: 500px;
|
|
153
|
-
margin-bottom: 0.5em;
|
|
154
140
|
opacity: 1;
|
|
155
|
-
transition: all var(--transition-speed) ease-in-out;
|
|
156
141
|
}
|
|
157
142
|
|
|
158
143
|
.grouping-close-button {
|
|
144
|
+
position: relative;
|
|
145
|
+
display: inline-block;
|
|
159
146
|
opacity: 0;
|
|
160
147
|
float: right;
|
|
161
|
-
|
|
162
|
-
margin-right: -1em !important;
|
|
163
|
-
fill: #f2f2f2;
|
|
164
|
-
transition: opacity var(--transition-speed) ease-in;
|
|
148
|
+
--icon-color: #666;
|
|
165
149
|
}
|
|
166
150
|
|
|
167
151
|
.grouping.verbose.expanded:hover .grouping-close-button {
|
|
@@ -175,7 +159,7 @@ export const getEventStyles = () => {
|
|
|
175
159
|
}
|
|
176
160
|
|
|
177
161
|
.event {
|
|
178
|
-
margin
|
|
162
|
+
margin: 0.25em 0.5em;
|
|
179
163
|
border-radius: var(--curvature);
|
|
180
164
|
flex-grow: 1;
|
|
181
165
|
}
|
|
@@ -332,6 +316,7 @@ export const getEventStyles = () => {
|
|
|
332
316
|
font-size: 80%;
|
|
333
317
|
color: rgba(0, 0, 0, 0.6);
|
|
334
318
|
padding: 6px 3px;
|
|
319
|
+
margin-bottom: 0.5em;
|
|
335
320
|
}
|
|
336
321
|
|
|
337
322
|
.msg-summary temba-icon[name='log'] {
|
|
@@ -460,7 +445,6 @@ export interface EventGroup {
|
|
|
460
445
|
type: string;
|
|
461
446
|
events: ContactEvent[];
|
|
462
447
|
open: boolean;
|
|
463
|
-
closing: boolean;
|
|
464
448
|
}
|
|
465
449
|
|
|
466
450
|
export enum Events {
|
|
@@ -1081,7 +1065,9 @@ export const renderContactLanguageChangedEvent = (
|
|
|
1081
1065
|
event: ContactLanguageChangedEvent
|
|
1082
1066
|
): TemplateResult => {
|
|
1083
1067
|
return html`<temba-icon name="contact"></temba-icon>
|
|
1084
|
-
<div class="description">
|
|
1068
|
+
<div class="description">
|
|
1069
|
+
Language updated to <span class="attn">${event.language}</span>
|
|
1070
|
+
</div>`;
|
|
1085
1071
|
};
|
|
1086
1072
|
|
|
1087
1073
|
export const renderChannelEvent = (event: ChannelEvent): TemplateResult => {
|
package/src/list/TembaMenu.ts
CHANGED
|
@@ -20,7 +20,6 @@ export interface MenuItem {
|
|
|
20
20
|
items?: MenuItem[];
|
|
21
21
|
inline?: boolean;
|
|
22
22
|
type?: string;
|
|
23
|
-
parent?: MenuItem;
|
|
24
23
|
on_submit?: string;
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -57,7 +56,7 @@ export class TembaMenu extends RapidElement {
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
.section {
|
|
60
|
-
font-size: 1.
|
|
59
|
+
font-size: 1.5em;
|
|
61
60
|
margin-bottom: 0.2em;
|
|
62
61
|
color: var(--color-text-dark);
|
|
63
62
|
}
|
|
@@ -80,7 +79,7 @@ export class TembaMenu extends RapidElement {
|
|
|
80
79
|
user-select: none;
|
|
81
80
|
-webkit-user-select: none;
|
|
82
81
|
display: flex;
|
|
83
|
-
font-size:
|
|
82
|
+
font-size: 1em;
|
|
84
83
|
--icon-color: var(--color-text-dark);
|
|
85
84
|
}
|
|
86
85
|
|
|
@@ -368,7 +367,7 @@ export class TembaMenu extends RapidElement {
|
|
|
368
367
|
}
|
|
369
368
|
|
|
370
369
|
.sub-section {
|
|
371
|
-
font-size:
|
|
370
|
+
font-size: 1rem;
|
|
372
371
|
color: #888;
|
|
373
372
|
margin-top: 1rem;
|
|
374
373
|
margin-left: 0.3rem;
|
|
@@ -395,8 +394,8 @@ export class TembaMenu extends RapidElement {
|
|
|
395
394
|
}
|
|
396
395
|
|
|
397
396
|
temba-button {
|
|
398
|
-
margin-top: 0.
|
|
399
|
-
margin-bottom: 0.
|
|
397
|
+
margin-top: 0.2em;
|
|
398
|
+
margin-bottom: 0.2em;
|
|
400
399
|
margin-left: 0.75em;
|
|
401
400
|
margin-right: 0.75em;
|
|
402
401
|
}
|
|
@@ -519,7 +518,7 @@ export class TembaMenu extends RapidElement {
|
|
|
519
518
|
if (subItem.items) {
|
|
520
519
|
subItem.items.forEach(inlineItem => {
|
|
521
520
|
inlineItem.level = item.level + 2;
|
|
522
|
-
inlineItem.parent = subItem;
|
|
521
|
+
// inlineItem.parent = subItem;
|
|
523
522
|
});
|
|
524
523
|
}
|
|
525
524
|
});
|
|
@@ -563,10 +562,10 @@ export class TembaMenu extends RapidElement {
|
|
|
563
562
|
private handleItemClicked(
|
|
564
563
|
event: MouseEvent,
|
|
565
564
|
menuItem: MenuItem,
|
|
566
|
-
|
|
565
|
+
parent: MenuItem = null
|
|
567
566
|
) {
|
|
568
|
-
if (
|
|
569
|
-
this.handleItemClicked(null,
|
|
567
|
+
if (parent && parent.inline) {
|
|
568
|
+
this.handleItemClicked(null, parent);
|
|
570
569
|
}
|
|
571
570
|
|
|
572
571
|
if (this.collapsed) {
|
|
@@ -613,7 +612,6 @@ export class TembaMenu extends RapidElement {
|
|
|
613
612
|
this.loadItems(menuItem, !menuItem.href);
|
|
614
613
|
this.dispatchEvent(new Event('change'));
|
|
615
614
|
} else {
|
|
616
|
-
this.dispatchEvent(new Event('change'));
|
|
617
615
|
if (this.pending && this.pending.length > 0) {
|
|
618
616
|
// auto select the next pending click
|
|
619
617
|
const nextId = this.pending.shift();
|
|
@@ -622,10 +620,14 @@ export class TembaMenu extends RapidElement {
|
|
|
622
620
|
const nextItem = findItem(item.items, nextId).item;
|
|
623
621
|
if (nextItem) {
|
|
624
622
|
this.handleItemClicked(null, nextItem);
|
|
623
|
+
} else {
|
|
624
|
+
this.fireNoPath(nextId);
|
|
625
625
|
}
|
|
626
626
|
} else {
|
|
627
627
|
this.fireNoPath(nextId);
|
|
628
628
|
}
|
|
629
|
+
} else {
|
|
630
|
+
this.dispatchEvent(new Event('change'));
|
|
629
631
|
}
|
|
630
632
|
this.requestUpdate('root');
|
|
631
633
|
}
|
|
@@ -756,7 +758,10 @@ export class TembaMenu extends RapidElement {
|
|
|
756
758
|
return expanded;
|
|
757
759
|
}
|
|
758
760
|
|
|
759
|
-
private renderMenuItem = (
|
|
761
|
+
private renderMenuItem = (
|
|
762
|
+
menuItem: MenuItem,
|
|
763
|
+
parent: MenuItem = null
|
|
764
|
+
): TemplateResult => {
|
|
760
765
|
if (menuItem.type === 'divider') {
|
|
761
766
|
return html`<div class="divider"></div>`;
|
|
762
767
|
}
|
|
@@ -812,7 +817,7 @@ export class TembaMenu extends RapidElement {
|
|
|
812
817
|
id="menu-${menuItem.id}"
|
|
813
818
|
class="${itemClasses}"
|
|
814
819
|
@click=${event => {
|
|
815
|
-
this.handleItemClicked(event, menuItem);
|
|
820
|
+
this.handleItemClicked(event, menuItem, parent);
|
|
816
821
|
}}
|
|
817
822
|
>
|
|
818
823
|
${menuItem.level === 0
|
|
@@ -928,7 +933,7 @@ export class TembaMenu extends RapidElement {
|
|
|
928
933
|
return html`${this.renderMenuItem(item)}
|
|
929
934
|
<div class="inline-children">
|
|
930
935
|
${item.items.map((child: MenuItem) => {
|
|
931
|
-
return this.renderMenuItem(child);
|
|
936
|
+
return this.renderMenuItem(child, item);
|
|
932
937
|
})}
|
|
933
938
|
</div>`;
|
|
934
939
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { css, html, TemplateResult } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators';
|
|
3
|
+
import { RapidElement } from '../RapidElement';
|
|
4
|
+
import { getClasses } from '../utils';
|
|
5
|
+
|
|
6
|
+
export class Tab extends RapidElement {
|
|
7
|
+
static get styles() {
|
|
8
|
+
return css`
|
|
9
|
+
:host {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
flex-grow: 1;
|
|
13
|
+
min-height: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
slot {
|
|
17
|
+
// display: none;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
slot.selected {
|
|
21
|
+
// display: flex;
|
|
22
|
+
// flex-direction: column;
|
|
23
|
+
// flex-grow: 1;
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@property({ type: String })
|
|
29
|
+
name: string;
|
|
30
|
+
|
|
31
|
+
@property({ type: String })
|
|
32
|
+
icon: string;
|
|
33
|
+
|
|
34
|
+
@property({ type: Boolean })
|
|
35
|
+
selected = false;
|
|
36
|
+
|
|
37
|
+
public render(): TemplateResult {
|
|
38
|
+
return html`<slot
|
|
39
|
+
class="${getClasses({ selected: this.selected })}"
|
|
40
|
+
></slot>`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { css, html, TemplateResult } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators';
|
|
3
|
+
import { RapidElement } from '../RapidElement';
|
|
4
|
+
import { Tab } from './Tab';
|
|
5
|
+
|
|
6
|
+
export class TabPane extends RapidElement {
|
|
7
|
+
static get styles() {
|
|
8
|
+
return css`
|
|
9
|
+
:host {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
min-height: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.tabs {
|
|
16
|
+
display: flex;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.tab {
|
|
20
|
+
padding: 0.5em 1em;
|
|
21
|
+
margin: 0em 0em;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
display: flex;
|
|
24
|
+
border-radius: var(--curvature);
|
|
25
|
+
border-bottom-right-radius: 0px;
|
|
26
|
+
border-bottom-left-radius: 0px;
|
|
27
|
+
border: 0px solid rgba(0, 0, 0, 0.45);
|
|
28
|
+
color: var(--color-text-dark);
|
|
29
|
+
--icon-color: var(--color-text-dark);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.tab temba-icon {
|
|
33
|
+
margin-right: 0.4em;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tab.selected {
|
|
37
|
+
cursor: default;
|
|
38
|
+
box-shadow: 2px 1px 3px 2px rgba(0, 0, 0, 0.07);
|
|
39
|
+
background: #fff;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.pane {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
flex-grow: 1;
|
|
46
|
+
background: #fff;
|
|
47
|
+
border-radius: var(--curvature);
|
|
48
|
+
box-shadow: 2px 5px 12px 2px rgba(0, 0, 0, 0.09),
|
|
49
|
+
3px 3px 2px 1px rgba(0, 0, 0, 0.05);
|
|
50
|
+
min-height: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.pane.first {
|
|
54
|
+
border-top-left-radius: 0px;
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@property({ type: Number })
|
|
60
|
+
index = 0;
|
|
61
|
+
|
|
62
|
+
private handleTabClick(event: MouseEvent): void {
|
|
63
|
+
this.index = parseInt(
|
|
64
|
+
(event.currentTarget as HTMLDivElement).dataset.index
|
|
65
|
+
);
|
|
66
|
+
this.requestUpdate('index');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public updated(changedProperties: Map<string, any>) {
|
|
70
|
+
super.updated(changedProperties);
|
|
71
|
+
if (changedProperties.has('index')) {
|
|
72
|
+
if (this.children.length > this.index) {
|
|
73
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
74
|
+
const tab = this.children[i] as Tab;
|
|
75
|
+
tab.selected = i == this.index;
|
|
76
|
+
|
|
77
|
+
if (tab.selected) {
|
|
78
|
+
tab.style.display = 'flex';
|
|
79
|
+
} else {
|
|
80
|
+
tab.style.display = 'none';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public render(): TemplateResult {
|
|
88
|
+
const tabs: Tab[] = [];
|
|
89
|
+
for (const tab of this.children) {
|
|
90
|
+
tabs.push(tab as Tab);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return html`
|
|
94
|
+
<div class="tabs">
|
|
95
|
+
${tabs.map(
|
|
96
|
+
(tab, index) => html`
|
|
97
|
+
<div
|
|
98
|
+
@click=${this.handleTabClick}
|
|
99
|
+
data-index=${index}
|
|
100
|
+
class="tab ${index == this.index ? 'selected' : ''}"
|
|
101
|
+
>
|
|
102
|
+
${tab.icon ? html`<temba-icon name=${tab.icon} />` : null}
|
|
103
|
+
${tab.name}
|
|
104
|
+
</div>
|
|
105
|
+
`
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
<div class="pane ${this.index === 0 ? 'first' : null}">
|
|
109
|
+
<slot></slot>
|
|
110
|
+
</div>
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
}
|