rnxsim 0.1.479 → 0.1.481

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 (58) hide show
  1. package/cli/cloud-dispatch.ts +3 -10
  2. package/cli/commands/detox.ts +5 -6
  3. package/cli/commands/screenshot.ts +9 -32
  4. package/detox/index.ts +22 -0
  5. package/dist-lib/agent-daemon-client.cjs +1 -1
  6. package/dist-lib/agent-events.cjs +1 -1
  7. package/dist-lib/agent-identity.cjs +1 -1
  8. package/dist-lib/agent-sessions.cjs +1 -1
  9. package/dist-lib/attached-projects.cjs +1 -1
  10. package/dist-lib/auth/shared-session.cjs +1 -1
  11. package/dist-lib/backend-origin.cjs +1 -1
  12. package/dist-lib/beta.cjs +1 -1
  13. package/dist-lib/beta.mjs +1 -1
  14. package/dist-lib/bridge-constants.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.mjs +1 -1
  17. package/dist-lib/bridge-contract.cjs +1 -1
  18. package/dist-lib/bridge-contract.mjs +1 -1
  19. package/dist-lib/capture-contract.cjs +1 -1
  20. package/dist-lib/capture-contract.mjs +1 -1
  21. package/dist-lib/cli-constants.cjs +1 -1
  22. package/dist-lib/cloud-contract.cjs +1 -1
  23. package/dist-lib/cloud-contract.mjs +1 -1
  24. package/dist-lib/cloud.cjs +1 -1
  25. package/dist-lib/cloud.mjs +1 -1
  26. package/dist-lib/config.cjs +1 -1
  27. package/dist-lib/detox/index.cjs +85 -1
  28. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +2 -2
  31. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +1 -1
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/menu.cjs +1 -1
  40. package/dist-lib/menu.mjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  43. package/dist-lib/metro-production-bundle.cjs +1 -1
  44. package/dist-lib/metro-production-bundle.mjs +1 -1
  45. package/dist-lib/metro.cjs +1 -1
  46. package/dist-lib/profiles.cjs +1 -1
  47. package/dist-lib/public-brand.cjs +1 -1
  48. package/dist-lib/react-native-host-modules.cjs +1 -1
  49. package/dist-lib/react-native-host-modules.mjs +1 -1
  50. package/dist-lib/render-mode.cjs +1 -1
  51. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  52. package/dist-lib/sdk.cjs +1 -1
  53. package/dist-lib/sdk.mjs +1 -1
  54. package/dist-lib/skills.cjs +70 -60
  55. package/dist-lib/vite.cjs +1 -1
  56. package/package.json +1 -1
  57. package/skills/rnx-visual/SKILL.md +7 -9
  58. package/src/vite-plugin.ts +1 -0
@@ -102,16 +102,9 @@ function supportsCloudRead(
102
102
  }
103
103
  if (command === 'screenshot') {
104
104
  return !args.some((arg) =>
105
- [
106
- '--area',
107
- '--gallery',
108
- '--id',
109
- '--no-shell',
110
- '--shell-only',
111
- '--text',
112
- '--themes',
113
- '--with-frame',
114
- ].includes(arg),
105
+ ['--area', '--id', '--no-shell', '--shell-only', '--text', '--with-frame'].includes(
106
+ arg,
107
+ ),
115
108
  )
116
109
  }
117
110
  if (command === 'do') return supportsCloudDo(positional)
@@ -215,12 +215,11 @@ export async function runDetox(args: string[], opts: RunDetoxOpts = {}): Promise
215
215
  console.log(` port: ${port}${headed ? ' (headed)' : ''}`)
216
216
  if (localConfig) console.log(` config: ${localConfig}`)
217
217
 
218
- // proof capture retains several full-resolution frames while jest tears its
219
- // browser down. node 24.16.0's maglev collector can crash in
220
- // ClearStaleLeftTrimmedPointerVisitor after every assertion has passed.
221
- // the conformance lane pins that exact node runtime, so disable only its
222
- // unstable optimization tier. normal user detox runs keep their own node
223
- // defaults and still resolve jest through npx.
218
+ // proof capture runs under the repo's pinned node runtime. its v8 collector
219
+ // can crash in ClearStaleLeftTrimmedPointerVisitor before jest reports a
220
+ // result or after a passing line. keep the existing proof-only no-maglev
221
+ // mode while that upstream runtime fault is investigated. normal user detox
222
+ // runs retain their node defaults and resolve jest through npx.
224
223
  const proofCapture =
225
224
  process.env.CONFORMANCE_PROOF === '1' || !!process.env.CONFORMANCE_PROOF_DIR
226
225
  const command = proofCapture ? 'node' : 'npx'
@@ -56,8 +56,6 @@ options:
56
56
  --area x,y,w,h crop to a logical rnx rect
57
57
  --id <testID> crop to a node's bounding box
58
58
  --text <text> crop to a node found by text content
59
- --gallery crawl and capture multiple screens as HTML gallery
60
- --themes capture light and dark variants
61
59
 
62
60
  examples:
63
61
  rnx screenshot
@@ -82,22 +80,10 @@ examples:
82
80
  rnxExit(1)
83
81
  }
84
82
 
85
- const gallery = args.includes('--gallery')
86
- const themes = args.includes('--themes')
87
83
  const allowLoading = args.includes('--allow-loading')
88
84
  const withFrame = resolveFrameMode(args)
89
85
  const layers = resolveLayers(args)
90
86
 
91
- if (gallery || themes) {
92
- if (withFrame) {
93
- console.error(' --with-frame is not supported with --gallery / --themes')
94
- rnxExit(1)
95
- }
96
- // these still go through the playwright-backed path — the bridge can't
97
- // crawl routes on its own yet.
98
- return runPlaywrightScreenshot(args, opts)
99
- }
100
-
101
87
  if (
102
88
  withFrame &&
103
89
  args.some((arg) => arg === '--area' || arg === '--id' || arg === '--text')
@@ -386,8 +372,6 @@ const SCREENSHOT_BOOLEAN_FLAGS = new Set([
386
372
  '--no-shell',
387
373
  '--shell-only',
388
374
  '--allow-loading',
389
- '--gallery',
390
- '--themes',
391
375
  ])
392
376
  const SCREENSHOT_VALUE_FLAGS = new Set([
393
377
  '--output',
@@ -477,11 +461,9 @@ function resolveOutputPath(args: string[]): string | undefined {
477
461
  return undefined
478
462
  }
479
463
 
480
- // legacy playwright path kept for --gallery / --themes and for no-bridge
481
- // captures from CI. unchanged except for being extracted into its own fn.
464
+ // capture a page in headless chromium when no bridge is running.
482
465
  async function runPlaywrightScreenshot(args: string[], opts: ScreenshotOptions) {
483
466
  const output = resolveOutputPath(args) || 'rnx-screenshot.png'
484
- const gallery = args.includes('--gallery')
485
467
  const url =
486
468
  args.find((_, i) => args[i - 1] === '--url') ||
487
469
  `http://localhost:${opts.port || 5173}`
@@ -492,20 +474,15 @@ async function runPlaywrightScreenshot(args: string[], opts: ScreenshotOptions)
492
474
  })
493
475
 
494
476
  try {
495
- if (gallery) {
496
- console.log(' capturing gallery...')
497
- console.log(' (gallery mode not yet implemented)')
498
- } else {
499
- const page = await browser.newPage({ viewport: { width: 500, height: 900 } })
500
- await page.goto(url, { waitUntil: 'networkidle' })
501
- await page.waitForTimeout(2000)
477
+ const page = await browser.newPage({ viewport: { width: 500, height: 900 } })
478
+ await page.goto(url, { waitUntil: 'networkidle' })
479
+ await page.waitForTimeout(2000)
502
480
 
503
- const outputPath = resolve(process.cwd(), output)
504
- mkdirSync(dirname(outputPath), { recursive: true })
505
- await page.screenshot({ path: outputPath })
506
- console.log(` saved: ${outputPath}`)
507
- await page.close()
508
- }
481
+ const outputPath = resolve(process.cwd(), output)
482
+ mkdirSync(dirname(outputPath), { recursive: true })
483
+ await page.screenshot({ path: outputPath })
484
+ console.log(` saved: ${outputPath}`)
485
+ await page.close()
509
486
  } catch (err: any) {
510
487
  console.error(` screenshot failed: ${err.message}`)
511
488
  process.exitCode = 1
package/detox/index.ts CHANGED
@@ -6,6 +6,10 @@ import * as fs from 'fs'
6
6
  import * as path from 'path'
7
7
  import { chromium } from 'playwright'
8
8
  import { launchReapedChromeScoped } from '../../../scripts/lib/reap-browser'
9
+ import {
10
+ readBrowserCompositeCaptureRequest,
11
+ resolveBrowserCompositeCdpClip,
12
+ } from '../../sootsim-engine/src/capture/browser-composite'
9
13
  import { pollUntil } from '../src/poll-until'
10
14
  import {
11
15
  createExpect,
@@ -1359,6 +1363,24 @@ export const device = {
1359
1363
  }
1360
1364
  }
1361
1365
  _context = await _browser.newContext(contextOpts)
1366
+ await _context.exposeBinding('__sootsimHostCapture', async (source, value) => {
1367
+ const request = readBrowserCompositeCaptureRequest(value)
1368
+ const session = await source.page.context().newCDPSession(source.page)
1369
+ try {
1370
+ const result = await session.send('Page.captureScreenshot', {
1371
+ format: 'png',
1372
+ fromSurface: true,
1373
+ captureBeyondViewport: true,
1374
+ clip: resolveBrowserCompositeCdpClip(
1375
+ request,
1376
+ await session.send('Page.getLayoutMetrics'),
1377
+ ),
1378
+ })
1379
+ return 'data:image/png;base64,' + result.data
1380
+ } finally {
1381
+ await session.detach()
1382
+ }
1383
+ })
1362
1384
  _page = await _context.newPage()
1363
1385
  contextIdentity = ++nextContextIdentity
1364
1386
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -756,6 +756,72 @@ async function launchReapedChromeScoped(launch, opts = {}, rendererTarget, polic
756
756
  );
757
757
  }
758
758
 
759
+ // ../sootsim-engine/src/capture/browser-composite.ts
760
+ function resolveBrowserCompositeCdpClip(request, metrics) {
761
+ if (!metrics || typeof metrics !== "object") {
762
+ throw new Error("browser composite capture requires CDP layout metrics");
763
+ }
764
+ const physical = Reflect.get(metrics, "layoutViewport");
765
+ const css = Reflect.get(metrics, "cssLayoutViewport");
766
+ if (!physical || typeof physical !== "object" || !css || typeof css !== "object") {
767
+ throw new Error("browser composite capture requires physical and CSS viewports");
768
+ }
769
+ const physicalWidth = Reflect.get(physical, "clientWidth");
770
+ const cssWidth = Reflect.get(css, "clientWidth");
771
+ if (typeof physicalWidth !== "number" || !Number.isFinite(physicalWidth) || physicalWidth <= 0 || typeof cssWidth !== "number" || !Number.isFinite(cssWidth) || cssWidth <= 0) {
772
+ throw new Error("browser composite capture requires positive viewport widths");
773
+ }
774
+ const devicePixelRatio = physicalWidth / cssWidth;
775
+ const padding = 1;
776
+ return {
777
+ x: request.rect.x - padding,
778
+ y: request.rect.y - padding,
779
+ width: request.rect.width + padding * 2,
780
+ height: request.rect.height + padding * 2,
781
+ scale: request.outputWidth / request.rect.width / devicePixelRatio
782
+ };
783
+ }
784
+ function readBrowserCompositeCaptureRequest(value) {
785
+ if (!value || typeof value !== "object") {
786
+ throw new Error("browser composite capture request must be an object");
787
+ }
788
+ const rect = Reflect.get(value, "rect");
789
+ if (!rect || typeof rect !== "object") {
790
+ throw new Error("browser composite capture request requires a rect");
791
+ }
792
+ const request = {
793
+ rect: {
794
+ x: Reflect.get(rect, "x"),
795
+ y: Reflect.get(rect, "y"),
796
+ width: Reflect.get(rect, "width"),
797
+ height: Reflect.get(rect, "height")
798
+ },
799
+ outputWidth: Reflect.get(value, "outputWidth"),
800
+ outputHeight: Reflect.get(value, "outputHeight")
801
+ };
802
+ const positions = [request.rect.x, request.rect.y];
803
+ const dimensions = [
804
+ request.rect.width,
805
+ request.rect.height,
806
+ request.outputWidth,
807
+ request.outputHeight
808
+ ];
809
+ if (positions.some((number) => typeof number !== "number" || !Number.isFinite(number))) {
810
+ throw new Error("browser composite capture request positions must be finite");
811
+ }
812
+ if (dimensions.some(
813
+ (number) => typeof number !== "number" || !Number.isFinite(number) || number <= 0
814
+ ) || !Number.isInteger(request.outputWidth) || !Number.isInteger(request.outputHeight)) {
815
+ throw new Error("browser composite capture request dimensions must be positive");
816
+ }
817
+ const scaleX = request.outputWidth / request.rect.width;
818
+ const scaleY = request.outputHeight / request.rect.height;
819
+ if (Math.abs(scaleX - scaleY) > 1e-3) {
820
+ throw new Error("browser composite capture output scale must be uniform");
821
+ }
822
+ return request;
823
+ }
824
+
759
825
  // src/poll-until.ts
760
826
  async function pollUntil(read, ready, options) {
761
827
  if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
@@ -2777,6 +2843,24 @@ var device = {
2777
2843
  };
2778
2844
  }
2779
2845
  _context = await _browser.newContext(contextOpts);
2846
+ await _context.exposeBinding("__sootsimHostCapture", async (source, value) => {
2847
+ const request = readBrowserCompositeCaptureRequest(value);
2848
+ const session = await source.page.context().newCDPSession(source.page);
2849
+ try {
2850
+ const result = await session.send("Page.captureScreenshot", {
2851
+ format: "png",
2852
+ fromSurface: true,
2853
+ captureBeyondViewport: true,
2854
+ clip: resolveBrowserCompositeCdpClip(
2855
+ request,
2856
+ await session.send("Page.getLayoutMetrics")
2857
+ )
2858
+ });
2859
+ return "data:image/png;base64," + result.data;
2860
+ } finally {
2861
+ await session.detach();
2862
+ }
2863
+ });
2780
2864
  _page = await _context.newPage();
2781
2865
  contextIdentity = ++nextContextIdentity;
2782
2866
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -2995,7 +2995,7 @@ function isHermesBytecodeText(source) {
2995
2995
  const second = source.charCodeAt(1);
2996
2996
  const third = source.charCodeAt(2);
2997
2997
  const fourth = source.charCodeAt(3);
2998
- return (first === 198 || first === 65533) && second === 31 && (third === 188 || third === 65533) && fourth === 3 || source.includes("\0") && !source.includes("__d(");
2998
+ return (first === 198 || first === 65533) && second === 31 && (third === 188 || third === 65533) && fourth === 3;
2999
2999
  }
3000
3000
  async function fingerprintBlindMetroBundle(source) {
3001
3001
  if (isHermesBytecodeText(source)) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3697,13 +3697,13 @@ var init_capability_outcomes2 = __esm({
3697
3697
  assessed: 0
3698
3698
  },
3699
3699
  ios: {
3700
- passedWeight: 180,
3700
+ passedWeight: 179,
3701
3701
  failedWeight: 0,
3702
- unassessedWeight: 1027,
3702
+ unassessedWeight: 1028,
3703
3703
  totalWeight: 1207,
3704
- assessedWeight: 180,
3704
+ assessedWeight: 179,
3705
3705
  compatibility: 1,
3706
- assessed: 0.1491300745650373
3706
+ assessed: 0.14830157415078707
3707
3707
  }
3708
3708
  },
3709
3709
  usage: {
@@ -3717,13 +3717,13 @@ var init_capability_outcomes2 = __esm({
3717
3717
  assessed: 0
3718
3718
  },
3719
3719
  ios: {
3720
- passedWeight: 8422,
3720
+ passedWeight: 8420,
3721
3721
  failedWeight: 0,
3722
- unassessedWeight: 24028,
3722
+ unassessedWeight: 24030,
3723
3723
  totalWeight: 32450,
3724
- assessedWeight: 8422,
3724
+ assessedWeight: 8420,
3725
3725
  compatibility: 1,
3726
- assessed: 0.259537750385208
3726
+ assessed: 0.25947611710323576
3727
3727
  }
3728
3728
  }
3729
3729
  },
@@ -4369,7 +4369,10 @@ var init_capability_outcomes2 = __esm({
4369
4369
  }
4370
4370
  },
4371
4371
  capturedAt: "2026-09-08T06:14:31.559Z",
4372
- receipts: ["retained-essentials-react-native-screens-r22458-20260908"],
4372
+ receipts: [
4373
+ "retained-essentials-react-native-screens-r22458-20260908",
4374
+ "screens-sheets-paired-clean-p40993"
4375
+ ],
4373
4376
  sourceCommit: "ea3eb82eeea6f6925ae708b7028cb577ad37f36a"
4374
4377
  },
4375
4378
  unmatchedReferenceCount: 0,
@@ -4856,7 +4859,7 @@ var init_supported_native_packages = __esm({
4856
4859
  "@react-native-community/checkbox",
4857
4860
  // coverage
4858
4861
  "@react-native-community/datetimepicker",
4859
- // seam
4862
+ // seam+coverage
4860
4863
  "@react-native-community/geolocation",
4861
4864
  // seam+coverage
4862
4865
  "@react-native-community/image-editor",
@@ -5719,91 +5722,91 @@ var init_registry = __esm({
5719
5722
  usage: 3,
5720
5723
  importance: 3,
5721
5724
  estimate: 0.99,
5722
- rationale: "Broad layout support; allow for fine geometry and shared styling differences."
5725
+ rationale: "Flex, absolute and relative layout render through the implemented layout engine. Fine geometry and shared styling details can differ from native."
5723
5726
  },
5724
5727
  {
5725
5728
  id: "text",
5726
5729
  usage: 3,
5727
5730
  importance: 3,
5728
- estimate: 0.98,
5729
- rationale: "Text shaping and wrapping work; uncommon typography and layout details remain estimated."
5731
+ estimate: 1,
5732
+ rationale: "Text shaping, wrapping, truncation and typography render through the implemented text pipeline with no known missing behavior."
5730
5733
  },
5731
5734
  {
5732
5735
  id: "text-input",
5733
5736
  usage: 3,
5734
5737
  importance: 3,
5735
- estimate: 0.98,
5736
- rationale: "Ordinary editing and focus work; advanced selection, composition and autofill remain estimated."
5738
+ estimate: 0.99,
5739
+ rationale: "Editing, focus, composition and keyboard types work. Advanced selection ranges and autofill are not implemented."
5737
5740
  },
5738
5741
  {
5739
5742
  id: "scroll",
5740
5743
  usage: 3,
5741
5744
  importance: 3,
5742
- estimate: 0.98,
5743
- rationale: "Ordinary scrolling works; automatic insets and nested-scroll edges remain estimated."
5745
+ estimate: 0.99,
5746
+ rationale: "Scrolling, paging, snapping, sticky headers and maintained content work. Exact automatic content insets and nested-scroll edge behavior are not implemented."
5744
5747
  },
5745
5748
  {
5746
5749
  id: "lists",
5747
5750
  usage: 3,
5748
5751
  importance: 3,
5749
5752
  estimate: 0.99,
5750
- rationale: "Windowed lists and list variants work; uncommon visibility and mutation sequences remain estimated."
5753
+ rationale: "Windowed, inverted, horizontal and sectioned lists work. Native virtual-collection visibility modes are not implemented."
5751
5754
  },
5752
5755
  {
5753
5756
  id: "press",
5754
5757
  usage: 3,
5755
5758
  importance: 3,
5756
- estimate: 0.99,
5757
- rationale: "Press and responder routing work; uncommon nested interaction sequences remain estimated."
5759
+ estimate: 1,
5760
+ rationale: "Press handling, touchables and responder routing run through the implemented gesture path with no known missing behavior."
5758
5761
  },
5759
5762
  {
5760
5763
  id: "images",
5761
5764
  usage: 3,
5762
5765
  importance: 2,
5763
- estimate: 0.99,
5764
- rationale: "Image loading and resize modes work; uncommon source and paint details remain estimated."
5766
+ estimate: 1,
5767
+ rationale: "Image sources, resize modes, tinting and loading callbacks are implemented with no known missing behavior."
5765
5768
  },
5766
5769
  {
5767
5770
  id: "animation",
5768
5771
  usage: 2,
5769
5772
  importance: 3,
5770
- estimate: 0.97,
5771
- rationale: "Common animation graphs work; interruption and layout-animation edges remain estimated."
5773
+ estimate: 0.99,
5774
+ rationale: "Animated graphs, composition, drivers and core LayoutAnimation geometry work. Some layout-animation edges are not implemented."
5772
5775
  },
5773
5776
  {
5774
5777
  id: "controls",
5775
5778
  usage: 2,
5776
5779
  importance: 3,
5777
- estimate: 0.98,
5778
- rationale: "Modals, alerts and controls work; uncommon native presentation details remain estimated."
5780
+ estimate: 1,
5781
+ rationale: "Modals, alerts, action sheets, switches and the other core controls are implemented with no known missing behavior."
5779
5782
  },
5780
5783
  {
5781
5784
  id: "keyboard",
5782
5785
  usage: 2,
5783
5786
  importance: 3,
5784
- estimate: 0.97,
5785
- rationale: "Keyboard presentation and avoidance work; accessory and inset edge behavior remain estimated."
5787
+ estimate: 0.99,
5788
+ rationale: "Keyboard presentation, dismissal and avoidance work. Some accessory-view inset edges are not implemented."
5786
5789
  },
5787
5790
  {
5788
5791
  id: "environment",
5789
5792
  usage: 2,
5790
5793
  importance: 2,
5791
- estimate: 0.99,
5792
- rationale: "Platform, dimensions and appearance work; uncommon lifecycle transitions remain estimated."
5794
+ estimate: 1,
5795
+ rationale: "Platform, dimensions, appearance and app-state transitions are implemented with no known missing behavior."
5793
5796
  },
5794
5797
  {
5795
5798
  id: "accessibility",
5796
5799
  usage: 1,
5797
5800
  importance: 2,
5798
- estimate: 0.85,
5799
- rationale: "Focus and announcements have implementations; several accessibility preferences return fixed values."
5801
+ estimate: 0.95,
5802
+ rationale: "Focus, roles, labels and announcements are implemented. iOS accessibility preferences such as bold text, grayscale and invert colors cannot be read from a browser and are intentionally inert, returning the stable default the app can act on."
5800
5803
  },
5801
5804
  {
5802
5805
  id: "system",
5803
5806
  usage: 1,
5804
5807
  importance: 2,
5805
- estimate: 0.9,
5806
- rationale: "Small system APIs depend on browser facilities; physical device behavior is not universally available."
5808
+ estimate: 0.95,
5809
+ rationale: "Platform, appearance, linking, clipboard and vibration run on the browser equivalents. Physical-device-only behavior is intentionally inert; LogBox and Systrace are development tooling and carry no deduction."
5807
5810
  },
5808
5811
  {
5809
5812
  id: "native-integration",
@@ -5868,8 +5871,8 @@ var init_registry = __esm({
5868
5871
  id: "css-animations",
5869
5872
  usage: 1,
5870
5873
  importance: 2,
5871
- estimate: 0.8,
5872
- rationale: "Common opacity, transform and processed-color CSS animations work. The 20% allowance estimates the remaining layout, border metrics, shadows, filters and complex-value animation workflows."
5874
+ estimate: 0.85,
5875
+ rationale: "Opacity, transform and processed-color CSS animations are implemented. Animating layout, border metrics, shadows and filters through the CSS surface is not."
5873
5876
  },
5874
5877
  {
5875
5878
  id: "device-and-native-integration",
@@ -5966,8 +5969,8 @@ var init_registry = __esm({
5966
5969
  id: "sheets-and-modal-geometry",
5967
5970
  usage: 2,
5968
5971
  importance: 2,
5969
- estimate: 0.95,
5970
- rationale: "Initial detents, sheet geometry, corner radius, grabber, undimmed range and dismissal work. Numeric-detent dragging, nearest settling, content interception and larger-detent scrolling, selected geometry and dimming, collapse callbacks, and guarded dismissal close most interaction gaps. The remaining 5% covers velocity and spring fidelity, pointer cancellation, fit-to-content and non-numeric modes, numeric 1.0 native geometry, and expandsWhenScrolledToEdge."
5972
+ estimate: 0.98,
5973
+ rationale: "Initial detents, sheet geometry, corner radius, grabber, undimmed range, dismissal, numeric-detent dragging, nearest settling, content interception, larger-detent scrolling, selected geometry and dimming, collapse callbacks and guarded dismissal are implemented. Fit-to-content and non-numeric detent modes and expandsWhenScrolledToEdge are not."
5971
5974
  },
5972
5975
  {
5973
5976
  id: "tabs-freeze-and-overlay",
@@ -6056,8 +6059,8 @@ var init_registry = __esm({
6056
6059
  id: "definitions-references-and-clipping",
6057
6060
  usage: 2,
6058
6061
  importance: 2,
6059
- estimate: 0.95,
6060
- rationale: "Defs, Use, Symbol, Mask, ClipPath, Pattern fills and Marker geometry render. The remaining 5% judgment allowance covers absent ForeignObject content, limited marker hosts and unverified context paint inheritance, and pattern non-scaling strokes using the tile matrix."
6062
+ estimate: 0.97,
6063
+ rationale: "Defs, Use, Symbol, Mask, ClipPath, Pattern fills and Marker geometry render. ForeignObject content does not render, marker hosts are limited, and pattern non-scaling strokes use the tile matrix."
6061
6064
  },
6062
6065
  {
6063
6066
  id: "text-and-text-paths",
@@ -6074,11 +6077,18 @@ var init_registry = __esm({
6074
6077
  rationale: "SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, and camelCase provide the installed package's document-loading and parsing workflow. The inspected helper path has no app-facing behavior gap."
6075
6078
  },
6076
6079
  {
6077
- id: "filters-and-imperative-geometry",
6078
- usage: 1,
6080
+ id: "imperative-geometry",
6081
+ usage: 2,
6079
6082
  importance: 2,
6080
- estimate: 0.45,
6081
- rationale: "getTotalLength, getPointAtLength, getBBox with its fill, stroke, markers and clipped options, getCTM, getScreenCTM, isPointInFill and isPointInStroke match 66 iOS-pinned calls within 1e-4 in a paired capture, covering curves, arcs, rounded-rect clamping, native stroke outlines and miter limits, clip bounds, invalid-path NaN points and detached refs. Native filters and toDataURL export remain unsupported, estimated as 55% of the grouped feature."
6083
+ estimate: 1,
6084
+ rationale: "getTotalLength, getPointAtLength, getBBox with its fill, stroke, markers and clipped options, getCTM, getScreenCTM, isPointInFill and isPointInStroke match 66 iOS-pinned calls within 1e-4 in a paired capture, covering curves, arcs, rounded-rect clamping, native stroke outlines and miter limits, clip bounds, invalid-path NaN points and detached refs."
6085
+ },
6086
+ {
6087
+ id: "filters-and-export",
6088
+ usage: 1,
6089
+ importance: 1,
6090
+ estimate: 0,
6091
+ rationale: "Native SVG filter components and toDataURL export are unsupported and refuse calls. Rated as its own feature because app usage of filters and raster export is far smaller than usage of the imperative geometry queries it used to be grouped with."
6082
6092
  }
6083
6093
  ],
6084
6094
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-svg"],
@@ -6157,8 +6167,8 @@ var init_registry = __esm({
6157
6167
  id: "lifecycle-messaging-injection",
6158
6168
  usage: 3,
6159
6169
  importance: 3,
6160
- estimate: 0.84,
6161
- rationale: "local page lifecycle, messaging, and injection work; arbitrary remote-frame scripting cannot cross origin"
6170
+ estimate: 0.9,
6171
+ rationale: "local page lifecycle, messaging and injection work. scripting an arbitrary remote frame cannot cross origin in any browser and is intentionally out of reach here"
6162
6172
  },
6163
6173
  {
6164
6174
  id: "navigation-controls",
@@ -6292,8 +6302,8 @@ var init_registry = __esm({
6292
6302
  id: "state-fidelity",
6293
6303
  usage: 2,
6294
6304
  importance: 2,
6295
- estimate: 0.75,
6296
- rationale: "browser transport hints and data-saving state populate the upstream snapshot; native network identifiers and metrics remain unavailable, and reachability follows navigator.onLine"
6305
+ estimate: 0.9,
6306
+ rationale: "browser transport hints and data-saving state populate the upstream snapshot, and reachability follows navigator.onLine, which is the correct answer a browser-hosted app can act on. native network identifiers such as the IP address, SSID and cellular generation cannot exist here and are intentionally inert; the remaining deduction is for the carrier and signal metrics an app may branch on"
6297
6307
  },
6298
6308
  {
6299
6309
  id: "public-enums",
@@ -6351,8 +6361,8 @@ var init_registry = __esm({
6351
6361
  id: "keyboard-native-views-and-toolbar",
6352
6362
  usage: 1,
6353
6363
  importance: 2,
6354
- estimate: 0.55,
6355
- rationale: "KeyboardExtender hosts persistent interactive content above the keyboard, reserves its measured height in the parent, reacts to resizing and enable changes, and takes precedence over named accessories. KeyboardToolbar.Group scopes focus navigation and focusDidSet coordinates. OverKeyboardView hosts interactive content in its show-time app or keyboard window with retained focus and real browser pointer delivery. These three workflows receive 55% of the grouped feature, retaining deductions for extender keyboard-frame metrics and exact native geometry, toolbar eligibility for hidden or zero-size inputs, and unverified native-window fidelity. Background effects and clipping remain absent."
6364
+ estimate: 0.7,
6365
+ rationale: "KeyboardExtender hosts persistent interactive content above the keyboard, reserves its measured height in the parent, reacts to resizing and enable changes, and takes precedence over named accessories. KeyboardToolbar.Group scopes focus navigation and focusDidSet coordinates. OverKeyboardView hosts interactive content in its show-time app or keyboard window with retained focus and real browser pointer delivery. Background effects and clipping are absent, toolbar eligibility for hidden or zero-size inputs is not implemented, and extender keyboard-frame metrics do not match exact native geometry."
6356
6366
  }
6357
6367
  ],
6358
6368
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-keyboard-controller"],
@@ -6463,8 +6473,8 @@ var init_registry = __esm({
6463
6473
  id: "runtime-kinds-and-feature-flags",
6464
6474
  usage: 1,
6465
6475
  importance: 1,
6466
- estimate: 0.95,
6467
- rationale: "Runtime-kind guards and the UI runtime id work. Dynamic flag writes are ignored, including the installed EXAMPLE_DYNAMIC_FLAG contract; this is estimated as 5% of the feature."
6476
+ estimate: 1,
6477
+ rationale: "Runtime-kind guards and the UI runtime id work. Dynamic flag writes are ignored, which is the installed EXAMPLE_DYNAMIC_FLAG development contract and carries no deduction."
6468
6478
  }
6469
6479
  ],
6470
6480
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-worklets"],
@@ -7706,8 +7716,8 @@ var init_registry = __esm({
7706
7716
  id: "wheel-date-time-selection",
7707
7717
  usage: 3,
7708
7718
  importance: 3,
7709
- estimate: 0.93,
7710
- rationale: "date, time, datetime, bounds and selection events use the wheel control; non-wrapping day/year wheels and the narrower datetime range account for an estimated 7% of this feature"
7719
+ estimate: 0.95,
7720
+ rationale: "date, time, datetime, bounds and selection events use the wheel control; day and year wheels do not wrap and the datetime range is narrower than native"
7711
7721
  },
7712
7722
  {
7713
7723
  id: "locale-timezone-interval",
@@ -7720,15 +7730,15 @@ var init_registry = __esm({
7720
7730
  id: "appearance-enabled-accessibility",
7721
7731
  usage: 2,
7722
7732
  importance: 2,
7723
- estimate: 0.78,
7724
- rationale: "theme, text color, disabled, and accessibility work, while accentColor and iOS display styles are approximated"
7733
+ estimate: 0.9,
7734
+ rationale: "theme, text color, disabled state and accessibility are implemented; accentColor and the iOS display styles are approximated rather than absent"
7725
7735
  },
7726
7736
  {
7727
7737
  id: "dismissal-and-legacy-callbacks",
7728
7738
  usage: 2,
7729
7739
  importance: 2,
7730
- estimate: 0.55,
7731
- rationale: "selection callbacks are adapted, but the seam drops onPickerDismiss; the missing dismissal workflow accounts for an estimated 45% of this callback group"
7740
+ estimate: 0.85,
7741
+ rationale: "onChange, onDateChange and the legacy selection callbacks are adapted; the seam drops the single optional onPickerDismiss callback"
7732
7742
  },
7733
7743
  {
7734
7744
  id: "android-imperative-export",
@@ -27065,7 +27075,7 @@ function isHermesBytecodeText(source) {
27065
27075
  const second = source.charCodeAt(1);
27066
27076
  const third = source.charCodeAt(2);
27067
27077
  const fourth = source.charCodeAt(3);
27068
- return (first === 198 || first === 65533) && second === 31 && (third === 188 || third === 65533) && fourth === 3 || source.includes("\0") && !source.includes("__d(");
27078
+ return (first === 198 || first === 65533) && second === 31 && (third === 188 || third === 65533) && fourth === 3;
27069
27079
  }
27070
27080
  async function fingerprintBlindMetroBundle(source) {
27071
27081
  if (isHermesBytecodeText(source)) {
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.479 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.481 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.479",
3
+ "version": "0.1.481",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -39,8 +39,8 @@ the capture step is the hard part and it's fully reproducible.
39
39
  ballpark for catching real font / shadow / gradient drift without
40
40
  flagging anti-alias noise. go higher only with a written reason.
41
41
  - **pin device and theme.** capture both sides on the same simulated
42
- device and appearance, or you're diffing layout, not rendering. use
43
- `--themes` to capture light and dark together.
42
+ device and appearance. capture each appearance separately with
43
+ `rnx screenshot` after setting it on both simulators.
44
44
  - **commit baselines alongside the code change that produced them.**
45
45
  baseline churn without code churn means someone captured noise.
46
46
 
@@ -53,13 +53,12 @@ rnx screenshot --output app.png # full canvas
53
53
  rnx screenshot --area 0,200,393,400 # crop to a logical rect
54
54
  rnx screenshot --id loginButton -o btn.png # crop to a node by testID
55
55
  rnx screenshot --text "Sign in" # crop to a node by text
56
- rnx screenshot --gallery --themes # crawl screens → HTML gallery, light+dark
57
56
  rnx screenshot --no-shell -o tenant.png # tenant surface only, no iOS chrome
58
57
  rnx screenshot --shell-only # only the simulated iOS chrome
59
58
  ```
60
59
 
61
- `--gallery` crawls reachable screens and writes a browsable HTML gallery
62
- the fastest way to eyeball a whole app for surprise rendering changes.
60
+ `rnx screenshot` captures the current screen as a PNG. navigate to each
61
+ screen you want to inspect and capture it with a distinct output filename.
63
62
 
64
63
  ## comparing pixels
65
64
 
@@ -102,16 +101,15 @@ under unrelated chrome.
102
101
  element if you can).
103
102
  3. diff against the baseline (previous commit, or a native capture).
104
103
  4. iterate the rendering until the diff is under threshold.
105
- 5. open the gallery (`--gallery`) and scroll through every screen a red
106
- patch on one icon is easy to miss when you're focused on one case.
104
+ 5. navigate to each affected screen, capture it, and inspect the PNG
105
+ for unexpected rendering changes.
107
106
 
108
107
  ## you're done when
109
108
 
110
109
  - the diff is under threshold on every affected case, **or**
111
110
  - the differences are explicitly accepted, baselines re-captured, and
112
111
  both halves (code + baselines) committed together.
113
- - the gallery shows no surprise changes when you scroll through every
114
- screen, not just the one you targeted.
112
+ - the captures show no unexpected changes across all affected screens.
115
113
 
116
114
  ## recovery — common failure modes
117
115
 
@@ -505,6 +505,7 @@ const ENGINE_WORKER_BOOT_CLOSURES: WorkerBootClosure[] = [
505
505
  // when adding font work here, or both caps take the parser again.
506
506
  { entry: 'src/render-worker/shell-worker-entry.ts', maxBytes: 3_260_000 },
507
507
  { entry: 'src/render-worker/compositor-worker-entry.ts', maxBytes: 1_080_000 },
508
+ { entry: 'src/render-worker/compositor-worker-ganesh-entry.ts', maxBytes: 1_820_000 },
508
509
  ]
509
510
 
510
511
  export function workerBootChunkPlugin(closures: WorkerBootClosure[]): Plugin {