@hanzogui/kitchen-sink 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/.detoxrc.js +130 -0
  2. package/.env.production +2 -0
  3. package/.maestro/config.yaml +4 -0
  4. package/.maestro/flows/shorthand-variables.yaml +23 -0
  5. package/.watchmanconfig +1 -0
  6. package/LICENSE +21 -0
  7. package/README.md +11 -0
  8. package/app.json +43 -0
  9. package/assets/adaptive-icon.png +0 -0
  10. package/assets/favicon.png +0 -0
  11. package/assets/icon.png +0 -0
  12. package/assets/splash.png +0 -0
  13. package/babel.config.js +25 -0
  14. package/e2e/CompilerExtraction.test.ts +147 -0
  15. package/e2e/GroupPressNative.test.ts +167 -0
  16. package/e2e/MediaQueryGtMd.test.ts +71 -0
  17. package/e2e/NativePortal.test.ts +113 -0
  18. package/e2e/PointerEvents.test.ts +116 -0
  19. package/e2e/PressStyleNative.noRngh.test.ts +191 -0
  20. package/e2e/PressStyleNative.test.ts +231 -0
  21. package/e2e/SafeArea.test.ts +57 -0
  22. package/e2e/SelectAndroidOnPress.test.ts +181 -0
  23. package/e2e/SelectRemount.test.ts +137 -0
  24. package/e2e/SheetDragResist.test.ts +370 -0
  25. package/e2e/SheetKeyboardDrag.test.ts +249 -0
  26. package/e2e/SheetScrollableDrag.test.ts +560 -0
  27. package/e2e/ShorthandVariables.test.ts +53 -0
  28. package/e2e/ThemeChangeBasic.test.ts +123 -0
  29. package/e2e/ThemeMutation.test.ts +80 -0
  30. package/e2e/check-rngh-status.test.ts +31 -0
  31. package/e2e/jest.config.js +19 -0
  32. package/e2e/utils/colors.ts +75 -0
  33. package/e2e/utils/navigation.ts +53 -0
  34. package/eas.json +22 -0
  35. package/flows/AlertDialog.yaml +17 -0
  36. package/flows/OpenApp.yaml +25 -0
  37. package/flows/Select.yaml +13 -0
  38. package/flows/Sheet.yaml +12 -0
  39. package/flows/Tabs.yaml +13 -0
  40. package/flows/Toast.yaml +14 -0
  41. package/flows/WarmUp.yaml +24 -0
  42. package/index.html +21 -0
  43. package/index.js +17 -0
  44. package/metro.config.js +64 -0
  45. package/next-router-shim.ts +9 -0
  46. package/package.json +118 -0
  47. package/plans/toast-2.md +471 -0
  48. package/playwright.config.ts +71 -0
  49. package/plugins/expo-modules-core-swift6.js +76 -0
  50. package/pod-install.sh +7 -0
  51. package/public/favicon.svg +70 -0
  52. package/public/fonts/inter.css +15 -0
  53. package/public/fonts/noto-cn.otf +0 -0
  54. package/public/gui-icon.svg +68 -0
  55. package/run-detox.sh +230 -0
  56. package/run-native-tests.sh +4 -0
  57. package/run-tests-parallel.ts +195 -0
  58. package/screenshots/Screenshotter.test.tsx +48 -0
  59. package/src/AnimationDemos.tsx +131 -0
  60. package/src/App.native.tsx +121 -0
  61. package/src/App.tsx +121 -0
  62. package/src/Navigation.tsx +98 -0
  63. package/src/Sandbox.tsx +87 -0
  64. package/src/TestDynamicEval.tsx +33 -0
  65. package/src/TestNativeSheet.tsx +100 -0
  66. package/src/components/TimedRender.tsx +18 -0
  67. package/src/constants/test-ids.ts +52 -0
  68. package/src/features/demos/demo-screen.tsx +72 -0
  69. package/src/features/home/ColorSchemeListItem.tsx +41 -0
  70. package/src/features/home/TestBuildAButton.tsx +102 -0
  71. package/src/features/home/TestSeparator.tsx +0 -0
  72. package/src/features/home/screen.tsx +285 -0
  73. package/src/features/testcases/screen.tsx +59 -0
  74. package/src/features/testcases/test-screen.tsx +50 -0
  75. package/src/generatedV5Theme.ts +112 -0
  76. package/src/gui.config.ts +411 -0
  77. package/src/guy.png +0 -0
  78. package/src/index.tsx +6 -0
  79. package/src/provider/index.tsx +18 -0
  80. package/src/test-gui-stack.tsx +11 -0
  81. package/src/test.tsx +3 -0
  82. package/src/useKitchenSinkTheme.tsx +15 -0
  83. package/src/usecases/ActionsSheetComparison.tsx +194 -0
  84. package/src/usecases/AnimatePresenceEnterExitCase.tsx +255 -0
  85. package/src/usecases/AnimatePresenceExitTest.tsx +69 -0
  86. package/src/usecases/AnimatedByProp.tsx +39 -0
  87. package/src/usecases/AnimationComprehensiveCase.tsx +2515 -0
  88. package/src/usecases/AnimationValueLoggingCase.tsx +526 -0
  89. package/src/usecases/AnimationsWithMediaQueriesCase.tsx +110 -0
  90. package/src/usecases/Benchmark.tsx +148 -0
  91. package/src/usecases/BenchmarkSelect.tsx +34 -0
  92. package/src/usecases/ButtonCircular.tsx +3 -0
  93. package/src/usecases/ButtonCustom.tsx +33 -0
  94. package/src/usecases/ButtonIconColor.tsx +18 -0
  95. package/src/usecases/ButtonInverse.tsx +30 -0
  96. package/src/usecases/ButtonUnstyled.tsx +31 -0
  97. package/src/usecases/CheckboxDisabledOnPress.tsx +62 -0
  98. package/src/usecases/ClickDuringEnterCase.tsx +59 -0
  99. package/src/usecases/CodeExamplesInput.tsx +9 -0
  100. package/src/usecases/ColorTokenFallback.tsx +52 -0
  101. package/src/usecases/CompilerExtraction.tsx +380 -0
  102. package/src/usecases/ComplexVariants.tsx +164 -0
  103. package/src/usecases/CrashAdaptSheet.tsx +98 -0
  104. package/src/usecases/CustomStyledAnimatedPopover.tsx +42 -0
  105. package/src/usecases/CustomStyledAnimatedTooltip.tsx +72 -0
  106. package/src/usecases/DOMNodeAPIs.tsx +154 -0
  107. package/src/usecases/DialogFocusScopeCase.tsx +277 -0
  108. package/src/usecases/DialogFocusScopeDebug.tsx +85 -0
  109. package/src/usecases/DialogNestedCase.tsx +121 -0
  110. package/src/usecases/DialogOpenControlled.tsx +49 -0
  111. package/src/usecases/DialogPointerEventsCase.tsx +58 -0
  112. package/src/usecases/DialogScopedCase.tsx +106 -0
  113. package/src/usecases/DialogSheetAdaptCase.tsx +178 -0
  114. package/src/usecases/DialogSheetAdaptResizeCase.tsx +98 -0
  115. package/src/usecases/DismissLayerStackingCase.tsx +223 -0
  116. package/src/usecases/DriverDisableAnimationPropsCase.tsx +44 -0
  117. package/src/usecases/Example.tsx +10 -0
  118. package/src/usecases/ExitCompletionCase.tsx +713 -0
  119. package/src/usecases/FocusVisibleButton.tsx +14 -0
  120. package/src/usecases/FocusVisibleButtonPointer.tsx +13 -0
  121. package/src/usecases/FocusVisibleButtonWithFocusStyle.tsx +16 -0
  122. package/src/usecases/FocusWithinCase.tsx +55 -0
  123. package/src/usecases/FontTokensInVariants.tsx +14 -0
  124. package/src/usecases/FormButtonTypeCase.tsx +34 -0
  125. package/src/usecases/GlobalScopedTriggerIsolationCase.tsx +178 -0
  126. package/src/usecases/GroupHoverMobile.tsx +39 -0
  127. package/src/usecases/GroupPressInVariant.tsx +92 -0
  128. package/src/usecases/GroupPressNative.tsx +200 -0
  129. package/src/usecases/GroupProp.tsx +96 -0
  130. package/src/usecases/GroupPseudoVariantOverride.tsx +56 -0
  131. package/src/usecases/GroupUseCases.tsx +94 -0
  132. package/src/usecases/HeightMediaQueryOverrideCase.tsx +183 -0
  133. package/src/usecases/InputAutoFocusAfterMenuCase.tsx +105 -0
  134. package/src/usecases/InputAutoFocusStyledCase.tsx +39 -0
  135. package/src/usecases/KeyboardControllerTest.tsx +146 -0
  136. package/src/usecases/ListItem.tsx +123 -0
  137. package/src/usecases/MediaQueriesV5.tsx +137 -0
  138. package/src/usecases/MediaQueryGtMd.tsx +73 -0
  139. package/src/usecases/MenuAboveDialogCase.tsx +75 -0
  140. package/src/usecases/MenuAccessibilityCase.tsx +133 -0
  141. package/src/usecases/MenuAnimatePositionCase.tsx +41 -0
  142. package/src/usecases/MenuArrowAnimatePresenceCase.tsx +98 -0
  143. package/src/usecases/MenuAsChildPositionCase.tsx +24 -0
  144. package/src/usecases/MenuAutoResizeCase.tsx +57 -0
  145. package/src/usecases/MenuBottomCase.tsx +55 -0
  146. package/src/usecases/MenuFocusLeaveCase.tsx +135 -0
  147. package/src/usecases/MenuHighlightCase.tsx +44 -0
  148. package/src/usecases/MenuItemFocusCase.tsx +79 -0
  149. package/src/usecases/MenuItemPseudoOverrideCase.tsx +270 -0
  150. package/src/usecases/MenuMultiTriggerCase.tsx +47 -0
  151. package/src/usecases/MenuOverflowCase.tsx +60 -0
  152. package/src/usecases/MenuSubCase.tsx +223 -0
  153. package/src/usecases/MenuSubLeftCase.tsx +178 -0
  154. package/src/usecases/MenuSubNestedPositionCase.tsx +171 -0
  155. package/src/usecases/MenuSubStyledCase.tsx +145 -0
  156. package/src/usecases/MenuThemeCase.tsx +50 -0
  157. package/src/usecases/MenuUnstyledCase.tsx +52 -0
  158. package/src/usecases/MultiDriverAnimation.tsx +118 -0
  159. package/src/usecases/NativePortalTest.tsx +179 -0
  160. package/src/usecases/NewInputBasic.tsx +16 -0
  161. package/src/usecases/NewInputEvents.tsx +29 -0
  162. package/src/usecases/NonGuiTextStyledType.tsx +23 -0
  163. package/src/usecases/OnLayoutCase.tsx +134 -0
  164. package/src/usecases/OnLayoutScaleCase.tsx +88 -0
  165. package/src/usecases/OnLayoutStressCase.tsx +353 -0
  166. package/src/usecases/OpacityModifierCase.tsx +113 -0
  167. package/src/usecases/OverlayStyled.tsx +66 -0
  168. package/src/usecases/ParagraphSpanFontInheritance.tsx +53 -0
  169. package/src/usecases/PlaceholderTextColor.tsx +20 -0
  170. package/src/usecases/PointerEventsCase.tsx +100 -0
  171. package/src/usecases/PopoverAndMenuMultiTriggerCase.tsx +138 -0
  172. package/src/usecases/PopoverCase.tsx +222 -0
  173. package/src/usecases/PopoverContentStyledPlusAnimations.tsx +44 -0
  174. package/src/usecases/PopoverFocusScopeCase.tsx +171 -0
  175. package/src/usecases/PopoverHoverableCase.tsx +167 -0
  176. package/src/usecases/PopoverHoverableDisableClickCase.tsx +118 -0
  177. package/src/usecases/PopoverHoverableRapidCase.tsx +103 -0
  178. package/src/usecases/PopoverHoverableScopedCase.tsx +135 -0
  179. package/src/usecases/PopoverScopedCase.tsx +76 -0
  180. package/src/usecases/PopoverTriggerIsolationCase.tsx +80 -0
  181. package/src/usecases/PressStyleNative.tsx +143 -0
  182. package/src/usecases/PseudoStyleMerge.tsx +25 -0
  183. package/src/usecases/PseudoTransitionCase.tsx +174 -0
  184. package/src/usecases/RawAnimatedValueCase.tsx +231 -0
  185. package/src/usecases/RemoveScrollCase.tsx +66 -0
  186. package/src/usecases/RenderPropCase.tsx +263 -0
  187. package/src/usecases/SafeAreaCase.tsx +236 -0
  188. package/src/usecases/ScrollViewRefCase.tsx +88 -0
  189. package/src/usecases/SecondPage.tsx +5 -0
  190. package/src/usecases/SelectAndroidOnPress.tsx +129 -0
  191. package/src/usecases/SelectFocusScopeCase.tsx +270 -0
  192. package/src/usecases/SelectRemount.tsx +136 -0
  193. package/src/usecases/Shadows.tsx +5 -0
  194. package/src/usecases/SheetAnimationCase.tsx +155 -0
  195. package/src/usecases/SheetDragCase.tsx +183 -0
  196. package/src/usecases/SheetDragResistCase.tsx +433 -0
  197. package/src/usecases/SheetDragResistCase.web.tsx +359 -0
  198. package/src/usecases/SheetKeyboardDragCase.tsx +328 -0
  199. package/src/usecases/SheetKeyboardFitContentCase.tsx +165 -0
  200. package/src/usecases/SheetOnAnimationCompleteCase.tsx +54 -0
  201. package/src/usecases/SheetScrollLockCase.tsx +166 -0
  202. package/src/usecases/SheetScrollableDrag.tsx +249 -0
  203. package/src/usecases/SheetSnapPointsFitCase.tsx +393 -0
  204. package/src/usecases/ShorthandVariables.tsx +49 -0
  205. package/src/usecases/SlowThemeReRender.tsx +48 -0
  206. package/src/usecases/SpinnerCustomColors.tsx +34 -0
  207. package/src/usecases/StackZIndex.tsx +82 -0
  208. package/src/usecases/StressPage.tsx +301 -0
  209. package/src/usecases/StylePlatform.tsx +30 -0
  210. package/src/usecases/StyleProp.tsx +29 -0
  211. package/src/usecases/StyledAnchor.tsx +27 -0
  212. package/src/usecases/StyledButtonAnimationAuto.tsx +99 -0
  213. package/src/usecases/StyledButtonTheme.tsx +63 -0
  214. package/src/usecases/StyledButtonVariantPseudo.tsx +25 -0
  215. package/src/usecases/StyledButtonVariantPseudoMerge.tsx +77 -0
  216. package/src/usecases/StyledCheckboxTheme.tsx +23 -0
  217. package/src/usecases/StyledContextColor.tsx +246 -0
  218. package/src/usecases/StyledContextTokens.tsx +147 -0
  219. package/src/usecases/StyledHOCNamed.tsx +20 -0
  220. package/src/usecases/StyledHtmlCase.tsx +144 -0
  221. package/src/usecases/StyledIconColor.tsx +19 -0
  222. package/src/usecases/StyledInputFocusStyle.tsx +21 -0
  223. package/src/usecases/StyledInputOnFocus.tsx +30 -0
  224. package/src/usecases/StyledMediaQueryMerge.tsx +95 -0
  225. package/src/usecases/StyledOverridePsuedo.tsx +26 -0
  226. package/src/usecases/StyledRNW.tsx +61 -0
  227. package/src/usecases/StyledStyleableInputOnFocus.tsx +34 -0
  228. package/src/usecases/StyledStyleableInputVariant.tsx +48 -0
  229. package/src/usecases/StyledStyledStyleableInputOnFocus.tsx +36 -0
  230. package/src/usecases/StyledVariantTextColor.tsx +25 -0
  231. package/src/usecases/StyledViewOnFocus.tsx +32 -0
  232. package/src/usecases/TabHoverAnimationCase.tsx +212 -0
  233. package/src/usecases/TextNestedInheritance.tsx +80 -0
  234. package/src/usecases/ThemeChange.tsx +100 -0
  235. package/src/usecases/ThemeChangeBasic.tsx +52 -0
  236. package/src/usecases/ThemeComponentResolution.tsx +119 -0
  237. package/src/usecases/ThemeConditionalName.tsx +31 -0
  238. package/src/usecases/ThemeMediaAnimationCase.tsx +39 -0
  239. package/src/usecases/ThemeMutation.tsx +86 -0
  240. package/src/usecases/ThemeNested.tsx +103 -0
  241. package/src/usecases/ThemeReset.tsx +62 -0
  242. package/src/usecases/ThemeShallowCase.tsx +83 -0
  243. package/src/usecases/ToastCase.tsx +46 -0
  244. package/src/usecases/ToggleGroupActiveProps.tsx +40 -0
  245. package/src/usecases/ToggleGroupXGroupCase.tsx +104 -0
  246. package/src/usecases/TooltipAnimationCase.tsx +99 -0
  247. package/src/usecases/TooltipCase.tsx +32 -0
  248. package/src/usecases/TooltipGlobalPatternCase.tsx +83 -0
  249. package/src/usecases/TooltipGroupCase.tsx +102 -0
  250. package/src/usecases/TooltipMultiTriggerCase.tsx +88 -0
  251. package/src/usecases/TooltipPositionJumpCase.tsx +91 -0
  252. package/src/usecases/TooltipTriggerInlineCase.tsx +60 -0
  253. package/src/usecases/TransformMediaQueryMerge.tsx +98 -0
  254. package/src/usecases/UseCases.tsx +409 -0
  255. package/src/usecases/UseTheme.tsx +41 -0
  256. package/src/usecases/V5ThemeBuilderOutput.tsx +231 -0
  257. package/src/usecases/VariantFontFamily.tsx +25 -0
  258. package/src/usecases/VariantsOrder.tsx +117 -0
  259. package/src/usecases/ZIndex.tsx +155 -0
  260. package/src/usecases/helpers.tsx +44 -0
  261. package/src/usecases/index.native.ts +122 -0
  262. package/src/usecases/index.ts +3 -0
  263. package/src/usecases/index.web.ts +177 -0
  264. package/tests/AnimatePresenceEnterExit.animated.test.tsx +176 -0
  265. package/tests/AnimatedByProp.animated.test.tsx +138 -0
  266. package/tests/AnimationBehavior.animated.test.tsx +543 -0
  267. package/tests/AnimationTiming.animated.test.tsx +195 -0
  268. package/tests/AnimationsWithMediaQueries.animated.test.tsx +154 -0
  269. package/tests/BuildAButton.test.tsx +87 -0
  270. package/tests/ButtonCircular.test.tsx +17 -0
  271. package/tests/ButtonCustom.test.tsx +17 -0
  272. package/tests/ButtonIconColor.test.tsx +23 -0
  273. package/tests/ButtonUnstyled.test.tsx +56 -0
  274. package/tests/ClickDuringEnter.animated.test.tsx +174 -0
  275. package/tests/ColorTokenFallback.test.tsx +45 -0
  276. package/tests/DOMNodeAPIs.test.tsx +161 -0
  277. package/tests/DialogFocusScope.animated.test.tsx +309 -0
  278. package/tests/DialogNested.test.tsx +128 -0
  279. package/tests/DialogOpenControlled.test.tsx +42 -0
  280. package/tests/DialogPointerEvents.animated.test.tsx +108 -0
  281. package/tests/DialogScoped.test.tsx +137 -0
  282. package/tests/DialogSheetAdapt.test.tsx +68 -0
  283. package/tests/DialogSheetAdaptResize.test.tsx +161 -0
  284. package/tests/DismissLayerStacking.test.tsx +292 -0
  285. package/tests/DriverDisableAnimationProps.animated.test.tsx +157 -0
  286. package/tests/ExitCompletion.animated.test.tsx +425 -0
  287. package/tests/ExitTimingCheck.animated.test.ts +34 -0
  288. package/tests/FocusVisibleButton.test.tsx +41 -0
  289. package/tests/FocusVisibleButtonPointerFocus.test.tsx +23 -0
  290. package/tests/FocusVisibleButtonPointerFocusWithFocusStyle.test.tsx +40 -0
  291. package/tests/FocusWithinStyle.animated.test.tsx +66 -0
  292. package/tests/FocusWithinStyle.test.tsx +60 -0
  293. package/tests/FormButtonType.test.tsx +42 -0
  294. package/tests/GlobalScopedTriggerIsolation.test.tsx +89 -0
  295. package/tests/GroupHoverMobile.test.tsx +52 -0
  296. package/tests/GroupPressInVariant.test.tsx +82 -0
  297. package/tests/GroupProp.test.tsx +30 -0
  298. package/tests/GroupPseudoVariantOverride.test.tsx +57 -0
  299. package/tests/GroupUseCases.test.tsx +111 -0
  300. package/tests/GuiSiteMotion.test.ts +481 -0
  301. package/tests/HeightMediaQueryOverride.test.tsx +112 -0
  302. package/tests/InputAutoFocusAfterMenu.test.tsx +55 -0
  303. package/tests/InputAutoFocusStyled.test.tsx +22 -0
  304. package/tests/ListItem.test.tsx +129 -0
  305. package/tests/MediaQueriesV5.test.tsx +113 -0
  306. package/tests/MediaQueryGtMd.test.tsx +84 -0
  307. package/tests/MenuAboveDialog.test.tsx +108 -0
  308. package/tests/MenuAccessibility.test.tsx +346 -0
  309. package/tests/MenuAnimatePosition.animated.test.tsx +57 -0
  310. package/tests/MenuArrowAnimatePresence.animated.test.tsx +71 -0
  311. package/tests/MenuAsChildPosition.test.tsx +16 -0
  312. package/tests/MenuAutoResize.test.tsx +54 -0
  313. package/tests/MenuFocusLeave.test.tsx +181 -0
  314. package/tests/MenuHighlight.test.tsx +165 -0
  315. package/tests/MenuHoverKeyboardBugs.test.tsx +252 -0
  316. package/tests/MenuItemFocus.test.tsx +59 -0
  317. package/tests/MenuItemPseudoOverride.test.tsx +231 -0
  318. package/tests/MenuMultiTrigger.test.tsx +101 -0
  319. package/tests/MenuOverflow.test.tsx +93 -0
  320. package/tests/MenuStayInFrame.test.tsx +102 -0
  321. package/tests/MenuSubKeyboardFocus.test.tsx +220 -0
  322. package/tests/MenuSubLeftSafePolygon.test.tsx +88 -0
  323. package/tests/MenuSubNestedPosition.test.tsx +48 -0
  324. package/tests/MenuSubSafePolygon.test.tsx +97 -0
  325. package/tests/MenuSubStyled.test.tsx +40 -0
  326. package/tests/MenuTheme.test.tsx +34 -0
  327. package/tests/MenuUnstyled.test.tsx +56 -0
  328. package/tests/MultiDriverAnimation.test.tsx +207 -0
  329. package/tests/NewInputBasic.test.tsx +50 -0
  330. package/tests/NewInputEvents.test.tsx +55 -0
  331. package/tests/OnLayout.test.tsx +163 -0
  332. package/tests/OnLayoutScale.test.tsx +100 -0
  333. package/tests/OnLayoutStress.test.tsx +304 -0
  334. package/tests/ParagraphSpanFontInheritance.test.tsx +73 -0
  335. package/tests/PointerEvents.test.tsx +123 -0
  336. package/tests/Popover.animated.test.tsx +234 -0
  337. package/tests/PopoverAndMenuMultiTrigger.test.tsx +184 -0
  338. package/tests/PopoverAnimatePosition.animated.test.tsx +51 -0
  339. package/tests/PopoverClickDuringEnter.animated.test.tsx +197 -0
  340. package/tests/PopoverFocusScope.test.tsx +242 -0
  341. package/tests/PopoverHoverable.test.tsx +383 -0
  342. package/tests/PopoverHoverableDisableClick.test.tsx +106 -0
  343. package/tests/PopoverHoverableRapid.test.tsx +129 -0
  344. package/tests/PopoverHoverableReposition.test.tsx +111 -0
  345. package/tests/PopoverHoverableScoped.animated.test.tsx +103 -0
  346. package/tests/PopoverHoverableStress.test.tsx +169 -0
  347. package/tests/PopoverInitialPosition.animated.test.tsx +82 -0
  348. package/tests/PopoverMiddlewareSkipRegression.animated.test.tsx +221 -0
  349. package/tests/PopoverScoped.test.tsx +128 -0
  350. package/tests/PopoverScopedPositionGlitch.animated.test.tsx +184 -0
  351. package/tests/PopoverTriggerIsolation.test.tsx +62 -0
  352. package/tests/PseudoTransition.animated.test.tsx +319 -0
  353. package/tests/RawAnimatedValue.test.tsx +147 -0
  354. package/tests/RemoveScroll.test.tsx +223 -0
  355. package/tests/RenderProp.test.tsx +293 -0
  356. package/tests/ScrollViewRef.test.tsx +39 -0
  357. package/tests/SelectClickHold.test.tsx +147 -0
  358. package/tests/SelectFocusScope.test.tsx +176 -0
  359. package/tests/SelectInnerPositioning.test.tsx +82 -0
  360. package/tests/SelectKeyboardNav.test.tsx +173 -0
  361. package/tests/SelectPositioning.test.tsx +56 -0
  362. package/tests/SelectTypeahead.test.tsx +63 -0
  363. package/tests/Shadows.test.tsx +14 -0
  364. package/tests/SheetAnimation.animated.test.tsx +413 -0
  365. package/tests/SheetDrag.animated.test.tsx +223 -0
  366. package/tests/SheetDragResist.animated.test.tsx +393 -0
  367. package/tests/SheetOnAnimationComplete.animated.test.tsx +62 -0
  368. package/tests/SheetScrollLock.animated.test.tsx +287 -0
  369. package/tests/SheetScrollableDrag.animated.test.tsx +1264 -0
  370. package/tests/SheetSnapPointsFit.animated.test.tsx +259 -0
  371. package/tests/ShorthandVariables.test.tsx +44 -0
  372. package/tests/SpinnerCustomColors.test.tsx +67 -0
  373. package/tests/StackZIndex.test.tsx +51 -0
  374. package/tests/StressPagePerf.test.tsx +76 -0
  375. package/tests/StylePlatform.test.tsx +38 -0
  376. package/tests/StyleProp.test.tsx +20 -0
  377. package/tests/StyledAnchor.test.tsx +17 -0
  378. package/tests/StyledButtonTheme.test.tsx +22 -0
  379. package/tests/StyledButtonVariantPseudo.test.tsx +20 -0
  380. package/tests/StyledButtonVariantPseudoMerge.animated.test.tsx +33 -0
  381. package/tests/StyledCheckboxTheme.test.tsx +16 -0
  382. package/tests/StyledContextColor.test.tsx +119 -0
  383. package/tests/StyledContextTokens.test.tsx +56 -0
  384. package/tests/StyledHOCNamed.test.tsx +16 -0
  385. package/tests/StyledHtml.test.tsx +161 -0
  386. package/tests/StyledIconColor.test.tsx +32 -0
  387. package/tests/StyledInputFocusStyle.test.tsx +19 -0
  388. package/tests/StyledInputOnFocus.test.tsx +27 -0
  389. package/tests/StyledMediaQueryMerge.test.tsx +66 -0
  390. package/tests/StyledRNW.test.tsx +17 -0
  391. package/tests/StyledStyleableInputOnFocus.test.tsx +27 -0
  392. package/tests/StyledStyleableInputVariant.test.tsx +22 -0
  393. package/tests/StyledStyledStyleableInputOnFocus.test.tsx +27 -0
  394. package/tests/StyledVariantTextColor.test.tsx +24 -0
  395. package/tests/StyledViewOnFocus.test.tsx +27 -0
  396. package/tests/TabHoverAnimation.animated.test.tsx +468 -0
  397. package/tests/TabHoverPositionSmooth.animated.test.tsx +129 -0
  398. package/tests/TextNestedInheritance.test.tsx +93 -0
  399. package/tests/ThemeChange.test.tsx +70 -0
  400. package/tests/ThemeComponentResolution.test.tsx +82 -0
  401. package/tests/ThemeConditionalName.test.tsx +34 -0
  402. package/tests/ThemeMediaAnimation.test.tsx +65 -0
  403. package/tests/ThemeNested.test.tsx +141 -0
  404. package/tests/ThemeReset.test.tsx +63 -0
  405. package/tests/ThemeShallow.test.tsx +95 -0
  406. package/tests/Toast.test.tsx +106 -0
  407. package/tests/ToggleGroup.test.tsx +61 -0
  408. package/tests/ToggleGroupActiveProps.test.tsx +38 -0
  409. package/tests/ToggleGroupXGroup.test.tsx +172 -0
  410. package/tests/TooltipAnimation.animated.test.tsx +260 -0
  411. package/tests/TooltipEnterInterrupt.animated.test.tsx +76 -0
  412. package/tests/TooltipGlobalPattern.animated.test.tsx +208 -0
  413. package/tests/TooltipGroup.animated.test.tsx +79 -0
  414. package/tests/TooltipMultiTrigger.test.tsx +116 -0
  415. package/tests/TooltipPositionJump.animated.test.tsx +229 -0
  416. package/tests/TooltipPositionJumpNotes.md +219 -0
  417. package/tests/TooltipRapidSwitch.animated.test.tsx +399 -0
  418. package/tests/TooltipTriggerInline.test.tsx +65 -0
  419. package/tests/TransformMediaQueryMerge.test.tsx +104 -0
  420. package/tests/TransitionEnterExit.animated.test.tsx +311 -0
  421. package/tests/UseTheme.test.tsx +16 -0
  422. package/tests/V5ThemeBuilderOutput.test.tsx +164 -0
  423. package/tests/VariantFontFamily.test.tsx +11 -0
  424. package/tests/VariantsOrder.test.tsx +53 -0
  425. package/tests/_debug_position.mjs +52 -0
  426. package/tests/test-utils.ts +106 -0
  427. package/tests/utils.tsx +54 -0
  428. package/tsconfig.json +45 -0
  429. package/vite-env.d.ts +1 -0
  430. package/vite.config.ts +14 -0
  431. package/webpack.config.js +139 -0
@@ -0,0 +1,165 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { Keyboard } from 'react-native'
3
+ import { Button, Image, Input, Sheet, Text, XStack, YStack } from '@hanzo/gui'
4
+
5
+ const MOCK_URLS = {
6
+ tall: 'https://picsum.photos/400/600',
7
+ short: 'https://picsum.photos/400/150',
8
+ }
9
+
10
+ /**
11
+ * Test case for Sheet + Keyboard + Dynamic fit content
12
+ *
13
+ * Press a button to load a mock image URL. The image height is
14
+ * taller or shorter than the placeholder, testing whether the
15
+ * sheet adjusts its fit-content height correctly.
16
+ */
17
+ export function SheetKeyboardFitContentCase() {
18
+ const [open, setOpen] = useState(false)
19
+ const [events, setEvents] = useState<string[]>([])
20
+ const [caption, setCaption] = useState('')
21
+ const [imageUrl, setImageUrl] = useState<string | null>(null)
22
+
23
+ const addEvent = useCallback((event: string) => {
24
+ setEvents((prev) => [...prev.slice(-6), event])
25
+ }, [])
26
+
27
+ return (
28
+ <YStack padding="$4" gap="$4" testID="sheet-kb-fit-screen">
29
+ <Text fontSize="$5" fontWeight="bold">
30
+ Sheet + Keyboard + Fit Content
31
+ </Text>
32
+
33
+ <Text fontSize="$3" color="$gray11">
34
+ Load a mock image URL to change content height while keyboard may be open.
35
+ </Text>
36
+
37
+ <Button testID="sheet-kb-fit-trigger" theme="green" onPress={() => setOpen(true)}>
38
+ Open Sheet
39
+ </Button>
40
+
41
+ <YStack gap="$2" padding="$3" bg="$backgroundHover" borderRadius="$2">
42
+ <Text>Events: {events.join(', ') || '(none)'}</Text>
43
+ </YStack>
44
+
45
+ <Sheet
46
+ modal
47
+ open={open}
48
+ onOpenChange={setOpen}
49
+ snapPointsMode="fit"
50
+ dismissOnSnapToBottom
51
+ moveOnKeyboardChange
52
+ zIndex={100000}
53
+ transition="medium"
54
+ >
55
+ <Sheet.Overlay
56
+ transition="lazy"
57
+ bg="$color"
58
+ opacity={0.5}
59
+ enterStyle={{ opacity: 0 }}
60
+ exitStyle={{ opacity: 0 }}
61
+ />
62
+ <Sheet.Frame testID="sheet-kb-fit-frame" padding="$4">
63
+ <YStack gap="$4">
64
+ <Text fontSize="$5" fontWeight="bold">
65
+ Create Post
66
+ </Text>
67
+
68
+ <Input
69
+ testID="sheet-kb-fit-input"
70
+ placeholder="What's on your mind?"
71
+ value={caption}
72
+ onChangeText={setCaption}
73
+ onFocus={() => addEvent('focus')}
74
+ onBlur={() => addEvent('blur')}
75
+ />
76
+
77
+ {/* Image area — always rendered, height changes with URL */}
78
+ {imageUrl ? (
79
+ <Image
80
+ testID="sheet-kb-fit-image"
81
+ source={{ uri: imageUrl }}
82
+ width="100%"
83
+ height={imageUrl === MOCK_URLS.tall ? 300 : 100}
84
+ borderRadius="$4"
85
+ bg="$backgroundHover"
86
+ />
87
+ ) : (
88
+ <YStack
89
+ testID="sheet-kb-fit-placeholder"
90
+ height={150}
91
+ borderWidth={2}
92
+ borderColor="$borderColor"
93
+ borderStyle="dashed"
94
+ borderRadius="$4"
95
+ alignItems="center"
96
+ justifyContent="center"
97
+ bg="$backgroundHover"
98
+ >
99
+ <Text color="$gray11">No image loaded</Text>
100
+ </YStack>
101
+ )}
102
+
103
+ <XStack gap="$2">
104
+ <Button
105
+ testID="sheet-kb-fit-load-tall"
106
+ size="$3"
107
+ theme="green"
108
+ flex={1}
109
+ onPress={() => {
110
+ setImageUrl(MOCK_URLS.tall)
111
+ addEvent('load-tall')
112
+ }}
113
+ >
114
+ Load Tall (300)
115
+ </Button>
116
+ <Button
117
+ testID="sheet-kb-fit-load-short"
118
+ size="$3"
119
+ theme="blue"
120
+ flex={1}
121
+ onPress={() => {
122
+ setImageUrl(MOCK_URLS.short)
123
+ addEvent('load-short')
124
+ }}
125
+ >
126
+ Load Short (100)
127
+ </Button>
128
+ <Button
129
+ testID="sheet-kb-fit-reset"
130
+ size="$3"
131
+ flex={1}
132
+ onPress={() => {
133
+ setImageUrl(null)
134
+ addEvent('reset')
135
+ }}
136
+ >
137
+ Reset (150)
138
+ </Button>
139
+ </XStack>
140
+
141
+ <Button
142
+ testID="sheet-kb-fit-dismiss-kb"
143
+ size="$3"
144
+ onPress={() => {
145
+ Keyboard.dismiss()
146
+ addEvent('dismiss-kb')
147
+ }}
148
+ >
149
+ Dismiss Keyboard
150
+ </Button>
151
+
152
+ <Button
153
+ testID="sheet-kb-fit-close"
154
+ size="$3"
155
+ theme="red"
156
+ onPress={() => setOpen(false)}
157
+ >
158
+ Close
159
+ </Button>
160
+ </YStack>
161
+ </Sheet.Frame>
162
+ </Sheet>
163
+ </YStack>
164
+ )
165
+ }
@@ -0,0 +1,54 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { Button, Paragraph, Sheet, YStack } from '@hanzo/gui'
3
+
4
+ export function SheetOnAnimationCompleteCase() {
5
+ const [open, setOpen] = useState(false)
6
+ const [lastEvent, setLastEvent] = useState('')
7
+ const [eventCount, setEventCount] = useState(0)
8
+
9
+ const handleAnimationComplete = useCallback((info: { open: boolean }) => {
10
+ setLastEvent(info.open ? 'opened' : 'closed')
11
+ setEventCount((c) => c + 1)
12
+ }, [])
13
+
14
+ return (
15
+ <YStack gap="$4" padding="$4">
16
+ <Button
17
+ onPress={() => setOpen(true)}
18
+ testID="sheet-open-trigger"
19
+ data-testid="sheet-open-trigger"
20
+ >
21
+ Open Sheet
22
+ </Button>
23
+
24
+ <Paragraph data-testid="last-event">{lastEvent}</Paragraph>
25
+ <Paragraph data-testid="event-count">{eventCount}</Paragraph>
26
+
27
+ <Sheet
28
+ open={open}
29
+ onOpenChange={setOpen}
30
+ onAnimationComplete={handleAnimationComplete}
31
+ transition="quick"
32
+ modal
33
+ dismissOnSnapToBottom
34
+ snapPoints={[40]}
35
+ >
36
+ <Sheet.Overlay
37
+ opacity={0.5}
38
+ enterStyle={{ opacity: 0 }}
39
+ exitStyle={{ opacity: 0 }}
40
+ />
41
+ <Sheet.Frame padding="$4" bg="$background" data-testid="sheet-frame">
42
+ <Paragraph>Sheet content</Paragraph>
43
+ <Button
44
+ onPress={() => setOpen(false)}
45
+ testID="sheet-close"
46
+ data-testid="sheet-close"
47
+ >
48
+ Close
49
+ </Button>
50
+ </Sheet.Frame>
51
+ </Sheet>
52
+ </YStack>
53
+ )
54
+ }
@@ -0,0 +1,166 @@
1
+ import { useState } from 'react'
2
+ import { Button, H2, Paragraph, Sheet, YStack } from '@hanzo/gui'
3
+
4
+ /**
5
+ * Test case for Sheet scroll lock behavior
6
+ * Tests that body doesn't scroll when sheet is open and dragged
7
+ * Also tests Sheet.ScrollView handoff behavior
8
+ */
9
+ export function SheetScrollLockCase() {
10
+ return (
11
+ <YStack
12
+ $platform-web={{
13
+ minHeight: '200vh',
14
+ }}
15
+ padding="$4"
16
+ gap="$4"
17
+ >
18
+ <H2>Sheet Scroll Lock Test</H2>
19
+ <Paragraph data-testid="scroll-indicator">
20
+ This page has a lot of content that makes the body scrollable. When the sheet is
21
+ open, the body should NOT scroll.
22
+ </Paragraph>
23
+
24
+ {/* some content before buttons to require scrolling */}
25
+ {Array.from({ length: 8 }).map((_, i) => (
26
+ <Paragraph key={`pre-${i}`}>
27
+ Scroll down to find the sheet buttons. Lorem ipsum dolor sit amet, consectetur
28
+ adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna
29
+ aliqua.
30
+ </Paragraph>
31
+ ))}
32
+
33
+ <BasicScrollLockSheet />
34
+ <SheetWithScrollView />
35
+
36
+ {/* lots of content to make body scrollable */}
37
+ {Array.from({ length: 30 }).map((_, i) => (
38
+ <Paragraph key={i} data-testid={`body-content-${i}`}>
39
+ Body content paragraph {i + 1}. Lorem ipsum dolor sit amet, consectetur
40
+ adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna
41
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
42
+ ut aliquip ex ea commodo consequat.
43
+ </Paragraph>
44
+ ))}
45
+ </YStack>
46
+ )
47
+ }
48
+
49
+ /**
50
+ * Basic sheet to test body scroll lock
51
+ */
52
+ function BasicScrollLockSheet() {
53
+ const [open, setOpen] = useState(false)
54
+ const [position, setPosition] = useState(0)
55
+
56
+ return (
57
+ <>
58
+ <Button data-testid="basic-scroll-lock-trigger" onPress={() => setOpen(true)}>
59
+ Open Basic Sheet
60
+ </Button>
61
+ <Sheet
62
+ modal
63
+ open={open}
64
+ onOpenChange={setOpen}
65
+ snapPoints={[70, 40]}
66
+ snapPointsMode="percent"
67
+ position={position}
68
+ onPositionChange={setPosition}
69
+ dismissOnSnapToBottom
70
+ zIndex={100000}
71
+ transition="medium"
72
+ >
73
+ <Sheet.Overlay
74
+ data-testid="basic-scroll-lock-overlay"
75
+ transition="lazy"
76
+ bg="$color"
77
+ opacity={0.5}
78
+ enterStyle={{ opacity: 0 }}
79
+ exitStyle={{ opacity: 0 }}
80
+ />
81
+ <Sheet.Handle data-testid="basic-scroll-lock-handle" />
82
+ <Sheet.Frame data-testid="basic-scroll-lock-frame" padding="$4" gap="$4">
83
+ <Paragraph data-testid="basic-scroll-lock-snap-indicator">
84
+ Current snap point: {position}
85
+ </Paragraph>
86
+ <Paragraph>
87
+ Drag the handle to test scroll lock. The body behind this sheet should NOT
88
+ scroll while dragging.
89
+ </Paragraph>
90
+ <YStack flex={1} justifyContent="center" alignItems="center">
91
+ <Paragraph opacity={0.5}>Sheet content area</Paragraph>
92
+ </YStack>
93
+ <Button data-testid="basic-scroll-lock-close" onPress={() => setOpen(false)}>
94
+ Close
95
+ </Button>
96
+ </Sheet.Frame>
97
+ </Sheet>
98
+ </>
99
+ )
100
+ }
101
+
102
+ /**
103
+ * Sheet with ScrollView to test handoff behavior
104
+ * The Sheet.ScrollView should allow scrolling inside when at top snap point,
105
+ * but pass control to the sheet drag when pulled down from scroll position 0
106
+ */
107
+ function SheetWithScrollView() {
108
+ const [open, setOpen] = useState(false)
109
+ const [position, setPosition] = useState(0)
110
+
111
+ return (
112
+ <>
113
+ <Button data-testid="scrollview-sheet-trigger" onPress={() => setOpen(true)}>
114
+ Open Sheet with ScrollView
115
+ </Button>
116
+ <Sheet
117
+ modal
118
+ open={open}
119
+ onOpenChange={setOpen}
120
+ snapPoints={[85, 50]}
121
+ snapPointsMode="percent"
122
+ position={position}
123
+ onPositionChange={setPosition}
124
+ dismissOnSnapToBottom
125
+ zIndex={100000}
126
+ transition="medium"
127
+ >
128
+ <Sheet.Overlay
129
+ data-testid="scrollview-sheet-overlay"
130
+ transition="lazy"
131
+ bg="$color"
132
+ opacity={0.5}
133
+ enterStyle={{ opacity: 0 }}
134
+ exitStyle={{ opacity: 0 }}
135
+ />
136
+ <Sheet.Handle data-testid="scrollview-sheet-handle" />
137
+ <Sheet.Frame data-testid="scrollview-sheet-frame" padding="$4">
138
+ <Paragraph data-testid="scrollview-sheet-snap-indicator">
139
+ Current snap point: {position}
140
+ </Paragraph>
141
+ <Sheet.ScrollView data-testid="scrollview-sheet-scrollview">
142
+ <YStack gap="$4" padding="$2">
143
+ <Paragraph fontWeight="bold">
144
+ This content is inside Sheet.ScrollView.
145
+ </Paragraph>
146
+ <Paragraph>
147
+ When scrolled to top and pulling down, the sheet should drag. When there's
148
+ scroll content above, the content should scroll.
149
+ </Paragraph>
150
+ {Array.from({ length: 20 }).map((_, i) => (
151
+ <Paragraph key={i} data-testid={`scrollview-content-${i}`}>
152
+ ScrollView paragraph {i + 1}. Lorem ipsum dolor sit amet, consectetur
153
+ adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore
154
+ magna aliqua.
155
+ </Paragraph>
156
+ ))}
157
+ <Button data-testid="scrollview-sheet-close" onPress={() => setOpen(false)}>
158
+ Close
159
+ </Button>
160
+ </YStack>
161
+ </Sheet.ScrollView>
162
+ </Sheet.Frame>
163
+ </Sheet>
164
+ </>
165
+ )
166
+ }
@@ -0,0 +1,249 @@
1
+ import { useState, useCallback, useRef, useEffect } from 'react'
2
+ import { ScrollView as RNScrollView } from 'react-native'
3
+ import { Button, Sheet, Text, YStack } from '@hanzo/gui'
4
+ import { getGestureHandler } from '@hanzogui/native'
5
+
6
+ /**
7
+ * Test case for Sheet + ScrollView drag interaction
8
+ *
9
+ * SMOOTH HANDOFF requirements:
10
+ * 1. Drag sheet down, then up until it hits top snap point -> should THEN start scrolling content
11
+ * 2. Scroll content, then drag down until scrollY=0 -> should SWITCH BACK to dragging sheet
12
+ * 3. No "stuck" states - always be able to scroll or drag as appropriate
13
+ */
14
+ export function SheetScrollableDrag() {
15
+ const [open, setOpen] = useState(false)
16
+ const [position, setPosition] = useState(0)
17
+ const [scrollY, setScrollY] = useState(0)
18
+ const [dragEvents, setDragEvents] = useState<string[]>([])
19
+ const [scrollEventCount, setScrollEventCount] = useState(0)
20
+ const [minScrollY, setMinScrollY] = useState(0)
21
+ const [maxScrollY, setMaxScrollY] = useState(0)
22
+ const [itemCount, setItemCount] = useState(20)
23
+ const [maxPosition, setMaxPosition] = useState(0)
24
+ const [unexpectedClose, setUnexpectedClose] = useState(false)
25
+ const lastScrollY = useRef(0)
26
+
27
+ const rnghEnabled = getGestureHandler().isEnabled
28
+
29
+ useEffect(() => {
30
+ console.log('[SheetScrollableDrag] RNGH enabled:', rnghEnabled)
31
+ }, [rnghEnabled])
32
+
33
+ const addEvent = useCallback((event: string) => {
34
+ setDragEvents((prev) => [...prev.slice(-4), event])
35
+ }, [])
36
+
37
+ return (
38
+ <YStack padding="$4" gap="$4" testID="sheet-scrollable-drag-screen">
39
+ <Text testID="sheet-scrollable-drag-title" fontSize="$5" fontWeight="bold">
40
+ Sheet + ScrollView Drag Test (v4)
41
+ </Text>
42
+
43
+ <Text
44
+ testID="sheet-scrollable-drag-rngh-status"
45
+ fontSize="$3"
46
+ color={rnghEnabled ? '$green10' : '$red10'}
47
+ fontWeight="bold"
48
+ >
49
+ RNGH: {rnghEnabled ? '✓ enabled' : '✗ disabled'}
50
+ </Text>
51
+
52
+ {/* Debug: test if plain RN ScrollView fires onScroll */}
53
+ <RNScrollView
54
+ style={{ height: 60, backgroundColor: '#eef' }}
55
+ onScroll={(e) => {
56
+ console.log('[TEST RNScrollView] onScroll:', e.nativeEvent.contentOffset.y)
57
+ }}
58
+ scrollEventThrottle={16}
59
+ >
60
+ <Text style={{ padding: 8 }}>Scroll me to test (outside sheet) - 1</Text>
61
+ <Text style={{ padding: 8 }}>Scroll me to test (outside sheet) - 2</Text>
62
+ <Text style={{ padding: 8 }}>Scroll me to test (outside sheet) - 3</Text>
63
+ <Text style={{ padding: 8 }}>Scroll me to test (outside sheet) - 4</Text>
64
+ </RNScrollView>
65
+
66
+ <Text testID="sheet-scrollable-drag-instructions" fontSize="$3" color="$gray11">
67
+ Test smooth handoff: drag down then up to scroll, scroll up then drag down to drag
68
+ sheet.
69
+ </Text>
70
+
71
+ <YStack flexDirection="row" gap="$2">
72
+ <Button
73
+ testID="sheet-scrollable-drag-trigger"
74
+ onPress={() => setOpen(true)}
75
+ flex={1}
76
+ >
77
+ Open Sheet
78
+ </Button>
79
+ <Button
80
+ testID="sheet-scrollable-drag-reset"
81
+ onPress={() => {
82
+ setScrollEventCount(0)
83
+ setMinScrollY(0)
84
+ setMaxScrollY(0)
85
+ setMaxPosition(0)
86
+ setDragEvents([])
87
+ setItemCount(10)
88
+ lastScrollY.current = 0
89
+ }}
90
+ theme="red"
91
+ >
92
+ Reset
93
+ </Button>
94
+ </YStack>
95
+
96
+ <YStack gap="$2" padding="$3" bg="$backgroundHover" borderRadius="$2">
97
+ <Text testID="sheet-scrollable-drag-position">Sheet position: {position}</Text>
98
+ <Text testID="sheet-scrollable-drag-scroll-y">
99
+ ScrollView Y: {scrollY.toFixed(0)}
100
+ </Text>
101
+ <Text testID="sheet-scrollable-drag-scroll-count">
102
+ Scroll events: {scrollEventCount}
103
+ </Text>
104
+ <Text testID="sheet-scrollable-drag-min-scroll-y">
105
+ Min scroll Y: {minScrollY.toFixed(0)}
106
+ </Text>
107
+ <Text testID="sheet-scrollable-drag-max-scroll-y">
108
+ Max scroll Y: {maxScrollY.toFixed(0)}
109
+ </Text>
110
+ <Text testID="sheet-scrollable-drag-max-position">
111
+ Max position: {maxPosition}
112
+ </Text>
113
+ <Text testID="sheet-scrollable-drag-unexpected-close">
114
+ Unexpected close: {unexpectedClose ? 'yes' : 'no'}
115
+ </Text>
116
+ <Text testID="sheet-scrollable-drag-events">
117
+ Events: {dragEvents.join(', ') || '(none)'}
118
+ </Text>
119
+ </YStack>
120
+
121
+ <YStack gap="$1" padding="$2" bg="$green3" borderRadius="$2">
122
+ <Text fontSize="$2" fontWeight="bold">
123
+ Smooth handoff test:
124
+ </Text>
125
+ <Text fontSize="$2">
126
+ 1. Drag sheet down → then up → hits top → starts scrolling{'\n'}
127
+ 2. Scroll down → drag up → hits scrollY=0 → starts dragging sheet
128
+ </Text>
129
+ </YStack>
130
+
131
+ <Sheet
132
+ modal
133
+ open={open}
134
+ onOpenChange={(val) => {
135
+ if (!val && open) {
136
+ // sheet closing while it was open - track this
137
+ setUnexpectedClose(true)
138
+ }
139
+ setOpen(val)
140
+ }}
141
+ snapPoints={[85, 50]}
142
+ snapPointsMode="percent"
143
+ position={position}
144
+ onPositionChange={(pos) => {
145
+ setPosition(pos)
146
+ setMaxPosition((prev) => Math.max(prev, pos))
147
+ addEvent(`snap:${pos}`)
148
+ }}
149
+ dismissOnSnapToBottom
150
+ zIndex={100000}
151
+ transition="medium"
152
+ >
153
+ <Sheet.Overlay
154
+ testID="sheet-scrollable-drag-overlay"
155
+ transition="lazy"
156
+ bg="$color"
157
+ opacity={0.5}
158
+ enterStyle={{ opacity: 0 }}
159
+ exitStyle={{ opacity: 0 }}
160
+ />
161
+ <Sheet.Handle testID="sheet-scrollable-drag-handle" />
162
+ <Sheet.Frame testID="sheet-scrollable-drag-frame">
163
+ <Sheet.ScrollView
164
+ testID="sheet-scrollable-drag-scrollview"
165
+ onScroll={(e) => {
166
+ const y = e.nativeEvent.contentOffset.y
167
+ setScrollY(y)
168
+ setScrollEventCount((c) => c + 1)
169
+ if (y < minScrollY) {
170
+ setMinScrollY(y)
171
+ }
172
+ if (y > maxScrollY) {
173
+ setMaxScrollY(y)
174
+ }
175
+ if (Math.abs(y - lastScrollY.current) > 5) {
176
+ addEvent(`scroll:${y.toFixed(0)}`)
177
+ lastScrollY.current = y
178
+ }
179
+ }}
180
+ onScrollBeginDrag={() => {
181
+ addEvent('dragStart')
182
+ }}
183
+ onScrollEndDrag={() => {
184
+ addEvent('dragEnd')
185
+ }}
186
+ scrollEventThrottle={16}
187
+ >
188
+ <YStack gap="$3" padding="$4">
189
+ <Text
190
+ testID="sheet-scrollable-drag-snap-label"
191
+ fontSize="$3"
192
+ color="$gray11"
193
+ >
194
+ Snap: {position} | Scroll Y: {scrollY.toFixed(0)} | Items: {itemCount}
195
+ </Text>
196
+
197
+ <Text
198
+ testID="sheet-scrollable-drag-content-top"
199
+ fontWeight="bold"
200
+ fontSize="$4"
201
+ >
202
+ ↕ Drag here to test handoff ↕
203
+ </Text>
204
+
205
+ <Button
206
+ testID="sheet-scrollable-drag-add-items"
207
+ onPress={() => setItemCount((c) => c + 5)}
208
+ size="$3"
209
+ >
210
+ Add 5 Items ({itemCount} total)
211
+ </Button>
212
+
213
+ <Text
214
+ testID="sheet-scrollable-drag-scroll-indicator"
215
+ padding="$2"
216
+ bg="$blue3"
217
+ borderRadius="$2"
218
+ >
219
+ Scroll Y: {scrollY.toFixed(0)}
220
+ </Text>
221
+
222
+ {Array.from({ length: itemCount }).map((_, i) => (
223
+ <YStack
224
+ key={i}
225
+ testID={`sheet-scrollable-drag-item-${i}`}
226
+ padding="$3"
227
+ bg="$background"
228
+ borderRadius="$2"
229
+ borderWidth={1}
230
+ borderColor="$borderColor"
231
+ >
232
+ <Text>Item {i + 1}</Text>
233
+ </YStack>
234
+ ))}
235
+
236
+ <Button
237
+ testID="sheet-scrollable-drag-close"
238
+ onPress={() => setOpen(false)}
239
+ marginTop="$4"
240
+ >
241
+ Close Sheet
242
+ </Button>
243
+ </YStack>
244
+ </Sheet.ScrollView>
245
+ </Sheet.Frame>
246
+ </Sheet>
247
+ </YStack>
248
+ )
249
+ }