classcard-ui 0.2.1474 → 0.2.1476
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.
- package/dist/classcard-ui.common.js +403 -124
- package/dist/classcard-ui.common.js.map +1 -1
- package/dist/classcard-ui.css +2 -2
- package/dist/classcard-ui.umd.js +403 -124
- package/dist/classcard-ui.umd.js.map +1 -1
- package/dist/classcard-ui.umd.min.js +3 -3
- package/dist/classcard-ui.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CMultiselect/CMultiselect.vue +318 -85
- package/src/components/CSelect/CSelect.vue +74 -29
- package/src/icons.js +1 -0
package/package.json
CHANGED
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
<div class="relative">
|
|
15
15
|
<v-select
|
|
16
16
|
ref="vselect"
|
|
17
|
-
class="
|
|
17
|
+
:class="[
|
|
18
|
+
'disabled:custom-disabled-state absolute inline-block h-full w-full text-sm',
|
|
19
|
+
isMultiple ? 'c-multiselect--capped-pills' : '',
|
|
20
|
+
]"
|
|
18
21
|
:placeholder="placeholder"
|
|
19
22
|
:multiple="isMultiple"
|
|
20
23
|
:taggable="isTaggable"
|
|
@@ -62,48 +65,76 @@
|
|
|
62
65
|
/>
|
|
63
66
|
</span>
|
|
64
67
|
</template>
|
|
65
|
-
<template
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
68
|
+
<template
|
|
69
|
+
#selected-option-container="{ option, deselect, multiple, disabled }"
|
|
70
|
+
>
|
|
71
|
+
<template v-for="row in [getPillRow(option)]">
|
|
72
|
+
<div
|
|
73
|
+
v-if="row && row.showPill"
|
|
74
|
+
:key="row.slotKey"
|
|
75
|
+
class="vs__selected vs__selected--capped inline-flex items-center gap-1.5"
|
|
76
|
+
>
|
|
77
|
+
<p
|
|
78
|
+
v-if="!option.header"
|
|
79
|
+
:class="[
|
|
80
|
+
'vs__selected-inner inline-flex min-w-0 max-w-[120px] items-center gap-1.5 rounded bg-gray-100 px-2 py-1 text-gray-800',
|
|
81
|
+
isDisabled ? 'text-gray-500' : '',
|
|
82
|
+
]"
|
|
83
|
+
>
|
|
84
|
+
<c-icon
|
|
85
|
+
v-if="option.icon"
|
|
86
|
+
:name="option.icon.name"
|
|
87
|
+
:type="option.icon.type"
|
|
88
|
+
:class="[
|
|
89
|
+
'h-4 w-4 flex-shrink-0 text-gray-400',
|
|
90
|
+
option.icon.optionIconClass,
|
|
91
|
+
]"
|
|
92
|
+
/>
|
|
93
|
+
<c-avatar
|
|
94
|
+
v-if="option.image && displaySelectedOptionAvatar"
|
|
95
|
+
:size="
|
|
96
|
+
option.description && showAdditionalText
|
|
97
|
+
? 'extrasmall'
|
|
98
|
+
: 'extraextrasmall'
|
|
99
|
+
"
|
|
100
|
+
:image="option.image"
|
|
101
|
+
:rounded="true"
|
|
102
|
+
:description="option.description"
|
|
103
|
+
class="flex-shrink-0"
|
|
104
|
+
></c-avatar>
|
|
105
|
+
<c-avatar
|
|
106
|
+
v-else-if="option.initials && displaySelectedOptionAvatar"
|
|
107
|
+
size="extraextrasmall"
|
|
108
|
+
:nameInitials="option.initials"
|
|
109
|
+
:description="option.description"
|
|
110
|
+
:rounded="true"
|
|
111
|
+
:isDynamicallyColored="true"
|
|
112
|
+
class="flex-shrink-0"
|
|
113
|
+
></c-avatar>
|
|
114
|
+
<span class="min-w-0 flex-1 truncate">{{ row.label }}</span>
|
|
115
|
+
<button
|
|
116
|
+
v-if="multiple"
|
|
117
|
+
type="button"
|
|
118
|
+
class="flex h-2 w-2 flex-shrink-0 items-center justify-center rounded text-gray-400 focus:outline-none"
|
|
119
|
+
:disabled="disabled"
|
|
120
|
+
:title="`Deselect ${row.label}`"
|
|
121
|
+
:aria-label="`Deselect ${row.label}`"
|
|
122
|
+
@click.stop.prevent="deselect(option)"
|
|
123
|
+
>
|
|
124
|
+
<span class="text-base leading-none" aria-hidden="true"
|
|
125
|
+
>×</span
|
|
126
|
+
>
|
|
127
|
+
</button>
|
|
128
|
+
</p>
|
|
129
|
+
<span
|
|
130
|
+
v-if="row.showOverflowBadge"
|
|
131
|
+
class="vs__selected-overflow inline-flex w-max rounded bg-gray-100 px-2 py-1 text-gray-800"
|
|
132
|
+
aria-live="polite"
|
|
133
|
+
>
|
|
134
|
+
+{{ selectedOverflowCount }}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
</template>
|
|
107
138
|
</template>
|
|
108
139
|
<!-- eslint-disable-next-line vue/no-unused-vars -->
|
|
109
140
|
<template #no-options="{ search, searching, loading }">
|
|
@@ -145,6 +176,12 @@
|
|
|
145
176
|
<div v-if="!isGrouped">
|
|
146
177
|
<div v-if="option.hasNoData" class="dropdown-menu-bordered"></div>
|
|
147
178
|
<div v-else class="mt-1 flex h-full w-full items-center">
|
|
179
|
+
<div @click.stop v-if="addCheckBox" class="flex-shrink-0">
|
|
180
|
+
<c-checkbox
|
|
181
|
+
:value="isChecked(option)"
|
|
182
|
+
@onChange="handleSingleSelect(option)"
|
|
183
|
+
/>
|
|
184
|
+
</div>
|
|
148
185
|
<p v-if="showOptionImage" class="flex-shrink-0">
|
|
149
186
|
<c-avatar
|
|
150
187
|
v-if="option[imageLabel]"
|
|
@@ -210,12 +247,6 @@
|
|
|
210
247
|
</span>
|
|
211
248
|
</div>
|
|
212
249
|
</div>
|
|
213
|
-
<div @click.stop v-if="addCheckBox">
|
|
214
|
-
<c-checkbox
|
|
215
|
-
:value="isChecked(option)"
|
|
216
|
-
@onChange="handleSingleSelect(option)"
|
|
217
|
-
/>
|
|
218
|
-
</div>
|
|
219
250
|
</div>
|
|
220
251
|
<p
|
|
221
252
|
class="text-xs"
|
|
@@ -315,9 +346,14 @@
|
|
|
315
346
|
<li ref="load" class="loader" v-show="hasNextPage">
|
|
316
347
|
Loading more options...
|
|
317
348
|
</li>
|
|
349
|
+
|
|
350
|
+
<!-- Footer buttons when footer buttons are visible -->
|
|
318
351
|
<div
|
|
319
|
-
|
|
320
|
-
:class="
|
|
352
|
+
v-if="showFooterButton || showFooterButton2"
|
|
353
|
+
:class="[
|
|
354
|
+
'group sticky bottom-0 mt-1 bg-white',
|
|
355
|
+
showFooterButton && showFooterButton2 ? 'space-y-2' : '',
|
|
356
|
+
]"
|
|
321
357
|
>
|
|
322
358
|
<li
|
|
323
359
|
v-if="showFooterButton"
|
|
@@ -372,6 +408,8 @@
|
|
|
372
408
|
</div>
|
|
373
409
|
</li>
|
|
374
410
|
</div>
|
|
411
|
+
|
|
412
|
+
<!-- Create option button when showCreateOption is true and there is a search term -->
|
|
375
413
|
<div
|
|
376
414
|
v-if="
|
|
377
415
|
showCreateOption &&
|
|
@@ -379,7 +417,9 @@
|
|
|
379
417
|
search &&
|
|
380
418
|
search.trim()
|
|
381
419
|
"
|
|
382
|
-
|
|
420
|
+
ref="createOption"
|
|
421
|
+
class="sticky z-10 flex min-h-[44px] items-start gap-3 bg-white px-3 py-2 shadow-lg ring-1 ring-gray-900 ring-opacity-5"
|
|
422
|
+
:style="footerStickyStyles.create"
|
|
383
423
|
>
|
|
384
424
|
<span class="word-break flex-1 text-sm text-gray-700">{{
|
|
385
425
|
search
|
|
@@ -400,9 +440,13 @@
|
|
|
400
440
|
Create
|
|
401
441
|
</button>
|
|
402
442
|
</div>
|
|
443
|
+
|
|
444
|
+
<!-- Other option checkbox when otherOption is true -->
|
|
403
445
|
<div
|
|
404
446
|
v-if="otherOption"
|
|
405
|
-
|
|
447
|
+
ref="otherOption"
|
|
448
|
+
class="sticky z-10 border-t border-gray-100 bg-gray-50 px-3 py-2"
|
|
449
|
+
:style="footerStickyStyles.other"
|
|
406
450
|
>
|
|
407
451
|
<div class="flex" @mousedown.prevent.stop>
|
|
408
452
|
<c-checkbox
|
|
@@ -419,6 +463,20 @@
|
|
|
419
463
|
</div>
|
|
420
464
|
</div>
|
|
421
465
|
</div>
|
|
466
|
+
|
|
467
|
+
<!-- Clear all button when multiple is true and there are selected values -->
|
|
468
|
+
<button
|
|
469
|
+
v-if="isMultiple && hasSelectedValues"
|
|
470
|
+
ref="clearAllButton"
|
|
471
|
+
type="button"
|
|
472
|
+
class="sticky z-10 w-full border-t border-gray-200 bg-gray-50 px-4 py-3 text-left text-sm text-gray-500 hover:text-gray-900 focus:outline-none"
|
|
473
|
+
:style="footerStickyStyles.clear"
|
|
474
|
+
:id="id + '_clear_all_button'"
|
|
475
|
+
aria-label="Clear all selections"
|
|
476
|
+
@mousedown.prevent.stop="handleClearAll"
|
|
477
|
+
>
|
|
478
|
+
Clear all
|
|
479
|
+
</button>
|
|
422
480
|
</template>
|
|
423
481
|
</v-select>
|
|
424
482
|
<button
|
|
@@ -436,7 +494,10 @@
|
|
|
436
494
|
</button>
|
|
437
495
|
</div>
|
|
438
496
|
<p v-if="subLabel" class="mt-2 text-sm text-gray-500">{{ subLabel }}</p>
|
|
439
|
-
<p
|
|
497
|
+
<p
|
|
498
|
+
v-if="!isValidate && errorMessage"
|
|
499
|
+
class="mt-2 text-left text-sm text-red-600"
|
|
500
|
+
>
|
|
440
501
|
{{ errorMessage }}
|
|
441
502
|
</p>
|
|
442
503
|
<p v-if="helpText && isValidate == true" class="mt-2 text-sm text-gray-500">
|
|
@@ -450,7 +511,6 @@ import CAvatar from "../CAvatar/CAvatar.vue";
|
|
|
450
511
|
import CIcon from "../CIcon/CIcon.vue";
|
|
451
512
|
import CCheckbox from "../CCheckbox/CCheckbox.vue";
|
|
452
513
|
import { debounce } from "lodash-es";
|
|
453
|
-
// import Fuse from "fuse.js";
|
|
454
514
|
import "vue-select/dist/vue-select.css";
|
|
455
515
|
import { getActionID } from "../../helper";
|
|
456
516
|
import CTag from "../CTag/CTag.vue";
|
|
@@ -523,6 +583,11 @@ export default {
|
|
|
523
583
|
selectedOptionLabel: {
|
|
524
584
|
type: String,
|
|
525
585
|
},
|
|
586
|
+
// the key to compare the options when addCheckBox is true
|
|
587
|
+
primaryComparisonKey: {
|
|
588
|
+
type: String,
|
|
589
|
+
default: "id",
|
|
590
|
+
},
|
|
526
591
|
// action to trigger after selecting option from dropdown
|
|
527
592
|
onSelectOptions: {
|
|
528
593
|
type: Function,
|
|
@@ -681,6 +746,67 @@ export default {
|
|
|
681
746
|
|
|
682
747
|
return !hasExactMatch;
|
|
683
748
|
},
|
|
749
|
+
/*
|
|
750
|
+
This function is used to get the remaining count of options that are not shown in the dropdown.
|
|
751
|
+
*/
|
|
752
|
+
selectedOverflowCount() {
|
|
753
|
+
if (!this.isMultiple) return 0;
|
|
754
|
+
const totalSelectedOptions = Array.isArray(this.value)
|
|
755
|
+
? this.value.length
|
|
756
|
+
: 0;
|
|
757
|
+
return totalSelectedOptions > 2 ? totalSelectedOptions - 2 : 0;
|
|
758
|
+
},
|
|
759
|
+
hasSelectedValues() {
|
|
760
|
+
return Array.isArray(this.value) && this.value.length > 0;
|
|
761
|
+
},
|
|
762
|
+
/**
|
|
763
|
+
* Pre-built pill rows keyed by `value[i]` and by vue-select option key.
|
|
764
|
+
* Recomputes only when selection / multi / overflow-relevant state changes — not on dropdown hover.
|
|
765
|
+
* Index comes from `value` order (same order vue-select uses for selected-option-container).
|
|
766
|
+
*/
|
|
767
|
+
pillRowsBySlotLookup() {
|
|
768
|
+
if (!Array.isArray(this.value)) {
|
|
769
|
+
return { byRef: new Map(), byKey: new Map() };
|
|
770
|
+
}
|
|
771
|
+
const byRef = new Map();
|
|
772
|
+
const byKey = new Map();
|
|
773
|
+
const overflow = this.selectedOverflowCount;
|
|
774
|
+
|
|
775
|
+
this.value.forEach((item, index) => {
|
|
776
|
+
const label = this.getDisplayLabelForOption(item);
|
|
777
|
+
const key = this.getVueSelectOptionKey(item);
|
|
778
|
+
const slotKey = `slot-${index}-${String(key)}`;
|
|
779
|
+
const meta = { index, key, label, slotKey };
|
|
780
|
+
const showPill = this.isMultiple;
|
|
781
|
+
const showOverflowBadge =
|
|
782
|
+
this.isMultiple && index === 1 && overflow > 0;
|
|
783
|
+
const row = {
|
|
784
|
+
meta,
|
|
785
|
+
showPill,
|
|
786
|
+
showOverflowBadge,
|
|
787
|
+
label,
|
|
788
|
+
slotKey,
|
|
789
|
+
};
|
|
790
|
+
byRef.set(item, row);
|
|
791
|
+
if (!byKey.has(key)) {
|
|
792
|
+
byKey.set(key, row);
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
return { byRef, byKey };
|
|
796
|
+
},
|
|
797
|
+
/**
|
|
798
|
+
* Sticky `bottom` offsets so create → other → clear stack without overlap.
|
|
799
|
+
* DOM order is create (top of sticky group), other, clear (anchored to dropdown bottom).
|
|
800
|
+
*/
|
|
801
|
+
footerStickyStyles() {
|
|
802
|
+
const clearH = Number(this.footerMetaData.clearAllHeight) || 0;
|
|
803
|
+
const otherH = Number(this.footerMetaData.otherOptionHeight) || 0;
|
|
804
|
+
return {
|
|
805
|
+
create: { bottom: `${clearH + otherH}px` },
|
|
806
|
+
other: { bottom: `${clearH}px` },
|
|
807
|
+
clear: { bottom: "0px" },
|
|
808
|
+
};
|
|
809
|
+
},
|
|
684
810
|
},
|
|
685
811
|
data() {
|
|
686
812
|
return {
|
|
@@ -690,6 +816,11 @@ export default {
|
|
|
690
816
|
? this.optionsSelected
|
|
691
817
|
: [],
|
|
692
818
|
observer: null,
|
|
819
|
+
footerMetaData: {
|
|
820
|
+
clearAllHeight: 0,
|
|
821
|
+
otherOptionHeight: 0,
|
|
822
|
+
createOptionHeight: 0,
|
|
823
|
+
},
|
|
693
824
|
};
|
|
694
825
|
},
|
|
695
826
|
methods: {
|
|
@@ -702,6 +833,8 @@ export default {
|
|
|
702
833
|
},
|
|
703
834
|
fetchOptions(search, loaderSearching) {
|
|
704
835
|
this.emitGetOptions(search, loaderSearching);
|
|
836
|
+
|
|
837
|
+
this._updateFooterHeights();
|
|
705
838
|
},
|
|
706
839
|
emitGetOptions: debounce(function (search, loaderSearching) {
|
|
707
840
|
this.$emit("getOptions", search.trim(), loaderSearching);
|
|
@@ -724,23 +857,93 @@ export default {
|
|
|
724
857
|
this.emitGetOptions("", true);
|
|
725
858
|
},
|
|
726
859
|
onClose() {
|
|
727
|
-
this.observer
|
|
860
|
+
if (this.observer) {
|
|
861
|
+
this.observer.disconnect();
|
|
862
|
+
}
|
|
728
863
|
},
|
|
729
864
|
async infiniteScroll([{ isIntersecting }]) {
|
|
730
865
|
if (isIntersecting) {
|
|
731
866
|
this.emitLoadNextPage();
|
|
732
867
|
}
|
|
733
868
|
},
|
|
734
|
-
|
|
735
|
-
|
|
869
|
+
/*
|
|
870
|
+
This function is used to create a unique key for the option.
|
|
871
|
+
*/
|
|
872
|
+
createUniqueKeyForOption(sortable) {
|
|
873
|
+
const ordered = {};
|
|
874
|
+
Object.keys(sortable)
|
|
875
|
+
.sort()
|
|
876
|
+
.forEach((key) => {
|
|
877
|
+
ordered[key] = sortable[key];
|
|
878
|
+
});
|
|
879
|
+
return JSON.stringify(ordered);
|
|
880
|
+
},
|
|
881
|
+
/*
|
|
882
|
+
This function is used to get the key of the option for the selected pills.
|
|
883
|
+
Aligns with vue-select default getOptionKey.
|
|
884
|
+
Reference: https://vue-select.org/api/props.html#getoptionkey
|
|
885
|
+
*/
|
|
886
|
+
getVueSelectOptionKey(option) {
|
|
887
|
+
if (typeof option !== "object" || option === null) {
|
|
888
|
+
return option;
|
|
889
|
+
}
|
|
890
|
+
try {
|
|
891
|
+
return Object.prototype.hasOwnProperty.call(option, "id")
|
|
892
|
+
? option.id
|
|
893
|
+
: this.createUniqueKeyForOption(option);
|
|
894
|
+
} catch (e) {
|
|
895
|
+
return String(option);
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
getDisplayLabelForOption(option) {
|
|
899
|
+
if (!option) return "";
|
|
900
|
+
if (this.selectedOptionLabel && option[this.selectedOptionLabel]) {
|
|
901
|
+
return option[this.selectedOptionLabel];
|
|
902
|
+
}
|
|
903
|
+
if (this.optionLabelSecondary && option[this.optionLabelSecondary]) {
|
|
904
|
+
return option[this.optionLabelSecondary];
|
|
905
|
+
}
|
|
906
|
+
if (this.optionLabel && option[this.optionLabel]) {
|
|
907
|
+
return option[this.optionLabel];
|
|
908
|
+
}
|
|
909
|
+
return "";
|
|
910
|
+
},
|
|
911
|
+
/**
|
|
912
|
+
* Easy lookup for each selected-option slot.
|
|
913
|
+
*/
|
|
914
|
+
getPillRow(option) {
|
|
915
|
+
const { byRef, byKey } = this.pillRowsBySlotLookup;
|
|
916
|
+
if (byRef.has(option)) {
|
|
917
|
+
return byRef.get(option);
|
|
918
|
+
}
|
|
919
|
+
const k = this.getVueSelectOptionKey(option);
|
|
920
|
+
return byKey.get(k) || null;
|
|
921
|
+
},
|
|
922
|
+
handleClearAll() {
|
|
923
|
+
this.value = [];
|
|
924
|
+
this.$emit("onSelectOptions", []);
|
|
925
|
+
this.$nextTick(() => {
|
|
926
|
+
if (this.$refs.vselect) {
|
|
927
|
+
this.$refs.vselect.search = "";
|
|
928
|
+
}
|
|
929
|
+
});
|
|
736
930
|
},
|
|
737
931
|
isChecked(option) {
|
|
738
|
-
return this.value.
|
|
932
|
+
return this.value.some(
|
|
933
|
+
(item) =>
|
|
934
|
+
item[this.primaryComparisonKey] === option[this.primaryComparisonKey]
|
|
935
|
+
)
|
|
936
|
+
? 1
|
|
937
|
+
: 0;
|
|
739
938
|
},
|
|
740
939
|
handleSingleSelect(option) {
|
|
741
940
|
if (this.addCheckBox) {
|
|
742
|
-
if (this.isChecked(option)
|
|
743
|
-
this.value = this.value.filter(
|
|
941
|
+
if (this.isChecked(option) === 1) {
|
|
942
|
+
this.value = this.value.filter(
|
|
943
|
+
(item) =>
|
|
944
|
+
item[this.primaryComparisonKey] !==
|
|
945
|
+
option[this.primaryComparisonKey]
|
|
946
|
+
);
|
|
744
947
|
} else {
|
|
745
948
|
this.value = [...this.value, option];
|
|
746
949
|
}
|
|
@@ -751,10 +954,12 @@ export default {
|
|
|
751
954
|
}
|
|
752
955
|
},
|
|
753
956
|
handleOtherOptionChange() {
|
|
754
|
-
const isSelected = this.isChecked(this.otherOption)
|
|
957
|
+
const isSelected = this.isChecked(this.otherOption) === 1;
|
|
755
958
|
if (isSelected) {
|
|
756
959
|
this.value = this.value.filter(
|
|
757
|
-
(item) =>
|
|
960
|
+
(item) =>
|
|
961
|
+
item[this.primaryComparisonKey] !==
|
|
962
|
+
this.otherOption[this.primaryComparisonKey]
|
|
758
963
|
);
|
|
759
964
|
} else {
|
|
760
965
|
this.value = [...this.value, this.otherOption];
|
|
@@ -822,6 +1027,19 @@ export default {
|
|
|
822
1027
|
}
|
|
823
1028
|
}
|
|
824
1029
|
},
|
|
1030
|
+
_updateFooterHeights() {
|
|
1031
|
+
this.$nextTick(() => {
|
|
1032
|
+
const createEl = this.$refs.createOption;
|
|
1033
|
+
const otherEl = this.$refs.otherOption;
|
|
1034
|
+
const clearEl = this.$refs.clearAllButton;
|
|
1035
|
+
|
|
1036
|
+
this.footerMetaData = {
|
|
1037
|
+
createOptionHeight: createEl ? createEl.offsetHeight : 0,
|
|
1038
|
+
otherOptionHeight: otherEl ? otherEl.offsetHeight : 0,
|
|
1039
|
+
clearAllHeight: clearEl ? clearEl.offsetHeight : 0,
|
|
1040
|
+
};
|
|
1041
|
+
});
|
|
1042
|
+
},
|
|
825
1043
|
},
|
|
826
1044
|
watch: {
|
|
827
1045
|
optionsSelected: {
|
|
@@ -830,41 +1048,52 @@ export default {
|
|
|
830
1048
|
},
|
|
831
1049
|
deep: true,
|
|
832
1050
|
},
|
|
1051
|
+
value: {
|
|
1052
|
+
handler() {
|
|
1053
|
+
this._updateFooterHeights();
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
833
1056
|
},
|
|
834
1057
|
mounted() {
|
|
835
1058
|
this.observer = new IntersectionObserver(this.infiniteScroll);
|
|
836
1059
|
},
|
|
1060
|
+
beforeDestroy() {
|
|
1061
|
+
if (this.observer) {
|
|
1062
|
+
this.observer.disconnect();
|
|
1063
|
+
this.observer = null;
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
837
1066
|
};
|
|
838
1067
|
</script>
|
|
839
1068
|
<style>
|
|
840
|
-
.disabled {
|
|
841
|
-
pointer-events: none;
|
|
842
|
-
color: #bfcbd9;
|
|
843
|
-
cursor: not-allowed;
|
|
844
|
-
background-image: none;
|
|
845
|
-
background-color: #eef1f6;
|
|
846
|
-
border-color: #d1dbe5;
|
|
847
|
-
}
|
|
848
1069
|
.v-select {
|
|
849
1070
|
@apply cursor-pointer;
|
|
850
1071
|
}
|
|
1072
|
+
|
|
851
1073
|
.vs__dropdown-toggle {
|
|
852
|
-
@apply
|
|
1074
|
+
@apply min-h-9 w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm;
|
|
853
1075
|
}
|
|
1076
|
+
|
|
854
1077
|
.vs__selected-options {
|
|
855
|
-
flex-
|
|
856
|
-
height: auto;
|
|
857
|
-
max-height: 60px;
|
|
858
|
-
overflow: hidden;
|
|
859
|
-
overflow-y: auto;
|
|
1078
|
+
@apply flex items-center gap-1.5 p-0;
|
|
860
1079
|
}
|
|
1080
|
+
|
|
1081
|
+
.c-multiselect--capped-pills .vs__selected-options {
|
|
1082
|
+
@apply min-w-0 flex-nowrap overflow-hidden;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/* Hide 3rd+ chips if they still mount (key mismatch); keeps one row */
|
|
1086
|
+
.c-multiselect--capped-pills
|
|
1087
|
+
.vs__selected-options
|
|
1088
|
+
> .vs__selected:nth-child(n + 3) {
|
|
1089
|
+
display: none !important;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
861
1092
|
.vs--open .vs__dropdown-toggle {
|
|
862
1093
|
border-bottom-color: rgba(212, 212, 216, var(--tw-border-opacity));
|
|
863
1094
|
@apply rounded-b-md;
|
|
864
1095
|
}
|
|
865
|
-
|
|
866
|
-
@apply m-0 border-none text-gray-700;
|
|
867
|
-
}
|
|
1096
|
+
|
|
868
1097
|
.extra:hover {
|
|
869
1098
|
color: white;
|
|
870
1099
|
}
|
|
@@ -912,7 +1141,7 @@ export default {
|
|
|
912
1141
|
}
|
|
913
1142
|
|
|
914
1143
|
.vs__dropdown-option--disabled {
|
|
915
|
-
@apply !
|
|
1144
|
+
@apply cursor-not-allowed !border-gray-200 !bg-gray-50 !text-gray-500 opacity-100 shadow-none;
|
|
916
1145
|
}
|
|
917
1146
|
|
|
918
1147
|
.vs__dropdown-option--disabled * {
|
|
@@ -927,11 +1156,15 @@ export default {
|
|
|
927
1156
|
@apply pointer-events-none opacity-100;
|
|
928
1157
|
}
|
|
929
1158
|
|
|
930
|
-
.vs__dropdown-toggle {
|
|
931
|
-
height: 100%;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
1159
|
.vs__no-options {
|
|
935
1160
|
@apply px-4 py-3 text-sm text-gray-500;
|
|
936
1161
|
}
|
|
1162
|
+
|
|
1163
|
+
.vs__selected {
|
|
1164
|
+
@apply m-0 border-none !bg-transparent !p-0;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
.vs__deselect {
|
|
1168
|
+
@apply m-0;
|
|
1169
|
+
}
|
|
937
1170
|
</style>
|