@nyaruka/temba-components 0.118.2 → 0.118.4

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.
@@ -41,6 +41,19 @@ export class Lightbox extends RapidElement {
41
41
  overflow: hidden;
42
42
  box-shadow: 0 0 12px 3px rgba(0, 0, 0, 0.15);
43
43
  }
44
+
45
+ .download {
46
+ background: rgba(0, 0, 0, 0.5);
47
+ position: absolute;
48
+ display:flex;
49
+ align-items:center;
50
+ color:#fff;
51
+ padding:0.5em;
52
+ border-radius:var(--curvature);
53
+ background:rgba(0,0,0,0.5);
54
+ }
55
+
56
+ }
44
57
  `;
45
58
  }
46
59
 
@@ -62,8 +75,8 @@ export class Lightbox extends RapidElement {
62
75
  private height: number;
63
76
  private width: number;
64
77
  private scale = 1;
65
- private xTrans = '0px';
66
- private yTrans = '0px';
78
+ private xTrans = 0;
79
+ private yTrans = 0;
67
80
 
68
81
  protected updated(
69
82
  changed: PropertyValueMap<any> | Map<PropertyKey, unknown>
@@ -92,8 +105,8 @@ export class Lightbox extends RapidElement {
92
105
  this.width = bounds.width;
93
106
  this.height = bounds.height;
94
107
 
95
- this.xTrans = '0px';
96
- this.yTrans = '0px';
108
+ this.xTrans = 0;
109
+ this.yTrans = 0;
97
110
  this.scale = 1;
98
111
 
99
112
  let desiredWidth = this.width;
@@ -116,11 +129,11 @@ export class Lightbox extends RapidElement {
116
129
 
117
130
  const xGrowth = (desiredWidth - this.width) / 2;
118
131
  const xDest = (window.innerWidth - desiredWidth) / 2;
119
- this.xTrans = xDest - this.left + xGrowth + 'px';
132
+ this.xTrans = xDest - this.left + xGrowth;
120
133
 
121
134
  const yGrowth = (desiredHeight - this.height) / 2;
122
135
  const yDest = (window.innerHeight - desiredHeight) / 2;
123
- this.yTrans = yDest - this.top + yGrowth + 'px';
136
+ this.yTrans = yDest - this.top + yGrowth;
124
137
 
125
138
  this.scale = desiredScale;
126
139
  this.show = true;
@@ -139,13 +152,12 @@ export class Lightbox extends RapidElement {
139
152
  styles['left'] = this.left + 'px';
140
153
  styles['top'] = this.top + 'px';
141
154
  styles['width'] = this.width + 'px';
142
- styles['height'] = this.height + 'px';
143
155
  }
144
156
 
145
157
  if (this.zoom) {
146
158
  styles[
147
159
  'transform'
148
- ] = `translate(${this.xTrans}, ${this.yTrans}) scale(${this.scale}, ${this.scale})`;
160
+ ] = `translate(${this.xTrans}px, ${this.yTrans}px) scale(${this.scale}, ${this.scale})`;
149
161
  }
150
162
 
151
163
  return html`
@@ -162,7 +174,7 @@ export class Lightbox extends RapidElement {
162
174
  style="transition: all ${this.animationTime}ms; ease"
163
175
  ></div>
164
176
  <div class=${getClasses({ matte: true })} style=${styleMap(styles)}>
165
- ${this.show ? this.ele : null}
177
+ ${this.show ? html`${this.ele}` : null}
166
178
  </div>
167
179
  </div>
168
180
  `;
@@ -47,6 +47,7 @@ export class MediaPicker extends RapidElement {
47
47
  flex-direction: row;
48
48
  flex-wrap: wrap;
49
49
  padding: 0.2em;
50
+ align-items: center;
50
51
  }
51
52
 
52
53
  .attachment-item {
@@ -3,7 +3,6 @@ import { RapidElement } from '../RapidElement';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { getClasses } from '../utils';
5
5
  import { Lightbox } from '../lightbox/Lightbox';
6
- import { styleMap } from 'lit-html/directives/style-map.js';
7
6
  import { WebChatIcon } from '../webchat';
8
7
 
9
8
  enum ThumbnailContentType {
@@ -48,8 +47,7 @@ export class Thumbnail extends RapidElement {
48
47
  .zoom .thumb {
49
48
  border-radius: 0px !important;
50
49
  width: calc(var(--thumb-size, 4em) + 0.8em);
51
- height: calc(var(--thumb-size, 4em) + 0.8em);
52
- max-height: calc(var(--thumb-size, 4em) + 0.8em);
50
+ max-height: calc(90vh - 10em);
53
51
  }
54
52
 
55
53
  .thumb {
@@ -57,8 +55,7 @@ export class Thumbnail extends RapidElement {
57
55
  background-position: center;
58
56
  background-repeat: no-repeat;
59
57
  border-radius: var(--curvature);
60
- max-height: var(--thumb-size, 4em);
61
- height: var(--thumb-size, 4em);
58
+ max-height: calc(var(--thumb-size, 4em) * 2);
62
59
  width: var(--thumb-size, 4em);
63
60
  display: flex;
64
61
  align-items: center;
@@ -84,8 +81,24 @@ export class Thumbnail extends RapidElement {
84
81
  display: block;
85
82
  }
86
83
 
87
- .zoom temba-icon {
84
+ .download {
88
85
  display: none;
86
+ position: absolute;
87
+ right: 0em;
88
+ bottom: 0em;
89
+ border-radius: var(--curvature);
90
+ transform: scale(0.2) translate(3em, 3em);
91
+ padding: 0.4em;
92
+ }
93
+
94
+ .zoom .download {
95
+ display: block;
96
+ background: rgba(0, 0, 0, 0.5);
97
+ }
98
+
99
+ .zoom .download:hover {
100
+ background: rgba(0, 0, 0, 0.6);
101
+ cursor: pointer;
89
102
  }
90
103
  `;
91
104
  }
@@ -96,6 +109,12 @@ export class Thumbnail extends RapidElement {
96
109
  @property({ type: String })
97
110
  attachment: string;
98
111
 
112
+ @property({ type: Number })
113
+ ratio: number = 0;
114
+
115
+ @property({ type: Boolean })
116
+ preview: boolean = true;
117
+
99
118
  @property({ type: Boolean, attribute: false })
100
119
  zoom: boolean;
101
120
 
@@ -107,6 +126,23 @@ export class Thumbnail extends RapidElement {
107
126
  ): void {
108
127
  super.updated(changes);
109
128
 
129
+ if (
130
+ changes.has('contentType') &&
131
+ this.contentType === ThumbnailContentType.IMAGE
132
+ ) {
133
+ const toObserve = this.shadowRoot.querySelector('.observe');
134
+ if (toObserve) {
135
+ new ResizeObserver((e, observer) => {
136
+ if (toObserve.clientHeight > 0 && toObserve.clientWidth > 0) {
137
+ this.ratio = toObserve.clientHeight / toObserve.clientWidth;
138
+ this.preview =
139
+ this.ratio === 0 || (this.ratio > 0.25 && this.ratio <= 1.5);
140
+ observer.disconnect();
141
+ }
142
+ }).observe(toObserve);
143
+ }
144
+ }
145
+
110
146
  // convert our attachment to a url and label
111
147
  if (changes.has('attachment')) {
112
148
  if (this.attachment) {
@@ -134,7 +170,7 @@ export class Thumbnail extends RapidElement {
134
170
  }
135
171
 
136
172
  public handleThumbnailClicked() {
137
- if (this.contentType === ThumbnailContentType.IMAGE) {
173
+ if (this.contentType === ThumbnailContentType.IMAGE && this.preview) {
138
174
  window.setTimeout(() => {
139
175
  const lightbox = document.querySelector('temba-lightbox') as Lightbox;
140
176
  lightbox.showElement(this);
@@ -144,6 +180,14 @@ export class Thumbnail extends RapidElement {
144
180
  }
145
181
  }
146
182
 
183
+ public handleDownload(e: Event) {
184
+ e.stopPropagation();
185
+ e.preventDefault();
186
+
187
+ // open this.url in another tab
188
+ window.open(this.url, '_blank');
189
+ }
190
+
147
191
  public render() {
148
192
  return html`
149
193
  <div
@@ -151,21 +195,21 @@ export class Thumbnail extends RapidElement {
151
195
  class="${getClasses({ wrapper: true, zoom: this.zoom })}"
152
196
  url=${this.url}
153
197
  >
154
- <div
155
- class="thumb ${this.contentType} "
156
- style="${this.url
157
- ? styleMap({
158
- backgroundImage: `url(${this.url})`
159
- })
160
- : ''}"
161
- >
162
- ${this.contentType !== ThumbnailContentType.IMAGE
163
- ? html`<temba-icon
198
+ ${this.contentType === ThumbnailContentType.IMAGE && this.preview
199
+ ? html`<div class=""><div class="download" @click=${this.handleDownload.bind(
200
+ this
201
+ )}><temba-icon size="1" style="color:#fff;" name="download"></temba-icon></div><img
202
+ class="observe thumb ${this.contentType}"
203
+ src="${this.url}"
204
+ ></img></div>`
205
+ : html`<div
206
+ style="padding:1em; background:rgba(0,0,0,.05);border-radius:var(--curvature);"
207
+ >
208
+ <temba-icon
164
209
  size="1.5"
165
210
  name="${ThumbnailIcons[this.contentType]}"
166
- ></temba-icon>`
167
- : null}
168
- </div>
211
+ ></temba-icon>
212
+ </div>`}
169
213
  </div>
170
214
  `;
171
215
  }
@@ -15,7 +15,7 @@ export const getDate = async (attrs: any = {}) => {
15
15
  return (await getComponent(TAG, attrs)) as TembaDate;
16
16
  };
17
17
 
18
- mockNow('2022-12-02T21:00:00.000000-07:00');
18
+ mockNow('2022-12-02T21:00:00.000000');
19
19
 
20
20
  describe('temba-date', () => {
21
21
  beforeEach(() => {
@@ -23,7 +23,7 @@ describe('temba-date', () => {
23
23
  });
24
24
 
25
25
  it('renders default', async () => {
26
- const date = await getDate({ value: '1978-11-18T02:22:00.000000-07:00' });
26
+ const date = await getDate({ value: '1978-11-18T02:22:00.000000' });
27
27
  const dateString = (
28
28
  date.shadowRoot.querySelector('.date') as HTMLSpanElement
29
29
  ).innerText;
@@ -34,7 +34,7 @@ describe('temba-date', () => {
34
34
 
35
35
  it('renders duration', async () => {
36
36
  const date = await getDate({
37
- value: '1978-11-18T02:22:00.000000-07:00',
37
+ value: '1978-11-18T02:22:00.000000',
38
38
  display: 'duration'
39
39
  });
40
40
  const dateString = (
@@ -47,7 +47,7 @@ describe('temba-date', () => {
47
47
 
48
48
  it('renders datetime', async () => {
49
49
  const date = await getDate({
50
- value: '1978-11-18T02:22:00.000000-07:00',
50
+ value: '1978-11-18T02:22:00.000000',
51
51
  display: 'datetime'
52
52
  });
53
53
  const dateString = (
@@ -55,15 +55,26 @@ describe('temba-date', () => {
55
55
  ).innerText;
56
56
 
57
57
  await assertScreenshot('date/datetime', getClip(date));
58
- expect(dateString).to.equal('11/18/1978, 9:22 AM');
58
+ expect(dateString).to.equal('11/18/1978, 2:22 AM');
59
+ });
60
+
61
+ it('renders timedate', async () => {
62
+ const date = await getDate({
63
+ value: '2022-12-01T21:30:00.000000',
64
+ display: 'timedate'
65
+ });
66
+ const dateString = (
67
+ date.shadowRoot.querySelector('.date') as HTMLSpanElement
68
+ ).innerText;
69
+ await assertScreenshot('date/timedate', getClip(date));
70
+ expect(dateString).to.equal('Dec 1');
59
71
  });
60
72
 
61
73
  it('renders inline', async () => {
62
74
  const el: HTMLElement = await fixture(html`
63
75
  <span
64
76
  >Your birthday is
65
- <temba-date value="1978-11-18T02:22:00.000000-07:00"></temba-date
66
- >!</span
77
+ <temba-date value="1978-11-18T02:22:00.000000"></temba-date>!</span
67
78
  >
68
79
  `);
69
80