create-disposabl-app 0.0.4 → 0.1.1
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/dist/index.js +490 -105
- package/dist/templates/default/LICENSE +21 -0
- package/dist/templates/default/apps/blog/package.json +1 -0
- package/dist/templates/default/apps/changelog/package.json +1 -0
- package/dist/templates/default/apps/desktop/.oxfmtrc.json +5 -0
- package/dist/templates/default/apps/desktop/.oxlintrc.json +6 -0
- package/dist/templates/default/apps/desktop/README.md +58 -0
- package/dist/templates/default/apps/desktop/forge.config.mts +90 -0
- package/dist/templates/default/apps/desktop/index.html +12 -0
- package/dist/templates/default/apps/desktop/package.json +55 -0
- package/dist/templates/default/apps/desktop/src/declarations.d.ts +2 -0
- package/dist/templates/default/apps/desktop/src/index.css +8 -0
- package/dist/templates/default/apps/desktop/src/main.ts +58 -0
- package/dist/templates/default/apps/desktop/src/preload.ts +3 -0
- package/dist/templates/default/apps/desktop/src/renderer.ts +19 -0
- package/dist/templates/default/apps/desktop/tsconfig.json +14 -0
- package/dist/templates/default/apps/desktop/vite.main.config.mts +4 -0
- package/dist/templates/default/apps/desktop/vite.preload.config.mts +4 -0
- package/dist/templates/default/apps/desktop/vite.renderer.config.mts +4 -0
- package/dist/templates/default/apps/docs/package.json +1 -0
- package/dist/templates/default/apps/mobile/.agents/skills/agent-device/SKILL.md +22 -0
- package/dist/templates/default/apps/mobile/.agents/skills/android-emulator/SKILL.md +32 -0
- package/dist/templates/default/apps/mobile/.agents/skills/dogfood/SKILL.md +27 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/SKILL.md +176 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/app-store-metadata.md +497 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/ios-app-store.md +376 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/native-ios.md +167 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/play-store.md +244 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/testflight.md +62 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/workflows.md +120 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-hosting/SKILL.md +431 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-hosting/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/SKILL.md +46 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/metrics.md +98 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/queries.md +444 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/setup.md +529 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/third-party.md +136 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/SKILL.md +237 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/controllers.md +139 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/logs-and-crashes.md +101 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/run-your-app.md +256 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/troubleshooting.md +56 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update/SKILL.md +146 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/SKILL.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/SKILL.md +99 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/scripts/fetch.js +109 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/scripts/package.json +6 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/LICENSE +21 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/RECIPES.md +385 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/SKILL.md +274 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/SKILL.md +290 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/references/native-module.md +96 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/SKILL.md +69 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/brownfield-integrated.md +551 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/brownfield-isolated.md +449 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/comparison.md +63 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/feature-integration.md +163 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/version-compatibility.md +40 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/SKILL.md +478 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/references/expo-router-loaders.md +341 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/references/offline-and-cancellation.md +68 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/SKILL.md +376 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/references/audit.md +190 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/references/native-slop.md +74 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dev-client/SKILL.md +184 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dev-client/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dom/SKILL.md +425 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dom/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/SKILL.md +106 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/references/catalog.md +105 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/SKILL.md +124 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/compatibility.md +130 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/example.md +212 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/migration-map.md +457 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/SKILL.md +151 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/config-plugin.md +90 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/create-expo-module.md +206 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/lifecycle.md +127 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/module-config.md +48 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/native-module.md +286 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/native-view.md +171 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/SKILL.md +201 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/controls.md +231 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/gradients.md +106 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/icons.md +232 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/media.md +193 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/storage.md +121 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/visual-effects.md +198 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/webgpu-three.md +605 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/SKILL.md +120 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/references/launch-without-dev-menu.md +24 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-project-structure/SKILL.md +114 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-project-structure/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/SKILL.md +240 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/form-sheet.md +253 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/route-structure.md +229 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/search.md +248 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/tabs.md +433 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/toolbar-and-headers.md +284 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/zoom-transitions.md +158 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/SKILL.md +314 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/agents/visual-grader.md +52 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/references/design-rubric.md +45 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/references/runtime-matrix.md +34 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/check-static.sh +64 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/clean-fixture.sh +56 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/generate_viewer.py +450 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/latest-sdk.sh +46 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/make-fixture.sh +95 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/make-workspace.sh +31 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-android.sh +284 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-ios.sh +132 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-web.sh +61 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/SKILL.md +101 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/drop-in-replacements.md +27 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/jetpack-compose.md +73 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/swift-ui.md +73 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/universal.md +104 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/scripts/list-components.js +193 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/SKILL.md +150 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/expo-av-to-audio.md +132 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/expo-av-to-video.md +160 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/native-tabs.md +124 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/new-architecture.md +79 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-19.md +79 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-compiler.md +59 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-navigation-to-expo-router.md +61 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/SKILL.md +91 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/false-friends.md +119 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/native-patterns.md +39 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/run-as-goal.md +48 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/verify-on-device.md +45 -0
- package/dist/templates/default/apps/mobile/.agents/skills/ios-simulator/SKILL.md +32 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/POWER.md +172 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/SKILL.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-analyze-app.md +208 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-analyze-js.md +264 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md +250 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-code-splitting.md +255 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-hermes-mmap.md +167 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-library-size.md +164 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-native-assets.md +208 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-r8-android.md +231 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-tree-shaking.md +215 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/bundle-treemap-source-map-explorer.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/controlled-textinput-pingpong.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/devtools-flamegraph.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/emerge-xray-ios.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/expo-atlas-treemap.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/flashlight-flatlist-vs-flashlist.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/fps-drop-graph.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/memory-heap-snapshot.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/tti-warm-start-diagram.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/view-hierarchy-flattening.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/xcode-instruments-templates.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/xcode-thread-view.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-animations-reanimated.md +273 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-atomic-state.md +190 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-bottomsheet.md +339 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-concurrent-react.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-lists-flatlist-flashlist.md +223 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-measure-fps.md +178 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-memory-leaks.md +168 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-profile-react.md +138 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-react-compiler.md +261 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-uncontrolled-components.md +219 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-android-16kb-alignment.md +114 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-measure-tti.md +221 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-memory-leaks.md +206 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-memory-patterns.md +240 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-platform-setup.md +112 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-profiling.md +140 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-sdks-over-polyfills.md +192 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-threading-model.md +230 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-turbo-modules.md +210 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-view-flattening.md +180 -0
- package/dist/templates/default/apps/mobile/AGENTS.md +41 -0
- package/dist/templates/default/apps/mobile/app.json +38 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/Assets/expo-symbol 2.svg +3 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/Assets/grid.png +0 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/icon.json +40 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-background.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-foreground.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-monochrome.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/icon.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/splash-icon.png +0 -0
- package/dist/templates/default/apps/mobile/eslint.config.js +10 -0
- package/dist/templates/default/apps/mobile/package.json +43 -0
- package/dist/templates/default/apps/mobile/skills-lock.json +185 -0
- package/dist/templates/default/apps/mobile/src/app/_layout.tsx +5 -0
- package/dist/templates/default/apps/mobile/src/app/index.tsx +17 -0
- package/dist/templates/default/apps/mobile/tsconfig.json +20 -0
- package/dist/templates/default/apps/web/.agents/skills/frontend-design/SKILL.md +71 -0
- package/dist/templates/default/apps/web/.agents/skills/web-design-guidelines/SKILL.md +39 -0
- package/dist/templates/default/apps/web/.env.example +3 -0
- package/dist/templates/default/apps/web/components.json +23 -0
- package/dist/templates/default/apps/web/eslint.config.ts +21 -0
- package/dist/templates/default/apps/web/package.json +39 -0
- package/dist/templates/default/apps/web/public/disposabl-logo.svg +8 -0
- package/dist/templates/default/apps/web/public/favicon.ico +0 -0
- package/dist/templates/default/apps/web/public/manifest.json +25 -0
- package/dist/templates/default/apps/web/skills-lock.json +17 -0
- package/dist/templates/default/apps/web/src/index.css +92 -0
- package/dist/templates/default/apps/web/src/routeTree.gen.ts +282 -0
- package/dist/templates/default/apps/web/src/router/__root.tsx +63 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/dashboard.tsx +9 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/todos/$id.tsx +27 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/todos/index.tsx +33 -0
- package/dist/templates/default/apps/web/src/router/index.tsx +15 -0
- package/dist/templates/default/apps/web/src/router.tsx +20 -0
- package/dist/templates/default/apps/web/tsconfig.json +33 -0
- package/dist/templates/default/apps/web/tsr.config.json +6 -0
- package/dist/templates/default/apps/web/vite.config.ts +67 -0
- package/dist/templates/default/bun.lock +3932 -0
- package/dist/templates/default/bunfig.toml +5 -0
- package/dist/templates/default/disposabl.json +5 -0
- package/dist/templates/default/gitignore +10 -0
- package/dist/templates/default/package.json +31 -10
- package/dist/templates/default/packages/backend/.agents/skills/convex/SKILL.md +69 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-add/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-advisor/SKILL.md +32 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-agent/SKILL.md +25 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-auth/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-authz/SKILL.md +36 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-backup/SKILL.md +33 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-billing/SKILL.md +69 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-cost/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/SKILL.md +325 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/agents/openai.yaml +14 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/assets/icon.svg +3 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/advanced-patterns.md +146 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/hybrid-components.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/local-components.md +39 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/packaged-components.md +54 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-crons/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-deploy-guard/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-design/SKILL.md +30 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-docs/SKILL.md +31 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-domains/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-env/SKILL.md +24 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-expert/SKILL.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-explain-app/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-improve-convex-plugin/SKILL.md +24 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-insights/SKILL.md +32 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-launch-readiness/SKILL.md +35 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-migrate/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-migrate-rehearse/SKILL.md +31 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-monitor/SKILL.md +22 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-optimize/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/agents/openai.yaml +14 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/assets/icon.svg +4 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-reviewer/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-seed/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-self-heal/SKILL.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-sentinel/SKILL.md +25 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-suggest/SKILL.md +27 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-test/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-verify/SKILL.md +34 -0
- package/dist/templates/default/packages/backend/.prettierignore +4 -0
- package/dist/templates/default/packages/backend/AGENTS.md +18 -0
- package/dist/templates/default/packages/backend/CLAUDE.md +13 -0
- package/dist/templates/default/packages/backend/README.md +25 -0
- package/dist/templates/default/packages/backend/convex/_generated/ai/ai-files.state.json +6 -0
- package/dist/templates/default/packages/backend/convex/_generated/ai/guidelines.md +286 -0
- package/dist/templates/default/packages/backend/convex/_generated/api.d.ts +66 -0
- package/dist/templates/default/packages/backend/convex/_generated/api.js +23 -0
- package/dist/templates/default/packages/backend/convex/_generated/dataModel.d.ts +60 -0
- package/dist/templates/default/packages/backend/convex/_generated/server.d.ts +164 -0
- package/dist/templates/default/packages/backend/convex/_generated/server.js +101 -0
- package/dist/templates/default/packages/backend/convex/auth.config.ts +14 -0
- package/dist/templates/default/packages/backend/convex/auth.ts +15 -0
- package/dist/templates/default/packages/backend/convex/convex.config.ts +30 -0
- package/dist/templates/default/packages/backend/convex/http.ts +5 -0
- package/dist/templates/default/packages/backend/convex/mcp.ts +8 -0
- package/dist/templates/default/packages/backend/convex/schema.ts +10 -0
- package/dist/templates/default/packages/backend/convex/todos/index.ts +26 -0
- package/dist/templates/default/packages/backend/convex/todos/internal.ts +43 -0
- package/dist/templates/default/packages/backend/convex/tsconfig.json +27 -0
- package/dist/templates/default/packages/backend/convex/users.ts +20 -0
- package/dist/templates/default/packages/backend/eslint.config.mjs +62 -0
- package/dist/templates/default/packages/backend/package.json +36 -0
- package/dist/templates/default/packages/backend/skills-lock.json +203 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/accordion.tsx +77 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/alert-dialog.tsx +185 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/alert.tsx +75 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/aspect-ratio.tsx +22 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/attachment.tsx +207 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/avatar.tsx +106 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/badge.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/breadcrumb.tsx +121 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/bubble.tsx +127 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/button-group.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/button.tsx +57 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/calendar.tsx +241 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/card.tsx +102 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/carousel.tsx +239 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/chart.tsx +368 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/checkbox.tsx +27 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/code-block.tsx +243 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/collapsible.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/combobox.tsx +300 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/command.tsx +194 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/context-menu.tsx +271 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/dialog.tsx +156 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/direction.tsx +4 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/drawer.tsx +224 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/dropdown-menu.tsx +269 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/empty.tsx +103 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/field.tsx +236 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/hover-card.tsx +50 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input-group.tsx +158 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input-otp.tsx +83 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/item.tsx +201 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/kbd.tsx +26 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/label.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/marker.tsx +70 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/menubar.tsx +284 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/message-scroller.tsx +128 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/message.tsx +91 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/native-select.tsx +64 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/navigation-menu.tsx +170 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/pagination.tsx +133 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/popover.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/progress.tsx +82 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/questionnaire.tsx +330 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/radio-group.tsx +35 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/resizable.tsx +49 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/scroll-area.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/select.tsx +201 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/separator.tsx +22 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/sheet.tsx +132 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/sidebar.tsx +723 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/skeleton.tsx +13 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/slider.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/spinner.tsx +16 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/switch.tsx +31 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/table.tsx +113 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/tabs.tsx +81 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/textarea.tsx +17 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toast.tsx +229 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toggle-group.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toggle.tsx +42 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/tooltip.tsx +65 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/trace.tsx +161 -0
- package/dist/templates/default/packages/disposabl-kit/client/hooks/use-mobile.ts +21 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/prerender.ts +89 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/return-to.ts +12 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/utils.ts +1 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_auth-pages/login.tsx +114 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_auth-pages/signUp.tsx +120 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_authenticated/route.tsx +38 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/consent.tsx +137 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/route.tsx +30 -0
- package/dist/templates/default/packages/disposabl-kit/client/styles/globals.css +60 -0
- package/dist/templates/default/packages/disposabl-kit/client/vite.config.ts +32 -0
- package/dist/templates/default/packages/disposabl-kit/components.json +23 -0
- package/dist/templates/default/packages/disposabl-kit/eslint.config.js +21 -0
- package/dist/templates/default/packages/disposabl-kit/package.json +60 -0
- package/dist/templates/default/packages/disposabl-kit/server/http.ts +86 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/functions.ts +40 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/platforms.ts +20 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/static-routes.ts +56 -0
- package/dist/templates/default/packages/disposabl-kit/tsconfig.json +17 -0
- package/dist/templates/default/patches/@convex-dev%2Fauth@2.0.0-beta.0.patch +310 -0
- package/dist/templates/default/patches/@convex-dev%2Fstatic-hosting@0.2.1.patch +187 -0
- package/dist/templates/default/tsconfig.json +9 -0
- package/dist/templates/default/turbo.json +51 -0
- package/package.json +21 -5
- package/README.md +0 -34
- package/dist/templates/default/README.md +0 -12
- package/dist/templates/default/docs/index.html +0 -8
- package/dist/templates/default/eslint.config.js +0 -18
- package/dist/templates/default/index.ts +0 -14
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Bottom Sheet
|
|
3
|
+
impact: HIGH
|
|
4
|
+
tags: bottom-sheet, gorhom, re-renders, shared-values, gestures, context, scrollable, modal, keyboard
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Bottom Sheet Best Practices
|
|
8
|
+
|
|
9
|
+
Optimize `@gorhom/bottom-sheet` for smooth 60 FPS by keeping gesture/scroll-driven state on the UI thread.
|
|
10
|
+
|
|
11
|
+
## Quick Pattern
|
|
12
|
+
|
|
13
|
+
**Incorrect (can re-enter JS repeatedly during interaction — full subtree re-render):**
|
|
14
|
+
|
|
15
|
+
```jsx
|
|
16
|
+
const handleAnimate = useCallback((fromIndex, toIndex) => {
|
|
17
|
+
setIsExpanded(toIndex > 0); // re-renders entire tree
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
<BottomSheet onAnimate={handleAnimate}>
|
|
21
|
+
<ExpensiveContent isExpanded={isExpanded} />
|
|
22
|
+
</BottomSheet>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (stays on UI thread — zero re-renders):**
|
|
26
|
+
|
|
27
|
+
```jsx
|
|
28
|
+
const animatedIndex = useSharedValue(0);
|
|
29
|
+
|
|
30
|
+
const overlayStyle = useAnimatedStyle(() => ({
|
|
31
|
+
opacity: interpolate(
|
|
32
|
+
animatedIndex.value,
|
|
33
|
+
[0, 1],
|
|
34
|
+
[0, 0.5],
|
|
35
|
+
Extrapolation.CLAMP
|
|
36
|
+
),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
<BottomSheet animatedIndex={animatedIndex}>
|
|
40
|
+
<ExpensiveContent />
|
|
41
|
+
</BottomSheet>
|
|
42
|
+
<Animated.View style={[styles.overlay, overlayStyle]} />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## When to Use
|
|
46
|
+
|
|
47
|
+
- Implementing or optimizing a bottom sheet with `@gorhom/bottom-sheet`
|
|
48
|
+
- Bottom sheet gestures cause jank or dropped frames
|
|
49
|
+
- Scroll inside bottom sheet triggers excessive re-renders
|
|
50
|
+
- Context provider wrapping bottom sheet re-renders the entire subtree
|
|
51
|
+
- Visual-only state (shadow, opacity, footer visibility) managed with `useState`
|
|
52
|
+
- Need to choose between `BottomSheet` and `BottomSheetModal`
|
|
53
|
+
- Scrollable content inside bottom sheet doesn't coordinate with gestures
|
|
54
|
+
- Keyboard doesn't interact properly with the sheet
|
|
55
|
+
|
|
56
|
+
## Prerequisites
|
|
57
|
+
|
|
58
|
+
- Check the official [`@gorhom/bottom-sheet` versioning / compatibility table](https://github.com/gorhom/react-native-bottom-sheet#versioning) first.
|
|
59
|
+
- If your app is on `@gorhom/bottom-sheet` below v5, upgrade to v5 before applying the patterns in this skill.
|
|
60
|
+
- `@gorhom/bottom-sheet` v5 is the current maintained line and is built for `react-native-reanimated` v3.
|
|
61
|
+
- `react-native-reanimated` v4 may work in some apps, but the bottom-sheet docs do not officially guarantee it. Decide explicitly whether to stay on v3 or try v4 and validate thoroughly on device.
|
|
62
|
+
- `react-native-gesture-handler` v2+
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @gorhom/bottom-sheet@^5 react-native-reanimated@^3 react-native-gesture-handler
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> **Note**: In v5, `enableDynamicSizing` defaults to `true`. If you need fixed snap-point indexing or do not want the library to insert a dynamic snap point based on content height, set `enableDynamicSizing={false}` explicitly.
|
|
69
|
+
|
|
70
|
+
## Problem Description
|
|
71
|
+
|
|
72
|
+
Bottom-sheet gesture, animation, and scroll callbacks that update React state can re-render the sheet subtree during interaction. In practice, callbacks like `onAnimate` may run repeatedly as the sheet retargets animations, which can cause visible jank if they drive expensive React updates.
|
|
73
|
+
|
|
74
|
+
## Step-by-Step Instructions
|
|
75
|
+
|
|
76
|
+
### 1. Convert Gesture-Driven State to SharedValue
|
|
77
|
+
|
|
78
|
+
Avoid React state for gesture-driven visual state. Update a shared value and consume it via `useAnimatedStyle`.
|
|
79
|
+
|
|
80
|
+
**Before:**
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
const [shadowOpacity, setShadowOpacity] = useState(0);
|
|
84
|
+
|
|
85
|
+
const handleAnimate = useCallback((fromIndex, toIndex) => {
|
|
86
|
+
setShadowOpacity(toIndex > 0 ? 0.3 : 0);
|
|
87
|
+
}, []);
|
|
88
|
+
|
|
89
|
+
<BottomSheet onAnimate={handleAnimate}>
|
|
90
|
+
<View style={{ shadowOpacity }}>
|
|
91
|
+
<HeavyContent />
|
|
92
|
+
</View>
|
|
93
|
+
</BottomSheet>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**After:**
|
|
97
|
+
|
|
98
|
+
```jsx
|
|
99
|
+
const animatedIndex = useSharedValue(0);
|
|
100
|
+
|
|
101
|
+
const shadowStyle = useAnimatedStyle(() => ({
|
|
102
|
+
shadowOpacity: interpolate(
|
|
103
|
+
animatedIndex.value,
|
|
104
|
+
[0, 1],
|
|
105
|
+
[0, 0.3],
|
|
106
|
+
Extrapolation.CLAMP
|
|
107
|
+
),
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
<BottomSheet animatedIndex={animatedIndex}>
|
|
111
|
+
<Animated.View style={shadowStyle}>
|
|
112
|
+
<HeavyContent />
|
|
113
|
+
</Animated.View>
|
|
114
|
+
</BottomSheet>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 2. Drive Sheet-Index Visibility via `useAnimatedReaction`
|
|
118
|
+
|
|
119
|
+
Toggling content based on sheet index via `{showFooter && <Footer/>}` causes mount/unmount cycles on every snap. Instead, always mount, animate visibility from `animatedIndex`, and bridge only the minimal boolean needed for `pointerEvents`/accessibility — scoped to a wrapper so the full tree doesn't re-render.
|
|
120
|
+
|
|
121
|
+
**Before:**
|
|
122
|
+
|
|
123
|
+
```jsx
|
|
124
|
+
const [showFooter, setShowFooter] = useState(false);
|
|
125
|
+
|
|
126
|
+
// re-mounts footer on every toggle
|
|
127
|
+
{showFooter && <Footer />}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**After:**
|
|
131
|
+
|
|
132
|
+
```jsx
|
|
133
|
+
const SheetVisibilityWrapper = ({ animatedIndex, threshold = 1, children }) => {
|
|
134
|
+
const [isInteractive, setIsInteractive] = useState(false);
|
|
135
|
+
|
|
136
|
+
const style = useAnimatedStyle(() => {
|
|
137
|
+
const progress = interpolate(
|
|
138
|
+
animatedIndex.value,
|
|
139
|
+
[threshold - 0.01, threshold],
|
|
140
|
+
[0, 1],
|
|
141
|
+
Extrapolation.CLAMP
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
opacity: progress,
|
|
146
|
+
transform: [{ translateY: interpolate(progress, [0, 1], [50, 0]) }],
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
useAnimatedReaction(
|
|
151
|
+
() => animatedIndex.value >= threshold,
|
|
152
|
+
(visible, prev) => {
|
|
153
|
+
if (visible !== prev) runOnJS(setIsInteractive)(visible);
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<Animated.View
|
|
159
|
+
style={style}
|
|
160
|
+
pointerEvents={isInteractive ? 'auto' : 'none'}
|
|
161
|
+
accessibilityElementsHidden={!isInteractive}
|
|
162
|
+
importantForAccessibility={isInteractive ? 'auto' : 'no-hide-descendants'}
|
|
163
|
+
>
|
|
164
|
+
{children}
|
|
165
|
+
</Animated.View>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Usage:
|
|
170
|
+
<SheetVisibilityWrapper animatedIndex={animatedIndex}>
|
|
171
|
+
<Footer />
|
|
172
|
+
</SheetVisibilityWrapper>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 3. Keep Scroll-Driven Logic off the JS Thread
|
|
176
|
+
|
|
177
|
+
`BottomSheetScrollView` ignores `scrollEventThrottle`, so setting it is not an optimization. Keep JS `onScroll` work minimal, or move scroll-driven logic to `useAnimatedScrollHandler` (see [js-animations-reanimated.md](./js-animations-reanimated.md)) so it stays on the UI thread:
|
|
178
|
+
|
|
179
|
+
```jsx
|
|
180
|
+
const scrollHandler = useAnimatedScrollHandler((event) => {
|
|
181
|
+
scrollY.value = event.contentOffset.y;
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
<BottomSheetScrollView onScroll={scrollHandler}>
|
|
185
|
+
<Content />
|
|
186
|
+
</BottomSheetScrollView>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 4. Use Library-Provided Components and Props
|
|
190
|
+
|
|
191
|
+
**Scrollables** — always use these instead of React Native built-ins inside a bottom sheet:
|
|
192
|
+
|
|
193
|
+
```jsx
|
|
194
|
+
import {
|
|
195
|
+
BottomSheetScrollView,
|
|
196
|
+
BottomSheetFlatList,
|
|
197
|
+
BottomSheetSectionList,
|
|
198
|
+
} from '@gorhom/bottom-sheet';
|
|
199
|
+
|
|
200
|
+
// FlashList v2: BottomSheetFlashList is deprecated.
|
|
201
|
+
// Create the scroll component, then pass it to FlashList.
|
|
202
|
+
import { useBottomSheetScrollableCreator } from '@gorhom/bottom-sheet';
|
|
203
|
+
import { FlashList } from '@shopify/flash-list';
|
|
204
|
+
|
|
205
|
+
const BottomSheetFlashListScrollComponent = useBottomSheetScrollableCreator();
|
|
206
|
+
|
|
207
|
+
<BottomSheet snapPoints={snapPoints} enableDynamicSizing={false}>
|
|
208
|
+
<FlashList
|
|
209
|
+
data={data}
|
|
210
|
+
keyExtractor={(item) => item.id}
|
|
211
|
+
renderItem={renderItem}
|
|
212
|
+
renderScrollComponent={BottomSheetFlashListScrollComponent}
|
|
213
|
+
/>
|
|
214
|
+
</BottomSheet>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Key props:**
|
|
218
|
+
|
|
219
|
+
| Prop | Purpose |
|
|
220
|
+
|------|---------|
|
|
221
|
+
| `containerHeight` | Provide to skip extra measurement re-render on mount |
|
|
222
|
+
| `enableDynamicSizing={false}` | Use when you want fixed snap-point indexing and do not want a dynamic content-height snap point inserted |
|
|
223
|
+
| `animatedIndex` | SharedValue for continuous index tracking on UI thread |
|
|
224
|
+
| `animatedPosition` | SharedValue for continuous position tracking on UI thread |
|
|
225
|
+
| `onChange` | Fires on snap **completion** only (discrete) — use for analytics/side effects |
|
|
226
|
+
| `onAnimate` | Fires before each animation start/retarget — use sparingly, because it can run repeatedly during interaction |
|
|
227
|
+
|
|
228
|
+
### 5. BottomSheetModal Setup
|
|
229
|
+
|
|
230
|
+
```jsx
|
|
231
|
+
import {
|
|
232
|
+
BottomSheetModal,
|
|
233
|
+
BottomSheetModalProvider,
|
|
234
|
+
} from '@gorhom/bottom-sheet';
|
|
235
|
+
|
|
236
|
+
const App = () => (
|
|
237
|
+
<BottomSheetModalProvider>
|
|
238
|
+
<BottomSheetModal
|
|
239
|
+
ref={modalRef}
|
|
240
|
+
snapPoints={snapPoints}
|
|
241
|
+
enableDismissOnClose={true}
|
|
242
|
+
>
|
|
243
|
+
<Content />
|
|
244
|
+
</BottomSheetModal>
|
|
245
|
+
</BottomSheetModalProvider>
|
|
246
|
+
);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**iOS layering fix** — use `FullWindowOverlay` to render above native navigation:
|
|
250
|
+
|
|
251
|
+
```jsx
|
|
252
|
+
import { FullWindowOverlay } from 'react-native-screens';
|
|
253
|
+
|
|
254
|
+
<BottomSheetModal
|
|
255
|
+
containerComponent={(props) => <FullWindowOverlay>{props.children}</FullWindowOverlay>}
|
|
256
|
+
>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 6. Keyboard Handling
|
|
260
|
+
|
|
261
|
+
```jsx
|
|
262
|
+
<BottomSheet
|
|
263
|
+
snapPoints={snapPoints}
|
|
264
|
+
enableDynamicSizing={false}
|
|
265
|
+
keyboardBehavior="interactive" // 'extend' | 'fillParent' | 'interactive'
|
|
266
|
+
keyboardBlurBehavior="restore" // reset sheet position when keyboard dismisses
|
|
267
|
+
enableBlurKeyboardOnGesture={true} // dismiss keyboard on drag
|
|
268
|
+
>
|
|
269
|
+
<BottomSheetTextInput
|
|
270
|
+
placeholder="Type here..."
|
|
271
|
+
style={styles.input}
|
|
272
|
+
/>
|
|
273
|
+
</BottomSheet>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
| `keyboardBehavior` | Effect |
|
|
277
|
+
|--------------------|--------|
|
|
278
|
+
| `extend` | Sheet grows to accommodate keyboard |
|
|
279
|
+
| `fillParent` | Sheet fills parent when keyboard appears |
|
|
280
|
+
| `interactive` | Sheet follows keyboard position interactively |
|
|
281
|
+
|
|
282
|
+
> Prefer `BottomSheetTextInput` inside a bottom sheet. If you need a custom input, copy the focus/blur handlers from the library's `BottomSheetTextInput` implementation so keyboard handling still works correctly.
|
|
283
|
+
|
|
284
|
+
## Derived Animations with `animatedPosition`
|
|
285
|
+
|
|
286
|
+
Use the `animatedPosition` shared value for smooth derived UI that stays on the UI thread:
|
|
287
|
+
|
|
288
|
+
```jsx
|
|
289
|
+
const animatedPosition = useSharedValue(0);
|
|
290
|
+
|
|
291
|
+
const backdropStyle = useAnimatedStyle(() => ({
|
|
292
|
+
opacity: interpolate(
|
|
293
|
+
animatedPosition.value,
|
|
294
|
+
[0, 300],
|
|
295
|
+
[0.5, 0],
|
|
296
|
+
Extrapolation.CLAMP
|
|
297
|
+
),
|
|
298
|
+
}));
|
|
299
|
+
|
|
300
|
+
<BottomSheet animatedPosition={animatedPosition} snapPoints={snapPoints}>
|
|
301
|
+
<Content />
|
|
302
|
+
</BottomSheet>
|
|
303
|
+
<Animated.View style={[StyleSheet.absoluteFill, backdropStyle]} pointerEvents="none" />
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Native Alternative: react-native-true-sheet
|
|
307
|
+
|
|
308
|
+
If your app already runs on **New Architecture (Fabric)** and needs a standard native-feeling sheet, evaluate `@lodev09/react-native-true-sheet`. Keep `@gorhom/bottom-sheet` when you need fine-grained Reanimated customization, custom gestures, or a mature cross-platform fallback.
|
|
309
|
+
|
|
310
|
+
| Scenario | Recommendation |
|
|
311
|
+
|----------|---------------|
|
|
312
|
+
| Need deep JS customization (custom gestures, animated derived UI) | `@gorhom/bottom-sheet` |
|
|
313
|
+
| Standard sheet with native feel + accessibility | `react-native-true-sheet` |
|
|
314
|
+
| Legacy Architecture (no Fabric) | `@gorhom/bottom-sheet` (true-sheet v3+ requires Fabric) |
|
|
315
|
+
| Web support needed | Either (true-sheet uses `@gorhom/bottom-sheet` on web internally) |
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
npm install @lodev09/react-native-true-sheet
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Common Pitfalls
|
|
322
|
+
|
|
323
|
+
- **Using `onChange` for continuous position tracking** — it fires on snap completion only (discrete). Use `animatedPosition` or `animatedIndex` shared values instead.
|
|
324
|
+
- **Starting timing animations inside sheet-index style worklets** — derive gesture-linked visuals with `interpolate`; reserve `withTiming` for explicit state transitions.
|
|
325
|
+
- **Forgetting `pointerEvents='none'` on always-mounted hidden elements** — invisible elements still capture touches.
|
|
326
|
+
- **Missing accessibility attributes on hidden elements** — add `accessibilityElementsHidden` and `importantForAccessibility='no-hide-descendants'`.
|
|
327
|
+
- **Bundling independent state values in one context** — see [js-atomic-state.md](./js-atomic-state.md) for splitting patterns.
|
|
328
|
+
- **Assuming `enableDynamicSizing` must be disabled whenever you pass `snapPoints`** — it does not have to be, but leaving it enabled can insert an additional snap point and change indexing.
|
|
329
|
+
- **Using React Native `ScrollView`/`FlatList` inside bottom sheet** — gestures won't coordinate. Use `BottomSheetScrollView`, `BottomSheetFlatList`, etc.
|
|
330
|
+
- **Gesture conflicts with React Native touchables** — when touches do not respond inside the sheet, use the touchable components exported by `@gorhom/bottom-sheet`, especially on Android.
|
|
331
|
+
- **Not providing `containerHeight`** — causes an extra re-render on mount for measurement.
|
|
332
|
+
- **Using a custom `TextInput` without porting the library's focus/blur handlers** — keyboard handling will be incomplete. Prefer `BottomSheetTextInput` unless you need a custom input.
|
|
333
|
+
|
|
334
|
+
## Related Skills
|
|
335
|
+
|
|
336
|
+
- [js-animations-reanimated.md](./js-animations-reanimated.md) — SharedValue and useAnimatedStyle fundamentals
|
|
337
|
+
- [js-atomic-state.md](./js-atomic-state.md) — Context splitting and atomic state patterns
|
|
338
|
+
- [js-profile-react.md](./js-profile-react.md) — Profiling to measure re-render reduction
|
|
339
|
+
- [js-measure-fps.md](./js-measure-fps.md) — Verify FPS improvement after optimization
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Concurrent React
|
|
3
|
+
impact: HIGH
|
|
4
|
+
tags: useDeferredValue, useTransition, suspense, concurrent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Concurrent React
|
|
8
|
+
|
|
9
|
+
Use `useDeferredValue` and `useTransition` to improve perceived performance by prioritizing critical updates.
|
|
10
|
+
|
|
11
|
+
## Quick Pattern
|
|
12
|
+
|
|
13
|
+
**Incorrect (blocks input on every keystroke):**
|
|
14
|
+
|
|
15
|
+
```jsx
|
|
16
|
+
const [query, setQuery] = useState('');
|
|
17
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
18
|
+
<ExpensiveList query={query} /> // Blocks typing
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Correct (input stays responsive):**
|
|
22
|
+
|
|
23
|
+
```jsx
|
|
24
|
+
const [query, setQuery] = useState('');
|
|
25
|
+
const deferredQuery = useDeferredValue(query);
|
|
26
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
27
|
+
<ExpensiveList query={deferredQuery} /> // Deferred update
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## When to Use
|
|
31
|
+
|
|
32
|
+
- Search/filter inputs feel laggy with large result sets
|
|
33
|
+
- Expensive computations block UI interactions
|
|
34
|
+
- Loading states appear too frequently
|
|
35
|
+
- Want to show stale content while loading new content
|
|
36
|
+
- Need to prioritize user input over background updates
|
|
37
|
+
|
|
38
|
+
## Prerequisites
|
|
39
|
+
|
|
40
|
+
- React 18+ features (`useDeferredValue`, `useTransition`, `Suspense`)
|
|
41
|
+
- React Native version that supports your target concurrent behavior; validate on the app architecture you ship
|
|
42
|
+
|
|
43
|
+
## Concept Overview
|
|
44
|
+
|
|
45
|
+
**Concurrent React** allows updates to be:
|
|
46
|
+
- **Paused**: Low-priority work can wait
|
|
47
|
+
- **Interrupted**: User input takes priority
|
|
48
|
+
- **Abandoned**: Outdated updates can be skipped
|
|
49
|
+
|
|
50
|
+
## Step-by-Step Instructions
|
|
51
|
+
|
|
52
|
+
### Pattern 1: Defer Expensive Rendering with `useDeferredValue`
|
|
53
|
+
|
|
54
|
+
Use when a value drives expensive computation but you want input to stay responsive.
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
import { useState, useDeferredValue } from 'react';
|
|
58
|
+
|
|
59
|
+
const SearchScreen = () => {
|
|
60
|
+
const [query, setQuery] = useState('');
|
|
61
|
+
const deferredQuery = useDeferredValue(query);
|
|
62
|
+
|
|
63
|
+
// query updates immediately (input stays responsive)
|
|
64
|
+
// deferredQuery updates when React has time
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<View>
|
|
68
|
+
<TextInput
|
|
69
|
+
value={query}
|
|
70
|
+
onChangeText={setQuery}
|
|
71
|
+
placeholder="Search..."
|
|
72
|
+
/>
|
|
73
|
+
{/* ExpensiveList receives deferred value */}
|
|
74
|
+
<ExpensiveList query={deferredQuery} />
|
|
75
|
+
</View>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Pattern 2: Show Stale Content While Loading
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
const SearchWithStaleIndicator = () => {
|
|
84
|
+
const [query, setQuery] = useState('');
|
|
85
|
+
const deferredQuery = useDeferredValue(query);
|
|
86
|
+
const isStale = query !== deferredQuery;
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<View>
|
|
90
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
91
|
+
<View style={isStale && { opacity: 0.7 }}>
|
|
92
|
+
<SearchResults query={deferredQuery} />
|
|
93
|
+
</View>
|
|
94
|
+
{isStale && <ActivityIndicator />}
|
|
95
|
+
</View>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Pattern 3: Transition Non-Critical Updates with `useTransition`
|
|
101
|
+
|
|
102
|
+
Use when you have multiple state updates and want to mark some as low-priority.
|
|
103
|
+
|
|
104
|
+
```jsx
|
|
105
|
+
import { useState, useTransition } from 'react';
|
|
106
|
+
|
|
107
|
+
const TransitionExample = () => {
|
|
108
|
+
const [count, setCount] = useState(0);
|
|
109
|
+
const [heavyData, setHeavyData] = useState(null);
|
|
110
|
+
const [isPending, startTransition] = useTransition();
|
|
111
|
+
|
|
112
|
+
const handleIncrement = () => {
|
|
113
|
+
// High priority - updates immediately
|
|
114
|
+
setCount(c => c + 1);
|
|
115
|
+
|
|
116
|
+
// Low priority - can be interrupted
|
|
117
|
+
startTransition(() => {
|
|
118
|
+
setHeavyData(computeExpensiveData());
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<View>
|
|
124
|
+
<Text>Count: {count}</Text>
|
|
125
|
+
{isPending ? <ActivityIndicator /> : <HeavyComponent data={heavyData} />}
|
|
126
|
+
<Button onPress={handleIncrement} title="Increment" />
|
|
127
|
+
</View>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Pattern 4: Suspense for Data Fetching
|
|
133
|
+
|
|
134
|
+
Use this only with a Suspense-enabled data source or framework integration. Wrapping arbitrary `fetch()` code in `Suspense` does not make it suspend automatically.
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
import { Suspense, useDeferredValue } from 'react';
|
|
138
|
+
|
|
139
|
+
const DataScreen = () => {
|
|
140
|
+
const [query, setQuery] = useState('');
|
|
141
|
+
const deferredQuery = useDeferredValue(query);
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<View>
|
|
145
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
146
|
+
<Suspense fallback={<LoadingSpinner />}>
|
|
147
|
+
<SearchResults query={deferredQuery} />
|
|
148
|
+
</Suspense>
|
|
149
|
+
</View>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Code Examples
|
|
155
|
+
|
|
156
|
+
### Slow Component Optimization
|
|
157
|
+
|
|
158
|
+
```jsx
|
|
159
|
+
// Without Concurrent React - UI freezes
|
|
160
|
+
const SlowSearch = () => {
|
|
161
|
+
const [query, setQuery] = useState('');
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<>
|
|
165
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
166
|
+
<SlowComponent query={query} /> {/* Blocks every keystroke */}
|
|
167
|
+
</>
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// With Concurrent React - UI stays responsive
|
|
172
|
+
const FastSearch = () => {
|
|
173
|
+
const [query, setQuery] = useState('');
|
|
174
|
+
const deferredQuery = useDeferredValue(query);
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
<TextInput value={query} onChangeText={setQuery} />
|
|
179
|
+
<SlowComponent query={deferredQuery} />
|
|
180
|
+
</>
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Important: Wrap SlowComponent in memo to prevent re-renders from parent
|
|
185
|
+
const SlowComponent = memo(({ query }) => {
|
|
186
|
+
// Expensive computation here
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Automatic Batching (React 18+)
|
|
191
|
+
|
|
192
|
+
React 18 automatically batches state updates:
|
|
193
|
+
|
|
194
|
+
```jsx
|
|
195
|
+
// Before React 18 - 2 re-renders
|
|
196
|
+
setTimeout(() => {
|
|
197
|
+
setCount(c => c + 1);
|
|
198
|
+
setFlag(f => !f);
|
|
199
|
+
// Rendered twice
|
|
200
|
+
}, 1000);
|
|
201
|
+
|
|
202
|
+
// React 18+ - 1 re-render (automatic batching)
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
setCount(c => c + 1);
|
|
205
|
+
setFlag(f => !f);
|
|
206
|
+
// Rendered once!
|
|
207
|
+
}, 1000);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## When to Use Which
|
|
211
|
+
|
|
212
|
+
| Scenario | Solution |
|
|
213
|
+
|----------|----------|
|
|
214
|
+
| Single value drives expensive render | `useDeferredValue` |
|
|
215
|
+
| Multiple state updates, some non-critical | `useTransition` |
|
|
216
|
+
| Need loading indicator for transition | `useTransition` (has `isPending`) |
|
|
217
|
+
| Data fetching with loading states | `Suspense` + `useDeferredValue` |
|
|
218
|
+
| Simple parent-to-child value deferral | `useDeferredValue` |
|
|
219
|
+
|
|
220
|
+
## Important Considerations
|
|
221
|
+
|
|
222
|
+
1. **Wrap expensive components in `memo()`**: Without memoization, the component re-renders from parent anyway.
|
|
223
|
+
|
|
224
|
+
2. **Validate on your shipped architecture**: Concurrent behavior depends on the React Native and React versions in the app.
|
|
225
|
+
|
|
226
|
+
3. **Don't overuse**: Only defer truly expensive work. Adding complexity for fast components is counterproductive.
|
|
227
|
+
|
|
228
|
+
## Common Pitfalls
|
|
229
|
+
|
|
230
|
+
- **Forgetting subtree isolation**: `useDeferredValue` helps most when the expensive subtree is memoized or otherwise isolated from immediate parent re-renders
|
|
231
|
+
- **Using for simple state**: Overhead isn't worth it for cheap updates
|
|
232
|
+
- **Expecting faster computation**: These hooks don't make code faster, they prioritize what runs when
|
|
233
|
+
|
|
234
|
+
## Related Skills
|
|
235
|
+
|
|
236
|
+
- [js-profile-react.md](./js-profile-react.md) - Identify slow components
|
|
237
|
+
- [js-react-compiler.md](./js-react-compiler.md) - Automatic memoization
|
|
238
|
+
- [js-lists-flatlist-flashlist.md](./js-lists-flatlist-flashlist.md) - For list-specific optimizations
|