js-kompo-utils 1.0.21 → 1.0.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.
- package/components/VlDropdown.vue +14 -20
- package/components/VlSelect.vue +75 -27
- package/package.json +1 -1
|
@@ -63,6 +63,9 @@ export default {
|
|
|
63
63
|
shouldShowMenu(visible) {
|
|
64
64
|
if (visible) {
|
|
65
65
|
this.updatePosition()
|
|
66
|
+
this.attachListeners()
|
|
67
|
+
} else {
|
|
68
|
+
this.detachListeners()
|
|
66
69
|
}
|
|
67
70
|
if (!visible && this.openOnClick) {
|
|
68
71
|
this.open = false
|
|
@@ -147,11 +150,10 @@ export default {
|
|
|
147
150
|
},
|
|
148
151
|
mounted() {
|
|
149
152
|
this.teleportMenu()
|
|
150
|
-
this.setupListeners()
|
|
151
153
|
},
|
|
152
154
|
beforeDestroy() {
|
|
153
155
|
this.cleanupMenu()
|
|
154
|
-
this.
|
|
156
|
+
this.detachListeners()
|
|
155
157
|
},
|
|
156
158
|
methods:{
|
|
157
159
|
teleportMenu() {
|
|
@@ -182,27 +184,19 @@ export default {
|
|
|
182
184
|
clearTimeout(this._closeTimeout)
|
|
183
185
|
}
|
|
184
186
|
},
|
|
185
|
-
|
|
186
|
-
this.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
this._resizeHandler = () => {
|
|
192
|
-
if (this.shouldShowMenu) {
|
|
193
|
-
this.updatePosition()
|
|
194
|
-
}
|
|
195
|
-
}
|
|
187
|
+
attachListeners() {
|
|
188
|
+
if (this._listenersAttached) return
|
|
189
|
+
this._scrollHandler = () => requestAnimationFrame(() => this.updatePosition())
|
|
190
|
+
this._resizeHandler = () => this.updatePosition()
|
|
196
191
|
window.addEventListener('scroll', this._scrollHandler, true)
|
|
197
192
|
window.addEventListener('resize', this._resizeHandler, { passive: true })
|
|
193
|
+
this._listenersAttached = true
|
|
198
194
|
},
|
|
199
|
-
|
|
200
|
-
if (this.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
window.removeEventListener('resize', this._resizeHandler)
|
|
205
|
-
}
|
|
195
|
+
detachListeners() {
|
|
196
|
+
if (!this._listenersAttached) return
|
|
197
|
+
window.removeEventListener('scroll', this._scrollHandler, true)
|
|
198
|
+
window.removeEventListener('resize', this._resizeHandler)
|
|
199
|
+
this._listenersAttached = false
|
|
206
200
|
},
|
|
207
201
|
updatePosition() {
|
|
208
202
|
const root = this.$refs.dropdownRoot
|
package/components/VlSelect.vue
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
<vlTaggableInput
|
|
4
4
|
v-click-out="blur"
|
|
5
5
|
v-bind="$_taggableInputAttributes"
|
|
6
|
-
v-on="$_taggableInputEvents"
|
|
6
|
+
v-on="$_taggableInputEvents"
|
|
7
|
+
ref="taggableInput">
|
|
7
8
|
<template v-slot:prepend v-if="$_icon">
|
|
8
9
|
<div v-bind="prependIcon" />
|
|
9
10
|
</template>
|
|
@@ -21,11 +22,11 @@
|
|
|
21
22
|
<div v-html="appendIcon"/>
|
|
22
23
|
</template>
|
|
23
24
|
</vlTaggableInput>
|
|
24
|
-
<div class="vlOptions"
|
|
25
|
+
<div class="vlOptions vlOptionsTeleported"
|
|
25
26
|
:key="optionsKey"
|
|
26
27
|
ref="selectOptions"
|
|
27
28
|
:style="optionsStyle"
|
|
28
|
-
:class="{ 'vlOptionsFlipUp': flipUp }">
|
|
29
|
+
:class="{ 'vlOptionsFlipUp': flipUp, 'vlOptionsVisible': isFocused }">
|
|
29
30
|
<template v-if="filteredOptions.length">
|
|
30
31
|
<div v-for="(option,key) in filteredOptions" :key="option.value" :ref="key"
|
|
31
32
|
class="vlOption"
|
|
@@ -58,7 +59,7 @@ export default {
|
|
|
58
59
|
data() {
|
|
59
60
|
return {
|
|
60
61
|
flipUp: false,
|
|
61
|
-
|
|
62
|
+
panelStyle: null,
|
|
62
63
|
}
|
|
63
64
|
},
|
|
64
65
|
computed: {
|
|
@@ -69,51 +70,98 @@ export default {
|
|
|
69
70
|
return !!this.$_config('openUpward')
|
|
70
71
|
},
|
|
71
72
|
optionsStyle() {
|
|
72
|
-
if (this.
|
|
73
|
-
|
|
74
|
-
return { top: 'auto', bottom: '100%', borderRadius: '5px 5px 0 0' }
|
|
75
|
-
}
|
|
76
|
-
return {}
|
|
73
|
+
if (!this.isFocused || !this.panelStyle) return { display: 'none' }
|
|
74
|
+
return this.panelStyle
|
|
77
75
|
},
|
|
78
76
|
},
|
|
79
77
|
watch: {
|
|
80
78
|
isFocused(focused) {
|
|
81
79
|
if (focused) {
|
|
82
80
|
this.$nextTick(() => this.refresh())
|
|
81
|
+
this.attachListeners()
|
|
83
82
|
} else {
|
|
84
83
|
this.flipUp = false
|
|
85
|
-
this.
|
|
84
|
+
this.panelStyle = null
|
|
85
|
+
this.detachListeners()
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
filteredOptions() {
|
|
89
89
|
if (this.isFocused) this.$nextTick(() => this.refresh())
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
|
+
mounted() {
|
|
93
|
+
this.teleportOptions()
|
|
94
|
+
},
|
|
95
|
+
beforeDestroy() {
|
|
96
|
+
this.cleanupOptions()
|
|
97
|
+
this.detachListeners()
|
|
98
|
+
},
|
|
92
99
|
methods: {
|
|
100
|
+
teleportOptions() {
|
|
101
|
+
const opts = this.$refs.selectOptions
|
|
102
|
+
if (opts && opts.parentNode !== document.body) {
|
|
103
|
+
document.body.appendChild(opts)
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
cleanupOptions() {
|
|
107
|
+
const opts = this.$refs.selectOptions
|
|
108
|
+
if (opts && opts.parentNode === document.body) {
|
|
109
|
+
document.body.removeChild(opts)
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
anchorEl() {
|
|
113
|
+
return this.$refs.taggableInput?.$el || this.$refs.input?.parentElement
|
|
114
|
+
},
|
|
115
|
+
attachListeners() {
|
|
116
|
+
if (this._listenersAttached) return
|
|
117
|
+
this._onScroll = (e) => {
|
|
118
|
+
const opts = this.$refs.selectOptions
|
|
119
|
+
if (opts && e.target instanceof Node && opts.contains(e.target)) return
|
|
120
|
+
this.blur()
|
|
121
|
+
}
|
|
122
|
+
this._onResize = () => this.refresh()
|
|
123
|
+
window.addEventListener('scroll', this._onScroll, true)
|
|
124
|
+
window.addEventListener('resize', this._onResize, { passive: true })
|
|
125
|
+
this._listenersAttached = true
|
|
126
|
+
},
|
|
127
|
+
detachListeners() {
|
|
128
|
+
if (!this._listenersAttached) return
|
|
129
|
+
window.removeEventListener('scroll', this._onScroll, true)
|
|
130
|
+
window.removeEventListener('resize', this._onResize)
|
|
131
|
+
this._listenersAttached = false
|
|
132
|
+
},
|
|
93
133
|
refresh() {
|
|
94
134
|
const opts = this.$refs.selectOptions
|
|
95
|
-
const anchor =
|
|
135
|
+
const anchor = this.anchorEl()
|
|
96
136
|
if (!opts || !anchor) return
|
|
97
137
|
|
|
98
138
|
const rect = anchor.getBoundingClientRect()
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
139
|
+
const inOverlay = !!anchor.closest('.kompoModal, .kompoDrawer, .vl-sidebar-l')
|
|
140
|
+
const baseStyle = {
|
|
141
|
+
position: 'fixed',
|
|
142
|
+
left: rect.left + 'px',
|
|
143
|
+
width: rect.width + 'px',
|
|
144
|
+
zIndex: inOverlay ? 5001 : 1000,
|
|
145
|
+
top: rect.bottom + 'px',
|
|
146
|
+
bottom: 'auto',
|
|
147
|
+
}
|
|
148
|
+
this.panelStyle = baseStyle
|
|
103
149
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
150
|
+
this.$nextTick(() => {
|
|
151
|
+
const optsHeight = opts.offsetHeight
|
|
152
|
+
const spaceBelow = window.innerHeight - rect.bottom
|
|
153
|
+
const spaceAbove = rect.top
|
|
154
|
+
const shouldFlip = this.forceUp || (spaceBelow < optsHeight && spaceAbove > spaceBelow)
|
|
155
|
+
this.flipUp = shouldFlip
|
|
156
|
+
if (shouldFlip) {
|
|
157
|
+
this.panelStyle = {
|
|
158
|
+
...baseStyle,
|
|
159
|
+
top: 'auto',
|
|
160
|
+
bottom: (window.innerHeight - rect.top) + 'px',
|
|
161
|
+
borderRadius: '5px 5px 0 0',
|
|
162
|
+
}
|
|
113
163
|
}
|
|
114
|
-
}
|
|
115
|
-
this.overlayStyle = null
|
|
116
|
-
}
|
|
164
|
+
})
|
|
117
165
|
},
|
|
118
166
|
},
|
|
119
167
|
}
|