@nyaruka/temba-components 0.43.4 → 0.43.5

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.
@@ -1,5 +1,7 @@
1
1
  import { css, html, TemplateResult } from 'lit';
2
+ import { property } from 'lit/decorators.js';
2
3
  import { Group } from '../interfaces';
4
+ import { debounce, getClasses } from '../utils';
3
5
  import { Icon } from '../vectoricon';
4
6
  import { ContactStoreElement } from './ContactStoreElement';
5
7
 
@@ -12,83 +14,189 @@ const STATUS = {
12
14
  export class ContactBadges extends ContactStoreElement {
13
15
  static get styles() {
14
16
  return css`
17
+ .wrapper {
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ }
22
+
15
23
  temba-label {
16
24
  margin: 0.3em;
17
25
  }
18
26
 
27
+ .expanded .badges {
28
+ max-height: inherit;
29
+ }
30
+
31
+ .expanded .show-button {
32
+ opacity: 1;
33
+ margin-bottom: 0em;
34
+ margin-top: -0.5em;
35
+ }
36
+
37
+ .expanded .show-line {
38
+ width: 98%;
39
+ opacity: 1;
40
+ }
41
+
19
42
  .badges {
20
43
  display: flex;
44
+ overflow: hidden;
21
45
  flex-wrap: wrap;
46
+ max-height: 2.2em;
47
+ align-self: flex-start;
48
+ }
49
+
50
+ .show-button {
51
+ transition: all var(--transition-speed) ease-in-out
52
+ var(--transition-speed);
53
+ opacity: 0;
54
+ display: flex;
55
+ padding: 0em 1em;
56
+ margin-top: -0.8em;
57
+ cursor: pointer;
58
+ --icon-color-circle: #fff;
59
+ margin-bottom: -1.5em;
60
+ }
61
+
62
+ .show-line {
63
+ height: 1px;
64
+ width: 100%;
65
+ background: rgba(0, 0, 0, 0.05);
66
+ margin-top: 1em;
67
+ width: 0px;
68
+ transition: width calc(var(--transition-speed) * 2) linear
69
+ var(--transition-speed);
70
+ }
71
+
72
+ .has-more .show-line {
73
+ width: 98%;
74
+ }
75
+
76
+ .has-more .show-button {
77
+ opacity: 1;
78
+ margin-bottom: 0em;
79
+ margin-top: -0.5em;
80
+ }
81
+
82
+ .show-button temba-icon {
83
+ border-radius: 9999px;
22
84
  }
23
85
  `;
24
86
  }
25
87
 
88
+ @property({ type: Boolean })
89
+ hasMore = false;
90
+
91
+ @property({ type: Boolean })
92
+ expanded = false;
93
+
94
+ private handleResized() {
95
+ if (this.shadowRoot) {
96
+ const badges = this.shadowRoot.querySelector('.badges');
97
+ if (badges) {
98
+ this.hasMore = badges.scrollHeight > badges.clientHeight;
99
+ }
100
+ }
101
+ }
102
+
103
+ public updated(changedProperties: Map<string, any>) {
104
+ super.updated(changedProperties);
105
+ if (changedProperties.has('data')) {
106
+ if (!changedProperties.get('data')) {
107
+ const badges = this.shadowRoot.querySelector('.badges');
108
+ new ResizeObserver(
109
+ debounce(this.handleResized.bind(this), 200)
110
+ ).observe(badges);
111
+ }
112
+ }
113
+ }
114
+
26
115
  public render(): TemplateResult {
27
116
  if (this.data) {
28
117
  const status = STATUS[this.data.status];
29
-
30
118
  return html`
31
- <div class="badges">
32
- ${status && this.data.status !== 'active'
33
- ? html`
34
- <temba-label
35
- icon="icon.contact_${this.data.status}"
36
- onclick="goto(event)"
37
- href="/contact/${status.name.toLowerCase()}/"
38
- secondary
39
- clickable
40
- shadow
41
- >
42
- ${status.name}
43
- </temba-label>
44
- `
45
- : null}
46
- ${this.data.flow
47
- ? html`
48
- <temba-label
49
- icon="flow"
50
- onclick="goto(event)"
51
- href="/contact/?search=flow+%3D+${encodeURIComponent(
52
- '"' + this.data.flow.name + '"'
53
- )}"
54
- clickable
55
- primary
56
- shadow
57
- >
58
- ${this.data.flow.name}
59
- </temba-label>
60
- `
61
- : null}
62
- ${this.data.language
63
- ? html`
119
+ <div
120
+ class=${getClasses({
121
+ wrapper: true,
122
+ 'has-more': this.hasMore,
123
+ expanded: this.expanded,
124
+ })}
125
+ >
126
+ <div class="badges">
127
+ ${status && this.data.status !== 'active'
128
+ ? html`
129
+ <temba-label
130
+ icon="icon.contact_${this.data.status}"
131
+ onclick="goto(event)"
132
+ href="/contact/${status.name.toLowerCase()}/"
133
+ secondary
134
+ clickable
135
+ shadow
136
+ >
137
+ ${status.name}
138
+ </temba-label>
139
+ `
140
+ : null}
141
+ ${this.data.flow
142
+ ? html`
143
+ <temba-label
144
+ icon="flow"
145
+ onclick="goto(event)"
146
+ href="/contact/?search=flow+%3D+${encodeURIComponent(
147
+ '"' + this.data.flow.name + '"'
148
+ )}"
149
+ clickable
150
+ primary
151
+ shadow
152
+ >
153
+ ${this.data.flow.name}
154
+ </temba-label>
155
+ `
156
+ : null}
157
+ ${this.data.language
158
+ ? html`
159
+ <temba-label
160
+ icon=${Icon.language}
161
+ onclick="goto(event)"
162
+ href="/contact/?search=language+%3D+${encodeURIComponent(
163
+ '"' + this.data.language + '"'
164
+ )}"
165
+ clickable
166
+ primary
167
+ shadow
168
+ >
169
+ ${this.store.getLanguageName(this.data.language)}
170
+ </temba-label>
171
+ `
172
+ : null}
173
+ ${this.data.groups.map((group: Group) => {
174
+ return html`
64
175
  <temba-label
65
- icon=${Icon.language}
176
+ class="group"
66
177
  onclick="goto(event)"
67
- href="/contact/?search=language+%3D+${encodeURIComponent(
68
- '"' + this.data.language + '"'
69
- )}"
178
+ href="/contact/filter/${group.uuid}/"
179
+ icon=${group.is_dynamic ? Icon.group_smart : Icon.group}
70
180
  clickable
71
- primary
72
181
  shadow
73
182
  >
74
- ${this.store.getLanguageName(this.data.language)}
183
+ ${group.name}
75
184
  </temba-label>
76
- `
77
- : null}
78
- ${this.data.groups.map((group: Group) => {
79
- return html`
80
- <temba-label
81
- class="group"
82
- onclick="goto(event)"
83
- href="/contact/filter/${group.uuid}/"
84
- icon=${group.is_dynamic ? Icon.group_smart : Icon.group}
85
- clickable
86
- shadow
87
- >
88
- ${group.name}
89
- </temba-label>
90
- `;
91
- })}
185
+ `;
186
+ })}
187
+ </div>
188
+ <div class="show-line"></div>
189
+
190
+ <div class="show-button">
191
+ <temba-icon
192
+ @click=${() => {
193
+ this.expanded = !this.expanded;
194
+ }}
195
+ circled
196
+ name=${!this.expanded ? Icon.down : Icon.up}
197
+ animateChange="spin"
198
+ ></temba-icon>
199
+ </div>
92
200
  </div>
93
201
  `;
94
202
  } else {
@@ -95,7 +95,7 @@ export class VectorIcon extends LitElement {
95
95
  }
96
96
 
97
97
  .circled {
98
- background: rgb(240, 240, 240);
98
+ background: var(--icon-color-circle);
99
99
  padding: 0.15em;
100
100
  margin: -0.15em;
101
101
  box-shadow: var(--shadow);
@@ -31,6 +31,7 @@ export enum Icon {
31
31
  dashboard = 'pie-chart-01',
32
32
  delete = 'trash-03',
33
33
  delete_small = 'x',
34
+ down = 'chevron-down',
34
35
  download = 'download-01',
35
36
  email = 'mail-01',
36
37
  error = 'alert-circle',
@@ -86,6 +87,7 @@ export enum Icon {
86
87
  trigger = 'signal-01',
87
88
  triggers = 'signal-01',
88
89
  updated = 'edit-02',
90
+ up = 'chevron-up',
89
91
  upload = 'upload-cloud-01',
90
92
  usages = 'link-04',
91
93
  user = 'users-01',
@@ -110,6 +110,7 @@
110
110
  --icon-color: var(--text-color);
111
111
  --icon-color-hover: var(--icon-color);
112
112
  --icon-color-circle-hover: rgba(245, 245, 245, .8);
113
+ --icon-color-circle: rgb(240, 240, 240);
113
114
 
114
115
  --transition-speed: 250ms;
115
116
  --event-padding: 0.5em 1em;