@dxos/react-ui 0.8.4-main.ae835ea → 0.8.4-main.bc674ce
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/dist/lib/browser/chunk-CEKVHJ27.mjs +774 -0
- package/dist/lib/browser/chunk-CEKVHJ27.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3163 -64
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +34 -46
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/chunk-2NHEX4AD.mjs +776 -0
- package/dist/lib/node-esm/chunk-2NHEX4AD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +3163 -64
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +34 -46
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/components/{Buttons → Button}/Button.d.ts +1 -1
- package/dist/types/src/components/Button/Button.d.ts.map +1 -0
- package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -0
- package/dist/types/src/components/{Buttons → Button}/IconButton.d.ts +2 -2
- package/dist/types/src/components/Button/IconButton.d.ts.map +1 -0
- package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -0
- package/dist/types/src/components/Button/Toggle.d.ts.map +1 -0
- package/dist/types/src/components/Button/Toggle.stories.d.ts +16 -0
- package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -0
- package/dist/types/src/components/{Buttons → Button}/ToggleGroup.d.ts +4 -4
- package/dist/types/src/components/Button/ToggleGroup.d.ts.map +1 -0
- package/dist/types/src/components/{Buttons → Button}/ToggleGroup.stories.d.ts +4 -4
- package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -0
- package/dist/types/src/components/Button/index.d.ts.map +1 -0
- package/dist/types/src/components/Clipboard/CopyButton.d.ts +1 -1
- package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
- package/dist/types/src/components/DensityProvider/DensityProvider.d.ts +1 -1
- package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/Dialog.d.ts +40 -0
- package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -0
- package/dist/types/src/components/{Dialogs → Dialog}/Dialog.stories.d.ts +7 -5
- package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/index.d.ts.map +1 -0
- package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts +1 -1
- package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
- package/dist/types/src/components/Icon/Icon.d.ts +1 -1
- package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.d.ts +5 -2
- package/dist/types/src/components/Input/Input.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.stories.d.ts +1 -1
- package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
- package/dist/types/src/components/{Lists → List}/List.d.ts +1 -1
- package/dist/types/src/components/List/List.d.ts.map +1 -0
- package/dist/types/src/components/List/List.stories.d.ts.map +1 -0
- package/dist/types/src/components/List/ListDropIndicator.d.ts.map +1 -0
- package/dist/types/src/components/List/Tree.d.ts.map +1 -0
- package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -0
- package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +1 -0
- package/dist/types/src/components/List/Treegrid.d.ts.map +1 -0
- package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -0
- package/dist/types/src/components/List/index.d.ts.map +1 -0
- package/dist/types/src/components/Main/Main.d.ts +44 -19
- package/dist/types/src/components/Main/Main.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.stories.d.ts +2 -1
- package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
- package/dist/types/src/components/{Menus → Menu}/ContextMenu.d.ts +6 -6
- package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -0
- package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/{Menus → Menu}/DropdownMenu.d.ts +3 -4
- package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -0
- package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/Menu/index.d.ts.map +1 -0
- package/dist/types/src/components/Message/Message.d.ts +1 -1
- package/dist/types/src/components/Message/Message.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +9 -7
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +4 -0
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +39 -0
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -0
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +19 -0
- package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -0
- package/dist/types/src/components/ScrollContainer/index.d.ts +2 -0
- package/dist/types/src/components/ScrollContainer/index.d.ts.map +1 -0
- package/dist/types/src/components/Select/Select.d.ts +10 -10
- package/dist/types/src/components/Select/Select.d.ts.map +1 -1
- package/dist/types/src/components/Separator/Separator.d.ts +1 -1
- package/dist/types/src/components/Tag/Tag.d.ts +1 -1
- package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -2
- package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -8
- package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
- package/dist/types/src/components/ThemeProvider/index.d.ts +2 -1
- package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
- package/dist/types/src/components/Toast/Toast.d.ts +4 -4
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +11 -11
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +5 -4
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
- package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
- package/dist/types/src/hooks/useElevationContext.d.ts +1 -1
- package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/index.d.ts +1 -1
- package/dist/types/src/testing/decorators/index.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withLayout.d.ts +3 -3
- package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withLayoutVariants.d.ts +12 -0
- package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -0
- package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -2
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -25
- package/src/components/Avatars/Avatar.stories.tsx +2 -2
- package/src/components/Avatars/Avatar.tsx +1 -1
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
- package/src/components/{Buttons → Button}/Button.stories.tsx +2 -2
- package/src/components/{Buttons → Button}/Button.tsx +1 -1
- package/src/components/{Buttons → Button}/IconButton.tsx +19 -13
- package/src/components/{Buttons → Button}/Toggle.stories.tsx +5 -4
- package/src/components/Clipboard/CopyButton.tsx +4 -4
- package/src/components/DensityProvider/DensityProvider.tsx +1 -1
- package/src/components/{Dialogs → Dialog}/AlertDialog.stories.tsx +1 -1
- package/src/components/Dialog/Dialog.stories.tsx +97 -0
- package/src/components/{Dialogs → Dialog}/Dialog.tsx +140 -40
- package/src/components/ElevationProvider/ElevationProvider.tsx +1 -1
- package/src/components/Icon/Icon.stories.tsx +1 -1
- package/src/components/Icon/Icon.tsx +1 -1
- package/src/components/Input/Input.stories.tsx +2 -2
- package/src/components/Input/Input.tsx +13 -4
- package/src/components/{Lists → List}/List.stories.tsx +17 -13
- package/src/components/{Lists → List}/List.tsx +1 -1
- package/src/components/{Lists → List}/ListDropIndicator.tsx +1 -1
- package/src/components/Main/Main.stories.tsx +127 -20
- package/src/components/Main/Main.tsx +265 -58
- package/src/components/{Menus → Menu}/DropdownMenu.stories.tsx +1 -1
- package/src/components/{Menus → Menu}/DropdownMenu.tsx +79 -58
- package/src/components/Message/Message.stories.tsx +1 -1
- package/src/components/Message/Message.tsx +30 -5
- package/src/components/Popover/Popover.stories.tsx +1 -1
- package/src/components/Popover/Popover.tsx +52 -33
- package/src/components/ScrollArea/ScrollArea.stories.tsx +54 -4
- package/src/components/ScrollArea/ScrollArea.tsx +50 -4
- package/src/components/ScrollContainer/ScrollContainer.stories.tsx +70 -0
- package/src/components/ScrollContainer/ScrollContainer.tsx +233 -0
- package/src/components/ScrollContainer/index.ts +5 -0
- package/src/components/Select/Select.stories.tsx +2 -2
- package/src/components/Select/Select.tsx +4 -4
- package/src/components/Tag/Tag.stories.tsx +2 -2
- package/src/components/Tag/Tag.tsx +1 -1
- package/src/components/ThemeProvider/ThemeProvider.tsx +1 -3
- package/src/components/ThemeProvider/TranslationsProvider.tsx +1 -16
- package/src/components/ThemeProvider/index.ts +3 -3
- package/src/components/Toast/Toast.stories.tsx +1 -1
- package/src/components/Toolbar/Toolbar.stories.tsx +2 -4
- package/src/components/Toolbar/Toolbar.tsx +24 -9
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +22 -20
- package/src/components/index.ts +5 -4
- package/src/hooks/useDensityContext.ts +1 -1
- package/src/hooks/useElevationContext.ts +1 -1
- package/src/index.ts +1 -1
- package/src/playground/Controls.stories.tsx +2 -2
- package/src/playground/Custom.stories.tsx +6 -8
- package/src/testing/decorators/index.ts +1 -1
- package/src/testing/decorators/withLayout.tsx +22 -15
- package/src/testing/decorators/{withSurfaceVariantsLayout.tsx → withLayoutVariants.tsx} +5 -5
- package/src/testing/decorators/withTheme.tsx +3 -2
- package/src/util/index.ts +2 -2
- package/dist/lib/browser/chunk-HUZZ56DW.mjs +0 -4509
- package/dist/lib/browser/chunk-HUZZ56DW.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OJLL6E2Z.mjs +0 -4511
- package/dist/lib/node-esm/chunk-OJLL6E2Z.mjs.map +0 -7
- package/dist/types/src/components/Buttons/Button.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/Button.stories.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/IconButton.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/IconButton.stories.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/Toggle.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/Toggle.stories.d.ts +0 -13
- package/dist/types/src/components/Buttons/Toggle.stories.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/ToggleGroup.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/ToggleGroup.stories.d.ts.map +0 -1
- package/dist/types/src/components/Buttons/index.d.ts.map +0 -1
- package/dist/types/src/components/Dialogs/AlertDialog.d.ts.map +0 -1
- package/dist/types/src/components/Dialogs/AlertDialog.stories.d.ts.map +0 -1
- package/dist/types/src/components/Dialogs/Dialog.d.ts +0 -31
- package/dist/types/src/components/Dialogs/Dialog.d.ts.map +0 -1
- package/dist/types/src/components/Dialogs/Dialog.stories.d.ts.map +0 -1
- package/dist/types/src/components/Dialogs/index.d.ts.map +0 -1
- package/dist/types/src/components/Lists/List.d.ts.map +0 -1
- package/dist/types/src/components/Lists/List.stories.d.ts.map +0 -1
- package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +0 -1
- package/dist/types/src/components/Lists/Tree.d.ts.map +0 -1
- package/dist/types/src/components/Lists/Tree.stories.d.ts.map +0 -1
- package/dist/types/src/components/Lists/TreeDropIndicator.d.ts.map +0 -1
- package/dist/types/src/components/Lists/Treegrid.d.ts.map +0 -1
- package/dist/types/src/components/Lists/Treegrid.stories.d.ts.map +0 -1
- package/dist/types/src/components/Lists/index.d.ts.map +0 -1
- package/dist/types/src/components/Menus/ContextMenu.d.ts.map +0 -1
- package/dist/types/src/components/Menus/ContextMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +0 -1
- package/dist/types/src/components/Menus/DropdownMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/Menus/index.d.ts.map +0 -1
- package/dist/types/src/testing/decorators/withSurfaceVariantsLayout.d.ts +0 -12
- package/dist/types/src/testing/decorators/withSurfaceVariantsLayout.d.ts.map +0 -1
- package/dist/types/src/util/ThemedClassName.d.ts +0 -5
- package/dist/types/src/util/ThemedClassName.d.ts.map +0 -1
- package/dist/types/src/util/domino.d.ts +0 -18
- package/dist/types/src/util/domino.d.ts.map +0 -1
- package/src/components/Dialogs/Dialog.stories.tsx +0 -67
- package/src/util/ThemedClassName.ts +0 -7
- package/src/util/domino.ts +0 -53
- /package/dist/types/src/components/{Buttons → Button}/Button.stories.d.ts +0 -0
- /package/dist/types/src/components/{Buttons → Button}/IconButton.stories.d.ts +0 -0
- /package/dist/types/src/components/{Buttons → Button}/Toggle.d.ts +0 -0
- /package/dist/types/src/components/{Buttons → Button}/index.d.ts +0 -0
- /package/dist/types/src/components/{Dialogs → Dialog}/AlertDialog.d.ts +0 -0
- /package/dist/types/src/components/{Dialogs → Dialog}/AlertDialog.stories.d.ts +0 -0
- /package/dist/types/src/components/{Dialogs → Dialog}/index.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/List.stories.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/ListDropIndicator.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/Tree.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/Tree.stories.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/TreeDropIndicator.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/Treegrid.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/Treegrid.stories.d.ts +0 -0
- /package/dist/types/src/components/{Lists → List}/index.d.ts +0 -0
- /package/dist/types/src/components/{Menus → Menu}/ContextMenu.stories.d.ts +0 -0
- /package/dist/types/src/components/{Menus → Menu}/DropdownMenu.stories.d.ts +0 -0
- /package/dist/types/src/components/{Menus → Menu}/index.d.ts +0 -0
- /package/src/components/{Buttons → Button}/IconButton.stories.tsx +0 -0
- /package/src/components/{Buttons → Button}/Toggle.tsx +0 -0
- /package/src/components/{Buttons → Button}/ToggleGroup.stories.tsx +0 -0
- /package/src/components/{Buttons → Button}/ToggleGroup.tsx +0 -0
- /package/src/components/{Buttons → Button}/index.ts +0 -0
- /package/src/components/{Dialogs → Dialog}/AlertDialog.tsx +0 -0
- /package/src/components/{Dialogs → Dialog}/index.ts +0 -0
- /package/src/components/{Lists → List}/Tree.stories.tsx +0 -0
- /package/src/components/{Lists → List}/Tree.tsx +0 -0
- /package/src/components/{Lists → List}/TreeDropIndicator.tsx +0 -0
- /package/src/components/{Lists → List}/Treegrid.stories.tsx +0 -0
- /package/src/components/{Lists → List}/Treegrid.tsx +0 -0
- /package/src/components/{Lists → List}/index.ts +0 -0
- /package/src/components/{Menus → Menu}/ContextMenu.stories.tsx +0 -0
- /package/src/components/{Menus → Menu}/ContextMenu.tsx +0 -0
- /package/src/components/{Menus → Menu}/index.ts +0 -0
|
@@ -22,8 +22,10 @@ import React, {
|
|
|
22
22
|
useState,
|
|
23
23
|
} from 'react';
|
|
24
24
|
|
|
25
|
+
import { addEventListener } from '@dxos/async';
|
|
25
26
|
import { log } from '@dxos/log';
|
|
26
|
-
import { useForwardedRef, useMediaQuery } from '@dxos/react-hooks';
|
|
27
|
+
import { useDynamicRef, useForwardedRef, useMediaQuery, useViewportResize } from '@dxos/react-hooks';
|
|
28
|
+
import { type MainStyleProps } from '@dxos/ui-theme';
|
|
27
29
|
|
|
28
30
|
import { useThemeContext } from '../../hooks';
|
|
29
31
|
import { type ThemedClassName } from '../../util';
|
|
@@ -31,22 +33,20 @@ import { type Label, toLocalizedString, useTranslation } from '../ThemeProvider'
|
|
|
31
33
|
|
|
32
34
|
import { useSwipeToDismiss } from './useSwipeToDismiss';
|
|
33
35
|
|
|
36
|
+
const MAIN_NAME = 'Main';
|
|
34
37
|
const MAIN_ROOT_NAME = 'MainRoot';
|
|
35
38
|
const NAVIGATION_SIDEBAR_NAME = 'NavigationSidebar';
|
|
36
39
|
const COMPLEMENTARY_SIDEBAR_NAME = 'ComplementarySidebar';
|
|
37
|
-
const
|
|
38
|
-
const GENERIC_CONSUMER_NAME = 'GenericConsumer';
|
|
40
|
+
const DRAWER_NAME = 'Drawer';
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
type MainContextValue = {
|
|
43
|
-
resizing: boolean;
|
|
44
|
-
navigationSidebarState: SidebarState;
|
|
45
|
-
setNavigationSidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
|
|
46
|
-
complementarySidebarState: SidebarState;
|
|
47
|
-
setComplementarySidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
|
|
42
|
+
const handleOpenAutoFocus = (event: Event) => {
|
|
43
|
+
!document.body.hasAttribute('data-is-keyboard') && event.preventDefault();
|
|
48
44
|
};
|
|
49
45
|
|
|
46
|
+
//
|
|
47
|
+
// Landmark
|
|
48
|
+
//
|
|
49
|
+
|
|
50
50
|
const landmarkAttr = 'data-main-landmark';
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -72,35 +72,104 @@ const useLandmarkMover = (propsOnKeyDown: ComponentPropsWithoutRef<'div'>['onKey
|
|
|
72
72
|
[propsOnKeyDown],
|
|
73
73
|
);
|
|
74
74
|
|
|
75
|
-
// TODO(thure): This was disconnected once before in #8818
|
|
76
|
-
// extension, please ensure the change doesn’t break web, desktop and mobile.
|
|
75
|
+
// TODO(thure): This was disconnected once before in #8818;
|
|
76
|
+
// if this should change again to support the browser extension, please ensure the change doesn’t break web, desktop and mobile.
|
|
77
77
|
const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited', ignoreDefaultKeydown: { Tab: true } });
|
|
78
78
|
|
|
79
79
|
return {
|
|
80
|
-
onKeyDown: handleKeyDown,
|
|
81
80
|
[landmarkAttr]: landmark,
|
|
82
81
|
tabIndex: 0,
|
|
82
|
+
onKeyDown: handleKeyDown,
|
|
83
83
|
...focusableGroupAttrs,
|
|
84
84
|
};
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
+
// TODO(burdon): Better way to detect software keyboard on mobile?
|
|
88
|
+
const isFullscreen = () => {
|
|
89
|
+
const isMobile = window.innerHeight <= 1000;
|
|
90
|
+
return window.visualViewport && isMobile ? window.visualViewport.height < 700 : false;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Detects if drawer should be in full mode based on:
|
|
95
|
+
* - Device is mobile (width)
|
|
96
|
+
* - Visual viewport is constrained (keyboard visible)
|
|
97
|
+
*/
|
|
98
|
+
const useDynamicDrawer = (consumerName: string) => {
|
|
99
|
+
const { drawerState, setDrawerState } = useSidebars(consumerName);
|
|
100
|
+
const drawersStateRef = useDynamicRef(drawerState);
|
|
101
|
+
|
|
102
|
+
const checkViewport = useCallback(() => {
|
|
103
|
+
if (window.visualViewport) {
|
|
104
|
+
document.documentElement.style.setProperty('--visual-viewport-height', `${window.visualViewport.height}px`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (drawersStateRef.current !== 'closed') {
|
|
108
|
+
setDrawerState(isFullscreen() ? 'full' : 'expanded');
|
|
109
|
+
}
|
|
110
|
+
}, [setDrawerState]);
|
|
111
|
+
|
|
112
|
+
// Check resize.
|
|
113
|
+
useViewportResize(checkViewport, [], 100);
|
|
114
|
+
|
|
115
|
+
// Check on window resize (for device orientation changes).
|
|
116
|
+
useEffect(() => addEventListener(window, 'resize', checkViewport), [checkViewport]);
|
|
117
|
+
|
|
118
|
+
return drawerState;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
//
|
|
122
|
+
// Context
|
|
123
|
+
//
|
|
124
|
+
|
|
125
|
+
// TODO(burdon): Define collapsed state.
|
|
126
|
+
type SidebarState = 'expanded' | 'collapsed' | 'closed';
|
|
127
|
+
type DrawerState = 'expanded' | 'full' | 'closed';
|
|
128
|
+
|
|
129
|
+
type MainContextValue = {
|
|
130
|
+
resizing: boolean;
|
|
131
|
+
|
|
132
|
+
// Navigation
|
|
133
|
+
navigationSidebarState: SidebarState;
|
|
134
|
+
setNavigationSidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
|
|
135
|
+
|
|
136
|
+
// Complementary
|
|
137
|
+
complementarySidebarState: SidebarState;
|
|
138
|
+
setComplementarySidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
|
|
139
|
+
|
|
140
|
+
// Drawer
|
|
141
|
+
drawerState: DrawerState;
|
|
142
|
+
setDrawerState: Dispatch<SetStateAction<DrawerState | undefined>>;
|
|
143
|
+
};
|
|
144
|
+
|
|
87
145
|
const [MainProvider, useMainContext] = createContext<MainContextValue>(MAIN_NAME, {
|
|
88
146
|
resizing: false,
|
|
147
|
+
|
|
89
148
|
navigationSidebarState: 'closed',
|
|
90
149
|
setNavigationSidebarState: (_nextState) => {
|
|
91
|
-
|
|
92
|
-
log.warn('Attempt to set sidebar state without initializing `MainRoot`');
|
|
150
|
+
log.warn('Not initialized');
|
|
93
151
|
},
|
|
152
|
+
|
|
94
153
|
complementarySidebarState: 'closed',
|
|
95
154
|
setComplementarySidebarState: (_nextState) => {
|
|
96
|
-
|
|
97
|
-
|
|
155
|
+
log.warn('Not initialized');
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
drawerState: 'closed',
|
|
159
|
+
setDrawerState: (_nextState) => {
|
|
160
|
+
log.warn('Not initialized');
|
|
98
161
|
},
|
|
99
162
|
});
|
|
100
163
|
|
|
101
|
-
const useSidebars = (consumerName
|
|
102
|
-
const {
|
|
103
|
-
|
|
164
|
+
const useSidebars = (consumerName: string) => {
|
|
165
|
+
const {
|
|
166
|
+
navigationSidebarState,
|
|
167
|
+
setNavigationSidebarState,
|
|
168
|
+
complementarySidebarState,
|
|
169
|
+
setComplementarySidebarState,
|
|
170
|
+
drawerState,
|
|
171
|
+
setDrawerState,
|
|
172
|
+
} = useMainContext(consumerName);
|
|
104
173
|
|
|
105
174
|
return {
|
|
106
175
|
navigationSidebarState,
|
|
@@ -112,6 +181,7 @@ const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
|
|
|
112
181
|
openNavigationSidebar: useCallback(() => setNavigationSidebarState('expanded'), []),
|
|
113
182
|
collapseNavigationSidebar: useCallback(() => setNavigationSidebarState('collapsed'), []),
|
|
114
183
|
closeNavigationSidebar: useCallback(() => setNavigationSidebarState('closed'), []),
|
|
184
|
+
|
|
115
185
|
complementarySidebarState,
|
|
116
186
|
setComplementarySidebarState,
|
|
117
187
|
toggleComplementarySidebar: useCallback(
|
|
@@ -121,27 +191,49 @@ const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
|
|
|
121
191
|
openComplementarySidebar: useCallback(() => setComplementarySidebarState('expanded'), []),
|
|
122
192
|
collapseComplementarySidebar: useCallback(() => setComplementarySidebarState('collapsed'), []),
|
|
123
193
|
closeComplementarySidebar: useCallback(() => setComplementarySidebarState('closed'), []),
|
|
194
|
+
|
|
195
|
+
drawerState,
|
|
196
|
+
setDrawerState,
|
|
197
|
+
toggleDrawer: useCallback(
|
|
198
|
+
() => setDrawerState(drawerState === 'closed' ? (isFullscreen() ? 'full' : 'expanded') : 'closed'),
|
|
199
|
+
[drawerState, setDrawerState],
|
|
200
|
+
),
|
|
201
|
+
openDrawer: useCallback(() => setDrawerState('expanded'), []),
|
|
202
|
+
closeDrawer: useCallback(() => setDrawerState('closed'), []),
|
|
124
203
|
};
|
|
125
204
|
};
|
|
126
205
|
|
|
206
|
+
//
|
|
207
|
+
// Root
|
|
208
|
+
//
|
|
209
|
+
|
|
127
210
|
type MainRootProps = PropsWithChildren<{
|
|
128
211
|
navigationSidebarState?: SidebarState;
|
|
129
212
|
defaultNavigationSidebarState?: SidebarState;
|
|
130
213
|
onNavigationSidebarStateChange?: (nextState: SidebarState) => void;
|
|
214
|
+
|
|
131
215
|
complementarySidebarState?: SidebarState;
|
|
132
216
|
defaultComplementarySidebarState?: SidebarState;
|
|
133
217
|
onComplementarySidebarStateChange?: (nextState: SidebarState) => void;
|
|
134
|
-
}>;
|
|
135
218
|
|
|
136
|
-
|
|
219
|
+
drawerState?: DrawerState;
|
|
220
|
+
defaultDrawerState?: DrawerState;
|
|
221
|
+
onDrawerStateChange?: (nextState: DrawerState) => void;
|
|
222
|
+
}>;
|
|
137
223
|
|
|
138
224
|
const MainRoot = ({
|
|
139
225
|
navigationSidebarState: propsNavigationSidebarState,
|
|
140
|
-
defaultNavigationSidebarState,
|
|
226
|
+
defaultNavigationSidebarState = 'closed',
|
|
141
227
|
onNavigationSidebarStateChange,
|
|
228
|
+
|
|
142
229
|
complementarySidebarState: propsComplementarySidebarState,
|
|
143
|
-
defaultComplementarySidebarState,
|
|
230
|
+
defaultComplementarySidebarState = 'closed',
|
|
144
231
|
onComplementarySidebarStateChange,
|
|
232
|
+
|
|
233
|
+
drawerState: propsDrawerState,
|
|
234
|
+
defaultDrawerState = 'closed',
|
|
235
|
+
onDrawerStateChange,
|
|
236
|
+
|
|
145
237
|
children,
|
|
146
238
|
...props
|
|
147
239
|
}: MainRootProps) => {
|
|
@@ -158,25 +250,29 @@ const MainRoot = ({
|
|
|
158
250
|
defaultProp: defaultComplementarySidebarState,
|
|
159
251
|
onChange: onComplementarySidebarStateChange,
|
|
160
252
|
});
|
|
253
|
+
const [drawerState = 'closed', setDrawerState] = useControllableState<DrawerState>({
|
|
254
|
+
prop: propsDrawerState,
|
|
255
|
+
defaultProp: defaultDrawerState,
|
|
256
|
+
onChange: onDrawerStateChange,
|
|
257
|
+
});
|
|
161
258
|
|
|
162
259
|
const [resizing, setResizing] = useState(false);
|
|
163
260
|
const resizeInterval = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
261
|
+
useEffect(
|
|
262
|
+
() =>
|
|
263
|
+
addEventListener(window, 'resize', () => {
|
|
264
|
+
setResizing(true);
|
|
265
|
+
if (resizeInterval.current) {
|
|
266
|
+
clearTimeout(resizeInterval.current);
|
|
267
|
+
}
|
|
164
268
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
resizeInterval.current = null;
|
|
173
|
-
}, resizeDebounce);
|
|
174
|
-
}, []);
|
|
175
|
-
|
|
176
|
-
useEffect(() => {
|
|
177
|
-
window.addEventListener('resize', handleResize);
|
|
178
|
-
return () => window.removeEventListener('resize', handleResize);
|
|
179
|
-
}, [handleResize]);
|
|
269
|
+
resizeInterval.current = setTimeout(() => {
|
|
270
|
+
setResizing(false);
|
|
271
|
+
resizeInterval.current = null;
|
|
272
|
+
}, 3_000);
|
|
273
|
+
}),
|
|
274
|
+
[],
|
|
275
|
+
);
|
|
180
276
|
|
|
181
277
|
return (
|
|
182
278
|
<MainProvider
|
|
@@ -186,6 +282,8 @@ const MainRoot = ({
|
|
|
186
282
|
setNavigationSidebarState,
|
|
187
283
|
complementarySidebarState,
|
|
188
284
|
setComplementarySidebarState,
|
|
285
|
+
drawerState,
|
|
286
|
+
setDrawerState,
|
|
189
287
|
}}
|
|
190
288
|
resizing={resizing}
|
|
191
289
|
>
|
|
@@ -196,9 +294,9 @@ const MainRoot = ({
|
|
|
196
294
|
|
|
197
295
|
MainRoot.displayName = MAIN_ROOT_NAME;
|
|
198
296
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
297
|
+
//
|
|
298
|
+
// Sidebar
|
|
299
|
+
//
|
|
202
300
|
|
|
203
301
|
type MainSidebarProps = ThemedClassName<ComponentPropsWithRef<typeof DialogContent>> & {
|
|
204
302
|
swipeToDismiss?: boolean;
|
|
@@ -219,9 +317,11 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
|
|
|
219
317
|
const { t } = useTranslation();
|
|
220
318
|
const ref = useForwardedRef(forwardedRef);
|
|
221
319
|
const noopRef = useRef(null);
|
|
320
|
+
|
|
222
321
|
useSwipeToDismiss(swipeToDismiss ? ref : noopRef, {
|
|
223
322
|
onDismiss: () => onStateChange?.('closed'),
|
|
224
323
|
});
|
|
324
|
+
|
|
225
325
|
// NOTE(thure): This is a workaround for something further down the tree grabbing focus on Escape. Adding this
|
|
226
326
|
// intervention to `Tabs.Root` or `Tabs.Tabpenel` instances is somehow ineffectual.
|
|
227
327
|
const handleKeyDown = useCallback(
|
|
@@ -236,6 +336,7 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
|
|
|
236
336
|
},
|
|
237
337
|
[props.onKeyDown],
|
|
238
338
|
);
|
|
339
|
+
|
|
239
340
|
const Root = isLg ? Primitive.div : DialogContent;
|
|
240
341
|
|
|
241
342
|
return (
|
|
@@ -243,13 +344,13 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
|
|
|
243
344
|
{!isLg && <DialogTitle className='sr-only'>{toLocalizedString(label, t)}</DialogTitle>}
|
|
244
345
|
<Root
|
|
245
346
|
{...(!isLg && { forceMount: true, tabIndex: -1, onOpenAutoFocus: onOpenAutoFocus ?? handleOpenAutoFocus })}
|
|
347
|
+
{...(state === 'closed' && { inert: true })}
|
|
246
348
|
{...props}
|
|
247
349
|
data-side={side === 'inline-end' ? 'ie' : 'is'}
|
|
248
350
|
data-state={state}
|
|
249
351
|
data-resizing={resizing ? 'true' : 'false'}
|
|
250
352
|
className={tx('main.sidebar', 'main__sidebar', {}, classNames)}
|
|
251
353
|
onKeyDownCapture={handleKeyDown}
|
|
252
|
-
{...(state === 'closed' && { inert: true })}
|
|
253
354
|
ref={ref}
|
|
254
355
|
>
|
|
255
356
|
{children}
|
|
@@ -259,6 +360,10 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
|
|
|
259
360
|
},
|
|
260
361
|
);
|
|
261
362
|
|
|
363
|
+
//
|
|
364
|
+
// Navigation Sidebar
|
|
365
|
+
//
|
|
366
|
+
|
|
262
367
|
type MainNavigationSidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
|
|
263
368
|
|
|
264
369
|
const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarProps>((props, forwardedRef) => {
|
|
@@ -280,6 +385,10 @@ const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarPr
|
|
|
280
385
|
|
|
281
386
|
MainNavigationSidebar.displayName = NAVIGATION_SIDEBAR_NAME;
|
|
282
387
|
|
|
388
|
+
//
|
|
389
|
+
// Complementary Sidebar
|
|
390
|
+
//
|
|
391
|
+
|
|
283
392
|
type MainComplementarySidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
|
|
284
393
|
|
|
285
394
|
const MainComplementarySidebar = forwardRef<HTMLDivElement, MainComplementarySidebarProps>((props, forwardedRef) => {
|
|
@@ -300,20 +409,104 @@ const MainComplementarySidebar = forwardRef<HTMLDivElement, MainComplementarySid
|
|
|
300
409
|
);
|
|
301
410
|
});
|
|
302
411
|
|
|
303
|
-
|
|
412
|
+
MainComplementarySidebar.displayName = COMPLEMENTARY_SIDEBAR_NAME;
|
|
304
413
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
414
|
+
//
|
|
415
|
+
// Drawer
|
|
416
|
+
//
|
|
417
|
+
|
|
418
|
+
type MainDrawerProps = ThemedClassName<ComponentPropsWithRef<typeof DialogContent>> & {
|
|
419
|
+
swipeToDismiss?: boolean;
|
|
420
|
+
state?: DrawerState;
|
|
421
|
+
resizing?: boolean;
|
|
422
|
+
onStateChange?: (nextState: DrawerState) => void;
|
|
423
|
+
label: Label;
|
|
309
424
|
};
|
|
310
425
|
|
|
311
|
-
const
|
|
312
|
-
(
|
|
313
|
-
|
|
426
|
+
const MainDrawer = forwardRef<HTMLDivElement, MainDrawerProps>(
|
|
427
|
+
(
|
|
428
|
+
{ classNames, children, swipeToDismiss, onOpenAutoFocus, state, resizing, onStateChange, label, ...props },
|
|
429
|
+
forwardedRef,
|
|
430
|
+
) => {
|
|
431
|
+
const [isLg] = useMediaQuery('lg');
|
|
314
432
|
const { tx } = useThemeContext();
|
|
315
|
-
const
|
|
433
|
+
const { t } = useTranslation();
|
|
434
|
+
const ref = useForwardedRef(forwardedRef);
|
|
435
|
+
const noopRef = useRef(null);
|
|
436
|
+
|
|
437
|
+
// TODO(burdon): Implement vertical swipe-to-dismiss for drawer.
|
|
438
|
+
useSwipeToDismiss(swipeToDismiss ? ref : noopRef, {
|
|
439
|
+
onDismiss: () => onStateChange?.('closed'),
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
const handleKeyDown = useCallback(
|
|
443
|
+
(event: KeyboardEvent<HTMLDivElement>) => {
|
|
444
|
+
const focusGroupParent = (event.target as HTMLElement).closest('[data-tabster]');
|
|
445
|
+
if (event.key === 'Escape' && focusGroupParent) {
|
|
446
|
+
event.preventDefault();
|
|
447
|
+
event.stopPropagation();
|
|
448
|
+
(focusGroupParent as HTMLElement).focus();
|
|
449
|
+
}
|
|
450
|
+
props.onKeyDown?.(event);
|
|
451
|
+
},
|
|
452
|
+
[props.onKeyDown],
|
|
453
|
+
);
|
|
316
454
|
|
|
455
|
+
return (
|
|
456
|
+
<Primitive.div
|
|
457
|
+
{...(state === 'closed' && { inert: true })}
|
|
458
|
+
{...(!isLg && { forceMount: true, tabIndex: -1, onOpenAutoFocus: onOpenAutoFocus ?? handleOpenAutoFocus })}
|
|
459
|
+
{...props}
|
|
460
|
+
role='region'
|
|
461
|
+
aria-label={toLocalizedString(label, t)}
|
|
462
|
+
data-state={state}
|
|
463
|
+
data-resizing={resizing ? 'true' : 'false'}
|
|
464
|
+
className={tx('main.drawer', 'main__drawer', {}, classNames)}
|
|
465
|
+
onKeyDownCapture={handleKeyDown}
|
|
466
|
+
ref={ref}
|
|
467
|
+
>
|
|
468
|
+
{children}
|
|
469
|
+
</Primitive.div>
|
|
470
|
+
);
|
|
471
|
+
},
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
type MainDrawerRootProps = Omit<MainDrawerProps, 'state' | 'resizing' | 'onStateChange'>;
|
|
475
|
+
|
|
476
|
+
const MainDrawerRoot = forwardRef<HTMLDivElement, MainDrawerRootProps>((props, forwardedRef) => {
|
|
477
|
+
const { drawerState, setDrawerState, resizing } = useMainContext(DRAWER_NAME);
|
|
478
|
+
const mover = useLandmarkMover(props.onKeyDown, '3');
|
|
479
|
+
|
|
480
|
+
return (
|
|
481
|
+
<MainDrawer
|
|
482
|
+
{...mover}
|
|
483
|
+
{...props}
|
|
484
|
+
resizing={resizing}
|
|
485
|
+
state={drawerState}
|
|
486
|
+
onStateChange={setDrawerState}
|
|
487
|
+
ref={forwardedRef}
|
|
488
|
+
/>
|
|
489
|
+
);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
MainDrawerRoot.displayName = DRAWER_NAME;
|
|
493
|
+
|
|
494
|
+
//
|
|
495
|
+
// Content
|
|
496
|
+
//
|
|
497
|
+
|
|
498
|
+
type MainContentProps = ThemedClassName<
|
|
499
|
+
ComponentPropsWithRef<typeof Primitive.div> &
|
|
500
|
+
MainStyleProps & {
|
|
501
|
+
asChild?: boolean;
|
|
502
|
+
}
|
|
503
|
+
>;
|
|
504
|
+
|
|
505
|
+
const MainContent = forwardRef<HTMLDivElement, MainContentProps>(
|
|
506
|
+
({ asChild, classNames, bounce, handlesFocus, children, role, ...props }: MainContentProps, forwardedRef) => {
|
|
507
|
+
const { navigationSidebarState, complementarySidebarState, drawerState } = useMainContext(MAIN_NAME);
|
|
508
|
+
const { tx } = useThemeContext();
|
|
509
|
+
const Root = asChild ? Slot : role ? 'div' : 'main';
|
|
317
510
|
const mover = useLandmarkMover(props.onKeyDown, '1');
|
|
318
511
|
|
|
319
512
|
return (
|
|
@@ -323,6 +516,7 @@ const MainContent = forwardRef<HTMLDivElement, MainProps>(
|
|
|
323
516
|
{...props}
|
|
324
517
|
data-sidebar-inline-start-state={navigationSidebarState}
|
|
325
518
|
data-sidebar-inline-end-state={complementarySidebarState}
|
|
519
|
+
data-drawer-state={drawerState}
|
|
326
520
|
data-handles-focus={handlesFocus}
|
|
327
521
|
className={tx('main.content', 'main', { bounce, handlesFocus }, classNames)}
|
|
328
522
|
ref={forwardedRef}
|
|
@@ -335,7 +529,7 @@ const MainContent = forwardRef<HTMLDivElement, MainProps>(
|
|
|
335
529
|
|
|
336
530
|
MainContent.displayName = MAIN_NAME;
|
|
337
531
|
|
|
338
|
-
type MainOverlayProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.div>, 'children'>>;
|
|
532
|
+
type MainOverlayProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.div>, 'children' | 'onClick'>>;
|
|
339
533
|
|
|
340
534
|
const MainOverlay = forwardRef<HTMLDivElement, MainOverlayProps>(({ classNames, ...props }, forwardedRef) => {
|
|
341
535
|
const [isLg] = useMediaQuery('lg');
|
|
@@ -344,15 +538,19 @@ const MainOverlay = forwardRef<HTMLDivElement, MainOverlayProps>(({ classNames,
|
|
|
344
538
|
const { tx } = useThemeContext();
|
|
345
539
|
return (
|
|
346
540
|
<div
|
|
541
|
+
{...props}
|
|
347
542
|
onClick={() => {
|
|
348
543
|
setNavigationSidebarState('collapsed');
|
|
349
544
|
setComplementarySidebarState('collapsed');
|
|
350
545
|
}}
|
|
351
|
-
{...props}
|
|
352
546
|
className={tx(
|
|
353
547
|
'main.overlay',
|
|
354
548
|
'main__overlay',
|
|
355
|
-
{
|
|
549
|
+
{
|
|
550
|
+
isLg,
|
|
551
|
+
inlineStartSidebarOpen: navigationSidebarState,
|
|
552
|
+
inlineEndSidebarOpen: complementarySidebarState,
|
|
553
|
+
},
|
|
356
554
|
classNames,
|
|
357
555
|
)}
|
|
358
556
|
data-state={navigationSidebarState === 'expanded' || complementarySidebarState === 'expanded' ? 'open' : 'closed'}
|
|
@@ -368,8 +566,17 @@ export const Main = {
|
|
|
368
566
|
Overlay: MainOverlay,
|
|
369
567
|
NavigationSidebar: MainNavigationSidebar,
|
|
370
568
|
ComplementarySidebar: MainComplementarySidebar,
|
|
569
|
+
Drawer: MainDrawerRoot,
|
|
371
570
|
};
|
|
372
571
|
|
|
373
|
-
export { useMainContext, useSidebars, useLandmarkMover };
|
|
572
|
+
export { useMainContext, useSidebars, useLandmarkMover, useDynamicDrawer };
|
|
374
573
|
|
|
375
|
-
export type {
|
|
574
|
+
export type {
|
|
575
|
+
MainRootProps,
|
|
576
|
+
MainContentProps,
|
|
577
|
+
MainOverlayProps,
|
|
578
|
+
MainNavigationSidebarProps,
|
|
579
|
+
MainDrawerRootProps,
|
|
580
|
+
SidebarState,
|
|
581
|
+
DrawerState,
|
|
582
|
+
};
|
|
@@ -6,7 +6,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useRef, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { withTheme } from '../../testing';
|
|
9
|
-
import { Button } from '../
|
|
9
|
+
import { Button } from '../Button';
|
|
10
10
|
|
|
11
11
|
import { DropdownMenu } from './DropdownMenu';
|
|
12
12
|
|