peachsim 0.1.940 → 0.1.1399
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.
- package/README.md +28 -22
- package/cli/app-catalog.ts +29 -14
- package/cli/app-fonts.ts +5 -3
- package/cli/bridge-flow-runner.ts +40 -29
- package/cli/cloud-client.ts +57 -21
- package/cli/cloud-test-tunnel.ts +12 -18
- package/cli/commands/agent.ts +1 -1
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +8 -8
- package/cli/commands/auth.ts +8 -3
- package/cli/commands/box/bundle-plane.ts +13 -1
- package/cli/commands/box.ts +16 -5
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +125 -71
- package/cli/commands/cpu-profile.ts +45 -1
- package/cli/commands/daemon.ts +131 -33
- package/cli/commands/debug.ts +24 -17
- package/cli/commands/desktop.ts +7 -1
- package/cli/commands/detect.ts +101 -0
- package/cli/commands/detox.ts +6 -6
- package/cli/commands/device.ts +12 -12
- package/cli/commands/electron.ts +32 -14
- package/cli/commands/flow.ts +49 -41
- package/cli/commands/guest-host.ts +39 -1
- package/cli/commands/inspect/core.ts +14 -8
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/settle.ts +5 -3
- package/cli/commands/inspect/settling.ts +229 -44
- package/cli/commands/inspect/wait-idle.ts +3 -2
- package/cli/commands/inspect.ts +105 -93
- package/cli/commands/install-cli.ts +36 -15
- package/cli/commands/install-desktop.ts +68 -195
- package/cli/commands/kotlin.ts +6 -5
- package/cli/commands/login.ts +5 -5
- package/cli/commands/maestro-compare.ts +554 -0
- package/cli/commands/maestro-generate.ts +6 -3
- package/cli/commands/maestro.ts +22 -0
- package/cli/commands/mode.ts +2 -2
- package/cli/commands/no-bridge-hint.ts +6 -2
- package/cli/commands/platform.ts +35 -6
- package/cli/commands/preview.ts +6 -0
- package/cli/commands/project-report.ts +10 -12
- package/cli/commands/record.ts +37 -37
- package/cli/commands/runtime.ts +9 -9
- package/cli/commands/screenshot-layers.ts +4 -4
- package/cli/commands/screenshot-mode.ts +2 -2
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +2 -2
- package/cli/commands/serve.ts +9 -12
- package/cli/commands/setup.ts +29 -14
- package/cli/commands/shell-boolean-mode.ts +2 -2
- package/cli/commands/show-touches-mode.ts +2 -2
- package/cli/commands/skills.ts +11 -11
- package/cli/commands/swift.ts +29 -11
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +5 -0
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +2 -2
- package/cli/commands/upload.ts +15 -15
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +6 -3
- package/cli/desktop-companion.ts +55 -149
- package/cli/dev-build-freshness.ts +2 -2
- package/cli/drivers/desktop.ts +17 -9
- package/cli/drivers/electron.ts +1 -2
- package/cli/drivers/playwright-sim-host.ts +11 -2
- package/cli/drivers/playwright.ts +35 -2
- package/cli/drivers/types.ts +8 -0
- package/cli/maestro-compare.ts +670 -0
- package/cli/outbound-endpoints.ts +46 -8
- package/cli/recording-access.ts +6 -6
- package/cli/run-registry.ts +1 -1
- package/cli/runtime-compat.ts +5 -1
- package/cli/send-to-box.ts +3 -3
- package/cli/shell-init.ts +2 -1
- package/cli/ws-bridge.ts +9 -5
- package/detox/element-types.ts +1 -0
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +67 -38
- package/detox/navigation-lifecycle.ts +9 -6
- package/detox/proof-frame.cjs +6 -4
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +42 -17
- package/dist-lib/bridge-contract-input.mjs +41 -16
- package/dist-lib/bridge-contract.cjs +1 -4
- package/dist-lib/bridge-contract.mjs +1 -3
- package/dist-lib/bundle-channel.cjs +2918 -550
- package/dist-lib/capture-contract.cjs +65 -24
- package/dist-lib/capture-contract.mjs +63 -24
- package/dist-lib/cloud-contract.cjs +2 -2
- package/dist-lib/cloud-contract.mjs +2 -2
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -3
- package/dist-lib/cloud.mjs +3 -3
- package/dist-lib/config.cjs +15 -5
- package/dist-lib/config.mjs +154 -0
- package/dist-lib/detox/index.cjs +495 -139
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1168 -238
- package/dist-lib/expo-swift-metadata.cjs +34 -23
- package/dist-lib/expo-swift-metadata.mjs +32 -23
- package/dist-lib/home-paths.cjs +2 -2
- package/dist-lib/host/bridge-host.cjs +2938 -654
- package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
- package/dist-lib/host/replacement-module-handler.cjs +2 -2
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +981 -353
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +332 -19
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +7 -7
- package/dist-lib/metro-production-bundle.mjs +5 -5
- package/dist-lib/metro.cjs +670 -250
- package/dist-lib/native-app-identity-project.cjs +2647 -0
- package/dist-lib/native-app-identity-project.mjs +1257 -0
- package/dist-lib/native-app-identity.cjs +304 -25
- package/dist-lib/native-app-identity.mjs +302 -25
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +5 -1
- package/dist-lib/react-native-host-modules.mjs +5 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
- package/dist-lib/sdk.cjs +231 -51
- package/dist-lib/sdk.mjs +231 -51
- package/dist-lib/skills.cjs +4107 -1374
- package/dist-lib/swift-compile.cjs +290 -30
- package/dist-lib/swift-compile.mjs +290 -30
- package/dist-lib/swift-package.cjs +143 -12
- package/dist-lib/swift-package.mjs +137 -11
- package/dist-lib/swift-submit.cjs +47 -5
- package/dist-lib/swift-submit.mjs +42 -5
- package/dist-lib/swift-toolchain.cjs +7 -2
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1392 -458
- package/dist-lib/vite.cjs +13 -17
- package/dist-lib/worklet-executable.cjs +248 -33
- package/dist-lib/worklet-executable.mjs +248 -33
- package/install.sh +10 -1
- package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
- package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
- package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
- package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
- package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
- package/kotlin/AppSources/android/view/Window.kt +36 -0
- package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
- package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
- package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
- package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
- package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
- package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
- package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
- package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
- package/kotlin/README.md +13 -3
- package/kotlin/Sources/android/os/Build.kt +17 -0
- package/kotlin/Sources/android/os/Handler.kt +35 -0
- package/kotlin/Sources/android/os/Looper.kt +17 -0
- package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
- package/kotlin/Sources/android/os/SystemClock.kt +14 -0
- package/kotlin/Sources/android/util/Log.kt +64 -0
- package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
- package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
- package/kotlin/Sources/org/json/JSON.kt +44 -0
- package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
- package/kotlin/fixtures/counter/Counter.kt +10 -3
- package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
- package/kotlin/fixtures/counter/vite.config.ts +2 -2
- package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
- package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-animation/Animation.kt +80 -0
- package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
- package/kotlin/fixtures/import-animation/README.md +24 -0
- package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
- package/kotlin/fixtures/import-animation/package.json +23 -0
- package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
- package/kotlin/fixtures/import-editor/Editor.kt +59 -0
- package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
- package/kotlin/fixtures/import-editor/README.md +27 -0
- package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-editor/package.json +23 -0
- package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
- package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
- package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
- package/kotlin/fixtures/import-effects/Effects.kt +87 -0
- package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
- package/kotlin/fixtures/import-effects/README.md +19 -0
- package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-effects/package.json +23 -0
- package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
- package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
- package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
- package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
- package/kotlin/fixtures/import-layout/Layout.kt +72 -0
- package/kotlin/fixtures/import-layout/README.md +24 -0
- package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-layout/package.json +23 -0
- package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
- package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
- package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
- package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
- package/kotlin/fixtures/import-navigation/README.md +31 -0
- package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-navigation/package.json +23 -0
- package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
- package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
- package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
- package/kotlin/fixtures/import-overlays/README.md +34 -0
- package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-overlays/package.json +23 -0
- package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
- package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
- package/kotlin/fixtures/import-scroll/README.md +23 -0
- package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
- package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
- package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-scroll/package.json +23 -0
- package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
- package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
- package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
- package/kotlin/fixtures/import-selection/README.md +32 -0
- package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
- package/kotlin/fixtures/import-selection/Selection.kt +78 -0
- package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-selection/package.json +23 -0
- package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
- package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
- package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
- package/kotlin/fixtures/import-surfaces/README.md +22 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
- package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-surfaces/package.json +23 -0
- package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
- package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
- package/kotlin/fixtures/import-values/README.md +23 -0
- package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
- package/kotlin/fixtures/import-values/Values.kt +66 -0
- package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/package.json +23 -0
- package/kotlin/fixtures/import-values/tsconfig.json +20 -0
- package/kotlin/fixtures/import-values/vite.config.ts +20 -0
- package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
- package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
- package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
- package/kotlin/fork/NOTICE +6 -1
- package/kotlin/fork/README.md +15 -7
- package/kotlin/fork/build.sh +2 -0
- package/kotlin/fork/compose-worker-globals.patch +186 -4
- package/kotlin/fork/fork.json +2 -2
- package/kotlin/fork/skiko-worker-clock.patch +12 -0
- package/kotlin/toolchain.json +12 -12
- package/kotlin/tools/expo-types.main.kts +115 -0
- package/package.json +17 -23
- package/scripts/dev-server-scanner.ts +92 -66
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-debug/SKILL.md +1 -1
- package/skills/peach-perf/SKILL.md +1 -1
- package/skills/peach-setup/SKILL.md +2 -1
- package/skills/peach-test/SKILL.md +8 -0
- package/src/assetCatalogContract.ts +43 -1
- package/src/bridge-contract-input.ts +46 -19
- package/src/bridge-contract.ts +0 -1
- package/src/bundle-channel.mjs +197 -84
- package/src/bundleGlobalFooter.ts +38 -0
- package/src/capture-contract.ts +107 -33
- package/src/cloud-contract.ts +5 -1
- package/src/cloud.ts +5 -2
- package/src/config.ts +22 -3
- package/src/configured-bundle-producer.ts +1 -1
- package/src/desktop-host-delivery.ts +95 -1
- package/src/expo-kotlin-bundle.ts +29 -0
- package/src/expo-kotlin-host.ts +201 -0
- package/src/expo-swift-host.ts +96 -76
- package/src/expoKotlinContract.ts +70 -0
- package/src/expoSwiftContract.ts +4 -25
- package/src/home-paths.ts +7 -4
- package/src/host/bridge-host.ts +23 -3
- package/src/host/fetch-proxy-handler.ts +13 -0
- package/src/host/fetch-proxy-overrides.ts +11 -0
- package/src/host/replacement-module-handler.ts +5 -2
- package/src/index.ts +3 -1
- package/src/kotlin-host.ts +463 -19
- package/src/metro-plugin.ts +56 -28
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-app-identity-project.ts +190 -0
- package/src/native-app-identity.ts +367 -34
- package/src/native-firebase-config.ts +69 -15
- package/src/native-seam-manifest.ts +6 -0
- package/src/one-widget-discovery.ts +2 -1
- package/src/openstep-plist.ts +107 -0
- package/src/react-native-host-modules.ts +4 -0
- package/src/runtime-assets.ts +2 -2
- package/src/sim-client.ts +2 -2
- package/src/swift-binary-modules.ts +3 -1
- package/src/swift-compile.ts +286 -38
- package/src/swift-distribution-contract.ts +4 -0
- package/src/swift-distribution.lock.json +123 -12
- package/src/swift-distribution.ts +7 -3
- package/src/swift-host.ts +298 -83
- package/src/swift-package-manifest.ts +29 -2
- package/src/swift-package.ts +180 -10
- package/src/swift-packages.ts +4 -0
- package/src/swift-standin-emit.ts +4 -1
- package/src/swift-standins.ts +274 -15
- package/src/swift-submit.ts +62 -7
- package/src/swift-toolchain.ts +6 -1
- package/src/swiftContract.ts +126 -3
- package/src/vite-plugin-one.ts +13 -16
- package/src/vite-plugin-swift.ts +4 -5
- package/src/vite-plugin.ts +360 -144
- package/src/vite.d.ts +1 -1
- package/src/worker-system-chunks.ts +221 -0
- package/src/worklet-executable.ts +348 -38
- package/src/worklets-babel.ts +1 -1
- package/src/xcode-project.ts +243 -127
- package/dist-lib/agent-identity.cjs +0 -39
- package/dist-lib/agent-sessions.cjs +0 -760
- package/dist-lib/cli-constants.cjs +0 -32
- package/dist-lib/render-mode.cjs +0 -44
- package/kotlin/AppSources/android/view/View.kt +0 -74
- package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
- package/src/render-mode.ts +0 -15
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
- /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package dev.contrast.kotlinlayout
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.background
|
|
4
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
5
|
+
import androidx.compose.foundation.layout.Box
|
|
6
|
+
import androidx.compose.foundation.layout.Column
|
|
7
|
+
import androidx.compose.foundation.layout.Row
|
|
8
|
+
import androidx.compose.foundation.layout.Spacer
|
|
9
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
10
|
+
import androidx.compose.foundation.layout.padding
|
|
11
|
+
import androidx.compose.foundation.layout.size
|
|
12
|
+
import androidx.compose.foundation.layout.width
|
|
13
|
+
import androidx.compose.material3.Button
|
|
14
|
+
import androidx.compose.material3.MaterialTheme
|
|
15
|
+
import androidx.compose.material3.Surface
|
|
16
|
+
import androidx.compose.material3.Text
|
|
17
|
+
import androidx.compose.material3.lightColorScheme
|
|
18
|
+
import androidx.compose.runtime.Composable
|
|
19
|
+
import androidx.compose.runtime.getValue
|
|
20
|
+
import androidx.compose.runtime.mutableStateOf
|
|
21
|
+
import androidx.compose.runtime.remember
|
|
22
|
+
import androidx.compose.runtime.setValue
|
|
23
|
+
import androidx.compose.ui.Alignment
|
|
24
|
+
import androidx.compose.ui.Modifier
|
|
25
|
+
import androidx.compose.ui.graphics.Color
|
|
26
|
+
import androidx.compose.ui.layout.onGloballyPositioned
|
|
27
|
+
import androidx.compose.ui.layout.positionInParent
|
|
28
|
+
import androidx.compose.ui.platform.testTag
|
|
29
|
+
import androidx.compose.ui.unit.dp
|
|
30
|
+
|
|
31
|
+
@Composable
|
|
32
|
+
fun Layout(title: String, onStep: ((Int) -> Unit)? = null) {
|
|
33
|
+
var count by remember { mutableStateOf(0) }
|
|
34
|
+
var geometry by remember { mutableStateOf(mapOf<String, List<Int>>()) }
|
|
35
|
+
fun measured(name: String, modifier: Modifier): Modifier = modifier.onGloballyPositioned {
|
|
36
|
+
val position = it.positionInParent()
|
|
37
|
+
val value = listOf(position.x.toInt(), position.y.toInt(), it.size.width, it.size.height)
|
|
38
|
+
if (geometry[name] != value) geometry = geometry + (name to value)
|
|
39
|
+
}
|
|
40
|
+
MaterialTheme(colorScheme = lightColorScheme()) {
|
|
41
|
+
Surface(Modifier.fillMaxSize()) {
|
|
42
|
+
Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
|
43
|
+
Text(title, modifier = Modifier.testTag("layout-title"))
|
|
44
|
+
Text("Count: $count", modifier = Modifier.testTag("layout-count"))
|
|
45
|
+
Row(
|
|
46
|
+
measured("row", Modifier.size(280.dp, 60.dp).background(Color(0xFFE8DEF8))),
|
|
47
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
48
|
+
) {
|
|
49
|
+
Box(measured("first", Modifier.weight(1f).size(height = 20.dp, width = 1.dp).background(Color(0xFF6750A4))))
|
|
50
|
+
Spacer(measured("spacer", Modifier.width(8.dp)))
|
|
51
|
+
Box(measured("second", Modifier.weight(2f).size(height = 40.dp, width = 1.dp).background(Color(0xFF625B71))))
|
|
52
|
+
}
|
|
53
|
+
Box(measured("box", Modifier.size(280.dp, 80.dp).background(Color(0xFFEADDFF)))) {
|
|
54
|
+
Box(measured("aligned", Modifier.align(Alignment.BottomEnd).size(40.dp, 24.dp).background(Color(0xFF7D5260))))
|
|
55
|
+
}
|
|
56
|
+
Button(
|
|
57
|
+
onClick = { count += 1; onStep?.invoke(count) },
|
|
58
|
+
modifier = Modifier.testTag("layout-step"),
|
|
59
|
+
) { Text("Next layout step") }
|
|
60
|
+
Button(
|
|
61
|
+
onClick = { count += 1000; onStep?.invoke(count) },
|
|
62
|
+
enabled = false,
|
|
63
|
+
modifier = Modifier.testTag("layout-disabled"),
|
|
64
|
+
) { Text("Disabled layout step") }
|
|
65
|
+
Text(
|
|
66
|
+
geometry.entries.sortedBy { it.key }.joinToString(";") { (name, value) -> "$name=${value.joinToString(",")}" },
|
|
67
|
+
modifier = Modifier.testTag("layout-geometry"),
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Imported Compose layout
|
|
2
|
+
|
|
3
|
+
Run One from this directory with `bunx one dev --port 8081`. Build Android
|
|
4
|
+
through the repository's remote builder after `bunx one prebuild --platform android`.
|
|
5
|
+
Open the same server in Peach with `peach open <port> --device pixel-8`.
|
|
6
|
+
For Contrast, import the fixture with catalog versions materialized.
|
|
7
|
+
|
|
8
|
+
The unchanged Kotlin import lays out a weighted Row, Spacer and aligned Box
|
|
9
|
+
inside a padded Column. `layout-geometry` reports child positions and sizes in
|
|
10
|
+
physical pixels. Compare it between hosts at the same device density.
|
|
11
|
+
|
|
12
|
+
Tap `layout-step`. Compose's count and React's step must both advance once,
|
|
13
|
+
and the callback must update the imported title to `Layout step 1` while the
|
|
14
|
+
remembered count stays at one. Tapping `layout-disabled` must preserve that
|
|
15
|
+
state. A second enabled tap must advance every readout to two.
|
|
16
|
+
Capture each state and bind its source, bundle and compiled artifacts.
|
|
17
|
+
|
|
18
|
+
RAN, 2026-10-11: fresh One Android API 37, Peach and Contrast Android import
|
|
19
|
+
runs pass all four states with identical measured geometry. The
|
|
20
|
+
[functional receipt](https://r2.sootsim.com/kotlin-evidence/import-layout/44494c189ca794bbf49431d924c9e77dcf9c04af54a25a38ef06bf642ced1461/proof.json)
|
|
21
|
+
binds the Kotlin source, compiled artifact, native APK, captures, trees and
|
|
22
|
+
probes. Wrong geometry and a disabled callback change both fail the saved
|
|
23
|
+
receipt verdict. This covers geometry and callback state, with no full-frame
|
|
24
|
+
pixel, glyph, release APK or production-delivery claim.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportLayout.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-layout-fixture",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"targets": [
|
|
6
|
+
"native"
|
|
7
|
+
],
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@react-navigation/core": "catalog:",
|
|
10
|
+
"@react-navigation/native": "catalog:",
|
|
11
|
+
"one": "catalog:",
|
|
12
|
+
"react": "catalog:",
|
|
13
|
+
"react-native": "catalog:",
|
|
14
|
+
"react-native-reanimated": "catalog:",
|
|
15
|
+
"react-native-screens": "catalog:",
|
|
16
|
+
"react-native-worklets": "catalog:"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@react-native-community/template": "catalog:",
|
|
20
|
+
"peachsim": "workspace:*",
|
|
21
|
+
"vite": "catalog:"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"paths": {
|
|
4
|
+
"~/*": ["./*"]
|
|
5
|
+
},
|
|
6
|
+
"strict": true,
|
|
7
|
+
"allowArbitraryExtensions": true,
|
|
8
|
+
"rootDir": ".",
|
|
9
|
+
"module": "Preserve",
|
|
10
|
+
// allows react-native style imports without path extensions, for compat with platform-specific files
|
|
11
|
+
"moduleResolution": "Bundler",
|
|
12
|
+
"preserveSymlinks": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"noImplicitAny": false,
|
|
16
|
+
"types": ["node", "react", "vite/client"],
|
|
17
|
+
"lib": ["dom", "esnext"]
|
|
18
|
+
},
|
|
19
|
+
"exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { one } from 'one/vite'
|
|
2
|
+
import { peachPlugin } from 'peachsim/vite'
|
|
3
|
+
export default {
|
|
4
|
+
root: import.meta.dirname,
|
|
5
|
+
plugins: [
|
|
6
|
+
one({
|
|
7
|
+
web: { defaultRenderMode: 'spa' },
|
|
8
|
+
native: {
|
|
9
|
+
bundler: 'vite',
|
|
10
|
+
app: {
|
|
11
|
+
name: 'KotlinLayout',
|
|
12
|
+
scheme: 'kotlinlayout',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinlayout' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Text, View, type ViewStyle } from 'react-native'
|
|
3
|
+
import { Navigation } from './Navigation.kt'
|
|
4
|
+
|
|
5
|
+
export default function Index() {
|
|
6
|
+
const [step, setStep] = useState(0)
|
|
7
|
+
const navigationProps = {
|
|
8
|
+
title: `Navigation step ${step}`,
|
|
9
|
+
onStep: setStep,
|
|
10
|
+
style: { flex: 1 } satisfies ViewStyle,
|
|
11
|
+
}
|
|
12
|
+
return (
|
|
13
|
+
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
|
14
|
+
<Navigation {...navigationProps} />
|
|
15
|
+
<Text testID="navigation-react-step">React step: {step}</Text>
|
|
16
|
+
</View>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package dev.contrast.kotlinnavigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
4
|
+
import androidx.compose.foundation.layout.Column
|
|
5
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
6
|
+
import androidx.compose.foundation.layout.padding
|
|
7
|
+
import androidx.compose.material3.Button
|
|
8
|
+
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
9
|
+
import androidx.compose.material3.MaterialTheme
|
|
10
|
+
import androidx.compose.material3.NavigationBar
|
|
11
|
+
import androidx.compose.material3.NavigationBarItem
|
|
12
|
+
import androidx.compose.material3.Scaffold
|
|
13
|
+
import androidx.compose.material3.Text
|
|
14
|
+
import androidx.compose.material3.TopAppBar
|
|
15
|
+
import androidx.compose.material3.lightColorScheme
|
|
16
|
+
import androidx.compose.runtime.Composable
|
|
17
|
+
import androidx.compose.runtime.getValue
|
|
18
|
+
import androidx.compose.runtime.mutableStateOf
|
|
19
|
+
import androidx.compose.runtime.remember
|
|
20
|
+
import androidx.compose.runtime.saveable.rememberSaveable
|
|
21
|
+
import androidx.compose.runtime.setValue
|
|
22
|
+
import androidx.compose.ui.Modifier
|
|
23
|
+
import androidx.compose.ui.platform.testTag
|
|
24
|
+
import androidx.compose.ui.unit.dp
|
|
25
|
+
import androidx.navigation.compose.NavHost
|
|
26
|
+
import androidx.navigation.compose.composable
|
|
27
|
+
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
28
|
+
import androidx.navigation.compose.rememberNavController
|
|
29
|
+
|
|
30
|
+
@OptIn(ExperimentalMaterial3Api::class)
|
|
31
|
+
@Composable
|
|
32
|
+
fun Navigation(title: String, onStep: ((Int) -> Unit)? = null) {
|
|
33
|
+
var count by remember { mutableStateOf(0) }
|
|
34
|
+
val nav = rememberNavController()
|
|
35
|
+
val entry by nav.currentBackStackEntryAsState()
|
|
36
|
+
val route = entry?.destination?.route
|
|
37
|
+
MaterialTheme(colorScheme = lightColorScheme()) {
|
|
38
|
+
Scaffold(
|
|
39
|
+
modifier = Modifier.fillMaxSize(),
|
|
40
|
+
topBar = {
|
|
41
|
+
TopAppBar(
|
|
42
|
+
title = { Text(title, Modifier.testTag("navigation-title")) },
|
|
43
|
+
navigationIcon = {
|
|
44
|
+
Button(
|
|
45
|
+
onClick = { nav.popBackStack(); count += 1; onStep?.invoke(count) },
|
|
46
|
+
enabled = route == "detail",
|
|
47
|
+
modifier = Modifier.testTag("navigation-back"),
|
|
48
|
+
) { Text("Return home") }
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
},
|
|
52
|
+
bottomBar = {
|
|
53
|
+
NavigationBar {
|
|
54
|
+
NavigationBarItem(
|
|
55
|
+
selected = route == "home",
|
|
56
|
+
onClick = {
|
|
57
|
+
if (route != "home") {
|
|
58
|
+
nav.popBackStack()
|
|
59
|
+
count += 1
|
|
60
|
+
onStep?.invoke(count)
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
icon = { Text("H") },
|
|
64
|
+
label = { Text("Home tab") },
|
|
65
|
+
modifier = Modifier.testTag("navigation-home-tab"),
|
|
66
|
+
)
|
|
67
|
+
NavigationBarItem(
|
|
68
|
+
selected = route == "detail",
|
|
69
|
+
onClick = {
|
|
70
|
+
if (route != "detail") {
|
|
71
|
+
nav.navigate("detail")
|
|
72
|
+
count += 1
|
|
73
|
+
onStep?.invoke(count)
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
icon = { Text("D") },
|
|
77
|
+
label = { Text("Detail tab") },
|
|
78
|
+
modifier = Modifier.testTag("navigation-open-detail"),
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
) { padding ->
|
|
83
|
+
Column(Modifier.fillMaxSize().padding(padding).padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
84
|
+
Text("Count: $count", Modifier.testTag("navigation-count"))
|
|
85
|
+
Text("route=$route;step=$count", Modifier.testTag("navigation-state"))
|
|
86
|
+
Button(onClick = { count += 1000; onStep?.invoke(count) }, enabled = false, modifier = Modifier.testTag("navigation-disabled")) {
|
|
87
|
+
Text("Disabled navigation step")
|
|
88
|
+
}
|
|
89
|
+
NavHost(nav, startDestination = "home", modifier = Modifier.weight(1f)) {
|
|
90
|
+
composable("home") {
|
|
91
|
+
var taps by rememberSaveable { mutableStateOf(0) }
|
|
92
|
+
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
93
|
+
Text("Saved home: $taps", Modifier.testTag("navigation-home-count"))
|
|
94
|
+
Button(onClick = { taps += 1; count += 1; onStep?.invoke(count) }, modifier = Modifier.testTag("navigation-increment")) {
|
|
95
|
+
Text("Increment home")
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
composable("detail") { Text("Detail screen", Modifier.testTag("navigation-detail")) }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Imported Compose navigation
|
|
2
|
+
|
|
3
|
+
Run One in this fixture, then open its Android bundle in Peach on Pixel 8.
|
|
4
|
+
Build the native Android target on a remote builder. Import the same files in
|
|
5
|
+
Contrast with catalog versions materialized.
|
|
6
|
+
|
|
7
|
+
Increment the home counter, tap the detail navigation item, try the disabled
|
|
8
|
+
button, return with the top app bar button, then increment home again. The
|
|
9
|
+
home counter must survive the NavHost push/pop as one, then advance to two.
|
|
10
|
+
Each enabled action updates React and the imported title while Compose retains
|
|
11
|
+
the action count. Capture all six states and read the actual destination route.
|
|
12
|
+
This fixture claims settled navigation and saveable state, without system-back,
|
|
13
|
+
transition timing, activity restoration or full-frame pixel fidelity.
|
|
14
|
+
|
|
15
|
+
RAN One Android, Peach and Contrast: initial, increment, detail, disabled,
|
|
16
|
+
returned and second increment. Counts are 0, 1, 2, 2, 3 and 4; the saved home
|
|
17
|
+
count returns as one, then advances to two. React callback/title/footer values
|
|
18
|
+
match in all states. Contrast loads its initial preview document once, with no
|
|
19
|
+
browser errors, failed requests or failed responses.
|
|
20
|
+
|
|
21
|
+
[Hash-verified three-host proof](https://r2.sootsim.com/kotlin-evidence/import-navigation/8046f59ff6e63ae4c3e0eb21cf58852ab63b0900550f7ffc1f1d3b179618b437/proof.json) contains 71 objects and rejecting
|
|
22
|
+
controls for wrong saved state, disabled callbacks, runtime and duplicate loads.
|
|
23
|
+
Kotlin SHA256 `ab8c24c7540fc1916caa6581e8e63231c03e81c411837fb7ae971d1cc843a974`;
|
|
24
|
+
runtime `dd802e83b984a06811f4998c1a66c187dad7404b3f73077cf285f01a5accdff4`.
|
|
25
|
+
One native proof uses family canary `2.0.0-0.canary.1791736959809`, whose host
|
|
26
|
+
bounds intrinsic measurement and includes navigation-compose. The family pin
|
|
27
|
+
stays on the isolated helper branch until the dependency lane adopts it.
|
|
28
|
+
This receipt covers debug Android API37 and settled state. System back,
|
|
29
|
+
transition timing, activity restoration, text glyphs, shell and full-frame
|
|
30
|
+
pixel fidelity remain outside this fixture's grade. Images live in the proof,
|
|
31
|
+
with existing native captures converted losslessly to WebP without resizing.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportNavigation.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-navigation-fixture",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"targets": [
|
|
6
|
+
"native"
|
|
7
|
+
],
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@react-navigation/core": "catalog:",
|
|
10
|
+
"@react-navigation/native": "catalog:",
|
|
11
|
+
"one": "catalog:",
|
|
12
|
+
"react": "catalog:",
|
|
13
|
+
"react-native": "catalog:",
|
|
14
|
+
"react-native-reanimated": "catalog:",
|
|
15
|
+
"react-native-screens": "catalog:",
|
|
16
|
+
"react-native-worklets": "catalog:"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@react-native-community/template": "catalog:",
|
|
20
|
+
"peachsim": "workspace:*",
|
|
21
|
+
"vite": "catalog:"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"paths": {
|
|
4
|
+
"~/*": ["./*"]
|
|
5
|
+
},
|
|
6
|
+
"strict": true,
|
|
7
|
+
"allowArbitraryExtensions": true,
|
|
8
|
+
"rootDir": ".",
|
|
9
|
+
"module": "Preserve",
|
|
10
|
+
// allows react-native style imports without path extensions, for compat with platform-specific files
|
|
11
|
+
"moduleResolution": "Bundler",
|
|
12
|
+
"preserveSymlinks": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"noImplicitAny": false,
|
|
16
|
+
"types": ["node", "react", "vite/client"],
|
|
17
|
+
"lib": ["dom", "esnext"]
|
|
18
|
+
},
|
|
19
|
+
"exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { one } from 'one/vite'
|
|
2
|
+
import { peachPlugin } from 'peachsim/vite'
|
|
3
|
+
export default {
|
|
4
|
+
root: import.meta.dirname,
|
|
5
|
+
plugins: [
|
|
6
|
+
one({
|
|
7
|
+
web: { defaultRenderMode: 'spa' },
|
|
8
|
+
native: {
|
|
9
|
+
bundler: 'vite',
|
|
10
|
+
app: {
|
|
11
|
+
name: 'KotlinNavigation',
|
|
12
|
+
scheme: 'kotlinnavigation',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinnavigation' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Pressable, Text, View } from 'react-native'
|
|
3
|
+
import { Overlays } from './Overlays.kt'
|
|
4
|
+
|
|
5
|
+
type DecisionEvent = [string, number]
|
|
6
|
+
|
|
7
|
+
export default function Index() {
|
|
8
|
+
const [title, setTitle] = useState('Imported overlays')
|
|
9
|
+
const [events, setEvents] = useState<DecisionEvent[]>([])
|
|
10
|
+
return (
|
|
11
|
+
<View style={{ flex: 1, paddingTop: 48, backgroundColor: '#fff' }}>
|
|
12
|
+
<View style={{ flex: 1 }}>
|
|
13
|
+
<Overlays
|
|
14
|
+
title={title}
|
|
15
|
+
onDecision={(value, count) =>
|
|
16
|
+
setEvents((previous) => [...previous, [value, count]])
|
|
17
|
+
}
|
|
18
|
+
/>
|
|
19
|
+
</View>
|
|
20
|
+
<View style={{ height: 200, padding: 24 }}>
|
|
21
|
+
<Text testID="overlays-props">{JSON.stringify({ title })}</Text>
|
|
22
|
+
<Text testID="overlays-events">{JSON.stringify(events)}</Text>
|
|
23
|
+
<Pressable testID="overlays-title" onPress={() => setTitle('Updated overlays')}>
|
|
24
|
+
<Text>Update title</Text>
|
|
25
|
+
</Pressable>
|
|
26
|
+
</View>
|
|
27
|
+
</View>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
package dev.contrast.kotlinoverlays
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
4
|
+
import androidx.compose.foundation.layout.Box
|
|
5
|
+
import androidx.compose.foundation.layout.Column
|
|
6
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
7
|
+
import androidx.compose.foundation.layout.padding
|
|
8
|
+
import androidx.compose.material3.AlertDialog
|
|
9
|
+
import androidx.compose.material3.Button
|
|
10
|
+
import androidx.compose.material3.DropdownMenu
|
|
11
|
+
import androidx.compose.material3.DropdownMenuItem
|
|
12
|
+
import androidx.compose.material3.MaterialTheme
|
|
13
|
+
import androidx.compose.material3.Surface
|
|
14
|
+
import androidx.compose.material3.Text
|
|
15
|
+
import androidx.compose.material3.TextButton
|
|
16
|
+
import androidx.compose.material3.lightColorScheme
|
|
17
|
+
import androidx.compose.runtime.Composable
|
|
18
|
+
import androidx.compose.runtime.getValue
|
|
19
|
+
import androidx.compose.runtime.mutableStateOf
|
|
20
|
+
import androidx.compose.runtime.remember
|
|
21
|
+
import androidx.compose.runtime.setValue
|
|
22
|
+
import androidx.compose.ui.Modifier
|
|
23
|
+
import androidx.compose.ui.platform.testTag
|
|
24
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
25
|
+
import androidx.compose.ui.semantics.semantics
|
|
26
|
+
import androidx.compose.ui.unit.dp
|
|
27
|
+
|
|
28
|
+
@Composable
|
|
29
|
+
fun Overlays(title: String, onDecision: ((String, Int) -> Unit)? = null) {
|
|
30
|
+
var dialog by remember { mutableStateOf(false) }
|
|
31
|
+
var menu by remember { mutableStateOf(false) }
|
|
32
|
+
var result by remember { mutableStateOf("none") }
|
|
33
|
+
var decisions by remember { mutableStateOf(0) }
|
|
34
|
+
fun decide(value: String) {
|
|
35
|
+
result = value
|
|
36
|
+
decisions += 1
|
|
37
|
+
onDecision?.invoke(value, decisions)
|
|
38
|
+
}
|
|
39
|
+
val state = "$title|$result|$decisions|$dialog|$menu"
|
|
40
|
+
MaterialTheme(colorScheme = lightColorScheme()) {
|
|
41
|
+
Surface(Modifier.fillMaxSize()) {
|
|
42
|
+
Column(
|
|
43
|
+
Modifier.fillMaxSize().padding(24.dp),
|
|
44
|
+
verticalArrangement = Arrangement.spacedBy(16.dp),
|
|
45
|
+
) {
|
|
46
|
+
Text(title, style = MaterialTheme.typography.headlineSmall)
|
|
47
|
+
Text(state, Modifier.testTag("overlays-state"))
|
|
48
|
+
Button(
|
|
49
|
+
onClick = { dialog = true },
|
|
50
|
+
modifier = Modifier.testTag("overlays-dialog").semantics { contentDescription = "overlays-dialog" },
|
|
51
|
+
) { Text("Open dialog") }
|
|
52
|
+
Box {
|
|
53
|
+
Button(
|
|
54
|
+
onClick = { menu = true },
|
|
55
|
+
modifier = Modifier.testTag("overlays-menu").semantics { contentDescription = "overlays-menu" },
|
|
56
|
+
) { Text("Open menu") }
|
|
57
|
+
DropdownMenu(
|
|
58
|
+
expanded = menu,
|
|
59
|
+
onDismissRequest = { menu = false; decide("menu-dismissed") },
|
|
60
|
+
) {
|
|
61
|
+
Text(state, Modifier.padding(12.dp).testTag("overlays-menu-state"))
|
|
62
|
+
listOf("First", "Second", "Third").forEach { item ->
|
|
63
|
+
DropdownMenuItem(
|
|
64
|
+
text = { Text(item) },
|
|
65
|
+
onClick = { menu = false; decide(item) },
|
|
66
|
+
modifier = Modifier.testTag("overlays-$item").semantics { contentDescription = "overlays-$item" },
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (dialog) {
|
|
74
|
+
AlertDialog(
|
|
75
|
+
onDismissRequest = { dialog = false; decide("dialog-dismissed") },
|
|
76
|
+
title = { Text("Discard draft?") },
|
|
77
|
+
text = { Text(state, Modifier.testTag("overlays-dialog-state")) },
|
|
78
|
+
confirmButton = {
|
|
79
|
+
TextButton(
|
|
80
|
+
onClick = { dialog = false; decide("confirmed") },
|
|
81
|
+
modifier = Modifier.testTag("overlays-confirm").semantics { contentDescription = "overlays-confirm" },
|
|
82
|
+
) { Text("Discard") }
|
|
83
|
+
},
|
|
84
|
+
dismissButton = {
|
|
85
|
+
TextButton(
|
|
86
|
+
onClick = { dialog = false; decide("kept") },
|
|
87
|
+
modifier = Modifier.testTag("overlays-keep").semantics { contentDescription = "overlays-keep" },
|
|
88
|
+
) { Text("Keep") }
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Imported Compose overlays
|
|
2
|
+
|
|
3
|
+
This fixture imports a public composable into React Native and reports dialog
|
|
4
|
+
and menu decisions to React. Compose retains its decision count when React
|
|
5
|
+
changes the title prop.
|
|
6
|
+
|
|
7
|
+
Run One here with `bunx one dev --port 8081`, then open that port with
|
|
8
|
+
`peach open 8081 --device pixel-8`. Generate Android with
|
|
9
|
+
`bunx one prebuild --platform android`; send Gradle builds through `bun remote`.
|
|
10
|
+
|
|
11
|
+
Open the dialog and choose Keep. Update the React title, reopen the dialog and
|
|
12
|
+
choose Discard. Open the menu and choose Second. Reopen the menu and dismiss it
|
|
13
|
+
with Android Back, then open the dialog and dismiss it with Back. The final
|
|
14
|
+
state is `Updated overlays|dialog-dismissed|5|false|false`; React receives
|
|
15
|
+
`[["kept",1],["confirmed",2],["Second",3],["menu-dismissed",4],["dialog-dismissed",5]]`.
|
|
16
|
+
Native popup windows hide the React footer, so callbacks are checked after close.
|
|
17
|
+
|
|
18
|
+
RAN 2026-10-11: Android debug and Kotlin/Wasm builds passed. Fresh One Android,
|
|
19
|
+
then Peach, then Contrast's native bundle producer matched all twelve states
|
|
20
|
+
and five callbacks. Peach and Contrast reported no preview errors; Contrast
|
|
21
|
+
compiled `Overlays.kt` and produced a complete bundle graph. These runs used
|
|
22
|
+
One `2.0.0-0.canary.1791724440037` and one complete shell, engine and tenant
|
|
23
|
+
runtime build. Runtime pairs must stay together: newly bundled CanvasKit
|
|
24
|
+
loaders reject older paired Wasm, and mixing ordinary CanvasKit versions also
|
|
25
|
+
prevented captures.
|
|
26
|
+
|
|
27
|
+
The imported host measures the root separately from popup layers, constrains
|
|
28
|
+
popups to the laid-out view bounds, and gives imported views a navigation
|
|
29
|
+
dispatcher that receives hardware Back. Dialog opening previously failed its
|
|
30
|
+
minimum constraints; menu opening rejected an infinite scroll height; Back
|
|
31
|
+
previously left the app instead of dismissing its menu. The retained probe
|
|
32
|
+
reproduces those failures and verifies the repaired behavior. This establishes
|
|
33
|
+
import and interaction behavior, without grading pixels or the signed-in
|
|
34
|
+
editor. Captures, hashes and receipts are retained in task `t-mv3ww8ql-120u0`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportOverlays.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-overlays-fixture",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"targets": [
|
|
6
|
+
"native"
|
|
7
|
+
],
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@react-navigation/core": "catalog:",
|
|
10
|
+
"@react-navigation/native": "catalog:",
|
|
11
|
+
"one": "catalog:",
|
|
12
|
+
"react": "catalog:",
|
|
13
|
+
"react-native": "catalog:",
|
|
14
|
+
"react-native-reanimated": "catalog:",
|
|
15
|
+
"react-native-screens": "catalog:",
|
|
16
|
+
"react-native-worklets": "catalog:"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@react-native-community/template": "catalog:",
|
|
20
|
+
"peachsim": "workspace:*",
|
|
21
|
+
"vite": "catalog:"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"paths": {
|
|
4
|
+
"~/*": ["./*"]
|
|
5
|
+
},
|
|
6
|
+
"strict": true,
|
|
7
|
+
"allowArbitraryExtensions": true,
|
|
8
|
+
"rootDir": ".",
|
|
9
|
+
"module": "Preserve",
|
|
10
|
+
// allows react-native style imports without path extensions, for compat with platform-specific files
|
|
11
|
+
"moduleResolution": "Bundler",
|
|
12
|
+
"preserveSymlinks": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"noImplicitAny": false,
|
|
16
|
+
"types": ["node", "react", "vite/client"],
|
|
17
|
+
"lib": ["dom", "esnext"]
|
|
18
|
+
},
|
|
19
|
+
"exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { one } from 'one/vite'
|
|
2
|
+
import { peachPlugin } from 'peachsim/vite'
|
|
3
|
+
export default {
|
|
4
|
+
root: import.meta.dirname,
|
|
5
|
+
plugins: [
|
|
6
|
+
one({
|
|
7
|
+
web: { defaultRenderMode: 'spa' },
|
|
8
|
+
native: {
|
|
9
|
+
bundler: 'vite',
|
|
10
|
+
app: {
|
|
11
|
+
name: 'KotlinOverlays',
|
|
12
|
+
scheme: 'kotlinoverlays',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinoverlays' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|