32
32
/>
33
33
</div >
34
34
</div >
35
- <div v-if =" showDropdown" ref =" dropdownEl" :style =" dropdownStyle" :class =" {'shadow-none': isTop}"
36
- class =" absolute z-10 mt-1 w-full bg-white shadow-lg dark:shadow-black dark:bg-gray-700
35
+ <teleport to =" body" v-if =" teleportToBody && showDropdown" >
36
+ <div ref =" dropdownEl" :style =" getDropdownPosition" :class =" {'shadow-none': isTop}"
37
+ class =" fixed z-50 w-full bg-white shadow-lg dark:shadow-black dark:bg-gray-700
38
+ dark:border-gray-600 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm max-h-48" >
39
+ <div
40
+ v-for =" item in filteredItems"
41
+ :key =" item.value"
42
+ class =" px-4 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-400"
43
+ :class =" { 'bg-lightPrimaryOpacity dark:bg-darkPrimaryOpacity': selectedItems.includes(item) }"
44
+ @click =" toogleItem(item)"
45
+ >
46
+ <slot name =" item" :option =" item" ></slot >
47
+ <label v-if =" !$slots.item" :for =" item.value" >{{ item.label }}</label >
48
+ </div >
49
+ <div v-if =" !filteredItems.length" class =" px-4 py-2 cursor-pointer text-gray-400 dark:text-gray-300" >
50
+ {{ options.length ? $t('No results found') : $t('No items here') }}
51
+ </div >
52
+
53
+ <div v-if =" $slots['extra-item']" class =" px-4 py-2 dark:text-gray-400" >
54
+ <slot name =" extra-item" ></slot >
55
+ </div >
56
+ </div >
57
+ </teleport >
58
+
59
+ <div v-if =" !teleportToBody && showDropdown" ref =" dropdownEl" :style =" dropdownStyle" :class =" {'shadow-none': isTop}"
60
+ class =" absolute z-10 mt-1 w-full bg-white shadow-lg dark:shadow-black dark:bg-gray-700
37
61
dark:border-gray-600 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm max-h-48" >
38
62
<div
39
63
v-for =" item in filteredItems"
@@ -106,6 +130,10 @@ const props = defineProps({
106
130
type: Boolean ,
107
131
default: false ,
108
132
},
133
+ teleportToBody: {
134
+ type: Boolean ,
135
+ default: true ,
136
+ },
109
137
});
110
138
111
139
const emit = defineEmits ([' update:modelValue' ]);
@@ -242,4 +270,20 @@ onUnmounted(() => {
242
270
removeClickListener ();
243
271
});
244
272
273
+ const getDropdownPosition = computed (() => {
274
+ if (! inputEl .value ) return {};
275
+ const rect = inputEl .value .getBoundingClientRect ();
276
+ const style: { left: string ; top: string ; width: string } = {
277
+ left: ` ${rect .left }px ` ,
278
+ top: ` ${rect .bottom + 8 }px ` ,
279
+ width: ` ${rect .width }px `
280
+ };
281
+
282
+ if (isTop .value && dropdownHeight .value ) {
283
+ style .top = ` ${rect .top - dropdownHeight .value - 8 }px ` ;
284
+ }
285
+
286
+ return style ;
287
+ });
288
+
245
289
</script >
0 commit comments