@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,370 @@
1
+ /**
2
+ * Detox E2E tests for Sheet drag resistance behavior
3
+ *
4
+ * Tests three scenarios:
5
+ * 1. Sheet without ScrollView - drag up should show resistance
6
+ * 2. Sheet with ScrollView but NO scrollable content - drag should move sheet, not scroll
7
+ * 3. Sheet with ScrollView and scrollable content - drag up at top should show resistance
8
+ *
9
+ * These tests validate the bugs:
10
+ * - Bug #1: if has scrollview but content not scrollable, dragging wasn't moving the sheet
11
+ * - Bug #2: drag up past end / resist isn't moving much
12
+ * - Bug #3: no scrollview also drag up / resist not doing much
13
+ */
14
+
15
+ import { by, device, element, expect, waitFor } from 'detox'
16
+ import { navigateToTestCase } from './utils/navigation'
17
+
18
+ // only run on iOS - RNGH gesture handling differs on Android
19
+ const isAndroid = () => device.getPlatform() === 'android'
20
+
21
+ describe('SheetDragResist', () => {
22
+ beforeAll(async () => {
23
+ if (isAndroid()) return
24
+ await device.launchApp({ newInstance: true })
25
+ })
26
+
27
+ beforeEach(async () => {
28
+ if (isAndroid()) return
29
+ // reload between tests for clean state
30
+ await device.reloadReactNative()
31
+ await navigateToSheetDragResistCase()
32
+ // disable sync AFTER navigation to avoid hang on spring animations during tests
33
+ await device.disableSynchronization()
34
+ })
35
+
36
+ afterEach(async () => {
37
+ if (isAndroid()) return
38
+ await device.enableSynchronization()
39
+ })
40
+
41
+ it('should navigate to SheetDragResistCase test case', async () => {
42
+ if (isAndroid()) return
43
+ // the screen may not be fully visible due to scroll position, use toExist instead
44
+ await expect(element(by.id('sheet-drag-resist-screen'))).toExist()
45
+ await expect(element(by.id('no-scroll-trigger'))).toBeVisible()
46
+ await expect(element(by.id('non-scrollable-trigger'))).toBeVisible()
47
+ await expect(element(by.id('scrollable-trigger'))).toBeVisible()
48
+ })
49
+
50
+ describe('Bug #3: Sheet without ScrollView - drag up resistance', () => {
51
+ /**
52
+ * BUG #3 TEST: Drag up on sheet without ScrollView should show resistance
53
+ *
54
+ * Expected: When at top snap point, dragging up should apply resistance
55
+ * (sheet moves slightly then springs back, showing visual rubber band effect)
56
+ *
57
+ * BUG: Currently dragging up doesn't show much/any movement at all
58
+ */
59
+ it('should show resistance when dragging up on handle at top position', async () => {
60
+ if (isAndroid()) return
61
+
62
+ await element(by.id('no-scroll-trigger')).tap()
63
+
64
+ await waitFor(element(by.id('no-scroll-frame')))
65
+ .toBeVisible()
66
+ .withTimeout(5000)
67
+
68
+ await new Promise((resolve) => setTimeout(resolve, 400))
69
+
70
+ // verify we're at position 0 (top snap point)
71
+ await expect(element(by.id('no-scroll-snap-indicator'))).toHaveText(
72
+ 'Current snap point: 0'
73
+ )
74
+
75
+ // screenshot removed for CI speed
76
+
77
+ // drag UP on handle - this should show resistance and spring back
78
+ await element(by.id('no-scroll-handle')).swipe('up', 'slow', 0.8)
79
+
80
+ await new Promise((resolve) => setTimeout(resolve, 400))
81
+
82
+ // screenshot removed for CI speed
83
+
84
+ // sheet should still be at position 0 (didn't dismiss or change snap)
85
+ await expect(element(by.id('no-scroll-snap-indicator'))).toHaveText(
86
+ 'Current snap point: 0'
87
+ )
88
+ // frame should still be visible (sheet didn't disappear)
89
+ await expect(element(by.id('no-scroll-frame'))).toBeVisible()
90
+ })
91
+
92
+ it('should show resistance when dragging up on frame content', async () => {
93
+ if (isAndroid()) return
94
+
95
+ await element(by.id('no-scroll-trigger')).tap()
96
+
97
+ await waitFor(element(by.id('no-scroll-frame')))
98
+ .toBeVisible()
99
+ .withTimeout(5000)
100
+
101
+ await new Promise((resolve) => setTimeout(resolve, 400))
102
+
103
+ // verify at position 0
104
+ await expect(element(by.id('no-scroll-snap-indicator'))).toHaveText(
105
+ 'Current snap point: 0'
106
+ )
107
+
108
+ // reset tracking
109
+ await element(by.id('no-scroll-reset')).tap()
110
+
111
+ // screenshot removed for CI speed
112
+
113
+ // drag UP on frame content - should show resistance
114
+ await element(by.id('no-scroll-frame')).swipe('up', 'slow', 0.9)
115
+
116
+ await new Promise((resolve) => setTimeout(resolve, 400))
117
+
118
+ // screenshot removed for CI speed
119
+
120
+ // sheet should snap back to position 0
121
+ await expect(element(by.id('no-scroll-snap-indicator'))).toHaveText(
122
+ 'Current snap point: 0'
123
+ )
124
+
125
+ // check the max drag indicator - should be > 0 if resistance was working
126
+ // (the test component tracks maximum upward drag distance)
127
+ const attrs = await element(by.id('no-scroll-drag-indicator')).getAttributes()
128
+ console.log('Bug #3 - Max upward drag detected:', (attrs as any).text)
129
+ })
130
+ })
131
+
132
+ describe('Bug #1: Sheet with non-scrollable ScrollView', () => {
133
+ /**
134
+ * BUG #1 TEST: Non-scrollable ScrollView content should let sheet drag through
135
+ *
136
+ * Expected: When ScrollView has content that fits (not scrollable), dragging
137
+ * down should move the sheet to the next snap point.
138
+ *
139
+ * NOTE: These tests document a DETOX LIMITATION, not a Hanzo GUI bug.
140
+ * Detox's swipe() doesn't trigger RNGH gestures when ScrollView content
141
+ * is non-scrollable. The feature has been MANUALLY VERIFIED to work.
142
+ * - Manual test via XcodeBuildMCP: swiping down moves sheet from position 0 to 1 ✓
143
+ * - react-native-actions-sheet comparison test also fails (confirming Detox issue)
144
+ * See: https://github.com/wix/Detox/issues/2886
145
+ */
146
+ it.skip('should drag sheet DOWN when ScrollView content is not scrollable', async () => {
147
+ if (isAndroid()) return
148
+
149
+ await element(by.id('non-scrollable-trigger')).tap()
150
+
151
+ await waitFor(element(by.id('non-scrollable-frame')))
152
+ .toBeVisible()
153
+ .withTimeout(5000)
154
+
155
+ await new Promise((resolve) => setTimeout(resolve, 400))
156
+
157
+ // reset counters
158
+ await element(by.id('non-scrollable-reset')).tap()
159
+
160
+ // verify we start at position 0
161
+ await expect(element(by.id('non-scrollable-snap-indicator'))).toHaveText(
162
+ 'Current snap point: 0'
163
+ )
164
+
165
+ // screenshot removed for CI speed
166
+
167
+ // swipe DOWN on the scrollview (matching SheetScrollableDrag.test.ts pattern)
168
+ // at scrollY=0 with non-scrollable content, this should drag the sheet
169
+ await element(by.id('non-scrollable-scrollview')).swipe('down', 'slow', 0.5)
170
+
171
+ await new Promise((resolve) => setTimeout(resolve, 400))
172
+
173
+ // screenshot removed for CI speed
174
+
175
+ // check results
176
+ const posAttr = await element(
177
+ by.id('non-scrollable-snap-indicator')
178
+ ).getAttributes()
179
+ const statusAttr = await element(by.id('non-scrollable-status')).getAttributes()
180
+ console.log(
181
+ 'Bug #1 result - Position:',
182
+ (posAttr as any).text,
183
+ 'Status:',
184
+ (statusAttr as any).text
185
+ )
186
+
187
+ // EXPECTED: position changes to 1 (sheet moved down to lower snap)
188
+ // BUGGY: position stays 0 but scroll events fired
189
+ await expect(element(by.id('non-scrollable-snap-indicator'))).toHaveText(
190
+ 'Current snap point: 1'
191
+ )
192
+ })
193
+
194
+ // Also skipped due to same Detox limitation - handle swipe also fails with non-scrollable content
195
+ it.skip('should let handle always be draggable regardless of ScrollView', async () => {
196
+ if (isAndroid()) return
197
+
198
+ await element(by.id('non-scrollable-trigger')).tap()
199
+
200
+ await waitFor(element(by.id('non-scrollable-frame')))
201
+ .toBeVisible()
202
+ .withTimeout(5000)
203
+
204
+ await new Promise((resolve) => setTimeout(resolve, 400))
205
+
206
+ // verify we start at position 0
207
+ await expect(element(by.id('non-scrollable-snap-indicator'))).toHaveText(
208
+ 'Current snap point: 0'
209
+ )
210
+
211
+ // screenshot removed for CI speed
212
+
213
+ // swipe down on handle - this should ALWAYS work
214
+ // using 'fast' speed like Case 8 in SheetScrollableDrag.test.ts
215
+ await element(by.id('non-scrollable-handle')).swipe('down', 'fast', 0.5)
216
+
217
+ await new Promise((resolve) => setTimeout(resolve, 400))
218
+
219
+ // screenshot removed for CI speed
220
+
221
+ // handle drag should move the sheet
222
+ await expect(element(by.id('non-scrollable-snap-indicator'))).toHaveText(
223
+ 'Current snap point: 1'
224
+ )
225
+ })
226
+ })
227
+
228
+ describe('Bug #2: Sheet with scrollable ScrollView - drag up resistance', () => {
229
+ /**
230
+ * BUG #2 TEST: At scroll top and sheet top, dragging up should show resistance
231
+ *
232
+ * Expected: When scrollY=0 and sheet at top snap point, dragging up should
233
+ * apply resistance (rubber band effect) rather than doing nothing.
234
+ *
235
+ * BUG: Dragging up at this position doesn't move much at all
236
+ */
237
+ it('should show resistance when dragging up at scroll top and sheet top', async () => {
238
+ if (isAndroid()) return
239
+
240
+ await element(by.id('scrollable-trigger')).tap()
241
+
242
+ await waitFor(element(by.id('scrollable-frame')))
243
+ .toBeVisible()
244
+ .withTimeout(5000)
245
+
246
+ await new Promise((resolve) => setTimeout(resolve, 400))
247
+
248
+ // reset tracking
249
+ await element(by.id('scrollable-reset')).tap()
250
+
251
+ // ensure we're at scroll top and position 0
252
+ await expect(element(by.id('scrollable-at-top'))).toHaveText('At scroll top: YES')
253
+
254
+ // screenshot removed for CI speed
255
+
256
+ // drag UP on handle - at scroll top + sheet top, should show resistance
257
+ await element(by.id('scrollable-handle')).swipe('up', 'slow', 0.8)
258
+
259
+ await new Promise((resolve) => setTimeout(resolve, 400))
260
+
261
+ // screenshot removed for CI speed
262
+
263
+ // after rubber band, should still be at scroll top (no scroll happened)
264
+ await expect(element(by.id('scrollable-at-top'))).toHaveText('At scroll top: YES')
265
+
266
+ // frame should still be visible (sheet didn't disappear)
267
+ await expect(element(by.id('scrollable-frame'))).toBeVisible()
268
+
269
+ // check max drag indicator
270
+ const attrs = await element(by.id('scrollable-status')).getAttributes()
271
+ console.log('Bug #2 - Max upward drag:', (attrs as any).text)
272
+ })
273
+
274
+ it('should scroll content when swiping up inside scrollable sheet', async () => {
275
+ if (isAndroid()) return
276
+
277
+ await element(by.id('scrollable-trigger')).tap()
278
+
279
+ await waitFor(element(by.id('scrollable-frame')))
280
+ .toBeVisible()
281
+ .withTimeout(5000)
282
+
283
+ await new Promise((resolve) => setTimeout(resolve, 400))
284
+
285
+ // verify starting state - at scroll top
286
+ await expect(element(by.id('scrollable-at-top'))).toHaveText('At scroll top: YES')
287
+
288
+ // swipe UP on scrollview content - should scroll content (not move sheet)
289
+ await element(by.id('scrollable-scrollview')).swipe('up', 'slow', 0.5)
290
+
291
+ await new Promise((resolve) => setTimeout(resolve, 300))
292
+
293
+ // scroll Y should now be > 0
294
+ await expect(element(by.id('scrollable-at-top'))).toHaveText('At scroll top: NO')
295
+ })
296
+
297
+ it('should drag sheet DOWN via handle when at scroll top', async () => {
298
+ if (isAndroid()) return
299
+
300
+ await element(by.id('scrollable-trigger')).tap()
301
+
302
+ await waitFor(element(by.id('scrollable-frame')))
303
+ .toBeVisible()
304
+ .withTimeout(5000)
305
+
306
+ await new Promise((resolve) => setTimeout(resolve, 400))
307
+
308
+ // verify at scroll top
309
+ await expect(element(by.id('scrollable-at-top'))).toHaveText('At scroll top: YES')
310
+
311
+ // screenshot removed for CI speed
312
+
313
+ // drag DOWN on handle - should move sheet to position 1
314
+ await element(by.id('scrollable-handle')).swipe('down', 'slow', 0.8)
315
+
316
+ await new Promise((resolve) => setTimeout(resolve, 400))
317
+
318
+ // screenshot removed for CI speed
319
+
320
+ // sheet should be at lower snap point (or dismissed)
321
+ // verify animation completes without crash
322
+ await new Promise((resolve) => setTimeout(resolve, 400))
323
+ })
324
+ })
325
+
326
+ describe('Comparison: react-native-actions-sheet', () => {
327
+ /**
328
+ * Reference test using react-native-actions-sheet to verify Detox
329
+ * can properly trigger RNGH gestures.
330
+ *
331
+ * RESULT: This test ALSO FAILS, confirming that Detox's swipe() cannot
332
+ * trigger RNGH gestures when content is non-scrollable. This is a Detox
333
+ * limitation, not a bug in either Hanzo GUI or actions-sheet.
334
+ */
335
+ it.skip('should drag actions-sheet DOWN with non-scrollable content', async () => {
336
+ if (isAndroid()) return
337
+
338
+ await element(by.id('actions-sheet-trigger')).tap()
339
+
340
+ await waitFor(element(by.id('actions-sheet-content')))
341
+ .toBeVisible()
342
+ .withTimeout(5000)
343
+
344
+ await new Promise((resolve) => setTimeout(resolve, 400))
345
+
346
+ // verify at snap index 0
347
+ await expect(element(by.id('actions-sheet-snap-indicator'))).toHaveText(
348
+ 'Snap index: 0'
349
+ )
350
+
351
+ // screenshot removed for CI speed
352
+
353
+ // swipe DOWN on content - should move sheet
354
+ await element(by.id('actions-sheet-content')).swipe('down', 'slow', 0.5)
355
+
356
+ await new Promise((resolve) => setTimeout(resolve, 400))
357
+
358
+ // screenshot removed for CI speed
359
+
360
+ // if actions-sheet can move via Detox swipe, expect snap index 1
361
+ await expect(element(by.id('actions-sheet-snap-indicator'))).toHaveText(
362
+ 'Snap index: 1'
363
+ )
364
+ })
365
+ })
366
+ })
367
+
368
+ async function navigateToSheetDragResistCase() {
369
+ await navigateToTestCase('SheetDragResistCase', 'sheet-drag-resist-screen')
370
+ }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Detox E2E Test for Sheet + Keyboard interaction
3
+ *
4
+ * Tests smooth keyboard + sheet coordination:
5
+ * 1. Open keyboard (tap input) -> sheet moves up smoothly
6
+ * 2. Drag sheet down while keyboard open -> keyboard dismisses FIRST
7
+ * 3. Dismiss keyboard (tap outside) -> sheet returns to original position
8
+ * 4. Fast keyboard show/hide should be smooth
9
+ *
10
+ * When keyboard-controller is installed, these should be extra smooth (60/120 FPS).
11
+ * Without it, falls back to basic Keyboard API (still functional, less smooth).
12
+ *
13
+ * TODO: This test is WIP - keyboard-controller causes Detox sync issues.
14
+ * Need to investigate disableSynchronization() timing or alternative approach.
15
+ */
16
+
17
+ import { by, device, element, expect, waitFor } from 'detox'
18
+
19
+ // only run on iOS - keyboard behavior differs on Android
20
+ const isAndroid = () => device.getPlatform() === 'android'
21
+
22
+ // skip until we fix keyboard-controller sync issues with Detox
23
+ describe.skip('SheetKeyboardDrag - Keyboard + Sheet Integration', () => {
24
+ beforeAll(async () => {
25
+ if (isAndroid()) return
26
+ await device.launchApp({ newInstance: true })
27
+ await navigateToSheetKeyboardDrag()
28
+ })
29
+
30
+ beforeEach(async () => {
31
+ if (isAndroid()) return
32
+ await device.reloadReactNative()
33
+ await navigateToSheetKeyboardDrag()
34
+ })
35
+
36
+ it('should show status indicators', async () => {
37
+ if (isAndroid()) return
38
+ // RNGH should be enabled
39
+ await expect(element(by.id('sheet-keyboard-drag-rngh-status'))).toHaveText('RNGH: ✓')
40
+ // KBC status shows whether keyboard-controller is installed
41
+ // either ✓ (enabled) or ○ (not installed, using fallback)
42
+ })
43
+
44
+ it('Case 1: open sheet and verify initial state', async () => {
45
+ if (isAndroid()) return
46
+
47
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
48
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
49
+ .toBeVisible()
50
+ .withTimeout(3000)
51
+
52
+ // wait for animation
53
+ await new Promise((r) => setTimeout(r, 400))
54
+
55
+ // should be at position 0, keyboard hidden
56
+ await expect(element(by.id('sheet-keyboard-drag-position'))).toHaveText(
57
+ 'Sheet position: 0'
58
+ )
59
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
60
+ 'Keyboard: hidden'
61
+ )
62
+ })
63
+
64
+ it('Case 2: tap input shows keyboard, sheet moves up', async () => {
65
+ if (isAndroid()) return
66
+
67
+ // open sheet
68
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
69
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
70
+ .toBeVisible()
71
+ .withTimeout(3000)
72
+ await new Promise((r) => setTimeout(r, 400))
73
+
74
+ await device.takeScreenshot('case2-before-keyboard')
75
+
76
+ // tap input to show keyboard
77
+ await element(by.id('sheet-keyboard-drag-input')).tap()
78
+ await new Promise((r) => setTimeout(r, 500)) // wait for keyboard animation
79
+
80
+ await device.takeScreenshot('case2-after-keyboard')
81
+
82
+ // keyboard should be visible
83
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
84
+ 'Keyboard: visible'
85
+ )
86
+
87
+ // keyboard height should be > 0
88
+ const kbHeightAttr = await element(
89
+ by.id('sheet-keyboard-drag-kb-height')
90
+ ).getAttributes()
91
+ const kbHeightText = (kbHeightAttr as any).text as string
92
+ const kbHeight = parseInt(kbHeightText.replace('Keyboard height: ', ''), 10)
93
+ console.log('Case 2: keyboard height =', kbHeight)
94
+ if (kbHeight < 200) {
95
+ throw new Error(`Expected keyboard height > 200, got ${kbHeight}`)
96
+ }
97
+ })
98
+
99
+ it('Case 3: dismiss keyboard returns sheet to original position', async () => {
100
+ if (isAndroid()) return
101
+
102
+ // open sheet
103
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
104
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
105
+ .toBeVisible()
106
+ .withTimeout(3000)
107
+ await new Promise((r) => setTimeout(r, 400))
108
+
109
+ // tap input to show keyboard
110
+ await element(by.id('sheet-keyboard-drag-input')).tap()
111
+ await new Promise((r) => setTimeout(r, 500))
112
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
113
+ 'Keyboard: visible'
114
+ )
115
+
116
+ await device.takeScreenshot('case3-keyboard-visible')
117
+
118
+ // dismiss keyboard via button
119
+ await element(by.id('sheet-keyboard-drag-dismiss-kb')).tap()
120
+ await new Promise((r) => setTimeout(r, 400))
121
+
122
+ await device.takeScreenshot('case3-keyboard-dismissed')
123
+
124
+ // keyboard should be hidden
125
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
126
+ 'Keyboard: hidden'
127
+ )
128
+ // sheet should still be at position 0 (restored)
129
+ await expect(element(by.id('sheet-keyboard-drag-position'))).toHaveText(
130
+ 'Sheet position: 0'
131
+ )
132
+ })
133
+
134
+ it('Case 4: drag sheet down while keyboard open dismisses keyboard first', async () => {
135
+ if (isAndroid()) return
136
+
137
+ // open sheet
138
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
139
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
140
+ .toBeVisible()
141
+ .withTimeout(3000)
142
+ await new Promise((r) => setTimeout(r, 400))
143
+
144
+ // tap input to show keyboard
145
+ await element(by.id('sheet-keyboard-drag-input')).tap()
146
+ await new Promise((r) => setTimeout(r, 500))
147
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
148
+ 'Keyboard: visible'
149
+ )
150
+
151
+ await device.takeScreenshot('case4-before-drag')
152
+
153
+ // drag sheet down on handle (should dismiss keyboard)
154
+ await element(by.id('sheet-keyboard-drag-handle')).swipe('down', 'slow', 0.3)
155
+ await new Promise((r) => setTimeout(r, 600))
156
+
157
+ await device.takeScreenshot('case4-after-drag')
158
+
159
+ // keyboard should be dismissed
160
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
161
+ 'Keyboard: hidden'
162
+ )
163
+
164
+ // check events - should see keyboard dismiss
165
+ const eventsAttr = await element(by.id('sheet-keyboard-drag-events')).getAttributes()
166
+ console.log('Case 4 events:', (eventsAttr as any).text)
167
+ })
168
+
169
+ it('Case 5: switch between inputs keeps keyboard visible', async () => {
170
+ if (isAndroid()) return
171
+
172
+ // open sheet
173
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
174
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
175
+ .toBeVisible()
176
+ .withTimeout(3000)
177
+ await new Promise((r) => setTimeout(r, 400))
178
+
179
+ // tap first input
180
+ await element(by.id('sheet-keyboard-drag-input')).tap()
181
+ await new Promise((r) => setTimeout(r, 400))
182
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
183
+ 'Keyboard: visible'
184
+ )
185
+
186
+ // tap second input
187
+ await element(by.id('sheet-keyboard-drag-input-2')).tap()
188
+ await new Promise((r) => setTimeout(r, 300))
189
+
190
+ // keyboard should still be visible
191
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
192
+ 'Keyboard: visible'
193
+ )
194
+
195
+ await device.takeScreenshot('case5-switched-inputs')
196
+ })
197
+
198
+ it('Case 6: close sheet dismisses keyboard', async () => {
199
+ if (isAndroid()) return
200
+
201
+ // open sheet
202
+ await element(by.id('sheet-keyboard-drag-trigger')).tap()
203
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
204
+ .toBeVisible()
205
+ .withTimeout(5000)
206
+ await new Promise((r) => setTimeout(r, 600))
207
+
208
+ // tap input to show keyboard
209
+ await element(by.id('sheet-keyboard-drag-input')).tap()
210
+ await new Promise((r) => setTimeout(r, 500))
211
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
212
+ 'Keyboard: visible'
213
+ )
214
+
215
+ // close sheet
216
+ await element(by.id('sheet-keyboard-drag-close')).tap()
217
+ await new Promise((r) => setTimeout(r, 500))
218
+
219
+ // sheet should be closed
220
+ await waitFor(element(by.id('sheet-keyboard-drag-frame')))
221
+ .not.toBeVisible()
222
+ .withTimeout(2000)
223
+
224
+ // keyboard should be hidden (check outside sheet)
225
+ await expect(element(by.id('sheet-keyboard-drag-kb-visible'))).toHaveText(
226
+ 'Keyboard: hidden'
227
+ )
228
+ })
229
+ })
230
+
231
+ async function navigateToSheetKeyboardDrag() {
232
+ // wait for app to load
233
+ await waitFor(element(by.text('Kitchen Sink')))
234
+ .toExist()
235
+ .withTimeout(30000)
236
+
237
+ await new Promise((r) => setTimeout(r, 500))
238
+
239
+ // use quick access link from home screen
240
+ await waitFor(element(by.id('home-sheet-keyboard-test')))
241
+ .toBeVisible()
242
+ .withTimeout(5000)
243
+ await element(by.id('home-sheet-keyboard-test')).tap()
244
+
245
+ // wait for test screen
246
+ await waitFor(element(by.id('sheet-keyboard-drag-trigger')))
247
+ .toExist()
248
+ .withTimeout(5000)
249
+ }