one 1.6.11 → 1.6.12

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.
Files changed (2) hide show
  1. package/devtools/devtools.mjs +322 -69
  2. package/package.json +9 -9
@@ -1,5 +1,5 @@
1
1
  // One DevTools - All panels in one draggable window
2
- // Alt+Space opens Spotlight-style quick picker
2
+ // Alt+Space opens searchable hot menu
3
3
 
4
4
  ;(function () {
5
5
  try {
@@ -14,10 +14,132 @@
14
14
  const panelPos = { x: 20, y: 20 }
15
15
  let snappedEdge = { h: null, v: null }
16
16
  let removalObserver = null
17
+ let selectedIndex = 0
18
+ let filteredItems = []
17
19
 
18
20
  const LOGO_SVG =
19
21
  '<svg width="24" height="24" viewBox="0 0 100 100"><circle cx="50" cy="50" r="48" fill="#FCD34D" stroke="#222" stroke-width="2"/><circle cx="50" cy="35" r="16" fill="white"/><text x="50" y="41" text-anchor="middle" font-family="system-ui" font-size="16" font-weight="bold" fill="#222">1</text></svg>'
20
22
 
23
+ const allItems = [
24
+ { id: 'seo', name: 'SEO Preview', type: 'panel', category: 'Panels' },
25
+ { id: 'route', name: 'Route Info', type: 'panel', category: 'Panels' },
26
+ { id: 'loader', name: 'Loader Timing', type: 'panel', category: 'Panels' },
27
+ { id: 'errors', name: 'Errors', type: 'panel', category: 'Panels' },
28
+ { id: 'inspect', name: 'Inspect Source', type: 'tool', category: 'Panels' },
29
+ { id: 'clear-cookies', name: 'Clear Cookies', type: 'action', category: 'Clear Data' },
30
+ {
31
+ id: 'clear-localstorage',
32
+ name: 'Clear localStorage',
33
+ type: 'action',
34
+ category: 'Clear Data',
35
+ },
36
+ {
37
+ id: 'clear-sessionstorage',
38
+ name: 'Clear sessionStorage',
39
+ type: 'action',
40
+ category: 'Clear Data',
41
+ },
42
+ { id: 'clear-indexeddb', name: 'Clear IndexedDB', type: 'action', category: 'Clear Data' },
43
+ {
44
+ id: 'clear-caches',
45
+ name: 'Clear Cache Storage',
46
+ type: 'action',
47
+ category: 'Clear Data',
48
+ },
49
+ {
50
+ id: 'clear-sw',
51
+ name: 'Clear Service Workers',
52
+ type: 'action',
53
+ category: 'Clear Data',
54
+ },
55
+ { id: 'clear-all', name: 'Clear All', type: 'action', category: 'Clear Data' },
56
+ { id: 'reload', name: 'Reload Page', type: 'action', category: 'Actions' },
57
+ { id: 'hard-reload', name: 'Hard Reload', type: 'action', category: 'Actions' },
58
+ { id: 'copy-url', name: 'Copy Current URL', type: 'action', category: 'Actions' },
59
+ { id: 'copy-route', name: 'Copy Route Info', type: 'action', category: 'Actions' },
60
+ ]
61
+
62
+ const itemActions = {
63
+ 'clear-cookies': async () => {
64
+ document.cookie.split(';').forEach((cookie) => {
65
+ const name = (cookie.split('=')[0] || '').trim()
66
+ if (!name) return
67
+ const d = location.hostname
68
+ document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/'
69
+ document.cookie =
70
+ name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=' + d
71
+ document.cookie =
72
+ name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=.' + d
73
+ })
74
+ },
75
+ 'clear-localstorage': async () => {
76
+ localStorage.clear()
77
+ },
78
+ 'clear-sessionstorage': async () => {
79
+ sessionStorage.clear()
80
+ },
81
+ 'clear-indexeddb': async () => {
82
+ if ('indexedDB' in window && typeof indexedDB.databases === 'function') {
83
+ const dbs = await indexedDB.databases()
84
+ await Promise.all(
85
+ dbs.map((db) =>
86
+ db.name
87
+ ? new Promise((resolve) => {
88
+ const req = indexedDB.deleteDatabase(db.name)
89
+ req.onsuccess = resolve
90
+ req.onerror = resolve
91
+ req.onblocked = resolve
92
+ })
93
+ : Promise.resolve()
94
+ )
95
+ )
96
+ }
97
+ },
98
+ 'clear-caches': async () => {
99
+ if ('caches' in window) {
100
+ const names = await caches.keys()
101
+ await Promise.all(names.map((n) => caches.delete(n)))
102
+ }
103
+ },
104
+ 'clear-sw': async () => {
105
+ if ('serviceWorker' in navigator) {
106
+ const regs = await navigator.serviceWorker.getRegistrations()
107
+ await Promise.all(regs.map((r) => r.unregister()))
108
+ }
109
+ },
110
+ 'clear-all': async () => {
111
+ await itemActions['clear-cookies']()
112
+ await itemActions['clear-localstorage']()
113
+ await itemActions['clear-sessionstorage']()
114
+ await itemActions['clear-indexeddb']()
115
+ await itemActions['clear-caches']()
116
+ await itemActions['clear-sw']()
117
+ },
118
+ reload: async () => {
119
+ location.reload()
120
+ },
121
+ 'hard-reload': async () => {
122
+ if ('caches' in window) {
123
+ const names = await caches.keys()
124
+ await Promise.all(names.map((n) => caches.delete(n)))
125
+ }
126
+ location.reload()
127
+ },
128
+ 'copy-url': async () => {
129
+ await navigator.clipboard.writeText(location.href)
130
+ },
131
+ 'copy-route': async () => {
132
+ const dt = window.__oneDevtools || {}
133
+ const info = {
134
+ pathname: location.pathname,
135
+ search: location.search,
136
+ hash: location.hash,
137
+ params: dt.routeInfo?.params || {},
138
+ }
139
+ await navigator.clipboard.writeText(JSON.stringify(info, null, 2))
140
+ },
141
+ }
142
+
21
143
  function escapeHtml(str) {
22
144
  if (!str) return ''
23
145
  return String(str)
@@ -39,15 +161,23 @@
39
161
  dialog::backdrop { background: transparent; }
40
162
  #spotlight-dialog::backdrop { background: rgba(0,0,0,0.3); backdrop-filter: blur(8px); }
41
163
  .spotlight { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
42
- .spotlight-box { background: #1a1a1a; border-radius: 12px; width: 320px; max-width: 90vw; overflow: hidden; box-shadow: 0 16px 48px rgba(0,0,0,0.5); }
43
- .spotlight-header { display: flex; align-items: center; padding: 12px 16px; border-bottom: 1px solid #252525; gap: 10px; }
164
+ .spotlight-box { background: #1a1a1a; border-radius: 12px; width: 340px; max-width: 90vw; overflow: hidden; box-shadow: 0 16px 48px rgba(0,0,0,0.5); display: flex; flex-direction: column; }
165
+ .spotlight-header { display: flex; align-items: center; padding: 12px 14px; border-bottom: 1px solid #252525; gap: 10px; flex-shrink: 0; }
44
166
  .spotlight-header svg { width: 20px; height: 20px; flex-shrink: 0; }
45
- .spotlight-header-title { font: 13px system-ui, sans-serif; color: #ccc; flex: 1; }
46
- .spotlight-header-version { font: 11px system-ui, sans-serif; color: #666; }
47
- .spotlight-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; color: #ccc; font: 13px system-ui, sans-serif; cursor: pointer; transition: background 0.1s; border-bottom: 1px solid #252525; }
48
- .spotlight-item:last-child { border-bottom: none; }
49
- .spotlight-item:hover { background: #252525; color: #fff; }
50
- .spotlight-item .key { background: #333; color: #888; padding: 2px 6px; border-radius: 4px; font-size: 11px; margin-left: auto; }
167
+ .spotlight-search { flex: 1; background: transparent; border: none; color: #eee; font: 14px system-ui, sans-serif; outline: none; min-width: 0; }
168
+ .spotlight-search::placeholder { color: #555; }
169
+ .spotlight-items { max-height: 354px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #333 transparent; }
170
+ .spotlight-items::-webkit-scrollbar { width: 4px; }
171
+ .spotlight-items::-webkit-scrollbar-track { background: transparent; }
172
+ .spotlight-items::-webkit-scrollbar-thumb { background: #333; border-radius: 2px; }
173
+ .spotlight-category { font: 10px system-ui, sans-serif; color: #505050; text-transform: uppercase; letter-spacing: 0.5px; padding: 10px 16px 4px; user-select: none; }
174
+ .spotlight-item { display: flex; align-items: center; padding: 10px 16px; color: #aaa; font: 13px system-ui, sans-serif; cursor: pointer; transition: background 0.08s; }
175
+ .spotlight-item:hover, .spotlight-item.selected { background: #252525; color: #fff; }
176
+ .spotlight-item .name { flex: 1; }
177
+ .spotlight-item .status { font-size: 11px; color: #666; margin-left: 8px; }
178
+ .spotlight-item .status.ok { color: #4ade80; }
179
+ .spotlight-item .status.err { color: #f87171; }
180
+ .spotlight-empty { text-align: center; color: #444; padding: 24px; font: 13px system-ui, sans-serif; }
51
181
  .panel-dialog { position: fixed; margin: 0; inset: unset; z-index: 2147483647; }
52
182
  .panel-dialog::backdrop { display: none; }
53
183
  .panel { width: 420px; max-width: calc(100vw - 40px); max-height: calc(100vh - 40px); background: #161616; border-radius: 10px; box-shadow: 0 12px 40px rgba(0,0,0,0.4); display: flex; flex-direction: column; overflow: hidden; font: 13px system-ui, sans-serif; color: #ccc; }
@@ -90,7 +220,15 @@
90
220
  shadow.innerHTML =
91
221
  '<style>' +
92
222
  css +
93
- '</style><dialog id="spotlight-dialog"><div class="spotlight"><div class="spotlight-box" id="spotlight-box"></div></div></dialog><dialog class="panel-dialog" id="panel-dialog"><div class="panel" id="panel"></div></dialog>'
223
+ '</style>' +
224
+ '<dialog id="spotlight-dialog"><div class="spotlight"><div class="spotlight-box" id="spotlight-box">' +
225
+ '<div class="spotlight-header">' +
226
+ LOGO_SVG +
227
+ '<input type="text" class="spotlight-search" id="spotlight-search" placeholder="Search actions..." autocomplete="off" spellcheck="false" />' +
228
+ '</div>' +
229
+ '<div class="spotlight-items" id="spotlight-items"></div>' +
230
+ '</div></div></dialog>' +
231
+ '<dialog class="panel-dialog" id="panel-dialog"><div class="panel" id="panel"></div></dialog>'
94
232
  document.body.appendChild(host)
95
233
 
96
234
  setupSpotlight()
@@ -121,51 +259,180 @@
121
259
  removalObserver.observe(document.body, { childList: true })
122
260
  }
123
261
 
262
+ function fuzzyScore(raw, query) {
263
+ // light fuzzy: prefer matching at word starts
264
+ const text = raw.toLowerCase().replace(/\s+/g, '')
265
+ const words = raw.toLowerCase().split(/\s+/)
266
+ const wordStarts = new Set()
267
+ let pos = 0
268
+ for (const w of words) {
269
+ wordStarts.add(pos)
270
+ pos += w.length
271
+ }
272
+ let ti = 0
273
+ let score = 0
274
+ for (let qi = 0; qi < query.length; qi++) {
275
+ const ch = query[qi]
276
+ // scan for first match, but prefer word-start match
277
+ let first = -1
278
+ for (let j = ti; j < text.length; j++) {
279
+ if (text[j] === ch) {
280
+ if (wordStarts.has(j)) { first = j; break }
281
+ if (first === -1) first = j
282
+ }
283
+ }
284
+ if (first === -1) return -1
285
+ score += wordStarts.has(first) ? 10 : 1
286
+ ti = first + 1
287
+ }
288
+ return score
289
+ }
290
+
291
+ function renderSpotlightItems(query) {
292
+ const q = (query || '').toLowerCase().replace(/\s+/g, '')
293
+ const scored = []
294
+ for (const item of allItems) {
295
+ if (!q) {
296
+ scored.push({ item, score: 0 })
297
+ continue
298
+ }
299
+ const ns = fuzzyScore(item.name, q)
300
+ const cs = fuzzyScore(item.category, q)
301
+ const best = Math.max(ns, cs)
302
+ if (best >= 0) scored.push({ item, score: best })
303
+ }
304
+ scored.sort((a, b) => b.score - a.score)
305
+ filteredItems = scored.map((s) => s.item)
306
+ selectedIndex = filteredItems.length > 0 ? 0 : -1
307
+
308
+ const container = shadow.getElementById('spotlight-items')
309
+ if (!filteredItems.length) {
310
+ container.innerHTML = '<div class="spotlight-empty">No matching actions</div>'
311
+ return
312
+ }
313
+
314
+ let html = ''
315
+ let lastCategory = ''
316
+ filteredItems.forEach((item, index) => {
317
+ if (item.category !== lastCategory) {
318
+ lastCategory = item.category
319
+ html +=
320
+ '<div class="spotlight-category">' + escapeHtml(item.category) + '</div>'
321
+ }
322
+ html +=
323
+ '<div class="spotlight-item' +
324
+ (index === selectedIndex ? ' selected' : '') +
325
+ '" data-id="' +
326
+ item.id +
327
+ '" data-index="' +
328
+ index +
329
+ '"><span class="name">' +
330
+ escapeHtml(item.name) +
331
+ '</span><span class="status"></span></div>'
332
+ })
333
+
334
+ container.innerHTML = html
335
+ }
336
+
337
+ function updateSelection() {
338
+ if (!shadow) return
339
+ shadow.querySelectorAll('.spotlight-item').forEach((el) => {
340
+ const idx = parseInt(el.dataset.index)
341
+ el.classList.toggle('selected', idx === selectedIndex)
342
+ })
343
+ const selected = shadow.querySelector('.spotlight-item.selected')
344
+ if (selected) selected.scrollIntoView({ block: 'nearest' })
345
+ }
346
+
347
+ function handleItemClick(itemId) {
348
+ const item = allItems.find((i) => i.id === itemId)
349
+ if (!item) return
350
+
351
+ if (item.type === 'panel') {
352
+ hideSpotlight()
353
+ activeTab = item.id
354
+ showPanel()
355
+ return
356
+ }
357
+
358
+ if (item.id === 'inspect') {
359
+ hideSpotlight()
360
+ window.__oneSourceInspector?.activate()
361
+ return
362
+ }
363
+
364
+ const actionFn = itemActions[item.id]
365
+ if (!actionFn) return
366
+
367
+ const el = shadow.querySelector('.spotlight-item[data-id="' + item.id + '"]')
368
+ const statusEl = el?.querySelector('.status')
369
+ if (statusEl) statusEl.textContent = '...'
370
+
371
+ actionFn()
372
+ .then(() => {
373
+ if (statusEl) {
374
+ statusEl.textContent = '\u2713'
375
+ statusEl.className = 'status ok'
376
+ }
377
+ setTimeout(hideSpotlight, 500)
378
+ })
379
+ .catch((err) => {
380
+ if (statusEl) {
381
+ statusEl.textContent = '\u2717'
382
+ statusEl.className = 'status err'
383
+ }
384
+ console.error('[One DevTools]', err)
385
+ })
386
+ }
387
+
124
388
  function setupSpotlight() {
125
389
  spotlightDialog = shadow.getElementById('spotlight-dialog')
126
390
  const box = shadow.getElementById('spotlight-box')
391
+ const searchInput = shadow.getElementById('spotlight-search')
392
+ const itemsContainer = shadow.getElementById('spotlight-items')
127
393
 
128
- const items = [
129
- { id: 'seo', name: 'SEO Preview', key: '⌥S' },
130
- { id: 'route', name: 'Route Info', key: '⌥R' },
131
- { id: 'loader', name: 'Loader Timing', key: '⌥L' },
132
- { id: 'errors', name: 'Errors', key: '⌥E' },
133
- { id: 'inspect', name: 'Inspect Source', key: '⌥I' },
134
- ]
394
+ searchInput.addEventListener('input', () => {
395
+ renderSpotlightItems(searchInput.value)
396
+ })
135
397
 
136
- const header =
137
- '<div class="spotlight-header">' +
138
- LOGO_SVG +
139
- '<span class="spotlight-header-title">Dev Tools</span><span class="spotlight-header-version">v1.2.57</span></div>'
140
- box.innerHTML =
141
- header +
142
- items
143
- .map(
144
- (item) =>
145
- '<div class="spotlight-item" data-tab="' +
146
- item.id +
147
- '"><span>' +
148
- item.name +
149
- '</span><span class="key">' +
150
- item.key +
151
- '</span></div>'
152
- )
153
- .join('')
398
+ box.addEventListener('keydown', (e) => {
399
+ if (e.key === 'ArrowDown') {
400
+ e.preventDefault()
401
+ if (filteredItems.length) {
402
+ selectedIndex = (selectedIndex + 1) % filteredItems.length
403
+ updateSelection()
404
+ }
405
+ } else if (e.key === 'ArrowUp') {
406
+ e.preventDefault()
407
+ if (filteredItems.length) {
408
+ selectedIndex =
409
+ selectedIndex <= 0 ? filteredItems.length - 1 : selectedIndex - 1
410
+ updateSelection()
411
+ }
412
+ } else if (e.key === 'Enter') {
413
+ e.preventDefault()
414
+ if (selectedIndex >= 0 && selectedIndex < filteredItems.length) {
415
+ handleItemClick(filteredItems[selectedIndex].id)
416
+ }
417
+ }
418
+ })
154
419
 
155
- box.addEventListener('click', (e) => {
420
+ itemsContainer.addEventListener('mousemove', (e) => {
156
421
  const item = e.target.closest('.spotlight-item')
157
422
  if (item) {
158
- const tab = item.dataset.tab
159
- hideSpotlight()
160
- if (tab === 'inspect') {
161
- window.__oneSourceInspector?.activate()
162
- } else {
163
- activeTab = tab
164
- showPanel()
423
+ const idx = parseInt(item.dataset.index)
424
+ if (!isNaN(idx) && idx !== selectedIndex) {
425
+ selectedIndex = idx
426
+ updateSelection()
165
427
  }
166
428
  }
167
429
  })
168
430
 
431
+ itemsContainer.addEventListener('click', (e) => {
432
+ const item = e.target.closest('.spotlight-item')
433
+ if (item) handleItemClick(item.dataset.id)
434
+ })
435
+
169
436
  spotlightDialog.addEventListener('click', (e) => {
170
437
  if (e.target === spotlightDialog) spotlightDialog.close()
171
438
  })
@@ -177,7 +444,7 @@
177
444
  panel.innerHTML =
178
445
  '<div class="panel-header" id="panel-header">' +
179
446
  LOGO_SVG +
180
- '<span class="panel-title">DevTools</span><button class="panel-close" id="panel-close">×</button></div><div class="tabs" id="tabs"><button class="tab active" data-tab="seo">SEO</button><button class="tab" data-tab="route">Route</button><button class="tab" data-tab="loader">Loader</button><button class="tab" data-tab="errors">Errors</button></div><div class="content" id="content"></div>'
447
+ '<span class="panel-title">DevTools</span><button class="panel-close" id="panel-close">\u00d7</button></div><div class="tabs" id="tabs"><button class="tab active" data-tab="seo">SEO</button><button class="tab" data-tab="route">Route</button><button class="tab" data-tab="loader">Loader</button><button class="tab" data-tab="errors">Errors</button></div><div class="content" id="content"></div>'
181
448
 
182
449
  shadow.getElementById('panel-close').addEventListener('click', hidePanel)
183
450
 
@@ -263,36 +530,18 @@
263
530
  function setupKeyboard() {
264
531
  if (keyboardSetup) return
265
532
  keyboardSetup = true
266
- // use capture: false so app handlers can preventDefault first
267
533
  document.addEventListener(
268
534
  'keydown',
269
535
  (e) => {
270
- // respect other handlers and browser shortcuts
271
536
  if (e.defaultPrevented || e.metaKey || e.ctrlKey) return
272
537
 
273
538
  if (e.altKey && e.code === 'Space') {
274
539
  e.preventDefault()
275
540
  toggleSpotlight()
276
- } else if (e.altKey) {
277
- if (e.code === 'KeyI') {
278
- e.preventDefault()
279
- hideSpotlight()
280
- window.__oneSourceInspector?.activate()
281
- return
282
- }
283
- const tabMap = {
284
- KeyS: 'seo',
285
- KeyR: 'route',
286
- KeyL: 'loader',
287
- KeyE: 'errors',
288
- }
289
- const tab = tabMap[e.code]
290
- if (tab) {
291
- e.preventDefault()
292
- activeTab = tab
293
- hideSpotlight()
294
- showPanel()
295
- }
541
+ } else if (e.altKey && e.code === 'KeyI') {
542
+ e.preventDefault()
543
+ hideSpotlight()
544
+ window.__oneSourceInspector?.activate()
296
545
  } else if (e.code === 'Escape') {
297
546
  if (spotlightDialog?.open) spotlightDialog.close()
298
547
  else if (panelDialog?.open) panelDialog.close()
@@ -309,11 +558,15 @@
309
558
 
310
559
  function showSpotlight() {
311
560
  if (!host) createHost()
561
+ const searchInput = shadow.getElementById('spotlight-search')
562
+ searchInput.value = ''
563
+ renderSpotlightItems('')
312
564
  spotlightDialog.showModal()
565
+ requestAnimationFrame(() => searchInput.focus())
313
566
  }
314
567
 
315
568
  function hideSpotlight() {
316
- spotlightDialog.close()
569
+ if (spotlightDialog?.open) spotlightDialog.close()
317
570
  }
318
571
 
319
572
  function showPanel() {
@@ -391,7 +644,7 @@
391
644
  issues.forEach((i) => {
392
645
  html +=
393
646
  '<div class="issue-item"><span class="issue-icon">' +
394
- (i.type === 'error' ? '' : '') +
647
+ (i.type === 'error' ? '\u2716' : '\u26a0') +
395
648
  '</span><span>' +
396
649
  escapeHtml(i.msg) +
397
650
  '</span></div>'
@@ -591,7 +844,7 @@
591
844
  const errors = devtools.errorHistory || []
592
845
 
593
846
  if (!errors.length) {
594
- return '<div class="empty">✓ No errors recorded</div>'
847
+ return '<div class="empty">\u2713 No errors recorded</div>'
595
848
  }
596
849
 
597
850
  let html = ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one",
3
- "version": "1.6.11",
3
+ "version": "1.6.12",
4
4
  "license": "BSD-3-Clause",
5
5
  "sideEffects": [
6
6
  "setup.mjs",
@@ -149,17 +149,17 @@
149
149
  "@react-navigation/routers": "~7.5.1",
150
150
  "@swc/core": "^1.14.0",
151
151
  "@ungap/structured-clone": "^1.2.0",
152
- "@vxrn/color-scheme": "1.6.11",
153
- "@vxrn/compiler": "1.6.11",
154
- "@vxrn/resolve": "1.6.11",
155
- "@vxrn/tslib-lite": "1.6.11",
156
- "@vxrn/use-isomorphic-layout-effect": "1.6.11",
157
- "@vxrn/vite-plugin-metro": "1.6.11",
152
+ "@vxrn/color-scheme": "1.6.12",
153
+ "@vxrn/compiler": "1.6.12",
154
+ "@vxrn/resolve": "1.6.12",
155
+ "@vxrn/tslib-lite": "1.6.12",
156
+ "@vxrn/use-isomorphic-layout-effect": "1.6.12",
157
+ "@vxrn/vite-plugin-metro": "1.6.12",
158
158
  "babel-dead-code-elimination": "1.0.10",
159
159
  "babel-plugin-module-resolver": "^5.0.2",
160
160
  "citty": "^0.1.6",
161
161
  "core-js": "^3.38.1",
162
- "create-vxrn": "1.6.11",
162
+ "create-vxrn": "1.6.12",
163
163
  "escape-string-regexp": "^5.0.0",
164
164
  "expo-linking": "~8.0.8",
165
165
  "expo-modules-core": "~3.0.24",
@@ -184,7 +184,7 @@
184
184
  "use-latest-callback": "^0.2.3",
185
185
  "vite": "^7.1.12",
186
186
  "vite-tsconfig-paths": "^6.0.5",
187
- "vxrn": "1.6.11",
187
+ "vxrn": "1.6.12",
188
188
  "ws": "^8.18.0",
189
189
  "xxhashjs": "^0.2.2"
190
190
  },