js-kompo-utils 1.0.24 → 1.0.25
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/VlSelect.vue +98 -10
- package/package.json +1 -1
package/components/VlSelect.vue
CHANGED
|
@@ -27,9 +27,11 @@
|
|
|
27
27
|
class="vlNativeSelect"
|
|
28
28
|
:value="nativeValue"
|
|
29
29
|
@change="onNativeChange"
|
|
30
|
+
@mousedown="onNativeOpen"
|
|
31
|
+
@focus="onNativeOpen"
|
|
30
32
|
:style="nativeSelectStyle">
|
|
31
33
|
<option value="">{{ nativePlaceholder }}</option>
|
|
32
|
-
<option v-for="opt in
|
|
34
|
+
<option v-for="opt in nativeOptionsList" :key="opt.value" :value="opt.value">{{ nativeLabel(opt) }}</option>
|
|
33
35
|
</select>
|
|
34
36
|
</div>
|
|
35
37
|
<div class="vlOptions vlOptionsTeleported"
|
|
@@ -86,7 +88,10 @@ export default {
|
|
|
86
88
|
},
|
|
87
89
|
useNativeMobile() {
|
|
88
90
|
if (!this.$_config('native_on_mobile')) return false
|
|
89
|
-
return this.isTouchDevice && !this.$_multiple
|
|
91
|
+
return this.isTouchDevice && !this.$_multiple
|
|
92
|
+
},
|
|
93
|
+
nativeOptionsList() {
|
|
94
|
+
return this.ajaxOptions ? this.filteredOptions : this.options
|
|
90
95
|
},
|
|
91
96
|
nativeValue() {
|
|
92
97
|
return this.$_value && this.$_value.length ? this.$_value[0].value : ''
|
|
@@ -121,12 +126,21 @@ export default {
|
|
|
121
126
|
filteredOptions() {
|
|
122
127
|
if (this.isFocused) this.$nextTick(() => this.refresh())
|
|
123
128
|
},
|
|
129
|
+
optionsKey() {
|
|
130
|
+
this.$nextTick(() => {
|
|
131
|
+
this.teleportOptions()
|
|
132
|
+
if (this.isFocused) this.refresh()
|
|
133
|
+
})
|
|
134
|
+
},
|
|
124
135
|
},
|
|
125
136
|
mounted() {
|
|
126
137
|
this.teleportOptions()
|
|
127
138
|
if (typeof window !== 'undefined' && window.matchMedia) {
|
|
128
139
|
this.isTouchDevice = window.matchMedia('(pointer: coarse)').matches
|
|
129
140
|
}
|
|
141
|
+
if (this.useNativeMobile && this.ajaxOptions) {
|
|
142
|
+
this.$nextTick(() => this.onNativeOpen())
|
|
143
|
+
}
|
|
130
144
|
},
|
|
131
145
|
beforeDestroy() {
|
|
132
146
|
this.cleanupOptions()
|
|
@@ -136,9 +150,19 @@ export default {
|
|
|
136
150
|
onNativeChange(e) {
|
|
137
151
|
const v = e.target.value
|
|
138
152
|
if (v === '') return
|
|
139
|
-
const
|
|
153
|
+
const list = this.nativeOptionsList || []
|
|
154
|
+
const opt = list.find(o => String(o.value) === String(v))
|
|
140
155
|
if (opt) this.select(opt)
|
|
141
156
|
},
|
|
157
|
+
onNativeOpen() {
|
|
158
|
+
if (!this.ajaxOptions) return
|
|
159
|
+
if (this.ajaxOptionsFromField) {
|
|
160
|
+
this.$kompo.vlRequestFieldValue(this.kompoid, this.ajaxOptionsFromField, this.$_elKompoId)
|
|
161
|
+
this.performAjax(this.$_getFromStore())
|
|
162
|
+
} else {
|
|
163
|
+
this.performAjax('')
|
|
164
|
+
}
|
|
165
|
+
},
|
|
142
166
|
nativeLabel(opt) {
|
|
143
167
|
const l = opt.label
|
|
144
168
|
let raw = ''
|
|
@@ -171,22 +195,82 @@ export default {
|
|
|
171
195
|
},
|
|
172
196
|
attachListeners() {
|
|
173
197
|
if (this._listenersAttached) return
|
|
198
|
+
this._rafId = null
|
|
174
199
|
this._onScroll = (e) => {
|
|
175
200
|
const opts = this.$refs.selectOptions
|
|
176
201
|
if (opts && e.target instanceof Node && opts.contains(e.target)) return
|
|
177
|
-
this.
|
|
202
|
+
if (this._rafId) return
|
|
203
|
+
this._rafId = requestAnimationFrame(() => {
|
|
204
|
+
this._rafId = null
|
|
205
|
+
this.trackPosition()
|
|
206
|
+
})
|
|
178
207
|
}
|
|
179
208
|
this._onResize = () => this.refresh()
|
|
180
209
|
window.addEventListener('scroll', this._onScroll, true)
|
|
181
210
|
window.addEventListener('resize', this._onResize, { passive: true })
|
|
211
|
+
|
|
212
|
+
const opts = this.$refs.selectOptions
|
|
213
|
+
const anchor = this.anchorEl()
|
|
214
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
215
|
+
this._panelObserver = new ResizeObserver(() => {
|
|
216
|
+
if (this.isFocused) this.trackPosition()
|
|
217
|
+
})
|
|
218
|
+
if (opts) this._panelObserver.observe(opts)
|
|
219
|
+
this._anchorObserver = new ResizeObserver((entries) => {
|
|
220
|
+
const entry = entries[0]
|
|
221
|
+
if (!entry) return
|
|
222
|
+
const r = entry.contentRect
|
|
223
|
+
const el = entry.target
|
|
224
|
+
if (r.width === 0 || r.height === 0 || !el.isConnected) {
|
|
225
|
+
this.blur()
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
if (anchor) this._anchorObserver.observe(anchor)
|
|
229
|
+
}
|
|
230
|
+
if (typeof IntersectionObserver !== 'undefined' && anchor) {
|
|
231
|
+
this._anchorIntersection = new IntersectionObserver((entries) => {
|
|
232
|
+
const entry = entries[entries.length - 1]
|
|
233
|
+
if (entry && entry.intersectionRatio === 0) this.blur()
|
|
234
|
+
}, { threshold: 0 })
|
|
235
|
+
this._anchorIntersection.observe(anchor)
|
|
236
|
+
}
|
|
237
|
+
|
|
182
238
|
this._listenersAttached = true
|
|
183
239
|
},
|
|
184
240
|
detachListeners() {
|
|
185
241
|
if (!this._listenersAttached) return
|
|
242
|
+
if (this._rafId) {
|
|
243
|
+
cancelAnimationFrame(this._rafId)
|
|
244
|
+
this._rafId = null
|
|
245
|
+
}
|
|
186
246
|
window.removeEventListener('scroll', this._onScroll, true)
|
|
187
247
|
window.removeEventListener('resize', this._onResize)
|
|
248
|
+
if (this._panelObserver) {
|
|
249
|
+
this._panelObserver.disconnect()
|
|
250
|
+
this._panelObserver = null
|
|
251
|
+
}
|
|
252
|
+
if (this._anchorObserver) {
|
|
253
|
+
this._anchorObserver.disconnect()
|
|
254
|
+
this._anchorObserver = null
|
|
255
|
+
}
|
|
256
|
+
if (this._anchorIntersection) {
|
|
257
|
+
this._anchorIntersection.disconnect()
|
|
258
|
+
this._anchorIntersection = null
|
|
259
|
+
}
|
|
188
260
|
this._listenersAttached = false
|
|
189
261
|
},
|
|
262
|
+
trackPosition() {
|
|
263
|
+
const opts = this.$refs.selectOptions
|
|
264
|
+
const anchor = this.anchorEl()
|
|
265
|
+
if (!opts || !anchor) return
|
|
266
|
+
const rect = anchor.getBoundingClientRect()
|
|
267
|
+
const x = Math.round(rect.left)
|
|
268
|
+
const y = this.flipUp
|
|
269
|
+
? Math.round(rect.top) - opts.offsetHeight + 1
|
|
270
|
+
: Math.round(rect.bottom) - 1
|
|
271
|
+
opts.style.transform = `translate3d(${x}px, ${y}px, 0)`
|
|
272
|
+
opts.style.width = Math.round(rect.width) + 'px'
|
|
273
|
+
},
|
|
190
274
|
refresh() {
|
|
191
275
|
const opts = this.$refs.selectOptions
|
|
192
276
|
const anchor = this.anchorEl()
|
|
@@ -194,13 +278,17 @@ export default {
|
|
|
194
278
|
|
|
195
279
|
const rect = anchor.getBoundingClientRect()
|
|
196
280
|
const inOverlay = !!anchor.closest('.kompoModal, .kompoDrawer, .vl-sidebar-l')
|
|
281
|
+
const x = Math.round(rect.left)
|
|
282
|
+
const yBelow = Math.round(rect.bottom) - 1
|
|
197
283
|
const baseStyle = {
|
|
198
284
|
position: 'fixed',
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
zIndex: inOverlay ? 5001 : 1000,
|
|
202
|
-
top: rect.bottom + 'px',
|
|
285
|
+
top: '0px',
|
|
286
|
+
left: '0px',
|
|
203
287
|
bottom: 'auto',
|
|
288
|
+
width: Math.round(rect.width) + 'px',
|
|
289
|
+
zIndex: inOverlay ? 5001 : 1000,
|
|
290
|
+
transform: `translate3d(${x}px, ${yBelow}px, 0)`,
|
|
291
|
+
willChange: 'transform',
|
|
204
292
|
}
|
|
205
293
|
this.panelStyle = baseStyle
|
|
206
294
|
|
|
@@ -211,10 +299,10 @@ export default {
|
|
|
211
299
|
const shouldFlip = this.forceUp || (spaceBelow < optsHeight && spaceAbove > spaceBelow)
|
|
212
300
|
this.flipUp = shouldFlip
|
|
213
301
|
if (shouldFlip) {
|
|
302
|
+
const yAbove = Math.round(rect.top) - optsHeight + 1
|
|
214
303
|
this.panelStyle = {
|
|
215
304
|
...baseStyle,
|
|
216
|
-
|
|
217
|
-
bottom: (window.innerHeight - rect.top) + 'px',
|
|
305
|
+
transform: `translate3d(${x}px, ${yAbove}px, 0)`,
|
|
218
306
|
borderRadius: '5px 5px 0 0',
|
|
219
307
|
}
|
|
220
308
|
}
|