rnxsim 0.1.517 → 0.1.519

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 (54) hide show
  1. package/detox/index.ts +65 -32
  2. package/dist-lib/agent-daemon-client.cjs +1 -1
  3. package/dist-lib/agent-events.cjs +1 -1
  4. package/dist-lib/agent-identity.cjs +1 -1
  5. package/dist-lib/agent-sessions.cjs +1 -1
  6. package/dist-lib/attached-projects.cjs +1 -1
  7. package/dist-lib/auth/shared-session.cjs +1 -1
  8. package/dist-lib/backend-origin.cjs +1 -1
  9. package/dist-lib/beta.cjs +1 -1
  10. package/dist-lib/beta.mjs +1 -1
  11. package/dist-lib/bridge-constants.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.mjs +1 -1
  14. package/dist-lib/bridge-contract.cjs +1 -1
  15. package/dist-lib/bridge-contract.mjs +1 -1
  16. package/dist-lib/capture-contract.cjs +1 -1
  17. package/dist-lib/capture-contract.mjs +1 -1
  18. package/dist-lib/cli-constants.cjs +1 -1
  19. package/dist-lib/cloud-contract.cjs +1 -1
  20. package/dist-lib/cloud-contract.mjs +1 -1
  21. package/dist-lib/cloud.cjs +1 -1
  22. package/dist-lib/cloud.mjs +1 -1
  23. package/dist-lib/config.cjs +1 -1
  24. package/dist-lib/detox/index.cjs +34 -15
  25. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  26. package/dist-lib/home-paths.cjs +1 -1
  27. package/dist-lib/host/bridge-host.cjs +1 -1
  28. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  29. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  31. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  32. package/dist-lib/host/websocket-proxy.cjs +1 -1
  33. package/dist-lib/index.cjs +1 -1
  34. package/dist-lib/jump-to-source-babel.cjs +1 -1
  35. package/dist-lib/jump-to-source-native.cjs +1 -1
  36. package/dist-lib/menu.cjs +1 -1
  37. package/dist-lib/menu.mjs +1 -1
  38. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  39. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  40. package/dist-lib/metro-production-bundle.cjs +1 -1
  41. package/dist-lib/metro-production-bundle.mjs +1 -1
  42. package/dist-lib/metro.cjs +1 -1
  43. package/dist-lib/profiles.cjs +1 -1
  44. package/dist-lib/public-brand.cjs +1 -1
  45. package/dist-lib/react-native-host-modules.cjs +1 -1
  46. package/dist-lib/react-native-host-modules.mjs +1 -1
  47. package/dist-lib/render-mode.cjs +1 -1
  48. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  49. package/dist-lib/sdk.cjs +1 -1
  50. package/dist-lib/sdk.mjs +1 -1
  51. package/dist-lib/skills.cjs +1 -1
  52. package/dist-lib/swift.cjs +1 -1
  53. package/dist-lib/vite.cjs +1 -1
  54. package/package.json +1 -1
package/detox/index.ts CHANGED
@@ -524,7 +524,15 @@ async function findNodeByMatcher(matcher: Matcher): Promise<any> {
524
524
  ? { hasRole: indexedMatcher.value }
525
525
  : { type: indexedMatcher.value }
526
526
  const results = await window.__sootsimTest!.queryAll(filter)
527
- return results[indexedMatcher.index ?? 0] ?? null
527
+ // detox indexes by.text over the text elements that read exactly that
528
+ // text. hasText also matches every ancestor, so index 0 would be the root.
529
+ const indexed =
530
+ indexedMatcher.type === 'text'
531
+ ? results.filter(
532
+ (node) => node.type === 'text' && node.text === indexedMatcher.value,
533
+ )
534
+ : results
535
+ return indexed[indexedMatcher.index ?? 0] ?? null
528
536
  }, matcher)
529
537
  }
530
538
  if (matcher.type === 'id') {
@@ -1772,8 +1780,15 @@ export const device = {
1772
1780
  // once durationMs of lockstep time has elapsed, so held states (a lifted
1773
1781
  // control thumb, a pressed row) are painted mid-hold. an external trigger
1774
1782
  // that holds and releases before returning never paints a frame in
1775
- // between, because no lockstep frame steps while it runs.
1776
- hold?: { durationMs: number; x: number; y: number } | null
1783
+ // between, because no lockstep frame steps while it runs. moves drag the
1784
+ // held pointer to each point once afterMs of lockstep time has elapsed
1785
+ // since the press, and the release lands at the last point reached.
1786
+ hold?: {
1787
+ durationMs: number
1788
+ moves?: Array<{ afterMs: number; x: number; y: number }>
1789
+ x: number
1790
+ y: number
1791
+ } | null
1777
1792
  rootFrame?: { height: number; width: number; x: number; y: number } | null
1778
1793
  settleMs?: number
1779
1794
  trigger?: () => unknown
@@ -1851,6 +1866,7 @@ export const device = {
1851
1866
  bridges?: {
1852
1867
  interact?: {
1853
1868
  touchDown: (x: number, y: number) => Promise<boolean>
1869
+ touchMove: (x: number, y: number) => Promise<boolean>
1854
1870
  touchUp: (x: number, y: number) => Promise<boolean>
1855
1871
  }
1856
1872
  liveComposite?: {
@@ -1982,23 +1998,45 @@ export const device = {
1982
1998
  const frameMs = 1000 / 60
1983
1999
  const controller = await lockstep.begin(60)
1984
2000
  // the hold's pointer goes down before the first stepped frame, so its
1985
- // start is one frame before the first receipt; the release lands on the
1986
- // first stepped frame at or past durationMs from there. the deadline is
1987
- // a frame index: comparing summed virtual timestamps against the
1988
- // duration lets rounding push the release past the frame it belongs to.
1989
- const holdState: { released: boolean; releaseFrameIndex: number | null } = {
2001
+ // start is one frame before the first receipt; each move and the release
2002
+ // land on the first stepped frame at or past their time from there. the
2003
+ // deadlines are frame indexes: comparing summed virtual timestamps
2004
+ // against a duration lets rounding push an event past its frame.
2005
+ const moves = input.hold?.moves ?? []
2006
+ const holdState = {
2007
+ nextMove: 0,
2008
+ pressFrameIndex: null as number | null,
1990
2009
  released: false,
1991
- releaseFrameIndex: null,
2010
+ x: input.hold?.x ?? 0,
2011
+ y: input.hold?.y ?? 0,
2012
+ }
2013
+ const holdEventFrameIndex = (afterMs: number) =>
2014
+ (holdState.pressFrameIndex ?? 0) + Math.ceil(afterMs / frameMs)
2015
+ const nextHoldEventFrameIndex = () => {
2016
+ if (!input.hold || holdState.released || holdState.pressFrameIndex === null) {
2017
+ return null
2018
+ }
2019
+ const move = moves[holdState.nextMove]
2020
+ return holdEventFrameIndex(move ? move.afterMs : input.hold.durationMs)
1992
2021
  }
1993
- const releaseHoldIfDue = async (receipt: FrameReceipt) => {
2022
+ const advanceHold = async (receipt: FrameReceipt) => {
1994
2023
  if (!input.hold || !interact || holdState.released) return
1995
- if (holdState.releaseFrameIndex === null) {
1996
- holdState.releaseFrameIndex =
1997
- receipt.frameIndex - 1 + Math.ceil(input.hold.durationMs / frameMs)
2024
+ if (holdState.pressFrameIndex === null) {
2025
+ holdState.pressFrameIndex = receipt.frameIndex - 1
1998
2026
  }
1999
- if (receipt.frameIndex < holdState.releaseFrameIndex) return
2027
+ for (
2028
+ let move = moves[holdState.nextMove];
2029
+ move && receipt.frameIndex >= holdEventFrameIndex(move.afterMs);
2030
+ move = moves[holdState.nextMove]
2031
+ ) {
2032
+ holdState.nextMove++
2033
+ holdState.x = move.x
2034
+ holdState.y = move.y
2035
+ await interact.touchMove(move.x, move.y)
2036
+ }
2037
+ if (receipt.frameIndex < holdEventFrameIndex(input.hold.durationMs)) return
2000
2038
  holdState.released = true
2001
- await interact.touchUp(input.hold.x, input.hold.y)
2039
+ await interact.touchUp(holdState.x, holdState.y)
2002
2040
  }
2003
2041
  try {
2004
2042
  const baselineBitmap = await captureBitmap()
@@ -2023,7 +2061,7 @@ export const device = {
2023
2061
  for (let frame = 0; frame < detectionFrameLimit; frame++) {
2024
2062
  if (state.cancelled) throw new Error('rnx motion capture was cancelled')
2025
2063
  const receipt = await controller.stepFrame()
2026
- await releaseHoldIfDue(receipt)
2064
+ await advanceHold(receipt)
2027
2065
  const candidateBitmap = await captureBitmap()
2028
2066
  const bounds = boundsFor(candidateBitmap)
2029
2067
  const measurement = measureChange({
@@ -2050,25 +2088,20 @@ export const device = {
2050
2088
  const snapshots: Snapshot[] = []
2051
2089
  for (const stage of input.stages) {
2052
2090
  if (state.cancelled) throw new Error('rnx motion capture was cancelled')
2053
- if (
2054
- input.hold &&
2055
- !holdState.released &&
2056
- holdState.releaseFrameIndex !== null
2091
+ // step through every hold move and the release that fall before
2092
+ // this stage one frame at a time, so the stage paints the pointer
2093
+ // where it belongs rather than a hold the jump skipped past.
2094
+ const stageFrameIndex =
2095
+ visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs)
2096
+ for (
2097
+ let eventFrameIndex = nextHoldEventFrameIndex();
2098
+ eventFrameIndex !== null && stageFrameIndex > eventFrameIndex;
2099
+ eventFrameIndex = nextHoldEventFrameIndex()
2057
2100
  ) {
2058
- // step to the release frame first when this stage lies past it,
2059
- // so the stage paints the released state rather than a hold
2060
- // that overran because the jump skipped its deadline.
2061
- const stageFrameIndex =
2062
- visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs)
2063
- while (
2064
- !holdState.released &&
2065
- stageFrameIndex > holdState.releaseFrameIndex
2066
- ) {
2067
- await releaseHoldIfDue(await controller.stepFrame())
2068
- }
2101
+ await advanceHold(await controller.stepFrame())
2069
2102
  }
2070
2103
  const receipt = await controller.stepToOffset(visibleStart, stage.offsetMs)
2071
- await releaseHoldIfDue(receipt)
2104
+ await advanceHold(receipt)
2072
2105
  snapshots.push({
2073
2106
  actualMs: receipt.virtualTimestampMs - visibleStart.virtualTimestampMs,
2074
2107
  bitmap: await captureBitmap(),
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var REFUSED_PERFORM_STEP_TYPES = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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;
@@ -2247,7 +2247,10 @@ async function findNodeByMatcher(matcher) {
2247
2247
  return page.evaluate(async (indexedMatcher) => {
2248
2248
  const filter = indexedMatcher.type === "id" ? { hasId: indexedMatcher.value } : indexedMatcher.type === "text" ? { hasText: indexedMatcher.value } : indexedMatcher.type === "label" ? { hasLabel: indexedMatcher.value } : indexedMatcher.type === "role" ? { hasRole: indexedMatcher.value } : { type: indexedMatcher.value };
2249
2249
  const results = await window.__sootsimTest.queryAll(filter);
2250
- return results[indexedMatcher.index ?? 0] ?? null;
2250
+ const indexed = indexedMatcher.type === "text" ? results.filter(
2251
+ (node) => node.type === "text" && node.text === indexedMatcher.value
2252
+ ) : results;
2253
+ return indexed[indexedMatcher.index ?? 0] ?? null;
2251
2254
  }, matcher);
2252
2255
  }
2253
2256
  if (matcher.type === "id") {
@@ -3267,18 +3270,36 @@ var device = {
3267
3270
  }
3268
3271
  const frameMs = 1e3 / 60;
3269
3272
  const controller = await lockstep.begin(60);
3273
+ const moves = input.hold?.moves ?? [];
3270
3274
  const holdState = {
3275
+ nextMove: 0,
3276
+ pressFrameIndex: null,
3271
3277
  released: false,
3272
- releaseFrameIndex: null
3278
+ x: input.hold?.x ?? 0,
3279
+ y: input.hold?.y ?? 0
3273
3280
  };
3274
- const releaseHoldIfDue = async (receipt) => {
3281
+ const holdEventFrameIndex = (afterMs) => (holdState.pressFrameIndex ?? 0) + Math.ceil(afterMs / frameMs);
3282
+ const nextHoldEventFrameIndex = () => {
3283
+ if (!input.hold || holdState.released || holdState.pressFrameIndex === null) {
3284
+ return null;
3285
+ }
3286
+ const move = moves[holdState.nextMove];
3287
+ return holdEventFrameIndex(move ? move.afterMs : input.hold.durationMs);
3288
+ };
3289
+ const advanceHold = async (receipt) => {
3275
3290
  if (!input.hold || !interact || holdState.released) return;
3276
- if (holdState.releaseFrameIndex === null) {
3277
- holdState.releaseFrameIndex = receipt.frameIndex - 1 + Math.ceil(input.hold.durationMs / frameMs);
3291
+ if (holdState.pressFrameIndex === null) {
3292
+ holdState.pressFrameIndex = receipt.frameIndex - 1;
3278
3293
  }
3279
- if (receipt.frameIndex < holdState.releaseFrameIndex) return;
3294
+ for (let move = moves[holdState.nextMove]; move && receipt.frameIndex >= holdEventFrameIndex(move.afterMs); move = moves[holdState.nextMove]) {
3295
+ holdState.nextMove++;
3296
+ holdState.x = move.x;
3297
+ holdState.y = move.y;
3298
+ await interact.touchMove(move.x, move.y);
3299
+ }
3300
+ if (receipt.frameIndex < holdEventFrameIndex(input.hold.durationMs)) return;
3280
3301
  holdState.released = true;
3281
- await interact.touchUp(input.hold.x, input.hold.y);
3302
+ await interact.touchUp(holdState.x, holdState.y);
3282
3303
  };
3283
3304
  try {
3284
3305
  const baselineBitmap = await captureBitmap();
@@ -3302,7 +3323,7 @@ var device = {
3302
3323
  for (let frame = 0; frame < detectionFrameLimit; frame++) {
3303
3324
  if (state.cancelled) throw new Error("rnx motion capture was cancelled");
3304
3325
  const receipt = await controller.stepFrame();
3305
- await releaseHoldIfDue(receipt);
3326
+ await advanceHold(receipt);
3306
3327
  const candidateBitmap = await captureBitmap();
3307
3328
  const bounds = boundsFor(candidateBitmap);
3308
3329
  const measurement = measureChange({
@@ -3328,14 +3349,12 @@ var device = {
3328
3349
  const snapshots = [];
3329
3350
  for (const stage of input.stages) {
3330
3351
  if (state.cancelled) throw new Error("rnx motion capture was cancelled");
3331
- if (input.hold && !holdState.released && holdState.releaseFrameIndex !== null) {
3332
- const stageFrameIndex = visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs);
3333
- while (!holdState.released && stageFrameIndex > holdState.releaseFrameIndex) {
3334
- await releaseHoldIfDue(await controller.stepFrame());
3335
- }
3352
+ const stageFrameIndex = visibleStart.frameIndex + Math.ceil(stage.offsetMs / frameMs);
3353
+ for (let eventFrameIndex = nextHoldEventFrameIndex(); eventFrameIndex !== null && stageFrameIndex > eventFrameIndex; eventFrameIndex = nextHoldEventFrameIndex()) {
3354
+ await advanceHold(await controller.stepFrame());
3336
3355
  }
3337
3356
  const receipt = await controller.stepToOffset(visibleStart, stage.offsetMs);
3338
- await releaseHoldIfDue(receipt);
3357
+ await advanceHold(receipt);
3339
3358
  snapshots.push({
3340
3359
  actualMs: receipt.virtualTimestampMs - visibleStart.virtualTimestampMs,
3341
3360
  bitmap: await captureBitmap(),
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.517 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.519 | (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.517",
3
+ "version": "0.1.519",
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",