@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.
- package/.detoxrc.js +130 -0
- package/.env.production +2 -0
- package/.maestro/config.yaml +4 -0
- package/.maestro/flows/shorthand-variables.yaml +23 -0
- package/.watchmanconfig +1 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/app.json +43 -0
- package/assets/adaptive-icon.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/icon.png +0 -0
- package/assets/splash.png +0 -0
- package/babel.config.js +25 -0
- package/e2e/CompilerExtraction.test.ts +147 -0
- package/e2e/GroupPressNative.test.ts +167 -0
- package/e2e/MediaQueryGtMd.test.ts +71 -0
- package/e2e/NativePortal.test.ts +113 -0
- package/e2e/PointerEvents.test.ts +116 -0
- package/e2e/PressStyleNative.noRngh.test.ts +191 -0
- package/e2e/PressStyleNative.test.ts +231 -0
- package/e2e/SafeArea.test.ts +57 -0
- package/e2e/SelectAndroidOnPress.test.ts +181 -0
- package/e2e/SelectRemount.test.ts +137 -0
- package/e2e/SheetDragResist.test.ts +370 -0
- package/e2e/SheetKeyboardDrag.test.ts +249 -0
- package/e2e/SheetScrollableDrag.test.ts +560 -0
- package/e2e/ShorthandVariables.test.ts +53 -0
- package/e2e/ThemeChangeBasic.test.ts +123 -0
- package/e2e/ThemeMutation.test.ts +80 -0
- package/e2e/check-rngh-status.test.ts +31 -0
- package/e2e/jest.config.js +19 -0
- package/e2e/utils/colors.ts +75 -0
- package/e2e/utils/navigation.ts +53 -0
- package/eas.json +22 -0
- package/flows/AlertDialog.yaml +17 -0
- package/flows/OpenApp.yaml +25 -0
- package/flows/Select.yaml +13 -0
- package/flows/Sheet.yaml +12 -0
- package/flows/Tabs.yaml +13 -0
- package/flows/Toast.yaml +14 -0
- package/flows/WarmUp.yaml +24 -0
- package/index.html +21 -0
- package/index.js +17 -0
- package/metro.config.js +64 -0
- package/next-router-shim.ts +9 -0
- package/package.json +118 -0
- package/plans/toast-2.md +471 -0
- package/playwright.config.ts +71 -0
- package/plugins/expo-modules-core-swift6.js +76 -0
- package/pod-install.sh +7 -0
- package/public/favicon.svg +70 -0
- package/public/fonts/inter.css +15 -0
- package/public/fonts/noto-cn.otf +0 -0
- package/public/gui-icon.svg +68 -0
- package/run-detox.sh +230 -0
- package/run-native-tests.sh +4 -0
- package/run-tests-parallel.ts +195 -0
- package/screenshots/Screenshotter.test.tsx +48 -0
- package/src/AnimationDemos.tsx +131 -0
- package/src/App.native.tsx +121 -0
- package/src/App.tsx +121 -0
- package/src/Navigation.tsx +98 -0
- package/src/Sandbox.tsx +87 -0
- package/src/TestDynamicEval.tsx +33 -0
- package/src/TestNativeSheet.tsx +100 -0
- package/src/components/TimedRender.tsx +18 -0
- package/src/constants/test-ids.ts +52 -0
- package/src/features/demos/demo-screen.tsx +72 -0
- package/src/features/home/ColorSchemeListItem.tsx +41 -0
- package/src/features/home/TestBuildAButton.tsx +102 -0
- package/src/features/home/TestSeparator.tsx +0 -0
- package/src/features/home/screen.tsx +285 -0
- package/src/features/testcases/screen.tsx +59 -0
- package/src/features/testcases/test-screen.tsx +50 -0
- package/src/generatedV5Theme.ts +112 -0
- package/src/gui.config.ts +411 -0
- package/src/guy.png +0 -0
- package/src/index.tsx +6 -0
- package/src/provider/index.tsx +18 -0
- package/src/test-gui-stack.tsx +11 -0
- package/src/test.tsx +3 -0
- package/src/useKitchenSinkTheme.tsx +15 -0
- package/src/usecases/ActionsSheetComparison.tsx +194 -0
- package/src/usecases/AnimatePresenceEnterExitCase.tsx +255 -0
- package/src/usecases/AnimatePresenceExitTest.tsx +69 -0
- package/src/usecases/AnimatedByProp.tsx +39 -0
- package/src/usecases/AnimationComprehensiveCase.tsx +2515 -0
- package/src/usecases/AnimationValueLoggingCase.tsx +526 -0
- package/src/usecases/AnimationsWithMediaQueriesCase.tsx +110 -0
- package/src/usecases/Benchmark.tsx +148 -0
- package/src/usecases/BenchmarkSelect.tsx +34 -0
- package/src/usecases/ButtonCircular.tsx +3 -0
- package/src/usecases/ButtonCustom.tsx +33 -0
- package/src/usecases/ButtonIconColor.tsx +18 -0
- package/src/usecases/ButtonInverse.tsx +30 -0
- package/src/usecases/ButtonUnstyled.tsx +31 -0
- package/src/usecases/CheckboxDisabledOnPress.tsx +62 -0
- package/src/usecases/ClickDuringEnterCase.tsx +59 -0
- package/src/usecases/CodeExamplesInput.tsx +9 -0
- package/src/usecases/ColorTokenFallback.tsx +52 -0
- package/src/usecases/CompilerExtraction.tsx +380 -0
- package/src/usecases/ComplexVariants.tsx +164 -0
- package/src/usecases/CrashAdaptSheet.tsx +98 -0
- package/src/usecases/CustomStyledAnimatedPopover.tsx +42 -0
- package/src/usecases/CustomStyledAnimatedTooltip.tsx +72 -0
- package/src/usecases/DOMNodeAPIs.tsx +154 -0
- package/src/usecases/DialogFocusScopeCase.tsx +277 -0
- package/src/usecases/DialogFocusScopeDebug.tsx +85 -0
- package/src/usecases/DialogNestedCase.tsx +121 -0
- package/src/usecases/DialogOpenControlled.tsx +49 -0
- package/src/usecases/DialogPointerEventsCase.tsx +58 -0
- package/src/usecases/DialogScopedCase.tsx +106 -0
- package/src/usecases/DialogSheetAdaptCase.tsx +178 -0
- package/src/usecases/DialogSheetAdaptResizeCase.tsx +98 -0
- package/src/usecases/DismissLayerStackingCase.tsx +223 -0
- package/src/usecases/DriverDisableAnimationPropsCase.tsx +44 -0
- package/src/usecases/Example.tsx +10 -0
- package/src/usecases/ExitCompletionCase.tsx +713 -0
- package/src/usecases/FocusVisibleButton.tsx +14 -0
- package/src/usecases/FocusVisibleButtonPointer.tsx +13 -0
- package/src/usecases/FocusVisibleButtonWithFocusStyle.tsx +16 -0
- package/src/usecases/FocusWithinCase.tsx +55 -0
- package/src/usecases/FontTokensInVariants.tsx +14 -0
- package/src/usecases/FormButtonTypeCase.tsx +34 -0
- package/src/usecases/GlobalScopedTriggerIsolationCase.tsx +178 -0
- package/src/usecases/GroupHoverMobile.tsx +39 -0
- package/src/usecases/GroupPressInVariant.tsx +92 -0
- package/src/usecases/GroupPressNative.tsx +200 -0
- package/src/usecases/GroupProp.tsx +96 -0
- package/src/usecases/GroupPseudoVariantOverride.tsx +56 -0
- package/src/usecases/GroupUseCases.tsx +94 -0
- package/src/usecases/HeightMediaQueryOverrideCase.tsx +183 -0
- package/src/usecases/InputAutoFocusAfterMenuCase.tsx +105 -0
- package/src/usecases/InputAutoFocusStyledCase.tsx +39 -0
- package/src/usecases/KeyboardControllerTest.tsx +146 -0
- package/src/usecases/ListItem.tsx +123 -0
- package/src/usecases/MediaQueriesV5.tsx +137 -0
- package/src/usecases/MediaQueryGtMd.tsx +73 -0
- package/src/usecases/MenuAboveDialogCase.tsx +75 -0
- package/src/usecases/MenuAccessibilityCase.tsx +133 -0
- package/src/usecases/MenuAnimatePositionCase.tsx +41 -0
- package/src/usecases/MenuArrowAnimatePresenceCase.tsx +98 -0
- package/src/usecases/MenuAsChildPositionCase.tsx +24 -0
- package/src/usecases/MenuAutoResizeCase.tsx +57 -0
- package/src/usecases/MenuBottomCase.tsx +55 -0
- package/src/usecases/MenuFocusLeaveCase.tsx +135 -0
- package/src/usecases/MenuHighlightCase.tsx +44 -0
- package/src/usecases/MenuItemFocusCase.tsx +79 -0
- package/src/usecases/MenuItemPseudoOverrideCase.tsx +270 -0
- package/src/usecases/MenuMultiTriggerCase.tsx +47 -0
- package/src/usecases/MenuOverflowCase.tsx +60 -0
- package/src/usecases/MenuSubCase.tsx +223 -0
- package/src/usecases/MenuSubLeftCase.tsx +178 -0
- package/src/usecases/MenuSubNestedPositionCase.tsx +171 -0
- package/src/usecases/MenuSubStyledCase.tsx +145 -0
- package/src/usecases/MenuThemeCase.tsx +50 -0
- package/src/usecases/MenuUnstyledCase.tsx +52 -0
- package/src/usecases/MultiDriverAnimation.tsx +118 -0
- package/src/usecases/NativePortalTest.tsx +179 -0
- package/src/usecases/NewInputBasic.tsx +16 -0
- package/src/usecases/NewInputEvents.tsx +29 -0
- package/src/usecases/NonGuiTextStyledType.tsx +23 -0
- package/src/usecases/OnLayoutCase.tsx +134 -0
- package/src/usecases/OnLayoutScaleCase.tsx +88 -0
- package/src/usecases/OnLayoutStressCase.tsx +353 -0
- package/src/usecases/OpacityModifierCase.tsx +113 -0
- package/src/usecases/OverlayStyled.tsx +66 -0
- package/src/usecases/ParagraphSpanFontInheritance.tsx +53 -0
- package/src/usecases/PlaceholderTextColor.tsx +20 -0
- package/src/usecases/PointerEventsCase.tsx +100 -0
- package/src/usecases/PopoverAndMenuMultiTriggerCase.tsx +138 -0
- package/src/usecases/PopoverCase.tsx +222 -0
- package/src/usecases/PopoverContentStyledPlusAnimations.tsx +44 -0
- package/src/usecases/PopoverFocusScopeCase.tsx +171 -0
- package/src/usecases/PopoverHoverableCase.tsx +167 -0
- package/src/usecases/PopoverHoverableDisableClickCase.tsx +118 -0
- package/src/usecases/PopoverHoverableRapidCase.tsx +103 -0
- package/src/usecases/PopoverHoverableScopedCase.tsx +135 -0
- package/src/usecases/PopoverScopedCase.tsx +76 -0
- package/src/usecases/PopoverTriggerIsolationCase.tsx +80 -0
- package/src/usecases/PressStyleNative.tsx +143 -0
- package/src/usecases/PseudoStyleMerge.tsx +25 -0
- package/src/usecases/PseudoTransitionCase.tsx +174 -0
- package/src/usecases/RawAnimatedValueCase.tsx +231 -0
- package/src/usecases/RemoveScrollCase.tsx +66 -0
- package/src/usecases/RenderPropCase.tsx +263 -0
- package/src/usecases/SafeAreaCase.tsx +236 -0
- package/src/usecases/ScrollViewRefCase.tsx +88 -0
- package/src/usecases/SecondPage.tsx +5 -0
- package/src/usecases/SelectAndroidOnPress.tsx +129 -0
- package/src/usecases/SelectFocusScopeCase.tsx +270 -0
- package/src/usecases/SelectRemount.tsx +136 -0
- package/src/usecases/Shadows.tsx +5 -0
- package/src/usecases/SheetAnimationCase.tsx +155 -0
- package/src/usecases/SheetDragCase.tsx +183 -0
- package/src/usecases/SheetDragResistCase.tsx +433 -0
- package/src/usecases/SheetDragResistCase.web.tsx +359 -0
- package/src/usecases/SheetKeyboardDragCase.tsx +328 -0
- package/src/usecases/SheetKeyboardFitContentCase.tsx +165 -0
- package/src/usecases/SheetOnAnimationCompleteCase.tsx +54 -0
- package/src/usecases/SheetScrollLockCase.tsx +166 -0
- package/src/usecases/SheetScrollableDrag.tsx +249 -0
- package/src/usecases/SheetSnapPointsFitCase.tsx +393 -0
- package/src/usecases/ShorthandVariables.tsx +49 -0
- package/src/usecases/SlowThemeReRender.tsx +48 -0
- package/src/usecases/SpinnerCustomColors.tsx +34 -0
- package/src/usecases/StackZIndex.tsx +82 -0
- package/src/usecases/StressPage.tsx +301 -0
- package/src/usecases/StylePlatform.tsx +30 -0
- package/src/usecases/StyleProp.tsx +29 -0
- package/src/usecases/StyledAnchor.tsx +27 -0
- package/src/usecases/StyledButtonAnimationAuto.tsx +99 -0
- package/src/usecases/StyledButtonTheme.tsx +63 -0
- package/src/usecases/StyledButtonVariantPseudo.tsx +25 -0
- package/src/usecases/StyledButtonVariantPseudoMerge.tsx +77 -0
- package/src/usecases/StyledCheckboxTheme.tsx +23 -0
- package/src/usecases/StyledContextColor.tsx +246 -0
- package/src/usecases/StyledContextTokens.tsx +147 -0
- package/src/usecases/StyledHOCNamed.tsx +20 -0
- package/src/usecases/StyledHtmlCase.tsx +144 -0
- package/src/usecases/StyledIconColor.tsx +19 -0
- package/src/usecases/StyledInputFocusStyle.tsx +21 -0
- package/src/usecases/StyledInputOnFocus.tsx +30 -0
- package/src/usecases/StyledMediaQueryMerge.tsx +95 -0
- package/src/usecases/StyledOverridePsuedo.tsx +26 -0
- package/src/usecases/StyledRNW.tsx +61 -0
- package/src/usecases/StyledStyleableInputOnFocus.tsx +34 -0
- package/src/usecases/StyledStyleableInputVariant.tsx +48 -0
- package/src/usecases/StyledStyledStyleableInputOnFocus.tsx +36 -0
- package/src/usecases/StyledVariantTextColor.tsx +25 -0
- package/src/usecases/StyledViewOnFocus.tsx +32 -0
- package/src/usecases/TabHoverAnimationCase.tsx +212 -0
- package/src/usecases/TextNestedInheritance.tsx +80 -0
- package/src/usecases/ThemeChange.tsx +100 -0
- package/src/usecases/ThemeChangeBasic.tsx +52 -0
- package/src/usecases/ThemeComponentResolution.tsx +119 -0
- package/src/usecases/ThemeConditionalName.tsx +31 -0
- package/src/usecases/ThemeMediaAnimationCase.tsx +39 -0
- package/src/usecases/ThemeMutation.tsx +86 -0
- package/src/usecases/ThemeNested.tsx +103 -0
- package/src/usecases/ThemeReset.tsx +62 -0
- package/src/usecases/ThemeShallowCase.tsx +83 -0
- package/src/usecases/ToastCase.tsx +46 -0
- package/src/usecases/ToggleGroupActiveProps.tsx +40 -0
- package/src/usecases/ToggleGroupXGroupCase.tsx +104 -0
- package/src/usecases/TooltipAnimationCase.tsx +99 -0
- package/src/usecases/TooltipCase.tsx +32 -0
- package/src/usecases/TooltipGlobalPatternCase.tsx +83 -0
- package/src/usecases/TooltipGroupCase.tsx +102 -0
- package/src/usecases/TooltipMultiTriggerCase.tsx +88 -0
- package/src/usecases/TooltipPositionJumpCase.tsx +91 -0
- package/src/usecases/TooltipTriggerInlineCase.tsx +60 -0
- package/src/usecases/TransformMediaQueryMerge.tsx +98 -0
- package/src/usecases/UseCases.tsx +409 -0
- package/src/usecases/UseTheme.tsx +41 -0
- package/src/usecases/V5ThemeBuilderOutput.tsx +231 -0
- package/src/usecases/VariantFontFamily.tsx +25 -0
- package/src/usecases/VariantsOrder.tsx +117 -0
- package/src/usecases/ZIndex.tsx +155 -0
- package/src/usecases/helpers.tsx +44 -0
- package/src/usecases/index.native.ts +122 -0
- package/src/usecases/index.ts +3 -0
- package/src/usecases/index.web.ts +177 -0
- package/tests/AnimatePresenceEnterExit.animated.test.tsx +176 -0
- package/tests/AnimatedByProp.animated.test.tsx +138 -0
- package/tests/AnimationBehavior.animated.test.tsx +543 -0
- package/tests/AnimationTiming.animated.test.tsx +195 -0
- package/tests/AnimationsWithMediaQueries.animated.test.tsx +154 -0
- package/tests/BuildAButton.test.tsx +87 -0
- package/tests/ButtonCircular.test.tsx +17 -0
- package/tests/ButtonCustom.test.tsx +17 -0
- package/tests/ButtonIconColor.test.tsx +23 -0
- package/tests/ButtonUnstyled.test.tsx +56 -0
- package/tests/ClickDuringEnter.animated.test.tsx +174 -0
- package/tests/ColorTokenFallback.test.tsx +45 -0
- package/tests/DOMNodeAPIs.test.tsx +161 -0
- package/tests/DialogFocusScope.animated.test.tsx +309 -0
- package/tests/DialogNested.test.tsx +128 -0
- package/tests/DialogOpenControlled.test.tsx +42 -0
- package/tests/DialogPointerEvents.animated.test.tsx +108 -0
- package/tests/DialogScoped.test.tsx +137 -0
- package/tests/DialogSheetAdapt.test.tsx +68 -0
- package/tests/DialogSheetAdaptResize.test.tsx +161 -0
- package/tests/DismissLayerStacking.test.tsx +292 -0
- package/tests/DriverDisableAnimationProps.animated.test.tsx +157 -0
- package/tests/ExitCompletion.animated.test.tsx +425 -0
- package/tests/ExitTimingCheck.animated.test.ts +34 -0
- package/tests/FocusVisibleButton.test.tsx +41 -0
- package/tests/FocusVisibleButtonPointerFocus.test.tsx +23 -0
- package/tests/FocusVisibleButtonPointerFocusWithFocusStyle.test.tsx +40 -0
- package/tests/FocusWithinStyle.animated.test.tsx +66 -0
- package/tests/FocusWithinStyle.test.tsx +60 -0
- package/tests/FormButtonType.test.tsx +42 -0
- package/tests/GlobalScopedTriggerIsolation.test.tsx +89 -0
- package/tests/GroupHoverMobile.test.tsx +52 -0
- package/tests/GroupPressInVariant.test.tsx +82 -0
- package/tests/GroupProp.test.tsx +30 -0
- package/tests/GroupPseudoVariantOverride.test.tsx +57 -0
- package/tests/GroupUseCases.test.tsx +111 -0
- package/tests/GuiSiteMotion.test.ts +481 -0
- package/tests/HeightMediaQueryOverride.test.tsx +112 -0
- package/tests/InputAutoFocusAfterMenu.test.tsx +55 -0
- package/tests/InputAutoFocusStyled.test.tsx +22 -0
- package/tests/ListItem.test.tsx +129 -0
- package/tests/MediaQueriesV5.test.tsx +113 -0
- package/tests/MediaQueryGtMd.test.tsx +84 -0
- package/tests/MenuAboveDialog.test.tsx +108 -0
- package/tests/MenuAccessibility.test.tsx +346 -0
- package/tests/MenuAnimatePosition.animated.test.tsx +57 -0
- package/tests/MenuArrowAnimatePresence.animated.test.tsx +71 -0
- package/tests/MenuAsChildPosition.test.tsx +16 -0
- package/tests/MenuAutoResize.test.tsx +54 -0
- package/tests/MenuFocusLeave.test.tsx +181 -0
- package/tests/MenuHighlight.test.tsx +165 -0
- package/tests/MenuHoverKeyboardBugs.test.tsx +252 -0
- package/tests/MenuItemFocus.test.tsx +59 -0
- package/tests/MenuItemPseudoOverride.test.tsx +231 -0
- package/tests/MenuMultiTrigger.test.tsx +101 -0
- package/tests/MenuOverflow.test.tsx +93 -0
- package/tests/MenuStayInFrame.test.tsx +102 -0
- package/tests/MenuSubKeyboardFocus.test.tsx +220 -0
- package/tests/MenuSubLeftSafePolygon.test.tsx +88 -0
- package/tests/MenuSubNestedPosition.test.tsx +48 -0
- package/tests/MenuSubSafePolygon.test.tsx +97 -0
- package/tests/MenuSubStyled.test.tsx +40 -0
- package/tests/MenuTheme.test.tsx +34 -0
- package/tests/MenuUnstyled.test.tsx +56 -0
- package/tests/MultiDriverAnimation.test.tsx +207 -0
- package/tests/NewInputBasic.test.tsx +50 -0
- package/tests/NewInputEvents.test.tsx +55 -0
- package/tests/OnLayout.test.tsx +163 -0
- package/tests/OnLayoutScale.test.tsx +100 -0
- package/tests/OnLayoutStress.test.tsx +304 -0
- package/tests/ParagraphSpanFontInheritance.test.tsx +73 -0
- package/tests/PointerEvents.test.tsx +123 -0
- package/tests/Popover.animated.test.tsx +234 -0
- package/tests/PopoverAndMenuMultiTrigger.test.tsx +184 -0
- package/tests/PopoverAnimatePosition.animated.test.tsx +51 -0
- package/tests/PopoverClickDuringEnter.animated.test.tsx +197 -0
- package/tests/PopoverFocusScope.test.tsx +242 -0
- package/tests/PopoverHoverable.test.tsx +383 -0
- package/tests/PopoverHoverableDisableClick.test.tsx +106 -0
- package/tests/PopoverHoverableRapid.test.tsx +129 -0
- package/tests/PopoverHoverableReposition.test.tsx +111 -0
- package/tests/PopoverHoverableScoped.animated.test.tsx +103 -0
- package/tests/PopoverHoverableStress.test.tsx +169 -0
- package/tests/PopoverInitialPosition.animated.test.tsx +82 -0
- package/tests/PopoverMiddlewareSkipRegression.animated.test.tsx +221 -0
- package/tests/PopoverScoped.test.tsx +128 -0
- package/tests/PopoverScopedPositionGlitch.animated.test.tsx +184 -0
- package/tests/PopoverTriggerIsolation.test.tsx +62 -0
- package/tests/PseudoTransition.animated.test.tsx +319 -0
- package/tests/RawAnimatedValue.test.tsx +147 -0
- package/tests/RemoveScroll.test.tsx +223 -0
- package/tests/RenderProp.test.tsx +293 -0
- package/tests/ScrollViewRef.test.tsx +39 -0
- package/tests/SelectClickHold.test.tsx +147 -0
- package/tests/SelectFocusScope.test.tsx +176 -0
- package/tests/SelectInnerPositioning.test.tsx +82 -0
- package/tests/SelectKeyboardNav.test.tsx +173 -0
- package/tests/SelectPositioning.test.tsx +56 -0
- package/tests/SelectTypeahead.test.tsx +63 -0
- package/tests/Shadows.test.tsx +14 -0
- package/tests/SheetAnimation.animated.test.tsx +413 -0
- package/tests/SheetDrag.animated.test.tsx +223 -0
- package/tests/SheetDragResist.animated.test.tsx +393 -0
- package/tests/SheetOnAnimationComplete.animated.test.tsx +62 -0
- package/tests/SheetScrollLock.animated.test.tsx +287 -0
- package/tests/SheetScrollableDrag.animated.test.tsx +1264 -0
- package/tests/SheetSnapPointsFit.animated.test.tsx +259 -0
- package/tests/ShorthandVariables.test.tsx +44 -0
- package/tests/SpinnerCustomColors.test.tsx +67 -0
- package/tests/StackZIndex.test.tsx +51 -0
- package/tests/StressPagePerf.test.tsx +76 -0
- package/tests/StylePlatform.test.tsx +38 -0
- package/tests/StyleProp.test.tsx +20 -0
- package/tests/StyledAnchor.test.tsx +17 -0
- package/tests/StyledButtonTheme.test.tsx +22 -0
- package/tests/StyledButtonVariantPseudo.test.tsx +20 -0
- package/tests/StyledButtonVariantPseudoMerge.animated.test.tsx +33 -0
- package/tests/StyledCheckboxTheme.test.tsx +16 -0
- package/tests/StyledContextColor.test.tsx +119 -0
- package/tests/StyledContextTokens.test.tsx +56 -0
- package/tests/StyledHOCNamed.test.tsx +16 -0
- package/tests/StyledHtml.test.tsx +161 -0
- package/tests/StyledIconColor.test.tsx +32 -0
- package/tests/StyledInputFocusStyle.test.tsx +19 -0
- package/tests/StyledInputOnFocus.test.tsx +27 -0
- package/tests/StyledMediaQueryMerge.test.tsx +66 -0
- package/tests/StyledRNW.test.tsx +17 -0
- package/tests/StyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledStyleableInputVariant.test.tsx +22 -0
- package/tests/StyledStyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledVariantTextColor.test.tsx +24 -0
- package/tests/StyledViewOnFocus.test.tsx +27 -0
- package/tests/TabHoverAnimation.animated.test.tsx +468 -0
- package/tests/TabHoverPositionSmooth.animated.test.tsx +129 -0
- package/tests/TextNestedInheritance.test.tsx +93 -0
- package/tests/ThemeChange.test.tsx +70 -0
- package/tests/ThemeComponentResolution.test.tsx +82 -0
- package/tests/ThemeConditionalName.test.tsx +34 -0
- package/tests/ThemeMediaAnimation.test.tsx +65 -0
- package/tests/ThemeNested.test.tsx +141 -0
- package/tests/ThemeReset.test.tsx +63 -0
- package/tests/ThemeShallow.test.tsx +95 -0
- package/tests/Toast.test.tsx +106 -0
- package/tests/ToggleGroup.test.tsx +61 -0
- package/tests/ToggleGroupActiveProps.test.tsx +38 -0
- package/tests/ToggleGroupXGroup.test.tsx +172 -0
- package/tests/TooltipAnimation.animated.test.tsx +260 -0
- package/tests/TooltipEnterInterrupt.animated.test.tsx +76 -0
- package/tests/TooltipGlobalPattern.animated.test.tsx +208 -0
- package/tests/TooltipGroup.animated.test.tsx +79 -0
- package/tests/TooltipMultiTrigger.test.tsx +116 -0
- package/tests/TooltipPositionJump.animated.test.tsx +229 -0
- package/tests/TooltipPositionJumpNotes.md +219 -0
- package/tests/TooltipRapidSwitch.animated.test.tsx +399 -0
- package/tests/TooltipTriggerInline.test.tsx +65 -0
- package/tests/TransformMediaQueryMerge.test.tsx +104 -0
- package/tests/TransitionEnterExit.animated.test.tsx +311 -0
- package/tests/UseTheme.test.tsx +16 -0
- package/tests/V5ThemeBuilderOutput.test.tsx +164 -0
- package/tests/VariantFontFamily.test.tsx +11 -0
- package/tests/VariantsOrder.test.tsx +53 -0
- package/tests/_debug_position.mjs +52 -0
- package/tests/test-utils.ts +106 -0
- package/tests/utils.tsx +54 -0
- package/tsconfig.json +45 -0
- package/vite-env.d.ts +1 -0
- package/vite.config.ts +14 -0
- package/webpack.config.js +139 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Comprehensive tests for Sheet animation configurations
|
|
6
|
+
* Tests CSS driver, Motion driver, and various animation prop combinations
|
|
7
|
+
* Verifies that different animation configs produce measurably different animation speeds
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Helper to measure actual animation duration by tracking position changes
|
|
11
|
+
async function measureSheetAnimationDuration(
|
|
12
|
+
page: any,
|
|
13
|
+
triggerTestId: string,
|
|
14
|
+
frameTestId: string,
|
|
15
|
+
closeTestId: string
|
|
16
|
+
): Promise<number> {
|
|
17
|
+
const closeButton = page.getByTestId(closeTestId)
|
|
18
|
+
|
|
19
|
+
// click trigger and measure how long until the frame's visual position stabilizes
|
|
20
|
+
const duration = await page.evaluate(
|
|
21
|
+
async ({ triggerId, frameId }: { triggerId: string; frameId: string }) => {
|
|
22
|
+
return new Promise<number>((resolve) => {
|
|
23
|
+
const trigger = document.querySelector(
|
|
24
|
+
`[data-testid="${triggerId}"]`
|
|
25
|
+
) as HTMLElement
|
|
26
|
+
if (!trigger) {
|
|
27
|
+
resolve(-1)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const startTime = performance.now()
|
|
32
|
+
let initialTop = -1
|
|
33
|
+
let lastTop = -1
|
|
34
|
+
let stableCount = 0
|
|
35
|
+
let hasMovedFromInitial = false
|
|
36
|
+
let checkCount = 0
|
|
37
|
+
const maxChecks = 200 // ~10 seconds max
|
|
38
|
+
|
|
39
|
+
trigger.click()
|
|
40
|
+
|
|
41
|
+
const checkAnimation = () => {
|
|
42
|
+
checkCount++
|
|
43
|
+
const frame = document.querySelector(
|
|
44
|
+
`[data-testid="${frameId}"]`
|
|
45
|
+
) as HTMLElement
|
|
46
|
+
if (!frame) {
|
|
47
|
+
if (checkCount < maxChecks) {
|
|
48
|
+
requestAnimationFrame(checkAnimation)
|
|
49
|
+
} else {
|
|
50
|
+
resolve(performance.now() - startTime)
|
|
51
|
+
}
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// use getBoundingClientRect which reflects parent transforms
|
|
56
|
+
const currentTop = Math.round(frame.getBoundingClientRect().top)
|
|
57
|
+
|
|
58
|
+
// record the initial position on first check
|
|
59
|
+
if (initialTop === -1) {
|
|
60
|
+
initialTop = currentTop
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// wait until the position has actually changed from the initial value
|
|
64
|
+
// before we start counting stability (animation might not start for a frame or two)
|
|
65
|
+
if (!hasMovedFromInitial && currentTop !== initialTop) {
|
|
66
|
+
hasMovedFromInitial = true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (hasMovedFromInitial && currentTop === lastTop) {
|
|
70
|
+
stableCount++
|
|
71
|
+
if (stableCount >= 3) {
|
|
72
|
+
resolve(performance.now() - startTime)
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
stableCount = 0
|
|
77
|
+
lastTop = currentTop
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (checkCount < maxChecks) {
|
|
81
|
+
requestAnimationFrame(checkAnimation)
|
|
82
|
+
} else {
|
|
83
|
+
resolve(performance.now() - startTime)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
requestAnimationFrame(checkAnimation)
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
{ triggerId: triggerTestId, frameId: frameTestId }
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
// close the sheet for next measurement
|
|
94
|
+
await closeButton.scrollIntoViewIfNeeded()
|
|
95
|
+
await closeButton.click({ timeout: 5000 })
|
|
96
|
+
await page.waitForTimeout(1500)
|
|
97
|
+
|
|
98
|
+
return Math.round(duration)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// CSS DRIVER TESTS
|
|
103
|
+
// Note: CSS driver has a known limitation where animation names don't translate
|
|
104
|
+
// to Sheet animation timing (the Sheet uses useAnimatedNumber internally which
|
|
105
|
+
// CSS driver doesn't animate - it relies on CSS transitions for component styles)
|
|
106
|
+
// ============================================================================
|
|
107
|
+
test.describe('Sheet Animation - CSS Driver', () => {
|
|
108
|
+
test.beforeEach(async ({ page }) => {
|
|
109
|
+
await setupPage(page, {
|
|
110
|
+
name: 'SheetAnimationCase',
|
|
111
|
+
type: 'useCase',
|
|
112
|
+
searchParams: { animationDriver: 'css' },
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('sheet transform has CSS transition applied', async ({ page }) => {
|
|
117
|
+
// This test verifies that the CSS driver properly applies a CSS transition
|
|
118
|
+
// to the Sheet's transform property, enabling smooth open/close animations
|
|
119
|
+
const trigger = page.getByTestId('animation-quick-trigger')
|
|
120
|
+
const closeButton = page.getByTestId('animation-quick-close')
|
|
121
|
+
|
|
122
|
+
await trigger.click()
|
|
123
|
+
await page.waitForTimeout(100) // Small wait for sheet to start rendering
|
|
124
|
+
|
|
125
|
+
// The transform is on the AnimatedView wrapper, which is the parent of Sheet.Frame
|
|
126
|
+
// We need to find the element with position:absolute that wraps the frame
|
|
127
|
+
const debugInfo = await page.evaluate(() => {
|
|
128
|
+
const frame = document.querySelector('[data-testid="animation-quick-frame"]')
|
|
129
|
+
if (!frame) return { found: false, error: 'frame not found' }
|
|
130
|
+
|
|
131
|
+
// The AnimatedView is a parent with position:absolute and transform
|
|
132
|
+
let animatedView: Element | null = frame
|
|
133
|
+
for (let i = 0; i < 5; i++) {
|
|
134
|
+
animatedView = animatedView?.parentElement || null
|
|
135
|
+
if (!animatedView) break
|
|
136
|
+
const style = getComputedStyle(animatedView)
|
|
137
|
+
if (style.position === 'absolute' && style.transform !== 'none') {
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!animatedView) {
|
|
143
|
+
return { found: false, error: 'animatedView not found' }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const style = getComputedStyle(animatedView)
|
|
147
|
+
// Get all style attributes for debugging
|
|
148
|
+
const allStyles: Record<string, string> = {}
|
|
149
|
+
for (let i = 0; i < style.length; i++) {
|
|
150
|
+
const prop = style[i]
|
|
151
|
+
if (prop.includes('transition') || prop.includes('transform')) {
|
|
152
|
+
allStyles[prop] = style.getPropertyValue(prop)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
found: true,
|
|
157
|
+
tagName: animatedView.tagName,
|
|
158
|
+
transition: style.transition,
|
|
159
|
+
transform: style.transform,
|
|
160
|
+
inlineStyle: (animatedView as HTMLElement).style.cssText,
|
|
161
|
+
allTransitionStyles: allStyles,
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Check that there's a transition that applies to transform
|
|
166
|
+
// CSS transition "0.1s ease-in" (without property name) means "all 0.1s ease-in"
|
|
167
|
+
// which applies to all properties including transform
|
|
168
|
+
const hasTransition =
|
|
169
|
+
debugInfo.found && debugInfo.transition && debugInfo.transition !== 'all'
|
|
170
|
+
expect(hasTransition).toBe(true)
|
|
171
|
+
|
|
172
|
+
await closeButton.click()
|
|
173
|
+
await page.waitForTimeout(600)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test('sheet actually animates (transform changes over time)', async ({ page }) => {
|
|
177
|
+
// This test verifies that the sheet's transform actually changes over time
|
|
178
|
+
// (i.e., it animates) rather than instantly snapping to position
|
|
179
|
+
const trigger = page.getByTestId('animation-lazy-trigger')
|
|
180
|
+
const closeButton = page.getByTestId('animation-lazy-close')
|
|
181
|
+
|
|
182
|
+
// Click to open the sheet
|
|
183
|
+
await trigger.click()
|
|
184
|
+
|
|
185
|
+
// Wait a small moment for sheet to start appearing
|
|
186
|
+
await page.waitForTimeout(50)
|
|
187
|
+
|
|
188
|
+
// Capture transform values over the animation duration
|
|
189
|
+
const transforms: string[] = []
|
|
190
|
+
for (let i = 0; i < 20; i++) {
|
|
191
|
+
const transform = await page.evaluate(() => {
|
|
192
|
+
// Find the AnimatedView (parent of frame with transform)
|
|
193
|
+
const frame = document.querySelector('[data-testid="animation-lazy-frame"]')
|
|
194
|
+
if (!frame) return 'frame-not-found'
|
|
195
|
+
|
|
196
|
+
let el: Element | null = frame
|
|
197
|
+
for (let j = 0; j < 5; j++) {
|
|
198
|
+
el = el?.parentElement
|
|
199
|
+
if (!el) break
|
|
200
|
+
const style = getComputedStyle(el)
|
|
201
|
+
if (style.position === 'absolute' && style.transform !== 'none') {
|
|
202
|
+
return style.transform
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return 'parent-not-found'
|
|
206
|
+
})
|
|
207
|
+
transforms.push(transform)
|
|
208
|
+
await page.waitForTimeout(30) // ~30ms between samples
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Filter out errors and get unique values
|
|
212
|
+
const uniqueTransforms = [
|
|
213
|
+
...new Set(transforms.filter((t) => !t.includes('not-found') && t !== 'none')),
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
// If animation is working, we should see multiple distinct transform values
|
|
217
|
+
// as the sheet animates from bottom to its snap point
|
|
218
|
+
expect(uniqueTransforms.length).toBeGreaterThan(1)
|
|
219
|
+
|
|
220
|
+
await closeButton.click()
|
|
221
|
+
await page.waitForTimeout(600)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
test('all sheet variants open and close correctly', async ({ page }) => {
|
|
225
|
+
// CSS driver doesn't support transitionConfig prop reliably - only test transition variants
|
|
226
|
+
const testIds = ['animation-quick', 'animation-lazy', 'animation-slow']
|
|
227
|
+
|
|
228
|
+
for (const testId of testIds) {
|
|
229
|
+
const trigger = page.getByTestId(`${testId}-trigger`)
|
|
230
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
231
|
+
const frame = page.getByTestId(`${testId}-frame`).first()
|
|
232
|
+
const closeButton = page.getByTestId(`${testId}-close`)
|
|
233
|
+
|
|
234
|
+
await trigger.click()
|
|
235
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
236
|
+
|
|
237
|
+
await closeButton.click()
|
|
238
|
+
// Wait longer for slow animations to complete
|
|
239
|
+
await page.waitForTimeout(1500)
|
|
240
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
// transitionConfig not working reliably with CSS driver
|
|
245
|
+
test.skip('transitionConfig prop works without animation prop', async ({ page }) => {
|
|
246
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
247
|
+
const frame = page.getByTestId('transitionConfig-only-frame').first()
|
|
248
|
+
const trigger = page.getByTestId('transitionConfig-only-trigger')
|
|
249
|
+
const closeButton = page.getByTestId('transitionConfig-only-close')
|
|
250
|
+
|
|
251
|
+
await trigger.click()
|
|
252
|
+
await expect(frame).toBeVisible({ timeout: 3000 })
|
|
253
|
+
|
|
254
|
+
// Sheet should open successfully with only transitionConfig
|
|
255
|
+
await closeButton.click()
|
|
256
|
+
await page.waitForTimeout(1500)
|
|
257
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
// ============================================================================
|
|
262
|
+
// MOTION DRIVER TESTS
|
|
263
|
+
// ============================================================================
|
|
264
|
+
test.describe('Sheet Animation - Motion Driver', () => {
|
|
265
|
+
test.beforeEach(async ({ page }) => {
|
|
266
|
+
await setupPage(page, {
|
|
267
|
+
name: 'SheetAnimationCase',
|
|
268
|
+
type: 'useCase',
|
|
269
|
+
searchParams: { animationDriver: 'motion' },
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
test('all sheet variants open and close correctly', async ({ page }) => {
|
|
274
|
+
// Skip transitionConfig variants - not working reliably
|
|
275
|
+
const testIds = ['animation-quick', 'animation-lazy', 'animation-slow']
|
|
276
|
+
|
|
277
|
+
for (const testId of testIds) {
|
|
278
|
+
const trigger = page.getByTestId(`${testId}-trigger`)
|
|
279
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
280
|
+
const frame = page.getByTestId(`${testId}-frame`).first()
|
|
281
|
+
const closeButton = page.getByTestId(`${testId}-close`)
|
|
282
|
+
|
|
283
|
+
await trigger.click()
|
|
284
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
285
|
+
|
|
286
|
+
await closeButton.click()
|
|
287
|
+
// Wait longer for slow animations to complete
|
|
288
|
+
await page.waitForTimeout(2000)
|
|
289
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('transitionConfig prop works without animation prop', async ({ page }) => {
|
|
294
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
295
|
+
const frame = page.getByTestId('transitionConfig-only-frame').first()
|
|
296
|
+
const trigger = page.getByTestId('transitionConfig-only-trigger')
|
|
297
|
+
const closeButton = page.getByTestId('transitionConfig-only-close')
|
|
298
|
+
|
|
299
|
+
await trigger.click()
|
|
300
|
+
await expect(frame).toBeVisible({ timeout: 3000 })
|
|
301
|
+
|
|
302
|
+
await closeButton.click()
|
|
303
|
+
await page.waitForTimeout(2000)
|
|
304
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
test('transitionConfig overrides transition prop', async ({ page }) => {
|
|
308
|
+
// transition="quick" (fast) + transitionConfig={type:'timing',duration:1000} (slow)
|
|
309
|
+
// if override works, the 1000ms config should make it measurably slower than the 100ms baseline
|
|
310
|
+
const baselineDuration = await measureSheetAnimationDuration(
|
|
311
|
+
page,
|
|
312
|
+
'transitionConfig-only-trigger',
|
|
313
|
+
'transitionConfig-only-frame',
|
|
314
|
+
'transitionConfig-only-close'
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
const overrideDuration = await measureSheetAnimationDuration(
|
|
318
|
+
page,
|
|
319
|
+
'animation-plus-config-trigger',
|
|
320
|
+
'animation-plus-config-frame',
|
|
321
|
+
'animation-plus-config-close'
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
console.info(
|
|
325
|
+
`Motion Driver - baseline (100ms): ${baselineDuration}ms, override (1000ms): ${overrideDuration}ms`
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
// the 1000ms override should be significantly slower than the 100ms baseline
|
|
329
|
+
// use absolute +250ms margin: CI inflates both measurements (spring settling + overhead)
|
|
330
|
+
// which compresses the ratio, but absolute difference stays well above 250ms
|
|
331
|
+
expect(overrideDuration).toBeGreaterThan(baselineDuration + 250)
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
// ============================================================================
|
|
336
|
+
// REANIMATED DRIVER TESTS (default)
|
|
337
|
+
// ============================================================================
|
|
338
|
+
test.describe('Sheet Animation - Reanimated Driver (default)', () => {
|
|
339
|
+
test.beforeEach(async ({ page }) => {
|
|
340
|
+
await setupPage(page, {
|
|
341
|
+
name: 'SheetAnimationCase',
|
|
342
|
+
type: 'useCase',
|
|
343
|
+
// No animationDriver param = default reanimated
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
test('all sheet variants open and close correctly', async ({ page }) => {
|
|
348
|
+
const testIds = ['animation-quick', 'animation-lazy', 'animation-slow']
|
|
349
|
+
|
|
350
|
+
for (const testId of testIds) {
|
|
351
|
+
const trigger = page.getByTestId(`${testId}-trigger`)
|
|
352
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
353
|
+
const frame = page.getByTestId(`${testId}-frame`).first()
|
|
354
|
+
const closeButton = page.getByTestId(`${testId}-close`)
|
|
355
|
+
|
|
356
|
+
await trigger.click()
|
|
357
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
358
|
+
|
|
359
|
+
await closeButton.click()
|
|
360
|
+
// Wait longer for slow animations to complete
|
|
361
|
+
await page.waitForTimeout(2000)
|
|
362
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
363
|
+
}
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
test('transitionConfig prop works', async ({ page }) => {
|
|
367
|
+
// transitionConfig only works with JS animation drivers, not CSS
|
|
368
|
+
const driver = (test.info().project?.metadata as any)?.animationDriver
|
|
369
|
+
test.skip(driver === 'css', 'transitionConfig not supported by CSS animation driver')
|
|
370
|
+
|
|
371
|
+
// Use .first() because Sheet passes testId to both Sheet.Frame and SheetCover
|
|
372
|
+
const frame = page.getByTestId('transitionConfig-only-frame').first()
|
|
373
|
+
const trigger = page.getByTestId('transitionConfig-only-trigger')
|
|
374
|
+
const closeButton = page.getByTestId('transitionConfig-only-close')
|
|
375
|
+
|
|
376
|
+
await trigger.click()
|
|
377
|
+
await expect(frame).toBeVisible({ timeout: 3000 })
|
|
378
|
+
|
|
379
|
+
await closeButton.click()
|
|
380
|
+
await page.waitForTimeout(2000)
|
|
381
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
test('transitionConfig overrides transition prop', async ({ page }) => {
|
|
385
|
+
// transitionConfig only works with JS animation drivers, not CSS
|
|
386
|
+
const driver = (test.info().project?.metadata as any)?.animationDriver
|
|
387
|
+
test.skip(driver === 'css', 'transitionConfig not supported by CSS animation driver')
|
|
388
|
+
// transition="quick" (fast) + transitionConfig={type:'timing',duration:1000} (slow)
|
|
389
|
+
// if override works, the 1000ms config should make it measurably slower than the 100ms baseline
|
|
390
|
+
const baselineDuration = await measureSheetAnimationDuration(
|
|
391
|
+
page,
|
|
392
|
+
'transitionConfig-only-trigger',
|
|
393
|
+
'transitionConfig-only-frame',
|
|
394
|
+
'transitionConfig-only-close'
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
const overrideDuration = await measureSheetAnimationDuration(
|
|
398
|
+
page,
|
|
399
|
+
'animation-plus-config-trigger',
|
|
400
|
+
'animation-plus-config-frame',
|
|
401
|
+
'animation-plus-config-close'
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
console.info(
|
|
405
|
+
`Reanimated Driver - baseline (100ms): ${baselineDuration}ms, override (1000ms): ${overrideDuration}ms`
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
// the 1000ms override should be significantly slower than the 100ms baseline
|
|
409
|
+
// use absolute +250ms margin: CI inflates both measurements (spring settling + overhead)
|
|
410
|
+
// which compresses the ratio, but absolute difference stays well above 250ms
|
|
411
|
+
expect(overrideDuration).toBeGreaterThan(baselineDuration + 250)
|
|
412
|
+
})
|
|
413
|
+
})
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { expect, test, type Page } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
// mobile viewport with touch support for realistic sheet drag testing
|
|
5
|
+
test.use({
|
|
6
|
+
viewport: { width: 390, height: 844 },
|
|
7
|
+
hasTouch: true,
|
|
8
|
+
isMobile: true,
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test.beforeEach(async ({ page }) => {
|
|
12
|
+
await setupPage(page, { name: 'SheetDragCase', type: 'useCase' })
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* perform a drag gesture using mouse events
|
|
17
|
+
* PanResponder responds to mouse events on web
|
|
18
|
+
*/
|
|
19
|
+
async function dragSheet(
|
|
20
|
+
page: Page,
|
|
21
|
+
startX: number,
|
|
22
|
+
startY: number,
|
|
23
|
+
deltaY: number,
|
|
24
|
+
options: { steps?: number; stepDelay?: number } = {}
|
|
25
|
+
) {
|
|
26
|
+
const { steps = 20, stepDelay = 16 } = options
|
|
27
|
+
|
|
28
|
+
await page.mouse.move(startX, startY)
|
|
29
|
+
await page.mouse.down()
|
|
30
|
+
|
|
31
|
+
for (let i = 1; i <= steps; i++) {
|
|
32
|
+
await page.mouse.move(startX, startY + (deltaY * i) / steps)
|
|
33
|
+
await page.waitForTimeout(stepDelay)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await page.mouse.up()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test.describe('Sheet drag interactions', () => {
|
|
40
|
+
test('dragging sheet changes snap point position state', async ({ page }) => {
|
|
41
|
+
const trigger = page.getByTestId('drag-percent-trigger')
|
|
42
|
+
const frame = page.getByTestId('drag-percent-frame')
|
|
43
|
+
const handle = page.getByTestId('drag-percent-handle')
|
|
44
|
+
const positionIndicator = page.getByTestId('drag-percent-snap-indicator')
|
|
45
|
+
|
|
46
|
+
await trigger.click()
|
|
47
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
48
|
+
await page.waitForTimeout(400)
|
|
49
|
+
|
|
50
|
+
await expect(positionIndicator).toContainText('0')
|
|
51
|
+
|
|
52
|
+
const handleBox = await handle.boundingBox()
|
|
53
|
+
expect(handleBox).toBeTruthy()
|
|
54
|
+
|
|
55
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
56
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
57
|
+
|
|
58
|
+
// drag down to cross threshold between 80% and 40%
|
|
59
|
+
await dragSheet(page, startX, startY, 250)
|
|
60
|
+
await page.waitForTimeout(600)
|
|
61
|
+
|
|
62
|
+
// verify snap point state changed (this works)
|
|
63
|
+
await expect(positionIndicator).toContainText('1')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('dragging sheet down changes snap point (constant mode)', async ({ page }) => {
|
|
67
|
+
const trigger = page.getByTestId('drag-constant-trigger')
|
|
68
|
+
const frame = page.getByTestId('drag-constant-frame')
|
|
69
|
+
const handle = page.getByTestId('drag-constant-handle')
|
|
70
|
+
const positionIndicator = page.getByTestId('drag-constant-snap-indicator')
|
|
71
|
+
|
|
72
|
+
await trigger.click()
|
|
73
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
74
|
+
await page.waitForTimeout(400)
|
|
75
|
+
|
|
76
|
+
await expect(positionIndicator).toContainText('0')
|
|
77
|
+
|
|
78
|
+
const handleBox = await handle.boundingBox()
|
|
79
|
+
expect(handleBox).toBeTruthy()
|
|
80
|
+
|
|
81
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
82
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
83
|
+
|
|
84
|
+
// drag 200px to move from 500px to 250px snap point
|
|
85
|
+
await dragSheet(page, startX, startY, 200)
|
|
86
|
+
await page.waitForTimeout(600)
|
|
87
|
+
|
|
88
|
+
// verify snap point state changed
|
|
89
|
+
await expect(positionIndicator).toContainText('1')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('dragging sheet past bottom dismisses it', async ({ page }) => {
|
|
93
|
+
const trigger = page.getByTestId('dismiss-drag-trigger')
|
|
94
|
+
const frame = page.getByTestId('dismiss-drag-frame')
|
|
95
|
+
const handle = page.getByTestId('dismiss-drag-handle')
|
|
96
|
+
const dismissCount = page.getByTestId('dismiss-drag-count')
|
|
97
|
+
|
|
98
|
+
await expect(dismissCount).toContainText('0')
|
|
99
|
+
|
|
100
|
+
await trigger.click()
|
|
101
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
102
|
+
await page.waitForTimeout(400)
|
|
103
|
+
|
|
104
|
+
const handleBox = await handle.boundingBox()
|
|
105
|
+
expect(handleBox).toBeTruthy()
|
|
106
|
+
|
|
107
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
108
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
109
|
+
|
|
110
|
+
// drag far down to dismiss (sheet is at 50%)
|
|
111
|
+
await dragSheet(page, startX, startY, 500)
|
|
112
|
+
await page.waitForTimeout(800)
|
|
113
|
+
|
|
114
|
+
await expect(frame).not.toBeInViewport({ ratio: 0.5 })
|
|
115
|
+
await expect(dismissCount).toContainText('1')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test('partial drag snaps back to original position', async ({ page }) => {
|
|
119
|
+
const trigger = page.getByTestId('drag-percent-trigger')
|
|
120
|
+
const frame = page.getByTestId('drag-percent-frame')
|
|
121
|
+
const handle = page.getByTestId('drag-percent-handle')
|
|
122
|
+
const positionIndicator = page.getByTestId('drag-percent-snap-indicator')
|
|
123
|
+
|
|
124
|
+
await trigger.click()
|
|
125
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
126
|
+
await page.waitForTimeout(400)
|
|
127
|
+
|
|
128
|
+
await expect(positionIndicator).toContainText('0')
|
|
129
|
+
|
|
130
|
+
const handleBox = await handle.boundingBox()
|
|
131
|
+
expect(handleBox).toBeTruthy()
|
|
132
|
+
|
|
133
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
134
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
135
|
+
|
|
136
|
+
// small drag that shouldn't cross threshold - use more steps for smoother movement
|
|
137
|
+
await dragSheet(page, startX, startY, 20, { steps: 10 })
|
|
138
|
+
await page.waitForTimeout(800)
|
|
139
|
+
|
|
140
|
+
await expect(positionIndicator).toContainText('0')
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// flaky: Playwright mouse events don't trigger PanResponder consistently for subsequent drags
|
|
144
|
+
test.skip('dragging up from lower snap point returns to higher', async ({ page }) => {
|
|
145
|
+
const trigger = page.getByTestId('drag-percent-trigger')
|
|
146
|
+
const frame = page.getByTestId('drag-percent-frame')
|
|
147
|
+
const handle = page.getByTestId('drag-percent-handle')
|
|
148
|
+
const positionIndicator = page.getByTestId('drag-percent-snap-indicator')
|
|
149
|
+
|
|
150
|
+
await trigger.click()
|
|
151
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
152
|
+
await page.waitForTimeout(400)
|
|
153
|
+
|
|
154
|
+
const handleBox = await handle.boundingBox()
|
|
155
|
+
expect(handleBox).toBeTruthy()
|
|
156
|
+
|
|
157
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
158
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
159
|
+
|
|
160
|
+
// first drag down to snap point 1
|
|
161
|
+
await dragSheet(page, startX, startY, 250)
|
|
162
|
+
await page.waitForTimeout(600)
|
|
163
|
+
|
|
164
|
+
await expect(positionIndicator).toContainText('1')
|
|
165
|
+
|
|
166
|
+
// wait for animation to fully settle
|
|
167
|
+
await page.waitForTimeout(800)
|
|
168
|
+
|
|
169
|
+
// get new handle position after snapping to lower position
|
|
170
|
+
const newHandleBox = await handle.boundingBox()
|
|
171
|
+
expect(newHandleBox).toBeTruthy()
|
|
172
|
+
|
|
173
|
+
const newStartX = newHandleBox!.x + newHandleBox!.width / 2
|
|
174
|
+
const newStartY = newHandleBox!.y + newHandleBox!.height / 2
|
|
175
|
+
|
|
176
|
+
// drag UP (negative) to return to snap point 0
|
|
177
|
+
await dragSheet(page, newStartX, newStartY, -200, { steps: 25, stepDelay: 16 })
|
|
178
|
+
await page.waitForTimeout(600)
|
|
179
|
+
|
|
180
|
+
// verify we returned to snap point 0
|
|
181
|
+
await expect(positionIndicator).toContainText('0')
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('sheet frame moves during drag', async ({ page }) => {
|
|
185
|
+
const trigger = page.getByTestId('drag-percent-trigger')
|
|
186
|
+
const frame = page.getByTestId('drag-percent-frame')
|
|
187
|
+
const handle = page.getByTestId('drag-percent-handle')
|
|
188
|
+
|
|
189
|
+
await trigger.click()
|
|
190
|
+
await expect(frame).toBeVisible({ timeout: 5000 })
|
|
191
|
+
await page.waitForTimeout(400)
|
|
192
|
+
|
|
193
|
+
const handleBox = await handle.boundingBox()
|
|
194
|
+
expect(handleBox).toBeTruthy()
|
|
195
|
+
|
|
196
|
+
// get initial frame position
|
|
197
|
+
const initialBox = await frame.boundingBox()
|
|
198
|
+
expect(initialBox).toBeTruthy()
|
|
199
|
+
const initialTop = initialBox!.y
|
|
200
|
+
|
|
201
|
+
const startX = handleBox!.x + handleBox!.width / 2
|
|
202
|
+
const startY = handleBox!.y + handleBox!.height / 2
|
|
203
|
+
|
|
204
|
+
// start drag and hold mid-drag
|
|
205
|
+
await page.mouse.move(startX, startY)
|
|
206
|
+
await page.mouse.down()
|
|
207
|
+
// move in steps like a real drag
|
|
208
|
+
for (let i = 1; i <= 10; i++) {
|
|
209
|
+
await page.mouse.move(startX, startY + 10 * i)
|
|
210
|
+
await page.waitForTimeout(40)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// check frame moved during drag
|
|
214
|
+
const midDragBox = await frame.boundingBox()
|
|
215
|
+
expect(midDragBox).toBeTruthy()
|
|
216
|
+
|
|
217
|
+
await page.mouse.up()
|
|
218
|
+
|
|
219
|
+
// frame should have moved down during drag
|
|
220
|
+
// this verifies the drag gesture is actually being detected by the sheet
|
|
221
|
+
expect(midDragBox!.y).toBeGreaterThan(initialTop)
|
|
222
|
+
})
|
|
223
|
+
})
|