peachsim 0.1.628 → 0.1.629

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 (66) hide show
  1. package/cli/commands/inspect/core.ts +5 -0
  2. package/cli/commands/inspect.ts +21 -12
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/agent-identity.cjs +1 -1
  6. package/dist-lib/agent-sessions.cjs +1 -1
  7. package/dist-lib/attached-projects.cjs +1 -1
  8. package/dist-lib/auth/shared-session.cjs +1 -1
  9. package/dist-lib/backend-origin.cjs +1 -1
  10. package/dist-lib/beta.cjs +1 -1
  11. package/dist-lib/beta.mjs +1 -1
  12. package/dist-lib/bridge-constants.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.mjs +1 -1
  15. package/dist-lib/bridge-contract.cjs +1 -1
  16. package/dist-lib/bridge-contract.mjs +1 -1
  17. package/dist-lib/capture-contract.cjs +1 -1
  18. package/dist-lib/capture-contract.mjs +1 -1
  19. package/dist-lib/cli-constants.cjs +1 -1
  20. package/dist-lib/cloud-contract.cjs +1 -1
  21. package/dist-lib/cloud-contract.mjs +1 -1
  22. package/dist-lib/cloud-test-args.cjs +1 -1
  23. package/dist-lib/cloud-test-args.mjs +1 -1
  24. package/dist-lib/cloud.cjs +1 -1
  25. package/dist-lib/cloud.mjs +1 -1
  26. package/dist-lib/config.cjs +1 -1
  27. package/dist-lib/detox/index.cjs +1 -1
  28. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +16 -61
  31. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +1 -1
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/menu.cjs +1 -1
  40. package/dist-lib/menu.mjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  43. package/dist-lib/metro-production-bundle.cjs +1 -1
  44. package/dist-lib/metro-production-bundle.mjs +1 -1
  45. package/dist-lib/metro.cjs +1 -1
  46. package/dist-lib/profiles.cjs +1 -1
  47. package/dist-lib/public-brand.cjs +1 -1
  48. package/dist-lib/react-native-host-modules.cjs +1 -1
  49. package/dist-lib/react-native-host-modules.mjs +1 -1
  50. package/dist-lib/render-mode.cjs +1 -1
  51. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  52. package/dist-lib/sdk.cjs +1 -1
  53. package/dist-lib/sdk.mjs +1 -1
  54. package/dist-lib/skills.cjs +20 -62
  55. package/dist-lib/swift-compile.cjs +1 -1
  56. package/dist-lib/swift-compile.mjs +1 -1
  57. package/dist-lib/swift-package.cjs +1 -1
  58. package/dist-lib/swift-package.mjs +1 -1
  59. package/dist-lib/swift-submit.cjs +1 -1
  60. package/dist-lib/swift-submit.mjs +1 -1
  61. package/dist-lib/swift.cjs +49 -69
  62. package/dist-lib/vite-kotlin.cjs +1 -1
  63. package/dist-lib/vite-swift.cjs +1 -1
  64. package/dist-lib/vite.cjs +1 -1
  65. package/package.json +1 -1
  66. package/src/screenshots/frame-compose.ts +4 -1
@@ -544,6 +544,11 @@ export interface LayoutElement {
544
544
  lastLineWords?: number
545
545
  // last line width relative to the widest line (0-1).
546
546
  lastLineWidthRatio?: number
547
+ // first display-size word (24px and up, space-delimited scripts) the browser
548
+ // split across two lines mid-letter. words with a legal break point
549
+ // (hyphen, dash, slash, soft hyphen, zero-width space) and domains or emails
550
+ // are never reported.
551
+ brokenWord?: string
547
552
  ellipsisActive?: boolean
548
553
  }
549
554
 
@@ -192,6 +192,24 @@ async function probeSimResponsive(bridge: WsBridge): Promise<boolean> {
192
192
  }
193
193
  }
194
194
 
195
+ // a bare `do tap <x>` resolves a testID; users coming from maestro's
196
+ // `tapOn: <text>` pass visible text there, so point them at `--text`.
197
+ async function reportMissingTarget(
198
+ bridge: WsBridge,
199
+ verb: 'tap' | 'double-tap' | 'long-press',
200
+ target: { mode: 'testid' | 'text'; value: string },
201
+ ): Promise<void> {
202
+ console.error(` not found: ${target.value}`)
203
+ if (target.mode !== 'testid') return
204
+ const byText = await inspectFind(bridge, { text: target.value }).catch(() => null)
205
+ if (byText?.result) {
206
+ console.error(` that is visible text: peach do ${verb} --text "${target.value}"`)
207
+ return
208
+ }
209
+ await printSimilarTestIds(bridge, target.value)
210
+ maybeHint('wait-selector-for-missing-testid', target.value)
211
+ }
212
+
195
213
  // surface the 5 closest candidates so callers can fix the typo without
196
214
  // dumping the full tree. uses a cheap prefix + Levenshtein score so a
197
215
  // trailing digit or near-miss casing still bubbles to the top.
@@ -1999,10 +2017,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1999
2017
  })
2000
2018
  const payload = outcome.payload
2001
2019
  if (!payload || typeof payload.cx !== 'number') {
2002
- console.error(` not found: ${target.value}`)
2003
- if (target.mode === 'testid') {
2004
- maybeHint('wait-selector-for-missing-testid', target.value)
2005
- }
2020
+ await reportMissingTarget(bridge, 'tap', target)
2006
2021
  rnxExit(1)
2007
2022
  }
2008
2023
  if (!isTapSuccess(outcome.result)) {
@@ -2773,10 +2788,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2773
2788
  if (target) {
2774
2789
  const resolved = await resolveTargetCoords(bridge, target)
2775
2790
  if (!resolved) {
2776
- console.error(` not found: ${target.value}`)
2777
- if (target.mode === 'testid') {
2778
- maybeHint('wait-selector-for-missing-testid', target.value)
2779
- }
2791
+ await reportMissingTarget(bridge, 'double-tap', target)
2780
2792
  rnxExit(1)
2781
2793
  }
2782
2794
  x = resolved.x
@@ -2816,10 +2828,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2816
2828
  if (target) {
2817
2829
  const resolved = await resolveTargetCoords(bridge, target)
2818
2830
  if (!resolved) {
2819
- console.error(` not found: ${target.value}`)
2820
- if (target.mode === 'testid') {
2821
- maybeHint('wait-selector-for-missing-testid', target.value)
2822
- }
2831
+ await reportMissingTarget(bridge, 'long-press', target)
2823
2832
  rnxExit(1)
2824
2833
  }
2825
2834
  x = resolved.x
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-test-args.ts
4
4
  var CLOUD_TEST_ARGS_MAX_COUNT = 32;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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;
@@ -939,7 +939,7 @@ function rotateDevice(device, side) {
939
939
  const barrelProtrusion = device.housing?.hingeBarrel?.protrusion ?? 0;
940
940
  if (side === "left") insets.top += barrelProtrusion;
941
941
  else insets.bottom += barrelProtrusion;
942
- const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 20, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
942
+ const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 34, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
943
943
  top: 0,
944
944
  bottom: 20,
945
945
  left: device.safeAreaInsets.top,
@@ -974,71 +974,24 @@ function rotateDevice(device, side) {
974
974
  // the bars stay on the interface's top and bottom; a cutout's inset moves
975
975
  // to whichever side the cutout turned to.
976
976
  safeAreaInsets: side === "left" ? safeArea : { ...safeArea, left: safeArea.right, right: safeArea.left },
977
- statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" && device.model !== "iphone-duo" ? 0 : device.statusBarHeight,
978
- homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? 20 : device.homeIndicatorHeight
977
+ statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" ? 0 : device.statusBarHeight,
978
+ // the indicator's band is the landscape bottom inset
979
+ homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? safeArea.bottom : device.homeIndicatorHeight
979
980
  };
980
981
  }
981
- function getDevice(model, posture, orientation, landscapeSide = "left") {
982
+ function defaultLandscapeSide(model, posture) {
983
+ return model === "iphone-duo" && resolveDevicePosture(model, posture) === "closed" ? "right" : "left";
984
+ }
985
+ function getDevice(model, posture, orientation, landscapeSide) {
982
986
  const device = devices[model];
987
+ const side = landscapeSide ?? defaultLandscapeSide(model, posture);
983
988
  if (!device.supportedPostures) {
984
- return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, landscapeSide) : device;
989
+ return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, side) : device;
985
990
  }
986
991
  const resolvedPosture = resolveDevicePosture(model, posture);
987
992
  const resolvedOrientation = orientation ?? deviceDefaultOrientation(model, resolvedPosture);
988
993
  if (resolvedPosture === "closed") {
989
- if (resolvedOrientation === "portrait") return device;
990
- const insets = device.frameInsets;
991
- const radii = device.cornerRadius;
992
- const body = device.frameCornerRadius ?? resolveDeviceFrameCorners(device).frameRadius;
993
- const housing = device.housing;
994
- const protrusion = housing?.hingeBarrel?.protrusion ?? 0;
995
- return {
996
- ...device,
997
- width: device.height,
998
- height: device.width,
999
- orientation: "landscape",
1000
- cornerRadius: {
1001
- topLeft: radii.topRight,
1002
- topRight: radii.bottomRight,
1003
- bottomRight: radii.bottomLeft,
1004
- bottomLeft: radii.topLeft
1005
- },
1006
- continuousCornerRadius: {
1007
- topLeft: device.continuousCornerRadius.topRight,
1008
- topRight: device.continuousCornerRadius.bottomRight,
1009
- bottomRight: device.continuousCornerRadius.bottomLeft,
1010
- bottomLeft: device.continuousCornerRadius.topLeft
1011
- },
1012
- frameInsets: {
1013
- top: insets.right,
1014
- right: insets.bottom,
1015
- bottom: insets.left + protrusion,
1016
- left: insets.top
1017
- },
1018
- frameCornerRadius: {
1019
- topLeft: body.topRight,
1020
- topRight: body.bottomRight,
1021
- bottomRight: body.bottomLeft,
1022
- bottomLeft: body.topLeft
1023
- },
1024
- housing: housing ? {
1025
- rail: {
1026
- top: housing.rail.right,
1027
- right: housing.rail.bottom,
1028
- bottom: housing.rail.left,
1029
- left: housing.rail.top
1030
- },
1031
- hingeBarrel: null
1032
- } : void 0,
1033
- cameraCutout: device.cameraCutout ? {
1034
- diameter: device.cameraCutout.diameter,
1035
- top: device.cameraCutout.top,
1036
- leading: device.cameraCutout.trailing
1037
- } : null,
1038
- safeAreaInsets: { top: 0, bottom: 34, left: 84, right: 0 },
1039
- // vertically compact, so the status bar is hidden.
1040
- statusBarHeight: 0
1041
- };
994
+ return resolvedOrientation === "portrait" ? device : rotateDevice(device, side);
1042
995
  }
1043
996
  const isRotatedPortrait = resolvedOrientation === "portrait";
1044
997
  return {
@@ -1565,10 +1518,12 @@ var init_devices = __esm({
1565
1518
  posture: "closed",
1566
1519
  supportedPostures: ["closed", "open"]
1567
1520
  }),
1521
+ // the ios 27.1 simulator's camera occlusion region: 37pt, 29 1/3 in from
1522
+ // the top and trailing edges
1568
1523
  cameraCutout: {
1569
1524
  diameter: 37,
1570
- top: 29,
1571
- trailing: 29
1525
+ top: 88 / 3,
1526
+ trailing: 88 / 3
1572
1527
  }
1573
1528
  },
1574
1529
  "ipad-pro-11": {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "Peach";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/is-record.ts
4
4
  function isRecord(value) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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;
@@ -24958,7 +24958,7 @@ function rotateDevice(device, side) {
24958
24958
  const barrelProtrusion = device.housing?.hingeBarrel?.protrusion ?? 0;
24959
24959
  if (side === "left") insets.top += barrelProtrusion;
24960
24960
  else insets.bottom += barrelProtrusion;
24961
- const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 20, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
24961
+ const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 34, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
24962
24962
  top: 0,
24963
24963
  bottom: 20,
24964
24964
  left: device.safeAreaInsets.top,
@@ -24993,71 +24993,24 @@ function rotateDevice(device, side) {
24993
24993
  // the bars stay on the interface's top and bottom; a cutout's inset moves
24994
24994
  // to whichever side the cutout turned to.
24995
24995
  safeAreaInsets: side === "left" ? safeArea : { ...safeArea, left: safeArea.right, right: safeArea.left },
24996
- statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" && device.model !== "iphone-duo" ? 0 : device.statusBarHeight,
24997
- homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? 20 : device.homeIndicatorHeight
24996
+ statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" ? 0 : device.statusBarHeight,
24997
+ // the indicator's band is the landscape bottom inset
24998
+ homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? safeArea.bottom : device.homeIndicatorHeight
24998
24999
  };
24999
25000
  }
25000
- function getDevice(model, posture, orientation, landscapeSide = "left") {
25001
+ function defaultLandscapeSide(model, posture) {
25002
+ return model === "iphone-duo" && resolveDevicePosture(model, posture) === "closed" ? "right" : "left";
25003
+ }
25004
+ function getDevice(model, posture, orientation, landscapeSide) {
25001
25005
  const device = devices[model];
25006
+ const side = landscapeSide ?? defaultLandscapeSide(model, posture);
25002
25007
  if (!device.supportedPostures) {
25003
- return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, landscapeSide) : device;
25008
+ return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, side) : device;
25004
25009
  }
25005
25010
  const resolvedPosture = resolveDevicePosture(model, posture);
25006
25011
  const resolvedOrientation = orientation ?? deviceDefaultOrientation(model, resolvedPosture);
25007
25012
  if (resolvedPosture === "closed") {
25008
- if (resolvedOrientation === "portrait") return device;
25009
- const insets = device.frameInsets;
25010
- const radii = device.cornerRadius;
25011
- const body = device.frameCornerRadius ?? resolveDeviceFrameCorners(device).frameRadius;
25012
- const housing = device.housing;
25013
- const protrusion = housing?.hingeBarrel?.protrusion ?? 0;
25014
- return {
25015
- ...device,
25016
- width: device.height,
25017
- height: device.width,
25018
- orientation: "landscape",
25019
- cornerRadius: {
25020
- topLeft: radii.topRight,
25021
- topRight: radii.bottomRight,
25022
- bottomRight: radii.bottomLeft,
25023
- bottomLeft: radii.topLeft
25024
- },
25025
- continuousCornerRadius: {
25026
- topLeft: device.continuousCornerRadius.topRight,
25027
- topRight: device.continuousCornerRadius.bottomRight,
25028
- bottomRight: device.continuousCornerRadius.bottomLeft,
25029
- bottomLeft: device.continuousCornerRadius.topLeft
25030
- },
25031
- frameInsets: {
25032
- top: insets.right,
25033
- right: insets.bottom,
25034
- bottom: insets.left + protrusion,
25035
- left: insets.top
25036
- },
25037
- frameCornerRadius: {
25038
- topLeft: body.topRight,
25039
- topRight: body.bottomRight,
25040
- bottomRight: body.bottomLeft,
25041
- bottomLeft: body.topLeft
25042
- },
25043
- housing: housing ? {
25044
- rail: {
25045
- top: housing.rail.right,
25046
- right: housing.rail.bottom,
25047
- bottom: housing.rail.left,
25048
- left: housing.rail.top
25049
- },
25050
- hingeBarrel: null
25051
- } : void 0,
25052
- cameraCutout: device.cameraCutout ? {
25053
- diameter: device.cameraCutout.diameter,
25054
- top: device.cameraCutout.top,
25055
- leading: device.cameraCutout.trailing
25056
- } : null,
25057
- safeAreaInsets: { top: 0, bottom: 34, left: 84, right: 0 },
25058
- // vertically compact, so the status bar is hidden.
25059
- statusBarHeight: 0
25060
- };
25013
+ return resolvedOrientation === "portrait" ? device : rotateDevice(device, side);
25061
25014
  }
25062
25015
  const isRotatedPortrait = resolvedOrientation === "portrait";
25063
25016
  return {
@@ -25584,10 +25537,12 @@ var init_devices = __esm({
25584
25537
  posture: "closed",
25585
25538
  supportedPostures: ["closed", "open"]
25586
25539
  }),
25540
+ // the ios 27.1 simulator's camera occlusion region: 37pt, 29 1/3 in from
25541
+ // the top and trailing edges
25587
25542
  cameraCutout: {
25588
25543
  diameter: 37,
25589
- top: 29,
25590
- trailing: 29
25544
+ top: 88 / 3,
25545
+ trailing: 88 / 3
25591
25546
  }
25592
25547
  },
25593
25548
  "ipad-pro-11": {
@@ -36316,7 +36271,10 @@ function getFramedScreenshotLayout(model) {
36316
36271
  const logicalScreenWidth = spec.width;
36317
36272
  const logicalScreenHeight = spec.height;
36318
36273
  const modernGeometry = (0, import_settings2.resolveDeviceFrameGeometry)(spec);
36319
- const housingLayers = isLegacyHardware ? null : (0, import_duo_housing.resolveHousingArt)(spec.posture ?? "closed", modernGeometry);
36274
+ const housingLayers = isLegacyHardware ? null : (0, import_duo_housing.resolveHousingArt)(spec.posture ?? "closed", modernGeometry, {
36275
+ orientation: spec.orientation,
36276
+ landscapeSide: spec.landscapeSide
36277
+ });
36320
36278
  const logicalFrameWidth = isLegacyHardware ? spec.width + import_chrome_metrics.LEGACY_SIDE_BEZEL * 2 : modernGeometry.frameWidth;
36321
36279
  const logicalFrameHeight = isLegacyHardware ? spec.height + import_chrome_metrics.LEGACY_TOP_BEZEL + import_chrome_metrics.LEGACY_BOTTOM_BEZEL : modernGeometry.frameHeight;
36322
36280
  const logicalFrameLeft = import_chrome_metrics.SIDE_BUTTON_RESERVE;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { execFile as execFile2 } from "node:child_process";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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;
@@ -1880,10 +1880,12 @@ var devices = {
1880
1880
  posture: "closed",
1881
1881
  supportedPostures: ["closed", "open"]
1882
1882
  }),
1883
+ // the ios 27.1 simulator's camera occlusion region: 37pt, 29 1/3 in from
1884
+ // the top and trailing edges
1883
1885
  cameraCutout: {
1884
1886
  diameter: 37,
1885
- top: 29,
1886
- trailing: 29
1887
+ top: 88 / 3,
1888
+ trailing: 88 / 3
1887
1889
  }
1888
1890
  },
1889
1891
  "ipad-pro-11": {
@@ -2232,7 +2234,7 @@ function rotateDevice(device, side) {
2232
2234
  const barrelProtrusion = device.housing?.hingeBarrel?.protrusion ?? 0;
2233
2235
  if (side === "left") insets.top += barrelProtrusion;
2234
2236
  else insets.bottom += barrelProtrusion;
2235
- const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 20, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
2237
+ const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 34, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
2236
2238
  top: 0,
2237
2239
  bottom: 20,
2238
2240
  left: device.safeAreaInsets.top,
@@ -2267,10 +2269,14 @@ function rotateDevice(device, side) {
2267
2269
  // the bars stay on the interface's top and bottom; a cutout's inset moves
2268
2270
  // to whichever side the cutout turned to.
2269
2271
  safeAreaInsets: side === "left" ? safeArea : { ...safeArea, left: safeArea.right, right: safeArea.left },
2270
- statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" && device.model !== "iphone-duo" ? 0 : device.statusBarHeight,
2271
- homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? 20 : device.homeIndicatorHeight
2272
+ statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" ? 0 : device.statusBarHeight,
2273
+ // the indicator's band is the landscape bottom inset
2274
+ homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? safeArea.bottom : device.homeIndicatorHeight
2272
2275
  };
2273
2276
  }
2277
+ function defaultLandscapeSide(model, posture) {
2278
+ return model === "iphone-duo" && resolveDevicePosture(model, posture) === "closed" ? "right" : "left";
2279
+ }
2274
2280
  function isPadIdiom(spec) {
2275
2281
  return spec.model === "ipad-pro-11";
2276
2282
  }
@@ -2304,67 +2310,16 @@ function deviceSizeClasses(model, orientation, posture) {
2304
2310
  function withOsVersionOverride(spec, osVersion) {
2305
2311
  return osVersion && spec.platform === "ios" ? { ...spec, osVersion, iosVersion: osVersion } : spec;
2306
2312
  }
2307
- function getDevice(model, posture, orientation, landscapeSide = "left") {
2313
+ function getDevice(model, posture, orientation, landscapeSide) {
2308
2314
  const device = devices[model];
2315
+ const side = landscapeSide ?? defaultLandscapeSide(model, posture);
2309
2316
  if (!device.supportedPostures) {
2310
- return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, landscapeSide) : device;
2317
+ return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, side) : device;
2311
2318
  }
2312
2319
  const resolvedPosture = resolveDevicePosture(model, posture);
2313
2320
  const resolvedOrientation = orientation ?? deviceDefaultOrientation(model, resolvedPosture);
2314
2321
  if (resolvedPosture === "closed") {
2315
- if (resolvedOrientation === "portrait") return device;
2316
- const insets = device.frameInsets;
2317
- const radii = device.cornerRadius;
2318
- const body = device.frameCornerRadius ?? resolveDeviceFrameCorners(device).frameRadius;
2319
- const housing = device.housing;
2320
- const protrusion = housing?.hingeBarrel?.protrusion ?? 0;
2321
- return {
2322
- ...device,
2323
- width: device.height,
2324
- height: device.width,
2325
- orientation: "landscape",
2326
- cornerRadius: {
2327
- topLeft: radii.topRight,
2328
- topRight: radii.bottomRight,
2329
- bottomRight: radii.bottomLeft,
2330
- bottomLeft: radii.topLeft
2331
- },
2332
- continuousCornerRadius: {
2333
- topLeft: device.continuousCornerRadius.topRight,
2334
- topRight: device.continuousCornerRadius.bottomRight,
2335
- bottomRight: device.continuousCornerRadius.bottomLeft,
2336
- bottomLeft: device.continuousCornerRadius.topLeft
2337
- },
2338
- frameInsets: {
2339
- top: insets.right,
2340
- right: insets.bottom,
2341
- bottom: insets.left + protrusion,
2342
- left: insets.top
2343
- },
2344
- frameCornerRadius: {
2345
- topLeft: body.topRight,
2346
- topRight: body.bottomRight,
2347
- bottomRight: body.bottomLeft,
2348
- bottomLeft: body.topLeft
2349
- },
2350
- housing: housing ? {
2351
- rail: {
2352
- top: housing.rail.right,
2353
- right: housing.rail.bottom,
2354
- bottom: housing.rail.left,
2355
- left: housing.rail.top
2356
- },
2357
- hingeBarrel: null
2358
- } : void 0,
2359
- cameraCutout: device.cameraCutout ? {
2360
- diameter: device.cameraCutout.diameter,
2361
- top: device.cameraCutout.top,
2362
- leading: device.cameraCutout.trailing
2363
- } : null,
2364
- safeAreaInsets: { top: 0, bottom: 34, left: 84, right: 0 },
2365
- // vertically compact, so the status bar is hidden.
2366
- statusBarHeight: 0
2367
- };
2322
+ return resolvedOrientation === "portrait" ? device : rotateDevice(device, side);
2368
2323
  }
2369
2324
  const isRotatedPortrait = resolvedOrientation === "portrait";
2370
2325
  return {
@@ -3189,6 +3144,10 @@ function getDefaults() {
3189
3144
  overrides.deviceModel ?? DEFAULT_DEVICE,
3190
3145
  defaults2.posture
3191
3146
  );
3147
+ defaults2.landscapeSide = overrides.landscapeSide ?? defaultLandscapeSide(
3148
+ overrides.deviceModel ?? DEFAULT_DEVICE,
3149
+ defaults2.posture
3150
+ );
3192
3151
  return defaults2;
3193
3152
  }
3194
3153
 
@@ -3407,6 +3366,10 @@ for (const key of PERSISTED_KEYS) {
3407
3366
  var _state = { ...defaults, ..._persisted };
3408
3367
  var _listeners = [];
3409
3368
  var _deviceCache = null;
3369
+ function arrivingLandscapeSide(prev, next) {
3370
+ const enters = next.orientation === "landscape" && (prev.orientation !== "landscape" || prev.posture !== next.posture || prev.deviceModel !== next.deviceModel);
3371
+ return enters ? defaultLandscapeSide(next.deviceModel, next.posture) : next.landscapeSide;
3372
+ }
3410
3373
  function notifyListeners() {
3411
3374
  for (const fn of _listeners) fn();
3412
3375
  }
@@ -3422,7 +3385,7 @@ function updateSetting(key, value) {
3422
3385
  if (typeof value !== "string" || !isDevicePosture(value)) return false;
3423
3386
  const nextPosture = resolveDevicePosture(_state.deviceModel, value);
3424
3387
  if (_state.posture === nextPosture) return false;
3425
- _state = {
3388
+ const next = {
3426
3389
  ..._state,
3427
3390
  posture: nextPosture,
3428
3391
  orientation: orientationAfterPostureChange(
@@ -3431,11 +3394,13 @@ function updateSetting(key, value) {
3431
3394
  nextPosture
3432
3395
  )
3433
3396
  };
3397
+ _state = { ...next, landscapeSide: arrivingLandscapeSide(_state, next) };
3434
3398
  _deviceCache = null;
3435
3399
  return true;
3436
3400
  }
3437
3401
  if (key === "deviceModel" && _state.deviceModel === value) return false;
3438
3402
  if (_state[key] === value) return false;
3403
+ const prev = _state;
3439
3404
  _state = { ..._state, [key]: value };
3440
3405
  if (key === "deviceModel") {
3441
3406
  const nextPosture = resolveDevicePosture(_state.deviceModel);
@@ -3445,6 +3410,8 @@ function updateSetting(key, value) {
3445
3410
  orientation: deviceDefaultOrientation(_state.deviceModel, nextPosture)
3446
3411
  };
3447
3412
  }
3413
+ if (key !== "landscapeSide")
3414
+ _state = { ..._state, landscapeSide: arrivingLandscapeSide(prev, _state) };
3448
3415
  if (key === "deviceModel" || key === "orientation" || key === "landscapeSide" || key === "osVersionOverride")
3449
3416
  _deviceCache = null;
3450
3417
  return true;
@@ -3524,6 +3491,11 @@ var settingsStore = {
3524
3491
  next.orientation = nextOrientation;
3525
3492
  changed = true;
3526
3493
  }
3494
+ const nextSide = overrides.landscapeSide ?? arrivingLandscapeSide(_state, next);
3495
+ if (next.landscapeSide !== nextSide) {
3496
+ next.landscapeSide = nextSide;
3497
+ changed = true;
3498
+ }
3527
3499
  if (changed) {
3528
3500
  _state = next;
3529
3501
  _deviceCache = null;
@@ -16344,7 +16316,6 @@ function ScrollViewInner(props, ref) {
16344
16316
  const headerRef = headerScroll?.headerRef;
16345
16317
  const containerView = hostingSafeArea?.view;
16346
16318
  const containerHeight = hostingSafeArea?.height;
16347
- const laidOutRef = (0, import_react10.useRef)(false);
16348
16319
  const measureOverlap = (0, import_react10.useCallback)(() => {
16349
16320
  const host = hostRef.current;
16350
16321
  if (!host) return;
@@ -16372,14 +16343,13 @@ function ScrollViewInner(props, ref) {
16372
16343
  const handleLayout = (0, import_react10.useCallback)(
16373
16344
  (event) => {
16374
16345
  onLayout?.(event);
16375
- laidOutRef.current = true;
16376
16346
  measureOverlap();
16377
16347
  },
16378
16348
  [onLayout, measureOverlap]
16379
16349
  );
16380
16350
  (0, import_react10.useEffect)(() => {
16381
- if (laidOutRef.current) measureOverlap();
16382
- }, [measureOverlap]);
16351
+ if (measuresSafeArea && hostRef.current) measureOverlap();
16352
+ }, [measuresSafeArea, measureOverlap]);
16383
16353
  const bouncesVertically = props.alwaysBounceVertical ?? !horizontal;
16384
16354
  const tracksContentHeight = measuresSafeArea && !bouncesVertically && behavior !== "always";
16385
16355
  const [contentHeight, setContentHeight] = (0, import_react10.useState)();
@@ -28047,7 +28017,7 @@ var import_sf_symbol_catalog4 = require("peach-engine/ios/sf-symbol-catalog");
28047
28017
  var import_SplitView2 = require("peach-engine/ios/SplitView");
28048
28018
  var import_platform_colors4 = require("peach-engine/react-native/platform-colors");
28049
28019
  var import_device_spec_bus26 = require("peach-engine/settings/device-spec-bus");
28050
- var import_devices6 = require("peach-engine/settings/devices");
28020
+ var import_devices7 = require("peach-engine/settings/devices");
28051
28021
  var import_store15 = require("peach-engine/settings/store");
28052
28022
  var import_use_device9 = require("peach-engine/settings/use-device");
28053
28023
  var import_react53 = require("react");
@@ -28555,7 +28525,7 @@ function deviceWindowSizeClasses() {
28555
28525
  throw new Error(
28556
28526
  `swift environment has no size classes on ${spec?.platform ?? "no device"}`
28557
28527
  );
28558
- return (0, import_devices6.deviceSizeClasses)(
28528
+ return (0, import_devices7.deviceSizeClasses)(
28559
28529
  spec.model,
28560
28530
  spec.width > spec.height ? "landscape" : "portrait",
28561
28531
  spec.posture
@@ -29617,6 +29587,7 @@ var NODE_COMPONENTS = {
29617
29587
  ContextMenu: import_ui.ContextMenu,
29618
29588
  ControlGroup: import_ui.ControlGroup,
29619
29589
  DatePicker: import_ui.DatePicker,
29590
+ DisclosureGroup: import_ui.DisclosureGroup,
29620
29591
  Divider: import_ui.Divider,
29621
29592
  EditButton: import_ui.Button,
29622
29593
  Ellipse: import_ui.Ellipse,
@@ -30446,6 +30417,15 @@ function nodeProps(node, deliver) {
30446
30417
  }
30447
30418
  case "GlassEffectContainer":
30448
30419
  return typeof props.spacing === "number" ? { spacing: props.spacing } : {};
30420
+ case "DisclosureGroup": {
30421
+ const onIsExpandedChange = handlerId(node, "onIsExpandedChange");
30422
+ return {
30423
+ ...typeof props.isExpanded === "boolean" ? { isExpanded: props.isExpanded } : {},
30424
+ ...onIsExpandedChange === void 0 ? {} : {
30425
+ onIsExpandedChange: (value) => deliver(onIsExpandedChange, value)
30426
+ }
30427
+ };
30428
+ }
30449
30429
  case "GroupBox":
30450
30430
  return pressProps(node, deliver);
30451
30431
  case "LabeledContent":
@@ -32180,7 +32160,7 @@ function buildNode(swiftNode, deliver, cache2, inToolbar = false, inList = false
32180
32160
  if (inToolbar) node = toolbarIconOnlyLabel(node);
32181
32161
  const modifiers = nodeModifiers(node);
32182
32162
  const childInList = node.t === "List" || node.t === "Form" || (node.t === "Section" || node.t === "Group") && inList;
32183
- if (node.t === "LabeledContent" || node.t === "GroupBox") {
32163
+ if (node.t === "LabeledContent" || node.t === "GroupBox" || node.t === "DisclosureGroup") {
32184
32164
  const { label, content } = labeledContentSlots(node);
32185
32165
  return withEnvironmentFont(
32186
32166
  node,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.629 | (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": "peachsim",
3
- "version": "0.1.628",
3
+ "version": "0.1.629",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -90,7 +90,10 @@ export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotL
90
90
  const modernGeometry = resolveDeviceFrameGeometry(spec)
91
91
  const housingLayers = isLegacyHardware
92
92
  ? null
93
- : resolveHousingArt(spec.posture ?? 'closed', modernGeometry)
93
+ : resolveHousingArt(spec.posture ?? 'closed', modernGeometry, {
94
+ orientation: spec.orientation,
95
+ landscapeSide: spec.landscapeSide,
96
+ })
94
97
  const logicalFrameWidth = isLegacyHardware
95
98
  ? spec.width + LEGACY_SIDE_BEZEL * 2
96
99
  : modernGeometry.frameWidth