@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,128 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
test.describe('Dialog Nested Stacking', () => {
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'DialogNestedCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('nested dialog appears above parent dialog (z-index stacking)', async ({
|
|
10
|
+
page,
|
|
11
|
+
}) => {
|
|
12
|
+
await page.waitForLoadState('networkidle')
|
|
13
|
+
|
|
14
|
+
// Open parent dialog
|
|
15
|
+
const parentTrigger = page.getByTestId('parent-dialog-trigger')
|
|
16
|
+
await parentTrigger.click()
|
|
17
|
+
|
|
18
|
+
const parentDialog = page.getByTestId('parent-dialog-content')
|
|
19
|
+
await expect(parentDialog).toBeVisible({ timeout: 5000 })
|
|
20
|
+
|
|
21
|
+
// Wait for animation to complete
|
|
22
|
+
await page.waitForTimeout(300)
|
|
23
|
+
|
|
24
|
+
// Open nested dialog
|
|
25
|
+
const nestedTrigger = page.getByTestId('nested-dialog-trigger')
|
|
26
|
+
await nestedTrigger.click()
|
|
27
|
+
|
|
28
|
+
const nestedDialog = page.getByTestId('nested-dialog-content')
|
|
29
|
+
await expect(nestedDialog).toBeVisible({ timeout: 5000 })
|
|
30
|
+
|
|
31
|
+
// Wait for animation to complete
|
|
32
|
+
await page.waitForTimeout(300)
|
|
33
|
+
|
|
34
|
+
// Get the z-index values of both dialog portal containers
|
|
35
|
+
// GuiRoot wraps portal content in Theme > span, so z-index is on the inner span
|
|
36
|
+
const zIndexInfo = await page.evaluate(() => {
|
|
37
|
+
const portals = document.querySelectorAll('span[style*="z-index"]')
|
|
38
|
+
const zIndices: number[] = []
|
|
39
|
+
|
|
40
|
+
portals.forEach((portal) => {
|
|
41
|
+
const style = window.getComputedStyle(portal)
|
|
42
|
+
const zIndex = parseInt(style.zIndex, 10)
|
|
43
|
+
if (!isNaN(zIndex)) {
|
|
44
|
+
zIndices.push(zIndex)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return zIndices.sort((a, b) => a - b)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Should have at least 2 different z-index values
|
|
52
|
+
expect(zIndexInfo.length).toBeGreaterThanOrEqual(2)
|
|
53
|
+
|
|
54
|
+
// The nested dialog should have a higher z-index than the parent
|
|
55
|
+
const parentZIndex = zIndexInfo[0]
|
|
56
|
+
const nestedZIndex = zIndexInfo[zIndexInfo.length - 1]
|
|
57
|
+
|
|
58
|
+
expect(nestedZIndex).toBeGreaterThan(parentZIndex)
|
|
59
|
+
|
|
60
|
+
// Verify the nested dialog is visually on top by checking element at center
|
|
61
|
+
const nestedBounds = await nestedDialog.boundingBox()
|
|
62
|
+
if (nestedBounds) {
|
|
63
|
+
const centerX = nestedBounds.x + nestedBounds.width / 2
|
|
64
|
+
const centerY = nestedBounds.y + nestedBounds.height / 2
|
|
65
|
+
|
|
66
|
+
const elementAtPoint = await page.evaluate(
|
|
67
|
+
({ x, y }) => {
|
|
68
|
+
const el = document.elementFromPoint(x, y)
|
|
69
|
+
return el?.closest('[data-testid="nested-dialog-content"]') !== null
|
|
70
|
+
},
|
|
71
|
+
{ x: centerX, y: centerY }
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
expect(elementAtPoint).toBe(true)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('three levels of nested dialogs stack correctly', async ({ page }) => {
|
|
79
|
+
await page.waitForLoadState('networkidle')
|
|
80
|
+
|
|
81
|
+
// Open level 1 dialog
|
|
82
|
+
const level1Trigger = page.getByTestId('parent-dialog-trigger')
|
|
83
|
+
await level1Trigger.click()
|
|
84
|
+
|
|
85
|
+
const level1Dialog = page.getByTestId('parent-dialog-content')
|
|
86
|
+
await expect(level1Dialog).toBeVisible({ timeout: 5000 })
|
|
87
|
+
|
|
88
|
+
// Wait for animation
|
|
89
|
+
await page.waitForTimeout(300)
|
|
90
|
+
|
|
91
|
+
// Open level 2 dialog
|
|
92
|
+
const level2Trigger = page.getByTestId('nested-dialog-trigger')
|
|
93
|
+
await level2Trigger.click()
|
|
94
|
+
|
|
95
|
+
const level2Dialog = page.getByTestId('nested-dialog-content')
|
|
96
|
+
await expect(level2Dialog).toBeVisible({ timeout: 5000 })
|
|
97
|
+
|
|
98
|
+
// Wait for animation
|
|
99
|
+
await page.waitForTimeout(300)
|
|
100
|
+
|
|
101
|
+
// Open level 3 dialog
|
|
102
|
+
const level3Trigger = page.getByTestId('level-3-dialog-trigger')
|
|
103
|
+
await level3Trigger.click()
|
|
104
|
+
|
|
105
|
+
const level3Dialog = page.getByTestId('level-3-dialog-content')
|
|
106
|
+
await expect(level3Dialog).toBeVisible({ timeout: 5000 })
|
|
107
|
+
|
|
108
|
+
// Wait for animation
|
|
109
|
+
await page.waitForTimeout(300)
|
|
110
|
+
|
|
111
|
+
// Verify level 3 is on top visually
|
|
112
|
+
const level3Bounds = await level3Dialog.boundingBox()
|
|
113
|
+
if (level3Bounds) {
|
|
114
|
+
const centerX = level3Bounds.x + level3Bounds.width / 2
|
|
115
|
+
const centerY = level3Bounds.y + level3Bounds.height / 2
|
|
116
|
+
|
|
117
|
+
const elementAtPoint = await page.evaluate(
|
|
118
|
+
({ x, y }) => {
|
|
119
|
+
const el = document.elementFromPoint(x, y)
|
|
120
|
+
return el?.closest('[data-testid="level-3-dialog-content"]') !== null
|
|
121
|
+
},
|
|
122
|
+
{ x: centerX, y: centerY }
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
expect(elementAtPoint).toBe(true)
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test for issue #3565
|
|
6
|
+
* Verifies that Dialog works when controlled with open={true}
|
|
7
|
+
*
|
|
8
|
+
* In JSDOM (Jest), this fails with "node.show is not a function"
|
|
9
|
+
* because JSDOM doesn't implement HTMLDialogElement.show()
|
|
10
|
+
*
|
|
11
|
+
* This test ensures the dialog renders correctly in a real browser.
|
|
12
|
+
*/
|
|
13
|
+
test.describe('Dialog Open Controlled', () => {
|
|
14
|
+
test.beforeEach(async ({ page }) => {
|
|
15
|
+
await setupPage(page, { name: 'DialogOpenControlled', type: 'useCase' })
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('dialog renders when controlled with open={true}', async ({ page }) => {
|
|
19
|
+
await page.waitForLoadState('networkidle')
|
|
20
|
+
|
|
21
|
+
// The dialog should be visible immediately since open={true}
|
|
22
|
+
const dialogContent = page.getByTestId('dialog-content')
|
|
23
|
+
await expect(dialogContent).toBeVisible({ timeout: 5000 })
|
|
24
|
+
await expect(dialogContent).toHaveText('Hiya!')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('dialog can be closed via close button', async ({ page }) => {
|
|
28
|
+
await page.waitForLoadState('networkidle')
|
|
29
|
+
|
|
30
|
+
// Dialog should be visible
|
|
31
|
+
const dialogContent = page.getByTestId('dialog-content')
|
|
32
|
+
await expect(dialogContent).toBeVisible({ timeout: 5000 })
|
|
33
|
+
|
|
34
|
+
// Click close button
|
|
35
|
+
const closeButton = page.getByTestId('dialog-close')
|
|
36
|
+
await closeButton.click()
|
|
37
|
+
|
|
38
|
+
// Dialog should still be visible because it's controlled with open={true}
|
|
39
|
+
// (no state management in the component - it's always open)
|
|
40
|
+
await expect(dialogContent).toBeVisible()
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test for dialog pointer events unlock timing
|
|
6
|
+
*
|
|
7
|
+
* Verifies that when a dialog closes, the dialog content gets pointer-events: none
|
|
8
|
+
* immediately, allowing clicks to pass through to elements behind during the
|
|
9
|
+
* exit animation.
|
|
10
|
+
*
|
|
11
|
+
* This is an animated test because the bug only manifests with animations enabled.
|
|
12
|
+
*/
|
|
13
|
+
test.describe('Dialog Pointer Events Unlock', () => {
|
|
14
|
+
test.beforeEach(async ({ page }) => {
|
|
15
|
+
await setupPage(page, { name: 'DialogPointerEventsCase', type: 'useCase' })
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('dialog content allows click-through during exit animation', async ({ page }) => {
|
|
19
|
+
// get initial click count
|
|
20
|
+
const clickCountEl = page.getByTestId('click-count')
|
|
21
|
+
await expect(clickCountEl).toHaveText('0')
|
|
22
|
+
|
|
23
|
+
// open the dialog
|
|
24
|
+
const triggerButton = page.getByTestId('dialog-trigger')
|
|
25
|
+
await triggerButton.click()
|
|
26
|
+
|
|
27
|
+
// wait for dialog to be visible
|
|
28
|
+
const dialogClose = page.locator('[data-testid="dialog-close"]')
|
|
29
|
+
await expect(dialogClose).toBeVisible({ timeout: 5000 })
|
|
30
|
+
|
|
31
|
+
// wait for enter animation to settle
|
|
32
|
+
await page.waitForTimeout(800)
|
|
33
|
+
|
|
34
|
+
// set up monitoring to check dialog content pointer events after close
|
|
35
|
+
const results = await page.evaluate(async () => {
|
|
36
|
+
return new Promise<{
|
|
37
|
+
contentPointerEvents: string[]
|
|
38
|
+
buttonAccessible: boolean[]
|
|
39
|
+
dialogStillAnimating: boolean
|
|
40
|
+
}>((resolve) => {
|
|
41
|
+
const contentPointerEvents: string[] = []
|
|
42
|
+
const buttonAccessible: boolean[] = []
|
|
43
|
+
const closeButton = document.querySelector(
|
|
44
|
+
'[data-testid="dialog-close"]'
|
|
45
|
+
) as HTMLElement
|
|
46
|
+
const dialogContent = document.querySelector('[role="dialog"]') as HTMLElement
|
|
47
|
+
const backgroundBtn = document.querySelector(
|
|
48
|
+
'[data-testid="background-button"]'
|
|
49
|
+
) as HTMLElement
|
|
50
|
+
|
|
51
|
+
// start sampling immediately
|
|
52
|
+
const interval = setInterval(() => {
|
|
53
|
+
if (dialogContent) {
|
|
54
|
+
contentPointerEvents.push(getComputedStyle(dialogContent).pointerEvents)
|
|
55
|
+
}
|
|
56
|
+
// check if the background button is accessible (not blocked by dialog)
|
|
57
|
+
const btnRect = backgroundBtn?.getBoundingClientRect()
|
|
58
|
+
if (btnRect) {
|
|
59
|
+
const elementAtPoint = document.elementFromPoint(
|
|
60
|
+
btnRect.left + btnRect.width / 2,
|
|
61
|
+
btnRect.top + btnRect.height / 2
|
|
62
|
+
)
|
|
63
|
+
buttonAccessible.push(
|
|
64
|
+
elementAtPoint === backgroundBtn || backgroundBtn.contains(elementAtPoint)
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}, 20)
|
|
68
|
+
|
|
69
|
+
// click close button
|
|
70
|
+
closeButton.click()
|
|
71
|
+
|
|
72
|
+
// after 300ms, check state and stop sampling
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
clearInterval(interval)
|
|
75
|
+
const stillAnimating = dialogContent
|
|
76
|
+
? getComputedStyle(dialogContent).opacity !== '0'
|
|
77
|
+
: false
|
|
78
|
+
resolve({
|
|
79
|
+
contentPointerEvents,
|
|
80
|
+
buttonAccessible,
|
|
81
|
+
dialogStillAnimating: stillAnimating,
|
|
82
|
+
})
|
|
83
|
+
}, 300)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
console.log('Content pointer events during exit:', results.contentPointerEvents)
|
|
88
|
+
console.log('Button accessible during exit:', results.buttonAccessible)
|
|
89
|
+
console.log('Dialog still animating at end:', results.dialogStillAnimating)
|
|
90
|
+
|
|
91
|
+
// the key assertion: the background button should become accessible quickly
|
|
92
|
+
// (within first few samples) - this is the actual user-facing behavior we care about
|
|
93
|
+
// note: the dialog portal container gets pointer-events: none, which allows clicks
|
|
94
|
+
// to pass through even if the dialog content itself has pointer-events: auto
|
|
95
|
+
const buttonAccessibleEarly = results.buttonAccessible.some(
|
|
96
|
+
(accessible, i) => i < 8 && accessible
|
|
97
|
+
)
|
|
98
|
+
expect(buttonAccessibleEarly).toBeTruthy()
|
|
99
|
+
|
|
100
|
+
// wait for dialog to fully close (reanimated driver can be much slower in CI)
|
|
101
|
+
await expect(dialogClose).not.toBeVisible({ timeout: 10000 })
|
|
102
|
+
|
|
103
|
+
// verify background button is clickable
|
|
104
|
+
const backgroundButton = page.getByTestId('background-button')
|
|
105
|
+
await backgroundButton.click()
|
|
106
|
+
await expect(clickCountEl).toHaveText('1')
|
|
107
|
+
})
|
|
108
|
+
})
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'DialogScopedCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('scoped dialogs work', async ({ page }) => {
|
|
10
|
+
// Wait for page to load
|
|
11
|
+
await page.waitForLoadState('networkidle')
|
|
12
|
+
|
|
13
|
+
async function testDialogScoped(name: string) {
|
|
14
|
+
const triggerTestId = `${name}-trigger`
|
|
15
|
+
const contentTestId = `${name}-dialog-content`
|
|
16
|
+
const trigger = page.getByTestId(triggerTestId)
|
|
17
|
+
const content = page.getByTestId(contentTestId)
|
|
18
|
+
const closeButton = content.getByTestId(`${name}-dialog-close`)
|
|
19
|
+
|
|
20
|
+
// Check initial state
|
|
21
|
+
await expect(trigger).toBeVisible()
|
|
22
|
+
await expect(content).not.toBeVisible()
|
|
23
|
+
|
|
24
|
+
// Click trigger to open dialog
|
|
25
|
+
await trigger.click()
|
|
26
|
+
|
|
27
|
+
// Wait for content to be visible
|
|
28
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
29
|
+
|
|
30
|
+
// Click close button
|
|
31
|
+
await closeButton.click()
|
|
32
|
+
|
|
33
|
+
// Verify dialog is closed
|
|
34
|
+
await expect(content).not.toBeVisible()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Test each scoped dialog
|
|
38
|
+
await testDialogScoped('plain')
|
|
39
|
+
await testDialogScoped('a')
|
|
40
|
+
await testDialogScoped('b')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('dialog scopes are isolated', async ({ page }) => {
|
|
44
|
+
// Wait for page to load
|
|
45
|
+
await page.waitForLoadState('networkidle')
|
|
46
|
+
|
|
47
|
+
const plainTrigger = page.getByTestId('plain-trigger')
|
|
48
|
+
const aTrigger = page.getByTestId('a-trigger')
|
|
49
|
+
const bTrigger = page.getByTestId('b-trigger')
|
|
50
|
+
|
|
51
|
+
const plainContent = page.getByTestId('plain-dialog-content')
|
|
52
|
+
const aContent = page.getByTestId('a-dialog-content')
|
|
53
|
+
const bContent = page.getByTestId('b-dialog-content')
|
|
54
|
+
|
|
55
|
+
// Open dialog A
|
|
56
|
+
await aTrigger.click()
|
|
57
|
+
await expect(aContent).toBeVisible({ timeout: 5000 })
|
|
58
|
+
|
|
59
|
+
// Verify other dialogs are not visible
|
|
60
|
+
await expect(plainContent).not.toBeVisible()
|
|
61
|
+
await expect(bContent).not.toBeVisible()
|
|
62
|
+
|
|
63
|
+
// Close dialog A
|
|
64
|
+
await aContent.getByTestId('a-dialog-close').click()
|
|
65
|
+
await expect(aContent).not.toBeVisible()
|
|
66
|
+
|
|
67
|
+
// Open dialog B
|
|
68
|
+
await bTrigger.click()
|
|
69
|
+
await expect(bContent).toBeVisible({ timeout: 5000 })
|
|
70
|
+
|
|
71
|
+
// Verify other dialogs are not visible
|
|
72
|
+
await expect(plainContent).not.toBeVisible()
|
|
73
|
+
await expect(aContent).not.toBeVisible()
|
|
74
|
+
|
|
75
|
+
// Close dialog B
|
|
76
|
+
await bContent.getByTestId('b-dialog-close').click()
|
|
77
|
+
await expect(bContent).not.toBeVisible()
|
|
78
|
+
|
|
79
|
+
// Open plain dialog
|
|
80
|
+
await plainTrigger.click()
|
|
81
|
+
await expect(plainContent).toBeVisible({ timeout: 5000 })
|
|
82
|
+
|
|
83
|
+
// Verify other dialogs are not visible
|
|
84
|
+
await expect(aContent).not.toBeVisible()
|
|
85
|
+
await expect(bContent).not.toBeVisible()
|
|
86
|
+
|
|
87
|
+
// Close plain dialog
|
|
88
|
+
await plainContent.getByTestId('plain-dialog-close').click()
|
|
89
|
+
await expect(plainContent).not.toBeVisible()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('scoped dialogs adapt to sheets', async ({ page: pageIn }) => {
|
|
93
|
+
const page = await setupPage(pageIn, {
|
|
94
|
+
name: 'DialogScopedCase',
|
|
95
|
+
type: 'useCase',
|
|
96
|
+
adapt: true,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// Wait for page to load
|
|
100
|
+
await page.waitForLoadState('networkidle')
|
|
101
|
+
|
|
102
|
+
async function testDialogAdapted(name: string) {
|
|
103
|
+
const trigger = page.getByTestId(`${name}-trigger`)
|
|
104
|
+
const sheetContents = page.getByTestId(`${name}-sheet-contents`).first()
|
|
105
|
+
const dialogContent = page.getByTestId(`${name}-dialog-content`)
|
|
106
|
+
|
|
107
|
+
// Click trigger to open sheet
|
|
108
|
+
await trigger.click()
|
|
109
|
+
|
|
110
|
+
// Wait for sheet to be visible and open
|
|
111
|
+
await expect(sheetContents).toBeVisible({ timeout: 5000 })
|
|
112
|
+
await expect(sheetContents).toHaveAttribute('data-state', 'open', { timeout: 5000 })
|
|
113
|
+
|
|
114
|
+
// Check that dialog content is inside sheet
|
|
115
|
+
await expect(sheetContents.locator(dialogContent)).toBeVisible()
|
|
116
|
+
|
|
117
|
+
// Dialog.Close hides in sheet mode
|
|
118
|
+
const closeButton = sheetContents.getByTestId('dialog-close')
|
|
119
|
+
await expect(closeButton).not.toBeVisible()
|
|
120
|
+
|
|
121
|
+
// Click sheet backdrop (at top of screen to avoid sheet content)
|
|
122
|
+
const overlay = page.locator(`#${name}-sheet-overlay`)
|
|
123
|
+
await expect(overlay).toBeVisible()
|
|
124
|
+
// Click near the top of the overlay where the sheet content doesn't cover
|
|
125
|
+
await overlay.click({ position: { x: 10, y: 10 } })
|
|
126
|
+
|
|
127
|
+
// Wait for sheet to close by checking data-state attribute
|
|
128
|
+
await expect(sheetContents).toHaveAttribute('data-state', 'closed', { timeout: 5000 })
|
|
129
|
+
|
|
130
|
+
// Verify sheet is visually off-screen
|
|
131
|
+
await expect(sheetContents).not.toBeInViewport({ ratio: 0.5 })
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await testDialogAdapted('plain')
|
|
135
|
+
await testDialogAdapted('a')
|
|
136
|
+
await testDialogAdapted('b')
|
|
137
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test for styled(Dialog.Overlay) with onPress
|
|
6
|
+
*
|
|
7
|
+
* This tests the fix for: "Cannot read property '_internalInstanceHandle' of null"
|
|
8
|
+
* which occurred on Android when using styled(Dialog.Overlay) with onPress.
|
|
9
|
+
*
|
|
10
|
+
* The fix skips GestureDetector wrapping for HOC components and passes press
|
|
11
|
+
* events down via props instead, allowing the inner component to handle gesture
|
|
12
|
+
* detection at the correct level where a native view exists.
|
|
13
|
+
*/
|
|
14
|
+
test.describe('Dialog Sheet Adapt - styled(Dialog.Overlay) with onPress', () => {
|
|
15
|
+
test.beforeEach(async ({ page }) => {
|
|
16
|
+
await setupPage(page, { name: 'DialogSheetAdaptCase', type: 'useCase' })
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('styled(Dialog.Overlay) with onPress should render without crashing', async ({
|
|
20
|
+
page,
|
|
21
|
+
}) => {
|
|
22
|
+
await page.waitForLoadState('networkidle')
|
|
23
|
+
|
|
24
|
+
// Open the dialog
|
|
25
|
+
const trigger = page.getByTestId('open-dialog')
|
|
26
|
+
await trigger.click()
|
|
27
|
+
|
|
28
|
+
// Wait for dialog overlay to be visible (the styled DialogOverlay)
|
|
29
|
+
// On web, this should work. The fix ensures HOC components pass press events
|
|
30
|
+
// down instead of wrapping with GestureDetector (which would crash on native
|
|
31
|
+
// when the inner component returns null during adapt)
|
|
32
|
+
await page.waitForTimeout(500)
|
|
33
|
+
|
|
34
|
+
// Dialog content should be visible
|
|
35
|
+
const dialogContent = page.locator('text=Dialog with Sheet Adapt')
|
|
36
|
+
await expect(dialogContent).toBeVisible({ timeout: 5000 })
|
|
37
|
+
|
|
38
|
+
// Close button should work
|
|
39
|
+
const closeButton = page.getByTestId('close-dialog')
|
|
40
|
+
await closeButton.click()
|
|
41
|
+
|
|
42
|
+
// Dialog should close
|
|
43
|
+
await expect(dialogContent).not.toBeVisible({ timeout: 5000 })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('can open and close dialog multiple times without errors', async ({ page }) => {
|
|
47
|
+
await page.waitForLoadState('networkidle')
|
|
48
|
+
|
|
49
|
+
// Test multiple open/close cycles to ensure stability
|
|
50
|
+
for (let i = 0; i < 3; i++) {
|
|
51
|
+
// Open the dialog
|
|
52
|
+
const trigger = page.getByTestId('open-dialog')
|
|
53
|
+
await trigger.click()
|
|
54
|
+
|
|
55
|
+
// Wait for dialog to be visible
|
|
56
|
+
await page.waitForTimeout(300)
|
|
57
|
+
const dialogContent = page.locator('text=Dialog with Sheet Adapt')
|
|
58
|
+
await expect(dialogContent).toBeVisible({ timeout: 5000 })
|
|
59
|
+
|
|
60
|
+
// Close via button
|
|
61
|
+
const closeButton = page.getByTestId('close-dialog')
|
|
62
|
+
await closeButton.click()
|
|
63
|
+
|
|
64
|
+
// Wait for dialog to close
|
|
65
|
+
await expect(dialogContent).not.toBeVisible({ timeout: 5000 })
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test for Dialog → Sheet content portaling on viewport resize
|
|
6
|
+
*
|
|
7
|
+
* This tests the fix for: When resizing from wide (Dialog) to narrow (Sheet via Adapt),
|
|
8
|
+
* the Sheet appears empty because the portal content isn't properly transferred.
|
|
9
|
+
*/
|
|
10
|
+
test.describe('Dialog Sheet Adapt - viewport resize', () => {
|
|
11
|
+
test.beforeEach(async ({ page }) => {
|
|
12
|
+
await setupPage(page, { name: 'DialogSheetAdaptResizeCase', type: 'useCase' })
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('content is visible in dialog at wide viewport', async ({ page }) => {
|
|
16
|
+
// set viewport to wide (above maxMd breakpoint of 768px)
|
|
17
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
18
|
+
await page.waitForTimeout(300)
|
|
19
|
+
|
|
20
|
+
// open the dialog
|
|
21
|
+
const trigger = page.getByTestId('open-dialog')
|
|
22
|
+
await trigger.click({ force: true })
|
|
23
|
+
await page.waitForTimeout(500)
|
|
24
|
+
|
|
25
|
+
// dialog content should be visible
|
|
26
|
+
const title = page.getByTestId('dialog-title')
|
|
27
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
28
|
+
|
|
29
|
+
const content = page.getByTestId('dialog-content')
|
|
30
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
31
|
+
|
|
32
|
+
// close button should work
|
|
33
|
+
const closeButton = page.getByTestId('close-dialog')
|
|
34
|
+
await closeButton.click({ force: true })
|
|
35
|
+
await expect(title).not.toBeVisible({ timeout: 5000 })
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('content is visible in sheet at narrow viewport', async ({ page }) => {
|
|
39
|
+
// set viewport to narrow (below maxMd breakpoint of 768px)
|
|
40
|
+
await page.setViewportSize({ width: 600, height: 768 })
|
|
41
|
+
await page.waitForTimeout(300)
|
|
42
|
+
|
|
43
|
+
// open - should show as sheet due to adapt
|
|
44
|
+
const trigger = page.getByTestId('open-dialog')
|
|
45
|
+
await trigger.click({ force: true })
|
|
46
|
+
await page.waitForTimeout(500)
|
|
47
|
+
|
|
48
|
+
// sheet content should be visible
|
|
49
|
+
const title = page.getByTestId('dialog-title')
|
|
50
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
51
|
+
|
|
52
|
+
const content = page.getByTestId('dialog-content')
|
|
53
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
54
|
+
|
|
55
|
+
// extra content should also be visible
|
|
56
|
+
const extra1 = page.getByTestId('extra-content-1')
|
|
57
|
+
await expect(extra1).toBeVisible({ timeout: 5000 })
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('content transfers from dialog to sheet on resize narrow', async ({ page }) => {
|
|
61
|
+
// start at wide viewport
|
|
62
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
63
|
+
await page.waitForTimeout(300)
|
|
64
|
+
|
|
65
|
+
// open the dialog at wide width
|
|
66
|
+
const trigger = page.getByTestId('open-dialog')
|
|
67
|
+
await trigger.click({ force: true })
|
|
68
|
+
await page.waitForTimeout(500)
|
|
69
|
+
|
|
70
|
+
// verify content visible in dialog
|
|
71
|
+
const title = page.getByTestId('dialog-title')
|
|
72
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
73
|
+
|
|
74
|
+
const content = page.getByTestId('dialog-content')
|
|
75
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
76
|
+
|
|
77
|
+
// resize to narrow - should adapt to sheet
|
|
78
|
+
await page.setViewportSize({ width: 600, height: 768 })
|
|
79
|
+
await page.waitForTimeout(500) // give time for adapt to trigger and animations
|
|
80
|
+
|
|
81
|
+
// content should still be visible (now in sheet)
|
|
82
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
83
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
84
|
+
|
|
85
|
+
// extra content should also be visible
|
|
86
|
+
const extra1 = page.getByTestId('extra-content-1')
|
|
87
|
+
await expect(extra1).toBeVisible({ timeout: 5000 })
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('content transfers from sheet to dialog on resize wide', async ({ page }) => {
|
|
91
|
+
// start at narrow viewport
|
|
92
|
+
await page.setViewportSize({ width: 600, height: 768 })
|
|
93
|
+
await page.waitForTimeout(300)
|
|
94
|
+
|
|
95
|
+
// open at narrow width - should show as sheet
|
|
96
|
+
const trigger = page.getByTestId('open-dialog')
|
|
97
|
+
await trigger.click({ force: true })
|
|
98
|
+
await page.waitForTimeout(500)
|
|
99
|
+
|
|
100
|
+
// verify content visible in sheet
|
|
101
|
+
const title = page.getByTestId('dialog-title')
|
|
102
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
103
|
+
|
|
104
|
+
const content = page.getByTestId('dialog-content')
|
|
105
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
106
|
+
|
|
107
|
+
// resize to wide - should adapt back to dialog
|
|
108
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
109
|
+
await page.waitForTimeout(500) // give time for adapt to trigger and animations
|
|
110
|
+
|
|
111
|
+
// content should still be visible (now in dialog)
|
|
112
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
113
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
114
|
+
|
|
115
|
+
// extra content should also be visible
|
|
116
|
+
const extra1 = page.getByTestId('extra-content-1')
|
|
117
|
+
await expect(extra1).toBeVisible({ timeout: 5000 })
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('multiple resize cycles preserve content', async ({ page }) => {
|
|
121
|
+
// start wide
|
|
122
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
123
|
+
await page.waitForTimeout(300)
|
|
124
|
+
|
|
125
|
+
// open dialog
|
|
126
|
+
const trigger = page.getByTestId('open-dialog')
|
|
127
|
+
await trigger.click({ force: true })
|
|
128
|
+
await page.waitForTimeout(500)
|
|
129
|
+
|
|
130
|
+
const title = page.getByTestId('dialog-title')
|
|
131
|
+
const content = page.getByTestId('dialog-content')
|
|
132
|
+
|
|
133
|
+
// verify initial state
|
|
134
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
135
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
136
|
+
|
|
137
|
+
// cycle 1: wide -> narrow
|
|
138
|
+
await page.setViewportSize({ width: 600, height: 768 })
|
|
139
|
+
await page.waitForTimeout(500)
|
|
140
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
141
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
142
|
+
|
|
143
|
+
// cycle 1: narrow -> wide
|
|
144
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
145
|
+
await page.waitForTimeout(500)
|
|
146
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
147
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
148
|
+
|
|
149
|
+
// cycle 2: wide -> narrow
|
|
150
|
+
await page.setViewportSize({ width: 600, height: 768 })
|
|
151
|
+
await page.waitForTimeout(500)
|
|
152
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
153
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
154
|
+
|
|
155
|
+
// cycle 2: narrow -> wide
|
|
156
|
+
await page.setViewportSize({ width: 1024, height: 768 })
|
|
157
|
+
await page.waitForTimeout(500)
|
|
158
|
+
await expect(title).toBeVisible({ timeout: 5000 })
|
|
159
|
+
await expect(content).toBeVisible({ timeout: 5000 })
|
|
160
|
+
})
|
|
161
|
+
})
|