peachsim 0.1.939 → 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 +999 -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 +688 -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 +325 -25
- package/dist-lib/native-app-identity.mjs +323 -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 +398 -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,13 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Text, View } from 'react-native'
|
|
3
|
+
import { Scroll } from './Scroll.kt'
|
|
4
|
+
|
|
5
|
+
export default function Index() {
|
|
6
|
+
const [step, setStep] = useState(0)
|
|
7
|
+
return (
|
|
8
|
+
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
|
9
|
+
<Scroll title={`Scroll step ${step}`} onStep={setStep} />
|
|
10
|
+
<Text testID="scroll-react-step">React step: {step}</Text>
|
|
11
|
+
</View>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Imported Compose scrolling
|
|
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
|
+
Tap `scroll-step` to scroll all five containers through their official state
|
|
8
|
+
APIs. The plain containers move to 180 and 80 physical pixels. LazyColumn,
|
|
9
|
+
LazyRow and LazyVerticalGrid move to index/offset pairs 5/8, 4/4 and 8/6.
|
|
10
|
+
The callback updates React and the imported title while Compose retains count.
|
|
11
|
+
The disabled action must preserve every value. The second enabled tap resets
|
|
12
|
+
every scroll state to zero and advances count to two. Capture all four states,
|
|
13
|
+
including visible indexed content. This fixture claims state and scroll-to
|
|
14
|
+
execution, without drag/fling timing or full-frame pixel fidelity.
|
|
15
|
+
|
|
16
|
+
RAN, 2026-10-11: fresh One Android API 37, Peach and Contrast Android import
|
|
17
|
+
runs pass the four states with identical offsets and visible item indices.
|
|
18
|
+
The [functional receipt](https://r2.sootsim.com/kotlin-evidence/import-scroll/916c4e8107ef1d5972d87c74dc24d331616d0edab675d9792e06905041b92171/proof.json)
|
|
19
|
+
binds the Kotlin source, compiler, native APK, captures and executed probes.
|
|
20
|
+
All 50 published objects pass SHA256 readback; a wrong offset and a disabled
|
|
21
|
+
callback change reject the saved verdict. Contrast uses the repository's
|
|
22
|
+
`CONTRAST_TEST_STABLE_WATCH=1` setup to preload its known dependencies before
|
|
23
|
+
navigation. Required CI delivery remains separate from this functional proof.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package dev.contrast.kotlinscroll
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.background
|
|
4
|
+
import androidx.compose.foundation.horizontalScroll
|
|
5
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
6
|
+
import androidx.compose.foundation.layout.Column
|
|
7
|
+
import androidx.compose.foundation.layout.Row
|
|
8
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
9
|
+
import androidx.compose.foundation.layout.padding
|
|
10
|
+
import androidx.compose.foundation.layout.size
|
|
11
|
+
import androidx.compose.foundation.lazy.LazyColumn
|
|
12
|
+
import androidx.compose.foundation.lazy.LazyRow
|
|
13
|
+
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
14
|
+
import androidx.compose.foundation.lazy.grid.GridCells
|
|
15
|
+
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|
16
|
+
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
|
17
|
+
import androidx.compose.foundation.rememberScrollState
|
|
18
|
+
import androidx.compose.foundation.verticalScroll
|
|
19
|
+
import androidx.compose.material3.Button
|
|
20
|
+
import androidx.compose.material3.MaterialTheme
|
|
21
|
+
import androidx.compose.material3.Surface
|
|
22
|
+
import androidx.compose.material3.Text
|
|
23
|
+
import androidx.compose.material3.lightColorScheme
|
|
24
|
+
import androidx.compose.runtime.Composable
|
|
25
|
+
import androidx.compose.runtime.getValue
|
|
26
|
+
import androidx.compose.runtime.mutableStateOf
|
|
27
|
+
import androidx.compose.runtime.remember
|
|
28
|
+
import androidx.compose.runtime.rememberCoroutineScope
|
|
29
|
+
import androidx.compose.runtime.setValue
|
|
30
|
+
import androidx.compose.ui.Modifier
|
|
31
|
+
import androidx.compose.ui.graphics.Color
|
|
32
|
+
import androidx.compose.ui.platform.testTag
|
|
33
|
+
import androidx.compose.ui.unit.dp
|
|
34
|
+
import kotlinx.coroutines.launch
|
|
35
|
+
|
|
36
|
+
@Composable
|
|
37
|
+
fun Scroll(title: String, onStep: ((Int) -> Unit)? = null) {
|
|
38
|
+
var count by remember { mutableStateOf(0) }
|
|
39
|
+
val vertical = rememberScrollState()
|
|
40
|
+
val horizontal = rememberScrollState()
|
|
41
|
+
val column = rememberLazyListState()
|
|
42
|
+
val row = rememberLazyListState()
|
|
43
|
+
val grid = rememberLazyGridState()
|
|
44
|
+
val scope = rememberCoroutineScope()
|
|
45
|
+
MaterialTheme(colorScheme = lightColorScheme()) {
|
|
46
|
+
Surface(Modifier.fillMaxSize()) {
|
|
47
|
+
Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
48
|
+
Text(title, Modifier.testTag("scroll-title"))
|
|
49
|
+
Text("Count: $count", Modifier.testTag("scroll-count"))
|
|
50
|
+
Column(Modifier.size(280.dp, 64.dp).verticalScroll(vertical).background(Color(0xFFEADDFF))) {
|
|
51
|
+
repeat(20) { Text("Vertical $it", Modifier.size(280.dp, 32.dp)) }
|
|
52
|
+
}
|
|
53
|
+
Row(Modifier.size(280.dp, 48.dp).horizontalScroll(horizontal).background(Color(0xFFE8DEF8))) {
|
|
54
|
+
repeat(20) { Text("Horizontal $it", Modifier.size(100.dp, 48.dp)) }
|
|
55
|
+
}
|
|
56
|
+
LazyColumn(Modifier.size(280.dp, 64.dp).background(Color(0xFFEADDFF)), state = column) {
|
|
57
|
+
items(30) { Text("Column $it", Modifier.size(280.dp, 32.dp)) }
|
|
58
|
+
}
|
|
59
|
+
LazyRow(Modifier.size(280.dp, 48.dp).background(Color(0xFFE8DEF8)), state = row) {
|
|
60
|
+
items(30) { Text("Row $it", Modifier.size(100.dp, 48.dp)) }
|
|
61
|
+
}
|
|
62
|
+
LazyVerticalGrid(columns = GridCells.Fixed(2), modifier = Modifier.size(280.dp, 64.dp).background(Color(0xFFEADDFF)), state = grid) {
|
|
63
|
+
items(30) { Text("Grid $it", Modifier.size(140.dp, 32.dp)) }
|
|
64
|
+
}
|
|
65
|
+
Button(
|
|
66
|
+
onClick = {
|
|
67
|
+
scope.launch {
|
|
68
|
+
val next = count + 1
|
|
69
|
+
val moved = next % 2 == 1
|
|
70
|
+
vertical.scrollTo(if (moved) 180 else 0)
|
|
71
|
+
horizontal.scrollTo(if (moved) 80 else 0)
|
|
72
|
+
column.scrollToItem(if (moved) 5 else 0, if (moved) 8 else 0)
|
|
73
|
+
row.scrollToItem(if (moved) 4 else 0, if (moved) 4 else 0)
|
|
74
|
+
grid.scrollToItem(if (moved) 8 else 0, if (moved) 6 else 0)
|
|
75
|
+
count = next
|
|
76
|
+
onStep?.invoke(next)
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
modifier = Modifier.testTag("scroll-step"),
|
|
80
|
+
) { Text("Next scroll step") }
|
|
81
|
+
Button(onClick = { count += 1000; onStep?.invoke(count) }, enabled = false, modifier = Modifier.testTag("scroll-disabled")) {
|
|
82
|
+
Text("Disabled scroll step")
|
|
83
|
+
}
|
|
84
|
+
Text(
|
|
85
|
+
"vertical=${vertical.value};horizontal=${horizontal.value};column=${column.firstVisibleItemIndex},${column.firstVisibleItemScrollOffset};row=${row.firstVisibleItemIndex},${row.firstVisibleItemScrollOffset};grid=${grid.firstVisibleItemIndex},${grid.firstVisibleItemScrollOffset}",
|
|
86
|
+
Modifier.testTag("scroll-geometry"),
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportScroll.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-scroll-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: 'KotlinScroll',
|
|
12
|
+
scheme: 'kotlinscroll',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinscroll' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Pressable, Text, View } from 'react-native'
|
|
3
|
+
import { Selection } from './Selection.kt'
|
|
4
|
+
|
|
5
|
+
type SelectionEvent = [string, boolean, number]
|
|
6
|
+
|
|
7
|
+
export default function Index() {
|
|
8
|
+
const [title, setTitle] = useState('Imported selection')
|
|
9
|
+
const [enabled, setEnabled] = useState(true)
|
|
10
|
+
const [events, setEvents] = useState<SelectionEvent[]>([])
|
|
11
|
+
return (
|
|
12
|
+
<View style={{ flex: 1, paddingTop: 48, backgroundColor: '#fff' }}>
|
|
13
|
+
<View style={{ flex: 1 }}>
|
|
14
|
+
<Selection
|
|
15
|
+
title={title}
|
|
16
|
+
enabled={enabled}
|
|
17
|
+
onSelection={(source, value, count) =>
|
|
18
|
+
setEvents((previous) => [...previous, [source, value, count]])
|
|
19
|
+
}
|
|
20
|
+
/>
|
|
21
|
+
</View>
|
|
22
|
+
<View style={{ height: 200, padding: 24 }}>
|
|
23
|
+
<Text testID="selection-props">{JSON.stringify({ title, enabled })}</Text>
|
|
24
|
+
<Text testID="selection-events">{JSON.stringify(events)}</Text>
|
|
25
|
+
<Pressable
|
|
26
|
+
testID="selection-title"
|
|
27
|
+
onPress={() =>
|
|
28
|
+
setTitle((value) =>
|
|
29
|
+
value === 'Imported selection' ? 'Updated selection' : 'Imported selection',
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<Text>Update title</Text>
|
|
34
|
+
</Pressable>
|
|
35
|
+
<Pressable
|
|
36
|
+
testID="selection-enabled"
|
|
37
|
+
onPress={() => setEnabled((value) => !value)}
|
|
38
|
+
>
|
|
39
|
+
<Text>{enabled ? 'Disable controls' : 'Enable controls'}</Text>
|
|
40
|
+
</Pressable>
|
|
41
|
+
</View>
|
|
42
|
+
</View>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Imported Compose selection controls
|
|
2
|
+
|
|
3
|
+
This fixture imports a public composable into a React Native app and reports
|
|
4
|
+
Switch, Checkbox, and RadioButton callbacks to React. Compose retains its
|
|
5
|
+
selection and callback count when React changes the title or enabled 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 native Android with
|
|
9
|
+
`bunx one prebuild --platform android`; build `android/` with
|
|
10
|
+
`./gradlew assembleDebug` on the repository's remote builder.
|
|
11
|
+
|
|
12
|
+
Toggle the React title twice before touching a native control. Tap Switch,
|
|
13
|
+
update the title, tap Checkbox, then RadioButton. Disable the controls and tap
|
|
14
|
+
Switch: neither Compose state nor React events may change. Enable them and
|
|
15
|
+
tap Checkbox again. The final state is `Updated selection|false|4|true`, and
|
|
16
|
+
`selection-events` contains
|
|
17
|
+
`[["switch",true,1],["checkbox",false,2],["radio",true,3],["checkbox",false,4]]`.
|
|
18
|
+
|
|
19
|
+
RAN 2026-10-11: Android debug and Kotlin/Wasm builds passed, followed in order
|
|
20
|
+
by One Android, Peach, and Contrast's native bundle producer. All eleven
|
|
21
|
+
observed states and the callback tuples above matched across the three hosts.
|
|
22
|
+
Peach and Contrast reported no preview errors. Contrast compiled `Selection.kt`
|
|
23
|
+
through its Kotlin import route and produced a complete bundle graph.
|
|
24
|
+
|
|
25
|
+
These runs used One `2.0.0-0.canary.1791724440037`, source
|
|
26
|
+
`65f7d27e6e6cbf33e94e41de7b8667c13c6a6077`, whose HMR socket uses the native
|
|
27
|
+
bundle server's origin. The earlier canary's connection-error toast intercepted
|
|
28
|
+
the React footer tap on Android. A separate direct Android tap now changes the
|
|
29
|
+
title, and the full interaction then passes on the unchanged Android native
|
|
30
|
+
sources. This establishes import and interaction behavior; it does not grade
|
|
31
|
+
pixels or the signed-in editor. Hashes, captures, and receipts are retained in
|
|
32
|
+
task `t-mv3qgkej-1kh0`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// generated by one typegen; edits will be replaced
|
|
2
|
+
import type { ReactElement } from 'react'
|
|
3
|
+
|
|
4
|
+
export declare function Selection(props: {
|
|
5
|
+
title: string
|
|
6
|
+
enabled: boolean
|
|
7
|
+
onSelection?: ((value0: string, value1: boolean, value2: number) => void) | null
|
|
8
|
+
}): ReactElement
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
package dev.contrast.kotlinselection
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
4
|
+
import androidx.compose.foundation.layout.Column
|
|
5
|
+
import androidx.compose.foundation.layout.Row
|
|
6
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
7
|
+
import androidx.compose.foundation.layout.padding
|
|
8
|
+
import androidx.compose.material3.Checkbox
|
|
9
|
+
import androidx.compose.material3.MaterialTheme
|
|
10
|
+
import androidx.compose.material3.RadioButton
|
|
11
|
+
import androidx.compose.material3.Surface
|
|
12
|
+
import androidx.compose.material3.Switch
|
|
13
|
+
import androidx.compose.material3.Text
|
|
14
|
+
import androidx.compose.material3.lightColorScheme
|
|
15
|
+
import androidx.compose.runtime.Composable
|
|
16
|
+
import androidx.compose.runtime.getValue
|
|
17
|
+
import androidx.compose.runtime.mutableStateOf
|
|
18
|
+
import androidx.compose.runtime.remember
|
|
19
|
+
import androidx.compose.runtime.setValue
|
|
20
|
+
import androidx.compose.ui.Alignment
|
|
21
|
+
import androidx.compose.ui.Modifier
|
|
22
|
+
import androidx.compose.ui.platform.testTag
|
|
23
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
24
|
+
import androidx.compose.ui.semantics.semantics
|
|
25
|
+
import androidx.compose.ui.unit.dp
|
|
26
|
+
|
|
27
|
+
@Composable
|
|
28
|
+
fun Selection(
|
|
29
|
+
title: String,
|
|
30
|
+
enabled: Boolean,
|
|
31
|
+
onSelection: ((String, Boolean, Int) -> Unit)? = null,
|
|
32
|
+
) {
|
|
33
|
+
var selected by remember { mutableStateOf(false) }
|
|
34
|
+
var changes by remember { mutableStateOf(0) }
|
|
35
|
+
fun change(source: String, value: Boolean) {
|
|
36
|
+
selected = value
|
|
37
|
+
changes += 1
|
|
38
|
+
onSelection?.invoke(source, value, changes)
|
|
39
|
+
}
|
|
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("$title|$selected|$changes|$enabled", Modifier.testTag("selection-state"))
|
|
48
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
49
|
+
Switch(
|
|
50
|
+
checked = selected,
|
|
51
|
+
enabled = enabled,
|
|
52
|
+
onCheckedChange = { change("switch", it) },
|
|
53
|
+
modifier = Modifier.testTag("selection-switch").semantics { contentDescription = "selection-switch" },
|
|
54
|
+
)
|
|
55
|
+
Text("Switch")
|
|
56
|
+
}
|
|
57
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
58
|
+
Checkbox(
|
|
59
|
+
checked = selected,
|
|
60
|
+
enabled = enabled,
|
|
61
|
+
onCheckedChange = { change("checkbox", it) },
|
|
62
|
+
modifier = Modifier.testTag("selection-checkbox").semantics { contentDescription = "selection-checkbox" },
|
|
63
|
+
)
|
|
64
|
+
Text("Checkbox")
|
|
65
|
+
}
|
|
66
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
67
|
+
RadioButton(
|
|
68
|
+
selected = selected,
|
|
69
|
+
enabled = enabled,
|
|
70
|
+
onClick = { change("radio", !selected) },
|
|
71
|
+
modifier = Modifier.testTag("selection-radio").semantics { contentDescription = "selection-radio" },
|
|
72
|
+
)
|
|
73
|
+
Text("Radio button")
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportSelection.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-selection-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: 'KotlinSelection',
|
|
12
|
+
scheme: 'kotlinselection',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinselection' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Text, View } from 'react-native'
|
|
3
|
+
import { Surfaces } from './Surfaces.kt'
|
|
4
|
+
|
|
5
|
+
export default function Index() {
|
|
6
|
+
const [step, setStep] = useState(0)
|
|
7
|
+
return (
|
|
8
|
+
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
|
9
|
+
<Surfaces title={`Surfaces step ${step}`} onStep={setStep} />
|
|
10
|
+
<Text testID="surfaces-react-step">React step: {step}</Text>
|
|
11
|
+
</View>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Imported Compose surfaces
|
|
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
|
+
Tap `surfaces-step` to alternate Material light and dark color schemes. The
|
|
8
|
+
callback updates React and the imported title while Compose retains count.
|
|
9
|
+
Capture the rounded Surface, cut corner Card and horizontal divider in all
|
|
10
|
+
four states: light zero, dark one, disabled one and restored light two.
|
|
11
|
+
The disabled button must preserve count and every palette value. Read the
|
|
12
|
+
actual color scheme ARGB values on native Android and require both imported
|
|
13
|
+
hosts to match. These checks prove execution and state, without a pixel grade.
|
|
14
|
+
|
|
15
|
+
RAN, 2026-10-11: fresh One Android API 37, Peach and Contrast Android import
|
|
16
|
+
runs pass all four states with identical palette readbacks and callback values.
|
|
17
|
+
The [functional receipt](https://r2.sootsim.com/kotlin-evidence/import-surfaces/1575299a492a37b497f5e923be69b865c2fae9c81d62b448810bed330596d052/proof.json)
|
|
18
|
+
binds Kotlin source, compiler, native APK, captures and executed probes.
|
|
19
|
+
All 50 published objects pass SHA256 readback. A wrong surface color and a
|
|
20
|
+
disabled callback change reject the saved verdict. Required CI delivery remains
|
|
21
|
+
separate from this functional proof. The existing preview shell chrome and
|
|
22
|
+
native debug HMR warning remain in captures; their fidelity is unclaimed.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package dev.contrast.kotlinsurfaces
|
|
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.foundation.layout.size
|
|
8
|
+
import androidx.compose.foundation.shape.CutCornerShape
|
|
9
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
10
|
+
import androidx.compose.material3.Button
|
|
11
|
+
import androidx.compose.material3.Card
|
|
12
|
+
import androidx.compose.material3.CardDefaults
|
|
13
|
+
import androidx.compose.material3.HorizontalDivider
|
|
14
|
+
import androidx.compose.material3.MaterialTheme
|
|
15
|
+
import androidx.compose.material3.Surface
|
|
16
|
+
import androidx.compose.material3.Text
|
|
17
|
+
import androidx.compose.material3.darkColorScheme
|
|
18
|
+
import androidx.compose.material3.lightColorScheme
|
|
19
|
+
import androidx.compose.runtime.Composable
|
|
20
|
+
import androidx.compose.runtime.getValue
|
|
21
|
+
import androidx.compose.runtime.mutableStateOf
|
|
22
|
+
import androidx.compose.runtime.remember
|
|
23
|
+
import androidx.compose.runtime.setValue
|
|
24
|
+
import androidx.compose.ui.Modifier
|
|
25
|
+
import androidx.compose.ui.graphics.toArgb
|
|
26
|
+
import androidx.compose.ui.platform.testTag
|
|
27
|
+
import androidx.compose.ui.unit.dp
|
|
28
|
+
|
|
29
|
+
@Composable
|
|
30
|
+
fun Surfaces(title: String, onStep: ((Int) -> Unit)? = null) {
|
|
31
|
+
var count by remember { mutableStateOf(0) }
|
|
32
|
+
val dark = count % 2 == 1
|
|
33
|
+
val scheme = if (dark) darkColorScheme() else lightColorScheme()
|
|
34
|
+
MaterialTheme(colorScheme = scheme) {
|
|
35
|
+
Surface(Modifier.fillMaxSize()) {
|
|
36
|
+
Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
37
|
+
Text(title, Modifier.testTag("surfaces-title"))
|
|
38
|
+
Text("Count: $count", Modifier.testTag("surfaces-count"))
|
|
39
|
+
Surface(
|
|
40
|
+
modifier = Modifier.size(280.dp, 64.dp).testTag("surfaces-rounded"),
|
|
41
|
+
shape = RoundedCornerShape(12.dp),
|
|
42
|
+
color = scheme.primary,
|
|
43
|
+
contentColor = scheme.onPrimary,
|
|
44
|
+
) { Text("Rounded surface", Modifier.padding(12.dp)) }
|
|
45
|
+
Card(
|
|
46
|
+
modifier = Modifier.size(280.dp, 64.dp).testTag("surfaces-cut"),
|
|
47
|
+
shape = CutCornerShape(8.dp),
|
|
48
|
+
colors = CardDefaults.cardColors(containerColor = scheme.secondaryContainer),
|
|
49
|
+
) { Text("Cut corner card", Modifier.padding(12.dp)) }
|
|
50
|
+
HorizontalDivider(Modifier.size(280.dp, 2.dp).testTag("surfaces-divider"), thickness = 2.dp)
|
|
51
|
+
Button(onClick = { count += 1; onStep?.invoke(count) }, modifier = Modifier.testTag("surfaces-step")) {
|
|
52
|
+
Text("Next surfaces step")
|
|
53
|
+
}
|
|
54
|
+
Button(onClick = { count += 1000; onStep?.invoke(count) }, enabled = false, modifier = Modifier.testTag("surfaces-disabled")) {
|
|
55
|
+
Text("Disabled surfaces step")
|
|
56
|
+
}
|
|
57
|
+
Text(
|
|
58
|
+
"dark=${if (dark) 1 else 0};surface=${scheme.surface.toArgb()};onSurface=${scheme.onSurface.toArgb()};primary=${scheme.primary.toArgb()};secondaryContainer=${scheme.secondaryContainer.toArgb()}",
|
|
59
|
+
Modifier.testTag("surfaces-palette"),
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../ImportSurfaces.native'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peach-kotlin-import-surfaces-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: 'KotlinSurfaces',
|
|
12
|
+
scheme: 'kotlinsurfaces',
|
|
13
|
+
android: { applicationId: 'dev.contrast.kotlinsurfaces' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
peachPlugin(),
|
|
18
|
+
],
|
|
19
|
+
server: { host: '0.0.0.0' },
|
|
20
|
+
}
|