@nyaruka/temba-components 0.120.1 → 0.120.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.
@@ -166,10 +166,6 @@ export class Compose extends FormElement {
166
166
  temba-shortcuts {
167
167
  flex-grow: 1;
168
168
  }
169
-
170
- .quick-replies {
171
- background: #f9f9f9;
172
- }
173
169
  `;
174
170
  }
175
171
 
@@ -182,6 +178,9 @@ export class Compose extends FormElement {
182
178
  @property({ type: Number })
183
179
  maxLength = 640;
184
180
 
181
+ @property({ type: Number })
182
+ maxQuickReplies = 10;
183
+
185
184
  @property({ type: Boolean })
186
185
  completion: boolean;
187
186
 
@@ -668,9 +667,11 @@ export class Compose extends FormElement {
668
667
  .count=${this.currentQuickReplies.length}
669
668
  >
670
669
  <temba-select
671
- class="quick-replies"
672
670
  @change=${this.handleQuickReplyChange}
673
671
  .values=${this.currentQuickReplies}
672
+ maxItems=${this.maxQuickReplies}
673
+ maxItemsText="You can only add ${this
674
+ .maxQuickReplies} Quick Replies"
674
675
  class="quick-replies"
675
676
  tags
676
677
  multi
@@ -358,6 +358,12 @@ export class Select<T extends SelectOption> extends FormElement {
358
358
  @property({ type: String })
359
359
  valueKey = 'value';
360
360
 
361
+ @property({ type: Number })
362
+ maxItems = 0;
363
+
364
+ @property({ type: String })
365
+ maxItemsText: string = 'Maximum items reached';
366
+
361
367
  @property({ attribute: false })
362
368
  currentFunction: CompletionOption;
363
369
 
@@ -807,6 +813,17 @@ export class Select<T extends SelectOption> extends FormElement {
807
813
  }
808
814
 
809
815
  public handleOptionSelection(event: CustomEvent) {
816
+ if (
817
+ this.multi &&
818
+ this.maxItems > 0 &&
819
+ this.values.length >= this.maxItems
820
+ ) {
821
+ this.infoText = this.maxItemsText;
822
+ return;
823
+ } else {
824
+ this.infoText = '';
825
+ }
826
+
810
827
  const selected = event.detail.selected;
811
828
  // check if we should post it
812
829
  if (selected.post && this.endpoint) {
@@ -953,6 +970,15 @@ export class Select<T extends SelectOption> extends FormElement {
953
970
  }
954
971
  }
955
972
 
973
+ if (
974
+ this.multi &&
975
+ this.maxItems > 0 &&
976
+ this.values.length >= this.maxItems
977
+ ) {
978
+ options = [];
979
+ this.infoText = this.maxItemsText;
980
+ }
981
+
956
982
  // finally sort
957
983
  if (this.sortFunction) {
958
984
  options.sort(this.sortFunction);
@@ -1129,6 +1155,14 @@ export class Select<T extends SelectOption> extends FormElement {
1129
1155
  this.visibleOptions = [];
1130
1156
  this.cursorIndex = 0;
1131
1157
  }
1158
+
1159
+ if (
1160
+ this.multi &&
1161
+ this.maxItems > 0 &&
1162
+ this.values.length >= this.maxItems
1163
+ ) {
1164
+ this.infoText = '';
1165
+ }
1132
1166
  }
1133
1167
 
1134
1168
  private handleClick(): void {
@@ -1347,12 +1381,14 @@ export class Select<T extends SelectOption> extends FormElement {
1347
1381
  this.values.splice(idx, 1);
1348
1382
  }
1349
1383
  this.requestUpdate('values', oldValues);
1384
+ this.infoText = '';
1350
1385
  }
1351
1386
 
1352
1387
  public popValue() {
1353
1388
  const oldValues = [...this.values];
1354
1389
  this.values.pop();
1355
1390
  this.requestUpdate('values', oldValues);
1391
+ this.infoText = '';
1356
1392
  }
1357
1393
 
1358
1394
  public clear() {
@@ -319,6 +319,40 @@ describe('temba-select', () => {
319
319
  );
320
320
  });
321
321
 
322
+ it('can select multiple options until maxitems', async () => {
323
+ const select = await createSelect(
324
+ clock,
325
+ getSelectHTML(colors, { placeholder: 'Select a color', multi: true, maxItems: 2 })
326
+ );
327
+ expect(select.values.length).to.equal(0);
328
+
329
+ const changeEvent = sinon.spy();
330
+ select.addEventListener('change', changeEvent);
331
+
332
+ // select the first option 3 times, only 2 (maxitems) options are handled and added
333
+ await openAndClick(clock, select, 0);
334
+ assert(changeEvent.called, 'change event not fired');
335
+
336
+ changeEvent.resetHistory();
337
+ await openAndClick(clock, select, 0);
338
+ assert(changeEvent.called, 'change event not fired');
339
+
340
+ changeEvent.resetHistory();
341
+ await open(clock, select);
342
+ assert.equal(select.visibleOptions.length, 0);
343
+ assert(!changeEvent.called, 'change event should not be fired');
344
+
345
+ // but we should have red and green selected only, no blue
346
+ expect(select.values.length).to.equal(2);
347
+ expect(select.shadowRoot.innerHTML).to.contain('Red');
348
+ expect(select.shadowRoot.innerHTML).to.contain('Green');
349
+
350
+ await assertScreenshot(
351
+ 'select/selected-multi-maxitems-reached',
352
+ getClipWithOptions(select)
353
+ );
354
+ });
355
+
322
356
  it('shows multiple values on initialization', async () => {
323
357
  const select = await createSelect(
324
358
  clock,