vite-plugin-vue-devtools 0.3.2 → 0.4.2
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/client/assets/{IframeView.vue_vue_type_script_setup_true_lang-73bb0458.js → IframeView.vue_vue_type_script_setup_true_lang-3efd85cd.js} +1 -1
- package/dist/client/assets/{StateFields.vue_vue_type_script_setup_true_lang-7733bfe8.js → StateFields.vue_vue_type_script_setup_true_lang-71b04a17.js} +4 -4
- package/dist/client/assets/{VIcon.vue_vue_type_script_setup_true_lang-844d8389.js → VIcon.vue_vue_type_script_setup_true_lang-bbd0395c.js} +1 -1
- package/dist/client/assets/{VIconButton.vue_vue_type_script_setup_true_lang-a2115df4.js → VIconButton.vue_vue_type_script_setup_true_lang-6f019c5b.js} +2 -2
- package/dist/client/assets/{VIconTitle.vue_vue_type_script_setup_true_lang-64110af4.js → VIconTitle.vue_vue_type_script_setup_true_lang-6c2f93bc.js} +1 -1
- package/dist/client/assets/{VPanelGrids-3a29966d.js → VPanelGrids-3d676ac1.js} +1 -1
- package/dist/client/assets/{VSectionBlock-b2b47991.js → VSectionBlock-ce3de44c.js} +3 -3
- package/dist/client/assets/{VTextInput.vue_vue_type_script_setup_true_lang-4ab475b0.js → VTextInput.vue_vue_type_script_setup_true_lang-387f21cb.js} +2 -2
- package/dist/client/assets/{__eyedropper-6c4f6cec.js → __eyedropper-e1877d6a.js} +2 -2
- package/dist/client/assets/{assets-c9b4a91c.js → assets-04d079f5.js} +8 -8
- package/dist/client/assets/{component-docs-f1e0f42d.js → component-docs-cb9ad5a2.js} +5 -5
- package/dist/client/assets/{components-8ce879b4.js → components-733e029a.js} +7 -7
- package/dist/client/assets/{documentations-8713b916.js → documentations-7d8323ed.js} +3 -3
- package/dist/client/assets/{graph-e31a8b10.js → graph-586e0cca.js} +2 -2
- package/dist/client/assets/{index-bfd864c8.js → index-5bdd8c01.js} +1 -1
- package/dist/client/assets/{index-5b7de771.css → index-99f31726.css} +1 -1
- package/dist/client/assets/{index-c8859523.js → index-fab050dd.js} +37 -49
- package/dist/client/assets/{inspect-0a6da43a.js → inspect-7b1f893a.js} +3 -3
- package/dist/client/assets/{npm-e3775c67.js → npm-068b3ea8.js} +6 -6
- package/dist/client/assets/{overview-d353d21c.js → overview-44a22030.js} +5 -5
- package/dist/client/assets/{pages-ce241043.js → pages-635198da.js} +5 -5
- package/dist/client/assets/{pinia-0dfabc87.js → pinia-f7635d5a.js} +6 -6
- package/dist/client/assets/{routes-2d8be0cc.js → routes-78f604b2.js} +7 -7
- package/dist/client/assets/{rpc-b60055dd.js → rpc-a4b59d16.js} +1 -1
- package/dist/client/assets/{settings-a79cec1c.js → settings-1082abbf.js} +3 -3
- package/dist/client/assets/{splitpanes.es-292c6c8e.js → splitpanes.es-8025e7b0.js} +1 -1
- package/dist/client/assets/{timeline-24b68a77.js → timeline-2dc5c96b.js} +7 -7
- package/dist/client/index.html +2 -2
- package/package.json +2 -1
- package/src/node/app.js +1 -1
- package/src/node/views/FrameBox.vue +212 -0
- package/src/node/views/Main.vue +382 -0
- package/src/node/views/composables.ts +402 -0
- package/src/node/views/utils.ts +204 -0
- package/dist/client/assets/__inspecting-27cecddb.js +0 -51
- package/src/node/Container.vue +0 -604
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { computed, onMounted, reactive, ref, shallowRef, watchEffect } from 'vue'
|
|
2
|
+
import type { CSSProperties, Ref } from 'vue'
|
|
3
|
+
import type { DevToolsFrameState } from '../../client/composables/state'
|
|
4
|
+
import { FRAME_STATE_STORAGE_KEY } from '../../client/constants'
|
|
5
|
+
import { clamp, useObjectStorage, useScreenSafeArea, useWindowEventListener } from './utils'
|
|
6
|
+
|
|
7
|
+
// ---- state ----
|
|
8
|
+
export const PANEL_PADDING = 10
|
|
9
|
+
export const PANEL_MIN = 20
|
|
10
|
+
export const PANEL_MAX = 100
|
|
11
|
+
|
|
12
|
+
export const popupWindow = shallowRef<Window | null>(null)
|
|
13
|
+
|
|
14
|
+
export const state = useObjectStorage<DevToolsFrameState>(FRAME_STATE_STORAGE_KEY, {
|
|
15
|
+
width: 80,
|
|
16
|
+
height: 60,
|
|
17
|
+
top: 0,
|
|
18
|
+
left: 50,
|
|
19
|
+
open: false,
|
|
20
|
+
route: '/',
|
|
21
|
+
position: 'bottom',
|
|
22
|
+
isFirstVisit: true,
|
|
23
|
+
closeOnOutsideClick: false,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// ---- useIframe ----
|
|
27
|
+
export function useIframe(clientUrl: string, onLoad: () => void) {
|
|
28
|
+
const iframe = ref<HTMLIFrameElement>()
|
|
29
|
+
function getIframe() {
|
|
30
|
+
if (iframe.value)
|
|
31
|
+
return iframe.value
|
|
32
|
+
iframe.value = document.createElement('iframe')
|
|
33
|
+
iframe.value.id = 'vue-devtools-iframe'
|
|
34
|
+
iframe.value.src = clientUrl
|
|
35
|
+
iframe.value.setAttribute('data-v-inspector-ignore', 'true')
|
|
36
|
+
iframe.value.onload = onLoad
|
|
37
|
+
return iframe.value
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
getIframe,
|
|
42
|
+
iframe,
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---- useInspector ----
|
|
47
|
+
export function useInspector() {
|
|
48
|
+
const inspectorEnabled = ref(false)
|
|
49
|
+
const inspectorLoaded = ref(false)
|
|
50
|
+
|
|
51
|
+
const enable = () => {
|
|
52
|
+
window.__VUE_INSPECTOR__?.enable()
|
|
53
|
+
inspectorEnabled.value = true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const disable = () => {
|
|
57
|
+
window.__VUE_INSPECTOR__?.disable()
|
|
58
|
+
inspectorEnabled.value = false
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const setupInspector = () => {
|
|
62
|
+
const componentInspector = window.__VUE_INSPECTOR__
|
|
63
|
+
if (componentInspector) {
|
|
64
|
+
const _openInEditor = componentInspector.openInEditor
|
|
65
|
+
componentInspector.openInEditor = async (...params: any[]) => {
|
|
66
|
+
disable()
|
|
67
|
+
_openInEditor(...params)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const waitForInspectorInit = () => {
|
|
73
|
+
const timer = setInterval(() => {
|
|
74
|
+
if (window.__VUE_INSPECTOR__) {
|
|
75
|
+
clearInterval(timer)
|
|
76
|
+
inspectorLoaded.value = true
|
|
77
|
+
setupInspector()
|
|
78
|
+
}
|
|
79
|
+
}, 30)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
useWindowEventListener('keydown', (e: KeyboardEvent) => {
|
|
83
|
+
if (!inspectorEnabled.value || !inspectorLoaded.value)
|
|
84
|
+
return
|
|
85
|
+
if (e.key === 'Escape')
|
|
86
|
+
disable()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
waitForInspectorInit()
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
toggleInspector() {
|
|
93
|
+
if (!inspectorLoaded.value)
|
|
94
|
+
return
|
|
95
|
+
inspectorEnabled.value ? disable() : enable()
|
|
96
|
+
},
|
|
97
|
+
inspectorEnabled,
|
|
98
|
+
enableInspector: enable,
|
|
99
|
+
disableInspector: disable,
|
|
100
|
+
setupInspector,
|
|
101
|
+
inspectorLoaded,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---- usePanelVisible ----
|
|
106
|
+
export function usePanelVisible() {
|
|
107
|
+
const visible = computed({
|
|
108
|
+
get() {
|
|
109
|
+
return state.value.open
|
|
110
|
+
},
|
|
111
|
+
set(value) {
|
|
112
|
+
state.value.open = value
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const toggleVisible = () => {
|
|
117
|
+
visible.value = !visible.value
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const closePanel = () => {
|
|
121
|
+
if (!visible.value)
|
|
122
|
+
return
|
|
123
|
+
visible.value = false
|
|
124
|
+
if (popupWindow.value) {
|
|
125
|
+
try {
|
|
126
|
+
popupWindow.value.close()
|
|
127
|
+
}
|
|
128
|
+
catch { }
|
|
129
|
+
popupWindow.value = null
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
onMounted(() => {
|
|
134
|
+
useWindowEventListener('keydown', (e) => {
|
|
135
|
+
// cmd + shift + D in <macOS>
|
|
136
|
+
// alt + shift + D in <Windows>
|
|
137
|
+
if (e.code === 'KeyD' && e.altKey && e.shiftKey)
|
|
138
|
+
toggleVisible()
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
panelVisible: visible,
|
|
144
|
+
togglePanelVisible: toggleVisible,
|
|
145
|
+
closePanel,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---- usePipMode ----
|
|
150
|
+
export function usePiPMode(iframeGetter: () => HTMLIFrameElement | undefined, hook: object) {
|
|
151
|
+
// Experimental: Picture-in-Picture mode
|
|
152
|
+
// https://developer.chrome.com/docs/web-platform/document-picture-in-picture/
|
|
153
|
+
// @ts-expect-error experimental API
|
|
154
|
+
const documentPictureInPicture = window.documentPictureInPicture
|
|
155
|
+
async function popup() {
|
|
156
|
+
const iframe = iframeGetter()
|
|
157
|
+
const pip = popupWindow.value = await documentPictureInPicture.requestWindow({
|
|
158
|
+
width: Math.round(window.innerWidth * state.value.width / 100),
|
|
159
|
+
height: Math.round(window.innerHeight * state.value.height / 100),
|
|
160
|
+
})
|
|
161
|
+
const style = pip.document.createElement('style')
|
|
162
|
+
style.innerHTML = `
|
|
163
|
+
body {
|
|
164
|
+
margin: 0;
|
|
165
|
+
padding: 0;
|
|
166
|
+
}
|
|
167
|
+
iframe {
|
|
168
|
+
width: 100vw;
|
|
169
|
+
height: 100vh;
|
|
170
|
+
border: none;
|
|
171
|
+
outline: none;
|
|
172
|
+
}
|
|
173
|
+
`
|
|
174
|
+
pip.__VUE_DEVTOOLS_GLOBAL_HOOK__ = hook
|
|
175
|
+
pip.__VUE_DEVTOOLS_IS_POPUP__ = true
|
|
176
|
+
pip.document.title = 'Vue DevTools'
|
|
177
|
+
pip.document.head.appendChild(style)
|
|
178
|
+
pip.document.body.appendChild(iframe)
|
|
179
|
+
pip.addEventListener('resize', () => {
|
|
180
|
+
state.value.width = Math.round(pip.innerWidth / window.innerWidth * 100)
|
|
181
|
+
state.value.height = Math.round(pip.innerHeight / window.innerHeight * 100)
|
|
182
|
+
})
|
|
183
|
+
pip.addEventListener('pagehide', () => {
|
|
184
|
+
popupWindow.value = null
|
|
185
|
+
pip.close()
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
popup,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ---- usePosition ----
|
|
194
|
+
const SNAP_THRESHOLD = 2
|
|
195
|
+
|
|
196
|
+
function snapToPoints(value: number) {
|
|
197
|
+
if (value < 5)
|
|
198
|
+
return 0
|
|
199
|
+
if (value > 95)
|
|
200
|
+
return 100
|
|
201
|
+
if (Math.abs(value - 50) < SNAP_THRESHOLD)
|
|
202
|
+
return 50
|
|
203
|
+
return value
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function usePosition(panelEl: Ref<HTMLElement | undefined>) {
|
|
207
|
+
const isDragging = ref(false)
|
|
208
|
+
const draggingOffset = reactive({ x: 0, y: 0 })
|
|
209
|
+
const windowSize = reactive({ width: 0, height: 0 })
|
|
210
|
+
const mousePosition = reactive({ x: 0, y: 0 })
|
|
211
|
+
const panelMargins = reactive({
|
|
212
|
+
left: 10,
|
|
213
|
+
top: 10,
|
|
214
|
+
right: 10,
|
|
215
|
+
bottom: 10,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
const safeArea = useScreenSafeArea()
|
|
219
|
+
|
|
220
|
+
watchEffect(() => {
|
|
221
|
+
panelMargins.left = safeArea.left.value + 10
|
|
222
|
+
panelMargins.top = safeArea.top.value + 10
|
|
223
|
+
panelMargins.right = safeArea.right.value + 10
|
|
224
|
+
panelMargins.bottom = safeArea.bottom.value + 10
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
const onPointerDown = (e: PointerEvent) => {
|
|
228
|
+
isDragging.value = true
|
|
229
|
+
const { left, top, width, height } = panelEl.value!.getBoundingClientRect()
|
|
230
|
+
draggingOffset.x = e.clientX - left - width / 2
|
|
231
|
+
draggingOffset.y = e.clientY - top - height / 2
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const setWindowSize = () => {
|
|
235
|
+
windowSize.width = window.innerWidth
|
|
236
|
+
windowSize.height = window.innerHeight
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
onMounted(() => {
|
|
240
|
+
setWindowSize()
|
|
241
|
+
|
|
242
|
+
useWindowEventListener('resize', () => {
|
|
243
|
+
setWindowSize()
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
useWindowEventListener('pointerup', () => {
|
|
247
|
+
isDragging.value = false
|
|
248
|
+
})
|
|
249
|
+
useWindowEventListener('pointerleave', () => {
|
|
250
|
+
isDragging.value = false
|
|
251
|
+
})
|
|
252
|
+
useWindowEventListener('pointermove', (e) => {
|
|
253
|
+
if (!isDragging.value)
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
const centerX = windowSize.width / 2
|
|
257
|
+
const centerY = windowSize.height / 2
|
|
258
|
+
|
|
259
|
+
const x = e.clientX - draggingOffset.x
|
|
260
|
+
const y = e.clientY - draggingOffset.y
|
|
261
|
+
|
|
262
|
+
mousePosition.x = x
|
|
263
|
+
mousePosition.y = y
|
|
264
|
+
|
|
265
|
+
// Get position
|
|
266
|
+
const deg = Math.atan2(y - centerY, x - centerX)
|
|
267
|
+
const HORIZONTAL_MARGIN = 70
|
|
268
|
+
const TL = Math.atan2(0 - centerY + HORIZONTAL_MARGIN, 0 - centerX)
|
|
269
|
+
const TR = Math.atan2(0 - centerY + HORIZONTAL_MARGIN, windowSize.width - centerX)
|
|
270
|
+
const BL = Math.atan2(windowSize.height - HORIZONTAL_MARGIN - centerY, 0 - centerX)
|
|
271
|
+
const BR = Math.atan2(windowSize.height - HORIZONTAL_MARGIN - centerY, windowSize.width - centerX)
|
|
272
|
+
|
|
273
|
+
state.value.position = (deg >= TL && deg <= TR)
|
|
274
|
+
? 'top'
|
|
275
|
+
: (deg >= TR && deg <= BR)
|
|
276
|
+
? 'right'
|
|
277
|
+
: (deg >= BR && deg <= BL)
|
|
278
|
+
? 'bottom'
|
|
279
|
+
: 'left'
|
|
280
|
+
|
|
281
|
+
state.value.left = snapToPoints(x / windowSize.width * 100)
|
|
282
|
+
state.value.top = snapToPoints(y / windowSize.height * 100)
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
const isVertical = computed(() => state.value.position === 'left' || state.value.position === 'right')
|
|
287
|
+
|
|
288
|
+
const anchorPos = computed(() => {
|
|
289
|
+
const halfWidth = (panelEl.value?.clientWidth || 0) / 2
|
|
290
|
+
const halfHeight = (panelEl.value?.clientHeight || 0) / 2
|
|
291
|
+
|
|
292
|
+
const left = state.value.left * windowSize.width / 100
|
|
293
|
+
const top = state.value.top * windowSize.height / 100
|
|
294
|
+
|
|
295
|
+
switch (state.value.position) {
|
|
296
|
+
case 'top':
|
|
297
|
+
return {
|
|
298
|
+
left: clamp(left, halfWidth + panelMargins.left, windowSize.width - halfWidth - panelMargins.right),
|
|
299
|
+
top: panelMargins.top + halfHeight,
|
|
300
|
+
}
|
|
301
|
+
case 'right':
|
|
302
|
+
return {
|
|
303
|
+
left: windowSize.width - panelMargins.right - halfHeight,
|
|
304
|
+
top: clamp(top, halfWidth + panelMargins.top, windowSize.height - halfWidth - panelMargins.bottom),
|
|
305
|
+
}
|
|
306
|
+
case 'left':
|
|
307
|
+
return {
|
|
308
|
+
left: panelMargins.left + halfHeight,
|
|
309
|
+
top: clamp(top, halfWidth + panelMargins.top, windowSize.height - halfWidth - panelMargins.bottom),
|
|
310
|
+
}
|
|
311
|
+
case 'bottom':
|
|
312
|
+
default:
|
|
313
|
+
return {
|
|
314
|
+
left: clamp(left, halfWidth + panelMargins.left, windowSize.width - halfWidth - panelMargins.right),
|
|
315
|
+
top: windowSize.height - panelMargins.bottom - halfHeight,
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
const anchorStyle = computed(() => ({ left: `${anchorPos.value.left}px`, top: `${anchorPos.value.top}px` }))
|
|
321
|
+
|
|
322
|
+
const iframeStyle = computed(() => {
|
|
323
|
+
// eslint-disable-next-line no-unused-expressions, no-sequences
|
|
324
|
+
mousePosition.x, mousePosition.y
|
|
325
|
+
|
|
326
|
+
const halfHeight = (panelEl.value?.clientHeight || 0) / 2
|
|
327
|
+
|
|
328
|
+
const frameMargin = {
|
|
329
|
+
left: panelMargins.left + halfHeight,
|
|
330
|
+
top: panelMargins.top + halfHeight,
|
|
331
|
+
right: panelMargins.right + halfHeight,
|
|
332
|
+
bottom: panelMargins.bottom + halfHeight,
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const marginHorizontal = frameMargin.left + frameMargin.right
|
|
336
|
+
const marginVertical = frameMargin.top + frameMargin.bottom
|
|
337
|
+
|
|
338
|
+
const maxWidth = windowSize.width - marginHorizontal
|
|
339
|
+
const maxHeight = windowSize.height - marginVertical
|
|
340
|
+
|
|
341
|
+
const style: CSSProperties = {
|
|
342
|
+
zIndex: -1,
|
|
343
|
+
pointerEvents: isDragging.value ? 'none' : 'auto',
|
|
344
|
+
width: `min(${state.value.width}vw, calc(100vw - ${marginHorizontal}px))`,
|
|
345
|
+
height: `min(${state.value.height}vh, calc(100vh - ${marginVertical}px))`,
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const anchor = anchorPos.value
|
|
349
|
+
const width = Math.min(maxWidth, state.value.width * windowSize.width / 100)
|
|
350
|
+
const height = Math.min(maxHeight, state.value.height * windowSize.height / 100)
|
|
351
|
+
|
|
352
|
+
const anchorX = anchor?.left || 0
|
|
353
|
+
const anchorY = anchor?.top || 0
|
|
354
|
+
|
|
355
|
+
switch (state.value.position) {
|
|
356
|
+
case 'top':
|
|
357
|
+
case 'bottom':
|
|
358
|
+
style.left = 0
|
|
359
|
+
style.transform = 'translate(-50%, 0)'
|
|
360
|
+
if ((anchorX - frameMargin.left) < width / 2)
|
|
361
|
+
style.left = `${width / 2 - anchorX + frameMargin.left}px`
|
|
362
|
+
else if ((windowSize.width - anchorX - frameMargin.right) < width / 2)
|
|
363
|
+
style.left = `${windowSize.width - anchorX - width / 2 - frameMargin.right}px`
|
|
364
|
+
break
|
|
365
|
+
case 'right':
|
|
366
|
+
case 'left':
|
|
367
|
+
style.top = 0
|
|
368
|
+
style.transform = 'translate(0, -50%)'
|
|
369
|
+
if ((anchorY - frameMargin.top) < height / 2)
|
|
370
|
+
style.top = `${height / 2 - anchorY + frameMargin.top}px`
|
|
371
|
+
else if ((windowSize.height - anchorY - frameMargin.bottom) < height / 2)
|
|
372
|
+
style.top = `${windowSize.height - anchorY - height / 2 - frameMargin.bottom}px`
|
|
373
|
+
break
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
switch (state.value.position) {
|
|
377
|
+
case 'top':
|
|
378
|
+
style.top = 0
|
|
379
|
+
break
|
|
380
|
+
case 'right':
|
|
381
|
+
style.right = 0
|
|
382
|
+
break
|
|
383
|
+
case 'left':
|
|
384
|
+
style.left = 0
|
|
385
|
+
break
|
|
386
|
+
case 'bottom':
|
|
387
|
+
default:
|
|
388
|
+
style.bottom = 0
|
|
389
|
+
break
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return style
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
isDragging,
|
|
397
|
+
onPointerDown,
|
|
398
|
+
isVertical,
|
|
399
|
+
anchorStyle,
|
|
400
|
+
iframeStyle,
|
|
401
|
+
}
|
|
402
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed, getCurrentScope, onScopeDispose, ref, toRef, watch, watchEffect,
|
|
3
|
+
} from 'vue'
|
|
4
|
+
import type { Ref } from 'vue'
|
|
5
|
+
|
|
6
|
+
export function tryOnScopeDispose(fn: () => void) {
|
|
7
|
+
const scope = getCurrentScope()
|
|
8
|
+
if (scope)
|
|
9
|
+
onScopeDispose(fn)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// ---- storage ----
|
|
13
|
+
export function useObjectStorage<T>(key: string, initial: T, readonly = false): Ref<T> {
|
|
14
|
+
const raw = localStorage.getItem(key)
|
|
15
|
+
const data = ref(raw ? JSON.parse(raw) : initial)
|
|
16
|
+
|
|
17
|
+
for (const key in initial) {
|
|
18
|
+
if (data.value[key] === undefined)
|
|
19
|
+
data.value[key] = initial[key]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let updating = false
|
|
23
|
+
let wrote = ''
|
|
24
|
+
|
|
25
|
+
if (!readonly) {
|
|
26
|
+
watch(data, (value) => {
|
|
27
|
+
if (updating)
|
|
28
|
+
return
|
|
29
|
+
wrote = JSON.stringify(value)
|
|
30
|
+
localStorage.setItem(key, wrote)
|
|
31
|
+
}, { deep: true, flush: 'post' })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
useWindowEventListener('storage', (e: StorageEvent) => {
|
|
35
|
+
if (e.key === key && e.newValue && e.newValue !== wrote) {
|
|
36
|
+
updating = true
|
|
37
|
+
data.value = JSON.parse(e.newValue)
|
|
38
|
+
updating = false
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return data
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function useStorage<T>(key: string, initial: T, readonly = false) {
|
|
46
|
+
const raw = localStorage.getItem(key)
|
|
47
|
+
const data = ref(raw || initial)
|
|
48
|
+
|
|
49
|
+
let updating = false
|
|
50
|
+
let wrote = ''
|
|
51
|
+
|
|
52
|
+
if (!readonly) {
|
|
53
|
+
watch(data, (value) => {
|
|
54
|
+
if (updating)
|
|
55
|
+
return
|
|
56
|
+
wrote = `${value}`
|
|
57
|
+
localStorage.setItem(key, wrote)
|
|
58
|
+
}, { deep: true, flush: 'post' })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
useWindowEventListener('storage', (e: StorageEvent) => {
|
|
62
|
+
if (e.key === key && e.newValue && e.newValue !== wrote) {
|
|
63
|
+
updating = true
|
|
64
|
+
data.value = e.newValue
|
|
65
|
+
updating = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return data
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---- index ----
|
|
73
|
+
export const checkIsSafari = () => navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')
|
|
74
|
+
export function clamp(value: number, min: number, max: number) {
|
|
75
|
+
return Math.min(Math.max(value, min), max)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ---- event ----
|
|
79
|
+
export function useEventListener(
|
|
80
|
+
target: EventTarget,
|
|
81
|
+
type: keyof WindowEventHandlersEventMap,
|
|
82
|
+
listener: EventListenerOrEventListenerObject,
|
|
83
|
+
options?: boolean | AddEventListenerOptions,
|
|
84
|
+
) {
|
|
85
|
+
target.addEventListener(type, listener, options)
|
|
86
|
+
tryOnScopeDispose(() => target.removeEventListener(type, listener, options))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function useWindowEventListener<K extends keyof WindowEventMap>(
|
|
90
|
+
type: K,
|
|
91
|
+
listener: (this: Window, ev: WindowEventMap[K]) => any,
|
|
92
|
+
options?: boolean | AddEventListenerOptions,
|
|
93
|
+
) {
|
|
94
|
+
useEventListener(window, type as keyof WindowEventHandlersEventMap, listener as EventListener, options)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ---- screen ----
|
|
98
|
+
const topVarName = '--vite-plugin-vue-devtools-safe-area-top'
|
|
99
|
+
const rightVarName = '--vite-plugin-vue-devtools-devtools-safe-area-right'
|
|
100
|
+
const bottomVarName = '--vite-plugin-vue-devtools-safe-area-bottom'
|
|
101
|
+
const leftVarName = '--vite-plugin-vue-devtools-safe-area-left'
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Reactive `env(safe-area-inset-*)`
|
|
105
|
+
*
|
|
106
|
+
* @see https://vueuse.org/useScreenSafeArea
|
|
107
|
+
*/
|
|
108
|
+
export function useScreenSafeArea() {
|
|
109
|
+
const top = ref(0)
|
|
110
|
+
const right = ref(0)
|
|
111
|
+
const bottom = ref(0)
|
|
112
|
+
const left = ref(0)
|
|
113
|
+
|
|
114
|
+
document.documentElement.style.setProperty(topVarName, 'env(safe-area-inset-top, 0px)')
|
|
115
|
+
document.documentElement.style.setProperty(rightVarName, 'env(safe-area-inset-right, 0px)')
|
|
116
|
+
document.documentElement.style.setProperty(bottomVarName, 'env(safe-area-inset-bottom, 0px)')
|
|
117
|
+
document.documentElement.style.setProperty(leftVarName, 'env(safe-area-inset-left, 0px)')
|
|
118
|
+
|
|
119
|
+
update()
|
|
120
|
+
useWindowEventListener('resize', update)
|
|
121
|
+
|
|
122
|
+
function getValue(position: string) {
|
|
123
|
+
return Number.parseFloat(getComputedStyle(document.documentElement).getPropertyValue(position)) || 0
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function update() {
|
|
127
|
+
top.value = getValue(topVarName)
|
|
128
|
+
right.value = getValue(rightVarName)
|
|
129
|
+
bottom.value = getValue(bottomVarName)
|
|
130
|
+
left.value = getValue(leftVarName)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
top,
|
|
135
|
+
right,
|
|
136
|
+
bottom,
|
|
137
|
+
left,
|
|
138
|
+
update,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// color-scheme
|
|
143
|
+
export const useColorScheme = () => useStorage('vueuse-color-scheme', 'auto', true)
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Reactive Media Query.
|
|
147
|
+
*
|
|
148
|
+
* @see https://vueuse.org/useMediaQuery
|
|
149
|
+
* @param query
|
|
150
|
+
* @param options
|
|
151
|
+
*/
|
|
152
|
+
export function useMediaQuery(query: string) {
|
|
153
|
+
const isSupported = () => window && 'matchMedia' in window && typeof window.matchMedia === 'function'
|
|
154
|
+
|
|
155
|
+
let mediaQuery: MediaQueryList | undefined
|
|
156
|
+
const matches = ref(false)
|
|
157
|
+
|
|
158
|
+
const cleanup = () => {
|
|
159
|
+
if (!mediaQuery)
|
|
160
|
+
return
|
|
161
|
+
if ('removeEventListener' in mediaQuery)
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
163
|
+
mediaQuery.removeEventListener('change', update)
|
|
164
|
+
else
|
|
165
|
+
// @ts-expect-error deprecated API
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
167
|
+
mediaQuery.removeListener(update)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const update = () => {
|
|
171
|
+
if (!isSupported)
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
cleanup()
|
|
175
|
+
|
|
176
|
+
mediaQuery = window!.matchMedia(toRef(query).value)
|
|
177
|
+
matches.value = !!mediaQuery?.matches
|
|
178
|
+
|
|
179
|
+
if (!mediaQuery)
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
if ('addEventListener' in mediaQuery)
|
|
183
|
+
mediaQuery.addEventListener('change', update)
|
|
184
|
+
else
|
|
185
|
+
// @ts-expect-error deprecated API
|
|
186
|
+
mediaQuery.addListener(update)
|
|
187
|
+
}
|
|
188
|
+
watchEffect(update)
|
|
189
|
+
|
|
190
|
+
tryOnScopeDispose(() => cleanup())
|
|
191
|
+
|
|
192
|
+
return matches
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Reactive prefers-color-scheme media query.
|
|
196
|
+
*
|
|
197
|
+
* @see https://vueuse.org/usePreferredColorScheme
|
|
198
|
+
* @param [options]
|
|
199
|
+
*/
|
|
200
|
+
export function usePreferredColorScheme() {
|
|
201
|
+
const isDark = useMediaQuery('(prefers-color-scheme: dark)')
|
|
202
|
+
|
|
203
|
+
return computed(() => isDark.value ? 'dark' : 'light')
|
|
204
|
+
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { _ as __unplugin_components_0 } from './VPanelGrids-3a29966d.js';
|
|
2
|
-
import { v as defineComponent, ad as useEventListener, o as openBlock, c as createBlock, h as withCtx, x as createBaseVNode, aJ as useDevtoolsClient } from './index-c8859523.js';
|
|
3
|
-
|
|
4
|
-
const _hoisted_1 = /* @__PURE__ */ createBaseVNode("div", null, " Inspecting Vue components ", -1);
|
|
5
|
-
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
6
|
-
__name: "__inspecting",
|
|
7
|
-
setup(__props) {
|
|
8
|
-
const client = useDevtoolsClient();
|
|
9
|
-
useEventListener("keydown", (e) => {
|
|
10
|
-
if (e.key === "Escape")
|
|
11
|
-
close();
|
|
12
|
-
});
|
|
13
|
-
function close() {
|
|
14
|
-
client.value?.inspector?.disable();
|
|
15
|
-
}
|
|
16
|
-
return (_ctx, _cache) => {
|
|
17
|
-
const _component_VPanelGrids = __unplugin_components_0;
|
|
18
|
-
return openBlock(), createBlock(_component_VPanelGrids, {
|
|
19
|
-
"h-screen": "",
|
|
20
|
-
"w-screen": "",
|
|
21
|
-
px5: ""
|
|
22
|
-
}, {
|
|
23
|
-
default: withCtx(() => [
|
|
24
|
-
createBaseVNode("div", {
|
|
25
|
-
absolute: "",
|
|
26
|
-
"right-0": "",
|
|
27
|
-
"top-0": "",
|
|
28
|
-
p2: ""
|
|
29
|
-
}, [
|
|
30
|
-
createBaseVNode("button", {
|
|
31
|
-
"carbon-close": "",
|
|
32
|
-
ma: "",
|
|
33
|
-
"text-xl": "",
|
|
34
|
-
op50: "",
|
|
35
|
-
"hover:op100": "",
|
|
36
|
-
onClick: close
|
|
37
|
-
})
|
|
38
|
-
]),
|
|
39
|
-
_hoisted_1
|
|
40
|
-
]),
|
|
41
|
-
_: 1
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
/* Injected with object hook! */
|
|
48
|
-
|
|
49
|
-
/* Injected with object hook! */
|
|
50
|
-
|
|
51
|
-
export { _sfc_main as default };
|