@dialpad/dialtone 9.55.1 → 9.56.1

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.
Files changed (37) hide show
  1. package/dist/css/dialtone.css +8 -3
  2. package/dist/css/dialtone.min.css +1 -1
  3. package/dist/tokens/css/variables-dark.css +1 -1
  4. package/dist/tokens/css/variables-expressive-dark.css +1 -1
  5. package/dist/tokens/css/variables-expressive-light.css +1 -1
  6. package/dist/tokens/css/variables-expressive-sm-dark.css +1 -1
  7. package/dist/tokens/css/variables-expressive-sm-light.css +1 -1
  8. package/dist/tokens/css/variables-light.css +1 -1
  9. package/dist/tokens/css/variables-tmo-dark.css +1 -1
  10. package/dist/tokens/css/variables-tmo-light.css +1 -1
  11. package/dist/tokens/less/variables-dark.less +1 -1
  12. package/dist/tokens/less/variables-expressive-dark.less +1 -1
  13. package/dist/tokens/less/variables-expressive-light.less +1 -1
  14. package/dist/tokens/less/variables-expressive-sm-dark.less +1 -1
  15. package/dist/tokens/less/variables-expressive-sm-light.less +1 -1
  16. package/dist/tokens/less/variables-light.less +1 -1
  17. package/dist/tokens/less/variables-tmo-dark.less +1 -1
  18. package/dist/tokens/less/variables-tmo-light.less +1 -1
  19. package/dist/vue2/lib/combobox-multi-select.cjs +43 -7
  20. package/dist/vue2/lib/combobox-multi-select.cjs.map +1 -1
  21. package/dist/vue2/lib/combobox-multi-select.js +43 -7
  22. package/dist/vue2/lib/combobox-multi-select.js.map +1 -1
  23. package/dist/vue2/lib/datepicker.cjs.map +1 -1
  24. package/dist/vue2/lib/datepicker.js.map +1 -1
  25. package/dist/vue2/style.css +16 -5
  26. package/dist/vue2/types/components/datepicker/formatUtils.d.ts +41 -5
  27. package/dist/vue2/types/components/datepicker/formatUtils.d.ts.map +1 -1
  28. package/dist/vue2/types/recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue.d.ts +2 -337
  29. package/dist/vue2/types/recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue.d.ts.map +1 -1
  30. package/dist/vue3/lib/combobox-multi-select.cjs +60 -24
  31. package/dist/vue3/lib/combobox-multi-select.cjs.map +1 -1
  32. package/dist/vue3/lib/combobox-multi-select.js +61 -25
  33. package/dist/vue3/lib/combobox-multi-select.js.map +1 -1
  34. package/dist/vue3/style.css +16 -5
  35. package/dist/vue3/types/recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue.d.ts +1 -367
  36. package/dist/vue3/types/recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue.d.ts.map +1 -1
  37. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:49 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:53 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:51 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:55 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-expressive-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:54 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-expressive-light {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:52 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:56 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-expressive-sm-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:51 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:56 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-expressive-sm-light {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:49 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:52 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-light {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:54 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-tmo-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ * Generated on Tue, 23 Jul 2024 10:08:53 GMT
4
4
  */
5
5
 
6
6
  .dialtone-theme-tmo-light {
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:49 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:53 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.5rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:51 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:55 GMT
4
4
 
5
5
  @dt-font-size-100: 1.6rem; // small
6
6
  @dt-font-size-200: 2rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:55 GMT
4
4
 
5
5
  @dt-font-size-100: 1.6rem; // small
6
6
  @dt-font-size-200: 2rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:52 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:56 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.6rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:51 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:56 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.6rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:49 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:53 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.5rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:54 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.5rem; // medium / base
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Mon, 15 Jul 2024 18:08:50 GMT
3
+ // Generated on Tue, 23 Jul 2024 10:08:54 GMT
4
4
 
5
5
  @dt-font-size-100: 1.2rem; // small
6
6
  @dt-font-size-200: 1.5rem; // medium / base
@@ -201,6 +201,14 @@ const _sfc_main = {
201
201
  transition: {
202
202
  type: String,
203
203
  default: "fade"
204
+ },
205
+ /**
206
+ * Determines whether the combobox should collapse to a single when losing focus.
207
+ * @type {boolean}
208
+ */
209
+ collapseOnFocusOut: {
210
+ type: Boolean,
211
+ default: false
204
212
  }
205
213
  },
206
214
  emits: [
@@ -245,10 +253,10 @@ const _sfc_main = {
245
253
  value: "",
246
254
  popoverOffset: [0, 4],
247
255
  showValidationMessages: false,
248
- initialInputPadding: {},
249
256
  resizeWindowObserver: null,
250
- originalInputSize: null,
251
- CHIP_SIZES
257
+ initialInputHeight: null,
258
+ CHIP_SIZES,
259
+ inputFocused: false
252
260
  };
253
261
  },
254
262
  computed: {
@@ -290,6 +298,11 @@ const _sfc_main = {
290
298
  item: selectedItem,
291
299
  key: common_utils.getUniqueString(selectedItem)
292
300
  }));
301
+ },
302
+ chipWrapperClass() {
303
+ return {
304
+ [`combobox__chip-wrapper-${this.size}--collapsed`]: !this.inputFocused && this.collapseOnFocusOut
305
+ };
293
306
  }
294
307
  },
295
308
  watch: {
@@ -311,13 +324,14 @@ const _sfc_main = {
311
324
  await this.$nextTick();
312
325
  const input = this.getInput();
313
326
  this.revertInputPadding(input);
314
- this.originalInputSize = input.getBoundingClientRect().height;
327
+ this.initialInputHeight = input.getBoundingClientRect().height;
315
328
  this.setInputPadding();
316
329
  this.setChipsTopPosition();
317
330
  }
318
331
  }
319
332
  },
320
333
  mounted() {
334
+ this.setInitialInputHeight();
321
335
  this.resizeWindowObserver = new ResizeObserver(async () => {
322
336
  this.setChipsTopPosition();
323
337
  this.setInputPadding();
@@ -447,7 +461,7 @@ const _sfc_main = {
447
461
  input.style.paddingLeft = left + "px";
448
462
  const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;
449
463
  const top = lastChip.offsetTop + 2;
450
- if (chipsSize > this.originalInputSize) {
464
+ if (chipsSize > this.initialInputHeight) {
451
465
  input.style.paddingTop = `${top}px`;
452
466
  }
453
467
  },
@@ -480,13 +494,35 @@ const _sfc_main = {
480
494
  } else {
481
495
  this.showValidationMessages = false;
482
496
  }
497
+ },
498
+ setInitialInputHeight() {
499
+ const input = this.getInput();
500
+ if (!input)
501
+ return;
502
+ this.initialInputHeight = input.getBoundingClientRect().height;
503
+ },
504
+ async handleInputFocusIn() {
505
+ this.inputFocused = true;
506
+ if (this.collapseOnFocusOut) {
507
+ await this.$nextTick();
508
+ this.setInputPadding();
509
+ }
510
+ },
511
+ async handleInputFocusOut() {
512
+ this.inputFocused = false;
513
+ if (this.collapseOnFocusOut) {
514
+ const input = this.getInput();
515
+ if (!input)
516
+ return;
517
+ this.revertInputPadding(input);
518
+ }
483
519
  }
484
520
  }
485
521
  };
486
522
  var _sfc_render = function render() {
487
523
  var _vm = this, _c = _vm._self._c;
488
524
  return _c("dt-recipe-combobox-with-popover", { ref: "comboboxWithPopover", attrs: { "label": _vm.label, "show-list": _vm.showList, "max-height": _vm.listMaxHeight, "popover-offset": _vm.popoverOffset, "has-suggestion-list": _vm.hasSuggestionList, "visually-hidden-close-label": _vm.visuallyHiddenCloseLabel, "visually-hidden-close": _vm.visuallyHiddenClose, "content-width": "anchor", "append-to": _vm.appendTo, "transition": _vm.transition }, on: { "select": _vm.onComboboxSelect }, scopedSlots: _vm._u([{ key: "input", fn: function({ onInput }) {
489
- return [_c("span", { ref: "inputSlotWrapper", staticClass: "combobox__input-wrapper" }, [_c("span", { ref: "chipsWrapper", staticClass: "combobox__chip-wrapper" }, _vm._l(_vm.selectedItemsWithKeys, function({ item, key }) {
525
+ return [_c("span", { ref: "inputSlotWrapper", staticClass: "combobox__input-wrapper", on: { "focusin": _vm.handleInputFocusIn, "focusout": _vm.handleInputFocusOut } }, [_c("span", { ref: "chipsWrapper", class: ["combobox__chip-wrapper", _vm.chipWrapperClass] }, _vm._l(_vm.selectedItemsWithKeys, function({ item, key }) {
490
526
  return _c("dt-chip", _vm._g({ key, ref: "chips", refInFor: true, staticClass: "combobox__chip", attrs: { "label-class": ["d-chip__label"], "close-button-props": { ariaLabel: "close" }, "size": _vm.CHIP_SIZES[_vm.size] }, on: { "keyup": function($event) {
491
527
  if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "backspace", void 0, $event.key, void 0))
492
528
  return null;
@@ -514,7 +550,7 @@ var __component__ = /* @__PURE__ */ _pluginVue2_normalizer.normalizeComponent(
514
550
  _sfc_staticRenderFns,
515
551
  false,
516
552
  null,
517
- "7d72ca8b",
553
+ "5c09d325",
518
554
  null,
519
555
  null
520
556
  );
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-multi-select.cjs","sources":["../../recipes/comboboxes/combobox_multi_select/combobox_multi_select_constants.js","../../recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue"],"sourcesContent":["export const MULTI_SELECT_SIZES = {\n // Chip has no 'lg' and 'xl' size. So we don't support that in multi-select.\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n DEFAULT: 'md',\n};\n\nexport const CHIP_SIZES = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n};\n\nexport const CHIP_TOP_POSITION = {\n xs: 1.4,\n sm: 0.4,\n md: 0.2,\n};\n\nexport default {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n};\n","<template>\n <dt-recipe-combobox-with-popover\n ref=\"comboboxWithPopover\"\n :label=\"label\"\n :show-list=\"showList\"\n :max-height=\"listMaxHeight\"\n :popover-offset=\"popoverOffset\"\n :has-suggestion-list=\"hasSuggestionList\"\n :visually-hidden-close-label=\"visuallyHiddenCloseLabel\"\n :visually-hidden-close=\"visuallyHiddenClose\"\n content-width=\"anchor\"\n :append-to=\"appendTo\"\n :transition=\"transition\"\n @select=\"onComboboxSelect\"\n >\n <template #input=\"{ onInput }\">\n <span\n ref=\"inputSlotWrapper\"\n class=\"combobox__input-wrapper\"\n >\n <span\n ref=\"chipsWrapper\"\n class=\"combobox__chip-wrapper\"\n >\n <dt-chip\n v-for=\"({ item, key }) in selectedItemsWithKeys\"\n ref=\"chips\"\n :key=\"key\"\n :label-class=\"['d-chip__label']\"\n class=\"combobox__chip\"\n :close-button-props=\"{ ariaLabel: 'close' }\"\n :size=\"CHIP_SIZES[size]\"\n v-on=\"chipListeners\"\n @keyup.backspace=\"onChipRemove(item)\"\n @close=\"onChipRemove(item)\"\n >\n {{ item }}\n </dt-chip>\n </span>\n\n <dt-input\n ref=\"input\"\n v-model=\"value\"\n class=\"combobox__input\"\n :aria-label=\"label\"\n :label=\"labelVisible ? label : ''\"\n :description=\"description\"\n :placeholder=\"inputPlaceHolder\"\n :show-messages=\"showInputMessages\"\n :messages=\"inputMessages\"\n :size=\"size\"\n v-on=\"inputListeners\"\n @input=\"onInput\"\n />\n\n <dt-validation-messages\n :validation-messages=\"maxSelectedMessage\"\n :show-messages=\"showValidationMessages\"\n />\n </span>\n </template>\n\n <!-- @slot slot for popover header -->\n <template\n v-if=\"$slots.header\"\n #header\n >\n <div ref=\"header\">\n <slot name=\"header\" />\n </div>\n </template>\n\n <!-- @slot slot for popover list -->\n <template #list>\n <div\n ref=\"list\"\n @mousedown.prevent\n >\n <slot\n v-if=\"!loading\"\n name=\"list\"\n />\n <div\n v-else\n class=\"combobox__list--loading\"\n >\n {{ loadingMessage }}\n </div>\n </div>\n </template>\n\n <!-- @slot slot for popover footer -->\n <template\n v-if=\"$slots.footer\"\n #footer\n >\n <div ref=\"footer\">\n <slot name=\"footer\" />\n </div>\n </template>\n </dt-recipe-combobox-with-popover>\n</template>\n\n<script>\nimport DtRecipeComboboxWithPopover from '@/recipes/comboboxes/combobox_with_popover/combobox_with_popover.vue';\nimport DtInput from '@/components/input/input.vue';\nimport DtChip from '@/components/chip/chip.vue';\nimport DtValidationMessages from '@/components/validation_messages/validation_messages.vue';\nimport { validationMessageValidator } from '@/common/validators';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '@/components/popover/popover_constants';\nimport {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n} from './combobox_multi_select_constants';\nimport SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';\nimport { getUniqueString } from '@/common/utils';\n\nexport default {\n name: 'DtRecipeComboboxMultiSelect',\n\n components: {\n DtRecipeComboboxWithPopover,\n DtInput,\n DtChip,\n DtValidationMessages,\n },\n\n mixins: [SrOnlyCloseButtonMixin],\n\n props: {\n /**\n * String to use for the input label.\n */\n label: {\n type: String,\n required: true,\n },\n\n /**\n * Determines visibility of input label.\n * @values true, false\n */\n labelVisible: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Description for the input\n */\n description: {\n type: String,\n default: '',\n },\n\n /**\n * Input placeholder\n */\n placeholder: {\n type: String,\n default: 'Select one or start typing',\n },\n\n /**\n * Input validation messages\n */\n inputMessages: {\n type: Array,\n default: () => [],\n validator: inputMessages => {\n return validationMessageValidator(inputMessages);\n },\n },\n\n /**\n * Show input validation message\n */\n showInputMessages: {\n type: Boolean,\n default: true,\n },\n\n // @TODO: https://dialpad.atlassian.net/browse/DP-52324\n // type: {\n // type: String,\n // values: ['input', 'select'],\n // default: 'select',\n // },\n\n /**\n * Determines if the list is loading\n */\n loading: {\n type: Boolean,\n default: false,\n },\n\n /**\n * The message when the list is loading\n */\n loadingMessage: {\n type: String,\n default: 'loading...',\n },\n\n /**\n * Determines when to show the list element and also controls the aria-expanded attribute.\n * Leaving this null will have the combobox trigger on input focus by default.\n * If you set this value, the default trigger behavior will be disabled and you can\n * control it as you need.\n */\n showList: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Determines maximum height for the popover before overflow.\n * Possible units rem|px|em\n */\n listMaxHeight: {\n type: String,\n default: '300px',\n },\n\n /**\n * The selected items\n */\n selectedItems: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Would be the maximum number of selections you can make. 0 is unlimited\n */\n maxSelected: {\n type: Number,\n default: 0,\n },\n\n /**\n * Max select message when the max selections is exceeded with the structure:\n * `[{\"message\": string, \"type\": VALIDATION_MESSAGE_TYPES }]`\n */\n maxSelectedMessage: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Displays the list when the combobox is focused, before the user has typed anything.\n * When this is enabled the list will not close after selection.\n */\n hasSuggestionList: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Size of the chip, one of `xs`, `sm`, `md`\n */\n size: {\n type: String,\n default: 'md',\n validator: (t) => Object.values(MULTI_SELECT_SIZES).includes(t),\n },\n\n /**\n * Sets the element to which the popover is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Named transition when the content display is toggled.\n * @see DtLazyShow\n */\n transition: {\n type: String,\n default: 'fade',\n },\n },\n\n emits: [\n /**\n * Native input event\n *\n * @event input\n * @type {String }\n */\n 'input',\n\n /**\n * Event fired when item selected\n *\n * @event select\n * @type {Number}\n */\n 'select',\n\n /**\n * Event fired when item removed\n *\n * @event remove\n * @type {String}\n */\n 'remove',\n\n /**\n * Event fired when max selected items limit is reached\n *\n * @event max-selected\n * @type {Object}\n */\n 'max-selected',\n\n /**\n * Native keyup event\n *\n * @event keyup\n * @type {KeyboardEvent}\n */\n 'keyup',\n ],\n\n data () {\n return {\n value: '',\n popoverOffset: [0, 4],\n showValidationMessages: false,\n initialInputPadding: {},\n resizeWindowObserver: null,\n originalInputSize: null,\n CHIP_SIZES,\n };\n },\n\n computed: {\n inputPlaceHolder () {\n return this.selectedItems?.length > 0 ? '' : this.placeholder;\n },\n\n chipListeners () {\n return {\n ...this.$listeners,\n keyup: event => {\n this.onChipKeyup(event);\n this.$emit('keyup', event);\n },\n };\n },\n\n inputListeners () {\n return {\n ...this.$listeners,\n input: event => {\n this.$emit('input', event);\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n\n keyup: event => {\n this.onInputKeyup(event);\n this.$emit('keyup', event);\n },\n\n click: event => {\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n };\n },\n\n selectedItemsWithKeys () {\n return this.selectedItems.map(selectedItem => ({\n item: selectedItem,\n key: getUniqueString(selectedItem),\n }));\n },\n },\n\n watch: {\n selectedItems: {\n async handler () {\n this.initSelectedItems();\n },\n },\n\n async label () {\n await this.$nextTick();\n // Adjust the chips position if label changed\n this.setChipsTopPosition();\n },\n\n async description () {\n await this.$nextTick();\n // Adjust the chips position if description changed\n this.setChipsTopPosition();\n },\n\n size: {\n async handler () {\n await this.$nextTick();\n const input = this.getInput();\n this.revertInputPadding(input);\n this.originalInputSize = input.getBoundingClientRect().height;\n this.setInputPadding();\n this.setChipsTopPosition();\n },\n },\n },\n\n mounted () {\n // Recalculate chip position and input padding when resizing window\n this.resizeWindowObserver = new ResizeObserver(async () => {\n this.setChipsTopPosition();\n this.setInputPadding();\n });\n this.resizeWindowObserver.observe(document.body);\n\n this.initSelectedItems();\n },\n\n beforeDestroy () {\n this.resizeWindowObserver?.unobserve(document.body);\n },\n\n methods: {\n async initSelectedItems () {\n await this.$nextTick();\n this.setInputPadding();\n this.setChipsTopPosition();\n this.setInputMinWidth();\n this.checkMaxSelected();\n },\n\n onChipRemove (item) {\n this.$emit('remove', item);\n this.$refs.input?.focus();\n },\n\n onComboboxSelect (i) {\n this.value = '';\n this.$emit('select', i);\n },\n\n showComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.showComboboxList();\n },\n\n closeComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.closeComboboxList();\n },\n\n getChipButtons () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el.querySelector('button'));\n },\n\n getChips () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el);\n },\n\n getLastChipButton () {\n return this.$refs.chips && this.getChipButtons()[this.getChipButtons().length - 1];\n },\n\n getLastChip () {\n return this.$refs.chips && this.getChips()[this.getChips().length - 1];\n },\n\n getFirstChip () {\n return this.$refs.chips && this.getChips()[0];\n },\n\n getInput () {\n return this.$refs.input?.$refs.input;\n },\n\n onChipKeyup (event) {\n const key = event.code?.toLowerCase();\n if (key === 'arrowleft') {\n // Move to the previous chip\n this.navigateBetweenChips(event.target, true);\n } else if (key === 'arrowright') {\n if (event.target.id === this.getLastChipButton().id) {\n // Move to the input if it's the last chip\n this.moveFromChipToInput();\n } else {\n // Move to the next chip\n this.navigateBetweenChips(event.target, false);\n }\n }\n },\n\n onInputKeyup (event) {\n const key = event.code?.toLowerCase();\n // If the cursor is at the start of the text,\n // press 'backspace' or 'left' focuses the last chip\n if (this.selectedItems.length > 0 && event.target.selectionStart === 0) {\n if (key === 'backspace' || key === 'arrowleft') {\n this.moveFromInputToChip();\n }\n }\n },\n\n moveFromInputToChip () {\n this.getLastChipButton().focus();\n this.$refs.input?.blur();\n this.closeComboboxList();\n },\n\n moveFromChipToInput () {\n this.getLastChipButton().blur();\n this.$refs.input?.focus();\n this.showComboboxList();\n },\n\n navigateBetweenChips (target, toLeft) {\n const from = this.getChipButtons().indexOf(target);\n const to = toLeft ? from - 1 : from + 1;\n if (to < 0 || to >= this.$refs.chips?.length) {\n return;\n }\n this.getChipButtons()[from].blur();\n this.getChipButtons()[to].focus();\n this.closeComboboxList();\n },\n\n setChipsTopPosition () {\n // To place the chips in the input box\n // The chip \"top\" position should be the same line as the input box\n const input = this.getInput();\n if (!input) return;\n const inputSlotWrapper = this.$refs.inputSlotWrapper;\n const top = input.getBoundingClientRect().top -\n inputSlotWrapper.getBoundingClientRect().top;\n const chipsWrapper = this.$refs.chipsWrapper;\n chipsWrapper.style.top = (top - CHIP_TOP_POSITION[this.size]) + 'px';\n },\n\n setInputPadding () {\n const lastChip = this.getLastChip();\n const input = this.getInput();\n const chipsWrapper = this.$refs.chipsWrapper;\n if (!input) return;\n this.revertInputPadding(input);\n this.popoverOffset = [0, 4];\n if (!lastChip) return;\n\n // Get the position of the last chip\n // The input cursor should be the same \"top\" as that chip and next besides it\n const left = lastChip.offsetLeft + this.getFullWidth(lastChip);\n input.style.paddingLeft = left + 'px';\n\n // Get the chip size minus the 4px padding\n const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;\n\n // Get lastChip offsetTop plus 2px of the input padding.\n const top = lastChip.offsetTop + 2;\n\n // Add padding to Top only if the chips need more space\n if (chipsSize > this.originalInputSize) {\n input.style.paddingTop = `${top}px`;\n }\n },\n\n revertInputPadding (input) {\n input.style.paddingLeft = '';\n input.style.paddingTop = '';\n input.style.paddingBottom = '';\n },\n\n getFullWidth (el) {\n const styles = window.getComputedStyle(el);\n return el.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);\n },\n\n setInputMinWidth () {\n // Ensure the width of the input is \"slightly bigger\" than the width of a single chip\n const firstChip = this.getFirstChip();\n const input = this.getInput();\n if (!input) return;\n if (firstChip) {\n // Add 4px buffer for typing room\n input.style.minWidth = (this.getFullWidth(firstChip) + 4) + 'px';\n } else {\n input.style.minWidth = '';\n }\n },\n\n checkMaxSelected () {\n if (this.maxSelected === 0) return;\n if (this.selectedItems.length > this.maxSelected) {\n this.showValidationMessages = true;\n this.$emit('max-selected');\n } else {\n this.showValidationMessages = false;\n }\n },\n },\n};\n</script>\n\n<style scoped lang=\"less\">\n.combobox__input-wrapper {\n position: relative;\n display: block;\n}\n\n.combobox__chip-wrapper {\n position: absolute;\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n padding-left: var(--dt-space-100);\n max-width: calc(var(--dt-size-100-percent) - var(--dt-space-400));\n}\n\n.combobox__chip {\n margin-top: var(--dt-space-300);\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n z-index: var(--zi-base1);\n max-width: var(--dt-size-100-percent);\n}\n\n.combobox__input {\n flex-grow: 1;\n}\n\n.combobox__list--loading {\n text-align: center;\n padding-top: var(--dt-space-500);\n padding-bottom: var(--dt-space-500);\n}\n</style>\n"],"names":["DtRecipeComboboxWithPopover","DtInput","DtChip","DtValidationMessages","SrOnlyCloseButtonMixin","validationMessageValidator","POPOVER_APPEND_TO_VALUES","getUniqueString"],"mappings":"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"}
1
+ {"version":3,"file":"combobox-multi-select.cjs","sources":["../../recipes/comboboxes/combobox_multi_select/combobox_multi_select_constants.js","../../recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue"],"sourcesContent":["export const MULTI_SELECT_SIZES = {\n // Chip has no 'lg' and 'xl' size. So we don't support that in multi-select.\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n DEFAULT: 'md',\n};\n\nexport const CHIP_SIZES = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n};\n\nexport const CHIP_TOP_POSITION = {\n xs: 1.4,\n sm: 0.4,\n md: 0.2,\n};\n\nexport default {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n};\n","<template>\n <dt-recipe-combobox-with-popover\n ref=\"comboboxWithPopover\"\n :label=\"label\"\n :show-list=\"showList\"\n :max-height=\"listMaxHeight\"\n :popover-offset=\"popoverOffset\"\n :has-suggestion-list=\"hasSuggestionList\"\n :visually-hidden-close-label=\"visuallyHiddenCloseLabel\"\n :visually-hidden-close=\"visuallyHiddenClose\"\n content-width=\"anchor\"\n :append-to=\"appendTo\"\n :transition=\"transition\"\n @select=\"onComboboxSelect\"\n >\n <template #input=\"{ onInput }\">\n <span\n ref=\"inputSlotWrapper\"\n class=\"combobox__input-wrapper\"\n @focusin=\"handleInputFocusIn\"\n @focusout=\"handleInputFocusOut\"\n >\n <span\n ref=\"chipsWrapper\"\n :class=\"['combobox__chip-wrapper', chipWrapperClass]\"\n >\n <dt-chip\n v-for=\"({ item, key }) in selectedItemsWithKeys\"\n ref=\"chips\"\n :key=\"key\"\n :label-class=\"['d-chip__label']\"\n class=\"combobox__chip\"\n :close-button-props=\"{ ariaLabel: 'close' }\"\n :size=\"CHIP_SIZES[size]\"\n v-on=\"chipListeners\"\n @keyup.backspace=\"onChipRemove(item)\"\n @close=\"onChipRemove(item)\"\n >\n {{ item }}\n </dt-chip>\n </span>\n\n <dt-input\n ref=\"input\"\n v-model=\"value\"\n class=\"combobox__input\"\n :aria-label=\"label\"\n :label=\"labelVisible ? label : ''\"\n :description=\"description\"\n :placeholder=\"inputPlaceHolder\"\n :show-messages=\"showInputMessages\"\n :messages=\"inputMessages\"\n :size=\"size\"\n v-on=\"inputListeners\"\n @input=\"onInput\"\n />\n\n <dt-validation-messages\n :validation-messages=\"maxSelectedMessage\"\n :show-messages=\"showValidationMessages\"\n />\n </span>\n </template>\n\n <!-- @slot slot for popover header -->\n <template\n v-if=\"$slots.header\"\n #header\n >\n <div ref=\"header\">\n <slot name=\"header\" />\n </div>\n </template>\n\n <!-- @slot slot for popover list -->\n <template #list>\n <div\n ref=\"list\"\n @mousedown.prevent\n >\n <slot\n v-if=\"!loading\"\n name=\"list\"\n />\n <div\n v-else\n class=\"combobox__list--loading\"\n >\n {{ loadingMessage }}\n </div>\n </div>\n </template>\n\n <!-- @slot slot for popover footer -->\n <template\n v-if=\"$slots.footer\"\n #footer\n >\n <div ref=\"footer\">\n <slot name=\"footer\" />\n </div>\n </template>\n </dt-recipe-combobox-with-popover>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport DtRecipeComboboxWithPopover from '@/recipes/comboboxes/combobox_with_popover/combobox_with_popover.vue';\nimport DtInput from '@/components/input/input.vue';\nimport DtChip from '@/components/chip/chip.vue';\nimport DtValidationMessages from '@/components/validation_messages/validation_messages.vue';\nimport { validationMessageValidator } from '@/common/validators';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '@/components/popover/popover_constants';\nimport {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n} from './combobox_multi_select_constants';\nimport SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';\nimport { getUniqueString } from '@/common/utils';\n\nexport default {\n name: 'DtRecipeComboboxMultiSelect',\n\n components: {\n DtRecipeComboboxWithPopover,\n DtInput,\n DtChip,\n DtValidationMessages,\n },\n\n mixins: [SrOnlyCloseButtonMixin],\n\n props: {\n /**\n * String to use for the input label.\n */\n label: {\n type: String,\n required: true,\n },\n\n /**\n * Determines visibility of input label.\n * @values true, false\n */\n labelVisible: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Description for the input\n */\n description: {\n type: String,\n default: '',\n },\n\n /**\n * Input placeholder\n */\n placeholder: {\n type: String,\n default: 'Select one or start typing',\n },\n\n /**\n * Input validation messages\n */\n inputMessages: {\n type: Array,\n default: () => [],\n validator: inputMessages => {\n return validationMessageValidator(inputMessages);\n },\n },\n\n /**\n * Show input validation message\n */\n showInputMessages: {\n type: Boolean,\n default: true,\n },\n\n // @TODO: https://dialpad.atlassian.net/browse/DP-52324\n // type: {\n // type: String,\n // values: ['input', 'select'],\n // default: 'select',\n // },\n\n /**\n * Determines if the list is loading\n */\n loading: {\n type: Boolean,\n default: false,\n },\n\n /**\n * The message when the list is loading\n */\n loadingMessage: {\n type: String,\n default: 'loading...',\n },\n\n /**\n * Determines when to show the list element and also controls the aria-expanded attribute.\n * Leaving this null will have the combobox trigger on input focus by default.\n * If you set this value, the default trigger behavior will be disabled and you can\n * control it as you need.\n */\n showList: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Determines maximum height for the popover before overflow.\n * Possible units rem|px|em\n */\n listMaxHeight: {\n type: String,\n default: '300px',\n },\n\n /**\n * The selected items\n */\n selectedItems: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Would be the maximum number of selections you can make. 0 is unlimited\n */\n maxSelected: {\n type: Number,\n default: 0,\n },\n\n /**\n * Max select message when the max selections is exceeded with the structure:\n * `[{\"message\": string, \"type\": VALIDATION_MESSAGE_TYPES }]`\n */\n maxSelectedMessage: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Displays the list when the combobox is focused, before the user has typed anything.\n * When this is enabled the list will not close after selection.\n */\n hasSuggestionList: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Size of the chip, one of `xs`, `sm`, `md`\n */\n size: {\n type: String,\n default: 'md',\n validator: (t) => Object.values(MULTI_SELECT_SIZES).includes(t),\n },\n\n /**\n * Sets the element to which the popover is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Named transition when the content display is toggled.\n * @see DtLazyShow\n */\n transition: {\n type: String,\n default: 'fade',\n },\n\n /**\n * Determines whether the combobox should collapse to a single when losing focus.\n * @type {boolean}\n */\n collapseOnFocusOut: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native input event\n *\n * @event input\n * @type {String }\n */\n 'input',\n\n /**\n * Event fired when item selected\n *\n * @event select\n * @type {Number}\n */\n 'select',\n\n /**\n * Event fired when item removed\n *\n * @event remove\n * @type {String}\n */\n 'remove',\n\n /**\n * Event fired when max selected items limit is reached\n *\n * @event max-selected\n * @type {Object}\n */\n 'max-selected',\n\n /**\n * Native keyup event\n *\n * @event keyup\n * @type {KeyboardEvent}\n */\n 'keyup',\n ],\n\n data () {\n return {\n value: '',\n popoverOffset: [0, 4],\n showValidationMessages: false,\n resizeWindowObserver: null,\n initialInputHeight: null,\n CHIP_SIZES,\n inputFocused: false,\n };\n },\n\n computed: {\n inputPlaceHolder () {\n return this.selectedItems?.length > 0 ? '' : this.placeholder;\n },\n\n chipListeners () {\n return {\n ...this.$listeners,\n keyup: event => {\n this.onChipKeyup(event);\n this.$emit('keyup', event);\n },\n };\n },\n\n inputListeners () {\n return {\n ...this.$listeners,\n input: event => {\n this.$emit('input', event);\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n\n keyup: event => {\n this.onInputKeyup(event);\n this.$emit('keyup', event);\n },\n\n click: event => {\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n };\n },\n\n selectedItemsWithKeys () {\n return this.selectedItems.map(selectedItem => ({\n item: selectedItem,\n key: getUniqueString(selectedItem),\n }));\n },\n\n chipWrapperClass () {\n return {\n [`combobox__chip-wrapper-${this.size}--collapsed`]: !this.inputFocused && this.collapseOnFocusOut,\n };\n },\n },\n\n watch: {\n selectedItems: {\n async handler () {\n this.initSelectedItems();\n },\n },\n\n async label () {\n await this.$nextTick();\n // Adjust the chips position if label changed\n this.setChipsTopPosition();\n },\n\n async description () {\n await this.$nextTick();\n // Adjust the chips position if description changed\n this.setChipsTopPosition();\n },\n\n size: {\n async handler () {\n await this.$nextTick();\n const input = this.getInput();\n this.revertInputPadding(input);\n this.initialInputHeight = input.getBoundingClientRect().height;\n this.setInputPadding();\n this.setChipsTopPosition();\n },\n },\n },\n\n mounted () {\n this.setInitialInputHeight();\n // Recalculate chip position and input padding when resizing window\n this.resizeWindowObserver = new ResizeObserver(async () => {\n this.setChipsTopPosition();\n this.setInputPadding();\n });\n this.resizeWindowObserver.observe(document.body);\n\n this.initSelectedItems();\n },\n\n beforeDestroy () {\n this.resizeWindowObserver?.unobserve(document.body);\n },\n\n methods: {\n async initSelectedItems () {\n await this.$nextTick();\n this.setInputPadding();\n this.setChipsTopPosition();\n this.setInputMinWidth();\n this.checkMaxSelected();\n },\n\n onChipRemove (item) {\n this.$emit('remove', item);\n this.$refs.input?.focus();\n },\n\n onComboboxSelect (i) {\n this.value = '';\n this.$emit('select', i);\n },\n\n showComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.showComboboxList();\n },\n\n closeComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.closeComboboxList();\n },\n\n getChipButtons () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el.querySelector('button'));\n },\n\n getChips () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el);\n },\n\n getLastChipButton () {\n return this.$refs.chips && this.getChipButtons()[this.getChipButtons().length - 1];\n },\n\n getLastChip () {\n return this.$refs.chips && this.getChips()[this.getChips().length - 1];\n },\n\n getFirstChip () {\n return this.$refs.chips && this.getChips()[0];\n },\n\n getInput () {\n return this.$refs.input?.$refs.input;\n },\n\n onChipKeyup (event) {\n const key = event.code?.toLowerCase();\n if (key === 'arrowleft') {\n // Move to the previous chip\n this.navigateBetweenChips(event.target, true);\n } else if (key === 'arrowright') {\n if (event.target.id === this.getLastChipButton().id) {\n // Move to the input if it's the last chip\n this.moveFromChipToInput();\n } else {\n // Move to the next chip\n this.navigateBetweenChips(event.target, false);\n }\n }\n },\n\n onInputKeyup (event) {\n const key = event.code?.toLowerCase();\n // If the cursor is at the start of the text,\n // press 'backspace' or 'left' focuses the last chip\n if (this.selectedItems.length > 0 && event.target.selectionStart === 0) {\n if (key === 'backspace' || key === 'arrowleft') {\n this.moveFromInputToChip();\n }\n }\n },\n\n moveFromInputToChip () {\n this.getLastChipButton().focus();\n this.$refs.input?.blur();\n this.closeComboboxList();\n },\n\n moveFromChipToInput () {\n this.getLastChipButton().blur();\n this.$refs.input?.focus();\n this.showComboboxList();\n },\n\n navigateBetweenChips (target, toLeft) {\n const from = this.getChipButtons().indexOf(target);\n const to = toLeft ? from - 1 : from + 1;\n if (to < 0 || to >= this.$refs.chips?.length) {\n return;\n }\n this.getChipButtons()[from].blur();\n this.getChipButtons()[to].focus();\n this.closeComboboxList();\n },\n\n setChipsTopPosition () {\n // To place the chips in the input box\n // The chip \"top\" position should be the same line as the input box\n const input = this.getInput();\n if (!input) return;\n const inputSlotWrapper = this.$refs.inputSlotWrapper;\n const top = input.getBoundingClientRect().top -\n inputSlotWrapper.getBoundingClientRect().top;\n const chipsWrapper = this.$refs.chipsWrapper;\n chipsWrapper.style.top = (top - CHIP_TOP_POSITION[this.size]) + 'px';\n },\n\n setInputPadding () {\n const lastChip = this.getLastChip();\n const input = this.getInput();\n const chipsWrapper = this.$refs.chipsWrapper;\n if (!input) return;\n this.revertInputPadding(input);\n this.popoverOffset = [0, 4];\n if (!lastChip) return;\n\n // Get the position of the last chip\n // The input cursor should be the same \"top\" as that chip and next besides it\n const left = lastChip.offsetLeft + this.getFullWidth(lastChip);\n input.style.paddingLeft = left + 'px';\n\n // Get the chip size minus the 4px padding\n const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;\n\n // Get lastChip offsetTop plus 2px of the input padding.\n const top = lastChip.offsetTop + 2;\n\n // Add padding to Top only if the chips need more space\n if (chipsSize > this.initialInputHeight) {\n input.style.paddingTop = `${top}px`;\n }\n },\n\n revertInputPadding (input) {\n input.style.paddingLeft = '';\n input.style.paddingTop = '';\n input.style.paddingBottom = '';\n },\n\n getFullWidth (el) {\n const styles = window.getComputedStyle(el);\n return el.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);\n },\n\n setInputMinWidth () {\n // Ensure the width of the input is \"slightly bigger\" than the width of a single chip\n const firstChip = this.getFirstChip();\n const input = this.getInput();\n if (!input) return;\n if (firstChip) {\n // Add 4px buffer for typing room\n input.style.minWidth = (this.getFullWidth(firstChip) + 4) + 'px';\n } else {\n input.style.minWidth = '';\n }\n },\n\n checkMaxSelected () {\n if (this.maxSelected === 0) return;\n if (this.selectedItems.length > this.maxSelected) {\n this.showValidationMessages = true;\n this.$emit('max-selected');\n } else {\n this.showValidationMessages = false;\n }\n },\n\n setInitialInputHeight () {\n const input = this.getInput();\n if (!input) return;\n this.initialInputHeight = input.getBoundingClientRect().height;\n },\n\n async handleInputFocusIn () {\n this.inputFocused = true;\n if (this.collapseOnFocusOut) {\n await this.$nextTick();\n this.setInputPadding();\n }\n },\n\n async handleInputFocusOut () {\n this.inputFocused = false;\n if (this.collapseOnFocusOut) {\n const input = this.getInput();\n if (!input) return;\n this.revertInputPadding(input);\n }\n },\n },\n};\n</script>\n\n<style scoped lang=\"less\">\n.combobox__input-wrapper {\n position: relative;\n display: block;\n}\n\n.combobox__chip-wrapper {\n position: absolute;\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n padding-left: var(--dt-space-100);\n max-width: calc(var(--dt-size-100-percent) - var(--dt-space-400));\n max-height: initial;\n overflow-y: visible;\n}\n\n.combobox__chip-wrapper-md--collapsed {\n max-height: 2.8rem;\n overflow-y: hidden;\n}\n\n.combobox__chip-wrapper-sm--collapsed,\n.combobox__chip-wrapper-xs--collapsed {\n max-height: 2.5rem;\n overflow-y: hidden;\n}\n\n.combobox__chip {\n margin-top: var(--dt-space-300);\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n z-index: var(--zi-base1);\n max-width: var(--dt-size-100-percent);\n}\n\n.combobox__input {\n flex-grow: 1;\n}\n\n.combobox__list--loading {\n text-align: center;\n padding-top: var(--dt-space-500);\n padding-bottom: var(--dt-space-500);\n}\n</style>\n"],"names":["DtRecipeComboboxWithPopover","DtInput","DtChip","DtValidationMessages","SrOnlyCloseButtonMixin","validationMessageValidator","POPOVER_APPEND_TO_VALUES","getUniqueString"],"mappings":"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"}
@@ -199,6 +199,14 @@ const _sfc_main = {
199
199
  transition: {
200
200
  type: String,
201
201
  default: "fade"
202
+ },
203
+ /**
204
+ * Determines whether the combobox should collapse to a single when losing focus.
205
+ * @type {boolean}
206
+ */
207
+ collapseOnFocusOut: {
208
+ type: Boolean,
209
+ default: false
202
210
  }
203
211
  },
204
212
  emits: [
@@ -243,10 +251,10 @@ const _sfc_main = {
243
251
  value: "",
244
252
  popoverOffset: [0, 4],
245
253
  showValidationMessages: false,
246
- initialInputPadding: {},
247
254
  resizeWindowObserver: null,
248
- originalInputSize: null,
249
- CHIP_SIZES
255
+ initialInputHeight: null,
256
+ CHIP_SIZES,
257
+ inputFocused: false
250
258
  };
251
259
  },
252
260
  computed: {
@@ -288,6 +296,11 @@ const _sfc_main = {
288
296
  item: selectedItem,
289
297
  key: getUniqueString(selectedItem)
290
298
  }));
299
+ },
300
+ chipWrapperClass() {
301
+ return {
302
+ [`combobox__chip-wrapper-${this.size}--collapsed`]: !this.inputFocused && this.collapseOnFocusOut
303
+ };
291
304
  }
292
305
  },
293
306
  watch: {
@@ -309,13 +322,14 @@ const _sfc_main = {
309
322
  await this.$nextTick();
310
323
  const input = this.getInput();
311
324
  this.revertInputPadding(input);
312
- this.originalInputSize = input.getBoundingClientRect().height;
325
+ this.initialInputHeight = input.getBoundingClientRect().height;
313
326
  this.setInputPadding();
314
327
  this.setChipsTopPosition();
315
328
  }
316
329
  }
317
330
  },
318
331
  mounted() {
332
+ this.setInitialInputHeight();
319
333
  this.resizeWindowObserver = new ResizeObserver(async () => {
320
334
  this.setChipsTopPosition();
321
335
  this.setInputPadding();
@@ -445,7 +459,7 @@ const _sfc_main = {
445
459
  input.style.paddingLeft = left + "px";
446
460
  const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;
447
461
  const top = lastChip.offsetTop + 2;
448
- if (chipsSize > this.originalInputSize) {
462
+ if (chipsSize > this.initialInputHeight) {
449
463
  input.style.paddingTop = `${top}px`;
450
464
  }
451
465
  },
@@ -478,13 +492,35 @@ const _sfc_main = {
478
492
  } else {
479
493
  this.showValidationMessages = false;
480
494
  }
495
+ },
496
+ setInitialInputHeight() {
497
+ const input = this.getInput();
498
+ if (!input)
499
+ return;
500
+ this.initialInputHeight = input.getBoundingClientRect().height;
501
+ },
502
+ async handleInputFocusIn() {
503
+ this.inputFocused = true;
504
+ if (this.collapseOnFocusOut) {
505
+ await this.$nextTick();
506
+ this.setInputPadding();
507
+ }
508
+ },
509
+ async handleInputFocusOut() {
510
+ this.inputFocused = false;
511
+ if (this.collapseOnFocusOut) {
512
+ const input = this.getInput();
513
+ if (!input)
514
+ return;
515
+ this.revertInputPadding(input);
516
+ }
481
517
  }
482
518
  }
483
519
  };
484
520
  var _sfc_render = function render() {
485
521
  var _vm = this, _c = _vm._self._c;
486
522
  return _c("dt-recipe-combobox-with-popover", { ref: "comboboxWithPopover", attrs: { "label": _vm.label, "show-list": _vm.showList, "max-height": _vm.listMaxHeight, "popover-offset": _vm.popoverOffset, "has-suggestion-list": _vm.hasSuggestionList, "visually-hidden-close-label": _vm.visuallyHiddenCloseLabel, "visually-hidden-close": _vm.visuallyHiddenClose, "content-width": "anchor", "append-to": _vm.appendTo, "transition": _vm.transition }, on: { "select": _vm.onComboboxSelect }, scopedSlots: _vm._u([{ key: "input", fn: function({ onInput }) {
487
- return [_c("span", { ref: "inputSlotWrapper", staticClass: "combobox__input-wrapper" }, [_c("span", { ref: "chipsWrapper", staticClass: "combobox__chip-wrapper" }, _vm._l(_vm.selectedItemsWithKeys, function({ item, key }) {
523
+ return [_c("span", { ref: "inputSlotWrapper", staticClass: "combobox__input-wrapper", on: { "focusin": _vm.handleInputFocusIn, "focusout": _vm.handleInputFocusOut } }, [_c("span", { ref: "chipsWrapper", class: ["combobox__chip-wrapper", _vm.chipWrapperClass] }, _vm._l(_vm.selectedItemsWithKeys, function({ item, key }) {
488
524
  return _c("dt-chip", _vm._g({ key, ref: "chips", refInFor: true, staticClass: "combobox__chip", attrs: { "label-class": ["d-chip__label"], "close-button-props": { ariaLabel: "close" }, "size": _vm.CHIP_SIZES[_vm.size] }, on: { "keyup": function($event) {
489
525
  if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "backspace", void 0, $event.key, void 0))
490
526
  return null;
@@ -512,7 +548,7 @@ var __component__ = /* @__PURE__ */ normalizeComponent(
512
548
  _sfc_staticRenderFns,
513
549
  false,
514
550
  null,
515
- "7d72ca8b",
551
+ "5c09d325",
516
552
  null,
517
553
  null
518
554
  );
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-multi-select.js","sources":["../../recipes/comboboxes/combobox_multi_select/combobox_multi_select_constants.js","../../recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue"],"sourcesContent":["export const MULTI_SELECT_SIZES = {\n // Chip has no 'lg' and 'xl' size. So we don't support that in multi-select.\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n DEFAULT: 'md',\n};\n\nexport const CHIP_SIZES = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n};\n\nexport const CHIP_TOP_POSITION = {\n xs: 1.4,\n sm: 0.4,\n md: 0.2,\n};\n\nexport default {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n};\n","<template>\n <dt-recipe-combobox-with-popover\n ref=\"comboboxWithPopover\"\n :label=\"label\"\n :show-list=\"showList\"\n :max-height=\"listMaxHeight\"\n :popover-offset=\"popoverOffset\"\n :has-suggestion-list=\"hasSuggestionList\"\n :visually-hidden-close-label=\"visuallyHiddenCloseLabel\"\n :visually-hidden-close=\"visuallyHiddenClose\"\n content-width=\"anchor\"\n :append-to=\"appendTo\"\n :transition=\"transition\"\n @select=\"onComboboxSelect\"\n >\n <template #input=\"{ onInput }\">\n <span\n ref=\"inputSlotWrapper\"\n class=\"combobox__input-wrapper\"\n >\n <span\n ref=\"chipsWrapper\"\n class=\"combobox__chip-wrapper\"\n >\n <dt-chip\n v-for=\"({ item, key }) in selectedItemsWithKeys\"\n ref=\"chips\"\n :key=\"key\"\n :label-class=\"['d-chip__label']\"\n class=\"combobox__chip\"\n :close-button-props=\"{ ariaLabel: 'close' }\"\n :size=\"CHIP_SIZES[size]\"\n v-on=\"chipListeners\"\n @keyup.backspace=\"onChipRemove(item)\"\n @close=\"onChipRemove(item)\"\n >\n {{ item }}\n </dt-chip>\n </span>\n\n <dt-input\n ref=\"input\"\n v-model=\"value\"\n class=\"combobox__input\"\n :aria-label=\"label\"\n :label=\"labelVisible ? label : ''\"\n :description=\"description\"\n :placeholder=\"inputPlaceHolder\"\n :show-messages=\"showInputMessages\"\n :messages=\"inputMessages\"\n :size=\"size\"\n v-on=\"inputListeners\"\n @input=\"onInput\"\n />\n\n <dt-validation-messages\n :validation-messages=\"maxSelectedMessage\"\n :show-messages=\"showValidationMessages\"\n />\n </span>\n </template>\n\n <!-- @slot slot for popover header -->\n <template\n v-if=\"$slots.header\"\n #header\n >\n <div ref=\"header\">\n <slot name=\"header\" />\n </div>\n </template>\n\n <!-- @slot slot for popover list -->\n <template #list>\n <div\n ref=\"list\"\n @mousedown.prevent\n >\n <slot\n v-if=\"!loading\"\n name=\"list\"\n />\n <div\n v-else\n class=\"combobox__list--loading\"\n >\n {{ loadingMessage }}\n </div>\n </div>\n </template>\n\n <!-- @slot slot for popover footer -->\n <template\n v-if=\"$slots.footer\"\n #footer\n >\n <div ref=\"footer\">\n <slot name=\"footer\" />\n </div>\n </template>\n </dt-recipe-combobox-with-popover>\n</template>\n\n<script>\nimport DtRecipeComboboxWithPopover from '@/recipes/comboboxes/combobox_with_popover/combobox_with_popover.vue';\nimport DtInput from '@/components/input/input.vue';\nimport DtChip from '@/components/chip/chip.vue';\nimport DtValidationMessages from '@/components/validation_messages/validation_messages.vue';\nimport { validationMessageValidator } from '@/common/validators';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '@/components/popover/popover_constants';\nimport {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n} from './combobox_multi_select_constants';\nimport SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';\nimport { getUniqueString } from '@/common/utils';\n\nexport default {\n name: 'DtRecipeComboboxMultiSelect',\n\n components: {\n DtRecipeComboboxWithPopover,\n DtInput,\n DtChip,\n DtValidationMessages,\n },\n\n mixins: [SrOnlyCloseButtonMixin],\n\n props: {\n /**\n * String to use for the input label.\n */\n label: {\n type: String,\n required: true,\n },\n\n /**\n * Determines visibility of input label.\n * @values true, false\n */\n labelVisible: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Description for the input\n */\n description: {\n type: String,\n default: '',\n },\n\n /**\n * Input placeholder\n */\n placeholder: {\n type: String,\n default: 'Select one or start typing',\n },\n\n /**\n * Input validation messages\n */\n inputMessages: {\n type: Array,\n default: () => [],\n validator: inputMessages => {\n return validationMessageValidator(inputMessages);\n },\n },\n\n /**\n * Show input validation message\n */\n showInputMessages: {\n type: Boolean,\n default: true,\n },\n\n // @TODO: https://dialpad.atlassian.net/browse/DP-52324\n // type: {\n // type: String,\n // values: ['input', 'select'],\n // default: 'select',\n // },\n\n /**\n * Determines if the list is loading\n */\n loading: {\n type: Boolean,\n default: false,\n },\n\n /**\n * The message when the list is loading\n */\n loadingMessage: {\n type: String,\n default: 'loading...',\n },\n\n /**\n * Determines when to show the list element and also controls the aria-expanded attribute.\n * Leaving this null will have the combobox trigger on input focus by default.\n * If you set this value, the default trigger behavior will be disabled and you can\n * control it as you need.\n */\n showList: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Determines maximum height for the popover before overflow.\n * Possible units rem|px|em\n */\n listMaxHeight: {\n type: String,\n default: '300px',\n },\n\n /**\n * The selected items\n */\n selectedItems: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Would be the maximum number of selections you can make. 0 is unlimited\n */\n maxSelected: {\n type: Number,\n default: 0,\n },\n\n /**\n * Max select message when the max selections is exceeded with the structure:\n * `[{\"message\": string, \"type\": VALIDATION_MESSAGE_TYPES }]`\n */\n maxSelectedMessage: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Displays the list when the combobox is focused, before the user has typed anything.\n * When this is enabled the list will not close after selection.\n */\n hasSuggestionList: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Size of the chip, one of `xs`, `sm`, `md`\n */\n size: {\n type: String,\n default: 'md',\n validator: (t) => Object.values(MULTI_SELECT_SIZES).includes(t),\n },\n\n /**\n * Sets the element to which the popover is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Named transition when the content display is toggled.\n * @see DtLazyShow\n */\n transition: {\n type: String,\n default: 'fade',\n },\n },\n\n emits: [\n /**\n * Native input event\n *\n * @event input\n * @type {String }\n */\n 'input',\n\n /**\n * Event fired when item selected\n *\n * @event select\n * @type {Number}\n */\n 'select',\n\n /**\n * Event fired when item removed\n *\n * @event remove\n * @type {String}\n */\n 'remove',\n\n /**\n * Event fired when max selected items limit is reached\n *\n * @event max-selected\n * @type {Object}\n */\n 'max-selected',\n\n /**\n * Native keyup event\n *\n * @event keyup\n * @type {KeyboardEvent}\n */\n 'keyup',\n ],\n\n data () {\n return {\n value: '',\n popoverOffset: [0, 4],\n showValidationMessages: false,\n initialInputPadding: {},\n resizeWindowObserver: null,\n originalInputSize: null,\n CHIP_SIZES,\n };\n },\n\n computed: {\n inputPlaceHolder () {\n return this.selectedItems?.length > 0 ? '' : this.placeholder;\n },\n\n chipListeners () {\n return {\n ...this.$listeners,\n keyup: event => {\n this.onChipKeyup(event);\n this.$emit('keyup', event);\n },\n };\n },\n\n inputListeners () {\n return {\n ...this.$listeners,\n input: event => {\n this.$emit('input', event);\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n\n keyup: event => {\n this.onInputKeyup(event);\n this.$emit('keyup', event);\n },\n\n click: event => {\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n };\n },\n\n selectedItemsWithKeys () {\n return this.selectedItems.map(selectedItem => ({\n item: selectedItem,\n key: getUniqueString(selectedItem),\n }));\n },\n },\n\n watch: {\n selectedItems: {\n async handler () {\n this.initSelectedItems();\n },\n },\n\n async label () {\n await this.$nextTick();\n // Adjust the chips position if label changed\n this.setChipsTopPosition();\n },\n\n async description () {\n await this.$nextTick();\n // Adjust the chips position if description changed\n this.setChipsTopPosition();\n },\n\n size: {\n async handler () {\n await this.$nextTick();\n const input = this.getInput();\n this.revertInputPadding(input);\n this.originalInputSize = input.getBoundingClientRect().height;\n this.setInputPadding();\n this.setChipsTopPosition();\n },\n },\n },\n\n mounted () {\n // Recalculate chip position and input padding when resizing window\n this.resizeWindowObserver = new ResizeObserver(async () => {\n this.setChipsTopPosition();\n this.setInputPadding();\n });\n this.resizeWindowObserver.observe(document.body);\n\n this.initSelectedItems();\n },\n\n beforeDestroy () {\n this.resizeWindowObserver?.unobserve(document.body);\n },\n\n methods: {\n async initSelectedItems () {\n await this.$nextTick();\n this.setInputPadding();\n this.setChipsTopPosition();\n this.setInputMinWidth();\n this.checkMaxSelected();\n },\n\n onChipRemove (item) {\n this.$emit('remove', item);\n this.$refs.input?.focus();\n },\n\n onComboboxSelect (i) {\n this.value = '';\n this.$emit('select', i);\n },\n\n showComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.showComboboxList();\n },\n\n closeComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.closeComboboxList();\n },\n\n getChipButtons () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el.querySelector('button'));\n },\n\n getChips () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el);\n },\n\n getLastChipButton () {\n return this.$refs.chips && this.getChipButtons()[this.getChipButtons().length - 1];\n },\n\n getLastChip () {\n return this.$refs.chips && this.getChips()[this.getChips().length - 1];\n },\n\n getFirstChip () {\n return this.$refs.chips && this.getChips()[0];\n },\n\n getInput () {\n return this.$refs.input?.$refs.input;\n },\n\n onChipKeyup (event) {\n const key = event.code?.toLowerCase();\n if (key === 'arrowleft') {\n // Move to the previous chip\n this.navigateBetweenChips(event.target, true);\n } else if (key === 'arrowright') {\n if (event.target.id === this.getLastChipButton().id) {\n // Move to the input if it's the last chip\n this.moveFromChipToInput();\n } else {\n // Move to the next chip\n this.navigateBetweenChips(event.target, false);\n }\n }\n },\n\n onInputKeyup (event) {\n const key = event.code?.toLowerCase();\n // If the cursor is at the start of the text,\n // press 'backspace' or 'left' focuses the last chip\n if (this.selectedItems.length > 0 && event.target.selectionStart === 0) {\n if (key === 'backspace' || key === 'arrowleft') {\n this.moveFromInputToChip();\n }\n }\n },\n\n moveFromInputToChip () {\n this.getLastChipButton().focus();\n this.$refs.input?.blur();\n this.closeComboboxList();\n },\n\n moveFromChipToInput () {\n this.getLastChipButton().blur();\n this.$refs.input?.focus();\n this.showComboboxList();\n },\n\n navigateBetweenChips (target, toLeft) {\n const from = this.getChipButtons().indexOf(target);\n const to = toLeft ? from - 1 : from + 1;\n if (to < 0 || to >= this.$refs.chips?.length) {\n return;\n }\n this.getChipButtons()[from].blur();\n this.getChipButtons()[to].focus();\n this.closeComboboxList();\n },\n\n setChipsTopPosition () {\n // To place the chips in the input box\n // The chip \"top\" position should be the same line as the input box\n const input = this.getInput();\n if (!input) return;\n const inputSlotWrapper = this.$refs.inputSlotWrapper;\n const top = input.getBoundingClientRect().top -\n inputSlotWrapper.getBoundingClientRect().top;\n const chipsWrapper = this.$refs.chipsWrapper;\n chipsWrapper.style.top = (top - CHIP_TOP_POSITION[this.size]) + 'px';\n },\n\n setInputPadding () {\n const lastChip = this.getLastChip();\n const input = this.getInput();\n const chipsWrapper = this.$refs.chipsWrapper;\n if (!input) return;\n this.revertInputPadding(input);\n this.popoverOffset = [0, 4];\n if (!lastChip) return;\n\n // Get the position of the last chip\n // The input cursor should be the same \"top\" as that chip and next besides it\n const left = lastChip.offsetLeft + this.getFullWidth(lastChip);\n input.style.paddingLeft = left + 'px';\n\n // Get the chip size minus the 4px padding\n const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;\n\n // Get lastChip offsetTop plus 2px of the input padding.\n const top = lastChip.offsetTop + 2;\n\n // Add padding to Top only if the chips need more space\n if (chipsSize > this.originalInputSize) {\n input.style.paddingTop = `${top}px`;\n }\n },\n\n revertInputPadding (input) {\n input.style.paddingLeft = '';\n input.style.paddingTop = '';\n input.style.paddingBottom = '';\n },\n\n getFullWidth (el) {\n const styles = window.getComputedStyle(el);\n return el.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);\n },\n\n setInputMinWidth () {\n // Ensure the width of the input is \"slightly bigger\" than the width of a single chip\n const firstChip = this.getFirstChip();\n const input = this.getInput();\n if (!input) return;\n if (firstChip) {\n // Add 4px buffer for typing room\n input.style.minWidth = (this.getFullWidth(firstChip) + 4) + 'px';\n } else {\n input.style.minWidth = '';\n }\n },\n\n checkMaxSelected () {\n if (this.maxSelected === 0) return;\n if (this.selectedItems.length > this.maxSelected) {\n this.showValidationMessages = true;\n this.$emit('max-selected');\n } else {\n this.showValidationMessages = false;\n }\n },\n },\n};\n</script>\n\n<style scoped lang=\"less\">\n.combobox__input-wrapper {\n position: relative;\n display: block;\n}\n\n.combobox__chip-wrapper {\n position: absolute;\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n padding-left: var(--dt-space-100);\n max-width: calc(var(--dt-size-100-percent) - var(--dt-space-400));\n}\n\n.combobox__chip {\n margin-top: var(--dt-space-300);\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n z-index: var(--zi-base1);\n max-width: var(--dt-size-100-percent);\n}\n\n.combobox__input {\n flex-grow: 1;\n}\n\n.combobox__list--loading {\n text-align: center;\n padding-top: var(--dt-space-500);\n padding-bottom: var(--dt-space-500);\n}\n</style>\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox-multi-select.js","sources":["../../recipes/comboboxes/combobox_multi_select/combobox_multi_select_constants.js","../../recipes/comboboxes/combobox_multi_select/combobox_multi_select.vue"],"sourcesContent":["export const MULTI_SELECT_SIZES = {\n // Chip has no 'lg' and 'xl' size. So we don't support that in multi-select.\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n DEFAULT: 'md',\n};\n\nexport const CHIP_SIZES = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n};\n\nexport const CHIP_TOP_POSITION = {\n xs: 1.4,\n sm: 0.4,\n md: 0.2,\n};\n\nexport default {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n};\n","<template>\n <dt-recipe-combobox-with-popover\n ref=\"comboboxWithPopover\"\n :label=\"label\"\n :show-list=\"showList\"\n :max-height=\"listMaxHeight\"\n :popover-offset=\"popoverOffset\"\n :has-suggestion-list=\"hasSuggestionList\"\n :visually-hidden-close-label=\"visuallyHiddenCloseLabel\"\n :visually-hidden-close=\"visuallyHiddenClose\"\n content-width=\"anchor\"\n :append-to=\"appendTo\"\n :transition=\"transition\"\n @select=\"onComboboxSelect\"\n >\n <template #input=\"{ onInput }\">\n <span\n ref=\"inputSlotWrapper\"\n class=\"combobox__input-wrapper\"\n @focusin=\"handleInputFocusIn\"\n @focusout=\"handleInputFocusOut\"\n >\n <span\n ref=\"chipsWrapper\"\n :class=\"['combobox__chip-wrapper', chipWrapperClass]\"\n >\n <dt-chip\n v-for=\"({ item, key }) in selectedItemsWithKeys\"\n ref=\"chips\"\n :key=\"key\"\n :label-class=\"['d-chip__label']\"\n class=\"combobox__chip\"\n :close-button-props=\"{ ariaLabel: 'close' }\"\n :size=\"CHIP_SIZES[size]\"\n v-on=\"chipListeners\"\n @keyup.backspace=\"onChipRemove(item)\"\n @close=\"onChipRemove(item)\"\n >\n {{ item }}\n </dt-chip>\n </span>\n\n <dt-input\n ref=\"input\"\n v-model=\"value\"\n class=\"combobox__input\"\n :aria-label=\"label\"\n :label=\"labelVisible ? label : ''\"\n :description=\"description\"\n :placeholder=\"inputPlaceHolder\"\n :show-messages=\"showInputMessages\"\n :messages=\"inputMessages\"\n :size=\"size\"\n v-on=\"inputListeners\"\n @input=\"onInput\"\n />\n\n <dt-validation-messages\n :validation-messages=\"maxSelectedMessage\"\n :show-messages=\"showValidationMessages\"\n />\n </span>\n </template>\n\n <!-- @slot slot for popover header -->\n <template\n v-if=\"$slots.header\"\n #header\n >\n <div ref=\"header\">\n <slot name=\"header\" />\n </div>\n </template>\n\n <!-- @slot slot for popover list -->\n <template #list>\n <div\n ref=\"list\"\n @mousedown.prevent\n >\n <slot\n v-if=\"!loading\"\n name=\"list\"\n />\n <div\n v-else\n class=\"combobox__list--loading\"\n >\n {{ loadingMessage }}\n </div>\n </div>\n </template>\n\n <!-- @slot slot for popover footer -->\n <template\n v-if=\"$slots.footer\"\n #footer\n >\n <div ref=\"footer\">\n <slot name=\"footer\" />\n </div>\n </template>\n </dt-recipe-combobox-with-popover>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport DtRecipeComboboxWithPopover from '@/recipes/comboboxes/combobox_with_popover/combobox_with_popover.vue';\nimport DtInput from '@/components/input/input.vue';\nimport DtChip from '@/components/chip/chip.vue';\nimport DtValidationMessages from '@/components/validation_messages/validation_messages.vue';\nimport { validationMessageValidator } from '@/common/validators';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '@/components/popover/popover_constants';\nimport {\n MULTI_SELECT_SIZES,\n CHIP_SIZES,\n CHIP_TOP_POSITION,\n} from './combobox_multi_select_constants';\nimport SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';\nimport { getUniqueString } from '@/common/utils';\n\nexport default {\n name: 'DtRecipeComboboxMultiSelect',\n\n components: {\n DtRecipeComboboxWithPopover,\n DtInput,\n DtChip,\n DtValidationMessages,\n },\n\n mixins: [SrOnlyCloseButtonMixin],\n\n props: {\n /**\n * String to use for the input label.\n */\n label: {\n type: String,\n required: true,\n },\n\n /**\n * Determines visibility of input label.\n * @values true, false\n */\n labelVisible: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Description for the input\n */\n description: {\n type: String,\n default: '',\n },\n\n /**\n * Input placeholder\n */\n placeholder: {\n type: String,\n default: 'Select one or start typing',\n },\n\n /**\n * Input validation messages\n */\n inputMessages: {\n type: Array,\n default: () => [],\n validator: inputMessages => {\n return validationMessageValidator(inputMessages);\n },\n },\n\n /**\n * Show input validation message\n */\n showInputMessages: {\n type: Boolean,\n default: true,\n },\n\n // @TODO: https://dialpad.atlassian.net/browse/DP-52324\n // type: {\n // type: String,\n // values: ['input', 'select'],\n // default: 'select',\n // },\n\n /**\n * Determines if the list is loading\n */\n loading: {\n type: Boolean,\n default: false,\n },\n\n /**\n * The message when the list is loading\n */\n loadingMessage: {\n type: String,\n default: 'loading...',\n },\n\n /**\n * Determines when to show the list element and also controls the aria-expanded attribute.\n * Leaving this null will have the combobox trigger on input focus by default.\n * If you set this value, the default trigger behavior will be disabled and you can\n * control it as you need.\n */\n showList: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Determines maximum height for the popover before overflow.\n * Possible units rem|px|em\n */\n listMaxHeight: {\n type: String,\n default: '300px',\n },\n\n /**\n * The selected items\n */\n selectedItems: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Would be the maximum number of selections you can make. 0 is unlimited\n */\n maxSelected: {\n type: Number,\n default: 0,\n },\n\n /**\n * Max select message when the max selections is exceeded with the structure:\n * `[{\"message\": string, \"type\": VALIDATION_MESSAGE_TYPES }]`\n */\n maxSelectedMessage: {\n type: Array,\n default: function () { return []; },\n },\n\n /**\n * Displays the list when the combobox is focused, before the user has typed anything.\n * When this is enabled the list will not close after selection.\n */\n hasSuggestionList: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Size of the chip, one of `xs`, `sm`, `md`\n */\n size: {\n type: String,\n default: 'md',\n validator: (t) => Object.values(MULTI_SELECT_SIZES).includes(t),\n },\n\n /**\n * Sets the element to which the popover is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Named transition when the content display is toggled.\n * @see DtLazyShow\n */\n transition: {\n type: String,\n default: 'fade',\n },\n\n /**\n * Determines whether the combobox should collapse to a single when losing focus.\n * @type {boolean}\n */\n collapseOnFocusOut: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native input event\n *\n * @event input\n * @type {String }\n */\n 'input',\n\n /**\n * Event fired when item selected\n *\n * @event select\n * @type {Number}\n */\n 'select',\n\n /**\n * Event fired when item removed\n *\n * @event remove\n * @type {String}\n */\n 'remove',\n\n /**\n * Event fired when max selected items limit is reached\n *\n * @event max-selected\n * @type {Object}\n */\n 'max-selected',\n\n /**\n * Native keyup event\n *\n * @event keyup\n * @type {KeyboardEvent}\n */\n 'keyup',\n ],\n\n data () {\n return {\n value: '',\n popoverOffset: [0, 4],\n showValidationMessages: false,\n resizeWindowObserver: null,\n initialInputHeight: null,\n CHIP_SIZES,\n inputFocused: false,\n };\n },\n\n computed: {\n inputPlaceHolder () {\n return this.selectedItems?.length > 0 ? '' : this.placeholder;\n },\n\n chipListeners () {\n return {\n ...this.$listeners,\n keyup: event => {\n this.onChipKeyup(event);\n this.$emit('keyup', event);\n },\n };\n },\n\n inputListeners () {\n return {\n ...this.$listeners,\n input: event => {\n this.$emit('input', event);\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n\n keyup: event => {\n this.onInputKeyup(event);\n this.$emit('keyup', event);\n },\n\n click: event => {\n if (this.hasSuggestionList) {\n this.showComboboxList();\n }\n },\n };\n },\n\n selectedItemsWithKeys () {\n return this.selectedItems.map(selectedItem => ({\n item: selectedItem,\n key: getUniqueString(selectedItem),\n }));\n },\n\n chipWrapperClass () {\n return {\n [`combobox__chip-wrapper-${this.size}--collapsed`]: !this.inputFocused && this.collapseOnFocusOut,\n };\n },\n },\n\n watch: {\n selectedItems: {\n async handler () {\n this.initSelectedItems();\n },\n },\n\n async label () {\n await this.$nextTick();\n // Adjust the chips position if label changed\n this.setChipsTopPosition();\n },\n\n async description () {\n await this.$nextTick();\n // Adjust the chips position if description changed\n this.setChipsTopPosition();\n },\n\n size: {\n async handler () {\n await this.$nextTick();\n const input = this.getInput();\n this.revertInputPadding(input);\n this.initialInputHeight = input.getBoundingClientRect().height;\n this.setInputPadding();\n this.setChipsTopPosition();\n },\n },\n },\n\n mounted () {\n this.setInitialInputHeight();\n // Recalculate chip position and input padding when resizing window\n this.resizeWindowObserver = new ResizeObserver(async () => {\n this.setChipsTopPosition();\n this.setInputPadding();\n });\n this.resizeWindowObserver.observe(document.body);\n\n this.initSelectedItems();\n },\n\n beforeDestroy () {\n this.resizeWindowObserver?.unobserve(document.body);\n },\n\n methods: {\n async initSelectedItems () {\n await this.$nextTick();\n this.setInputPadding();\n this.setChipsTopPosition();\n this.setInputMinWidth();\n this.checkMaxSelected();\n },\n\n onChipRemove (item) {\n this.$emit('remove', item);\n this.$refs.input?.focus();\n },\n\n onComboboxSelect (i) {\n this.value = '';\n this.$emit('select', i);\n },\n\n showComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.showComboboxList();\n },\n\n closeComboboxList () {\n if (this.showList != null) { return; }\n this.$refs.comboboxWithPopover?.closeComboboxList();\n },\n\n getChipButtons () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el.querySelector('button'));\n },\n\n getChips () {\n return this.$refs.chips && this.$refs.chips.map(chip => chip.$el);\n },\n\n getLastChipButton () {\n return this.$refs.chips && this.getChipButtons()[this.getChipButtons().length - 1];\n },\n\n getLastChip () {\n return this.$refs.chips && this.getChips()[this.getChips().length - 1];\n },\n\n getFirstChip () {\n return this.$refs.chips && this.getChips()[0];\n },\n\n getInput () {\n return this.$refs.input?.$refs.input;\n },\n\n onChipKeyup (event) {\n const key = event.code?.toLowerCase();\n if (key === 'arrowleft') {\n // Move to the previous chip\n this.navigateBetweenChips(event.target, true);\n } else if (key === 'arrowright') {\n if (event.target.id === this.getLastChipButton().id) {\n // Move to the input if it's the last chip\n this.moveFromChipToInput();\n } else {\n // Move to the next chip\n this.navigateBetweenChips(event.target, false);\n }\n }\n },\n\n onInputKeyup (event) {\n const key = event.code?.toLowerCase();\n // If the cursor is at the start of the text,\n // press 'backspace' or 'left' focuses the last chip\n if (this.selectedItems.length > 0 && event.target.selectionStart === 0) {\n if (key === 'backspace' || key === 'arrowleft') {\n this.moveFromInputToChip();\n }\n }\n },\n\n moveFromInputToChip () {\n this.getLastChipButton().focus();\n this.$refs.input?.blur();\n this.closeComboboxList();\n },\n\n moveFromChipToInput () {\n this.getLastChipButton().blur();\n this.$refs.input?.focus();\n this.showComboboxList();\n },\n\n navigateBetweenChips (target, toLeft) {\n const from = this.getChipButtons().indexOf(target);\n const to = toLeft ? from - 1 : from + 1;\n if (to < 0 || to >= this.$refs.chips?.length) {\n return;\n }\n this.getChipButtons()[from].blur();\n this.getChipButtons()[to].focus();\n this.closeComboboxList();\n },\n\n setChipsTopPosition () {\n // To place the chips in the input box\n // The chip \"top\" position should be the same line as the input box\n const input = this.getInput();\n if (!input) return;\n const inputSlotWrapper = this.$refs.inputSlotWrapper;\n const top = input.getBoundingClientRect().top -\n inputSlotWrapper.getBoundingClientRect().top;\n const chipsWrapper = this.$refs.chipsWrapper;\n chipsWrapper.style.top = (top - CHIP_TOP_POSITION[this.size]) + 'px';\n },\n\n setInputPadding () {\n const lastChip = this.getLastChip();\n const input = this.getInput();\n const chipsWrapper = this.$refs.chipsWrapper;\n if (!input) return;\n this.revertInputPadding(input);\n this.popoverOffset = [0, 4];\n if (!lastChip) return;\n\n // Get the position of the last chip\n // The input cursor should be the same \"top\" as that chip and next besides it\n const left = lastChip.offsetLeft + this.getFullWidth(lastChip);\n input.style.paddingLeft = left + 'px';\n\n // Get the chip size minus the 4px padding\n const chipsSize = chipsWrapper.getBoundingClientRect().height - 4;\n\n // Get lastChip offsetTop plus 2px of the input padding.\n const top = lastChip.offsetTop + 2;\n\n // Add padding to Top only if the chips need more space\n if (chipsSize > this.initialInputHeight) {\n input.style.paddingTop = `${top}px`;\n }\n },\n\n revertInputPadding (input) {\n input.style.paddingLeft = '';\n input.style.paddingTop = '';\n input.style.paddingBottom = '';\n },\n\n getFullWidth (el) {\n const styles = window.getComputedStyle(el);\n return el.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);\n },\n\n setInputMinWidth () {\n // Ensure the width of the input is \"slightly bigger\" than the width of a single chip\n const firstChip = this.getFirstChip();\n const input = this.getInput();\n if (!input) return;\n if (firstChip) {\n // Add 4px buffer for typing room\n input.style.minWidth = (this.getFullWidth(firstChip) + 4) + 'px';\n } else {\n input.style.minWidth = '';\n }\n },\n\n checkMaxSelected () {\n if (this.maxSelected === 0) return;\n if (this.selectedItems.length > this.maxSelected) {\n this.showValidationMessages = true;\n this.$emit('max-selected');\n } else {\n this.showValidationMessages = false;\n }\n },\n\n setInitialInputHeight () {\n const input = this.getInput();\n if (!input) return;\n this.initialInputHeight = input.getBoundingClientRect().height;\n },\n\n async handleInputFocusIn () {\n this.inputFocused = true;\n if (this.collapseOnFocusOut) {\n await this.$nextTick();\n this.setInputPadding();\n }\n },\n\n async handleInputFocusOut () {\n this.inputFocused = false;\n if (this.collapseOnFocusOut) {\n const input = this.getInput();\n if (!input) return;\n this.revertInputPadding(input);\n }\n },\n },\n};\n</script>\n\n<style scoped lang=\"less\">\n.combobox__input-wrapper {\n position: relative;\n display: block;\n}\n\n.combobox__chip-wrapper {\n position: absolute;\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n padding-left: var(--dt-space-100);\n max-width: calc(var(--dt-size-100-percent) - var(--dt-space-400));\n max-height: initial;\n overflow-y: visible;\n}\n\n.combobox__chip-wrapper-md--collapsed {\n max-height: 2.8rem;\n overflow-y: hidden;\n}\n\n.combobox__chip-wrapper-sm--collapsed,\n.combobox__chip-wrapper-xs--collapsed {\n max-height: 2.5rem;\n overflow-y: hidden;\n}\n\n.combobox__chip {\n margin-top: var(--dt-space-300);\n margin-left: var(--dt-space-200);\n margin-right: var(--dt-space-200);\n z-index: var(--zi-base1);\n max-width: var(--dt-size-100-percent);\n}\n\n.combobox__input {\n flex-grow: 1;\n}\n\n.combobox__list--loading {\n text-align: center;\n padding-top: var(--dt-space-500);\n padding-bottom: var(--dt-space-500);\n}\n</style>\n"],"names":[],"mappings":"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"}