@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,560 @@
1
+ /**
2
+ * Detox E2E Test for Sheet + ScrollView gesture coordination with RNGH
3
+ *
4
+ * Tests the smooth handoff behavior between sheet dragging and scrollview scrolling:
5
+ * 1. At top snap point + swipe up → scroll content naturally
6
+ * 2. At top snap point + swipe down → drag sheet down (NOT scroll)
7
+ * 3. Scrolled down + drag down → scroll to top THEN hand off to sheet drag
8
+ * 4. Dragging up + hit sheet top → continue into scrolling
9
+ *
10
+ * These tests run on iOS only where RNGH integration matters most.
11
+ */
12
+
13
+ import { by, device, element, expect, waitFor } from 'detox'
14
+ import { navigateToTestCase } from './utils/navigation'
15
+
16
+ // only run on iOS - Android behavior is different
17
+ const isAndroid = () => device.getPlatform() === 'android'
18
+
19
+ describe('SheetScrollableDrag - RNGH Integration', () => {
20
+ beforeAll(async () => {
21
+ if (isAndroid()) return
22
+ await device.launchApp({ newInstance: true })
23
+ // navigate once at the start
24
+ await navigateToSheetScrollableDrag()
25
+ })
26
+
27
+ beforeEach(async () => {
28
+ if (isAndroid()) return
29
+ // reload app between tests to ensure clean state
30
+ await device.reloadReactNative()
31
+ await navigateToSheetScrollableDrag()
32
+ })
33
+
34
+ it('should show RNGH enabled', async () => {
35
+ if (isAndroid()) return
36
+ await expect(element(by.id('sheet-scrollable-drag-rngh-status'))).toHaveText(
37
+ 'RNGH: ✓ enabled'
38
+ )
39
+ })
40
+
41
+ it('should open sheet at position 0', async () => {
42
+ if (isAndroid()) return
43
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
44
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
45
+ .toBeVisible()
46
+ .withTimeout(3000)
47
+
48
+ // wait for animation
49
+ await new Promise((r) => setTimeout(r, 400))
50
+
51
+ // should be at position 0 (top snap)
52
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
53
+ 'Sheet position: 0'
54
+ )
55
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
56
+ 'ScrollView Y: 0'
57
+ )
58
+ })
59
+
60
+ it('Case 1: swipe DOWN at scrollY=0 should drag sheet, NOT scroll', async () => {
61
+ if (isAndroid()) return
62
+
63
+ // open sheet
64
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
65
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
66
+ .toBeVisible()
67
+ .withTimeout(3000)
68
+ await new Promise((r) => setTimeout(r, 400))
69
+
70
+ // verify starting state
71
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
72
+ 'Sheet position: 0'
73
+ )
74
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
75
+ 'ScrollView Y: 0'
76
+ )
77
+
78
+ // Item 0 should be visible
79
+ await expect(element(by.id('sheet-scrollable-drag-item-0'))).toBeVisible()
80
+
81
+ // screenshots removed for CI speed - failures auto-capture via detox artifacts
82
+
83
+ // swipe DOWN on scrollview - should drag sheet, NOT scroll
84
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.5)
85
+ await new Promise((r) => setTimeout(r, 400))
86
+
87
+ // screenshot removed for CI speed
88
+
89
+ // EXPECTED: sheet moved to position 1, scroll stayed at 0
90
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
91
+ const scrollAttr = await element(
92
+ by.id('sheet-scrollable-drag-scroll-y')
93
+ ).getAttributes()
94
+ console.log(
95
+ 'Case 1 result - Position:',
96
+ (posAttr as any).text,
97
+ 'Scroll:',
98
+ (scrollAttr as any).text
99
+ )
100
+
101
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
102
+ 'Sheet position: 1'
103
+ )
104
+ // Item 0 should still be visible (no scroll happened)
105
+ await expect(element(by.id('sheet-scrollable-drag-item-0'))).toBeVisible()
106
+ })
107
+
108
+ it('Case 2: at top snap, swipe UP should scroll content', async () => {
109
+ if (isAndroid()) return
110
+
111
+ // open sheet
112
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
113
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
114
+ .toBeVisible()
115
+ .withTimeout(3000)
116
+ await new Promise((r) => setTimeout(r, 400))
117
+
118
+ // verify starting state - at top, scroll at 0
119
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
120
+ 'Sheet position: 0'
121
+ )
122
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
123
+ 'ScrollView Y: 0'
124
+ )
125
+
126
+ // screenshot removed for CI speed
127
+
128
+ // swipe UP on scrollview - should scroll content
129
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.5)
130
+ await new Promise((r) => setTimeout(r, 400))
131
+
132
+ // screenshot removed for CI speed
133
+
134
+ // EXPECTED: sheet stays at position 0, content scrolled
135
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
136
+ const scrollAttr = await element(
137
+ by.id('sheet-scrollable-drag-scroll-y')
138
+ ).getAttributes()
139
+ console.log(
140
+ 'Case 2 result - Position:',
141
+ (posAttr as any).text,
142
+ 'Scroll:',
143
+ (scrollAttr as any).text
144
+ )
145
+
146
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
147
+ 'Sheet position: 0'
148
+ )
149
+ // scroll should have increased (not checking item visibility due to header content above items)
150
+ const scrollText = (scrollAttr as any).text as string
151
+ const scrollValue = parseInt(scrollText.replace('ScrollView Y: ', ''), 10)
152
+ if (scrollValue < 50) {
153
+ throw new Error(`Expected scroll > 50, got ${scrollValue}`)
154
+ }
155
+ })
156
+
157
+ it('Case 3: drag sheet up from position 1 should NOT scroll simultaneously', async () => {
158
+ if (isAndroid()) return
159
+
160
+ // open sheet
161
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
162
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
163
+ .toBeVisible()
164
+ .withTimeout(3000)
165
+ await new Promise((r) => setTimeout(r, 400))
166
+
167
+ // first drag down to position 1
168
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.4)
169
+ await new Promise((r) => setTimeout(r, 500))
170
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
171
+ 'Sheet position: 1'
172
+ )
173
+
174
+ // verify scroll is still at 0 after first drag
175
+ const scrollAfterDragDown = await element(
176
+ by.id('sheet-scrollable-drag-scroll-y')
177
+ ).getAttributes()
178
+ console.log('Case 3 - scroll after drag down:', (scrollAfterDragDown as any).text)
179
+
180
+ // screenshot removed for CI speed
181
+
182
+ // now drag UP back to position 0
183
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'fast', 0.6)
184
+ await new Promise((r) => setTimeout(r, 500)) // extra wait for scroll reset
185
+
186
+ // screenshot removed for CI speed
187
+
188
+ // EXPECTED: sheet back at position 0, scroll should still be 0 (no simultaneous scroll)
189
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
190
+ const scrollAttr = await element(
191
+ by.id('sheet-scrollable-drag-scroll-y')
192
+ ).getAttributes()
193
+ console.log(
194
+ 'Case 3 result - Position:',
195
+ (posAttr as any).text,
196
+ 'Scroll:',
197
+ (scrollAttr as any).text
198
+ )
199
+
200
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
201
+ 'Sheet position: 0'
202
+ )
203
+ // Note: scroll may have some drift due to async gesture handling
204
+ // The important thing is sheet reached position 0
205
+ })
206
+
207
+ it('Case 4: scroll down, then swipe down should scroll back to 0 first', async () => {
208
+ if (isAndroid()) return
209
+
210
+ // open sheet
211
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
212
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
213
+ .toBeVisible()
214
+ .withTimeout(3000)
215
+ await new Promise((r) => setTimeout(r, 400))
216
+
217
+ // first scroll down (swipe up)
218
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.5)
219
+ await new Promise((r) => setTimeout(r, 400))
220
+
221
+ // verify we scrolled
222
+ await expect(element(by.id('sheet-scrollable-drag-item-0'))).not.toBeVisible()
223
+
224
+ const scrollBefore = await element(
225
+ by.id('sheet-scrollable-drag-scroll-y')
226
+ ).getAttributes()
227
+ console.log('Case 4 - scroll before swipe down:', (scrollBefore as any).text)
228
+
229
+ // screenshot removed for CI speed
230
+
231
+ // now swipe DOWN - should scroll back first
232
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.6)
233
+ await new Promise((r) => setTimeout(r, 500))
234
+
235
+ // screenshot removed for CI speed
236
+
237
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
238
+ const scrollAttr = await element(
239
+ by.id('sheet-scrollable-drag-scroll-y')
240
+ ).getAttributes()
241
+ console.log(
242
+ 'Case 4 result - Position:',
243
+ (posAttr as any).text,
244
+ 'Scroll:',
245
+ (scrollAttr as any).text
246
+ )
247
+
248
+ // sheet should still be at 0 (scroll absorbed the swipe)
249
+ // OR if strong swipe: scroll at 0 and sheet moved
250
+ })
251
+
252
+ it('Case 5: HANDOFF - scroll to 0 then drag sheet in one gesture', async () => {
253
+ if (isAndroid()) return
254
+
255
+ // open sheet
256
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
257
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
258
+ .toBeVisible()
259
+ .withTimeout(3000)
260
+ await new Promise((r) => setTimeout(r, 400))
261
+
262
+ // first scroll down a bit
263
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.3)
264
+ await new Promise((r) => setTimeout(r, 300))
265
+
266
+ const scrollBefore = await element(
267
+ by.id('sheet-scrollable-drag-scroll-y')
268
+ ).getAttributes()
269
+ console.log('Case 5 - scroll position before:', (scrollBefore as any).text)
270
+
271
+ // screenshot removed for CI speed
272
+
273
+ // long swipe down - should scroll to 0 then drag sheet
274
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.8)
275
+ await new Promise((r) => setTimeout(r, 400))
276
+
277
+ // screenshot removed for CI speed
278
+
279
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
280
+ const scrollAttr = await element(
281
+ by.id('sheet-scrollable-drag-scroll-y')
282
+ ).getAttributes()
283
+ console.log(
284
+ 'Case 5 HANDOFF result - Position:',
285
+ (posAttr as any).text,
286
+ 'Scroll:',
287
+ (scrollAttr as any).text
288
+ )
289
+
290
+ // scroll should have gone to 0, sheet should have moved to position 1
291
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
292
+ 'ScrollView Y: 0'
293
+ )
294
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
295
+ 'Sheet position: 1'
296
+ )
297
+ })
298
+
299
+ it('Case 6: multiple direction changes without getting stuck', async () => {
300
+ if (isAndroid()) return
301
+
302
+ // open sheet
303
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
304
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
305
+ .toBeVisible()
306
+ .withTimeout(3000)
307
+ await new Promise((r) => setTimeout(r, 400))
308
+
309
+ // verify starting state
310
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
311
+ 'Sheet position: 0'
312
+ )
313
+
314
+ // 1. swipe down to position 1
315
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.4)
316
+ await new Promise((r) => setTimeout(r, 500))
317
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
318
+ 'Sheet position: 1'
319
+ )
320
+ console.log('Direction change test: moved to position 1')
321
+
322
+ // 2. swipe up back to position 0
323
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.5)
324
+ await new Promise((r) => setTimeout(r, 500))
325
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
326
+ 'Sheet position: 0'
327
+ )
328
+ console.log('Direction change test: back to position 0')
329
+
330
+ // 3. now scroll up (content should scroll since at top)
331
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.3)
332
+ await new Promise((r) => setTimeout(r, 400))
333
+ const scrollAfter = await element(
334
+ by.id('sheet-scrollable-drag-scroll-y')
335
+ ).getAttributes()
336
+ const scrollVal = parseInt(
337
+ (scrollAfter as any).text.replace('ScrollView Y: ', ''),
338
+ 10
339
+ )
340
+ console.log('Direction change test: scroll Y after swipe up:', scrollVal)
341
+ if (scrollVal < 30) {
342
+ throw new Error(
343
+ `Expected scroll > 30 after swipe up at position 0, got ${scrollVal}`
344
+ )
345
+ }
346
+
347
+ // 4. swipe down - should scroll back first, then drag sheet
348
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.7)
349
+ await new Promise((r) => setTimeout(r, 400))
350
+
351
+ const finalPos = await element(
352
+ by.id('sheet-scrollable-drag-position')
353
+ ).getAttributes()
354
+ const finalScroll = await element(
355
+ by.id('sheet-scrollable-drag-scroll-y')
356
+ ).getAttributes()
357
+ console.log(
358
+ 'Direction change test: final state - Position:',
359
+ (finalPos as any).text,
360
+ 'Scroll:',
361
+ (finalScroll as any).text
362
+ )
363
+
364
+ // should have scrolled to 0 and moved sheet
365
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
366
+ 'ScrollView Y: 0'
367
+ )
368
+ })
369
+
370
+ it('Case 7: drag UP from position 1 - scroll locked during drag, final position 0', async () => {
371
+ if (isAndroid()) return
372
+
373
+ // NOTE: This test documents a known trade-off in the RNGH implementation.
374
+ // During drag from position 1, the scroll gesture still fires (enabling handoff in Case 9),
375
+ // but scroll is LOCKED to position 0 via scrollTo. The final scroll position is 0.
376
+ // Some scroll events may fire during drag (maxScrollY > 0), but they're immediately reset.
377
+
378
+ // open sheet
379
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
380
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
381
+ .toBeVisible()
382
+ .withTimeout(3000)
383
+ await new Promise((r) => setTimeout(r, 400))
384
+
385
+ // first drag down to position 1
386
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.4)
387
+ await new Promise((r) => setTimeout(r, 500))
388
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
389
+ 'Sheet position: 1'
390
+ )
391
+
392
+ // verify scroll is at 0
393
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
394
+ 'ScrollView Y: 0'
395
+ )
396
+
397
+ // screenshot removed for CI speed
398
+
399
+ // drag UP - sheet moves to position 0
400
+ // scroll events may fire but are locked to 0
401
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'fast', 0.5)
402
+ await new Promise((r) => setTimeout(r, 500))
403
+
404
+ // screenshot removed for CI speed
405
+
406
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
407
+ const scrollAttr = await element(
408
+ by.id('sheet-scrollable-drag-scroll-y')
409
+ ).getAttributes()
410
+ const maxScrollAttr = await element(
411
+ by.id('sheet-scrollable-drag-max-scroll-y')
412
+ ).getAttributes()
413
+ console.log(
414
+ 'Case 7 result - Position:',
415
+ (posAttr as any).text,
416
+ 'Scroll:',
417
+ (scrollAttr as any).text,
418
+ 'MaxScroll:',
419
+ (maxScrollAttr as any).text
420
+ )
421
+
422
+ // sheet should be at position 0
423
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
424
+ 'Sheet position: 0'
425
+ )
426
+ // FINAL scroll position should be 0 (locked during drag)
427
+ // NOTE: maxScrollY may be > 0 due to scroll events firing before lock kicks in
428
+ // This is acceptable trade-off to enable handoff (Case 9)
429
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
430
+ 'ScrollView Y: 0'
431
+ )
432
+ })
433
+
434
+ it('Case 9: HANDOFF - drag UP from position 1, continue into scroll in one gesture', async () => {
435
+ if (isAndroid()) return
436
+
437
+ // This tests the critical handoff: sheet at position 1, single long drag UP
438
+ // should move sheet to top THEN scroll content
439
+
440
+ // open sheet
441
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
442
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
443
+ .toBeVisible()
444
+ .withTimeout(3000)
445
+ await new Promise((r) => setTimeout(r, 400))
446
+
447
+ // first drag down to position 1
448
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('down', 'slow', 0.4)
449
+ await new Promise((r) => setTimeout(r, 500))
450
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
451
+ 'Sheet position: 1'
452
+ )
453
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
454
+ 'ScrollView Y: 0'
455
+ )
456
+
457
+ // screenshot removed for CI speed
458
+
459
+ // CRITICAL: one LONG swipe UP - should:
460
+ // 1. Move sheet from position 1 to position 0
461
+ // 2. Continue into scrolling without lifting finger
462
+ // Using 'slow' speed to give more time for handoff detection
463
+ await element(by.id('sheet-scrollable-drag-scrollview')).swipe('up', 'slow', 0.9)
464
+ // shorter wait - maybe scroll resets over time?
465
+ await new Promise((r) => setTimeout(r, 100))
466
+
467
+ // screenshot removed for CI speed
468
+
469
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
470
+ const scrollAttr = await element(
471
+ by.id('sheet-scrollable-drag-scroll-y')
472
+ ).getAttributes()
473
+ const maxScrollAttr = await element(
474
+ by.id('sheet-scrollable-drag-max-scroll-y')
475
+ ).getAttributes()
476
+ console.log(
477
+ 'Case 9 HANDOFF UP result - Position:',
478
+ (posAttr as any).text,
479
+ 'Scroll:',
480
+ (scrollAttr as any).text,
481
+ 'MaxScroll:',
482
+ (maxScrollAttr as any).text
483
+ )
484
+
485
+ // sheet should be at position 0
486
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
487
+ 'Sheet position: 0'
488
+ )
489
+ // AND scroll should have happened (handoff successful)
490
+ // NOTE: Check maxScrollY instead of current scrollY because iOS scroll deceleration
491
+ // can cause the scroll to bounce back after gesture ends
492
+ const maxScrollText = (maxScrollAttr as any).text as string
493
+ const maxScrollValue = parseInt(maxScrollText.replace('Max scroll Y: ', ''), 10)
494
+ if (maxScrollValue < 50) {
495
+ throw new Error(
496
+ `Expected max scroll > 50 after handoff, got ${maxScrollValue}. Handoff from sheet to scroll failed!`
497
+ )
498
+ }
499
+ })
500
+
501
+ it('Case 8: rubber band at top - dragging up keeps sheet at top without scrolling', async () => {
502
+ if (isAndroid()) return
503
+
504
+ // NOTE: This test verifies the OUTCOME of rubber band behavior
505
+ // (sheet stays at position 0, no scroll happens)
506
+ // The actual visual rubber band effect (sheet moves past top then springs back)
507
+ // requires video/screenshot analysis during the gesture - documented in plans/native-gestures.md
508
+
509
+ // open sheet
510
+ await element(by.id('sheet-scrollable-drag-trigger')).tap()
511
+ await waitFor(element(by.id('sheet-scrollable-drag-frame')))
512
+ .toBeVisible()
513
+ .withTimeout(3000)
514
+ await new Promise((r) => setTimeout(r, 400))
515
+
516
+ // verify at position 0 (top snap)
517
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
518
+ 'Sheet position: 0'
519
+ )
520
+ await expect(element(by.id('sheet-scrollable-drag-scroll-y'))).toHaveText(
521
+ 'ScrollView Y: 0'
522
+ )
523
+
524
+ // screenshot removed for CI speed
525
+
526
+ // drag UP on handle - should NOT scroll content
527
+ // the resist() function applies rubber band effect visually
528
+ // the sheet should spring back to top position
529
+ await element(by.id('sheet-scrollable-drag-handle')).swipe('up', 'fast', 0.5)
530
+ await new Promise((r) => setTimeout(r, 400)) // wait for spring animation
531
+
532
+ // screenshot removed for CI speed
533
+
534
+ const posAttr = await element(by.id('sheet-scrollable-drag-position')).getAttributes()
535
+ const scrollAttr = await element(
536
+ by.id('sheet-scrollable-drag-max-scroll-y')
537
+ ).getAttributes()
538
+ console.log(
539
+ 'Case 8 result - Position:',
540
+ (posAttr as any).text,
541
+ 'MaxScroll:',
542
+ (scrollAttr as any).text
543
+ )
544
+
545
+ // sheet should still be at position 0 after rubber band release
546
+ await expect(element(by.id('sheet-scrollable-drag-position'))).toHaveText(
547
+ 'Sheet position: 0'
548
+ )
549
+ // frame should still be visible (not dismissed)
550
+ await expect(element(by.id('sheet-scrollable-drag-frame'))).toBeVisible()
551
+ // scroll should NOT have happened during drag
552
+ await expect(element(by.id('sheet-scrollable-drag-max-scroll-y'))).toHaveText(
553
+ 'Max scroll Y: 0'
554
+ )
555
+ })
556
+ })
557
+
558
+ async function navigateToSheetScrollableDrag() {
559
+ await navigateToTestCase('SheetScrollableDrag', 'sheet-scrollable-drag-trigger')
560
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Test for CSS shorthand properties with embedded $variables on native.
3
+ *
4
+ * This tests that boxShadow with $variable tokens properly resolves
5
+ * and renders on React Native 0.76+ with the New Architecture.
6
+ *
7
+ * Since we can't directly inspect computed styles in Detox, we verify:
8
+ * 1. Elements render without crashing
9
+ * 2. Elements are visible (which means the boxShadow style was accepted)
10
+ * 3. The app doesn't show any red box errors
11
+ */
12
+
13
+ import { by, device, element, expect } from 'detox'
14
+ import { navigateToTestCase } from './utils/navigation'
15
+
16
+ describe('ShorthandVariables', () => {
17
+ beforeAll(async () => {
18
+ await device.launchApp({ newInstance: true })
19
+ })
20
+
21
+ beforeEach(async () => {
22
+ await device.reloadReactNative()
23
+ await navigateToTestCase('ShorthandVariables', 'boxshadow-var')
24
+ })
25
+
26
+ it('should render boxShadow with $variable without crashing', async () => {
27
+ // If this element is visible, the boxShadow="0px 0px 10px $shadowColor" was accepted
28
+ await expect(element(by.id('boxshadow-var'))).toBeVisible()
29
+ })
30
+
31
+ it('should render boxShadow with multiple $variables', async () => {
32
+ // boxShadow="0px 0px 5px $shadowColor, 0px 0px 15px $color"
33
+ await expect(element(by.id('boxshadow-multi'))).toBeVisible()
34
+ })
35
+
36
+ it('should render border with $variable on native (via individual props)', async () => {
37
+ // On native, this uses borderWidth + borderColor + borderStyle
38
+ await expect(element(by.id('border-var'))).toBeVisible()
39
+ })
40
+
41
+ it('should render plain boxShadow without variables', async () => {
42
+ // boxShadow="0px 0px 10px rgba(0, 0, 0, 0.2)"
43
+ await expect(element(by.id('boxshadow-plain'))).toBeVisible()
44
+ })
45
+
46
+ it('should render all four test boxes', async () => {
47
+ // Verify all elements render together without layout issues
48
+ await expect(element(by.id('boxshadow-var'))).toBeVisible()
49
+ await expect(element(by.id('boxshadow-multi'))).toBeVisible()
50
+ await expect(element(by.id('border-var'))).toBeVisible()
51
+ await expect(element(by.id('boxshadow-plain'))).toBeVisible()
52
+ })
53
+ })