@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,304 @@
1
+ import { expect, test, type Page } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ // layout poll interval is ~233ms (14 frames)
5
+ const POLL_WAIT = 500
6
+ // CI environments are slower - give more time for layouts to settle
7
+ const INITIAL_SETTLE_TIME = process.env.CI ? 3000 : 1500
8
+
9
+ // gating thresholds - fail if exceeded
10
+ const MAX_IO_DELAY_MS = 100 // fail if IO callback takes > 100ms
11
+ const MAX_WARNINGS_PER_TEST = 3 // fail if too many warnings
12
+
13
+ async function collectConsoleWarnings(
14
+ page: Page
15
+ ): Promise<{ count: number; avgDelay: number; maxDelay: number }> {
16
+ const result = await page.evaluate(() => {
17
+ const warnings = (window as any).__ioDelayWarnings || []
18
+ if (warnings.length === 0) return { count: 0, avgDelay: 0, maxDelay: 0 }
19
+ const sum = warnings.reduce((a: number, b: number) => a + b, 0)
20
+ const max = Math.max(...warnings)
21
+ return {
22
+ count: warnings.length,
23
+ avgDelay: Math.round(sum / warnings.length),
24
+ maxDelay: max,
25
+ }
26
+ })
27
+ return result
28
+ }
29
+
30
+ async function getStats(
31
+ page: Page
32
+ ): Promise<{ total: number; lastBatch: number; lastTime: number; max: number }> {
33
+ const total = await page.getByTestId('stat-total').innerText()
34
+ const lastBatch = await page.getByTestId('stat-last-batch').innerText()
35
+ const lastTime = await page.getByTestId('stat-last-time').innerText()
36
+ const max = await page.getByTestId('stat-max').innerText()
37
+
38
+ return {
39
+ total: parseInt(total.replace('total: ', ''), 10) || 0,
40
+ lastBatch: parseInt(lastBatch.replace('lastBatch: ', ''), 10) || 0,
41
+ lastTime: parseInt(lastTime.replace('lastTime: ', ''), 10) || 0,
42
+ max: parseInt(max.replace('max: ', '').replace('ms', ''), 10) || 0,
43
+ }
44
+ }
45
+
46
+ test.describe('onLayout stress test', () => {
47
+ // stress tests are flaky in CI - give them extra retries
48
+ test.describe.configure({ retries: 3 })
49
+
50
+ test.beforeEach(async ({ page }) => {
51
+ // set up console warning tracking
52
+ // BUG FIX: console.warn('[onLayout-io-delay]', delay + 'ms', ...) puts delay in args[1]
53
+ await page.addInitScript(() => {
54
+ ;(window as any).__ioDelayWarnings = []
55
+ const originalWarn = console.warn
56
+ console.warn = (...args: any[]) => {
57
+ const prefix = args[0]
58
+ const delayArg = args[1] // delay is in second argument
59
+ if (typeof prefix === 'string' && prefix.includes('[onLayout-io-delay]')) {
60
+ if (typeof delayArg === 'string') {
61
+ const match = delayArg.match(/(\d+)ms/)
62
+ if (match) {
63
+ ;(window as any).__ioDelayWarnings.push(parseInt(match[1], 10))
64
+ }
65
+ }
66
+ }
67
+ originalWarn.apply(console, args)
68
+ }
69
+ })
70
+
71
+ await setupPage(page, { name: 'OnLayoutStressCase', type: 'useCase' })
72
+ })
73
+
74
+ test('initial render should not exceed threshold', async ({ page }) => {
75
+ // wait for initial layout callbacks to settle
76
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
77
+
78
+ const stats = await getStats(page)
79
+ const warnings = await collectConsoleWarnings(page)
80
+
81
+ console.log('=== INITIAL RENDER BENCHMARK ===')
82
+ console.log(`total callbacks: ${stats.total}`)
83
+ console.log(`last batch size: ${stats.lastBatch}`)
84
+ console.log(`max batch time: ${stats.max}ms`)
85
+ console.log(`IO delay warnings: ${warnings.count}`)
86
+ if (warnings.count > 0) {
87
+ console.log(`avg IO delay: ${warnings.avgDelay}ms`)
88
+ console.log(`max IO delay: ${warnings.maxDelay}ms`)
89
+ }
90
+
91
+ // gating assertions
92
+ expect(stats.total, 'should have onLayout callbacks').toBeGreaterThan(50)
93
+ expect(warnings.maxDelay, `IO delay should be < ${MAX_IO_DELAY_MS}ms`).toBeLessThan(
94
+ MAX_IO_DELAY_MS
95
+ )
96
+ })
97
+
98
+ test('resize should trigger batch updates efficiently', async ({ page }) => {
99
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
100
+
101
+ // scroll sibling section into view — onLayout only fires for visible elements
102
+ await page.getByTestId('section-siblings').scrollIntoViewIfNeeded()
103
+ await page.waitForTimeout(POLL_WAIT)
104
+
105
+ // reset stats after initial render
106
+ await page.getByTestId('btn-reset-stats').click()
107
+ await page.waitForTimeout(200)
108
+
109
+ // trigger width resize
110
+ await page.getByTestId('btn-resize-width').click()
111
+ await page.waitForTimeout(POLL_WAIT * 3)
112
+
113
+ const stats = await getStats(page)
114
+ const warnings = await collectConsoleWarnings(page)
115
+
116
+ console.log('=== WIDTH RESIZE BENCHMARK ===')
117
+ console.log(`callbacks after resize: ${stats.total}`)
118
+ console.log(`last batch size: ${stats.lastBatch}`)
119
+ console.log(`last batch time: ${stats.lastTime}ms`)
120
+ console.log(`IO delay warnings: ${warnings.count}`)
121
+
122
+ // gating assertions
123
+ expect(stats.total, 'resize should trigger callbacks').toBeGreaterThan(0)
124
+ expect(
125
+ warnings.count,
126
+ `should have fewer than ${MAX_WARNINGS_PER_TEST} warnings`
127
+ ).toBeLessThan(MAX_WARNINGS_PER_TEST)
128
+ })
129
+
130
+ test('grid resize should trigger efficient updates', async ({ page }) => {
131
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
132
+ await page.getByTestId('btn-reset-stats').click()
133
+ await page.waitForTimeout(100)
134
+
135
+ await page.getByTestId('btn-resize-grid').click()
136
+ await page.waitForTimeout(POLL_WAIT * 3)
137
+
138
+ const stats = await getStats(page)
139
+ const warnings = await collectConsoleWarnings(page)
140
+
141
+ console.log('=== GRID RESIZE BENCHMARK ===')
142
+ console.log(`callbacks: ${stats.total}`)
143
+ console.log(`batch time: ${stats.lastTime}ms`)
144
+ console.log(`IO delay warnings: ${warnings.count}`)
145
+
146
+ // gating assertions - 40 grid items should trigger ~40 callbacks
147
+ expect(stats.total, 'grid resize should trigger callbacks').toBeGreaterThan(20)
148
+ expect(warnings.maxDelay, `IO delay should be < ${MAX_IO_DELAY_MS}ms`).toBeLessThan(
149
+ MAX_IO_DELAY_MS
150
+ )
151
+ })
152
+
153
+ test('list expand should trigger efficient updates', async ({ page }) => {
154
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
155
+ await page.getByTestId('btn-reset-stats').click()
156
+ await page.waitForTimeout(100)
157
+
158
+ await page.getByTestId('btn-toggle-expand').click()
159
+ await page.waitForTimeout(POLL_WAIT * 3)
160
+
161
+ const stats = await getStats(page)
162
+ const warnings = await collectConsoleWarnings(page)
163
+
164
+ console.log('=== LIST EXPAND BENCHMARK ===')
165
+ console.log(`callbacks: ${stats.total}`)
166
+ console.log(`batch time: ${stats.lastTime}ms`)
167
+ console.log(`IO delay warnings: ${warnings.count}`)
168
+
169
+ // gating assertions - 20 list items should trigger ~20 callbacks
170
+ expect(stats.total, 'list expand should trigger callbacks').toBeGreaterThan(10)
171
+ expect(warnings.maxDelay, `IO delay should be < ${MAX_IO_DELAY_MS}ms`).toBeLessThan(
172
+ MAX_IO_DELAY_MS
173
+ )
174
+ })
175
+
176
+ test('container resize affects all children', async ({ page }) => {
177
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
178
+ await page.getByTestId('btn-reset-stats').click()
179
+ await page.waitForTimeout(100)
180
+
181
+ await page.getByTestId('btn-resize-container').click()
182
+ await page.waitForTimeout(POLL_WAIT * 3)
183
+
184
+ const stats = await getStats(page)
185
+ const warnings = await collectConsoleWarnings(page)
186
+
187
+ console.log('=== CONTAINER RESIZE BENCHMARK ===')
188
+ console.log(`callbacks: ${stats.total}`)
189
+ console.log(`batch time: ${stats.lastTime}ms`)
190
+ console.log(`IO delay warnings: ${warnings.count}`)
191
+
192
+ // gating assertion
193
+ expect(warnings.maxDelay, `IO delay should be < ${MAX_IO_DELAY_MS}ms`).toBeLessThan(
194
+ MAX_IO_DELAY_MS
195
+ )
196
+ })
197
+
198
+ test('rapid successive resizes', async ({ page }) => {
199
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
200
+ await page.getByTestId('btn-reset-stats').click()
201
+ await page.waitForTimeout(100)
202
+
203
+ // rapid fire multiple resize operations
204
+ for (let i = 0; i < 5; i++) {
205
+ await page.getByTestId('btn-resize-width').click()
206
+ await page.waitForTimeout(50)
207
+ await page.getByTestId('btn-resize-grid').click()
208
+ await page.waitForTimeout(50)
209
+ }
210
+
211
+ await page.waitForTimeout(POLL_WAIT * 3)
212
+
213
+ const stats = await getStats(page)
214
+ const warnings = await collectConsoleWarnings(page)
215
+
216
+ console.log('=== RAPID RESIZE BENCHMARK ===')
217
+ console.log(`total callbacks: ${stats.total}`)
218
+ console.log(`max batch time: ${stats.max}ms`)
219
+ console.log(`IO delay warnings: ${warnings.count}`)
220
+ if (warnings.count > 0) {
221
+ console.log(`avg IO delay: ${warnings.avgDelay}ms`)
222
+ console.log(`max IO delay: ${warnings.maxDelay}ms`)
223
+ }
224
+
225
+ // gating assertion - rapid resize is stressful but shouldn't explode
226
+ expect(
227
+ warnings.maxDelay,
228
+ `IO delay should be < ${MAX_IO_DELAY_MS}ms even under stress`
229
+ ).toBeLessThan(MAX_IO_DELAY_MS)
230
+ })
231
+
232
+ test('full benchmark suite', async ({ page }) => {
233
+ const results: Record<string, any> = {}
234
+
235
+ // initial render
236
+ await page.waitForTimeout(INITIAL_SETTLE_TIME)
237
+ results.initial = {
238
+ ...(await getStats(page)),
239
+ warnings: await collectConsoleWarnings(page),
240
+ }
241
+
242
+ // width resize
243
+ await page.getByTestId('btn-reset-stats').click()
244
+ await page.waitForTimeout(100)
245
+ await page.getByTestId('btn-resize-width').click()
246
+ await page.waitForTimeout(POLL_WAIT * 3)
247
+ results.widthResize = {
248
+ ...(await getStats(page)),
249
+ warnings: await collectConsoleWarnings(page),
250
+ }
251
+
252
+ // grid resize
253
+ await page.getByTestId('btn-reset-stats').click()
254
+ await page.waitForTimeout(100)
255
+ await page.getByTestId('btn-resize-grid').click()
256
+ await page.waitForTimeout(POLL_WAIT * 3)
257
+ results.gridResize = {
258
+ ...(await getStats(page)),
259
+ warnings: await collectConsoleWarnings(page),
260
+ }
261
+
262
+ // expand list
263
+ await page.getByTestId('btn-reset-stats').click()
264
+ await page.waitForTimeout(100)
265
+ await page.getByTestId('btn-toggle-expand').click()
266
+ await page.waitForTimeout(POLL_WAIT * 3)
267
+ results.listExpand = {
268
+ ...(await getStats(page)),
269
+ warnings: await collectConsoleWarnings(page),
270
+ }
271
+
272
+ // container resize
273
+ await page.getByTestId('btn-reset-stats').click()
274
+ await page.waitForTimeout(100)
275
+ await page.getByTestId('btn-resize-container').click()
276
+ await page.waitForTimeout(POLL_WAIT * 3)
277
+ results.containerResize = {
278
+ ...(await getStats(page)),
279
+ warnings: await collectConsoleWarnings(page),
280
+ }
281
+
282
+ console.log('\n========== FULL BENCHMARK RESULTS ==========')
283
+ console.log(JSON.stringify(results, null, 2))
284
+ console.log('=============================================\n')
285
+
286
+ // calculate aggregate metrics
287
+ const allMaxDelays = Object.values(results).map((r: any) => r.warnings?.maxDelay || 0)
288
+ const overallMaxDelay = Math.max(...allMaxDelays)
289
+ const totalWarnings = Object.values(results).reduce(
290
+ (sum: number, r: any) => sum + (r.warnings?.count || 0),
291
+ 0
292
+ )
293
+
294
+ console.log(
295
+ `AGGREGATE: ${totalWarnings} total warnings, ${overallMaxDelay}ms max IO delay`
296
+ )
297
+
298
+ // gating assertions for the full suite
299
+ expect(
300
+ overallMaxDelay,
301
+ `max IO delay across all tests should be < ${MAX_IO_DELAY_MS}ms`
302
+ ).toBeLessThan(MAX_IO_DELAY_MS)
303
+ })
304
+ })
@@ -0,0 +1,73 @@
1
+ import { expect, test } from '@playwright/test'
2
+
3
+ import { getStyles } from './utils'
4
+ import { setupPage } from './test-utils'
5
+
6
+ test.beforeEach(async ({ page }) => {
7
+ await setupPage(page, { name: 'ParagraphSpanFontInheritance', type: 'useCase' })
8
+ })
9
+
10
+ test(`Span inherits $mono fontFamily from Paragraph`, async ({ page }) => {
11
+ const parentStyles = await getStyles(page.getByTestId('parent-mono').first())
12
+ const nestedStyles = await getStyles(page.getByTestId('nested-span-mono').first())
13
+
14
+ // parent should have mono font family
15
+ expect(parentStyles.fontFamily).toContain('mono')
16
+
17
+ // span should inherit the mono font family
18
+ expect(nestedStyles.fontFamily).toBe(parentStyles.fontFamily)
19
+ })
20
+
21
+ test(`Span inherits $body fontFamily from Paragraph`, async ({ page }) => {
22
+ const parentStyles = await getStyles(page.getByTestId('parent-body').first())
23
+ const nestedStyles = await getStyles(page.getByTestId('nested-span-body').first())
24
+
25
+ // span should inherit the body font family
26
+ expect(nestedStyles.fontFamily).toBe(parentStyles.fontFamily)
27
+ })
28
+
29
+ test(`nested Text inherits $mono fontFamily from Text (baseline)`, async ({ page }) => {
30
+ const parentStyles = await getStyles(page.getByTestId('parent-text-mono').first())
31
+ const nestedStyles = await getStyles(page.getByTestId('nested-text-mono').first())
32
+
33
+ // parent should have mono font family
34
+ expect(parentStyles.fontFamily).toContain('mono')
35
+
36
+ // nested text should inherit the mono font family
37
+ expect(nestedStyles.fontFamily).toBe(parentStyles.fontFamily)
38
+ })
39
+
40
+ test(`Span explicit fontFamily override works`, async ({ page }) => {
41
+ const parentStyles = await getStyles(page.getByTestId('parent-mono-override').first())
42
+ const nestedStyles = await getStyles(page.getByTestId('nested-span-override').first())
43
+
44
+ // parent should have mono font family
45
+ expect(parentStyles.fontFamily).toContain('mono')
46
+
47
+ // span with explicit $body should NOT inherit mono
48
+ expect(nestedStyles.fontFamily).not.toBe(parentStyles.fontFamily)
49
+ })
50
+
51
+ test(`SizableText keeps its explicit fontFamily (does not inherit)`, async ({ page }) => {
52
+ const parentStyles = await getStyles(page.getByTestId('parent-mono-sizable').first())
53
+ const nestedStyles = await getStyles(page.getByTestId('nested-sizable-body').first())
54
+
55
+ // parent should have mono font family
56
+ expect(parentStyles.fontFamily).toContain('mono')
57
+
58
+ // SizableText has explicit fontFamily: '$body' in its static config,
59
+ // so it should NOT inherit mono but keep its body font
60
+ expect(nestedStyles.fontFamily).not.toBe(parentStyles.fontFamily)
61
+ expect(nestedStyles.fontFamily).toContain('Inter')
62
+ })
63
+
64
+ test(`Text (like Link) inside Paragraph inherits fontFamily`, async ({ page }) => {
65
+ const parentStyles = await getStyles(page.getByTestId('parent-para-link').first())
66
+ const nestedStyles = await getStyles(page.getByTestId('nested-link-text').first())
67
+
68
+ // parent should have mono font family
69
+ expect(parentStyles.fontFamily).toContain('mono')
70
+
71
+ // nested Text should inherit the mono font family
72
+ expect(nestedStyles.fontFamily).toBe(parentStyles.fontFamily)
73
+ })
@@ -0,0 +1,123 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ test.beforeEach(async ({ page }) => {
5
+ await setupPage(page, { name: 'PointerEventsCase', type: 'useCase' })
6
+ })
7
+
8
+ test('pointer events - down and up fire on click', async ({ page }) => {
9
+ const target = page.locator('[data-testid="pointer-target"]')
10
+ const downCount = page.locator('[data-testid="down-count"]')
11
+ const upCount = page.locator('[data-testid="up-count"]')
12
+
13
+ await expect(downCount).toHaveText('Down: 0')
14
+ await expect(upCount).toHaveText('Up: 0')
15
+
16
+ await target.click()
17
+
18
+ await expect(downCount).toHaveText('Down: 1')
19
+ await expect(upCount).toHaveText('Up: 1')
20
+ })
21
+
22
+ test('pointer events - enter and leave fire on hover', async ({ page }) => {
23
+ const target = page.locator('[data-testid="pointer-target"]')
24
+ const enterCount = page.locator('[data-testid="enter-count"]')
25
+ const leaveCount = page.locator('[data-testid="leave-count"]')
26
+
27
+ await expect(enterCount).toHaveText('Enter: 0')
28
+ await expect(leaveCount).toHaveText('Leave: 0')
29
+
30
+ // hover over target
31
+ await target.hover()
32
+ await expect(enterCount).toHaveText('Enter: 1')
33
+
34
+ // move away from target
35
+ await page.mouse.move(0, 0)
36
+ await expect(leaveCount).toHaveText('Leave: 1')
37
+ })
38
+
39
+ test('pointer events - move fires during drag', async ({ page }) => {
40
+ const target = page.locator('[data-testid="pointer-target"]')
41
+ const moveCount = page.locator('[data-testid="move-count"]')
42
+
43
+ await expect(moveCount).toHaveText('Move: 0')
44
+
45
+ // get the bounding box and move within it
46
+ const box = await target.boundingBox()
47
+ if (!box) throw new Error('Could not get bounding box')
48
+
49
+ // move mouse across the target
50
+ const startX = box.x + 10
51
+ const startY = box.y + 10
52
+ const endX = box.x + box.width - 10
53
+ const endY = box.y + box.height - 10
54
+
55
+ await page.mouse.move(startX, startY)
56
+ await page.mouse.move(endX, endY, { steps: 5 })
57
+
58
+ // should have fired multiple move events
59
+ const text = await moveCount.textContent()
60
+ const count = parseInt(text?.replace('Move: ', '') || '0')
61
+ expect(count).toBeGreaterThan(0)
62
+ })
63
+
64
+ test('pointer events - box-none allows clicks to pass through parent to element behind', async ({
65
+ page,
66
+ }) => {
67
+ const parentCount = page.locator('[data-testid="box-none-parent-count"]')
68
+ const childCount = page.locator('[data-testid="box-none-child-count"]')
69
+ const behindCount = page.locator('[data-testid="box-none-behind-count"]')
70
+ const behind = page.locator('[data-testid="box-none-behind"]')
71
+
72
+ // initial state
73
+ await expect(parentCount).toHaveText('BoxNoneParent: 0')
74
+ await expect(childCount).toHaveText('BoxNoneChild: 0')
75
+ await expect(behindCount).toHaveText('BoxNoneBehind: 0')
76
+
77
+ // click directly on parent area (where behind element is underneath)
78
+ // box-none should let the click pass through to the behind element
79
+ const behindBox = await behind.boundingBox()
80
+ if (!behindBox) throw new Error('Could not get behind bounding box')
81
+
82
+ // get center of the behind element which is covered by the parent
83
+ const centerX = behindBox.x + behindBox.width / 2
84
+ const centerY = behindBox.y + behindBox.height / 2
85
+
86
+ // clicking at this position should:
87
+ // 1. NOT trigger the parent's onPress (box-none means parent ignores pointer events)
88
+ // 2. Trigger the behind element's onPress (click passes through)
89
+ await page.mouse.click(centerX, centerY)
90
+
91
+ // parent should not have received the click
92
+ await expect(parentCount).toHaveText('BoxNoneParent: 0')
93
+ // behind element should have received the click
94
+ await expect(behindCount).toHaveText('BoxNoneBehind: 1')
95
+ })
96
+
97
+ test('pointer events - box-none child still receives clicks', async ({ page }) => {
98
+ const childCount = page.locator('[data-testid="box-none-child-count"]')
99
+ const child = page.locator('[data-testid="box-none-child"]')
100
+
101
+ await expect(childCount).toHaveText('BoxNoneChild: 0')
102
+
103
+ // clicking on child should work (children can still receive events)
104
+ await child.click()
105
+ await expect(childCount).toHaveText('BoxNoneChild: 1')
106
+ })
107
+
108
+ test('pointer events - box-none applies correct CSS', async ({ page }) => {
109
+ const parent = page.locator('[data-testid="box-none-parent"]')
110
+ const child = page.locator('[data-testid="box-none-child"]')
111
+
112
+ // parent should have pointer-events: none
113
+ const parentPointerEvents = await parent.evaluate(
114
+ (el) => window.getComputedStyle(el).pointerEvents
115
+ )
116
+ expect(parentPointerEvents).toBe('none')
117
+
118
+ // direct children should have pointer-events: auto (due to box-none polyfill)
119
+ const childPointerEvents = await child.evaluate(
120
+ (el) => window.getComputedStyle(el).pointerEvents
121
+ )
122
+ expect(childPointerEvents).toBe('auto')
123
+ })