peachsim 0.1.1644 → 0.1.1653

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 (608) hide show
  1. package/README.md +12 -0
  2. package/cli/app-catalog.ts +1 -1
  3. package/cli/app-fonts.ts +11 -80
  4. package/cli/app-splash.ts +18 -12
  5. package/cli/bridge-flow-runner.ts +11 -7
  6. package/cli/cloud-client.ts +10 -13
  7. package/cli/command-registry.ts +13 -4
  8. package/cli/commands/box.ts +4 -4
  9. package/cli/commands/control.ts +93 -53
  10. package/cli/commands/coverage-parser.ts +67 -0
  11. package/cli/commands/coverage.ts +550 -0
  12. package/cli/commands/debug.ts +9 -18
  13. package/cli/commands/desktop.ts +19 -7
  14. package/cli/commands/device.ts +14 -9
  15. package/cli/commands/guest-host.ts +6 -10
  16. package/cli/commands/inspect/core.ts +81 -17
  17. package/cli/commands/inspect.ts +13 -8
  18. package/cli/commands/kotlin.ts +2 -2
  19. package/cli/commands/maestro-compare.ts +1 -1
  20. package/cli/commands/platform.ts +20 -11
  21. package/cli/commands/preview.ts +16 -18
  22. package/cli/commands/runtime.ts +3 -2
  23. package/cli/commands/screenshot-layers.ts +1 -1
  24. package/cli/commands/screenshot.ts +1 -1
  25. package/cli/commands/serve.ts +5 -1
  26. package/cli/commands/support.ts +4 -4
  27. package/cli/commands/three-mode.ts +22 -15
  28. package/cli/commands/upload.ts +44 -45
  29. package/cli/current-sim.ts +38 -0
  30. package/cli/desktop-companion.ts +36 -8
  31. package/cli/device-option.ts +1 -1
  32. package/cli/drivers/playwright.ts +1 -0
  33. package/cli/drivers/types.ts +4 -0
  34. package/cli/help-core.ts +1 -1
  35. package/cli/internal-child.ts +2 -1
  36. package/cli/main.ts +9 -3
  37. package/cli/outbound-endpoints.ts +11 -3
  38. package/cli/output-redaction.ts +39 -14
  39. package/cli/remote-simulators.ts +4 -1
  40. package/cli/scene-video.ts +5 -2
  41. package/cli/send-to-box.ts +7 -10
  42. package/cli/telemetry.ts +1 -1
  43. package/cli/ws-bridge.ts +8 -1
  44. package/detox/attempt-events.cjs +3 -1
  45. package/detox/attempt-events.d.cts +1 -1
  46. package/detox/expectations.ts +108 -99
  47. package/detox/frame-offset.d.mts +6 -0
  48. package/detox/frame-offset.mjs +35 -0
  49. package/detox/gestures.ts +6 -18
  50. package/detox/index.ts +169 -101
  51. package/detox/jest-preset.cjs +1 -3
  52. package/detox/jest-transform.cjs +4 -0
  53. package/detox/matchers.ts +3 -0
  54. package/detox/motion-change.cjs +46 -114
  55. package/detox/motion-change.d.cts +5 -27
  56. package/dist-lib/agent-daemon-client.cjs +1 -1
  57. package/dist-lib/agent-events.cjs +1 -1
  58. package/dist-lib/attached-projects.cjs +1 -1
  59. package/dist-lib/auth/shared-session.cjs +1 -1
  60. package/dist-lib/backend-origin.cjs +1 -1
  61. package/dist-lib/beta.cjs +1 -1
  62. package/dist-lib/beta.mjs +1 -1
  63. package/dist-lib/bridge-constants.cjs +1 -1
  64. package/dist-lib/bridge-contract-input.cjs +65 -1
  65. package/dist-lib/bridge-contract-input.mjs +63 -1
  66. package/dist-lib/bridge-contract.cjs +19 -1
  67. package/dist-lib/bridge-contract.mjs +17 -1
  68. package/dist-lib/bundle-channel.cjs +38091 -14846
  69. package/dist-lib/capture-contract.cjs +1 -1
  70. package/dist-lib/capture-contract.mjs +1 -1
  71. package/dist-lib/cloud-contract.cjs +1 -1
  72. package/dist-lib/cloud-contract.mjs +1 -1
  73. package/dist-lib/cloud-test-args.cjs +1 -1
  74. package/dist-lib/cloud-test-args.mjs +1 -1
  75. package/dist-lib/cloud.cjs +1 -1
  76. package/dist-lib/cloud.mjs +1 -1
  77. package/dist-lib/config.cjs +1 -1
  78. package/dist-lib/config.mjs +5 -3
  79. package/dist-lib/detox/index.cjs +1244 -4509
  80. package/dist-lib/detox/jest-preset.cjs +1 -3
  81. package/dist-lib/detox/jest-transform.cjs +4 -0
  82. package/dist-lib/dev-bundle-resolution.cjs +28 -24
  83. package/dist-lib/expo-swift-bundle.cjs +35049 -13125
  84. package/dist-lib/expo-swift-metadata.cjs +1 -1
  85. package/dist-lib/expo-swift-metadata.mjs +1 -1
  86. package/dist-lib/home-paths.cjs +1 -1
  87. package/dist-lib/host/bridge-host.cjs +45112 -63143
  88. package/dist-lib/host/fetch-proxy-handler.cjs +3544 -11
  89. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  90. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  91. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  92. package/dist-lib/host/websocket-proxy.cjs +1 -1
  93. package/dist-lib/index.cjs +1909 -2029
  94. package/dist-lib/jump-to-source-babel.cjs +1 -1
  95. package/dist-lib/jump-to-source-native.cjs +1 -1
  96. package/dist-lib/kotlin-host.cjs +2 -2
  97. package/dist-lib/menu.cjs +1 -1
  98. package/dist-lib/menu.mjs +1 -1
  99. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  100. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  101. package/dist-lib/metro-production-bundle.cjs +1 -1
  102. package/dist-lib/metro-production-bundle.mjs +1 -1
  103. package/dist-lib/metro.cjs +380 -522
  104. package/dist-lib/native-app-identity-project.cjs +39 -252
  105. package/dist-lib/native-app-identity-project.mjs +1174 -11
  106. package/dist-lib/native-app-identity.cjs +8 -3
  107. package/dist-lib/native-app-identity.mjs +8 -3
  108. package/dist-lib/native-firebase-metadata.cjs +1 -1
  109. package/dist-lib/native-firebase-metadata.mjs +1 -1
  110. package/dist-lib/plist.cjs +2 -244
  111. package/dist-lib/plist.mjs +1 -1
  112. package/dist-lib/profiles.cjs +1 -1
  113. package/dist-lib/public-brand.cjs +1 -1
  114. package/dist-lib/public-origins-lib-esm.json +290 -0
  115. package/dist-lib/public-origins-lib-static.json +1 -0
  116. package/dist-lib/public-origins-lib.json +1852 -0
  117. package/dist-lib/react-native-host-modules.cjs +1 -1
  118. package/dist-lib/react-native-host-modules.mjs +1 -1
  119. package/dist-lib/scripts/dev-server-scanner.cjs +14 -253
  120. package/dist-lib/sdk.cjs +83 -16
  121. package/dist-lib/sdk.mjs +81 -15
  122. package/dist-lib/skills.cjs +50546 -75098
  123. package/dist-lib/swift-compile.cjs +25897 -1070
  124. package/dist-lib/swift-compile.mjs +25866 -1033
  125. package/dist-lib/swift-package.cjs +79 -1
  126. package/dist-lib/swift-package.mjs +75 -1
  127. package/dist-lib/swift-submit.cjs +1 -1
  128. package/dist-lib/swift-submit.mjs +1 -1
  129. package/dist-lib/swift-toolchain.cjs +1 -1
  130. package/dist-lib/swift.cjs +1 -1
  131. package/dist-lib/vite-swift.cjs +34273 -12349
  132. package/dist-lib/vite.cjs +373 -298
  133. package/dist-lib/worklet-executable.cjs +1 -1
  134. package/dist-lib/worklet-executable.mjs +1 -1
  135. package/dist-types/packages/peach-compat/src/engine-config.d.ts +2 -0
  136. package/dist-types/packages/peach-compat/src/stubs/form-sheet-spring.d.ts +9 -0
  137. package/dist-types/packages/peach-compat/src/stubs/native-evaluation-lease.d.ts +47 -0
  138. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-cookies.d.ts +113 -0
  139. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-gesture-handler.d.ts +154 -0
  140. package/dist-types/packages/peach-compat/src/stubs/screen-transition-math.d.ts +756 -0
  141. package/dist-types/packages/peach-compat/src/stubs/transition-scalar.d.ts +25 -0
  142. package/dist-types/packages/peach-engine/src/billing/plans.d.ts +64 -0
  143. package/dist-types/packages/peach-engine/src/browser-page-target.d.ts +2 -0
  144. package/dist-types/packages/peach-engine/src/bundle-platform-url.d.ts +3 -0
  145. package/dist-types/packages/peach-engine/src/capture/browser-accessibility-host.d.ts +3 -0
  146. package/dist-types/packages/peach-engine/src/capture/browser-composite.d.ts +55 -0
  147. package/dist-types/packages/peach-engine/src/capture/browserAccessibilityContract.d.ts +27 -0
  148. package/dist-types/packages/peach-engine/src/capture/nativeScreenCaptureContract.d.ts +22 -0
  149. package/dist-types/packages/peach-engine/src/cli-companion.d.ts +36 -0
  150. package/dist-types/packages/peach-engine/src/components/native-ui/webview-frame-bridge.d.ts +34 -0
  151. package/dist-types/packages/peach-engine/src/config.d.ts +5 -0
  152. package/dist-types/packages/peach-engine/src/engine/android-stretch-effect.d.ts +57 -0
  153. package/dist-types/packages/peach-engine/src/engine/animated-driven-style.d.ts +47 -0
  154. package/dist-types/packages/peach-engine/src/engine/animated-value.d.ts +5 -0
  155. package/dist-types/packages/peach-engine/src/engine/animated.d.ts +195 -0
  156. package/dist-types/packages/peach-engine/src/engine/animation-clockContract.d.ts +15 -0
  157. package/dist-types/packages/peach-engine/src/engine/animation-graph.d.ts +148 -0
  158. package/dist-types/packages/peach-engine/src/engine/app-catalog-wire.d.ts +10 -0
  159. package/dist-types/packages/peach-engine/src/engine/app-font-registry.d.ts +87 -0
  160. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph-paint.d.ts +7 -0
  161. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph.d.ts +123 -0
  162. package/dist-types/packages/peach-engine/src/engine/audioContract.d.ts +16 -0
  163. package/dist-types/packages/peach-engine/src/engine/canvaskit-api.d.ts +93 -0
  164. package/dist-types/packages/peach-engine/src/engine/canvaskit-renderer.d.ts +216 -0
  165. package/dist-types/packages/peach-engine/src/engine/config-plugin-fonts.d.ts +40 -0
  166. package/dist-types/packages/peach-engine/src/engine/config-plugin-splash.d.ts +25 -0
  167. package/dist-types/packages/peach-engine/src/engine/cull-visibility.d.ts +44 -0
  168. package/dist-types/packages/peach-engine/src/engine/damage-rect.d.ts +19 -0
  169. package/dist-types/packages/peach-engine/src/engine/engine-resource.d.ts +6 -0
  170. package/dist-types/packages/peach-engine/src/engine/expo-manifest.d.ts +5 -0
  171. package/dist-types/packages/peach-engine/src/engine/fiber-debug-metadata.d.ts +30 -0
  172. package/dist-types/packages/peach-engine/src/engine/font-config.d.ts +139 -0
  173. package/dist-types/packages/peach-engine/src/engine/generated/sf-pro-font.d.ts +1 -0
  174. package/dist-types/packages/peach-engine/src/engine/glass-material.d.ts +31 -0
  175. package/dist-types/packages/peach-engine/src/engine/host-composite.d.ts +100 -0
  176. package/dist-types/packages/peach-engine/src/engine/hosted-semantics.d.ts +49 -0
  177. package/dist-types/packages/peach-engine/src/engine/image-audit.d.ts +70 -0
  178. package/dist-types/packages/peach-engine/src/engine/image-loader.d.ts +350 -0
  179. package/dist-types/packages/peach-engine/src/engine/inspect-info.d.ts +27 -0
  180. package/dist-types/packages/peach-engine/src/engine/inspect-outline.d.ts +14 -0
  181. package/dist-types/packages/peach-engine/src/engine/inspect-visibility.d.ts +33 -0
  182. package/dist-types/packages/peach-engine/src/engine/ios-fast-scroll.d.ts +16 -0
  183. package/dist-types/packages/peach-engine/src/engine/layout-sab.d.ts +43 -0
  184. package/dist-types/packages/peach-engine/src/engine/liquid-glass-rect.d.ts +23 -0
  185. package/dist-types/packages/peach-engine/src/engine/liquid-glass-shaders.d.ts +9 -0
  186. package/dist-types/packages/peach-engine/src/engine/liquid-glass.d.ts +283 -0
  187. package/dist-types/packages/peach-engine/src/engine/live-object-counts.d.ts +6 -0
  188. package/dist-types/packages/peach-engine/src/engine/lottie-runtime.d.ts +32 -0
  189. package/dist-types/packages/peach-engine/src/engine/lottie-types.d.ts +138 -0
  190. package/dist-types/packages/peach-engine/src/engine/memory-counts.d.ts +27 -0
  191. package/dist-types/packages/peach-engine/src/engine/metalDirectContract.d.ts +108 -0
  192. package/dist-types/packages/peach-engine/src/engine/metalShaderContract.d.ts +217 -0
  193. package/dist-types/packages/peach-engine/src/engine/native-animation-driver.d.ts +112 -0
  194. package/dist-types/packages/peach-engine/src/engine/native-animation-graph.d.ts +62 -0
  195. package/dist-types/packages/peach-engine/src/engine/native-layout.d.ts +133 -0
  196. package/dist-types/packages/peach-engine/src/engine/native-resources.d.ts +26 -0
  197. package/dist-types/packages/peach-engine/src/engine/nativeReanimatedContract.d.ts +25 -0
  198. package/dist-types/packages/peach-engine/src/engine/nativeReplayContract.d.ts +64 -0
  199. package/dist-types/packages/peach-engine/src/engine/node.d.ts +589 -0
  200. package/dist-types/packages/peach-engine/src/engine/paint-boundary-types.d.ts +112 -0
  201. package/dist-types/packages/peach-engine/src/engine/paint-boundary.d.ts +57 -0
  202. package/dist-types/packages/peach-engine/src/engine/portalContract.d.ts +21 -0
  203. package/dist-types/packages/peach-engine/src/engine/portals.d.ts +20 -0
  204. package/dist-types/packages/peach-engine/src/engine/render-damage.d.ts +107 -0
  205. package/dist-types/packages/peach-engine/src/engine/riveContract.d.ts +420 -0
  206. package/dist-types/packages/peach-engine/src/engine/rn-spring.d.ts +51 -0
  207. package/dist-types/packages/peach-engine/src/engine/scene-table.d.ts +379 -0
  208. package/dist-types/packages/peach-engine/src/engine/scroll-momentum-math.d.ts +152 -0
  209. package/dist-types/packages/peach-engine/src/engine/scroll-pan-contacts.d.ts +10 -0
  210. package/dist-types/packages/peach-engine/src/engine/scroll-platform.d.ts +75 -0
  211. package/dist-types/packages/peach-engine/src/engine/scroll-range.d.ts +14 -0
  212. package/dist-types/packages/peach-engine/src/engine/scroll-velocity.d.ts +14 -0
  213. package/dist-types/packages/peach-engine/src/engine/scroll.d.ts +320 -0
  214. package/dist-types/packages/peach-engine/src/engine/signal.d.ts +7 -0
  215. package/dist-types/packages/peach-engine/src/engine/snapshot-cache-policy.d.ts +6 -0
  216. package/dist-types/packages/peach-engine/src/engine/svg-geometry.d.ts +41 -0
  217. package/dist-types/packages/peach-engine/src/engine/text-attachment-paragraphs.d.ts +10 -0
  218. package/dist-types/packages/peach-engine/src/engine/text-decoration.d.ts +11 -0
  219. package/dist-types/packages/peach-engine/src/engine/text-line-break.d.ts +22 -0
  220. package/dist-types/packages/peach-engine/src/engine/text-paint-receipt.d.ts +98 -0
  221. package/dist-types/packages/peach-engine/src/engine/text-paragraph.d.ts +11 -0
  222. package/dist-types/packages/peach-engine/src/engine/text-paragraphContract.d.ts +34 -0
  223. package/dist-types/packages/peach-engine/src/engine/text-transform.d.ts +1 -0
  224. package/dist-types/packages/peach-engine/src/engine/types.d.ts +657 -0
  225. package/dist-types/packages/peach-engine/src/engine/visible-frame.d.ts +54 -0
  226. package/dist-types/packages/peach-engine/src/engine/webrtcContract.d.ts +74 -0
  227. package/dist-types/packages/peach-engine/src/graphite-stats-fields.d.ts +184 -0
  228. package/dist-types/packages/peach-engine/src/guest-import-meta.d.ts +12 -0
  229. package/dist-types/packages/peach-engine/src/guest-module-overrides.d.ts +7 -0
  230. package/dist-types/packages/peach-engine/src/ios/app-card-types.d.ts +7 -0
  231. package/dist-types/packages/peach-engine/src/ios/apps/canvas-map-data.d.ts +177 -0
  232. package/dist-types/packages/peach-engine/src/ios/aux-home-scene.d.ts +54 -0
  233. package/dist-types/packages/peach-engine/src/ios/chrome-metrics.d.ts +47 -0
  234. package/dist-types/packages/peach-engine/src/ios/constants.d.ts +21 -0
  235. package/dist-types/packages/peach-engine/src/ios/duo-housing.d.ts +37 -0
  236. package/dist-types/packages/peach-engine/src/ios/home/types.d.ts +29 -0
  237. package/dist-types/packages/peach-engine/src/ios/home-app-catalog.d.ts +43 -0
  238. package/dist-types/packages/peach-engine/src/ios/photo-store.d.ts +73 -0
  239. package/dist-types/packages/peach-engine/src/ios/photoLibraryContract.d.ts +166 -0
  240. package/dist-types/packages/peach-engine/src/ios/shell-controller-types.d.ts +21 -0
  241. package/dist-types/packages/peach-engine/src/ios/shell-transition-debug.d.ts +18 -0
  242. package/dist-types/packages/peach-engine/src/metro-asset-path.d.ts +21 -0
  243. package/dist-types/packages/peach-engine/src/metro-fingerprint-registry-client.d.ts +11 -0
  244. package/dist-types/packages/peach-engine/src/metro-fingerprint.d.ts +38 -0
  245. package/dist-types/packages/peach-engine/src/native-preview-bundle.d.ts +44 -0
  246. package/dist-types/packages/peach-engine/src/observability/types.d.ts +74 -0
  247. package/dist-types/packages/peach-engine/src/peach-warm-manifest.d.ts +32 -0
  248. package/dist-types/packages/peach-engine/src/permissions/app-settings-client.d.ts +25 -0
  249. package/dist-types/packages/peach-engine/src/permissions/system-permission-types.d.ts +20 -0
  250. package/dist-types/packages/peach-engine/src/platform/android-back-panel.d.ts +131 -0
  251. package/dist-types/packages/peach-engine/src/platform/android-gesture-exclusion.d.ts +28 -0
  252. package/dist-types/packages/peach-engine/src/platform/android-predictive-back.d.ts +33 -0
  253. package/dist-types/packages/peach-engine/src/platform/system-bars-state.d.ts +14 -0
  254. package/dist-types/packages/peach-engine/src/playwright-sim-host.d.ts +1 -0
  255. package/dist-types/packages/peach-engine/src/preview/bundle-layout.d.ts +8 -0
  256. package/dist-types/packages/peach-engine/src/preview/bundle-variantContract.d.ts +24 -0
  257. package/dist-types/packages/peach-engine/src/preview/capture-bundle.d.ts +26 -0
  258. package/dist-types/packages/peach-engine/src/preview/compress-node.d.ts +2 -0
  259. package/dist-types/packages/peach-engine/src/preview/compress.d.ts +2 -0
  260. package/dist-types/packages/peach-engine/src/preview/presigned-upload.d.ts +60 -0
  261. package/dist-types/packages/peach-engine/src/preview/trace.d.ts +144 -0
  262. package/dist-types/packages/peach-engine/src/preview/upload-protocol.d.ts +152 -0
  263. package/dist-types/packages/peach-engine/src/profiler/animation-recording-loader.d.ts +1 -0
  264. package/dist-types/packages/peach-engine/src/profiler/profile-trace.d.ts +4 -0
  265. package/dist-types/packages/peach-engine/src/react-bridge.d.ts +3 -0
  266. package/dist-types/packages/peach-engine/src/react-native/AppState.d.ts +45 -0
  267. package/dist-types/packages/peach-engine/src/react-native/Appearance.d.ts +34 -0
  268. package/dist-types/packages/peach-engine/src/react-native/framework-colors-data.d.ts +2 -0
  269. package/dist-types/packages/peach-engine/src/react-native/host-services.d.ts +42 -0
  270. package/dist-types/packages/peach-engine/src/react-native/layout-animation.d.ts +22 -0
  271. package/dist-types/packages/peach-engine/src/react-native/platform-colors.d.ts +17 -0
  272. package/dist-types/packages/peach-engine/src/remote-stream/client-config.d.ts +10 -0
  273. package/dist-types/packages/peach-engine/src/remote-stream/cloud-display.d.ts +58 -0
  274. package/dist-types/packages/peach-engine/src/remote-stream/scene-recording.d.ts +45 -0
  275. package/dist-types/packages/peach-engine/src/render-worker/animated-drive-output.d.ts +35 -0
  276. package/dist-types/packages/peach-engine/src/render-worker/app-load.d.ts +16 -0
  277. package/dist-types/packages/peach-engine/src/render-worker/aux-surface-types.d.ts +2 -0
  278. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-shared.d.ts +42 -0
  279. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-webgpu.d.ts +434 -0
  280. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-worker-init.d.ts +12 -0
  281. package/dist-types/packages/peach-engine/src/render-worker/compositor-backend.d.ts +31 -0
  282. package/dist-types/packages/peach-engine/src/render-worker/compositor-gpu.d.ts +202 -0
  283. package/dist-types/packages/peach-engine/src/render-worker/compositor-protocol.d.ts +1945 -0
  284. package/dist-types/packages/peach-engine/src/render-worker/compositor-runtime/scroll-drag-resample.d.ts +44 -0
  285. package/dist-types/packages/peach-engine/src/render-worker/css-keyframes-drive.d.ts +36 -0
  286. package/dist-types/packages/peach-engine/src/render-worker/edit-menu-geometry.d.ts +8 -0
  287. package/dist-types/packages/peach-engine/src/render-worker/engine-resource-relay.d.ts +21 -0
  288. package/dist-types/packages/peach-engine/src/render-worker/expo-widgetContract.d.ts +16 -0
  289. package/dist-types/packages/peach-engine/src/render-worker/gesture-seam-protocol.d.ts +152 -0
  290. package/dist-types/packages/peach-engine/src/render-worker/graph-linked-value.d.ts +29 -0
  291. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler-contract.d.ts +49 -0
  292. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler.d.ts +12 -0
  293. package/dist-types/packages/peach-engine/src/render-worker/host-service-protocol.d.ts +756 -0
  294. package/dist-types/packages/peach-engine/src/render-worker/image-lifecycle-event.d.ts +22 -0
  295. package/dist-types/packages/peach-engine/src/render-worker/image-pixel-contract.d.ts +48 -0
  296. package/dist-types/packages/peach-engine/src/render-worker/live-frame-mirror.d.ts +34 -0
  297. package/dist-types/packages/peach-engine/src/render-worker/map-command-channel.d.ts +189 -0
  298. package/dist-types/packages/peach-engine/src/render-worker/mapNativeContract.d.ts +101 -0
  299. package/dist-types/packages/peach-engine/src/render-worker/native-dynamic-synchronizable.d.ts +22 -0
  300. package/dist-types/packages/peach-engine/src/render-worker/native-menu-gesture.d.ts +9 -0
  301. package/dist-types/packages/peach-engine/src/render-worker/native-ui-commandContract.d.ts +23 -0
  302. package/dist-types/packages/peach-engine/src/render-worker/native-ui-protocol.d.ts +1087 -0
  303. package/dist-types/packages/peach-engine/src/render-worker/native-widgetContract.d.ts +100 -0
  304. package/dist-types/packages/peach-engine/src/render-worker/nativeAnimMirrorContract.d.ts +174 -0
  305. package/dist-types/packages/peach-engine/src/render-worker/nativeSyncReplyContract.d.ts +11 -0
  306. package/dist-types/packages/peach-engine/src/render-worker/one-native-contentContract.d.ts +54 -0
  307. package/dist-types/packages/peach-engine/src/render-worker/pointerSampleContract.d.ts +14 -0
  308. package/dist-types/packages/peach-engine/src/render-worker/protocol.d.ts +880 -0
  309. package/dist-types/packages/peach-engine/src/render-worker/reanimated-css-contract.d.ts +63 -0
  310. package/dist-types/packages/peach-engine/src/render-worker/reanimated-readiness.d.ts +29 -0
  311. package/dist-types/packages/peach-engine/src/render-worker/resilient-frame-clock.d.ts +22 -0
  312. package/dist-types/packages/peach-engine/src/render-worker/retained-app-load.d.ts +20 -0
  313. package/dist-types/packages/peach-engine/src/render-worker/screen-edge-swipe-commit-protocol.d.ts +1 -0
  314. package/dist-types/packages/peach-engine/src/render-worker/screen-form-sheet-commit-protocol.d.ts +26 -0
  315. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror-tenant.d.ts +37 -0
  316. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror.d.ts +164 -0
  317. package/dist-types/packages/peach-engine/src/render-worker/shell-event-registry.d.ts +119 -0
  318. package/dist-types/packages/peach-engine/src/render-worker/shell-gesture-regions.d.ts +41 -0
  319. package/dist-types/packages/peach-engine/src/render-worker/shell-protocol.d.ts +603 -0
  320. package/dist-types/packages/peach-engine/src/render-worker/shell-scene-schema.d.ts +101 -0
  321. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-inline-sources.d.ts +13 -0
  322. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-wire.d.ts +87 -0
  323. package/dist-types/packages/peach-engine/src/render-worker/test-bridge-protocol.d.ts +47 -0
  324. package/dist-types/packages/peach-engine/src/render-worker/text-inputContract.d.ts +93 -0
  325. package/dist-types/packages/peach-engine/src/render-worker/tree-sync-port.d.ts +102 -0
  326. package/dist-types/packages/peach-engine/src/render-worker/webgpu-frame-transaction.d.ts +292 -0
  327. package/dist-types/packages/peach-engine/src/render-worker/webgpu-readback-scheduler.d.ts +107 -0
  328. package/dist-types/packages/peach-engine/src/render-worker/webview-capture-protocol.d.ts +16 -0
  329. package/dist-types/packages/peach-engine/src/render-worker/worker-input-runtime.d.ts +211 -0
  330. package/dist-types/packages/peach-engine/src/render-worker/worker-storage.d.ts +33 -0
  331. package/dist-types/packages/peach-engine/src/render-worker/worklet-runtime.d.ts +987 -0
  332. package/dist-types/packages/peach-engine/src/render-worker/worklet-sab.d.ts +24 -0
  333. package/dist-types/packages/peach-engine/src/rolldown-bundle-inventory.d.ts +84 -0
  334. package/dist-types/packages/peach-engine/src/rolldown-production-fingerprint.d.ts +31 -0
  335. package/dist-types/packages/peach-engine/src/screenshots/timeline-assets.d.ts +10 -0
  336. package/dist-types/packages/peach-engine/src/screenshots/tokens.d.ts +9 -0
  337. package/dist-types/packages/peach-engine/src/settings/devices.d.ts +70 -0
  338. package/dist-types/packages/peach-engine/src/settings/duo-fold-bus.d.ts +87 -0
  339. package/dist-types/packages/peach-engine/src/settings/interface-rotation.d.ts +30 -0
  340. package/dist-types/packages/peach-engine/src/settings/react-native-configuration.d.ts +12 -0
  341. package/dist-types/packages/peach-engine/src/settings/scene-geometryContract.d.ts +40 -0
  342. package/dist-types/packages/peach-engine/src/settings/store.d.ts +37 -0
  343. package/dist-types/packages/peach-engine/src/shell-events.d.ts +203 -0
  344. package/dist-types/packages/peach-engine/src/shell-intent.d.ts +68 -0
  345. package/dist-types/packages/peach-engine/src/sootsim-event.d.ts +35 -0
  346. package/dist-types/packages/peach-engine/src/top-overlay-state.d.ts +5 -0
  347. package/dist-types/packages/peach-engine/src/web-authentication-automation-host.d.ts +2 -0
  348. package/dist-types/packages/peach-engine/src/webAuthenticationContract.d.ts +34 -0
  349. package/dist-types/packages/peach-engine/src/webview-automation-host.d.ts +180 -0
  350. package/dist-types/packages/peach-engine/src/wireframe-mode.d.ts +16 -0
  351. package/dist-types/packages/peach-globals/src/frameBreakdownContract.d.ts +16 -0
  352. package/dist-types/packages/peach-globals/src/index.d.ts +3311 -0
  353. package/dist-types/packages/peach-globals/src/nativeSurfaceContract.d.ts +76 -0
  354. package/dist-types/packages/peach-globals/src/pointerSourceEventContract.d.ts +8 -0
  355. package/dist-types/packages/peach-globals/src/profileTrace.d.ts +11 -0
  356. package/dist-types/packages/peach-globals/src/profilerContract.d.ts +223 -0
  357. package/dist-types/packages/peach-kit/src/capabilities.d.ts +721 -0
  358. package/dist-types/packages/peach-kit/src/internal.d.ts +4 -0
  359. package/dist-types/packages/peach-kit/src/materials/types.d.ts +27 -0
  360. package/dist-types/packages/peach-kit/src/materials/uikit-blur-material.d.ts +14 -0
  361. package/dist-types/packages/peach-kit/src/navigation-types.d.ts +11 -0
  362. package/dist-types/packages/peach-kit/src/react-bridge.d.ts +53 -0
  363. package/dist-types/packages/peach-kit/src/runtime.d.ts +26 -0
  364. package/dist-types/packages/peach-kit/src/ui/hosting-safe-area.d.ts +24 -0
  365. package/dist-types/packages/peach-kit/src/ui/popover-placement.d.ts +53 -0
  366. package/dist-types/packages/peach-kit/src/ui/presentationContract.d.ts +17 -0
  367. package/kotlin/ComposeSources/PeachComposeHost.kt +1 -1
  368. package/kotlin/JniSources/com/facebook/jni/HybridData.kt +0 -2
  369. package/kotlin/JniSources/dev/peach/jni/NativeBindings.kt +0 -2
  370. package/kotlin/JniTransportSources/dev/peach/jni/integration/JniTransport.kt +0 -2
  371. package/kotlin/README.md +6 -0
  372. package/package.json +22 -2
  373. package/runtime-companion.json +1 -0
  374. package/skills/contrast/SKILL.md +1 -0
  375. package/src/assetCatalogContract.ts +21 -0
  376. package/src/bridge-contract-input.ts +84 -0
  377. package/src/bridge-contract.ts +35 -3
  378. package/src/browser-launch-policy.ts +1 -0
  379. package/src/bundle-channel.mjs +4 -2
  380. package/src/cli-runtime.ts +55 -0
  381. package/src/crash-fingerprint.ts +26 -0
  382. package/src/dev-bundle-resolution.ts +50 -23
  383. package/src/device-catalog.ts +1159 -0
  384. package/src/host/bridge-host.ts +3 -26
  385. package/src/host/browser-pointer.ts +71 -0
  386. package/src/host/dev-server-package-versions.ts +23 -0
  387. package/src/host/fetch-proxy-handler.ts +17 -4
  388. package/src/installed-package-versions.ts +142 -38
  389. package/src/kotlin-host.ts +1 -1
  390. package/src/metro-plugin.ts +4 -4
  391. package/src/metro-project-root.ts +68 -0
  392. package/src/nitro-adapter.lock.json +26 -0
  393. package/src/nitro-adapter.ts +103 -0
  394. package/src/nitro-bundle.ts +24 -10
  395. package/src/nitro-compile.ts +33 -51
  396. package/src/nitro-source.ts +177 -96
  397. package/src/nitroAdapterContract.ts +217 -0
  398. package/src/nitroContract.ts +24 -11
  399. package/src/process-group.ts +41 -34
  400. package/src/react-bridge-importers.ts +28 -0
  401. package/src/reactNativeConfigurationContract.ts +36 -0
  402. package/src/runtime-assets.ts +7 -2
  403. package/src/runtime-delivery.ts +2 -0
  404. package/src/runtimePlatformContract.ts +70 -0
  405. package/src/screenshots/frame-compose.ts +42 -43
  406. package/src/screenshots/org-deck.ts +9 -4
  407. package/src/screenshots/preset-names.ts +29 -0
  408. package/src/screenshots/registry.ts +5 -5
  409. package/src/screenshots/schema.ts +1 -1
  410. package/src/screenshots/screenshotContract.ts +971 -0
  411. package/src/settings-flags.ts +107 -0
  412. package/src/settingsContract.ts +609 -0
  413. package/src/storageSnapshotContract.ts +344 -0
  414. package/src/stub-pattern-matcher.ts +550 -0
  415. package/src/swift-compile.ts +908 -40
  416. package/src/swift-compiler-digest.ts +13 -1
  417. package/src/swift-distribution.lock.json +49 -22
  418. package/src/swift-host.ts +167 -52
  419. package/src/swift-objc-compile.ts +54 -24
  420. package/src/swift-objc-export.ts +532 -0
  421. package/src/swift-objc-import.ts +769 -0
  422. package/src/swift-objc-metadata.ts +285 -10
  423. package/src/swift-objc-sdk.ts +13970 -158
  424. package/src/swift-objc-standin.ts +137 -1
  425. package/src/swift-package.ts +94 -0
  426. package/src/swift-packages.ts +5 -5
  427. package/src/swift-submit.ts +6 -0
  428. package/src/swiftContract.ts +99 -0
  429. package/src/target-matcher.ts +6 -1
  430. package/src/vite-plugin.ts +14 -40
  431. package/src/worker-system-chunks.ts +1 -1
  432. package/src/workerChunkContract.ts +5 -0
  433. package/src/worklets-babel.ts +24 -5
  434. package/src/xcode-project.ts +36 -7
  435. package/src/xcode-target-members.ts +10 -3
  436. package/cli/drivers/playwright-sim-host.ts +0 -825
  437. package/kotlin/fixtures/counter/Counter.d.kt.ts +0 -17
  438. package/kotlin/fixtures/counter/Counter.kt +0 -51
  439. package/kotlin/fixtures/counter/CounterApp.native.tsx +0 -61
  440. package/kotlin/fixtures/counter/CounterApp.tsx +0 -3
  441. package/kotlin/fixtures/counter/CounterScreen.d.kt.ts +0 -8
  442. package/kotlin/fixtures/counter/CounterScreen.kt +0 -56
  443. package/kotlin/fixtures/counter/app/_layout.tsx +0 -4
  444. package/kotlin/fixtures/counter/app/index+spa.tsx +0 -1
  445. package/kotlin/fixtures/counter/app/routes.d.ts +0 -18
  446. package/kotlin/fixtures/counter/package.json +0 -20
  447. package/kotlin/fixtures/counter/tsconfig.json +0 -19
  448. package/kotlin/fixtures/counter/vite.config.ts +0 -20
  449. package/kotlin/fixtures/headless-counter/Headless.kt +0 -234
  450. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +0 -7
  451. package/kotlin/fixtures/import-animation/Animation.kt +0 -80
  452. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +0 -13
  453. package/kotlin/fixtures/import-animation/README.md +0 -24
  454. package/kotlin/fixtures/import-animation/app/_layout.tsx +0 -4
  455. package/kotlin/fixtures/import-animation/app/index+spa.tsx +0 -1
  456. package/kotlin/fixtures/import-animation/app/routes.d.ts +0 -18
  457. package/kotlin/fixtures/import-animation/package.json +0 -23
  458. package/kotlin/fixtures/import-animation/tsconfig.json +0 -20
  459. package/kotlin/fixtures/import-animation/vite.config.ts +0 -20
  460. package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +0 -7
  461. package/kotlin/fixtures/import-drawing/Drawing.kt +0 -101
  462. package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +0 -18
  463. package/kotlin/fixtures/import-drawing/README.md +0 -34
  464. package/kotlin/fixtures/import-drawing/app/_layout.tsx +0 -4
  465. package/kotlin/fixtures/import-drawing/app/index+spa.tsx +0 -1
  466. package/kotlin/fixtures/import-drawing/package.json +0 -23
  467. package/kotlin/fixtures/import-drawing/tsconfig.json +0 -20
  468. package/kotlin/fixtures/import-drawing/vite.config.ts +0 -20
  469. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +0 -7
  470. package/kotlin/fixtures/import-editor/Editor.kt +0 -59
  471. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +0 -23
  472. package/kotlin/fixtures/import-editor/README.md +0 -27
  473. package/kotlin/fixtures/import-editor/app/_layout.tsx +0 -4
  474. package/kotlin/fixtures/import-editor/app/index+spa.tsx +0 -1
  475. package/kotlin/fixtures/import-editor/package.json +0 -23
  476. package/kotlin/fixtures/import-editor/tsconfig.json +0 -20
  477. package/kotlin/fixtures/import-editor/vite.config.ts +0 -20
  478. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +0 -7
  479. package/kotlin/fixtures/import-effects/Effects.kt +0 -87
  480. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +0 -13
  481. package/kotlin/fixtures/import-effects/README.md +0 -19
  482. package/kotlin/fixtures/import-effects/app/_layout.tsx +0 -4
  483. package/kotlin/fixtures/import-effects/app/index+spa.tsx +0 -1
  484. package/kotlin/fixtures/import-effects/package.json +0 -23
  485. package/kotlin/fixtures/import-effects/tsconfig.json +0 -20
  486. package/kotlin/fixtures/import-effects/vite.config.ts +0 -20
  487. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +0 -13
  488. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +0 -7
  489. package/kotlin/fixtures/import-layout/Layout.kt +0 -72
  490. package/kotlin/fixtures/import-layout/README.md +0 -24
  491. package/kotlin/fixtures/import-layout/app/_layout.tsx +0 -4
  492. package/kotlin/fixtures/import-layout/app/index+spa.tsx +0 -1
  493. package/kotlin/fixtures/import-layout/package.json +0 -23
  494. package/kotlin/fixtures/import-layout/tsconfig.json +0 -20
  495. package/kotlin/fixtures/import-layout/vite.config.ts +0 -20
  496. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +0 -18
  497. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +0 -7
  498. package/kotlin/fixtures/import-navigation/Navigation.kt +0 -104
  499. package/kotlin/fixtures/import-navigation/README.md +0 -31
  500. package/kotlin/fixtures/import-navigation/app/_layout.tsx +0 -4
  501. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +0 -1
  502. package/kotlin/fixtures/import-navigation/package.json +0 -23
  503. package/kotlin/fixtures/import-navigation/tsconfig.json +0 -20
  504. package/kotlin/fixtures/import-navigation/vite.config.ts +0 -20
  505. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +0 -29
  506. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +0 -7
  507. package/kotlin/fixtures/import-overlays/Overlays.kt +0 -93
  508. package/kotlin/fixtures/import-overlays/README.md +0 -34
  509. package/kotlin/fixtures/import-overlays/app/_layout.tsx +0 -4
  510. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +0 -1
  511. package/kotlin/fixtures/import-overlays/package.json +0 -23
  512. package/kotlin/fixtures/import-overlays/tsconfig.json +0 -20
  513. package/kotlin/fixtures/import-overlays/vite.config.ts +0 -20
  514. package/kotlin/fixtures/import-resources/ImportResources.native.tsx +0 -18
  515. package/kotlin/fixtures/import-resources/README.md +0 -26
  516. package/kotlin/fixtures/import-resources/Resources.d.kt.ts +0 -6
  517. package/kotlin/fixtures/import-resources/Resources.kt +0 -72
  518. package/kotlin/fixtures/import-resources/app/_layout.tsx +0 -4
  519. package/kotlin/fixtures/import-resources/app/index+spa.tsx +0 -1
  520. package/kotlin/fixtures/import-resources/package.json +0 -23
  521. package/kotlin/fixtures/import-resources/tsconfig.json +0 -20
  522. package/kotlin/fixtures/import-resources/vite.config.ts +0 -20
  523. package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +0 -10
  524. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +0 -13
  525. package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +0 -4
  526. package/kotlin/fixtures/import-scroll/Nested.kt +0 -64
  527. package/kotlin/fixtures/import-scroll/README.md +0 -38
  528. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +0 -7
  529. package/kotlin/fixtures/import-scroll/Scroll.kt +0 -91
  530. package/kotlin/fixtures/import-scroll/app/_layout.tsx +0 -4
  531. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +0 -1
  532. package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +0 -1
  533. package/kotlin/fixtures/import-scroll/package.json +0 -23
  534. package/kotlin/fixtures/import-scroll/tsconfig.json +0 -20
  535. package/kotlin/fixtures/import-scroll/vite.config.ts +0 -20
  536. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +0 -44
  537. package/kotlin/fixtures/import-selection/README.md +0 -32
  538. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +0 -8
  539. package/kotlin/fixtures/import-selection/Selection.kt +0 -78
  540. package/kotlin/fixtures/import-selection/app/_layout.tsx +0 -4
  541. package/kotlin/fixtures/import-selection/app/index+spa.tsx +0 -1
  542. package/kotlin/fixtures/import-selection/package.json +0 -23
  543. package/kotlin/fixtures/import-selection/tsconfig.json +0 -20
  544. package/kotlin/fixtures/import-selection/vite.config.ts +0 -20
  545. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +0 -13
  546. package/kotlin/fixtures/import-surfaces/README.md +0 -22
  547. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +0 -7
  548. package/kotlin/fixtures/import-surfaces/Surfaces.kt +0 -64
  549. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +0 -4
  550. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +0 -1
  551. package/kotlin/fixtures/import-surfaces/package.json +0 -23
  552. package/kotlin/fixtures/import-surfaces/tsconfig.json +0 -20
  553. package/kotlin/fixtures/import-surfaces/vite.config.ts +0 -20
  554. package/kotlin/fixtures/import-values/ImportValues.native.tsx +0 -61
  555. package/kotlin/fixtures/import-values/README.md +0 -28
  556. package/kotlin/fixtures/import-values/Values.d.kt.ts +0 -15
  557. package/kotlin/fixtures/import-values/Values.kt +0 -84
  558. package/kotlin/fixtures/import-values/app/_layout.tsx +0 -4
  559. package/kotlin/fixtures/import-values/app/index+spa.tsx +0 -1
  560. package/kotlin/fixtures/import-values/package.json +0 -23
  561. package/kotlin/fixtures/import-values/tsconfig.json +0 -20
  562. package/kotlin/fixtures/import-values/vite.config.ts +0 -20
  563. package/kotlin/fixtures/kotlin-app/app/build.gradle.kts +0 -30
  564. package/kotlin/fixtures/kotlin-app/app/src/main/AndroidManifest.xml +0 -13
  565. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/MainActivity.kt +0 -60
  566. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/ProbeApplication.kt +0 -18
  567. package/kotlin/fixtures/kotlin-app/build.gradle.kts +0 -5
  568. package/kotlin/fixtures/kotlin-app/gradle.properties +0 -4
  569. package/kotlin/fixtures/kotlin-app/settings.gradle.kts +0 -4
  570. package/kotlin/fixtures/kotlin-app-variants/Anim.kt +0 -62
  571. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +0 -38
  572. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +0 -36
  573. package/kotlin/fixtures/kotlin-app-variants/Bitmaps.kt +0 -50
  574. package/kotlin/fixtures/kotlin-app-variants/Browse.kt +0 -73
  575. package/kotlin/fixtures/kotlin-app-variants/Colors.kt +0 -41
  576. package/kotlin/fixtures/kotlin-app-variants/Controls.kt +0 -62
  577. package/kotlin/fixtures/kotlin-app-variants/Drag.kt +0 -56
  578. package/kotlin/fixtures/kotlin-app-variants/Draw.kt +0 -74
  579. package/kotlin/fixtures/kotlin-app-variants/Drawables.kt +0 -53
  580. package/kotlin/fixtures/kotlin-app-variants/Focus.kt +0 -62
  581. package/kotlin/fixtures/kotlin-app-variants/Form.kt +0 -47
  582. package/kotlin/fixtures/kotlin-app-variants/Icons.kt +0 -59
  583. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +0 -53
  584. package/kotlin/fixtures/kotlin-app-variants/Lists.kt +0 -57
  585. package/kotlin/fixtures/kotlin-app-variants/Nav.kt +0 -47
  586. package/kotlin/fixtures/kotlin-app-variants/Note.kt +0 -40
  587. package/kotlin/fixtures/kotlin-app-variants/Overlays.kt +0 -56
  588. package/kotlin/fixtures/kotlin-app-variants/Pan.kt +0 -38
  589. package/kotlin/fixtures/kotlin-app-variants/Pickers.kt +0 -44
  590. package/kotlin/fixtures/kotlin-app-variants/Press.kt +0 -43
  591. package/kotlin/fixtures/kotlin-app-variants/Scroll.kt +0 -63
  592. package/kotlin/fixtures/kotlin-app-variants/Sheet.kt +0 -43
  593. package/kotlin/fixtures/kotlin-app-variants/Strings.kt +0 -49
  594. package/kotlin/fixtures/kotlin-app-variants/Tabs.kt +0 -47
  595. package/kotlin/fixtures/kotlin-app-variants/TextWidth.kt +0 -45
  596. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +0 -50
  597. package/kotlin/fixtures/kotlin-app-variants/Transition.kt +0 -69
  598. package/kotlin/fixtures/kotlin-app-variants/ViewConfig.kt +0 -22
  599. package/kotlin/fixtures/kotlin-app-variants/Widgets.kt +0 -67
  600. package/kotlin/fixtures/runtime-state/RuntimeState.kt +0 -200
  601. package/kotlin/fork/README.md +0 -97
  602. package/kotlin/fork/build.sh +0 -176
  603. package/kotlin/fork/compose-worker-globals.patch +0 -1247
  604. package/kotlin/fork/fork.json +0 -46
  605. package/kotlin/fork/publish.ts +0 -99
  606. package/kotlin/fork/skia-android-shaping.patch +0 -189
  607. package/kotlin/fork/skiko-local.init.gradle +0 -10
  608. package/kotlin/fork/skiko-worker-clock.patch +0 -122
@@ -0,0 +1,971 @@
1
+ import { isRecord } from '../is-record.ts'
2
+ import {
3
+ BACKGROUND_PRESET_NAMES,
4
+ POSE_PRESET_NAMES,
5
+ SCREENSHOT_CANVAS_NAMES,
6
+ TEXT_PRESET_NAMES,
7
+ type BackgroundPresetName,
8
+ type PosePresetName,
9
+ type ScreenshotCanvasName,
10
+ type TextPresetName,
11
+ } from './preset-names.ts'
12
+ import type { DeviceModel } from '../device-catalog.ts'
13
+
14
+ export {
15
+ BACKGROUND_PRESET_NAMES,
16
+ POSE_PRESET_NAMES,
17
+ SCREENSHOT_CANVAS_NAMES,
18
+ TEXT_PRESET_NAMES,
19
+ type BackgroundPresetName,
20
+ type PosePresetName,
21
+ type ScreenshotCanvasName,
22
+ type TextPresetName,
23
+ }
24
+
25
+ // shared serialized scene contract, also used by the optional 3d renderer.
26
+ export const THREE_MODE_SETTING_IDS = [
27
+ 'none',
28
+ 'room',
29
+ 'window-wall',
30
+ 'white-backdrop',
31
+ 'cyclorama',
32
+ 'terrain',
33
+ ] as const
34
+
35
+ export type ThreeModeSetting = (typeof THREE_MODE_SETTING_IDS)[number]
36
+
37
+ export const THREE_WINDOW_LIGHT_OFFSET_RANGE: readonly [number, number] = [-3, 3]
38
+
39
+ export function isThreeModeSetting(value: unknown): value is ThreeModeSetting {
40
+ return typeof value === 'string' && THREE_MODE_SETTING_IDS.some((id) => id === value)
41
+ }
42
+
43
+ export interface CanvasPreset {
44
+ name: ScreenshotCanvasName
45
+ label: string
46
+ width: number
47
+ height: number
48
+ store: 'apple' | 'google'
49
+ deviceModel?: DeviceModel
50
+ }
51
+
52
+ export interface GradientStop {
53
+ offset: number
54
+ color: string
55
+ }
56
+
57
+ export interface BackgroundSpec {
58
+ type: 'solid' | 'gradient'
59
+ color?: string
60
+ direction?: number
61
+ stops?: GradientStop[]
62
+ glow?: string
63
+ }
64
+
65
+ export interface FrameShadowSpec {
66
+ color: string
67
+ blur: number
68
+ spread: number
69
+ opacity: number
70
+ }
71
+
72
+ export const SCREENSHOT_CANVASES: Record<ScreenshotCanvasName, CanvasPreset> = {
73
+ 'iphone-6-9': {
74
+ name: 'iphone-6-9',
75
+ label: 'iPhone 6.7"',
76
+ width: 1284,
77
+ height: 2778,
78
+ store: 'apple',
79
+ },
80
+ 'iphone-6-1': {
81
+ name: 'iphone-6-1',
82
+ label: 'iPhone 6.5"',
83
+ width: 1242,
84
+ height: 2688,
85
+ store: 'apple',
86
+ },
87
+ 'ipad-pro-13': {
88
+ name: 'ipad-pro-13',
89
+ label: 'iPad Pro 13-inch',
90
+ width: 2064,
91
+ height: 2752,
92
+ store: 'apple',
93
+ deviceModel: 'ipad-pro-13',
94
+ },
95
+ 'android-phone': {
96
+ name: 'android-phone',
97
+ label: 'Google Play phone',
98
+ width: 1080,
99
+ height: 1920,
100
+ store: 'google',
101
+ },
102
+ 'android-tablet-7': {
103
+ name: 'android-tablet-7',
104
+ label: 'Google Play 7" tablet',
105
+ width: 1200,
106
+ height: 1920,
107
+ store: 'google',
108
+ },
109
+ 'android-tablet-10': {
110
+ name: 'android-tablet-10',
111
+ label: 'Google Play 10" tablet',
112
+ width: 1600,
113
+ height: 2560,
114
+ store: 'google',
115
+ },
116
+ }
117
+
118
+ export const BACKGROUND_PRESETS: Record<BackgroundPresetName, BackgroundSpec> = {
119
+ dark: {
120
+ type: 'gradient',
121
+ direction: 180,
122
+ glow: '#4caeff',
123
+ stops: [
124
+ { offset: 0, color: '#111827' },
125
+ { offset: 40, color: '#101725' },
126
+ { offset: 100, color: '#06080d' },
127
+ ],
128
+ },
129
+ cyan: {
130
+ type: 'gradient',
131
+ direction: 180,
132
+ glow: '#25c3ec',
133
+ stops: [
134
+ { offset: 0, color: '#1b465c' },
135
+ { offset: 32, color: '#122336' },
136
+ { offset: 100, color: '#05070b' },
137
+ ],
138
+ },
139
+ gold: {
140
+ type: 'gradient',
141
+ direction: 180,
142
+ glow: '#ffc25a',
143
+ stops: [
144
+ { offset: 0, color: '#3b2f1a' },
145
+ { offset: 34, color: '#18140d' },
146
+ { offset: 100, color: '#050505' },
147
+ ],
148
+ },
149
+ red: {
150
+ type: 'gradient',
151
+ direction: 180,
152
+ glow: '#ff6178',
153
+ stops: [
154
+ { offset: 0, color: '#3e1018' },
155
+ { offset: 35, color: '#17080c' },
156
+ { offset: 100, color: '#050405' },
157
+ ],
158
+ },
159
+ }
160
+
161
+ export const DEFAULT_FRAME_SHADOW: FrameShadowSpec = {
162
+ color: '#25c3ec',
163
+ blur: 120,
164
+ spread: 52,
165
+ opacity: 0.34,
166
+ }
167
+
168
+ export const DEFAULT_FRAME_STYLE: DeviceModel = 'iphone-17-pro'
169
+
170
+ // stage / canvas-rect FLIP animation. used by DeviceFrame.tsx for the live
171
+ // stage tween and by the composer's compose.ts for parity.
172
+ export const SCREENSHOT_MODE_ANIM = {
173
+ durationMs: 250,
174
+ easing: 'cubic-bezier(0.22, 1, 0.36, 1)',
175
+ } as const
176
+
177
+ // css clamp() rules for text layers. live mode uses container queries keyed
178
+ // off the floating canvas rect; the composer writes the same clamp() rules
179
+ // in its exported html so the two painters render matching headlines at
180
+ // matching canvas sizes.
181
+ export const SCREENSHOT_TEXT_CLAMP = {
182
+ headline: 'clamp(2rem, 5.6cqi, 5.5rem)',
183
+ subhead: 'clamp(1rem, 2.4cqi, 2.25rem)',
184
+ } as const
185
+
186
+ // safe-area percentages inside the canvas rect — reserves headroom and side
187
+ // padding for the text layer so the device frame never crowds the edges.
188
+ export const SCREENSHOT_TEXT_SAFE_AREA = {
189
+ topPct: 8,
190
+ sidePct: 7,
191
+ bottomGapPct: 4,
192
+ } as const
193
+
194
+ // ─── screenshot project config (live multi-frame mode) ───────────────────
195
+ //
196
+ // a project carries one screenshot composition: a target store/canvas
197
+ // preset, the device to pose, and an ordered list of frame slides. each
198
+ // slide owns its own copy/theme/pose so the App-Store strip can show
199
+ // different posed screens side by side. the closed plugin-screenshot owns
200
+ // the visual mapping for ScreenshotThemeName; the name union lives here so
201
+ // the engine projects store can persist it without importing the plugin.
202
+
203
+ // the background is a two-stop vertical gradient: the user picks a top
204
+ // color and a bottom color independently (two flyouts in the rail). the
205
+ // palette includes white + a grey ramp so a screenshot can stay basically
206
+ // grey, plus the brand hues.
207
+ export type ScreenshotBgColorName =
208
+ | 'white'
209
+ | 'gray-light'
210
+ | 'gray'
211
+ | 'gray-dark'
212
+ | 'slate'
213
+ | 'black'
214
+ | 'cyan'
215
+ | 'blue'
216
+ | 'teal'
217
+ | 'green'
218
+ | 'lime'
219
+ | 'gold'
220
+ | 'orange'
221
+ | 'coral'
222
+ | 'red'
223
+ | 'berry'
224
+ | 'magenta'
225
+
226
+ export interface ScreenshotBgColor {
227
+ name: ScreenshotBgColorName
228
+ value: string
229
+ }
230
+
231
+ export const SCREENSHOT_BG_COLORS: ScreenshotBgColor[] = [
232
+ { name: 'white', value: '#ffffff' },
233
+ { name: 'gray-light', value: '#d1d5db' },
234
+ { name: 'gray', value: '#6b7280' },
235
+ { name: 'gray-dark', value: '#3b4350' },
236
+ { name: 'slate', value: '#2a3644' },
237
+ { name: 'black', value: '#000000' },
238
+ { name: 'cyan', value: '#25c3ec' },
239
+ { name: 'blue', value: '#3f7cff' },
240
+ { name: 'teal', value: '#1fc7b4' },
241
+ { name: 'green', value: '#42c95d' },
242
+ { name: 'lime', value: '#92d21b' },
243
+ { name: 'gold', value: '#f5c518' },
244
+ { name: 'orange', value: '#ff912e' },
245
+ { name: 'coral', value: '#ff6f5b' },
246
+ { name: 'red', value: '#ff4f6f' },
247
+ { name: 'berry', value: '#d054ff' },
248
+ { name: 'magenta', value: '#ff4eb8' },
249
+ ]
250
+
251
+ const BG_COLOR_MAP: Record<string, string> = Object.fromEntries(
252
+ SCREENSHOT_BG_COLORS.map((c) => [c.name, c.value]),
253
+ )
254
+
255
+ export function resolveBgColorValue(name: string): string {
256
+ return BG_COLOR_MAP[name] ?? BG_COLOR_MAP.gray
257
+ }
258
+
259
+ export interface ScreenshotBackgroundStyles {
260
+ background: string
261
+ foreground: string
262
+ eyebrow: string
263
+ subtitle: string
264
+ placeholder: string
265
+ }
266
+
267
+ export const DEFAULT_BG_TOP: ScreenshotBgColorName = 'gray'
268
+
269
+ export const DEFAULT_BG_BOTTOM: ScreenshotBgColorName = 'gray-dark'
270
+
271
+ // per-slide persistence of the 3d composition state (camera pose, scene
272
+ // look, env state) so a slide captured in 3d can re-open into the same
273
+ // scene. `null` titleColor means "auto contrast against bgTop" (the
274
+ // historical behavior); any palette name overrides.
275
+ // the operator's grade over the finished frame, as serializable ids. this is
276
+ // the one definition of the grade's shape: the 3d mode's own ThreeGradeState
277
+ // is this type, and the renderer maps each id to its number. It lives here
278
+ // because the plugins depend on the engine and not the other way round.
279
+ export interface ScreenshotThreeGrade {
280
+ contrast: 'low' | 'neutral' | 'high' | 'max'
281
+ saturation: 'low' | 'neutral' | 'high' | 'max'
282
+ brightness: 'low' | 'neutral' | 'high'
283
+ blackPoint: 'lifted' | 'neutral' | 'deep' | 'crushed'
284
+ grain: 'off' | 'subtle' | 'strong'
285
+ }
286
+
287
+ export const SCREENSHOT_THREE_GRADE_IDS: {
288
+ [K in keyof ScreenshotThreeGrade]: readonly ScreenshotThreeGrade[K][]
289
+ } = {
290
+ contrast: ['low', 'neutral', 'high', 'max'],
291
+ saturation: ['low', 'neutral', 'high', 'max'],
292
+ brightness: ['low', 'neutral', 'high'],
293
+ blackPoint: ['lifted', 'neutral', 'deep', 'crushed'],
294
+ grain: ['off', 'subtle', 'strong'],
295
+ }
296
+
297
+ // identity. a restored slide that saved no grade is put back onto this rather
298
+ // than left on whatever the previous slide was graded to.
299
+ export const SCREENSHOT_THREE_GRADE_DEFAULT: ScreenshotThreeGrade = {
300
+ contrast: 'neutral',
301
+ saturation: 'neutral',
302
+ brightness: 'neutral',
303
+ blackPoint: 'neutral',
304
+ grain: 'off',
305
+ }
306
+
307
+ // the Cyclorama setting's light rig and sweep. angles are degrees, sweepMs is
308
+ // authored timeline time, curveRadius and shadowSoftness are fractions of the
309
+ // device's longest side. Same ownership reason as the grade above.
310
+ export interface ScreenshotThreeCyclorama {
311
+ keyAzimuthDeg: number
312
+ keyElevationDeg: number
313
+ keyRiseDeg: number
314
+ sweepMs: number
315
+ keyIntensity: number
316
+ warmIntensity: number
317
+ coolIntensity: number
318
+ curveRadius: number
319
+ shadowSoftness: number
320
+ // the two tints the operator picks. warmColor drives the warm contribution
321
+ // and coolColor the cool one, each carried by its existing intensity field.
322
+ warmColor: string
323
+ coolColor: string
324
+ warmColorEnd: string | null
325
+ coolColorEnd: string | null
326
+ }
327
+
328
+ // the two colors are authored as strings, so the numeric ranges cover the
329
+ // numeric fields only rather than widening to a union nothing can clamp.
330
+ type ScreenshotThreeCycloramaNumericKey = {
331
+ [K in keyof ScreenshotThreeCyclorama]: ScreenshotThreeCyclorama[K] extends number
332
+ ? K
333
+ : never
334
+ }[keyof ScreenshotThreeCyclorama]
335
+
336
+ export const SCREENSHOT_THREE_CYCLORAMA_RANGES: {
337
+ [K in ScreenshotThreeCycloramaNumericKey]: readonly [number, number]
338
+ } = {
339
+ keyAzimuthDeg: [-360, 360],
340
+ keyElevationDeg: [1, 89],
341
+ keyRiseDeg: [1, 89],
342
+ sweepMs: [0, 600_000],
343
+ keyIntensity: [0, 40],
344
+ warmIntensity: [0, 40],
345
+ coolIntensity: [0, 40],
346
+ curveRadius: [0.05, 6],
347
+ shadowSoftness: [0, 0.5],
348
+ }
349
+
350
+ // the rig a Cyclorama slide opens on, calibrated against the rendered frame.
351
+ export const SCREENSHOT_THREE_CYCLORAMA_DEFAULT: ScreenshotThreeCyclorama = {
352
+ keyAzimuthDeg: 23.55,
353
+ keyElevationDeg: 59.7,
354
+ keyRiseDeg: 62.2,
355
+ sweepMs: 0,
356
+ keyIntensity: 3,
357
+ warmIntensity: 0.9,
358
+ coolIntensity: 1.1,
359
+ curveRadius: 0.08,
360
+ shadowSoftness: 0.06,
361
+ warmColor: '#ffcb12',
362
+ coolColor: '#2879ff',
363
+ warmColorEnd: null,
364
+ coolColorEnd: null,
365
+ }
366
+
367
+ // six-digit #RRGGBB only. a three-digit or named color parses differently in
368
+ // the picker, the film validator and the renderer's color conversion, so the
369
+ // one spelling every owner agrees on is the only one accepted.
370
+ const SCREENSHOT_THREE_CYCLORAMA_COLOR_KEY_SET: ReadonlySet<string> = new Set([
371
+ 'warmColor',
372
+ 'coolColor',
373
+ 'warmColorEnd',
374
+ 'coolColorEnd',
375
+ ])
376
+
377
+ const SCREENSHOT_THREE_CYCLORAMA_COLOR_PATTERN = /^#[0-9a-fA-F]{6}$/
378
+
379
+ export function isScreenshotThreeCycloramaColorKey(
380
+ key: string,
381
+ ): key is 'warmColor' | 'coolColor' | 'warmColorEnd' | 'coolColorEnd' {
382
+ return SCREENSHOT_THREE_CYCLORAMA_COLOR_KEY_SET.has(key)
383
+ }
384
+
385
+ export function isScreenshotThreeCycloramaColor(value: unknown): value is string {
386
+ return typeof value === 'string' && SCREENSHOT_THREE_CYCLORAMA_COLOR_PATTERN.test(value)
387
+ }
388
+
389
+ // null holds the starting tint throughout an authored sweep.
390
+ export function normalizeScreenshotThreeCycloramaEndColor(
391
+ value: unknown,
392
+ base: string | null = null,
393
+ ): string | null {
394
+ return value === null
395
+ ? null
396
+ : isScreenshotThreeCycloramaColor(value)
397
+ ? value.toLowerCase()
398
+ : base
399
+ }
400
+
401
+ /**
402
+ * The one place a cyclorama tint is turned into state. Anything that is not a
403
+ * six-digit hex takes the fallback rather than reaching the renderer, and a
404
+ * valid one is lower-cased so the picker, a saved slide and an authored film
405
+ * all hold the same spelling.
406
+ */
407
+ export function normalizeScreenshotThreeCycloramaColor(
408
+ value: unknown,
409
+ fallback: string,
410
+ ): string {
411
+ return isScreenshotThreeCycloramaColor(value) ? value.toLowerCase() : fallback
412
+ }
413
+
414
+ export interface ScreenshotThreeAppearance extends Record<string, unknown> {
415
+ caseStyle?: 'standard' | 'edge-to-edge'
416
+ grade?: ScreenshotThreeGrade
417
+ cyclorama?: ScreenshotThreeCyclorama
418
+ }
419
+
420
+ export interface ScreenshotThreeScene {
421
+ device: 'iphone-17-air' | 'iphone-17-pro' | 'pixel-10'
422
+ // [x, y, z]
423
+ cameraPosition: [number, number, number]
424
+ cameraUp?: [number, number, number]
425
+ // orbit-controls target the camera looks at
426
+ target: [number, number, number]
427
+ // phone model transform
428
+ phonePosition: [number, number, number]
429
+ phoneRotation: [number, number, number]
430
+ colorway: string
431
+ background: string
432
+ // custom gradient override (caller color stops). when present it takes
433
+ // precedence over `background` so the deck's shared brand palette is
434
+ // restored on re-open instead of the named preset.
435
+ customGradient?: {
436
+ stops: { offset: number; color: string }[]
437
+ angleDeg?: number
438
+ } | null
439
+ // ids follow the shared serialized contract; appearance is renderer-owned.
440
+ setting: ThreeModeSetting
441
+ appearance?: ScreenshotThreeAppearance
442
+ focus?: Record<string, string | boolean | null | undefined> | null
443
+ // env state. shape mirrors the bridge — kept as serializable plain
444
+ // objects, normalized at apply time.
445
+ environmentActive: boolean
446
+ environmentPins?: Record<string, string | null | undefined>
447
+ environmentEffects?: Record<string, boolean>
448
+ }
449
+
450
+ export type TitleSize = 'sm' | 'md' | 'lg'
451
+
452
+ export type TitleUnderlay = 'black' | 'white'
453
+
454
+ export type TitleShadow = 'light' | 'medium' | 'strong'
455
+
456
+ export type ScreenshotTextAlign = 'left' | 'center' | 'right'
457
+
458
+ export interface ScreenshotFontChoice {
459
+ family: string
460
+ }
461
+
462
+ export interface ScreenshotTextPosition {
463
+ // normalized canvas coordinates for the text block's aligned top anchor.
464
+ x: number
465
+ y: number
466
+ }
467
+
468
+ export interface ScreenshotImageLayer {
469
+ // ref into the same capture store used by screen/capture/clean layers.
470
+ ref: string
471
+ // normalized canvas coordinates for the image center.
472
+ x: number
473
+ y: number
474
+ // rendered image width as a fraction of the canvas width.
475
+ scale: number
476
+ // clockwise rotation in degrees.
477
+ rotation: number
478
+ }
479
+
480
+ export interface ScreenshotPhone2DTransform {
481
+ // percentage of the phone silhouette width.
482
+ x: number
483
+ // percentage of the phone silhouette height.
484
+ y: number
485
+ deg: number
486
+ scale: number
487
+ }
488
+
489
+ export const DEFAULT_PHONE_2D_TRANSFORM: ScreenshotPhone2DTransform = {
490
+ x: 0,
491
+ y: 0,
492
+ deg: 0,
493
+ scale: 1,
494
+ }
495
+
496
+ export const PHONE_2D_TRANSFORM_LIMITS = {
497
+ x: { min: -32, max: 32, step: 1 },
498
+ y: { min: -32, max: 32, step: 1 },
499
+ deg: { min: -18, max: 18, step: 1 },
500
+ scale: { min: 0.72, max: 1.28, step: 0.01 },
501
+ }
502
+
503
+ export interface ScreenshotSlide {
504
+ id: string
505
+ title: string
506
+ subtitle: string
507
+ bgTop: ScreenshotBgColorName
508
+ bgBottom: ScreenshotBgColorName
509
+ pose: PosePresetName
510
+ // override for the title/subtitle copy color. when undefined, copy
511
+ // contrast is derived automatically from bgTop. used by the rail's
512
+ // text-color picker so a designer can pin "white text on a light bg"
513
+ // intentionally, including in 3d mode where bgTop isn't the painted bg.
514
+ titleColor?: ScreenshotBgColorName
515
+ // type-scale preset for the title block (subtitle scales with it).
516
+ // undefined → 'md' default, same point size the rail shipped at.
517
+ titleSize?: TitleSize
518
+ // optional gradient underlay painted behind the title text — solid at
519
+ // the top of the slide, fading to transparent ~100px below the title.
520
+ // designed for 3d-mode shots where the live backdrop can be busy and
521
+ // copy needs a guaranteed legibility floor; in 2d mode it's purely
522
+ // stylistic. undefined → no underlay.
523
+ titleUnderlay?: TitleUnderlay
524
+ // text-shadow preset for the title/subtitle. boosts legibility on
525
+ // photographic / 3d backgrounds. undefined → no shadow.
526
+ titleShadow?: TitleShadow
527
+ // one Google Fonts family shared by title and subtitle. title/subtitle
528
+ // weights are selected from the curated family metadata at render time.
529
+ // undefined keeps the native SF Pro display/text stacks.
530
+ font?: ScreenshotFontChoice
531
+ // normalized top anchor for the complete title/subtitle block. the x
532
+ // coordinate follows textAlign (left edge, center, or right edge).
533
+ // undefined keeps the current top-center placement.
534
+ textPosition?: ScreenshotTextPosition
535
+ textAlign?: ScreenshotTextAlign
536
+ // decorative capture-store images. the editable overlay stack is the
537
+ // composed background/device base, these images, the text underlay, then
538
+ // text. keeping images above the reusable clean base means image and copy
539
+ // edits re-bake without booting the app or re-rendering a 3d scene.
540
+ images?: ScreenshotImageLayer[]
541
+ // ref into the binary capture store (cloud R2) for the COMPOSED App-Store
542
+ // deliverable — bg + title + posed phone + screen baked into one image (or
543
+ // the 3D-baked scene). this is what review shows edge-to-edge and what the
544
+ // zip exports. present once a slide has been captured.
545
+ captureRef?: string
546
+ // ref into the capture store for the COMPOSED deliverable WITHOUT the title
547
+ // block — same bg + posed phone + screen (or 3d scene), text omitted. baked
548
+ // alongside `captureRef` on every capture. lets a copy edit drop a live text
549
+ // overlay onto this and re-bake `captureRef` with NO device/screen repaint
550
+ // and, for 3d slides, NO scene re-render. absent on slides captured before
551
+ // this layer existed (and on composed-only org pushes) — callers fall back to
552
+ // recompose-from-screen / record-new there.
553
+ cleanRef?: string
554
+ // ref into the capture store for the BARE phone-screen pixels (screen only,
555
+ // no chrome). drives the fake-screen overlay so a slide can be re-posed /
556
+ // re-styled and re-baked into a new `captureRef` without booting a build.
557
+ // absent on composed-only org pushes, so Position is disabled until a slide
558
+ // has been captured with the 3-layer pipeline.
559
+ screenRef?: string
560
+ // 2d phone transform used by Position mode when 3d is off. x/y are stored as
561
+ // percentages of the phone silhouette width/height so preview and export
562
+ // apply the same transform regardless of card/canvas size.
563
+ phone2d?: ScreenshotPhone2DTransform
564
+ // 3d composition state, persisted on capture so re-opening the slide
565
+ // restores the exact scene the user shot.
566
+ threeScene?: ScreenshotThreeScene
567
+ }
568
+
569
+ function isTitleSize(value: unknown): value is TitleSize {
570
+ return value === 'sm' || value === 'md' || value === 'lg'
571
+ }
572
+
573
+ function isTitleUnderlay(value: unknown): value is TitleUnderlay {
574
+ return value === 'black' || value === 'white'
575
+ }
576
+
577
+ function isTitleShadow(value: unknown): value is TitleShadow {
578
+ return value === 'light' || value === 'medium' || value === 'strong'
579
+ }
580
+
581
+ function isScreenshotTextAlign(value: unknown): value is ScreenshotTextAlign {
582
+ return value === 'left' || value === 'center' || value === 'right'
583
+ }
584
+
585
+ function clampNumber(value: unknown, min: number, max: number, fallback: number): number {
586
+ if (typeof value !== 'number' || !Number.isFinite(value)) return fallback
587
+ return Math.min(max, Math.max(min, value))
588
+ }
589
+
590
+ export function normalizeScreenshotPhone2DTransform(
591
+ input: unknown,
592
+ ): ScreenshotPhone2DTransform | undefined {
593
+ if (!isRecord(input)) return undefined
594
+ const value = input
595
+ const x = clampNumber(
596
+ value.x,
597
+ PHONE_2D_TRANSFORM_LIMITS.x.min,
598
+ PHONE_2D_TRANSFORM_LIMITS.x.max,
599
+ DEFAULT_PHONE_2D_TRANSFORM.x,
600
+ )
601
+ const y = clampNumber(
602
+ value.y,
603
+ PHONE_2D_TRANSFORM_LIMITS.y.min,
604
+ PHONE_2D_TRANSFORM_LIMITS.y.max,
605
+ DEFAULT_PHONE_2D_TRANSFORM.y,
606
+ )
607
+ const deg = clampNumber(
608
+ value.deg,
609
+ PHONE_2D_TRANSFORM_LIMITS.deg.min,
610
+ PHONE_2D_TRANSFORM_LIMITS.deg.max,
611
+ DEFAULT_PHONE_2D_TRANSFORM.deg,
612
+ )
613
+ const scale = clampNumber(
614
+ value.scale,
615
+ PHONE_2D_TRANSFORM_LIMITS.scale.min,
616
+ PHONE_2D_TRANSFORM_LIMITS.scale.max,
617
+ DEFAULT_PHONE_2D_TRANSFORM.scale,
618
+ )
619
+ return { x, y, deg, scale }
620
+ }
621
+
622
+ function normalizeScreenshotFont(input: unknown): ScreenshotFontChoice | undefined {
623
+ if (!isRecord(input)) return undefined
624
+ const family = input.family
625
+ if (typeof family !== 'string') return undefined
626
+ const trimmed = family.trim()
627
+ return trimmed ? { family: trimmed.slice(0, 100) } : undefined
628
+ }
629
+
630
+ function normalizeScreenshotTextPosition(
631
+ input: unknown,
632
+ ): ScreenshotTextPosition | undefined {
633
+ if (!isRecord(input)) return undefined
634
+ const position = input
635
+ if (typeof position.x !== 'number' || typeof position.y !== 'number') return undefined
636
+ if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) return undefined
637
+ return {
638
+ x: clampNumber(position.x, 0, 1, 0.5),
639
+ y: clampNumber(position.y, 0, 1, 0.06),
640
+ }
641
+ }
642
+
643
+ function normalizeScreenshotImages(input: unknown): ScreenshotImageLayer[] | undefined {
644
+ if (!Array.isArray(input)) return undefined
645
+ const images: ScreenshotImageLayer[] = []
646
+ for (const candidate of input.slice(0, 32)) {
647
+ if (!isRecord(candidate)) continue
648
+ const image = candidate
649
+ if (typeof image.ref !== 'string' || !image.ref.trim()) continue
650
+ images.push({
651
+ ref: image.ref.trim(),
652
+ x: clampNumber(image.x, 0, 1, 0.5),
653
+ y: clampNumber(image.y, 0, 1, 0.5),
654
+ scale: clampNumber(image.scale, 0.02, 2, 0.25),
655
+ rotation: clampNumber(image.rotation, -360, 360, 0),
656
+ })
657
+ }
658
+ return images.length > 0 ? images : undefined
659
+ }
660
+
661
+ function normalizeCustomGradient(
662
+ input: unknown,
663
+ ): ScreenshotThreeScene['customGradient'] | undefined {
664
+ if (!isRecord(input)) return undefined
665
+ const g = input
666
+ if (!Array.isArray(g.stops)) return undefined
667
+ const stops = g.stops
668
+ .filter(
669
+ (s): s is { offset: number; color: string } =>
670
+ isRecord(s) && typeof s.color === 'string' && typeof s.offset === 'number',
671
+ )
672
+ .map((s) => ({ offset: s.offset, color: s.color }))
673
+ if (stops.length === 0) return undefined
674
+ return {
675
+ stops,
676
+ ...(typeof g.angleDeg === 'number' ? { angleDeg: g.angleDeg } : {}),
677
+ }
678
+ }
679
+
680
+ // every dimension is checked against its own id list, and anything unknown
681
+ // falls back to identity for that dimension. A string that merely looks like
682
+ // an id is exactly what must not reach the renderer: it would be dropped
683
+ // there, silently restoring a slide to a look it was never graded with.
684
+ function normalizeThreeSceneGrade(input: Record<string, unknown>): ScreenshotThreeGrade {
685
+ const read = <K extends keyof ScreenshotThreeGrade>(
686
+ key: K,
687
+ ): ScreenshotThreeGrade[K] => {
688
+ const value = input[key]
689
+ const ids: readonly ScreenshotThreeGrade[K][] = SCREENSHOT_THREE_GRADE_IDS[key]
690
+ return ids.find((id) => id === value) ?? SCREENSHOT_THREE_GRADE_DEFAULT[key]
691
+ }
692
+ return {
693
+ contrast: read('contrast'),
694
+ saturation: read('saturation'),
695
+ brightness: read('brightness'),
696
+ blackPoint: read('blackPoint'),
697
+ grain: read('grain'),
698
+ }
699
+ }
700
+
701
+ // authored numbers, clamped to the same ranges the 3d bridge validates
702
+ // against. A missing or non-finite field takes the default rather than
703
+ // dropping out of the saved rig.
704
+ function normalizeThreeSceneCyclorama(value: unknown): ScreenshotThreeCyclorama {
705
+ const input = isRecord(value) ? value : {}
706
+ const read = (key: ScreenshotThreeCycloramaNumericKey): number => {
707
+ const [min, max] = SCREENSHOT_THREE_CYCLORAMA_RANGES[key]
708
+ return clampNumber(input[key], min, max, SCREENSHOT_THREE_CYCLORAMA_DEFAULT[key])
709
+ }
710
+ const readColor = (key: 'warmColor' | 'coolColor'): string =>
711
+ normalizeScreenshotThreeCycloramaColor(
712
+ input[key],
713
+ SCREENSHOT_THREE_CYCLORAMA_DEFAULT[key],
714
+ )
715
+ return {
716
+ keyAzimuthDeg: read('keyAzimuthDeg'),
717
+ keyElevationDeg: read('keyElevationDeg'),
718
+ keyRiseDeg: read('keyRiseDeg'),
719
+ sweepMs: read('sweepMs'),
720
+ keyIntensity: read('keyIntensity'),
721
+ warmIntensity: read('warmIntensity'),
722
+ coolIntensity: read('coolIntensity'),
723
+ curveRadius: read('curveRadius'),
724
+ shadowSoftness: read('shadowSoftness'),
725
+ warmColor: readColor('warmColor'),
726
+ coolColor: readColor('coolColor'),
727
+ warmColorEnd: normalizeScreenshotThreeCycloramaEndColor(
728
+ 'warmColorEnd' in input ? input.warmColorEnd : null,
729
+ ),
730
+ coolColorEnd: normalizeScreenshotThreeCycloramaEndColor(
731
+ 'coolColorEnd' in input ? input.coolColorEnd : null,
732
+ ),
733
+ }
734
+ }
735
+
736
+ /**
737
+ * The 3d bridge options that put a saved slide's scene back. Every dimension
738
+ * the slide can carry is named here, including the ones it saved at their
739
+ * default: configure() merges partial input onto the LIVE state, which is
740
+ * what live editing wants and exactly what restoring must not do. Leaving
741
+ * caseStyle, grade or the cyclorama rig out is how a standard slide opened
742
+ * after an edge-to-edge one came back wearing the other slide's case, its
743
+ * grain and its lighting.
744
+ */
745
+ export function screenshotThreeSceneRestoreOptions(scene: ScreenshotThreeScene) {
746
+ return {
747
+ ...scene.appearance,
748
+ device: scene.device,
749
+ caseStyle: scene.appearance?.caseStyle ?? 'standard',
750
+ colorway: scene.colorway,
751
+ background: scene.background,
752
+ ...(scene.customGradient ? { customGradient: scene.customGradient } : {}),
753
+ setting: scene.setting,
754
+ grade: scene.appearance?.grade ?? SCREENSHOT_THREE_GRADE_DEFAULT,
755
+ // a slide saved before the tints existed carries a rig without them, and
756
+ // configure() merges partials onto the live state: hand the renderer a
757
+ // complete rig here or the previous slide's tints stay lit.
758
+ cyclorama: scene.appearance?.cyclorama
759
+ ? normalizeThreeSceneCyclorama(scene.appearance.cyclorama)
760
+ : SCREENSHOT_THREE_CYCLORAMA_DEFAULT,
761
+ focus: scene.focus,
762
+ environment: scene.environmentActive
763
+ ? {
764
+ pins: scene.environmentPins ?? {},
765
+ effects: scene.environmentEffects ?? {},
766
+ }
767
+ : false,
768
+ pose: {
769
+ phonePosition: scene.phonePosition,
770
+ phoneRotation: scene.phoneRotation,
771
+ cameraPosition: scene.cameraPosition,
772
+ cameraUp: scene.cameraUp,
773
+ target: scene.target,
774
+ },
775
+ }
776
+ }
777
+
778
+ function normalizeSceneRecord<T>(
779
+ input: unknown,
780
+ isValue: (value: unknown) => value is T,
781
+ ): Record<string, T> | undefined {
782
+ if (!isRecord(input)) return undefined
783
+ return Object.fromEntries(
784
+ Object.entries(input).filter((entry): entry is [string, T] => isValue(entry[1])),
785
+ )
786
+ }
787
+
788
+ function isScreenshotBgColorName(value: unknown): value is ScreenshotBgColorName {
789
+ return SCREENSHOT_BG_COLORS.some((color) => color.name === value)
790
+ }
791
+
792
+ function normalizeThreeScene(input: unknown): ScreenshotThreeScene | undefined {
793
+ if (!isRecord(input)) return undefined
794
+ const s = input
795
+ const vec3 = (v: unknown): [number, number, number] | null => {
796
+ if (!Array.isArray(v) || v.length !== 3) return null
797
+ if (!v.every((n) => typeof n === 'number' && Number.isFinite(n))) return null
798
+ return [v[0], v[1], v[2]]
799
+ }
800
+ const cam = vec3(s.cameraPosition)
801
+ const cameraUp = vec3(s.cameraUp)
802
+ const tgt = vec3(s.target)
803
+ const pp = vec3(s.phonePosition)
804
+ const pr = vec3(s.phoneRotation)
805
+ if (!cam || !tgt || !pp || !pr) return undefined
806
+ const customGradient = normalizeCustomGradient(s.customGradient)
807
+ let appearance: ScreenshotThreeAppearance | undefined
808
+ if (isRecord(s.appearance)) {
809
+ const { caseStyle, grade, cyclorama, ...rest } = s.appearance
810
+ appearance = rest
811
+ if (
812
+ typeof appearance.windowLightOffset !== 'number' ||
813
+ !Number.isFinite(appearance.windowLightOffset) ||
814
+ appearance.windowLightOffset < THREE_WINDOW_LIGHT_OFFSET_RANGE[0] ||
815
+ appearance.windowLightOffset > THREE_WINDOW_LIGHT_OFFSET_RANGE[1]
816
+ )
817
+ delete appearance.windowLightOffset
818
+ if (caseStyle === 'standard' || caseStyle === 'edge-to-edge')
819
+ appearance.caseStyle = caseStyle
820
+ if (isRecord(grade)) appearance.grade = normalizeThreeSceneGrade(grade)
821
+ if (isRecord(cyclorama))
822
+ appearance.cyclorama = normalizeThreeSceneCyclorama(cyclorama)
823
+ }
824
+ const focus = normalizeSceneRecord(
825
+ s.focus,
826
+ (value) => value == null || typeof value === 'string' || typeof value === 'boolean',
827
+ )
828
+ const environmentPins = normalizeSceneRecord(
829
+ s.environmentPins,
830
+ (value) => value == null || typeof value === 'string',
831
+ )
832
+ const environmentEffects = normalizeSceneRecord(
833
+ s.environmentEffects,
834
+ (value) => typeof value === 'boolean',
835
+ )
836
+ return {
837
+ device:
838
+ s.device === 'iphone-17-pro' || s.device === 'pixel-10'
839
+ ? s.device
840
+ : 'iphone-17-air',
841
+ cameraPosition: cam,
842
+ ...(cameraUp ? { cameraUp } : {}),
843
+ target: tgt,
844
+ phonePosition: pp,
845
+ phoneRotation: pr,
846
+ colorway: typeof s.colorway === 'string' ? s.colorway : 'black',
847
+ background: typeof s.background === 'string' ? s.background : 'black',
848
+ ...(customGradient ? { customGradient } : {}),
849
+ setting: isThreeModeSetting(s.setting) ? s.setting : 'none',
850
+ ...(appearance ? { appearance } : {}),
851
+ ...(focus ? { focus } : {}),
852
+ environmentActive: !!s.environmentActive,
853
+ environmentPins,
854
+ environmentEffects,
855
+ }
856
+ }
857
+
858
+ // normalize a (possibly legacy / partial) slide so the rest of the code
859
+ // has exactly one shape. pre-production: a legacy `theme` slide just
860
+ // resets to the grey default rather than carrying a compat shim.
861
+ export function normalizeScreenshotSlide(input: unknown, index = 0): ScreenshotSlide {
862
+ const s = isRecord(input) ? input : {}
863
+ const threeScene = normalizeThreeScene(s.threeScene)
864
+ const phone2d = normalizeScreenshotPhone2DTransform(s.phone2d)
865
+ const font = normalizeScreenshotFont(s.font)
866
+ const textPosition = normalizeScreenshotTextPosition(s.textPosition)
867
+ const images = normalizeScreenshotImages(s.images)
868
+ return {
869
+ id: typeof s.id === 'string' && s.id ? s.id : makeScreenshotSlide(index).id,
870
+ title: typeof s.title === 'string' ? s.title : '',
871
+ subtitle: typeof s.subtitle === 'string' ? s.subtitle : '',
872
+ bgTop: isScreenshotBgColorName(s.bgTop) ? s.bgTop : DEFAULT_BG_TOP,
873
+ bgBottom: isScreenshotBgColorName(s.bgBottom) ? s.bgBottom : DEFAULT_BG_BOTTOM,
874
+ pose: POSE_PRESET_NAMES.find((pose) => pose === s.pose) ?? 'straight',
875
+ ...(isScreenshotBgColorName(s.titleColor) ? { titleColor: s.titleColor } : {}),
876
+ ...(isTitleSize(s.titleSize) ? { titleSize: s.titleSize } : {}),
877
+ ...(isTitleUnderlay(s.titleUnderlay) ? { titleUnderlay: s.titleUnderlay } : {}),
878
+ ...(isTitleShadow(s.titleShadow) ? { titleShadow: s.titleShadow } : {}),
879
+ ...(font ? { font } : {}),
880
+ ...(textPosition ? { textPosition } : {}),
881
+ ...(isScreenshotTextAlign(s.textAlign) ? { textAlign: s.textAlign } : {}),
882
+ ...(images ? { images } : {}),
883
+ ...(typeof s.captureRef === 'string' ? { captureRef: s.captureRef } : {}),
884
+ ...(typeof s.cleanRef === 'string' ? { cleanRef: s.cleanRef } : {}),
885
+ ...(typeof s.screenRef === 'string' ? { screenRef: s.screenRef } : {}),
886
+ ...(phone2d ? { phone2d } : {}),
887
+ ...(threeScene ? { threeScene } : {}),
888
+ }
889
+ }
890
+
891
+ export interface ThreeProjectConfig {
892
+ colorway: string
893
+ background: string
894
+ // remaining 3d decor/script state is folded in during Phase 6.
895
+ }
896
+
897
+ export interface ScreenshotProjectConfig {
898
+ store: 'apple' | 'google'
899
+ canvas: ScreenshotCanvasName
900
+ deviceModel: DeviceModel
901
+ // false until the user picks a device from the screenshot rail. while
902
+ // false, entering screenshot mode adopts whatever device you were
903
+ // already on (the "default to current device" behavior); once true the
904
+ // project's device is authoritative and pushed to the engine on enter.
905
+ // single rule, no fallback ambiguity.
906
+ deviceModelExplicit?: boolean
907
+ frames: ScreenshotSlide[]
908
+ activeSlideId: string
909
+ three?: ThreeProjectConfig
910
+ }
911
+
912
+ // fresh projects open with a single slide; the user adds more from the
913
+ // overview gallery's + tile. matches the App-Store editor's blank-state
914
+ // expectation — empty canvas, not a grid of pre-seeded placeholders.
915
+ export const DEFAULT_SCREENSHOT_FRAME_COUNT = 1
916
+
917
+ // Apple allows up to 10 screenshots per device, Google Play 8.
918
+ export const SCREENSHOT_FRAME_LIMITS: Record<'apple' | 'google', number> = {
919
+ apple: 10,
920
+ google: 8,
921
+ }
922
+
923
+ export function makeScreenshotSlide(index: number): ScreenshotSlide {
924
+ return {
925
+ id: `slide_${Date.now().toString(36)}_${index}_${Math.random().toString(36).slice(2, 7)}`,
926
+ title: '',
927
+ subtitle: '',
928
+ bgTop: DEFAULT_BG_TOP,
929
+ bgBottom: DEFAULT_BG_BOTTOM,
930
+ pose: 'straight',
931
+ }
932
+ }
933
+
934
+ export function defaultScreenshotProjectConfig(
935
+ deviceModel: DeviceModel,
936
+ canvas: ScreenshotCanvasName = deviceModel === 'ipad-pro-13'
937
+ ? 'ipad-pro-13'
938
+ : 'iphone-6-9',
939
+ ): ScreenshotProjectConfig {
940
+ const frames = Array.from({ length: DEFAULT_SCREENSHOT_FRAME_COUNT }, (_, i) =>
941
+ makeScreenshotSlide(i),
942
+ )
943
+ const store = SCREENSHOT_CANVASES[canvas]?.store ?? 'apple'
944
+ return {
945
+ store,
946
+ canvas,
947
+ deviceModel,
948
+ frames,
949
+ activeSlideId: frames[0].id,
950
+ }
951
+ }
952
+
953
+ export function resolveCanvasPreset(name: string): CanvasPreset | null {
954
+ const preset = SCREENSHOT_CANVAS_NAMES.find((preset) => preset === name)
955
+ return preset ? SCREENSHOT_CANVASES[preset] : null
956
+ }
957
+
958
+ export function cloneBackgroundSpec(background: BackgroundSpec): BackgroundSpec {
959
+ return {
960
+ type: background.type,
961
+ color: background.color,
962
+ direction: background.direction,
963
+ glow: background.glow,
964
+ stops: background.stops?.map((stop) => ({ ...stop })),
965
+ }
966
+ }
967
+
968
+ export function resolveBackgroundPreset(name: string): BackgroundSpec | null {
969
+ const preset = BACKGROUND_PRESET_NAMES.find((preset) => preset === name)
970
+ return preset ? cloneBackgroundSpec(BACKGROUND_PRESETS[preset]) : null
971
+ }