frappe-ui 0.1.184 → 0.1.185
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/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { Dropdown } from '../Dropdown'
|
|
|
6
6
|
import LucideSettings from '~icons/lucide/settings'
|
|
7
7
|
import LucideStar from '~icons/lucide/star'
|
|
8
8
|
import LucideChevronDown from '~icons/lucide/chevron-down'
|
|
9
|
+
import { Autocomplete } from '../Autocomplete'
|
|
9
10
|
|
|
10
11
|
const dialog1 = ref(false)
|
|
11
12
|
const dialog2 = ref(false)
|
|
@@ -17,6 +18,8 @@ const dialog6 = ref(false)
|
|
|
17
18
|
// Dropdown state
|
|
18
19
|
const selectedOption = ref('Option 1')
|
|
19
20
|
|
|
21
|
+
const autocompleteValue = ref({ label: '', value: '' })
|
|
22
|
+
|
|
20
23
|
const dropdownOptions = [
|
|
21
24
|
{
|
|
22
25
|
label: 'Option 1',
|
|
@@ -181,6 +184,16 @@ const createPromise = (): Promise<void> => {
|
|
|
181
184
|
This dialog contains interactive elements to test proper layering.
|
|
182
185
|
</p>
|
|
183
186
|
|
|
187
|
+
<Autocomplete
|
|
188
|
+
:options="[
|
|
189
|
+
{ label: 'Option A', value: 'A' },
|
|
190
|
+
{ label: 'Option B', value: 'B' },
|
|
191
|
+
{ label: 'Option C', value: 'C' },
|
|
192
|
+
]"
|
|
193
|
+
placeholder="Type to search..."
|
|
194
|
+
v-model="autocompleteValue"
|
|
195
|
+
/>
|
|
196
|
+
|
|
184
197
|
<div class="space-y-3">
|
|
185
198
|
<label class="block text-sm font-medium text-gray-700">
|
|
186
199
|
Select an option:
|
|
@@ -1,284 +1,276 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
ref="target"
|
|
5
|
-
:class="['flex', $attrs.class]"
|
|
6
|
-
@click="updatePosition"
|
|
7
|
-
@focusin="updatePosition"
|
|
8
|
-
@keydown="updatePosition"
|
|
9
|
-
@mouseover="onMouseover"
|
|
10
|
-
@mouseleave="onMouseleave"
|
|
11
|
-
>
|
|
12
|
-
<slot
|
|
13
|
-
name="target"
|
|
14
|
-
v-bind="{ togglePopover, updatePosition, open, close, isOpen }"
|
|
15
|
-
/>
|
|
16
|
-
</div>
|
|
17
|
-
<teleport to="#frappeui-popper-root">
|
|
2
|
+
<PopoverRoot v-model:open="isOpen" @update:open="onUpdateOpen">
|
|
3
|
+
<PopoverAnchor asChild>
|
|
18
4
|
<div
|
|
19
|
-
ref="
|
|
20
|
-
class="
|
|
21
|
-
|
|
22
|
-
:style="{ minWidth: targetWidth ? targetWidth + 'px' : null }"
|
|
23
|
-
@mouseover="pointerOverTargetOrPopup = true"
|
|
5
|
+
ref="anchorRef"
|
|
6
|
+
:class="['flex', $attrs.class]"
|
|
7
|
+
@mouseover="onMouseover"
|
|
24
8
|
@mouseleave="onMouseleave"
|
|
25
9
|
>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
togglePopover,
|
|
37
|
-
updatePosition,
|
|
38
|
-
open,
|
|
39
|
-
close,
|
|
40
|
-
isOpen,
|
|
41
|
-
}"
|
|
42
|
-
/>
|
|
43
|
-
</div>
|
|
44
|
-
</slot>
|
|
45
|
-
</div>
|
|
46
|
-
</transition>
|
|
10
|
+
<slot
|
|
11
|
+
name="target"
|
|
12
|
+
v-bind="{
|
|
13
|
+
togglePopover,
|
|
14
|
+
updatePosition,
|
|
15
|
+
open,
|
|
16
|
+
close,
|
|
17
|
+
isOpen,
|
|
18
|
+
}"
|
|
19
|
+
/>
|
|
47
20
|
</div>
|
|
48
|
-
</
|
|
49
|
-
|
|
21
|
+
</PopoverAnchor>
|
|
22
|
+
<PopoverPortal>
|
|
23
|
+
<PopoverContent
|
|
24
|
+
:side="placementSide"
|
|
25
|
+
:align="placementAlign"
|
|
26
|
+
:style="{
|
|
27
|
+
minWidth: 'var(--reka-popover-trigger-width)',
|
|
28
|
+
}"
|
|
29
|
+
class="PopoverContent"
|
|
30
|
+
:class="{ 'has-transition': hasTransition }"
|
|
31
|
+
@mouseover="
|
|
32
|
+
() => {
|
|
33
|
+
pointerOverTargetOrPopup = true
|
|
34
|
+
}
|
|
35
|
+
"
|
|
36
|
+
@mouseleave="onMouseleave"
|
|
37
|
+
@interact-outside="onInteractOutside"
|
|
38
|
+
>
|
|
39
|
+
<div class="relative" :class="['body-container', popoverClass]">
|
|
40
|
+
<slot
|
|
41
|
+
name="body"
|
|
42
|
+
v-bind="{ togglePopover, updatePosition, open, close, isOpen }"
|
|
43
|
+
>
|
|
44
|
+
<div class="rounded-lg border bg-surface-modal shadow-xl">
|
|
45
|
+
<slot
|
|
46
|
+
name="body-main"
|
|
47
|
+
v-bind="{
|
|
48
|
+
togglePopover,
|
|
49
|
+
updatePosition,
|
|
50
|
+
open,
|
|
51
|
+
close,
|
|
52
|
+
isOpen,
|
|
53
|
+
}"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
</slot>
|
|
57
|
+
</div>
|
|
58
|
+
</PopoverContent>
|
|
59
|
+
</PopoverPortal>
|
|
60
|
+
</PopoverRoot>
|
|
50
61
|
</template>
|
|
51
62
|
|
|
52
|
-
<script>
|
|
53
|
-
import {
|
|
63
|
+
<script setup lang="ts">
|
|
64
|
+
import { computed, ref, onUnmounted } from 'vue'
|
|
65
|
+
import {
|
|
66
|
+
PopoverAnchor,
|
|
67
|
+
PopoverContent,
|
|
68
|
+
PopoverPortal,
|
|
69
|
+
PopoverRoot,
|
|
70
|
+
} from 'reka-ui'
|
|
71
|
+
import { PopoverProps } from './types'
|
|
72
|
+
|
|
73
|
+
const props = withDefaults(defineProps<PopoverProps>(), {
|
|
74
|
+
show: undefined,
|
|
75
|
+
trigger: 'click',
|
|
76
|
+
hoverDelay: 0,
|
|
77
|
+
leaveDelay: 0.5,
|
|
78
|
+
placement: 'bottom-start',
|
|
79
|
+
popoverClass: '',
|
|
80
|
+
transition: null,
|
|
81
|
+
hideOnBlur: true,
|
|
82
|
+
})
|
|
54
83
|
|
|
55
|
-
|
|
56
|
-
|
|
84
|
+
const emit = defineEmits<{
|
|
85
|
+
(event: 'open'): void
|
|
86
|
+
(event: 'close'): void
|
|
87
|
+
(event: 'update:show', value: boolean): void
|
|
88
|
+
}>()
|
|
89
|
+
|
|
90
|
+
defineExpose({ open, close })
|
|
91
|
+
|
|
92
|
+
defineOptions({
|
|
57
93
|
inheritAttrs: false,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
type: Number,
|
|
72
|
-
default: 0,
|
|
73
|
-
},
|
|
74
|
-
placement: {
|
|
75
|
-
type: String,
|
|
76
|
-
default: 'bottom-start',
|
|
77
|
-
},
|
|
78
|
-
popoverClass: [String, Object, Array],
|
|
79
|
-
transition: {
|
|
80
|
-
default: null,
|
|
81
|
-
},
|
|
82
|
-
hideOnBlur: {
|
|
83
|
-
default: true,
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
emits: ['open', 'close', 'update:show'],
|
|
87
|
-
expose: ['open', 'close'],
|
|
88
|
-
data() {
|
|
89
|
-
return {
|
|
90
|
-
popoverContainerClass: 'body-container',
|
|
91
|
-
showPopup: false,
|
|
92
|
-
targetWidth: null,
|
|
93
|
-
pointerOverTargetOrPopup: false,
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
watch: {
|
|
97
|
-
show(val) {
|
|
98
|
-
if (val) {
|
|
99
|
-
this.open()
|
|
100
|
-
} else {
|
|
101
|
-
this.close()
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
created() {
|
|
106
|
-
if (typeof window === 'undefined') return
|
|
107
|
-
if (!document.getElementById('frappeui-popper-root')) {
|
|
108
|
-
const root = document.createElement('div')
|
|
109
|
-
root.id = 'frappeui-popper-root'
|
|
110
|
-
document.body.appendChild(root)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const _isOpen = ref(false)
|
|
97
|
+
const pointerOverTargetOrPopup = ref(false)
|
|
98
|
+
const hoverTimer = ref<number | null>(null)
|
|
99
|
+
const leaveTimer = ref<number | null>(null)
|
|
100
|
+
const anchorRef = ref<HTMLElement | null>(null)
|
|
101
|
+
|
|
102
|
+
const isOpen = computed({
|
|
103
|
+
get: () => (isShowPropPassed.value ? props.show : _isOpen.value),
|
|
104
|
+
set: (value: boolean) => {
|
|
105
|
+
if (!isShowPropPassed.value) {
|
|
106
|
+
_isOpen.value = value
|
|
111
107
|
}
|
|
108
|
+
emit('update:show', value)
|
|
112
109
|
},
|
|
113
|
-
|
|
114
|
-
this.listener = (e) => {
|
|
115
|
-
const clickedElement = e.target
|
|
116
|
-
const reference = this.$refs.reference
|
|
117
|
-
const popoverBody = this.$refs.popover
|
|
118
|
-
const insideClick =
|
|
119
|
-
clickedElement === reference ||
|
|
120
|
-
clickedElement === popoverBody ||
|
|
121
|
-
reference?.contains(clickedElement) ||
|
|
122
|
-
popoverBody?.contains(clickedElement)
|
|
123
|
-
if (insideClick) {
|
|
124
|
-
return
|
|
125
|
-
}
|
|
110
|
+
})
|
|
126
111
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return this.close()
|
|
131
|
-
}
|
|
112
|
+
const isShowPropPassed = computed(() => {
|
|
113
|
+
return props.show !== undefined
|
|
114
|
+
})
|
|
132
115
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
clickedElementBody &&
|
|
138
|
-
currentPopoverBody &&
|
|
139
|
-
clickedElementBody === currentPopoverBody
|
|
116
|
+
const placementSide = computed(() => {
|
|
117
|
+
const [side] = props.placement.split('-')
|
|
118
|
+
return side as 'top' | 'right' | 'bottom' | 'left'
|
|
119
|
+
})
|
|
140
120
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
121
|
+
const placementAlign = computed(() => {
|
|
122
|
+
const [, align] = props.placement.split('-')
|
|
123
|
+
if (!align) return 'center'
|
|
124
|
+
return align as 'start' | 'center' | 'end'
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
function togglePopover(flag?: boolean | Event) {
|
|
128
|
+
if (flag instanceof Event) {
|
|
129
|
+
flag = undefined
|
|
130
|
+
}
|
|
131
|
+
if (flag == null) {
|
|
132
|
+
flag = !isOpen.value
|
|
133
|
+
}
|
|
134
|
+
flag = Boolean(flag)
|
|
135
|
+
if (flag) {
|
|
136
|
+
open()
|
|
137
|
+
} else {
|
|
138
|
+
close()
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function updatePosition() {
|
|
143
|
+
// not needed
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function open() {
|
|
147
|
+
isOpen.value = true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function close() {
|
|
151
|
+
isOpen.value = false
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function onUpdateOpen(value: boolean) {
|
|
155
|
+
emit('update:show', value)
|
|
156
|
+
if (value) {
|
|
157
|
+
emit('open')
|
|
158
|
+
} else {
|
|
159
|
+
emit('close')
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function onMouseover() {
|
|
164
|
+
pointerOverTargetOrPopup.value = true
|
|
165
|
+
if (leaveTimer.value) {
|
|
166
|
+
clearTimeout(leaveTimer.value)
|
|
167
|
+
leaveTimer.value = null
|
|
168
|
+
}
|
|
169
|
+
if (props.trigger === 'hover') {
|
|
170
|
+
if (props.hoverDelay) {
|
|
171
|
+
hoverTimer.value = setTimeout(
|
|
172
|
+
() => {
|
|
173
|
+
if (pointerOverTargetOrPopup.value) {
|
|
174
|
+
open()
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
Number(props.hoverDelay) * 1000,
|
|
178
|
+
) as unknown as number
|
|
179
|
+
} else {
|
|
180
|
+
open()
|
|
144
181
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function onMouseleave() {
|
|
186
|
+
pointerOverTargetOrPopup.value = false
|
|
187
|
+
if (hoverTimer.value) {
|
|
188
|
+
clearTimeout(hoverTimer.value)
|
|
189
|
+
hoverTimer.value = null
|
|
190
|
+
}
|
|
191
|
+
if (props.trigger === 'hover') {
|
|
192
|
+
if (leaveTimer.value) {
|
|
193
|
+
clearTimeout(leaveTimer.value)
|
|
149
194
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
this.popper && this.popper.destroy()
|
|
156
|
-
document.removeEventListener('click', this.listener)
|
|
157
|
-
document.removeEventListener('mousedown', this.listener)
|
|
158
|
-
},
|
|
159
|
-
computed: {
|
|
160
|
-
showPropPassed() {
|
|
161
|
-
return this.show != null
|
|
162
|
-
},
|
|
163
|
-
isOpen: {
|
|
164
|
-
get() {
|
|
165
|
-
if (this.showPropPassed) {
|
|
166
|
-
return this.show
|
|
167
|
-
}
|
|
168
|
-
return this.showPopup
|
|
169
|
-
},
|
|
170
|
-
set(val) {
|
|
171
|
-
val = Boolean(val)
|
|
172
|
-
if (this.showPropPassed) {
|
|
173
|
-
this.$emit('update:show', val)
|
|
174
|
-
} else {
|
|
175
|
-
this.showPopup = val
|
|
176
|
-
}
|
|
177
|
-
if (val === false) {
|
|
178
|
-
this.$emit('close')
|
|
179
|
-
} else if (val === true) {
|
|
180
|
-
this.$emit('open')
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
popupTransition() {
|
|
185
|
-
let templates = {
|
|
186
|
-
default: {
|
|
187
|
-
enterActiveClass: 'transition duration-150 ease-out',
|
|
188
|
-
enterFromClass: 'translate-y-1 opacity-0',
|
|
189
|
-
enterToClass: 'translate-y-0 opacity-100',
|
|
190
|
-
leaveActiveClass: 'transition duration-150 ease-in',
|
|
191
|
-
leaveFromClass: 'translate-y-0 opacity-100',
|
|
192
|
-
leaveToClass: 'translate-y-1 opacity-0',
|
|
193
|
-
},
|
|
194
|
-
}
|
|
195
|
-
if (typeof this.transition === 'string') {
|
|
196
|
-
return templates[this.transition]
|
|
197
|
-
}
|
|
198
|
-
return this.transition
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
methods: {
|
|
202
|
-
setupPopper() {
|
|
203
|
-
if (!this.popper) {
|
|
204
|
-
this.popper = createPopper(this.$refs.reference, this.$refs.popover, {
|
|
205
|
-
placement: this.placement,
|
|
206
|
-
})
|
|
207
|
-
} else {
|
|
208
|
-
this.updatePosition()
|
|
209
|
-
}
|
|
210
|
-
},
|
|
211
|
-
updatePosition() {
|
|
212
|
-
this.popper && this.popper.update()
|
|
213
|
-
},
|
|
214
|
-
togglePopover(flag) {
|
|
215
|
-
if (flag instanceof Event) {
|
|
216
|
-
flag = null
|
|
217
|
-
}
|
|
218
|
-
if (flag == null) {
|
|
219
|
-
flag = !this.isOpen
|
|
220
|
-
}
|
|
221
|
-
flag = Boolean(flag)
|
|
222
|
-
if (flag) {
|
|
223
|
-
this.open()
|
|
224
|
-
} else {
|
|
225
|
-
this.close()
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
open() {
|
|
229
|
-
this.isOpen = true
|
|
230
|
-
this.$nextTick(() => this.setupPopper())
|
|
231
|
-
},
|
|
232
|
-
close() {
|
|
233
|
-
this.isOpen = false
|
|
234
|
-
},
|
|
235
|
-
onMouseover() {
|
|
236
|
-
this.pointerOverTargetOrPopup = true
|
|
237
|
-
if (this.leaveTimer) {
|
|
238
|
-
clearTimeout(this.leaveTimer)
|
|
239
|
-
this.leaveTimer = null
|
|
240
|
-
}
|
|
241
|
-
if (this.trigger === 'hover') {
|
|
242
|
-
if (this.hoverDelay) {
|
|
243
|
-
this.hoverTimer = setTimeout(
|
|
244
|
-
() => {
|
|
245
|
-
if (this.pointerOverTargetOrPopup) {
|
|
246
|
-
this.open()
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
Number(this.hoverDelay) * 1000,
|
|
250
|
-
)
|
|
251
|
-
} else {
|
|
252
|
-
this.open()
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
onMouseleave(e) {
|
|
257
|
-
this.pointerOverTargetOrPopup = false
|
|
258
|
-
if (this.hoverTimer) {
|
|
259
|
-
clearTimeout(this.hoverTimer)
|
|
260
|
-
this.hoverTimer = null
|
|
261
|
-
}
|
|
262
|
-
if (this.trigger === 'hover') {
|
|
263
|
-
if (this.leaveTimer) {
|
|
264
|
-
clearTimeout(this.leaveTimer)
|
|
265
|
-
}
|
|
266
|
-
if (this.leaveDelay) {
|
|
267
|
-
this.leaveTimer = setTimeout(
|
|
268
|
-
() => {
|
|
269
|
-
if (!this.pointerOverTargetOrPopup) {
|
|
270
|
-
this.close()
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
Number(this.leaveDelay) * 1000,
|
|
274
|
-
)
|
|
275
|
-
} else {
|
|
276
|
-
if (!this.pointerOverTargetOrPopup) {
|
|
277
|
-
this.close()
|
|
195
|
+
if (props.leaveDelay) {
|
|
196
|
+
leaveTimer.value = setTimeout(
|
|
197
|
+
() => {
|
|
198
|
+
if (!pointerOverTargetOrPopup.value) {
|
|
199
|
+
close()
|
|
278
200
|
}
|
|
279
|
-
}
|
|
201
|
+
},
|
|
202
|
+
Number(props.leaveDelay) * 1000,
|
|
203
|
+
) as unknown as number
|
|
204
|
+
} else {
|
|
205
|
+
if (!pointerOverTargetOrPopup.value) {
|
|
206
|
+
close()
|
|
280
207
|
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function onInteractOutside(event: Event) {
|
|
213
|
+
if (!props.hideOnBlur) {
|
|
214
|
+
event.preventDefault()
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check if the click is on the trigger/anchor element
|
|
219
|
+
const target = event.target as Element
|
|
220
|
+
if (
|
|
221
|
+
anchorRef.value &&
|
|
222
|
+
(anchorRef.value.contains(target) || anchorRef.value === target)
|
|
223
|
+
) {
|
|
224
|
+
event.preventDefault()
|
|
225
|
+
return
|
|
226
|
+
}
|
|
283
227
|
}
|
|
228
|
+
|
|
229
|
+
const hasTransition = computed(() => {
|
|
230
|
+
return props.transition === 'default'
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// Cleanup timers on unmount
|
|
234
|
+
onUnmounted(() => {
|
|
235
|
+
if (hoverTimer.value) {
|
|
236
|
+
clearTimeout(hoverTimer.value)
|
|
237
|
+
}
|
|
238
|
+
if (leaveTimer.value) {
|
|
239
|
+
clearTimeout(leaveTimer.value)
|
|
240
|
+
}
|
|
241
|
+
})
|
|
284
242
|
</script>
|
|
243
|
+
|
|
244
|
+
<style>
|
|
245
|
+
/* Default transition animations */
|
|
246
|
+
@keyframes popover-enter {
|
|
247
|
+
from {
|
|
248
|
+
opacity: 0;
|
|
249
|
+
transform: translateY(4px);
|
|
250
|
+
}
|
|
251
|
+
to {
|
|
252
|
+
opacity: 1;
|
|
253
|
+
transform: translateY(0);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@keyframes popover-exit {
|
|
258
|
+
from {
|
|
259
|
+
opacity: 1;
|
|
260
|
+
transform: translateY(0);
|
|
261
|
+
}
|
|
262
|
+
to {
|
|
263
|
+
opacity: 0;
|
|
264
|
+
transform: translateY(4px);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Default transition */
|
|
269
|
+
.PopoverContent.has-transition[data-state='open'] {
|
|
270
|
+
animation: popover-enter 150ms ease-out;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.PopoverContent.has-transition[data-state='closed'] {
|
|
274
|
+
animation: popover-exit 150ms ease-in;
|
|
275
|
+
}
|
|
276
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface PopoverProps {
|
|
2
|
+
show?: boolean
|
|
3
|
+
trigger?: 'click' | 'hover'
|
|
4
|
+
hoverDelay?: number
|
|
5
|
+
leaveDelay?: number
|
|
6
|
+
placement?:
|
|
7
|
+
| 'top-start'
|
|
8
|
+
| 'top-end'
|
|
9
|
+
| 'bottom-start'
|
|
10
|
+
| 'bottom-end'
|
|
11
|
+
| 'right-start'
|
|
12
|
+
| 'right-end'
|
|
13
|
+
| 'left-start'
|
|
14
|
+
| 'left-end'
|
|
15
|
+
popoverClass?: string | object | Array<string | object>
|
|
16
|
+
transition?: 'default' | null
|
|
17
|
+
hideOnBlur?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface PopoverEmits {
|
|
21
|
+
(event: 'open'): void
|
|
22
|
+
(event: 'close'): void
|
|
23
|
+
(event: 'update:show', value: boolean): void
|
|
24
|
+
}
|