rnxsim 0.1.382 → 0.1.383

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 (52) hide show
  1. package/dist-lib/agent-daemon-client.cjs +1 -1
  2. package/dist-lib/agent-events.cjs +1 -1
  3. package/dist-lib/agent-identity.cjs +1 -1
  4. package/dist-lib/agent-sessions.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +1 -1
  11. package/dist-lib/bridge-contract-input.cjs +6 -1
  12. package/dist-lib/bridge-contract-input.mjs +6 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/capture-contract.cjs +113 -3
  16. package/dist-lib/capture-contract.mjs +109 -2
  17. package/dist-lib/cli-constants.cjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +10 -1
  19. package/dist-lib/cloud-contract.mjs +7 -1
  20. package/dist-lib/config.cjs +1 -1
  21. package/dist-lib/detox/index.cjs +1 -1
  22. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  23. package/dist-lib/home-paths.cjs +1 -1
  24. package/dist-lib/host/bridge-host.cjs +1 -1
  25. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  26. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  27. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  28. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  29. package/dist-lib/host/websocket-proxy.cjs +1 -1
  30. package/dist-lib/index.cjs +114 -3
  31. package/dist-lib/jump-to-source-babel.cjs +1 -1
  32. package/dist-lib/menu.cjs +1 -1
  33. package/dist-lib/menu.mjs +1 -1
  34. package/dist-lib/metro-production-bundle.cjs +1 -1
  35. package/dist-lib/metro-production-bundle.mjs +1 -1
  36. package/dist-lib/metro.cjs +1 -1
  37. package/dist-lib/profiles.cjs +1 -1
  38. package/dist-lib/public-brand.cjs +1 -1
  39. package/dist-lib/react-native-host-modules.cjs +1 -1
  40. package/dist-lib/react-native-host-modules.mjs +1 -1
  41. package/dist-lib/render-mode.cjs +1 -1
  42. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  43. package/dist-lib/sdk.cjs +1 -1
  44. package/dist-lib/sdk.mjs +1 -1
  45. package/dist-lib/skills.cjs +3 -2
  46. package/dist-lib/vite.cjs +1 -1
  47. package/package.json +1 -1
  48. package/src/bridge-contract-input.ts +8 -0
  49. package/src/bridge-contract.ts +10 -1
  50. package/src/capture-contract.ts +153 -0
  51. package/src/cloud-contract.ts +3 -0
  52. package/src/index.ts +4 -0
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
@@ -182,10 +182,15 @@ function parsePerformStep(value, index) {
182
182
  return { type, ms: numberValue(step.ms, `${path}.ms`) };
183
183
  case "waitFor": {
184
184
  const timeoutMs = semanticWaitTimeout(step, path);
185
+ const condition = step.condition === void 0 ? void 0 : stringValue(step.condition, `${path}.condition`);
186
+ if (condition !== void 0 && condition !== "present" && condition !== "absent") {
187
+ return validationFailure(`${path}.condition`, "must be present or absent");
188
+ }
185
189
  const selector = step.testID === void 0 ? { id: stringValue(step.id, `${path}.id`) } : { testID: stringValue(step.testID, `${path}.testID`) };
186
190
  return {
187
191
  type,
188
192
  ...selector,
193
+ ...condition === void 0 ? {} : { condition },
189
194
  ...timeoutMs === void 0 ? {} : { timeoutMs }
190
195
  };
191
196
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract-input.ts
4
4
  var BridgeInputError = class extends Error {
@@ -150,10 +150,15 @@ function parsePerformStep(value, index) {
150
150
  return { type, ms: numberValue(step.ms, `${path}.ms`) };
151
151
  case "waitFor": {
152
152
  const timeoutMs = semanticWaitTimeout(step, path);
153
+ const condition = step.condition === void 0 ? void 0 : stringValue(step.condition, `${path}.condition`);
154
+ if (condition !== void 0 && condition !== "present" && condition !== "absent") {
155
+ return validationFailure(`${path}.condition`, "must be present or absent");
156
+ }
153
157
  const selector = step.testID === void 0 ? { id: stringValue(step.id, `${path}.id`) } : { testID: stringValue(step.testID, `${path}.testID`) };
154
158
  return {
155
159
  type,
156
160
  ...selector,
161
+ ...condition === void 0 ? {} : { condition },
157
162
  ...timeoutMs === void 0 ? {} : { timeoutMs }
158
163
  };
159
164
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
@@ -24,10 +24,117 @@ var capture_contract_exports = {};
24
24
  __export(capture_contract_exports, {
25
25
  RNX_SCREEN_CAPTURE_VERSION: () => RNX_SCREEN_CAPTURE_VERSION,
26
26
  isRnxCaptureRegionAtlas: () => isRnxCaptureRegionAtlas,
27
- isRnxScreenCapture: () => isRnxScreenCapture
27
+ isRnxScreenCapture: () => isRnxScreenCapture,
28
+ rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
29
+ rnxRasterFrames: () => rnxRasterFrames,
30
+ selectRnxRasterNodeIds: () => selectRnxRasterNodeIds
28
31
  });
29
32
  module.exports = __toCommonJS(capture_contract_exports);
30
33
  var RNX_SCREEN_CAPTURE_VERSION = 1;
34
+ function selectRnxRasterNodeIds(tree) {
35
+ const nodesById = new Map(tree.nodes.map((node) => [node.nodeId, node]));
36
+ const unsupported = /* @__PURE__ */ new Set();
37
+ for (const node of tree.nodes) {
38
+ const visibleFrame = node.visibleFrame ?? node.frame;
39
+ if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue;
40
+ if (node.type === "masked-view" || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0) {
41
+ unsupported.add(node.nodeId);
42
+ }
43
+ }
44
+ for (const nodeId of [...unsupported]) {
45
+ let parentNodeId = nodesById.get(nodeId)?.parentNodeId ?? null;
46
+ while (parentNodeId !== null) {
47
+ if (unsupported.has(parentNodeId)) {
48
+ unsupported.delete(nodeId);
49
+ break;
50
+ }
51
+ parentNodeId = nodesById.get(parentNodeId)?.parentNodeId ?? null;
52
+ }
53
+ }
54
+ const screenArea = tree.width * tree.height;
55
+ const maxLayerArea = screenArea * 0.25;
56
+ const maxAtlasArea = screenArea * 0.5;
57
+ const candidates = [...unsupported].map((nodeId) => {
58
+ const node = nodesById.get(nodeId);
59
+ const frame = node?.visibleFrame ?? node?.frame;
60
+ return frame ? { nodeId, area: frame.width * frame.height } : null;
61
+ }).filter(
62
+ (candidate) => candidate !== null && candidate.area <= maxLayerArea
63
+ ).sort((left, right) => left.area - right.area || left.nodeId - right.nodeId);
64
+ const selected = /* @__PURE__ */ new Set();
65
+ let atlasArea = 0;
66
+ for (const candidate of candidates) {
67
+ if (atlasArea + candidate.area > maxAtlasArea) continue;
68
+ selected.add(candidate.nodeId);
69
+ atlasArea += candidate.area;
70
+ }
71
+ return selected;
72
+ }
73
+ function rnxRasterFrames(tree, nodeIds) {
74
+ const frames = /* @__PURE__ */ new Map();
75
+ for (const node of tree.nodes) {
76
+ if (!nodeIds.has(node.nodeId)) continue;
77
+ const frame = node.frame ?? {
78
+ x: node.absolutePosition.x,
79
+ y: node.absolutePosition.y,
80
+ width: node.layout.width,
81
+ height: node.layout.height
82
+ };
83
+ const liquidGlass = node.style._liquidGlass;
84
+ const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
85
+ const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
86
+ const shadowOffset = node.style.shadowOffset;
87
+ const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
88
+ const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
89
+ const left = Math.max(
90
+ 0,
91
+ frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
92
+ );
93
+ const top = Math.max(
94
+ 0,
95
+ frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
96
+ );
97
+ const right = Math.min(
98
+ tree.width,
99
+ frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
100
+ );
101
+ const bottom = Math.min(
102
+ tree.height,
103
+ frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
104
+ );
105
+ if (right > left && bottom > top) {
106
+ frames.set(node.nodeId, {
107
+ x: left,
108
+ y: top,
109
+ width: right - left,
110
+ height: bottom - top
111
+ });
112
+ }
113
+ }
114
+ return frames;
115
+ }
116
+ function rnxCaptureRasterRegions(capture) {
117
+ const tree = {
118
+ width: capture.tree.viewport.width,
119
+ height: capture.tree.viewport.height,
120
+ nodes: capture.tree.nodes.map((node) => ({
121
+ nodeId: node.nodeId,
122
+ parentNodeId: node.parentNodeId,
123
+ type: node.type,
124
+ style: node.style.resolved,
125
+ layout: node.layout.local,
126
+ frame: node.layout.frame,
127
+ absolutePosition: node.layout.absolutePosition,
128
+ visibleFrame: node.layout.visibleFrame
129
+ }))
130
+ };
131
+ const nodeIds = selectRnxRasterNodeIds(tree);
132
+ const frames = rnxRasterFrames(tree, nodeIds);
133
+ return [...nodeIds].flatMap((nodeId) => {
134
+ const frame = frames.get(nodeId);
135
+ return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
136
+ });
137
+ }
31
138
  function captureRecord(value) {
32
139
  return value !== null && typeof value === "object" && !Array.isArray(value);
33
140
  }
@@ -103,5 +210,8 @@ function isRnxCaptureRegionAtlas(value) {
103
210
  0 && (module.exports = {
104
211
  RNX_SCREEN_CAPTURE_VERSION,
105
212
  isRnxCaptureRegionAtlas,
106
- isRnxScreenCapture
213
+ isRnxScreenCapture,
214
+ rnxCaptureRasterRegions,
215
+ rnxRasterFrames,
216
+ selectRnxRasterNodeIds
107
217
  });
@@ -1,7 +1,111 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
5
+ function selectRnxRasterNodeIds(tree) {
6
+ const nodesById = new Map(tree.nodes.map((node) => [node.nodeId, node]));
7
+ const unsupported = /* @__PURE__ */ new Set();
8
+ for (const node of tree.nodes) {
9
+ const visibleFrame = node.visibleFrame ?? node.frame;
10
+ if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue;
11
+ if (node.type === "masked-view" || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0) {
12
+ unsupported.add(node.nodeId);
13
+ }
14
+ }
15
+ for (const nodeId of [...unsupported]) {
16
+ let parentNodeId = nodesById.get(nodeId)?.parentNodeId ?? null;
17
+ while (parentNodeId !== null) {
18
+ if (unsupported.has(parentNodeId)) {
19
+ unsupported.delete(nodeId);
20
+ break;
21
+ }
22
+ parentNodeId = nodesById.get(parentNodeId)?.parentNodeId ?? null;
23
+ }
24
+ }
25
+ const screenArea = tree.width * tree.height;
26
+ const maxLayerArea = screenArea * 0.25;
27
+ const maxAtlasArea = screenArea * 0.5;
28
+ const candidates = [...unsupported].map((nodeId) => {
29
+ const node = nodesById.get(nodeId);
30
+ const frame = node?.visibleFrame ?? node?.frame;
31
+ return frame ? { nodeId, area: frame.width * frame.height } : null;
32
+ }).filter(
33
+ (candidate) => candidate !== null && candidate.area <= maxLayerArea
34
+ ).sort((left, right) => left.area - right.area || left.nodeId - right.nodeId);
35
+ const selected = /* @__PURE__ */ new Set();
36
+ let atlasArea = 0;
37
+ for (const candidate of candidates) {
38
+ if (atlasArea + candidate.area > maxAtlasArea) continue;
39
+ selected.add(candidate.nodeId);
40
+ atlasArea += candidate.area;
41
+ }
42
+ return selected;
43
+ }
44
+ function rnxRasterFrames(tree, nodeIds) {
45
+ const frames = /* @__PURE__ */ new Map();
46
+ for (const node of tree.nodes) {
47
+ if (!nodeIds.has(node.nodeId)) continue;
48
+ const frame = node.frame ?? {
49
+ x: node.absolutePosition.x,
50
+ y: node.absolutePosition.y,
51
+ width: node.layout.width,
52
+ height: node.layout.height
53
+ };
54
+ const liquidGlass = node.style._liquidGlass;
55
+ const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
56
+ const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
57
+ const shadowOffset = node.style.shadowOffset;
58
+ const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
59
+ const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
60
+ const left = Math.max(
61
+ 0,
62
+ frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
63
+ );
64
+ const top = Math.max(
65
+ 0,
66
+ frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
67
+ );
68
+ const right = Math.min(
69
+ tree.width,
70
+ frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
71
+ );
72
+ const bottom = Math.min(
73
+ tree.height,
74
+ frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
75
+ );
76
+ if (right > left && bottom > top) {
77
+ frames.set(node.nodeId, {
78
+ x: left,
79
+ y: top,
80
+ width: right - left,
81
+ height: bottom - top
82
+ });
83
+ }
84
+ }
85
+ return frames;
86
+ }
87
+ function rnxCaptureRasterRegions(capture) {
88
+ const tree = {
89
+ width: capture.tree.viewport.width,
90
+ height: capture.tree.viewport.height,
91
+ nodes: capture.tree.nodes.map((node) => ({
92
+ nodeId: node.nodeId,
93
+ parentNodeId: node.parentNodeId,
94
+ type: node.type,
95
+ style: node.style.resolved,
96
+ layout: node.layout.local,
97
+ frame: node.layout.frame,
98
+ absolutePosition: node.layout.absolutePosition,
99
+ visibleFrame: node.layout.visibleFrame
100
+ }))
101
+ };
102
+ const nodeIds = selectRnxRasterNodeIds(tree);
103
+ const frames = rnxRasterFrames(tree, nodeIds);
104
+ return [...nodeIds].flatMap((nodeId) => {
105
+ const frame = frames.get(nodeId);
106
+ return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
107
+ });
108
+ }
5
109
  function captureRecord(value) {
6
110
  return value !== null && typeof value === "object" && !Array.isArray(value);
7
111
  }
@@ -76,5 +180,8 @@ function isRnxCaptureRegionAtlas(value) {
76
180
  export {
77
181
  RNX_SCREEN_CAPTURE_VERSION,
78
182
  isRnxCaptureRegionAtlas,
79
- isRnxScreenCapture
183
+ isRnxScreenCapture,
184
+ rnxCaptureRasterRegions,
185
+ rnxRasterFrames,
186
+ selectRnxRasterNodeIds
80
187
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
@@ -22,11 +22,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  // src/cloud-contract.ts
23
23
  var cloud_contract_exports = {};
24
24
  __export(cloud_contract_exports, {
25
+ RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES: () => RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
26
+ RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES: () => RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
27
+ RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT: () => RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT,
25
28
  RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES
26
29
  });
27
30
  module.exports = __toCommonJS(cloud_contract_exports);
28
31
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
32
+ var RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT = 16;
33
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
34
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
29
35
  // Annotate the CommonJS export names for ESM import in node:
30
36
  0 && (module.exports = {
37
+ RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
38
+ RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
39
+ RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT,
31
40
  RNX_CLOUD_MAX_ARTIFACT_BYTES
32
41
  });
@@ -1,7 +1,13 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
5
+ var RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT = 16;
6
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
7
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
5
8
  export {
9
+ RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
10
+ RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
11
+ RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT,
6
12
  RNX_CLOUD_MAX_ARTIFACT_BYTES
7
13
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
@@ -49,7 +49,10 @@ __export(src_exports, {
49
49
  isRnxScreenCapture: () => isRnxScreenCapture,
50
50
  jumpToSourceBabelPlugin: () => sootsimJumpToSourceBabelPlugin,
51
51
  metroPlugin: () => metro_plugin_default,
52
- rnxPlugin: () => rnxPlugin
52
+ rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
53
+ rnxPlugin: () => rnxPlugin,
54
+ rnxRasterFrames: () => rnxRasterFrames,
55
+ selectRnxRasterNodeIds: () => selectRnxRasterNodeIds
53
56
  });
54
57
  module.exports = __toCommonJS(src_exports);
55
58
 
@@ -502,6 +505,7 @@ function isDevBridgeLockfileFresh(lock, now = Date.now()) {
502
505
 
503
506
  // src/cloud-contract.ts
504
507
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
508
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
505
509
 
506
510
  // src/public-brand.ts
507
511
  var name = "rnx";
@@ -2646,6 +2650,110 @@ async function connect(options = {}) {
2646
2650
 
2647
2651
  // src/capture-contract.ts
2648
2652
  var RNX_SCREEN_CAPTURE_VERSION = 1;
2653
+ function selectRnxRasterNodeIds(tree) {
2654
+ const nodesById = new Map(tree.nodes.map((node) => [node.nodeId, node]));
2655
+ const unsupported = /* @__PURE__ */ new Set();
2656
+ for (const node of tree.nodes) {
2657
+ const visibleFrame = node.visibleFrame ?? node.frame;
2658
+ if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue;
2659
+ if (node.type === "masked-view" || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0) {
2660
+ unsupported.add(node.nodeId);
2661
+ }
2662
+ }
2663
+ for (const nodeId of [...unsupported]) {
2664
+ let parentNodeId = nodesById.get(nodeId)?.parentNodeId ?? null;
2665
+ while (parentNodeId !== null) {
2666
+ if (unsupported.has(parentNodeId)) {
2667
+ unsupported.delete(nodeId);
2668
+ break;
2669
+ }
2670
+ parentNodeId = nodesById.get(parentNodeId)?.parentNodeId ?? null;
2671
+ }
2672
+ }
2673
+ const screenArea = tree.width * tree.height;
2674
+ const maxLayerArea = screenArea * 0.25;
2675
+ const maxAtlasArea = screenArea * 0.5;
2676
+ const candidates = [...unsupported].map((nodeId) => {
2677
+ const node = nodesById.get(nodeId);
2678
+ const frame = node?.visibleFrame ?? node?.frame;
2679
+ return frame ? { nodeId, area: frame.width * frame.height } : null;
2680
+ }).filter(
2681
+ (candidate) => candidate !== null && candidate.area <= maxLayerArea
2682
+ ).sort((left, right) => left.area - right.area || left.nodeId - right.nodeId);
2683
+ const selected = /* @__PURE__ */ new Set();
2684
+ let atlasArea = 0;
2685
+ for (const candidate of candidates) {
2686
+ if (atlasArea + candidate.area > maxAtlasArea) continue;
2687
+ selected.add(candidate.nodeId);
2688
+ atlasArea += candidate.area;
2689
+ }
2690
+ return selected;
2691
+ }
2692
+ function rnxRasterFrames(tree, nodeIds) {
2693
+ const frames = /* @__PURE__ */ new Map();
2694
+ for (const node of tree.nodes) {
2695
+ if (!nodeIds.has(node.nodeId)) continue;
2696
+ const frame = node.frame ?? {
2697
+ x: node.absolutePosition.x,
2698
+ y: node.absolutePosition.y,
2699
+ width: node.layout.width,
2700
+ height: node.layout.height
2701
+ };
2702
+ const liquidGlass = node.style._liquidGlass;
2703
+ const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
2704
+ const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
2705
+ const shadowOffset = node.style.shadowOffset;
2706
+ const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
2707
+ const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
2708
+ const left = Math.max(
2709
+ 0,
2710
+ frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
2711
+ );
2712
+ const top = Math.max(
2713
+ 0,
2714
+ frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
2715
+ );
2716
+ const right = Math.min(
2717
+ tree.width,
2718
+ frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
2719
+ );
2720
+ const bottom = Math.min(
2721
+ tree.height,
2722
+ frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
2723
+ );
2724
+ if (right > left && bottom > top) {
2725
+ frames.set(node.nodeId, {
2726
+ x: left,
2727
+ y: top,
2728
+ width: right - left,
2729
+ height: bottom - top
2730
+ });
2731
+ }
2732
+ }
2733
+ return frames;
2734
+ }
2735
+ function rnxCaptureRasterRegions(capture) {
2736
+ const tree = {
2737
+ width: capture.tree.viewport.width,
2738
+ height: capture.tree.viewport.height,
2739
+ nodes: capture.tree.nodes.map((node) => ({
2740
+ nodeId: node.nodeId,
2741
+ parentNodeId: node.parentNodeId,
2742
+ type: node.type,
2743
+ style: node.style.resolved,
2744
+ layout: node.layout.local,
2745
+ frame: node.layout.frame,
2746
+ absolutePosition: node.layout.absolutePosition,
2747
+ visibleFrame: node.layout.visibleFrame
2748
+ }))
2749
+ };
2750
+ const nodeIds = selectRnxRasterNodeIds(tree);
2751
+ const frames = rnxRasterFrames(tree, nodeIds);
2752
+ return [...nodeIds].flatMap((nodeId) => {
2753
+ const frame = frames.get(nodeId);
2754
+ return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
2755
+ });
2756
+ }
2649
2757
  function captureRecord(value) {
2650
2758
  return value !== null && typeof value === "object" && !Array.isArray(value);
2651
2759
  }
@@ -3708,5 +3816,8 @@ function sootsimJumpToSourceBabelPlugin(api, options = {}) {
3708
3816
  isRnxScreenCapture,
3709
3817
  jumpToSourceBabelPlugin,
3710
3818
  metroPlugin,
3711
- rnxPlugin
3819
+ rnxCaptureRasterRegions,
3820
+ rnxPlugin,
3821
+ rnxRasterFrames,
3822
+ selectRnxRasterNodeIds
3712
3823
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION = "rnxsim";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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;
@@ -21428,11 +21428,12 @@ var init_cli_constants = __esm({
21428
21428
  });
21429
21429
 
21430
21430
  // src/cloud-contract.ts
21431
- var RNX_CLOUD_MAX_ARTIFACT_BYTES;
21431
+ var RNX_CLOUD_MAX_ARTIFACT_BYTES, RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES;
21432
21432
  var init_cloud_contract = __esm({
21433
21433
  "src/cloud-contract.ts"() {
21434
21434
  "use strict";
21435
21435
  RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
21436
+ RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
21436
21437
  }
21437
21438
  });
21438
21439
 
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.383 | (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.382",
3
+ "version": "0.1.383",
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",
@@ -189,6 +189,13 @@ export function parsePerformStep(value: unknown, index: number): SimPerformStep
189
189
  return { type, ms: numberValue(step.ms, `${path}.ms`) }
190
190
  case 'waitFor': {
191
191
  const timeoutMs = semanticWaitTimeout(step, path)
192
+ const condition =
193
+ step.condition === undefined
194
+ ? undefined
195
+ : stringValue(step.condition, `${path}.condition`)
196
+ if (condition !== undefined && condition !== 'present' && condition !== 'absent') {
197
+ return validationFailure(`${path}.condition`, 'must be present or absent')
198
+ }
192
199
  const selector =
193
200
  step.testID === undefined
194
201
  ? { id: stringValue(step.id, `${path}.id`) }
@@ -196,6 +203,7 @@ export function parsePerformStep(value: unknown, index: number): SimPerformStep
196
203
  return {
197
204
  type,
198
205
  ...selector,
206
+ ...(condition === undefined ? {} : { condition }),
199
207
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
200
208
  }
201
209
  }
@@ -19,6 +19,7 @@ export type BridgeCommandType =
19
19
  | 'screenshot'
20
20
  | 'capture'
21
21
  | 'captureRegions'
22
+ | 'settle'
22
23
  | 'setAppearance'
23
24
  | 'openUrl'
24
25
  | 'tap'
@@ -49,6 +50,7 @@ export interface WsCommand {
49
50
  x?: number
50
51
  y?: number
51
52
  durationMs?: number
53
+ maxFrames?: number
52
54
  target?: SootSimAgentActionDetail['target']
53
55
  action?: string
54
56
  text?: string
@@ -56,6 +58,7 @@ export interface WsCommand {
56
58
  url?: string
57
59
  includeVisual?: boolean
58
60
  includeFonts?: boolean
61
+ includeRasterAtlas?: boolean
59
62
  regions?: import('./capture-contract').RnxCaptureRegionRequest[]
60
63
  depth?: number
61
64
  // screenshot — which canvas layers to composite. omit for full (today's
@@ -140,7 +143,13 @@ export type PerformStep =
140
143
  | { type: 'key'; key: string }
141
144
  | { type: 'dismissKeyboard' }
142
145
  | { type: 'wait'; ms: number }
143
- | { type: 'waitFor'; testID?: string; id?: string; timeoutMs?: number }
146
+ | {
147
+ type: 'waitFor'
148
+ testID?: string
149
+ id?: string
150
+ condition?: 'present' | 'absent'
151
+ timeoutMs?: number
152
+ }
144
153
 
145
154
  export interface PerformOptions {
146
155
  // stop the batch at the first failing step. default true — a gesture whose
@@ -155,6 +155,159 @@ export interface RnxCaptureRegionRequest {
155
155
  frame: RnxCaptureRect
156
156
  }
157
157
 
158
+ export interface RnxRasterRegionTree {
159
+ width: number
160
+ height: number
161
+ nodes: readonly {
162
+ nodeId: number
163
+ parentNodeId: number | null
164
+ type: string
165
+ style: Record<string, unknown>
166
+ layout: RnxCaptureRect
167
+ frame: RnxCaptureRect | null
168
+ absolutePosition: { x: number; y: number }
169
+ visibleFrame?: RnxCaptureRect | null
170
+ }[]
171
+ }
172
+
173
+ export function selectRnxRasterNodeIds(tree: RnxRasterRegionTree): Set<number> {
174
+ const nodesById = new Map(tree.nodes.map((node) => [node.nodeId, node]))
175
+ const unsupported = new Set<number>()
176
+ for (const node of tree.nodes) {
177
+ const visibleFrame = node.visibleFrame ?? node.frame
178
+ if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue
179
+ if (
180
+ node.type === 'masked-view' ||
181
+ node.style._liquidGlass !== undefined ||
182
+ node.style._liquidGlassEdge !== undefined
183
+ ) {
184
+ unsupported.add(node.nodeId)
185
+ }
186
+ }
187
+
188
+ for (const nodeId of [...unsupported]) {
189
+ let parentNodeId = nodesById.get(nodeId)?.parentNodeId ?? null
190
+ while (parentNodeId !== null) {
191
+ if (unsupported.has(parentNodeId)) {
192
+ unsupported.delete(nodeId)
193
+ break
194
+ }
195
+ parentNodeId = nodesById.get(parentNodeId)?.parentNodeId ?? null
196
+ }
197
+ }
198
+
199
+ const screenArea = tree.width * tree.height
200
+ const maxLayerArea = screenArea * 0.25
201
+ const maxAtlasArea = screenArea * 0.5
202
+ const candidates = [...unsupported]
203
+ .map((nodeId) => {
204
+ const node = nodesById.get(nodeId)
205
+ const frame = node?.visibleFrame ?? node?.frame
206
+ return frame ? { nodeId, area: frame.width * frame.height } : null
207
+ })
208
+ .filter(
209
+ (candidate): candidate is { nodeId: number; area: number } =>
210
+ candidate !== null && candidate.area <= maxLayerArea,
211
+ )
212
+ .sort((left, right) => left.area - right.area || left.nodeId - right.nodeId)
213
+ const selected = new Set<number>()
214
+ let atlasArea = 0
215
+ for (const candidate of candidates) {
216
+ if (atlasArea + candidate.area > maxAtlasArea) continue
217
+ selected.add(candidate.nodeId)
218
+ atlasArea += candidate.area
219
+ }
220
+ return selected
221
+ }
222
+
223
+ export function rnxRasterFrames(
224
+ tree: RnxRasterRegionTree,
225
+ nodeIds: ReadonlySet<number>,
226
+ ): Map<number, RnxCaptureRect> {
227
+ const frames = new Map<number, RnxCaptureRect>()
228
+ for (const node of tree.nodes) {
229
+ if (!nodeIds.has(node.nodeId)) continue
230
+ const frame = node.frame ?? {
231
+ x: node.absolutePosition.x,
232
+ y: node.absolutePosition.y,
233
+ width: node.layout.width,
234
+ height: node.layout.height,
235
+ }
236
+ const liquidGlass = node.style._liquidGlass
237
+ const capturePadding =
238
+ liquidGlass &&
239
+ typeof liquidGlass === 'object' &&
240
+ typeof Reflect.get(liquidGlass, 'capturePadding') === 'number'
241
+ ? Reflect.get(liquidGlass, 'capturePadding')
242
+ : 0
243
+ const shadowRadius =
244
+ typeof node.style.shadowRadius === 'number' ? node.style.shadowRadius : 0
245
+ const shadowOffset = node.style.shadowOffset
246
+ const shadowOffsetX =
247
+ shadowOffset &&
248
+ typeof shadowOffset === 'object' &&
249
+ typeof Reflect.get(shadowOffset, 'width') === 'number'
250
+ ? Reflect.get(shadowOffset, 'width')
251
+ : 0
252
+ const shadowOffsetY =
253
+ shadowOffset &&
254
+ typeof shadowOffset === 'object' &&
255
+ typeof Reflect.get(shadowOffset, 'height') === 'number'
256
+ ? Reflect.get(shadowOffset, 'height')
257
+ : 0
258
+ const left = Math.max(
259
+ 0,
260
+ frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX),
261
+ )
262
+ const top = Math.max(
263
+ 0,
264
+ frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY),
265
+ )
266
+ const right = Math.min(
267
+ tree.width,
268
+ frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX),
269
+ )
270
+ const bottom = Math.min(
271
+ tree.height,
272
+ frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY),
273
+ )
274
+ if (right > left && bottom > top) {
275
+ frames.set(node.nodeId, {
276
+ x: left,
277
+ y: top,
278
+ width: right - left,
279
+ height: bottom - top,
280
+ })
281
+ }
282
+ }
283
+ return frames
284
+ }
285
+
286
+ export function rnxCaptureRasterRegions(
287
+ capture: RnxScreenCapture,
288
+ ): RnxCaptureRegionRequest[] {
289
+ const tree: RnxRasterRegionTree = {
290
+ width: capture.tree.viewport.width,
291
+ height: capture.tree.viewport.height,
292
+ nodes: capture.tree.nodes.map((node) => ({
293
+ nodeId: node.nodeId,
294
+ parentNodeId: node.parentNodeId,
295
+ type: node.type,
296
+ style: node.style.resolved,
297
+ layout: node.layout.local,
298
+ frame: node.layout.frame,
299
+ absolutePosition: node.layout.absolutePosition,
300
+ visibleFrame: node.layout.visibleFrame,
301
+ })),
302
+ }
303
+ const nodeIds = selectRnxRasterNodeIds(tree)
304
+ const frames = rnxRasterFrames(tree, nodeIds)
305
+ return [...nodeIds].flatMap((nodeId) => {
306
+ const frame = frames.get(nodeId)
307
+ return frame ? [{ key: String(nodeId), nodeId, frame }] : []
308
+ })
309
+ }
310
+
158
311
  export interface RnxCaptureAtlasRegion extends RnxCaptureRegionRequest {
159
312
  /** source rectangle inside the packed atlas, in logical atlas coordinates */
160
313
  source: RnxCaptureRect
@@ -1,4 +1,7 @@
1
1
  export const RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024
2
+ export const RNX_CLOUD_DESIGN_PARALLEL_JOB_LIMIT = 16
3
+ export const RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256
4
+ export const RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024
2
5
 
3
6
  export interface RnxCloudClaim {
4
7
  id: string
package/src/index.ts CHANGED
@@ -38,7 +38,10 @@ export type {
38
38
  export {
39
39
  isRnxCaptureRegionAtlas,
40
40
  isRnxScreenCapture,
41
+ rnxCaptureRasterRegions,
42
+ rnxRasterFrames,
41
43
  RNX_SCREEN_CAPTURE_VERSION,
44
+ selectRnxRasterNodeIds,
42
45
  type RnxCaptureAccessibility,
43
46
  type RnxCaptureAccessibilityState,
44
47
  type RnxCaptureAccessibilityValue,
@@ -54,6 +57,7 @@ export {
54
57
  type RnxCaptureTextSegment,
55
58
  type RnxCaptureTree,
56
59
  type RnxCaptureVisualEvidence,
60
+ type RnxRasterRegionTree,
57
61
  type RnxScreenCapture,
58
62
  } from './capture-contract'
59
63