@wordpress/ui 0.13.1-next.v.202605131032.0 → 0.15.0
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/CHANGELOG.md +46 -1
- package/CONTRIBUTING.md +34 -0
- package/README.md +15 -0
- package/build/alert-dialog/portal.cjs.map +2 -2
- package/build/alert-dialog/types.cjs.map +1 -1
- package/build/button/button.cjs +1 -1
- package/build/button/button.cjs.map +2 -2
- package/build/card/content.cjs +1 -1
- package/build/card/content.cjs.map +2 -2
- package/build/card/full-bleed.cjs +1 -1
- package/build/card/full-bleed.cjs.map +2 -2
- package/build/card/header.cjs +1 -1
- package/build/card/header.cjs.map +2 -2
- package/build/card/root.cjs +1 -1
- package/build/card/root.cjs.map +2 -2
- package/build/collapsible-card/header.cjs.map +2 -2
- package/build/dialog/portal.cjs.map +2 -2
- package/build/dialog/types.cjs.map +1 -1
- package/build/drawer/portal.cjs.map +2 -2
- package/build/drawer/types.cjs.map +1 -1
- package/build/form/primitives/autocomplete/clear.cjs +4 -1
- package/build/form/primitives/autocomplete/clear.cjs.map +2 -2
- package/build/form/primitives/autocomplete/empty.cjs +1 -1
- package/build/form/primitives/autocomplete/empty.cjs.map +2 -2
- package/build/form/primitives/autocomplete/index.cjs +4 -1
- package/build/form/primitives/autocomplete/index.cjs.map +2 -2
- package/build/form/primitives/autocomplete/item.cjs +1 -1
- package/build/form/primitives/autocomplete/item.cjs.map +2 -2
- package/build/form/primitives/autocomplete/list-body.cjs +1 -1
- package/build/form/primitives/autocomplete/list-body.cjs.map +2 -2
- package/build/form/primitives/autocomplete/list.cjs +1 -1
- package/build/form/primitives/autocomplete/list.cjs.map +2 -2
- package/build/form/primitives/autocomplete/popup.cjs +14 -31
- package/build/form/primitives/autocomplete/popup.cjs.map +3 -3
- package/build/form/primitives/autocomplete/portal.cjs +10 -2
- package/build/form/primitives/autocomplete/portal.cjs.map +2 -2
- package/build/form/primitives/autocomplete/positioner.cjs +158 -0
- package/build/form/primitives/autocomplete/positioner.cjs.map +7 -0
- package/build/form/primitives/autocomplete/types.cjs.map +1 -1
- package/build/form/primitives/constants.cjs.map +2 -2
- package/build/form/primitives/select/index.cjs +4 -1
- package/build/form/primitives/select/index.cjs.map +2 -2
- package/build/form/primitives/select/item.cjs +1 -1
- package/build/form/primitives/select/item.cjs.map +2 -2
- package/build/form/primitives/select/popup.cjs +18 -36
- package/build/form/primitives/select/popup.cjs.map +3 -3
- package/build/form/primitives/select/portal.cjs +11 -5
- package/build/form/primitives/select/portal.cjs.map +2 -2
- package/build/form/primitives/select/positioner.cjs +159 -0
- package/build/form/primitives/select/positioner.cjs.map +7 -0
- package/build/form/primitives/select/types.cjs.map +1 -1
- package/build/icon-button/icon-button.cjs +1 -1
- package/build/icon-button/icon-button.cjs.map +2 -2
- package/build/index.cjs +7 -1
- package/build/index.cjs.map +2 -2
- package/build/popover/index.cjs +3 -0
- package/build/popover/index.cjs.map +2 -2
- package/build/popover/popup.cjs +23 -51
- package/build/popover/popup.cjs.map +3 -3
- package/build/popover/portal.cjs.map +2 -2
- package/build/popover/positioner.cjs +168 -0
- package/build/popover/positioner.cjs.map +7 -0
- package/build/popover/root.cjs.map +2 -2
- package/build/popover/types.cjs.map +1 -1
- package/build/tooltip/portal.cjs +10 -2
- package/build/tooltip/portal.cjs.map +2 -2
- package/build/tooltip/positioner.cjs.map +2 -2
- package/build/tooltip/types.cjs.map +1 -1
- package/build/utils/use-enable-wp-compat-overlay-slot.cjs +39 -0
- package/build/utils/use-enable-wp-compat-overlay-slot.cjs.map +7 -0
- package/build/utils/wp-compat-overlay-slot.cjs +177 -0
- package/build/utils/wp-compat-overlay-slot.cjs.map +7 -0
- package/build-module/alert-dialog/portal.mjs.map +2 -2
- package/build-module/button/button.mjs +1 -1
- package/build-module/button/button.mjs.map +2 -2
- package/build-module/card/content.mjs +1 -1
- package/build-module/card/content.mjs.map +2 -2
- package/build-module/card/full-bleed.mjs +1 -1
- package/build-module/card/full-bleed.mjs.map +2 -2
- package/build-module/card/header.mjs +1 -1
- package/build-module/card/header.mjs.map +2 -2
- package/build-module/card/root.mjs +1 -1
- package/build-module/card/root.mjs.map +2 -2
- package/build-module/collapsible-card/header.mjs.map +2 -2
- package/build-module/dialog/portal.mjs.map +2 -2
- package/build-module/drawer/portal.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/clear.mjs +4 -1
- package/build-module/form/primitives/autocomplete/clear.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/empty.mjs +1 -1
- package/build-module/form/primitives/autocomplete/empty.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/index.mjs +3 -1
- package/build-module/form/primitives/autocomplete/index.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/item.mjs +1 -1
- package/build-module/form/primitives/autocomplete/item.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/list-body.mjs +1 -1
- package/build-module/form/primitives/autocomplete/list-body.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/list.mjs +1 -1
- package/build-module/form/primitives/autocomplete/list.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/popup.mjs +14 -31
- package/build-module/form/primitives/autocomplete/popup.mjs.map +3 -3
- package/build-module/form/primitives/autocomplete/portal.mjs +10 -2
- package/build-module/form/primitives/autocomplete/portal.mjs.map +2 -2
- package/build-module/form/primitives/autocomplete/positioner.mjs +123 -0
- package/build-module/form/primitives/autocomplete/positioner.mjs.map +7 -0
- package/build-module/form/primitives/constants.mjs.map +2 -2
- package/build-module/form/primitives/select/index.mjs +3 -1
- package/build-module/form/primitives/select/index.mjs.map +2 -2
- package/build-module/form/primitives/select/item.mjs +1 -1
- package/build-module/form/primitives/select/item.mjs.map +2 -2
- package/build-module/form/primitives/select/popup.mjs +18 -36
- package/build-module/form/primitives/select/popup.mjs.map +3 -3
- package/build-module/form/primitives/select/portal.mjs +11 -5
- package/build-module/form/primitives/select/portal.mjs.map +2 -2
- package/build-module/form/primitives/select/positioner.mjs +124 -0
- package/build-module/form/primitives/select/positioner.mjs.map +7 -0
- package/build-module/icon-button/icon-button.mjs +1 -1
- package/build-module/icon-button/icon-button.mjs.map +2 -2
- package/build-module/index.mjs +5 -1
- package/build-module/index.mjs.map +2 -2
- package/build-module/popover/index.mjs +2 -0
- package/build-module/popover/index.mjs.map +2 -2
- package/build-module/popover/popup.mjs +23 -51
- package/build-module/popover/popup.mjs.map +3 -3
- package/build-module/popover/portal.mjs.map +2 -2
- package/build-module/popover/positioner.mjs +133 -0
- package/build-module/popover/positioner.mjs.map +7 -0
- package/build-module/popover/root.mjs.map +2 -2
- package/build-module/tooltip/portal.mjs +10 -2
- package/build-module/tooltip/portal.mjs.map +2 -2
- package/build-module/tooltip/positioner.mjs.map +2 -2
- package/build-module/utils/use-enable-wp-compat-overlay-slot.mjs +14 -0
- package/build-module/utils/use-enable-wp-compat-overlay-slot.mjs.map +7 -0
- package/build-module/utils/wp-compat-overlay-slot.mjs +148 -0
- package/build-module/utils/wp-compat-overlay-slot.mjs.map +7 -0
- package/build-types/alert-dialog/portal.d.ts +8 -5
- package/build-types/alert-dialog/portal.d.ts.map +1 -1
- package/build-types/alert-dialog/types.d.ts +2 -2
- package/build-types/alert-dialog/types.d.ts.map +1 -1
- package/build-types/badge/stories/e2e/index.story.d.ts +7 -0
- package/build-types/badge/stories/e2e/index.story.d.ts.map +1 -0
- package/build-types/button/stories/e2e/index.story.d.ts +8 -0
- package/build-types/button/stories/e2e/index.story.d.ts.map +1 -0
- package/build-types/card/full-bleed.d.ts +18 -0
- package/build-types/card/full-bleed.d.ts.map +1 -1
- package/build-types/card/stories/index.story.d.ts +23 -0
- package/build-types/card/stories/index.story.d.ts.map +1 -1
- package/build-types/collapsible-card/header.d.ts +2 -0
- package/build-types/collapsible-card/header.d.ts.map +1 -1
- package/build-types/collapsible-card/stories/index.story.d.ts +14 -0
- package/build-types/collapsible-card/stories/index.story.d.ts.map +1 -1
- package/build-types/dialog/portal.d.ts +8 -6
- package/build-types/dialog/portal.d.ts.map +1 -1
- package/build-types/dialog/types.d.ts +2 -2
- package/build-types/dialog/types.d.ts.map +1 -1
- package/build-types/drawer/portal.d.ts +8 -6
- package/build-types/drawer/portal.d.ts.map +1 -1
- package/build-types/drawer/types.d.ts +2 -2
- package/build-types/drawer/types.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/clear.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/index.d.ts +2 -1
- package/build-types/form/primitives/autocomplete/index.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/popup.d.ts +1 -0
- package/build-types/form/primitives/autocomplete/popup.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/portal.d.ts +9 -4
- package/build-types/form/primitives/autocomplete/portal.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/positioner.d.ts +12 -0
- package/build-types/form/primitives/autocomplete/positioner.d.ts.map +1 -0
- package/build-types/form/primitives/autocomplete/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/autocomplete/types.d.ts +11 -9
- package/build-types/form/primitives/autocomplete/types.d.ts.map +1 -1
- package/build-types/form/primitives/constants.d.ts +9 -4
- package/build-types/form/primitives/constants.d.ts.map +1 -1
- package/build-types/form/primitives/select/index.d.ts +2 -1
- package/build-types/form/primitives/select/index.d.ts.map +1 -1
- package/build-types/form/primitives/select/popup.d.ts +1 -0
- package/build-types/form/primitives/select/popup.d.ts.map +1 -1
- package/build-types/form/primitives/select/portal.d.ts +9 -4
- package/build-types/form/primitives/select/portal.d.ts.map +1 -1
- package/build-types/form/primitives/select/positioner.d.ts +12 -0
- package/build-types/form/primitives/select/positioner.d.ts.map +1 -0
- package/build-types/form/primitives/select/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/select/types.d.ts +11 -2
- package/build-types/form/primitives/select/types.d.ts.map +1 -1
- package/build-types/icon/stories/index.story.d.ts.map +1 -1
- package/build-types/index.d.ts +2 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/popover/index.d.ts +2 -1
- package/build-types/popover/index.d.ts.map +1 -1
- package/build-types/popover/popup.d.ts +2 -1
- package/build-types/popover/popup.d.ts.map +1 -1
- package/build-types/popover/portal.d.ts +8 -5
- package/build-types/popover/portal.d.ts.map +1 -1
- package/build-types/popover/positioner.d.ts +12 -0
- package/build-types/popover/positioner.d.ts.map +1 -0
- package/build-types/popover/root.d.ts +5 -2
- package/build-types/popover/root.d.ts.map +1 -1
- package/build-types/popover/stories/index.story.d.ts +10 -21
- package/build-types/popover/stories/index.story.d.ts.map +1 -1
- package/build-types/popover/types.d.ts +12 -3
- package/build-types/popover/types.d.ts.map +1 -1
- package/build-types/tooltip/portal.d.ts +9 -4
- package/build-types/tooltip/portal.d.ts.map +1 -1
- package/build-types/tooltip/positioner.d.ts +8 -5
- package/build-types/tooltip/positioner.d.ts.map +1 -1
- package/build-types/tooltip/types.d.ts +3 -3
- package/build-types/tooltip/types.d.ts.map +1 -1
- package/build-types/utils/test/use-enable-wp-compat-overlay-slot.test.d.ts +2 -0
- package/build-types/utils/test/use-enable-wp-compat-overlay-slot.test.d.ts.map +1 -0
- package/build-types/utils/test/wp-compat-overlay-slot.test.d.ts +2 -0
- package/build-types/utils/test/wp-compat-overlay-slot.test.d.ts.map +1 -0
- package/build-types/utils/use-enable-wp-compat-overlay-slot.d.ts +17 -0
- package/build-types/utils/use-enable-wp-compat-overlay-slot.d.ts.map +1 -0
- package/build-types/utils/wp-compat-overlay-slot.d.ts +30 -0
- package/build-types/utils/wp-compat-overlay-slot.d.ts.map +1 -0
- package/package.json +12 -12
- package/src/alert-dialog/portal.tsx +1 -4
- package/src/alert-dialog/types.ts +2 -4
- package/src/badge/stories/e2e/index.story.tsx +20 -0
- package/src/button/stories/e2e/index.story.tsx +130 -0
- package/src/button/stories/index.story.tsx +1 -1
- package/src/button/style.module.css +17 -12
- package/src/card/full-bleed.tsx +18 -0
- package/src/card/stories/index.story.tsx +115 -1
- package/src/card/style.module.css +16 -0
- package/src/card/test/index.test.tsx +18 -1
- package/src/collapsible-card/header.tsx +2 -0
- package/src/collapsible-card/stories/index.story.tsx +66 -0
- package/src/dialog/portal.tsx +1 -5
- package/src/dialog/types.ts +2 -2
- package/src/drawer/portal.tsx +1 -5
- package/src/drawer/types.ts +2 -2
- package/src/form/primitives/autocomplete/clear.tsx +10 -4
- package/src/form/primitives/autocomplete/index.ts +2 -1
- package/src/form/primitives/autocomplete/popup.tsx +17 -21
- package/src/form/primitives/autocomplete/portal.tsx +11 -5
- package/src/form/primitives/autocomplete/positioner.tsx +29 -0
- package/src/form/primitives/autocomplete/stories/index.story.tsx +1 -0
- package/src/form/primitives/autocomplete/test/index.test.tsx +219 -0
- package/src/form/primitives/autocomplete/types.ts +15 -15
- package/src/form/primitives/constants.ts +7 -4
- package/src/form/primitives/select/index.ts +2 -1
- package/src/form/primitives/select/popup.tsx +30 -34
- package/src/form/primitives/select/portal.tsx +15 -8
- package/src/form/primitives/select/positioner.tsx +33 -0
- package/src/form/primitives/select/stories/index.story.tsx +1 -0
- package/src/form/primitives/select/test/index.test.tsx +134 -0
- package/src/form/primitives/select/types.ts +12 -2
- package/src/form/select-control/test/index.test.tsx +64 -0
- package/src/icon/stories/index.story.tsx +3 -2
- package/src/icon-button/icon-button.tsx +1 -1
- package/src/icon-button/test/index.test.tsx +10 -10
- package/src/index.ts +2 -0
- package/src/popover/index.ts +12 -1
- package/src/popover/popup.tsx +28 -45
- package/src/popover/portal.tsx +1 -4
- package/src/popover/positioner.tsx +42 -0
- package/src/popover/root.tsx +5 -2
- package/src/popover/stories/index.story.tsx +85 -138
- package/src/popover/test/index.test.tsx +36 -1
- package/src/popover/types.ts +13 -15
- package/src/tabs/stories/index.story.tsx +2 -2
- package/src/tooltip/portal.tsx +11 -5
- package/src/tooltip/positioner.tsx +1 -4
- package/src/tooltip/style.module.css +1 -1
- package/src/tooltip/test/index.test.tsx +110 -0
- package/src/tooltip/types.ts +3 -5
- package/src/utils/css/item-popup.module.css +7 -4
- package/src/utils/css/wp-compat-overlay-slot.module.css +35 -0
- package/src/utils/test/use-enable-wp-compat-overlay-slot.test.tsx +74 -0
- package/src/utils/test/wp-compat-overlay-slot.test.ts +300 -0
- package/src/utils/use-enable-wp-compat-overlay-slot.ts +32 -0
- package/src/utils/wp-compat-overlay-slot.ts +129 -0
|
@@ -7,49 +7,45 @@ import {
|
|
|
7
7
|
} from '@wordpress/theme';
|
|
8
8
|
import { unlock } from '../../../lock-unlock';
|
|
9
9
|
import { Portal } from './portal';
|
|
10
|
+
import { Positioner } from './positioner';
|
|
10
11
|
import { renderSlotWithChildren } from '../../../utils/render-slot-with-children';
|
|
11
12
|
import itemPopupStyles from '../../../utils/css/item-popup.module.css';
|
|
12
|
-
import resetStyles from '../../../utils/css/resets.module.css';
|
|
13
|
-
import styles from './style.module.css';
|
|
14
13
|
import type { SelectPopupProps } from './types';
|
|
15
|
-
import { ITEM_POPUP_POSITIONER_PROPS } from '../constants';
|
|
16
14
|
|
|
17
15
|
const ThemeProvider: typeof ThemeProviderType =
|
|
18
16
|
unlock( themePrivateApis ).ThemeProvider;
|
|
19
17
|
|
|
20
18
|
export const Popup = forwardRef< HTMLDivElement, SelectPopupProps >(
|
|
21
|
-
function Popup(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<_Select.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
>
|
|
45
|
-
{ children }
|
|
46
|
-
</div>
|
|
47
|
-
</_Select.List>
|
|
48
|
-
</_Select.Popup>
|
|
49
|
-
</ThemeProvider>
|
|
50
|
-
</_Select.Positioner>
|
|
19
|
+
function Popup(
|
|
20
|
+
{ className, portal, positioner, children, ...restProps },
|
|
21
|
+
ref
|
|
22
|
+
) {
|
|
23
|
+
const popupContent = (
|
|
24
|
+
<ThemeProvider>
|
|
25
|
+
<_Select.Popup
|
|
26
|
+
ref={ ref }
|
|
27
|
+
className={ clsx( itemPopupStyles.popup, className ) }
|
|
28
|
+
{ ...restProps }
|
|
29
|
+
>
|
|
30
|
+
<_Select.List className={ itemPopupStyles.list }>
|
|
31
|
+
<div
|
|
32
|
+
className={
|
|
33
|
+
itemPopupStyles[ 'list-scrollable-container' ]
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
{ children }
|
|
37
|
+
</div>
|
|
38
|
+
</_Select.List>
|
|
39
|
+
</_Select.Popup>
|
|
40
|
+
</ThemeProvider>
|
|
51
41
|
);
|
|
52
42
|
|
|
53
|
-
|
|
43
|
+
const positionedPopup = renderSlotWithChildren(
|
|
44
|
+
positioner,
|
|
45
|
+
<Positioner />,
|
|
46
|
+
popupContent
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return renderSlotWithChildren( portal, <Portal />, positionedPopup );
|
|
54
50
|
}
|
|
55
51
|
);
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { Select as _Select } from '@base-ui/react/select';
|
|
2
2
|
import { forwardRef } from '@wordpress/element';
|
|
3
3
|
import type { PortalProps } from './types';
|
|
4
|
+
import { getWpCompatOverlaySlot } from '../../../utils/wp-compat-overlay-slot';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
* uses this component with default props.
|
|
7
|
+
* Used to apply custom portal behavior to `Select`'s listbox content.
|
|
8
|
+
* `container` defaults to the `@wordpress/ui` compat overlay slot.
|
|
9
9
|
*/
|
|
10
|
-
const Portal = forwardRef< HTMLDivElement, PortalProps >(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const Portal = forwardRef< HTMLDivElement, PortalProps >( function SelectPortal(
|
|
11
|
+
{ container, ...restProps },
|
|
12
|
+
ref
|
|
13
|
+
) {
|
|
14
|
+
return (
|
|
15
|
+
<_Select.Portal
|
|
16
|
+
container={ container ?? getWpCompatOverlaySlot() }
|
|
17
|
+
{ ...restProps }
|
|
18
|
+
ref={ ref }
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
} );
|
|
15
22
|
|
|
16
23
|
export { Portal };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Select as _Select } from '@base-ui/react/select';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import type { PositionerProps } from './types';
|
|
5
|
+
import resetStyles from '../../../utils/css/resets.module.css';
|
|
6
|
+
import styles from './style.module.css';
|
|
7
|
+
import { ITEM_POPUP_POSITIONER_PROPS } from '../constants';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Used to apply custom positioning to `Select`'s listbox content.
|
|
11
|
+
*/
|
|
12
|
+
const Positioner = forwardRef< HTMLDivElement, PositionerProps >(
|
|
13
|
+
function SelectPositioner( { className, ...props }, ref ) {
|
|
14
|
+
return (
|
|
15
|
+
<_Select.Positioner
|
|
16
|
+
{ ...ITEM_POPUP_POSITIONER_PROPS }
|
|
17
|
+
// Override Base UI's `true` default so the popup is placed
|
|
18
|
+
// relative to the trigger rather than aligned with the
|
|
19
|
+
// highlighted item. Consumers can opt back in by passing `true`.
|
|
20
|
+
alignItemWithTrigger={ false }
|
|
21
|
+
{ ...props }
|
|
22
|
+
ref={ ref }
|
|
23
|
+
className={ clsx(
|
|
24
|
+
resetStyles[ 'box-sizing' ],
|
|
25
|
+
styles.positioner,
|
|
26
|
+
className
|
|
27
|
+
) }
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export { Positioner };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { render, screen, within } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { createRef } from '@wordpress/element';
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
4
5
|
import * as Select from '../index';
|
|
6
|
+
import { useEnableWpCompatOverlaySlot } from '../../../../utils/use-enable-wp-compat-overlay-slot';
|
|
5
7
|
|
|
6
8
|
describe( 'Select', () => {
|
|
7
9
|
it( 'supports object item values', async () => {
|
|
@@ -211,4 +213,136 @@ describe( 'Select', () => {
|
|
|
211
213
|
);
|
|
212
214
|
} );
|
|
213
215
|
} );
|
|
216
|
+
|
|
217
|
+
describe( 'positioner', () => {
|
|
218
|
+
it( 'should render the custom positioner element wrapping the popup content', async () => {
|
|
219
|
+
const user = userEvent.setup();
|
|
220
|
+
|
|
221
|
+
render(
|
|
222
|
+
<Select.Root>
|
|
223
|
+
<Select.Trigger />
|
|
224
|
+
<Select.Popup
|
|
225
|
+
positioner={
|
|
226
|
+
<Select.Positioner data-testid="custom-positioner" />
|
|
227
|
+
}
|
|
228
|
+
>
|
|
229
|
+
<Select.Item value="Item 1">Item 1</Select.Item>
|
|
230
|
+
</Select.Popup>
|
|
231
|
+
</Select.Root>
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
await user.click( screen.getByRole( 'combobox' ) );
|
|
235
|
+
|
|
236
|
+
const item = await screen.findByRole( 'option', {
|
|
237
|
+
name: 'Item 1',
|
|
238
|
+
} );
|
|
239
|
+
const positioner = screen.getByTestId( 'custom-positioner' );
|
|
240
|
+
|
|
241
|
+
expect( positioner ).toContainElement( item );
|
|
242
|
+
} );
|
|
243
|
+
} );
|
|
244
|
+
|
|
245
|
+
// Slot is identified by a data attribute, not a user-facing role/text.
|
|
246
|
+
/* eslint-disable testing-library/no-node-access */
|
|
247
|
+
describe( 'wp compat overlay slot', () => {
|
|
248
|
+
const SLOT_SELECTOR = '[data-wp-compat-overlay-slot]';
|
|
249
|
+
|
|
250
|
+
// Exercises the public opt-in path rather than poking the flag.
|
|
251
|
+
function WithSlotEnabled( { children }: { children: ReactNode } ) {
|
|
252
|
+
useEnableWpCompatOverlaySlot();
|
|
253
|
+
return <>{ children }</>;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
afterEach( () => {
|
|
257
|
+
// The hook is one-way at runtime; reset explicitly between tests.
|
|
258
|
+
delete ( window as { __wpUiCompatOverlaySlotEnabled?: boolean } )
|
|
259
|
+
.__wpUiCompatOverlaySlotEnabled;
|
|
260
|
+
document
|
|
261
|
+
.querySelectorAll( SLOT_SELECTOR )
|
|
262
|
+
.forEach( ( el ) => el.remove() );
|
|
263
|
+
} );
|
|
264
|
+
|
|
265
|
+
it( 'portals the popup into the slot when the consumer opts in', async () => {
|
|
266
|
+
const user = userEvent.setup();
|
|
267
|
+
|
|
268
|
+
render(
|
|
269
|
+
<WithSlotEnabled>
|
|
270
|
+
<Select.Root>
|
|
271
|
+
<Select.Trigger />
|
|
272
|
+
<Select.Popup>
|
|
273
|
+
<Select.Item value="Item 1">Item 1</Select.Item>
|
|
274
|
+
</Select.Popup>
|
|
275
|
+
</Select.Root>
|
|
276
|
+
</WithSlotEnabled>
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
await user.click( screen.getByRole( 'combobox' ) );
|
|
280
|
+
|
|
281
|
+
const item = await screen.findByRole( 'option', {
|
|
282
|
+
name: 'Item 1',
|
|
283
|
+
} );
|
|
284
|
+
expect( item ).toBeVisible();
|
|
285
|
+
|
|
286
|
+
const slot = document.querySelector( SLOT_SELECTOR );
|
|
287
|
+
expect( slot ).not.toBeNull();
|
|
288
|
+
expect( slot ).toContainElement( item );
|
|
289
|
+
} );
|
|
290
|
+
|
|
291
|
+
it( 'does not create a slot when the consumer has not opted in (dormant default)', async () => {
|
|
292
|
+
const user = userEvent.setup();
|
|
293
|
+
|
|
294
|
+
render(
|
|
295
|
+
<Select.Root>
|
|
296
|
+
<Select.Trigger />
|
|
297
|
+
<Select.Popup>
|
|
298
|
+
<Select.Item value="Item 1">Item 1</Select.Item>
|
|
299
|
+
</Select.Popup>
|
|
300
|
+
</Select.Root>
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
await user.click( screen.getByRole( 'combobox' ) );
|
|
304
|
+
|
|
305
|
+
const item = await screen.findByRole( 'option', {
|
|
306
|
+
name: 'Item 1',
|
|
307
|
+
} );
|
|
308
|
+
expect( item ).toBeVisible();
|
|
309
|
+
|
|
310
|
+
expect( document.querySelector( SLOT_SELECTOR ) ).toBeNull();
|
|
311
|
+
} );
|
|
312
|
+
|
|
313
|
+
it( 'lets a caller-supplied portal container override the slot', async () => {
|
|
314
|
+
const user = userEvent.setup();
|
|
315
|
+
const containerRef = createRef< HTMLDivElement >();
|
|
316
|
+
|
|
317
|
+
render(
|
|
318
|
+
<WithSlotEnabled>
|
|
319
|
+
<Select.Root>
|
|
320
|
+
<Select.Trigger />
|
|
321
|
+
<div
|
|
322
|
+
ref={ containerRef }
|
|
323
|
+
data-testid="custom-container"
|
|
324
|
+
/>
|
|
325
|
+
<Select.Popup
|
|
326
|
+
portal={
|
|
327
|
+
<Select.Portal container={ containerRef } />
|
|
328
|
+
}
|
|
329
|
+
>
|
|
330
|
+
<Select.Item value="Item 1">Item 1</Select.Item>
|
|
331
|
+
</Select.Popup>
|
|
332
|
+
</Select.Root>
|
|
333
|
+
</WithSlotEnabled>
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
await user.click( screen.getByRole( 'combobox' ) );
|
|
337
|
+
|
|
338
|
+
const item = await screen.findByRole( 'option', {
|
|
339
|
+
name: 'Item 1',
|
|
340
|
+
} );
|
|
341
|
+
expect( item ).toBeVisible();
|
|
342
|
+
expect( screen.getByTestId( 'custom-container' ) ).toContainElement(
|
|
343
|
+
item
|
|
344
|
+
);
|
|
345
|
+
} );
|
|
346
|
+
} );
|
|
347
|
+
/* eslint-enable testing-library/no-node-access */
|
|
214
348
|
} );
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Select as _Select } from '@base-ui/react/select';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
3
|
|
|
4
4
|
import type { ComponentProps } from '../../../utils/types';
|
|
5
5
|
import type { InputLayoutProps } from '../input-layout/types';
|
|
6
6
|
|
|
7
|
-
export type PortalProps =
|
|
7
|
+
export type PortalProps = ComponentProps< typeof _Select.Portal >;
|
|
8
|
+
|
|
9
|
+
export type PositionerProps = ComponentProps< typeof _Select.Positioner >;
|
|
8
10
|
|
|
9
11
|
// The second type parameter is the `multiple` flag (currently disabled).
|
|
10
12
|
export type SelectRootProps< Value = unknown > = Omit<
|
|
@@ -54,6 +56,14 @@ export type SelectPopupProps = ComponentProps< typeof _Select.Popup > & {
|
|
|
54
56
|
* be ignored.
|
|
55
57
|
*/
|
|
56
58
|
portal?: ReactElement< Omit< PortalProps, 'children' > >;
|
|
59
|
+
/**
|
|
60
|
+
* Optional positioner element, typically `<Select.Positioner />` with
|
|
61
|
+
* custom positioning props (`side`, `align`, `sideOffset`, collision
|
|
62
|
+
* settings, etc.). When omitted, `Select.Popup` uses `Select.Positioner`
|
|
63
|
+
* with default props. Do not pass `children` on the positioner element;
|
|
64
|
+
* they would be ignored.
|
|
65
|
+
*/
|
|
66
|
+
positioner?: ReactElement< Omit< PositionerProps, 'children' > >;
|
|
57
67
|
};
|
|
58
68
|
|
|
59
69
|
export type SelectItemProps = Omit<
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { act, render, screen } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { createRef } from '@wordpress/element';
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
4
5
|
import { SelectControl } from '../index';
|
|
6
|
+
import { useEnableWpCompatOverlaySlot } from '../../../utils/use-enable-wp-compat-overlay-slot';
|
|
5
7
|
|
|
6
8
|
describe( 'SelectControl', () => {
|
|
7
9
|
const mockItems = [
|
|
@@ -193,4 +195,66 @@ describe( 'SelectControl', () => {
|
|
|
193
195
|
expect( formData.get( 'country' ) ).toBe( '' );
|
|
194
196
|
} );
|
|
195
197
|
} );
|
|
198
|
+
|
|
199
|
+
// Slot is identified by a data attribute, not a user-facing role/text.
|
|
200
|
+
/* eslint-disable testing-library/no-node-access */
|
|
201
|
+
describe( 'wp compat overlay slot', () => {
|
|
202
|
+
const SLOT_SELECTOR = '[data-wp-compat-overlay-slot]';
|
|
203
|
+
|
|
204
|
+
// Exercises the public opt-in path rather than poking the flag.
|
|
205
|
+
function WithSlotEnabled( { children }: { children: ReactNode } ) {
|
|
206
|
+
useEnableWpCompatOverlaySlot();
|
|
207
|
+
return <>{ children }</>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
afterEach( () => {
|
|
211
|
+
// The hook is one-way at runtime; reset explicitly between tests.
|
|
212
|
+
delete ( window as { __wpUiCompatOverlaySlotEnabled?: boolean } )
|
|
213
|
+
.__wpUiCompatOverlaySlotEnabled;
|
|
214
|
+
document
|
|
215
|
+
.querySelectorAll( SLOT_SELECTOR )
|
|
216
|
+
.forEach( ( el ) => el.remove() );
|
|
217
|
+
} );
|
|
218
|
+
|
|
219
|
+
it( 'portals the popup into the slot when the consumer opts in', async () => {
|
|
220
|
+
const user = userEvent.setup();
|
|
221
|
+
|
|
222
|
+
render(
|
|
223
|
+
<WithSlotEnabled>
|
|
224
|
+
<SelectControl label="Country" items={ mockItems } />
|
|
225
|
+
</WithSlotEnabled>
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
await user.click(
|
|
229
|
+
screen.getByRole( 'combobox', { name: 'Country' } )
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const option = await screen.findByRole( 'option', {
|
|
233
|
+
name: 'Option 1',
|
|
234
|
+
} );
|
|
235
|
+
expect( option ).toBeVisible();
|
|
236
|
+
|
|
237
|
+
const slot = document.querySelector( SLOT_SELECTOR );
|
|
238
|
+
expect( slot ).not.toBeNull();
|
|
239
|
+
expect( slot ).toContainElement( option );
|
|
240
|
+
} );
|
|
241
|
+
|
|
242
|
+
it( 'does not create a slot when the consumer has not opted in (dormant default)', async () => {
|
|
243
|
+
const user = userEvent.setup();
|
|
244
|
+
|
|
245
|
+
render( <SelectControl label="Country" items={ mockItems } /> );
|
|
246
|
+
|
|
247
|
+
await user.click(
|
|
248
|
+
screen.getByRole( 'combobox', { name: 'Country' } )
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const option = await screen.findByRole( 'option', {
|
|
252
|
+
name: 'Option 1',
|
|
253
|
+
} );
|
|
254
|
+
expect( option ).toBeVisible();
|
|
255
|
+
|
|
256
|
+
expect( document.querySelector( SLOT_SELECTOR ) ).toBeNull();
|
|
257
|
+
} );
|
|
258
|
+
} );
|
|
259
|
+
/* eslint-enable testing-library/no-node-access */
|
|
196
260
|
} );
|
|
@@ -5,6 +5,7 @@ import { Icon } from '../index';
|
|
|
5
5
|
const meta: Meta< typeof Icon > = {
|
|
6
6
|
title: 'Design System/Components/Icon',
|
|
7
7
|
component: Icon,
|
|
8
|
+
tags: [ 'manifest' ],
|
|
8
9
|
decorators: [
|
|
9
10
|
( Story ) => {
|
|
10
11
|
return (
|
|
@@ -20,9 +21,9 @@ const meta: Meta< typeof Icon > = {
|
|
|
20
21
|
],
|
|
21
22
|
parameters: {
|
|
22
23
|
componentStatus: {
|
|
23
|
-
status: '
|
|
24
|
+
status: 'recommended',
|
|
24
25
|
whereUsed: 'global',
|
|
25
|
-
notes: '
|
|
26
|
+
notes: 'Prefer this component over the `Icon` component from `@wordpress/components` or `@wordpress/icons`.',
|
|
26
27
|
},
|
|
27
28
|
},
|
|
28
29
|
};
|
|
@@ -37,7 +37,14 @@ describe( 'IconButton', () => {
|
|
|
37
37
|
it( 'does not show tooltip when truly disabled', async () => {
|
|
38
38
|
const user = userEvent.setup();
|
|
39
39
|
|
|
40
|
-
render(
|
|
40
|
+
render(
|
|
41
|
+
<IconButton
|
|
42
|
+
label="Save"
|
|
43
|
+
icon={ <svg /> }
|
|
44
|
+
disabled
|
|
45
|
+
focusableWhenDisabled={ false }
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
41
48
|
|
|
42
49
|
const button = screen.getByRole( 'button', { name: 'Save' } );
|
|
43
50
|
await user.hover( button );
|
|
@@ -45,17 +52,10 @@ describe( 'IconButton', () => {
|
|
|
45
52
|
expect( screen.queryByText( 'Save' ) ).not.toBeInTheDocument();
|
|
46
53
|
} );
|
|
47
54
|
|
|
48
|
-
it( 'shows tooltip when
|
|
55
|
+
it( 'shows tooltip when disabled by default', async () => {
|
|
49
56
|
const user = userEvent.setup();
|
|
50
57
|
|
|
51
|
-
render(
|
|
52
|
-
<IconButton
|
|
53
|
-
label="Save"
|
|
54
|
-
icon={ <svg /> }
|
|
55
|
-
disabled
|
|
56
|
-
focusableWhenDisabled
|
|
57
|
-
/>
|
|
58
|
-
);
|
|
58
|
+
render( <IconButton label="Save" icon={ <svg /> } disabled /> );
|
|
59
59
|
|
|
60
60
|
const button = screen.getByRole( 'button', { name: 'Save' } );
|
|
61
61
|
await user.hover( button );
|
package/src/index.ts
CHANGED
|
@@ -17,4 +17,6 @@ export * from './stack';
|
|
|
17
17
|
export * as Tabs from './tabs';
|
|
18
18
|
export * from './text';
|
|
19
19
|
export * as Tooltip from './tooltip';
|
|
20
|
+
export { getWpCompatOverlaySlot } from './utils/wp-compat-overlay-slot';
|
|
21
|
+
export { useEnableWpCompatOverlaySlot } from './utils/use-enable-wp-compat-overlay-slot';
|
|
20
22
|
export * from './visually-hidden';
|
package/src/popover/index.ts
CHANGED
|
@@ -3,8 +3,19 @@ import { Close } from './close';
|
|
|
3
3
|
import { Description } from './description';
|
|
4
4
|
import { Popup } from './popup';
|
|
5
5
|
import { Portal } from './portal';
|
|
6
|
+
import { Positioner } from './positioner';
|
|
6
7
|
import { Root } from './root';
|
|
7
8
|
import { Title } from './title';
|
|
8
9
|
import { Trigger } from './trigger';
|
|
9
10
|
|
|
10
|
-
export {
|
|
11
|
+
export {
|
|
12
|
+
Arrow,
|
|
13
|
+
Close,
|
|
14
|
+
Description,
|
|
15
|
+
Popup,
|
|
16
|
+
Portal,
|
|
17
|
+
Positioner,
|
|
18
|
+
Root,
|
|
19
|
+
Title,
|
|
20
|
+
Trigger,
|
|
21
|
+
};
|
package/src/popover/popup.tsx
CHANGED
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
privateApis as themePrivateApis,
|
|
8
8
|
} from '@wordpress/theme';
|
|
9
9
|
import { unlock } from '../lock-unlock';
|
|
10
|
-
import resetStyles from '../utils/css/resets.module.css';
|
|
11
10
|
import { useDeprioritizedInitialFocus } from '../utils/use-deprioritized-initial-focus';
|
|
12
11
|
import { renderSlotWithChildren } from '../utils/render-slot-with-children';
|
|
13
12
|
import { PopoverValidationProvider } from './context';
|
|
14
13
|
import { Portal } from './portal';
|
|
14
|
+
import { Positioner } from './positioner';
|
|
15
15
|
import styles from './style.module.css';
|
|
16
16
|
import type { PopupProps } from './types';
|
|
17
17
|
|
|
@@ -26,27 +26,18 @@ const CLOSE_ATTR = 'data-wp-ui-popover-close';
|
|
|
26
26
|
* Handles portal rendering, positioning relative to the anchor, collision
|
|
27
27
|
* avoidance, focus management, and optional backdrop. Use
|
|
28
28
|
* `portal={ <Popover.Portal container={ ... } /> }` for cross-document
|
|
29
|
-
* scenarios such as iframes.
|
|
29
|
+
* scenarios such as iframes, and `positioner={ <Popover.Positioner … /> }`
|
|
30
|
+
* to customize placement.
|
|
30
31
|
*/
|
|
31
32
|
const Popup = forwardRef< HTMLDivElement, PopupProps >( function PopoverPopup(
|
|
32
33
|
{
|
|
33
|
-
align = 'center',
|
|
34
|
-
alignOffset,
|
|
35
|
-
anchor,
|
|
36
|
-
// Matches the popup's border-radius (--wpds-border-radius-md).
|
|
37
|
-
arrowPadding = 8,
|
|
38
34
|
backdrop = false,
|
|
39
35
|
children,
|
|
40
36
|
className,
|
|
41
|
-
collisionAvoidance,
|
|
42
|
-
collisionBoundary,
|
|
43
|
-
collisionPadding,
|
|
44
37
|
portal,
|
|
38
|
+
positioner,
|
|
45
39
|
finalFocus,
|
|
46
40
|
initialFocus,
|
|
47
|
-
side = 'bottom',
|
|
48
|
-
sideOffset = 8,
|
|
49
|
-
sticky,
|
|
50
41
|
variant = 'default',
|
|
51
42
|
...props
|
|
52
43
|
},
|
|
@@ -62,43 +53,35 @@ const Popup = forwardRef< HTMLDivElement, PopupProps >( function PopoverPopup(
|
|
|
62
53
|
<_Popover.Backdrop className={ styles.backdrop } />
|
|
63
54
|
) : null;
|
|
64
55
|
|
|
65
|
-
const
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
{ ...props }
|
|
89
|
-
>
|
|
90
|
-
<PopoverValidationProvider>
|
|
91
|
-
{ children }
|
|
92
|
-
</PopoverValidationProvider>
|
|
93
|
-
</_Popover.Popup>
|
|
94
|
-
</ThemeProvider>
|
|
95
|
-
</_Popover.Positioner>
|
|
56
|
+
const popupContent = (
|
|
57
|
+
<ThemeProvider>
|
|
58
|
+
<_Popover.Popup
|
|
59
|
+
ref={ mergedPopupRef }
|
|
60
|
+
initialFocus={ resolvedInitialFocus }
|
|
61
|
+
finalFocus={ finalFocus }
|
|
62
|
+
className={ clsx(
|
|
63
|
+
variant !== 'unstyled' && styles.popup,
|
|
64
|
+
className
|
|
65
|
+
) }
|
|
66
|
+
{ ...props }
|
|
67
|
+
>
|
|
68
|
+
<PopoverValidationProvider>
|
|
69
|
+
{ children }
|
|
70
|
+
</PopoverValidationProvider>
|
|
71
|
+
</_Popover.Popup>
|
|
72
|
+
</ThemeProvider>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const positionedPopup = renderSlotWithChildren(
|
|
76
|
+
positioner,
|
|
77
|
+
<Positioner />,
|
|
78
|
+
popupContent
|
|
96
79
|
);
|
|
97
80
|
|
|
98
81
|
const portalChildren = (
|
|
99
82
|
<>
|
|
100
83
|
{ backdropElement }
|
|
101
|
-
{
|
|
84
|
+
{ positionedPopup }
|
|
102
85
|
</>
|
|
103
86
|
);
|
|
104
87
|
|
package/src/popover/portal.tsx
CHANGED
|
@@ -3,10 +3,7 @@ import { forwardRef } from '@wordpress/element';
|
|
|
3
3
|
import type { PortalProps } from './types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* `Popover.Popup`'s `portal` prop (for example `container` for
|
|
8
|
-
* cross-document rendering). When `portal` is omitted, `Popover.Popup` uses
|
|
9
|
-
* this component with default props.
|
|
6
|
+
* Used to apply custom portal behavior to `Popover`'s floating content.
|
|
10
7
|
*/
|
|
11
8
|
const Portal = forwardRef< HTMLDivElement, PortalProps >(
|
|
12
9
|
function PopoverPortal( props, ref ) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import type { PositionerProps } from './types';
|
|
5
|
+
import resetStyles from '../utils/css/resets.module.css';
|
|
6
|
+
import styles from './style.module.css';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Used to apply custom positioning to `Popover`'s floating content.
|
|
10
|
+
*/
|
|
11
|
+
const Positioner = forwardRef< HTMLDivElement, PositionerProps >(
|
|
12
|
+
function PopoverPositioner(
|
|
13
|
+
{
|
|
14
|
+
align = 'center',
|
|
15
|
+
// Matches the popup's border-radius (--wpds-border-radius-md).
|
|
16
|
+
arrowPadding = 8,
|
|
17
|
+
className,
|
|
18
|
+
side = 'bottom',
|
|
19
|
+
sideOffset = 8,
|
|
20
|
+
...props
|
|
21
|
+
},
|
|
22
|
+
ref
|
|
23
|
+
) {
|
|
24
|
+
return (
|
|
25
|
+
<_Popover.Positioner
|
|
26
|
+
ref={ ref }
|
|
27
|
+
align={ align }
|
|
28
|
+
arrowPadding={ arrowPadding }
|
|
29
|
+
side={ side }
|
|
30
|
+
sideOffset={ sideOffset }
|
|
31
|
+
{ ...props }
|
|
32
|
+
className={ clsx(
|
|
33
|
+
resetStyles[ 'box-sizing' ],
|
|
34
|
+
styles.positioner,
|
|
35
|
+
className
|
|
36
|
+
) }
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export { Positioner };
|