@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,76 @@
1
+ // workaround: expo-modules-core 55.x ships Swift 6 strict concurrency
2
+ // which requires SWIFT_VERSION=6 to compile (uses @MainActor in conformance clauses).
3
+ // SWIFT_STRICT_CONCURRENCY=minimal suppresses the resulting concurrency warnings
4
+ // that would otherwise become errors in swift 6 mode.
5
+ // tracking issue: https://github.com/expo/expo/issues/42525
6
+ // remove this plugin once expo-modules-core ships a fix or expo SDK 56+ resolves it.
7
+ const { withDangerousMod } = require('@expo/config-plugins')
8
+ const fs = require('fs')
9
+ const path = require('path')
10
+
11
+ module.exports = function withExpoModulesCoreSwift6(config) {
12
+ return withDangerousMod(config, [
13
+ 'ios',
14
+ async (config) => {
15
+ const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile')
16
+
17
+ // the Podfile may not exist yet during early prebuild phases - skip if so
18
+ if (!fs.existsSync(podfilePath)) {
19
+ return config
20
+ }
21
+
22
+ let podfile = fs.readFileSync(podfilePath, 'utf8')
23
+
24
+ // avoid double-injection
25
+ if (podfile.includes('# workaround: expo-modules-core 55.x')) {
26
+ return config
27
+ }
28
+
29
+ const workaround = `
30
+ # workaround: expo-modules-core 55.x requires Swift 6 mode with isolated
31
+ # conformances (SE-0470) for @MainActor in protocol conformance syntax.
32
+ # SWIFT_STRICT_CONCURRENCY=minimal suppresses concurrency warnings/errors.
33
+ installer.pods_project.targets.each do |target|
34
+ if target.name == 'ExpoModulesCore'
35
+ target.build_configurations.each do |build_config|
36
+ build_config.build_settings['SWIFT_VERSION'] = '6'
37
+ build_config.build_settings['SWIFT_STRICT_CONCURRENCY'] = 'minimal'
38
+ flags = build_config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)'
39
+ unless flags.include?('IsolatedConformances')
40
+ build_config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -enable-upcoming-feature IsolatedConformances"
41
+ end
42
+ end
43
+ end
44
+ # workaround: ContextMenuAuxiliaryPreview uses deprecated transform: .default
45
+ # which is an error in Xcode 26 / Swift 6.2 strict mode.
46
+ if target.name == 'ContextMenuAuxiliaryPreview'
47
+ target.build_configurations.each do |build_config|
48
+ build_config.build_settings['SWIFT_TREAT_WARNINGS_AS_ERRORS'] = 'NO'
49
+ build_config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'NO'
50
+ end
51
+ end
52
+ end
53
+ `
54
+ // insert before the closing `end` of post_install block
55
+ const updated = podfile.replace(
56
+ /(post_install do \|installer\|.*?)(^\s+end\s*\nend)/ms,
57
+ `$1${workaround}$2`
58
+ )
59
+
60
+ if (updated === podfile) {
61
+ console.warn(
62
+ '[expo-modules-core-swift6] WARNING: could not find post_install block in Podfile - workaround not applied'
63
+ )
64
+ } else {
65
+ console.log(
66
+ '[expo-modules-core-swift6] applied ExpoModulesCore Swift 6 workaround to Podfile'
67
+ )
68
+ }
69
+
70
+ if (updated !== podfile) {
71
+ fs.writeFileSync(podfilePath, updated)
72
+ }
73
+ return config
74
+ },
75
+ ])
76
+ }
package/pod-install.sh ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ # ensure it doesnt complain
4
+ # we moved this out of the repo
5
+ # rm -r ../../starters/next-expo-solito/node_modules/react-native-gesture-handler
6
+
7
+ npx pod-install
@@ -0,0 +1,70 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <style>
4
+ rect {
5
+ fill: #444;
6
+ }
7
+ @media (prefers-color-scheme: dark) {
8
+ rect {
9
+ fill: #777;
10
+ }
11
+ }
12
+ </style>
13
+
14
+ <g id="favicon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
15
+ <g id="tamagui-icon-copy" transform="translate(16.000000, 16.000000) scale(-1, 1) translate(-16.000000, -16.000000) translate(1.000000, 2.000000)" fill="#141414">
16
+ <g id="guy">
17
+ <rect x="10" y="0" width="2" height="2"></rect>
18
+ <rect x="12" y="0" width="2" height="2"></rect>
19
+ <rect x="14" y="0" width="2" height="2"></rect>
20
+ <rect x="16" y="0" width="2" height="2"></rect>
21
+ <rect x="18" y="0" width="2" height="2"></rect>
22
+ <rect x="20" y="0" width="2" height="2"></rect>
23
+ <rect x="22" y="2" width="2" height="2"></rect>
24
+ <rect x="24" y="4" width="2" height="2"></rect>
25
+ <rect x="26" y="6" width="2" height="2"></rect>
26
+ <rect x="26" y="8" width="2" height="2"></rect>
27
+ <rect x="26" y="10" width="2" height="2"></rect>
28
+ <rect x="26" y="12" width="2" height="2"></rect>
29
+ <rect x="28" y="14" width="2" height="2"></rect>
30
+ <rect x="28" y="16" width="2" height="2"></rect>
31
+ <rect x="28" y="18" width="2" height="2"></rect>
32
+ <rect x="26" y="20" width="2" height="2"></rect>
33
+ <rect x="24" y="22" width="2" height="2"></rect>
34
+ <rect x="22" y="24" width="2" height="2"></rect>
35
+ <rect x="20" y="26" width="2" height="2"></rect>
36
+ <rect x="18" y="26" width="2" height="2"></rect>
37
+ <rect x="16" y="24" width="2" height="2"></rect>
38
+ <rect x="14" y="24" width="2" height="2"></rect>
39
+ <rect x="14" y="26" width="2" height="2"></rect>
40
+ <rect x="12" y="26" width="2" height="2"></rect>
41
+ <rect x="10" y="24" width="2" height="2"></rect>
42
+ <rect x="10" y="22" width="2" height="2"></rect>
43
+ <rect x="8" y="20" width="2" height="2"></rect>
44
+ <rect x="6" y="16" width="2" height="2"></rect>
45
+ <rect x="6" y="18" width="2" height="2"></rect>
46
+ <rect x="6" y="14" width="2" height="2"></rect>
47
+ <rect x="4" y="12" width="2" height="2"></rect>
48
+ <rect x="2" y="12" width="2" height="2"></rect>
49
+ <rect x="0" y="10" width="2" height="2"></rect>
50
+ <rect x="2" y="8" width="2" height="2"></rect>
51
+ <rect x="4" y="8" width="2" height="2"></rect>
52
+ <rect x="6" y="8" width="2" height="2"></rect>
53
+ <rect x="0" y="6" width="2" height="2"></rect>
54
+ <rect x="0" y="8" width="2" height="2"></rect>
55
+ <rect x="2" y="4" width="2" height="2"></rect>
56
+ <rect x="2" y="4" width="2" height="2"></rect>
57
+ <rect x="4" y="4" width="2" height="2"></rect>
58
+ <rect x="8" y="2" width="2" height="2"></rect>
59
+ <rect x="10" y="4" width="2" height="2"></rect>
60
+ <rect x="16" y="6" width="2" height="2"></rect>
61
+ <rect x="16" y="14" width="2" height="2"></rect>
62
+ <rect x="16" y="16" width="2" height="2"></rect>
63
+ <rect x="18" y="18" width="2" height="2"></rect>
64
+ <rect x="20" y="16" width="2" height="2"></rect>
65
+ <rect x="20" y="14" width="2" height="2"></rect>
66
+ <rect x="6" y="4" width="2" height="2"></rect>
67
+ </g>
68
+ </g>
69
+ </g>
70
+ </svg>
@@ -0,0 +1,15 @@
1
+ @font-face {
2
+ font-family: 'Inter';
3
+ src: url('Medium.woff2') format('woff2');
4
+ font-weight: 400;
5
+ font-style: normal;
6
+ font-display: swap;
7
+ }
8
+
9
+ @font-face {
10
+ font-family: 'Inter';
11
+ src: url('ExtraBold.woff2') format('woff2');
12
+ font-weight: 700;
13
+ font-style: normal;
14
+ font-display: swap;
15
+ }
Binary file
@@ -0,0 +1,68 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="424px" height="394px" viewBox="0 0 424 394" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
4
+ <g transform="translate(-156.000000, -164.000000)">
5
+ <g transform="translate(155.000000, 164.000000)">
6
+ <g transform="translate(22.500000, 30.000000)" opacity="0.267275856">
7
+ <g>
8
+ <path d="M289.285714,0 L289.285714,28.75 L351,28.75 L350.999,57.5 L405,57.5 L405,143.75 L350.999,143.75 L351,172.5 L289.285714,172.5 L289.285714,287.5 L260.357,287.5 L260.357143,345 L57.8571429,345 L57.857,287.5 L0,287.5 L0,57.5 L57.857,57.5 L57.8571429,0 L289.285714,0 Z"></path>
9
+ </g>
10
+ </g>
11
+ <g transform="translate(212.500000, 197.000000) scale(-1, 1) translate(-212.500000, -197.000000) translate(0.500000, 0.000000)" fill="#000">
12
+ <g>
13
+ <rect x="144" y="0" width="20" height="20"></rect>
14
+ <rect x="172.8" y="0" width="20" height="20"></rect>
15
+ <rect x="201.6" y="0" width="20" height="20"></rect>
16
+ <rect x="230.4" y="0" width="20" height="20"></rect>
17
+ <rect x="259.2" y="0" width="20" height="20"></rect>
18
+ <rect x="288" y="0" width="20" height="20"></rect>
19
+ <rect x="316.8" y="28.7142857" width="20" height="20"></rect>
20
+ <rect x="345.6" y="57.4285714" width="20" height="20"></rect>
21
+ <rect x="374.4" y="86.1428571" width="20" height="20"></rect>
22
+ <rect x="374.4" y="114.857143" width="20" height="20"></rect>
23
+ <rect x="374.4" y="143.571429" width="20" height="20"></rect>
24
+ <rect x="374.4" y="172.285714" width="20" height="20"></rect>
25
+ <rect x="403.2" y="201" width="20" height="20"></rect>
26
+ <rect x="403.2" y="229.714286" width="20" height="20"></rect>
27
+ <rect x="403.2" y="258.428571" width="20" height="20"></rect>
28
+ <rect x="374.4" y="287.142857" width="20" height="20"></rect>
29
+ <rect x="345.6" y="315.857143" width="20" height="20"></rect>
30
+ <rect x="316.8" y="344.571429" width="20" height="20"></rect>
31
+ <rect x="288" y="373.285714" width="20" height="20"></rect>
32
+ <rect x="259.2" y="373.285714" width="20" height="20"></rect>
33
+ <rect x="230.4" y="344.571429" width="20" height="20"></rect>
34
+ <rect x="201.6" y="344.571429" width="20" height="20"></rect>
35
+ <rect x="201.6" y="373.285714" width="20" height="20"></rect>
36
+ <rect x="172.8" y="373.285714" width="20" height="20"></rect>
37
+ <rect x="144" y="344.571429" width="20" height="20"></rect>
38
+ <rect x="144" y="315.857143" width="20" height="20"></rect>
39
+ <rect x="115.2" y="287.142857" width="20" height="20"></rect>
40
+ <rect x="86.4" y="229.714286" width="20" height="20"></rect>
41
+ <rect x="86.4" y="258.428571" width="20" height="20"></rect>
42
+ <rect x="86.4" y="201" width="20" height="20"></rect>
43
+ <rect x="57.6" y="172.285714" width="20" height="20"></rect>
44
+ <rect x="28.8" y="172.285714" width="20" height="20"></rect>
45
+ <rect x="0" y="143.571429" width="20" height="20"></rect>
46
+ <rect x="28.8" y="114.857143" width="20" height="20"></rect>
47
+ <rect x="57.6" y="114.857143" width="20" height="20"></rect>
48
+ <rect x="86.4" y="114.857143" width="20" height="20"></rect>
49
+ <rect x="0" y="86.1428571" width="20" height="20"></rect>
50
+ <rect x="0" y="114.857143" width="20" height="20"></rect>
51
+ <rect x="28.8" y="57.4285714" width="20" height="20"></rect>
52
+ <rect x="28.8" y="57.4285714" width="20" height="20"></rect>
53
+ <rect x="57.6" y="57.4285714" width="20" height="20"></rect>
54
+ <rect x="115.2" y="28.7142857" width="20" height="20"></rect>
55
+ <rect x="144" y="57.4285714" width="20" height="20"></rect>
56
+ <rect x="230.4" y="86.1428571" width="20" height="20"></rect>
57
+ <rect x="230.4" y="201" width="20" height="20"></rect>
58
+ <rect x="230.4" y="229.714286" width="20" height="20"></rect>
59
+ <rect x="259.2" y="258.428571" width="20" height="20"></rect>
60
+ <rect x="288" y="229.714286" width="20" height="20"></rect>
61
+ <rect x="288" y="201" width="20" height="20"></rect>
62
+ <rect x="86.4" y="57.4285714" width="20" height="20"></rect>
63
+ </g>
64
+ </g>
65
+ </g>
66
+ </g>
67
+ </g>
68
+ </svg>
package/run-detox.sh ADDED
@@ -0,0 +1,230 @@
1
+ #!/bin/bash
2
+ #
3
+ # run-detox.sh - Complete Detox E2E test runner
4
+ #
5
+ # Usage:
6
+ # bun run detox:run:ios # run all iOS tests
7
+ # bun run detox:run:ios "Sheet" # run tests matching "Sheet"
8
+ # bun run detox:run:android # run all Android tests
9
+ # bun run detox:run:android "Select" # run tests matching "Select"
10
+ #
11
+ # This script handles the full workflow:
12
+ # 1. Checks if pods need installing (iOS only)
13
+ # 2. Detects if app needs rebuilding (compares sources vs binary)
14
+ # 3. Builds if needed
15
+ # 4. Starts Metro if not running
16
+ # 5. Runs Detox tests
17
+ # 6. Cleans up Metro if we started it
18
+ #
19
+ # Environment variables:
20
+ # FORCE_BUILD=1 - Force rebuild even if app exists
21
+ # SKIP_BUILD=1 - Skip build check entirely
22
+ # SKIP_METRO=1 - Don't start Metro (assume it's running)
23
+ # DETOX_DEVICE=name - iOS simulator device type (default: iPhone 15)
24
+ #
25
+
26
+ set -e
27
+
28
+ PLATFORM="${1:-ios}" # ios or android
29
+
30
+ # --- Prerequisites check ---
31
+ check_prerequisites() {
32
+ local missing=false
33
+
34
+ if ! command -v detox &> /dev/null; then
35
+ echo "detox-cli not found. Install with: npm install -g detox-cli"
36
+ missing=true
37
+ fi
38
+
39
+ if [ "$PLATFORM" = "ios" ] && ! command -v applesimutils &> /dev/null; then
40
+ echo "applesimutils not found. Install with: brew tap wix/brew && brew install applesimutils"
41
+ missing=true
42
+ fi
43
+
44
+ if [ "$missing" = true ]; then
45
+ echo ""
46
+ echo "Install missing dependencies and try again."
47
+ exit 1
48
+ fi
49
+
50
+ # Detox framework cache (needed after Xcode updates)
51
+ if [ "$PLATFORM" = "ios" ] && [ ! -d "$HOME/Library/Detox/ios/framework" ]; then
52
+ echo "Detox framework cache not found. Building..."
53
+ npx detox clean-framework-cache && npx detox build-framework-cache
54
+ echo ""
55
+ fi
56
+
57
+ # iOS directory (expo prebuild)
58
+ if [ "$PLATFORM" = "ios" ] && [ ! -d "ios" ]; then
59
+ echo "No ios/ directory found. Running expo prebuild..."
60
+ npx expo prebuild --platform ios
61
+ echo ""
62
+ fi
63
+ }
64
+ TEST_FILTER="${2:-}" # optional test name filter
65
+
66
+ CONFIG=""
67
+ APP_PATH=""
68
+ BUILD_CMD=""
69
+
70
+ case "$PLATFORM" in
71
+ ios)
72
+ CONFIG="ios.sim.debug"
73
+ APP_PATH="ios/build/Build/Products/Debug-iphonesimulator/guikitchensink.app"
74
+ BUILD_CMD="bun run detox:build:ios"
75
+ ;;
76
+ android)
77
+ CONFIG="android.emu.debug"
78
+ APP_PATH="android/app/build/outputs/apk/debug/app-debug.apk"
79
+ BUILD_CMD="bun run detox:build:android"
80
+ ;;
81
+ *)
82
+ echo "Unknown platform: $PLATFORM"
83
+ echo "Usage: $0 [ios|android] [test-filter]"
84
+ exit 1
85
+ ;;
86
+ esac
87
+
88
+ METRO_PID=""
89
+ STARTED_METRO=false
90
+
91
+ cleanup() {
92
+ if [ "$STARTED_METRO" = true ] && [ -n "$METRO_PID" ]; then
93
+ echo ""
94
+ echo "=== Cleanup: Stopping Metro (PID: $METRO_PID) ==="
95
+ kill "$METRO_PID" 2>/dev/null || true
96
+ # also kill child processes
97
+ pkill -P "$METRO_PID" 2>/dev/null || true
98
+ fi
99
+ }
100
+ trap cleanup EXIT
101
+
102
+ is_metro_running() {
103
+ curl -s http://localhost:8081/status > /dev/null 2>&1
104
+ }
105
+
106
+ DID_BUILD=false
107
+
108
+ needs_rebuild() {
109
+ # if app doesn't exist, needs build
110
+ if [ ! -e "$APP_PATH" ]; then
111
+ echo "App not found at $APP_PATH"
112
+ return 0
113
+ fi
114
+
115
+ # if FORCE_BUILD is set, needs build
116
+ if [ "$FORCE_BUILD" = "1" ]; then
117
+ echo "FORCE_BUILD=1 set"
118
+ return 0
119
+ fi
120
+
121
+ # check if Podfile.lock is newer than app (pods changed)
122
+ if [ "$PLATFORM" = "ios" ]; then
123
+ if [ "ios/Podfile.lock" -nt "$APP_PATH" ]; then
124
+ echo "Podfile.lock is newer than app"
125
+ return 0
126
+ fi
127
+ fi
128
+
129
+ # check if package.json is newer (deps changed)
130
+ if [ "package.json" -nt "$APP_PATH" ]; then
131
+ echo "package.json is newer than app"
132
+ return 0
133
+ fi
134
+
135
+ return 1
136
+ }
137
+
138
+ echo "========================================"
139
+ echo " Detox Test Runner"
140
+ echo "========================================"
141
+ echo "Platform: $PLATFORM"
142
+ echo "Config: $CONFIG"
143
+ echo "Device: ${DETOX_DEVICE:-iPhone 15}"
144
+ echo "Test filter: ${TEST_FILTER:-<all tests>}"
145
+ echo ""
146
+
147
+ # step 0: check prerequisites
148
+ echo "=== Step 0: Checking prerequisites ==="
149
+ check_prerequisites
150
+ echo ""
151
+
152
+ # step 1: check if build needed
153
+ if [ "$SKIP_BUILD" != "1" ]; then
154
+ echo "=== Step 1: Checking if build needed ==="
155
+ if needs_rebuild; then
156
+ echo "Building app..."
157
+ $BUILD_CMD
158
+ DID_BUILD=true
159
+ else
160
+ echo "App is up to date, skipping build"
161
+ fi
162
+ echo ""
163
+ fi
164
+
165
+ # step 2: start metro if needed
166
+ if [ "$SKIP_METRO" != "1" ]; then
167
+ echo "=== Step 2: Metro bundler ==="
168
+ if is_metro_running; then
169
+ echo "Metro already running on port 8081"
170
+ else
171
+ echo "Starting Metro..."
172
+ bun run start > /tmp/metro-detox.log 2>&1 &
173
+ METRO_PID=$!
174
+ STARTED_METRO=true
175
+
176
+ # wait for metro to be ready (up to 60s)
177
+ echo -n "Waiting for Metro to start"
178
+ for i in {1..60}; do
179
+ if is_metro_running; then
180
+ echo " ready!"
181
+ break
182
+ fi
183
+ echo -n "."
184
+ sleep 1
185
+ done
186
+
187
+ if ! is_metro_running; then
188
+ echo " FAILED"
189
+ echo "Metro failed to start. Check /tmp/metro-detox.log:"
190
+ tail -20 /tmp/metro-detox.log
191
+ exit 1
192
+ fi
193
+ fi
194
+ echo ""
195
+ fi
196
+
197
+ # step 3: run detox tests
198
+ echo "=== Step 3: Running Detox tests ==="
199
+
200
+ # use --reuse only if we didn't build (to reinstall after build)
201
+ if [ "$DID_BUILD" = true ]; then
202
+ echo "Fresh build detected, will reinstall app on simulator"
203
+ DETOX_ARGS="-c $CONFIG --maxWorkers 1"
204
+ else
205
+ DETOX_ARGS="-c $CONFIG --reuse --maxWorkers 1"
206
+ fi
207
+
208
+ # add headless flag if requested
209
+ if [ "$HEADLESS" = "1" ]; then
210
+ DETOX_ARGS="$DETOX_ARGS --headless"
211
+ fi
212
+
213
+ if [ -n "$TEST_FILTER" ]; then
214
+ DETOX_ARGS="$DETOX_ARGS -t \"$TEST_FILTER\""
215
+ fi
216
+
217
+ # run with eval to handle quoted test filter
218
+ eval "npx detox test $DETOX_ARGS"
219
+ EXIT_CODE=$?
220
+
221
+ echo ""
222
+ echo "========================================"
223
+ if [ $EXIT_CODE -eq 0 ]; then
224
+ echo " Tests passed!"
225
+ else
226
+ echo " Tests failed (exit code: $EXIT_CODE)"
227
+ fi
228
+ echo "========================================"
229
+
230
+ exit $EXIT_CODE
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ if [ -z "$SKIP_NATIVE_TESTS" ]; then
3
+ bun run test:native
4
+ fi
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env bun
2
+ import { spawn, type Subprocess } from 'bun'
3
+
4
+ const DRIVERS = ['css', 'native', 'reanimated', 'motion'] as const
5
+ const PORT = process.env.PORT || '9000'
6
+ const COLORS = {
7
+ css: '\x1b[36m', // cyan
8
+ native: '\x1b[33m', // yellow
9
+ reanimated: '\x1b[35m', // magenta
10
+ motion: '\x1b[32m', // green
11
+ reset: '\x1b[0m',
12
+ red: '\x1b[31m',
13
+ green: '\x1b[32m',
14
+ dim: '\x1b[2m',
15
+ }
16
+
17
+ async function waitForServer(port: string, timeoutMs = 120_000) {
18
+ const start = Date.now()
19
+ const url = `http://localhost:${port}`
20
+ while (Date.now() - start < timeoutMs) {
21
+ try {
22
+ const res = await fetch(url)
23
+ if (res.ok) return
24
+ } catch {}
25
+ await new Promise((r) => setTimeout(r, 500))
26
+ }
27
+ throw new Error(`Server on port ${port} did not start within ${timeoutMs}ms`)
28
+ }
29
+
30
+ function startServer(port: string): Subprocess {
31
+ return spawn({
32
+ cmd: ['bun', 'run', 'start:web'],
33
+ cwd: import.meta.dir,
34
+ env: {
35
+ ...process.env,
36
+ PORT: port,
37
+ NODE_ENV: 'development',
38
+ DISABLE_EXTRACTION: 'true',
39
+ },
40
+ stdout: 'ignore',
41
+ stderr: 'ignore',
42
+ })
43
+ }
44
+
45
+ async function runPlaywright(args: string[], env?: Record<string, string>) {
46
+ const proc = spawn({
47
+ cmd: [
48
+ 'node',
49
+ '-r',
50
+ 'esbuild-register',
51
+ '../../node_modules/.bin/playwright',
52
+ 'test',
53
+ ...args,
54
+ ],
55
+ cwd: import.meta.dir,
56
+ env: {
57
+ ...process.env,
58
+ NODE_ENV: 'test',
59
+ PORT,
60
+ REUSE_SERVER: 'true',
61
+ ...env,
62
+ },
63
+ stdout: 'inherit',
64
+ stderr: 'inherit',
65
+ })
66
+ return proc.exited
67
+ }
68
+
69
+ async function runDriver(
70
+ driver: string
71
+ ): Promise<{ driver: string; code: number; output: string[] }> {
72
+ const output: string[] = []
73
+ const color = COLORS[driver as keyof typeof COLORS] || ''
74
+
75
+ const proc = spawn({
76
+ cmd: [
77
+ 'node',
78
+ '-r',
79
+ 'esbuild-register',
80
+ '../../node_modules/.bin/playwright',
81
+ 'test',
82
+ `--project=animated-${driver}`,
83
+ ],
84
+ cwd: import.meta.dir,
85
+ env: {
86
+ ...process.env,
87
+ NODE_ENV: 'test',
88
+ PORT,
89
+ REUSE_SERVER: 'true',
90
+ HANZO_GUI_TEST_ANIMATION_DRIVER: driver,
91
+ },
92
+ stdout: 'pipe',
93
+ stderr: 'pipe',
94
+ })
95
+
96
+ // stream stdout with prefix
97
+ const streamWithPrefix = async (
98
+ stream: ReadableStream<Uint8Array>,
99
+ isError = false
100
+ ) => {
101
+ const reader = stream.getReader()
102
+ const decoder = new TextDecoder()
103
+ let buffer = ''
104
+
105
+ while (true) {
106
+ const { done, value } = await reader.read()
107
+ if (done) break
108
+
109
+ buffer += decoder.decode(value, { stream: true })
110
+ const lines = buffer.split('\n')
111
+ buffer = lines.pop() || ''
112
+
113
+ for (const line of lines) {
114
+ if (line.trim()) {
115
+ const prefixed = isError
116
+ ? `${color}[${driver}]${COLORS.reset} ${COLORS.red}${line}${COLORS.reset}`
117
+ : `${color}[${driver}]${COLORS.reset} ${line}`
118
+ console.log(prefixed)
119
+ output.push(line)
120
+ }
121
+ }
122
+ }
123
+
124
+ // flush remaining buffer
125
+ if (buffer.trim()) {
126
+ output.push(buffer)
127
+ console.log(`${color}[${driver}]${COLORS.reset} ${buffer}`)
128
+ }
129
+ }
130
+
131
+ const stdoutDone = streamWithPrefix(proc.stdout)
132
+ const stderrDone = streamWithPrefix(proc.stderr, true)
133
+
134
+ const [code] = await Promise.all([proc.exited, stdoutDone, stderrDone])
135
+ return { driver, code, output }
136
+ }
137
+
138
+ async function main() {
139
+ // start a single shared webpack dev server
140
+ console.log(
141
+ `${COLORS.dim}Starting shared webpack dev server on port ${PORT}...${COLORS.reset}`
142
+ )
143
+ const server = startServer(PORT)
144
+
145
+ try {
146
+ await waitForServer(PORT)
147
+ console.log(`${COLORS.green}Server ready on port ${PORT}${COLORS.reset}\n`)
148
+
149
+ console.log(`${COLORS.dim}Running default + webkit tests...${COLORS.reset}\n`)
150
+
151
+ // run default and webkit first, reusing the shared server
152
+ const defaultCode = await runPlaywright(['--project=default', '--project=webkit'])
153
+ if (defaultCode !== 0) {
154
+ console.error(`\n${COLORS.red}Default/webkit tests failed${COLORS.reset}`)
155
+ process.exit(1)
156
+ }
157
+
158
+ console.log(
159
+ `\n${COLORS.dim}Running animated tests in parallel (${DRIVERS.join(', ')})...${COLORS.reset}\n`
160
+ )
161
+
162
+ // run all animated driver tests in parallel, all sharing the same server
163
+ const results = await Promise.all(DRIVERS.map(runDriver))
164
+
165
+ // summary
166
+ console.log(`\n${COLORS.dim}${'─'.repeat(60)}${COLORS.reset}`)
167
+ console.log('Summary:')
168
+
169
+ let failed = false
170
+ for (const { driver, code } of results) {
171
+ const color = COLORS[driver as keyof typeof COLORS] || ''
172
+ const status =
173
+ code === 0
174
+ ? `${COLORS.green}✓ passed${COLORS.reset}`
175
+ : `${COLORS.red}✗ failed (exit ${code})${COLORS.reset}`
176
+ console.log(` ${color}${driver}${COLORS.reset}: ${status}`)
177
+ if (code !== 0) failed = true
178
+ }
179
+
180
+ if (failed) {
181
+ console.error(`\n${COLORS.red}Some tests failed${COLORS.reset}`)
182
+ process.exit(1)
183
+ }
184
+
185
+ console.log(`\n${COLORS.green}All tests passed${COLORS.reset}`)
186
+ } finally {
187
+ // always clean up the server
188
+ server.kill()
189
+ }
190
+ }
191
+
192
+ main().catch((err) => {
193
+ console.error(err)
194
+ process.exit(1)
195
+ })