rnxsim 0.1.542 → 0.1.544

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 (57) 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 +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -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 +93 -2
  16. package/dist-lib/capture-contract.mjs +92 -2
  17. package/dist-lib/cli-constants.cjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud.cjs +1 -1
  21. package/dist-lib/cloud.mjs +1 -1
  22. package/dist-lib/config.cjs +1 -1
  23. package/dist-lib/detox/index.cjs +1 -1
  24. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  25. package/dist-lib/home-paths.cjs +1 -1
  26. package/dist-lib/host/bridge-host.cjs +1 -1
  27. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  28. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  29. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  30. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  31. package/dist-lib/host/websocket-proxy.cjs +1 -1
  32. package/dist-lib/index.cjs +93 -2
  33. package/dist-lib/jump-to-source-babel.cjs +1 -1
  34. package/dist-lib/jump-to-source-native.cjs +1 -1
  35. package/dist-lib/menu.cjs +1 -1
  36. package/dist-lib/menu.mjs +1 -1
  37. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  38. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  39. package/dist-lib/metro-production-bundle.cjs +1 -1
  40. package/dist-lib/metro-production-bundle.mjs +1 -1
  41. package/dist-lib/metro.cjs +1 -1
  42. package/dist-lib/profiles.cjs +1 -1
  43. package/dist-lib/public-brand.cjs +1 -1
  44. package/dist-lib/react-native-host-modules.cjs +1 -1
  45. package/dist-lib/react-native-host-modules.mjs +1 -1
  46. package/dist-lib/render-mode.cjs +1 -1
  47. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  48. package/dist-lib/sdk.cjs +1 -1
  49. package/dist-lib/sdk.mjs +1 -1
  50. package/dist-lib/skills.cjs +1 -1
  51. package/dist-lib/swift-submit.cjs +1 -1
  52. package/dist-lib/swift-submit.mjs +1 -1
  53. package/dist-lib/swift.cjs +1 -1
  54. package/dist-lib/vite.cjs +1 -1
  55. package/package.json +1 -1
  56. package/src/capture-contract.ts +143 -2
  57. package/src/index.ts +3 -0
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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;
@@ -25,6 +25,7 @@ __export(capture_contract_exports, {
25
25
  RNX_SCREEN_CAPTURE_VERSION: () => RNX_SCREEN_CAPTURE_VERSION,
26
26
  isRnxCaptureRegionAtlas: () => isRnxCaptureRegionAtlas,
27
27
  isRnxScreenCapture: () => isRnxScreenCapture,
28
+ packRnxCaptureRegions: () => packRnxCaptureRegions,
28
29
  rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
29
30
  rnxRasterFrames: () => rnxRasterFrames,
30
31
  selectRnxRasterNodeIds: () => selectRnxRasterNodeIds
@@ -138,6 +139,95 @@ function rnxCaptureRasterRegions(capture) {
138
139
  return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
139
140
  });
140
141
  }
142
+ function packRnxCaptureRegions(regions, pixelRatio, surface) {
143
+ const physical = regions.map((region) => {
144
+ const left = Math.floor(region.frame.x * pixelRatio);
145
+ const top = Math.floor(region.frame.y * pixelRatio);
146
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
147
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
148
+ if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
149
+ throw new Error(`capture region ${region.key} is outside the app surface`);
150
+ }
151
+ return {
152
+ key: region.key,
153
+ nodeId: region.nodeId,
154
+ frame: {
155
+ x: left / pixelRatio,
156
+ y: top / pixelRatio,
157
+ width: (right - left) / pixelRatio,
158
+ height: (bottom - top) / pixelRatio
159
+ },
160
+ sourceX: left,
161
+ sourceY: top,
162
+ pixelWidth: right - left,
163
+ pixelHeight: bottom - top
164
+ };
165
+ });
166
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
167
+ const totalArea = physical.reduce(
168
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
169
+ 0
170
+ );
171
+ if (totalArea > 4194304) {
172
+ throw new Error("capture region pixels exceed the atlas budget");
173
+ }
174
+ const candidates = [
175
+ largestWidth,
176
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
177
+ Math.max(largestWidth, surface.pixelWidth),
178
+ 4096
179
+ ];
180
+ const ordered = [...physical].sort(
181
+ (left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
182
+ );
183
+ let best = null;
184
+ for (const candidate of [...new Set(candidates)]) {
185
+ if (candidate > 4096) continue;
186
+ let x = 0;
187
+ let y = 0;
188
+ let rowHeight = 0;
189
+ let usedWidth = 0;
190
+ const packed = [];
191
+ for (const region of ordered) {
192
+ if (x > 0 && x + region.pixelWidth > candidate) {
193
+ y += rowHeight;
194
+ x = 0;
195
+ rowHeight = 0;
196
+ }
197
+ packed.push({ ...region, atlasX: x, atlasY: y });
198
+ x += region.pixelWidth;
199
+ rowHeight = Math.max(rowHeight, region.pixelHeight);
200
+ usedWidth = Math.max(usedWidth, x);
201
+ }
202
+ const height2 = y + rowHeight;
203
+ if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
204
+ const result = { width: usedWidth, height: height2, regions: packed };
205
+ if (!best || result.width * result.height < best.width * best.height) best = result;
206
+ }
207
+ if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
208
+ const width = best.width / pixelRatio;
209
+ const height = best.height / pixelRatio;
210
+ return {
211
+ width,
212
+ height,
213
+ pixelWidth: best.width,
214
+ pixelHeight: best.height,
215
+ regions: best.regions,
216
+ atlasRegions: best.regions.map((region) => ({
217
+ key: region.key,
218
+ nodeId: region.nodeId,
219
+ frame: region.frame,
220
+ // a region flush with the far edge is anchored to the logical edge so
221
+ // its source never runs past the atlas by a rounding hair
222
+ source: {
223
+ x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
224
+ y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
225
+ width: region.frame.width,
226
+ height: region.frame.height
227
+ }
228
+ }))
229
+ };
230
+ }
141
231
  function captureRecord(value) {
142
232
  return value !== null && typeof value === "object" && !Array.isArray(value);
143
233
  }
@@ -193,7 +283,7 @@ function isRnxScreenCapture(value) {
193
283
  return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
194
284
  }
195
285
  function isRnxCaptureRegionAtlas(value) {
196
- if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
286
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
197
287
  return false;
198
288
  }
199
289
  const scale = value.pixelWidth / value.width;
@@ -214,6 +304,7 @@ function isRnxCaptureRegionAtlas(value) {
214
304
  RNX_SCREEN_CAPTURE_VERSION,
215
305
  isRnxCaptureRegionAtlas,
216
306
  isRnxScreenCapture,
307
+ packRnxCaptureRegions,
217
308
  rnxCaptureRasterRegions,
218
309
  rnxRasterFrames,
219
310
  selectRnxRasterNodeIds
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -109,6 +109,95 @@ function rnxCaptureRasterRegions(capture) {
109
109
  return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
110
110
  });
111
111
  }
112
+ function packRnxCaptureRegions(regions, pixelRatio, surface) {
113
+ const physical = regions.map((region) => {
114
+ const left = Math.floor(region.frame.x * pixelRatio);
115
+ const top = Math.floor(region.frame.y * pixelRatio);
116
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
117
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
118
+ if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
119
+ throw new Error(`capture region ${region.key} is outside the app surface`);
120
+ }
121
+ return {
122
+ key: region.key,
123
+ nodeId: region.nodeId,
124
+ frame: {
125
+ x: left / pixelRatio,
126
+ y: top / pixelRatio,
127
+ width: (right - left) / pixelRatio,
128
+ height: (bottom - top) / pixelRatio
129
+ },
130
+ sourceX: left,
131
+ sourceY: top,
132
+ pixelWidth: right - left,
133
+ pixelHeight: bottom - top
134
+ };
135
+ });
136
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
137
+ const totalArea = physical.reduce(
138
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
139
+ 0
140
+ );
141
+ if (totalArea > 4194304) {
142
+ throw new Error("capture region pixels exceed the atlas budget");
143
+ }
144
+ const candidates = [
145
+ largestWidth,
146
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
147
+ Math.max(largestWidth, surface.pixelWidth),
148
+ 4096
149
+ ];
150
+ const ordered = [...physical].sort(
151
+ (left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
152
+ );
153
+ let best = null;
154
+ for (const candidate of [...new Set(candidates)]) {
155
+ if (candidate > 4096) continue;
156
+ let x = 0;
157
+ let y = 0;
158
+ let rowHeight = 0;
159
+ let usedWidth = 0;
160
+ const packed = [];
161
+ for (const region of ordered) {
162
+ if (x > 0 && x + region.pixelWidth > candidate) {
163
+ y += rowHeight;
164
+ x = 0;
165
+ rowHeight = 0;
166
+ }
167
+ packed.push({ ...region, atlasX: x, atlasY: y });
168
+ x += region.pixelWidth;
169
+ rowHeight = Math.max(rowHeight, region.pixelHeight);
170
+ usedWidth = Math.max(usedWidth, x);
171
+ }
172
+ const height2 = y + rowHeight;
173
+ if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
174
+ const result = { width: usedWidth, height: height2, regions: packed };
175
+ if (!best || result.width * result.height < best.width * best.height) best = result;
176
+ }
177
+ if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
178
+ const width = best.width / pixelRatio;
179
+ const height = best.height / pixelRatio;
180
+ return {
181
+ width,
182
+ height,
183
+ pixelWidth: best.width,
184
+ pixelHeight: best.height,
185
+ regions: best.regions,
186
+ atlasRegions: best.regions.map((region) => ({
187
+ key: region.key,
188
+ nodeId: region.nodeId,
189
+ frame: region.frame,
190
+ // a region flush with the far edge is anchored to the logical edge so
191
+ // its source never runs past the atlas by a rounding hair
192
+ source: {
193
+ x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
194
+ y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
195
+ width: region.frame.width,
196
+ height: region.frame.height
197
+ }
198
+ }))
199
+ };
200
+ }
112
201
  function captureRecord(value) {
113
202
  return value !== null && typeof value === "object" && !Array.isArray(value);
114
203
  }
@@ -164,7 +253,7 @@ function isRnxScreenCapture(value) {
164
253
  return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
165
254
  }
166
255
  function isRnxCaptureRegionAtlas(value) {
167
- if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
256
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
168
257
  return false;
169
258
  }
170
259
  const scale = value.pixelWidth / value.width;
@@ -184,6 +273,7 @@ export {
184
273
  RNX_SCREEN_CAPTURE_VERSION,
185
274
  isRnxCaptureRegionAtlas,
186
275
  isRnxScreenCapture,
276
+ packRnxCaptureRegions,
187
277
  rnxCaptureRasterRegions,
188
278
  rnxRasterFrames,
189
279
  selectRnxRasterNodeIds
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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,6 +49,7 @@ __export(src_exports, {
49
49
  isRnxScreenCapture: () => isRnxScreenCapture,
50
50
  jumpToSourceBabelPlugin: () => sootsimJumpToSourceBabelPlugin,
51
51
  metroPlugin: () => metro_plugin_default,
52
+ packRnxCaptureRegions: () => packRnxCaptureRegions,
52
53
  rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
53
54
  rnxPlugin: () => rnxPlugin,
54
55
  rnxRasterFrames: () => rnxRasterFrames,
@@ -3204,6 +3205,95 @@ function rnxCaptureRasterRegions(capture) {
3204
3205
  return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
3205
3206
  });
3206
3207
  }
3208
+ function packRnxCaptureRegions(regions, pixelRatio, surface) {
3209
+ const physical = regions.map((region) => {
3210
+ const left = Math.floor(region.frame.x * pixelRatio);
3211
+ const top = Math.floor(region.frame.y * pixelRatio);
3212
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
3213
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
3214
+ if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
3215
+ throw new Error(`capture region ${region.key} is outside the app surface`);
3216
+ }
3217
+ return {
3218
+ key: region.key,
3219
+ nodeId: region.nodeId,
3220
+ frame: {
3221
+ x: left / pixelRatio,
3222
+ y: top / pixelRatio,
3223
+ width: (right - left) / pixelRatio,
3224
+ height: (bottom - top) / pixelRatio
3225
+ },
3226
+ sourceX: left,
3227
+ sourceY: top,
3228
+ pixelWidth: right - left,
3229
+ pixelHeight: bottom - top
3230
+ };
3231
+ });
3232
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
3233
+ const totalArea = physical.reduce(
3234
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
3235
+ 0
3236
+ );
3237
+ if (totalArea > 4194304) {
3238
+ throw new Error("capture region pixels exceed the atlas budget");
3239
+ }
3240
+ const candidates = [
3241
+ largestWidth,
3242
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
3243
+ Math.max(largestWidth, surface.pixelWidth),
3244
+ 4096
3245
+ ];
3246
+ const ordered = [...physical].sort(
3247
+ (left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
3248
+ );
3249
+ let best = null;
3250
+ for (const candidate of [...new Set(candidates)]) {
3251
+ if (candidate > 4096) continue;
3252
+ let x = 0;
3253
+ let y = 0;
3254
+ let rowHeight = 0;
3255
+ let usedWidth = 0;
3256
+ const packed = [];
3257
+ for (const region of ordered) {
3258
+ if (x > 0 && x + region.pixelWidth > candidate) {
3259
+ y += rowHeight;
3260
+ x = 0;
3261
+ rowHeight = 0;
3262
+ }
3263
+ packed.push({ ...region, atlasX: x, atlasY: y });
3264
+ x += region.pixelWidth;
3265
+ rowHeight = Math.max(rowHeight, region.pixelHeight);
3266
+ usedWidth = Math.max(usedWidth, x);
3267
+ }
3268
+ const height2 = y + rowHeight;
3269
+ if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
3270
+ const result = { width: usedWidth, height: height2, regions: packed };
3271
+ if (!best || result.width * result.height < best.width * best.height) best = result;
3272
+ }
3273
+ if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
3274
+ const width = best.width / pixelRatio;
3275
+ const height = best.height / pixelRatio;
3276
+ return {
3277
+ width,
3278
+ height,
3279
+ pixelWidth: best.width,
3280
+ pixelHeight: best.height,
3281
+ regions: best.regions,
3282
+ atlasRegions: best.regions.map((region) => ({
3283
+ key: region.key,
3284
+ nodeId: region.nodeId,
3285
+ frame: region.frame,
3286
+ // a region flush with the far edge is anchored to the logical edge so
3287
+ // its source never runs past the atlas by a rounding hair
3288
+ source: {
3289
+ x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
3290
+ y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
3291
+ width: region.frame.width,
3292
+ height: region.frame.height
3293
+ }
3294
+ }))
3295
+ };
3296
+ }
3207
3297
  function captureRecord(value) {
3208
3298
  return value !== null && typeof value === "object" && !Array.isArray(value);
3209
3299
  }
@@ -3259,7 +3349,7 @@ function isRnxScreenCapture(value) {
3259
3349
  return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
3260
3350
  }
3261
3351
  function isRnxCaptureRegionAtlas(value) {
3262
- if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
3352
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
3263
3353
  return false;
3264
3354
  }
3265
3355
  const scale = value.pixelWidth / value.width;
@@ -4363,6 +4453,7 @@ function sootsimJumpToSourceBabelPlugin(api, options = {}) {
4363
4453
  isRnxScreenCapture,
4364
4454
  jumpToSourceBabelPlugin,
4365
4455
  metroPlugin,
4456
+ packRnxCaptureRegions,
4366
4457
  rnxCaptureRasterRegions,
4367
4458
  rnxPlugin,
4368
4459
  rnxRasterFrames,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-submit.ts
4
4
  var SWIFT_COMPILE_PATH = "/api/swift-compile";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.542 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.544 | (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.542",
3
+ "version": "0.1.544",
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",
@@ -318,6 +318,146 @@ export function rnxCaptureRasterRegions(
318
318
  })
319
319
  }
320
320
 
321
+ /** a region request snapped to the surface pixel grid and placed in the atlas */
322
+ export interface RnxPackedCaptureRegion extends RnxCaptureRegionRequest {
323
+ /** top-left of the region on the app surface, in pixels */
324
+ sourceX: number
325
+ sourceY: number
326
+ pixelWidth: number
327
+ pixelHeight: number
328
+ /** top-left of the region inside the atlas, in pixels */
329
+ atlasX: number
330
+ atlasY: number
331
+ }
332
+
333
+ export interface RnxPackedCaptureAtlas {
334
+ /** logical atlas dimensions; pixel dimensions are these times the pixel ratio */
335
+ width: number
336
+ height: number
337
+ pixelWidth: number
338
+ pixelHeight: number
339
+ regions: RnxPackedCaptureRegion[]
340
+ /** the wire regions a producer publishes beside the encoded atlas */
341
+ atlasRegions: RnxCaptureAtlasRegion[]
342
+ }
343
+
344
+ // the bounded selective-layer atlas every producer ships: regions snapped to
345
+ // whole surface pixels, shelf-packed into the smallest of a few candidate
346
+ // widths, and mapped back to logical atlas coordinates. one packer for the
347
+ // headless renderer (which draws isolated subtrees into the slots) and the
348
+ // browser producer (which crops them out of a screen-sized screenshot), so a
349
+ // consumer never learns which one made the artifact from the layout.
350
+ export function packRnxCaptureRegions(
351
+ regions: readonly RnxCaptureRegionRequest[],
352
+ pixelRatio: number,
353
+ surface: { pixelWidth: number; pixelHeight: number },
354
+ ): RnxPackedCaptureAtlas {
355
+ const physical = regions.map((region) => {
356
+ const left = Math.floor(region.frame.x * pixelRatio)
357
+ const top = Math.floor(region.frame.y * pixelRatio)
358
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio)
359
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio)
360
+ if (
361
+ left < 0 ||
362
+ top < 0 ||
363
+ right > surface.pixelWidth ||
364
+ bottom > surface.pixelHeight ||
365
+ right <= left ||
366
+ bottom <= top
367
+ ) {
368
+ throw new Error(`capture region ${region.key} is outside the app surface`)
369
+ }
370
+ return {
371
+ key: region.key,
372
+ nodeId: region.nodeId,
373
+ frame: {
374
+ x: left / pixelRatio,
375
+ y: top / pixelRatio,
376
+ width: (right - left) / pixelRatio,
377
+ height: (bottom - top) / pixelRatio,
378
+ },
379
+ sourceX: left,
380
+ sourceY: top,
381
+ pixelWidth: right - left,
382
+ pixelHeight: bottom - top,
383
+ }
384
+ })
385
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth))
386
+ const totalArea = physical.reduce(
387
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
388
+ 0,
389
+ )
390
+ if (totalArea > 4_194_304) {
391
+ throw new Error('capture region pixels exceed the atlas budget')
392
+ }
393
+ const candidates = [
394
+ largestWidth,
395
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
396
+ Math.max(largestWidth, surface.pixelWidth),
397
+ 4_096,
398
+ ]
399
+ const ordered = [...physical].sort(
400
+ (left, right) =>
401
+ right.pixelHeight - left.pixelHeight ||
402
+ right.pixelWidth - left.pixelWidth ||
403
+ left.key.localeCompare(right.key),
404
+ )
405
+ let best: { width: number; height: number; regions: RnxPackedCaptureRegion[] } | null =
406
+ null
407
+ for (const candidate of [...new Set(candidates)]) {
408
+ if (candidate > 4_096) continue
409
+ let x = 0
410
+ let y = 0
411
+ let rowHeight = 0
412
+ let usedWidth = 0
413
+ const packed: RnxPackedCaptureRegion[] = []
414
+ for (const region of ordered) {
415
+ if (x > 0 && x + region.pixelWidth > candidate) {
416
+ y += rowHeight
417
+ x = 0
418
+ rowHeight = 0
419
+ }
420
+ packed.push({ ...region, atlasX: x, atlasY: y })
421
+ x += region.pixelWidth
422
+ rowHeight = Math.max(rowHeight, region.pixelHeight)
423
+ usedWidth = Math.max(usedWidth, x)
424
+ }
425
+ const height = y + rowHeight
426
+ if (height > 4_096 || usedWidth * height > 4_194_304) continue
427
+ const result = { width: usedWidth, height, regions: packed }
428
+ if (!best || result.width * result.height < best.width * best.height) best = result
429
+ }
430
+ if (!best) throw new Error('capture regions cannot fit in one bounded atlas')
431
+ const width = best.width / pixelRatio
432
+ const height = best.height / pixelRatio
433
+ return {
434
+ width,
435
+ height,
436
+ pixelWidth: best.width,
437
+ pixelHeight: best.height,
438
+ regions: best.regions,
439
+ atlasRegions: best.regions.map((region) => ({
440
+ key: region.key,
441
+ nodeId: region.nodeId,
442
+ frame: region.frame,
443
+ // a region flush with the far edge is anchored to the logical edge so
444
+ // its source never runs past the atlas by a rounding hair
445
+ source: {
446
+ x:
447
+ region.atlasX + region.pixelWidth === best.width
448
+ ? width - region.frame.width
449
+ : region.atlasX / pixelRatio,
450
+ y:
451
+ region.atlasY + region.pixelHeight === best.height
452
+ ? height - region.frame.height
453
+ : region.atlasY / pixelRatio,
454
+ width: region.frame.width,
455
+ height: region.frame.height,
456
+ },
457
+ })),
458
+ }
459
+ }
460
+
321
461
  export interface RnxCaptureAtlasRegion extends RnxCaptureRegionRequest {
322
462
  /** source rectangle inside the packed atlas, in logical atlas coordinates */
323
463
  source: RnxCaptureRect
@@ -325,7 +465,7 @@ export interface RnxCaptureAtlasRegion extends RnxCaptureRegionRequest {
325
465
 
326
466
  export interface RnxCaptureRegionAtlas {
327
467
  kind: 'png-atlas'
328
- producer: 'headless-cpu-app-surface'
468
+ producer: 'headless-cpu-app-surface' | 'browser-compositor-app-surface'
329
469
  dataUri: string
330
470
  /** logical atlas dimensions; the encoded PNG uses pixelWidth × pixelHeight */
331
471
  width: number
@@ -533,7 +673,8 @@ export function isRnxCaptureRegionAtlas(value: unknown): value is RnxCaptureRegi
533
673
  if (
534
674
  !captureRecord(value) ||
535
675
  value.kind !== 'png-atlas' ||
536
- value.producer !== 'headless-cpu-app-surface' ||
676
+ (value.producer !== 'headless-cpu-app-surface' &&
677
+ value.producer !== 'browser-compositor-app-surface') ||
537
678
  typeof value.dataUri !== 'string' ||
538
679
  !value.dataUri.startsWith('data:image/png;base64,') ||
539
680
  !captureNumber(value.width) ||
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export {
39
39
  isRnxCaptureRegionAtlas,
40
40
  isRnxScreenCapture,
41
41
  rnxCaptureRasterRegions,
42
+ packRnxCaptureRegions,
42
43
  rnxRasterFrames,
43
44
  RNX_SCREEN_CAPTURE_VERSION,
44
45
  selectRnxRasterNodeIds,
@@ -54,6 +55,8 @@ export {
54
55
  type RnxCaptureSource,
55
56
  type RnxCaptureStyleTokenBinding,
56
57
  type RnxCaptureTextLine,
58
+ type RnxPackedCaptureAtlas,
59
+ type RnxPackedCaptureRegion,
57
60
  type RnxCaptureTextSegment,
58
61
  type RnxCaptureTree,
59
62
  type RnxCaptureVisualEvidence,