@avakhula/ui 0.1.20 → 0.1.22

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 (86) hide show
  1. package/dist/index.css +1 -0
  2. package/dist/index.js +13643 -12635
  3. package/dist/index.umd.cjs +91 -83
  4. package/package.json +6 -5
  5. package/src/assets/scss/mixins/dropdown-list-item.scss +3 -3
  6. package/src/assets/scss/mixins/tooltip-position.scss +7 -0
  7. package/src/assets/scss/mixins.scss +2 -2
  8. package/src/assets/scss/style.scss +4 -4
  9. package/src/components/Accordion/Accordion.scss +3 -3
  10. package/src/components/Accordion/Accordion.vue +2 -2
  11. package/src/components/Alert/Alert.vue +1 -1
  12. package/src/components/Alert/alert.scss +2 -2
  13. package/src/components/Avatar/Avatar.vue +2 -2
  14. package/src/components/Badge/Badge.vue +2 -2
  15. package/src/components/Breadcrumbs/Breadcrumbs.vue +7 -2
  16. package/src/components/Breadcrumbs/breadcrumbs.scss +5 -5
  17. package/src/components/Button/Button.vue +2 -2
  18. package/src/components/Button/button.scss +3 -3
  19. package/src/components/Chips/Chips.vue +3 -3
  20. package/src/components/Dropdown/Dropdown.spec.js +0 -0
  21. package/src/components/Dropdown/Dropdown.vue +104 -27
  22. package/src/components/Dropdown/DropdownDivider.vue +1 -1
  23. package/src/components/Dropdown/DropdownItem.vue +1 -1
  24. package/src/components/Dropdown/DropdownList.vue +11 -1
  25. package/src/components/Form/CharactersCount.vue +2 -2
  26. package/src/components/Form/Checkbox/Checkbox.scss +4 -4
  27. package/src/components/Form/Checkbox/Checkbox.vue +1 -1
  28. package/src/components/Form/DatePicker/DatePicker.scss +4 -4
  29. package/src/components/Form/DatePicker/DatePicker.vue +1 -1
  30. package/src/components/Form/FormGroup/FormGroup.vue +2 -2
  31. package/src/components/Form/FormGroup/FormGroupSet.vue +1 -1
  32. package/src/components/Form/Input/Input.vue +7 -4
  33. package/src/components/Form/Input/input.scss +3 -3
  34. package/src/components/Form/Label/Label.vue +2 -2
  35. package/src/components/Form/PhoneInput/PhoneInput.vue +56 -21
  36. package/src/components/Form/PhoneInput/phoneInput.scss +4 -4
  37. package/src/components/Form/Radio/Radio.vue +1 -1
  38. package/src/components/Form/Radio/radio.scss +3 -3
  39. package/src/components/Form/TextEditor/TextEditor.vue +27 -168
  40. package/src/components/Form/TextEditor/Toolbar.vue +723 -0
  41. package/src/components/Form/TextEditor/icons/toolbarIcons.js +8 -0
  42. package/src/components/Form/TextEditor/plugins/imageBlot.js +23 -0
  43. package/src/components/Form/TextEditor/setupTextEditor.js +71 -0
  44. package/src/components/Form/TextEditor/textEditor.scss +9 -357
  45. package/src/components/Form/Textarea/Textarea.spec.js +0 -0
  46. package/src/components/Form/Textarea/Textarea.vue +2 -1
  47. package/src/components/Form/Textarea/textarea.scss +3 -3
  48. package/src/components/Form/Toggle/Toggle.vue +1 -1
  49. package/src/components/Form/Toggle/toggle.scss +3 -3
  50. package/src/components/IconButton/IconButton.scss +2 -2
  51. package/src/components/IconButton/IconButton.vue +6 -4
  52. package/src/components/List.vue +1 -1
  53. package/src/components/Modal/Modal.vue +85 -49
  54. package/src/components/Pagination/Pagination.vue +28 -3
  55. package/src/components/Pagination/pagination.scss +20 -4
  56. package/src/components/Panel/Panel.vue +4 -4
  57. package/src/components/Popover/Popover.vue +7 -2
  58. package/src/components/Popover/popover.scss +3 -3
  59. package/src/components/ProgressBar/ProgressBar.vue +1 -1
  60. package/src/components/ProgressBar/progressBar.scss +1 -1
  61. package/src/components/Sorting/Sorting.vue +1 -1
  62. package/src/components/Sorting/sorting.scss +5 -5
  63. package/src/components/SplitButton/SplitButton.vue +1 -1
  64. package/src/components/SplitButton/SplitButtonItem.vue +1 -1
  65. package/src/components/SplitButton/splitButton.scss +3 -3
  66. package/src/components/StatusIndicator/StatusIndicator.vue +2 -2
  67. package/src/components/Table/Cells/Cell.vue +2 -2
  68. package/src/components/Table/Cells/CheckboxCell.vue +0 -0
  69. package/src/components/Table/Row.vue +1 -1
  70. package/src/components/Table/Table.stories.js +0 -0
  71. package/src/components/Table/Table.vue +0 -0
  72. package/src/components/Tabs/TabDropdown.vue +1 -1
  73. package/src/components/Tabs/Tabs.vue +9 -5
  74. package/src/components/Tabs/tabs.scss +4 -4
  75. package/src/components/TagPill/TagPill.vue +2 -2
  76. package/src/components/ToggleTip/ToggleTip.vue +1 -1
  77. package/src/components/ToggleTip/toggleTip.scss +5 -5
  78. package/src/components/Tooltip/Tooltip.vue +3 -3
  79. package/src/components/TreeSelect/Option.vue +16 -14
  80. package/src/components/TreeSelect/Select.vue +233 -134
  81. package/src/components/TreeSelect/scss/option.scss +6 -6
  82. package/src/components/TreeSelect/scss/select.scss +53 -4
  83. package/src/directives/tooltip/tooltip.js +46 -0
  84. package/src/index.js +6 -1
  85. package/vite.config.js +0 -0
  86. package/dist/style.css +0 -1
@@ -7,7 +7,7 @@
7
7
  v-bind="Object.fromEntries(Object.entries($attrs).filter(([key]) => key.startsWith('data-')))"
8
8
  class="tree-select"
9
9
  :class="{
10
- ...classList, 'tree-select-custom-trigger-content': hasTriggerContent
10
+ ...classList, 'tree-select-custom-trigger-content': hasTriggerContent, 'disabled-parent-autocheck': parentAutoCheck === false
11
11
  }"
12
12
  >
13
13
  <ib-dropdown
@@ -22,7 +22,7 @@
22
22
  @open="onOpen"
23
23
  >
24
24
  <template v-if="hasTrigger" v-slot:trigger>
25
- <slot v-bind:selected-count="selectedKeys.length" name="trigger"></slot>
25
+ <slot v-bind:selected-count="selectedKeys.length" v-bind:is-open="isOpen" name="trigger"></slot>
26
26
  </template>
27
27
 
28
28
  <template v-else v-slot:trigger="{ isOpened }">
@@ -82,8 +82,15 @@
82
82
  :name="isOpened ? 'chevron-up-outline' : 'chevron-down-outline'"
83
83
  :classes="'tree-select-caret'"
84
84
  />
85
- </div>
86
85
 
86
+ <input
87
+ v-for="id in selectedKeys"
88
+ type="hidden"
89
+ :key="'hidden-'+id"
90
+ :name="actualName"
91
+ :value="id"
92
+ />
93
+ </div>
87
94
  </template>
88
95
 
89
96
  <template v-slot:body>
@@ -109,14 +116,15 @@
109
116
  class="tree-search"
110
117
  v-if="showSearch"
111
118
  ref="search"
112
- autocomplete="off"
119
+ autocomplete="new-password"
113
120
  :show-icon="true"
114
121
  :value="filterString"
115
122
  :debounce="searchDebounce"
116
123
  :aria-label="
117
124
  searchPlaceholderText
118
125
  ? searchPlaceholderText
119
- : actualStrings.searchPlaceholder"
126
+ : actualStrings.searchPlaceholder
127
+ "
120
128
  :placeholder="
121
129
  searchPlaceholderText
122
130
  ? searchPlaceholderText
@@ -145,6 +153,7 @@
145
153
  >
146
154
  <slot name="emptyMessage"></slot>
147
155
  </div>
156
+
148
157
  <div
149
158
  v-else-if="!requiredDependencyNotFilled && !visibleOptionsCount"
150
159
  class="tree-select-default-empty tree-select-empty"
@@ -165,7 +174,7 @@
165
174
  checked: isEmpty,
166
175
  }"
167
176
  :name="actualName"
168
- :parent-auto-check="parentAutoCheck"
177
+ :parent-auto-check="parentAutoCheckVal"
169
178
  :is-multiple="isMultiple"
170
179
  role="option"
171
180
  @check="registerCheck"
@@ -176,7 +185,7 @@
176
185
  ></select-option>
177
186
  </template>
178
187
 
179
- <template v-if="Object.keys(actualBookmarkedOptions).length > 0">
188
+ <template v-if="Object.keys(actualBookmarkedOptions).length > 0">
180
189
  <select-option
181
190
  :key="'bookmark' + option.id"
182
191
  v-for="option in actualBookmarkedOptions"
@@ -197,6 +206,7 @@
197
206
  </template>
198
207
 
199
208
  <template v-if="!requiredDependencyNotFilled">
209
+ <div class="scrollable-container">
200
210
  <template
201
211
  v-if="
202
212
  allOptions &&
@@ -209,7 +219,6 @@
209
219
  <select-option
210
220
  :option="{
211
221
  title: actualStrings.selectAllOptions,
212
- id: '!all!',
213
222
  initiallyVisible: true,
214
223
  visible: true,
215
224
  isDisabled: visibleOptionsCount < optionsCount,
@@ -219,7 +228,6 @@
219
228
  : false,
220
229
  }"
221
230
  :is-toggle="isToggle"
222
- :name="actualName"
223
231
  :parent-auto-check="false"
224
232
  :is-multiple="isMultiple"
225
233
  :is-bookmarkable="false"
@@ -229,44 +237,54 @@
229
237
  :alphabetic-style="alphabeticStyle"
230
238
  role="option"
231
239
  @check="manageAll"
232
- @on-focus="(id) => focusedOptionId = id"
240
+ @on-focus="(id) => (focusedOptionId = id)"
233
241
  ></select-option>
234
242
  </template>
235
243
 
236
- <template
237
- v-for="option in actualOptions"
238
- :key="name + option.value"
239
- >
240
- <slot
241
- :option="option"
242
- :name="actualName"
243
- :parent-auto-check="parentAutoCheck"
244
- :is-multiple="isMultiple"
245
- :uid="uid"
246
- :only-end-nodes="onlyEndNodes"
247
- :html-title="htmlOptionTitle"
248
- :show-input="showInputs"
244
+ <div ref="parentRef">
245
+ <div
246
+ :style="{
247
+ height: virtualizer?.getTotalSize() + 'px',
248
+ position: 'relative',
249
+ }"
249
250
  >
250
- <select-option
251
- v-show="option.visible"
252
- :option="option"
253
- :is-toggle="isToggle"
254
- :name="actualName"
255
- role="option"
256
- :parent-auto-check="parentAutoCheck"
257
- :is-multiple="isMultiple"
258
- :is-bookmarkable="isBookmarkable"
259
- :uid="uid"
260
- :only-end-nodes="onlyEndNodes"
261
- :html-title="htmlOptionTitle"
262
- :show-input="showInputs"
263
- :alphabetic-style="alphabeticStyle"
264
- @check="registerCheck"
265
- @toggle-bookmark="toggleBookmark"
266
- @on-focus="(id) => focusedOptionId = id"
267
- ></select-option>
268
- </slot>
269
- </template>
251
+ <div
252
+ v-for="virtualRow in virtualizer?.getVirtualItems()"
253
+ :key="virtualRow.index"
254
+ :data-index="virtualRow.index"
255
+ :ref="virtualizer.measureElement"
256
+ :style="{
257
+ position: 'absolute',
258
+ top: 0,
259
+ left: 0,
260
+ width: '100%',
261
+ transform: `translateY(${virtualRow.start}px)`,
262
+ }"
263
+ >
264
+ <select-option
265
+ v-if="actualOptions[virtualRow.index]"
266
+ v-show="actualOptions[virtualRow.index].visible && !actualOptions[virtualRow.index].hidden"
267
+ :option="actualOptions[virtualRow.index]"
268
+ :is-toggle="isToggle"
269
+ :name="actualName"
270
+ role="option"
271
+ :parent-auto-check="parentAutoCheckVal"
272
+ :is-multiple="isMultiple"
273
+ :is-bookmarkable="isBookmarkable"
274
+ :uid="uid"
275
+ :only-end-nodes="onlyEndNodes"
276
+ :html-title="htmlOptionTitle"
277
+ :show-input="showInputs"
278
+ :alphabetic-style="alphabeticStyle"
279
+ @check="registerCheck"
280
+ @toggle-bookmark="toggleBookmark"
281
+ @on-focus="(id) => focusedOptionId = id"
282
+ ></select-option>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ </div>
287
+
270
288
  </template>
271
289
 
272
290
  <div v-if="infiniteLoader" ref="infinityLoader"></div>
@@ -278,7 +296,7 @@
278
296
  </template>
279
297
 
280
298
  <script>
281
- // <!-- TODO: use constants for vertical position -->
299
+ import { useVirtualizer } from "@tanstack/vue-virtual";
282
300
  import IbInput from "../Form/Input/Input.vue";
283
301
  import Option from "./Option.vue";
284
302
  import Mark from "mark.js/dist/mark.es6.min";
@@ -369,7 +387,7 @@ export default {
369
387
  },
370
388
  parentAutoCheck: {
371
389
  type: Boolean,
372
- default: true,
390
+ default: null,
373
391
  },
374
392
  strings: {
375
393
  type: Object,
@@ -463,6 +481,9 @@ export default {
463
481
  type: Boolean,
464
482
  default: false
465
483
  },
484
+ initialDependencyValue: {
485
+ type: Object
486
+ },
466
487
  },
467
488
  emits: [
468
489
  "close",
@@ -484,9 +505,15 @@ export default {
484
505
  },
485
506
  modelValue: {
486
507
  handler(value) {
487
- this.val = value;
488
- this.actualOptions = [];
489
- this.setPreparedValues();
508
+ if (this.isInternalChange) return;
509
+
510
+ this.val = value;
511
+ this.val = value;
512
+ if (!Array.isArray(value) || value.join(',') !== Object.keys(this.selected).join(',')) {
513
+ this.setPreparedValues(this.actualOptions, false);
514
+ }
515
+ const selectedSet = new Set(Array.isArray(value) ? value : [value].filter(Boolean));
516
+ this.syncCheckedBySet(selectedSet);
490
517
  },
491
518
  deep: true,
492
519
  },
@@ -547,6 +574,15 @@ export default {
547
574
  this.actualBookmarkedOptions = {};
548
575
  this.setBookmarkedOptions(this.actualOptions);
549
576
  },
577
+ initialDependencyValue(value) {
578
+ this.dependencyValue = value;
579
+
580
+ if (this.hasFilledDependency) {
581
+ this.$nextTick(() => {
582
+ this.loadValues();
583
+ });
584
+ }
585
+ },
550
586
  },
551
587
  mounted() {
552
588
  this.marker = new Mark(this.$refs.list.$el);
@@ -569,9 +605,12 @@ export default {
569
605
  if (filterString && this.keywordHighlighter) {
570
606
  this.marker.mark(filterString);
571
607
  }
608
+
609
+ this.virtualizer?.measure();
572
610
  }, 1000);
573
611
 
574
612
  return {
613
+ virtualizer: null,
575
614
  initialOptions: typeof this.options === "function" ? this.options : copy(this.options),
576
615
  val: this.modelValue ? this.modelValue : this.value,
577
616
  size: {
@@ -580,14 +619,15 @@ export default {
580
619
  },
581
620
  resizingProp: null,
582
621
  isInitialized: false,
583
- optionsIdsWatch: [],
584
622
  isLoading: false,
623
+ isOpen: false,
624
+ optionsIdsWatch: [],
585
625
  actualName: this.isMultiple ? this.name + "[]" : this.name,
626
+ parentAutoCheckVal: this.parentAutoCheck !== null ? this.parentAutoCheck : this.isMultiple,
586
627
  filterString: "",
587
628
  actualOptions: [],
588
629
  actualBookmarkedOptions: {},
589
630
  selected: [],
590
- isOpen: false,
591
631
  verticalVal: this.vertical ?? "bottom",
592
632
  allOptionsIsChecked: true,
593
633
  hasTreeChildren: false,
@@ -632,10 +672,39 @@ export default {
632
672
  },
633
673
  ...this.strings,
634
674
  },
635
- dependencyValue: null,
675
+ dependencyValue: this.initialDependencyValue,
676
+ isInternalChange: false,
677
+ nodeIndex: new Map()
636
678
  };
637
679
  },
638
680
  methods: {
681
+ toggleDuplicateOptionsFast(optionId, checked) {
682
+ const arr = this.nodeIndex.get(optionId);
683
+ if (!arr) return;
684
+ for (const node of arr) node.checked = checked;
685
+ },
686
+ buildNodeIndex() {
687
+ this.nodeIndex.clear();
688
+ this.traverseTree(this.actualOptions, (node) => {
689
+ if (!this.nodeIndex.has(node.id)) this.nodeIndex.set(node.id, []);
690
+ this.nodeIndex.get(node.id).push(node);
691
+ });
692
+ },
693
+ syncCheckedBySet(selectedSet) {
694
+ this.traverseTree(this.actualOptions, (opt) => {
695
+ const shouldBeChecked = selectedSet.has(opt.id);
696
+ if (opt.checked !== shouldBeChecked) opt.checked = shouldBeChecked;
697
+ });
698
+
699
+ this.selected = {};
700
+ this.traverseTree(this.actualOptions, (opt) => {
701
+ if (opt.checked && (!this.onlyEndNodes || !opt.children)) {
702
+ this.selected[opt.id] = opt;
703
+ }
704
+ });
705
+
706
+ this.allOptionsIsChecked = this.checkIfOptionsChecked(this.actualOptions);
707
+ },
639
708
  onBlur() {
640
709
  setTimeout(() => {
641
710
  if (!this.isOpen) {
@@ -658,7 +727,7 @@ export default {
658
727
  this.$refs.combobox.focus();
659
728
  },
660
729
  focusOnFirstOptions() {
661
- this.$refs.list.$el.querySelector('[tabindex]:not(hidden)').focus();
730
+ this.$refs.list.$el.querySelector("[tabindex]:not(hidden)").focus();
662
731
  },
663
732
  startResizing(prop) {
664
733
  this.resizingProp = prop;
@@ -681,23 +750,19 @@ export default {
681
750
  },
682
751
  registerDependency(oldDependency) {
683
752
  if (this.dependency) {
684
- this.$globalEvents.$on(
685
- "select-" + this.dependency + ":update",
686
- (dependencyValue) => {
687
- this.clear();
753
+ this.$globalEvents.$on("select-" + this.dependency + ":update", (dependencyValue) => {
754
+ this.clear();
688
755
  this.dependencyValue = dependencyValue;
689
756
 
690
- if (
691
- this.dependencyValue &&
692
- this.dependencyValue.values &&
693
- (!Array.isArray(this.dependencyValue.values) ||
694
- this.dependencyValue.values.length)
695
- ) {
757
+ if (this.dependencyValue && this.dependencyValue.values && (!Array.isArray(this.dependencyValue.values) || this.dependencyValue.values.length)) {
696
758
  this.setPreparedValues();
697
759
  }
698
760
  }
699
761
  );
700
762
  this.isLoading = false;
763
+ if (!oldDependency && this.hasFilledDependency) {
764
+ this.setPreparedValues();
765
+ }
701
766
  } else {
702
767
  this.$globalEvents.$off("select-" + oldDependency + ":update");
703
768
  this.setPreparedValues().then(() => {
@@ -708,7 +773,21 @@ export default {
708
773
  });
709
774
  });
710
775
  }
711
- },
776
+ },
777
+ loadValues() {
778
+ this.setPreparedValues().then(() => {
779
+ if (!this.dependency) {
780
+ const values = Object.keys(this.selected);
781
+
782
+ // SP-13363
783
+ if (!(Array.isArray(this.options) && !this.options.length)) {
784
+ this.$globalEvents.$emit('select-' + this.filterId + ':update', {values, filter: this.filterId});
785
+ }
786
+ }
787
+
788
+ this.$emit('loaded', this.dependencyValue);
789
+ });
790
+ },
712
791
  filter(filterString, options) {
713
792
  this.filterString = filterString;
714
793
  this.$emit("search", this.filterString);
@@ -722,35 +801,33 @@ export default {
722
801
  );
723
802
  }
724
803
 
725
- return this.prepare(options).then(([options, selected]) => {
726
- this.actualOptions = options;
727
- this.allOptionsIsChecked = this.checkIfOptionsChecked(options);
728
- this.isInitialized = true;
729
- this.selected = selected;
730
- this.setBookmarkedOptions(options);
731
- });
804
+ return this.prepare(options).then(([options, selected]) => {
805
+ this.actualOptions = options;
806
+ this.buildNodeIndex();
807
+ this.allOptionsIsChecked = this.checkIfOptionsChecked(options);
808
+ this.isInitialized = true;
809
+ this.selected = selected;
810
+ this.setBookmarkedOptions(options);
811
+ });
732
812
  },
733
813
  clear() {
734
- this.setPreparedValues();
814
+ this.actualOptions = [];
735
815
  this.allOptionsIsChecked = false;
816
+ this.countVisibleChildren = 0;
736
817
  this.selected = [];
737
-
738
- if (this.isMultiple) {
739
- this.$emit("update:modelValue", null);
740
- this.$emit("input", null);
741
- this.$emit("clear-value", null);
742
-
743
- } else {
744
- this.$emit("update:modelValue", []);
745
- this.$emit("input", []);
746
- this.$emit("clear-value", []);
747
- }
748
-
749
- this.setPreparedValues();
750
818
  },
751
819
  clearValue() {
752
- this.clear();
753
- this.setPreparedValues();
820
+ this.traverseTree(this.actualOptions, (opt) => (opt.checked = false));
821
+ this.clear();
822
+
823
+ this.isInternalChange = true;
824
+ const empty = this.isMultiple ? [] : null;
825
+
826
+ this.$emit("update:modelValue", empty);
827
+ this.$emit("input", empty);
828
+ this.$emit("clear-value", empty);
829
+ this.$nextTick(() => (this.isInternalChange = false));
830
+ this.setPreparedValues();
754
831
  },
755
832
  prepare(options, checkInitialVisibility = true) {
756
833
  return new Promise((res) => {
@@ -804,8 +881,10 @@ export default {
804
881
  ([preparedChildren, selectedChildren]) => {
805
882
  option.children = preparedChildren;
806
883
 
807
- if (this.parentAutoCheck) {
808
- option.checked = this.checkIfOptionsChecked(option.children);
884
+ if (this.parentAutoCheckVal) {
885
+ option.checked = this.checkIfOptionsChecked(
886
+ option.children
887
+ );
809
888
  }
810
889
 
811
890
  Object.assign(selected, selectedChildren);
@@ -841,8 +920,12 @@ export default {
841
920
  visibleOptionsCount += visibleChildrenCount;
842
921
 
843
922
  if (visibleChildrenCount) {
844
- option.isChildrenVisible = filterString.length > 0 || Boolean(Object.keys(this.actualBookmarkedOptions).length);
845
- option.isDisabled = visibleChildrenCount < option.children.length && !this.isBookmarkable;
923
+ option.isChildrenVisible =
924
+ filterString.length > 0 ||
925
+ Boolean(Object.keys(this.actualBookmarkedOptions).length);
926
+ option.isDisabled =
927
+ visibleChildrenCount < option.children.length &&
928
+ !this.isBookmarkable;
846
929
  }
847
930
 
848
931
  if (!isVisible) {
@@ -870,57 +953,52 @@ export default {
870
953
  this.$emit("submit");
871
954
  },
872
955
  change() {
873
- const values = Object.keys(this.selected);
874
- if (this.isMultiple) {
875
- this.$emit("update:modelValue", values);
876
- this.$emit("input", values);
877
- } else {
878
- this.$emit("update:modelValue", values[0]);
879
- this.$emit("input", values[0]);
880
- }
881
- this.$globalEvents.$emit("select-" + this.filterId + ":update", {
882
- values,
883
- filter: this.filterId,
884
- });
885
- this.$refs.dropdown.close();
956
+ const values = Object.keys(this.selected);
957
+ this.isInternalChange = true;
958
+ if (this.isMultiple) {
959
+ this.$emit("update:modelValue", values);
960
+ this.$emit("input", values);
961
+ } else {
962
+ this.$emit("update:modelValue", values[0]);
963
+ this.$emit("input", values[0]);
964
+ }
965
+ this.$nextTick(() => (this.isInternalChange = false));
966
+ this.$globalEvents.$emit("select-" + this.filterId + ":update", { values, filter: this.filterId });
967
+ if (!this.isMultiple) this.$refs.dropdown.close();
886
968
  },
887
969
  checkIfOptionsChecked(options) {
888
970
  return options.every((option) => option.checked || option.readonly);
889
971
  },
890
972
  registerCheck(option, isChecked, isDirectChild) {
891
- if (isChecked) {
892
- option.checked = true;
893
- if (this.isMultiple) {
894
- if (
895
- !(this.onlyEndNodes && option.children && option.children.length)
896
- ) {
973
+ if (isChecked) {
974
+ option.checked = true;
975
+ if (this.isMultiple && !(this.onlyEndNodes && option.children?.length)) {
897
976
  this.selected[option.id] = option;
898
- this.$emit("update:modelValue", Object.keys(this.selected));
899
- this.$emit("input", Object.keys(this.selected));
977
+ } else if (!this.isMultiple) {
978
+ const prev = Object.keys(this.selected)[0];
979
+ if (prev) this.selected[prev].checked = false;
980
+ this.selected = { [option.id]: option };
981
+ this.change();
982
+ return;
900
983
  }
901
984
  } else {
902
- const selectedOptionKey = Object.keys(this.selected)[0];
985
+ delete this.selected[option.id];
986
+ option.checked = false;
987
+ }
903
988
 
904
- if (selectedOptionKey) {
905
- this.selected[selectedOptionKey].checked = false;
906
- }
989
+ this.toggleDuplicateOptionsFast(option.id, isChecked);
907
990
 
908
- this.selected = { [option.id]: option };
909
- this.change();
991
+ if (isDirectChild) {
992
+ this.allOptionsIsChecked = this.checkIfOptionsChecked(this.actualOptions);
910
993
  }
911
- } else {
912
- delete this.selected[option.id];
913
- option.checked = false;
914
- this.$emit("update:modelValue", Object.keys(this.selected));
915
- this.$emit("input", Object.keys(this.selected));
916
- }
917
994
 
918
- this.toggleDuplicateOptions(this.actualOptions, option.id, isChecked);
919
- if (isDirectChild) {
920
- this.allOptionsIsChecked = this.checkIfOptionsChecked(
921
- this.actualOptions
922
- );
923
- }
995
+ if (this.isMultiple) {
996
+ this.isInternalChange = true;
997
+ const values = Object.keys(this.selected);
998
+ this.$emit("update:modelValue", values);
999
+ this.$emit("input", values);
1000
+ this.$nextTick(() => (this.isInternalChange = false));
1001
+ }
924
1002
  },
925
1003
  toggleDuplicateOptions(options, optionId, checked) {
926
1004
  for (let opt of options) {
@@ -990,6 +1068,7 @@ export default {
990
1068
  } else {
991
1069
  this.$emit("close", Object.keys(this.selected)[0]);
992
1070
  }
1071
+ this.virtualizer = null;
993
1072
  this.$emit("blur");
994
1073
  this.verticalVal = this.vertical ?? "bottom";
995
1074
  },
@@ -997,6 +1076,17 @@ export default {
997
1076
  const screenHeight = document.documentElement.scrollHeight;
998
1077
  this.isOpen = true;
999
1078
 
1079
+
1080
+ if (!this.virtualizer) {
1081
+ this.virtualizer = useVirtualizer({
1082
+ count: this.actualOptions.length,
1083
+ getScrollElement: () => this.$refs.parentRef,
1084
+ estimateSize: () => 40,
1085
+ overscan: 8,
1086
+ });
1087
+ }
1088
+ this.virtualizer?.measure();
1089
+
1000
1090
  if (this.vertical === "bottom") return;
1001
1091
 
1002
1092
  this.$nextTick(() => {
@@ -1005,7 +1095,7 @@ export default {
1005
1095
  this.verticalVal = "top";
1006
1096
  }
1007
1097
  })
1008
- }
1098
+ },
1009
1099
  },
1010
1100
  computed: {
1011
1101
  hasTrigger() {
@@ -1045,7 +1135,7 @@ export default {
1045
1135
  }
1046
1136
  });
1047
1137
  },
1048
- selectStatus() {
1138
+ selectStatus() {
1049
1139
  if (this.staticPlaceholder) {
1050
1140
  return this.placeholder;
1051
1141
  } else if (this.isLoading) {
@@ -1056,7 +1146,7 @@ export default {
1056
1146
  return this.selectedKeys
1057
1147
  .map((key) => this.selected[key].title)
1058
1148
  .join(",");
1059
- } else if (this.selectedKeys.length < this.optionsCount) {
1149
+ } else if (!this.allOptionsIsChecked) {
1060
1150
  return this.actualStrings.selectedCount
1061
1151
  .replace("{selected}", this.selectedKeys.length)
1062
1152
  .replace("{all}", this.optionsCount);
@@ -1076,7 +1166,7 @@ export default {
1076
1166
  );
1077
1167
  },
1078
1168
  showSearch() {
1079
- return this.useSearch || (this.optionsCount > 10 && !this.alphabeticStyle);
1169
+ return (this.useSearch || (this.optionsCount > 10 && !this.alphabeticStyle));
1080
1170
  },
1081
1171
  arrayOfOptions() {
1082
1172
  return this.getArrayOptions(this.actualOptions);
@@ -1113,6 +1203,9 @@ export default {
1113
1203
  : 0)
1114
1204
  );
1115
1205
  },
1206
+ hasFilledDependency() {
1207
+ return !!(this.dependency && this.dependencyValue && this.dependencyValue?.values && (!Array.isArray(this.dependencyValue?.values) || this.dependencyValue?.values.length));
1208
+ },
1116
1209
  },
1117
1210
  components: {
1118
1211
  IbAlert,
@@ -1134,7 +1227,13 @@ export default {
1134
1227
  };
1135
1228
  </script>
1136
1229
  <style lang="scss">
1137
- @import "./scss/select.scss";
1230
+ @use "./scss/select.scss" as *;
1231
+ @use "../../assets/scss/variables/colors.scss" as *;
1232
+
1233
+ .scrollable-container {
1234
+ overflow: auto;
1235
+ max-height: 300px;
1236
+ }
1138
1237
 
1139
1238
  .bookmarked-option {
1140
1239
  .tree-select-option-label {
@@ -1,6 +1,6 @@
1
- @import "../../../assets/scss/variables/colors.scss";
2
- @import "../../../assets/scss/typography.scss";
3
- @import "../../../assets/scss/mixins.scss";
1
+ @use "../../../assets/scss/variables/colors.scss" as *;
2
+ @use "../../../assets/scss/typography.scss" as *;
3
+ @use "../../../assets/scss/mixins.scss" as *;
4
4
 
5
5
  $option-hover-bg: $gray-100;
6
6
  $option-checked-bg: $gray-100;
@@ -41,7 +41,7 @@ $option-checked-hover-bg: $blue-50;
41
41
 
42
42
  .ib-checkbox-body {
43
43
  padding: 0;
44
- }
44
+ }
45
45
 
46
46
  .option-label {
47
47
  margin-left: 15px;
@@ -165,7 +165,7 @@ $option-checked-hover-bg: $blue-50;
165
165
  .ib-checkbox {
166
166
  transform: translateX(75px);
167
167
  }
168
-
168
+
169
169
  .option-label {
170
170
  width: calc(100% - 100px);
171
171
  }
@@ -212,7 +212,7 @@ $option-checked-hover-bg: $blue-50;
212
212
  }
213
213
  }
214
214
 
215
-
215
+
216
216
  .ib-toggle-container {
217
217
  position: absolute;
218
218
  right: 0;