@box/blueprint-web 14.13.0 → 14.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/dist/lib-esm/avatar/avatar.module.js +1 -1
- package/dist/lib-esm/index.css +410 -114
- package/dist/lib-esm/index.d.ts +1 -0
- package/dist/lib-esm/index.js +1 -0
- package/dist/lib-esm/primitives/menu-combobox/index.d.ts +27 -0
- package/dist/lib-esm/primitives/menu-combobox/index.js +21 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-content.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-content.js +61 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-context.d.ts +8 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-context.js +13 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-empty.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-empty.js +27 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-header.d.ts +18 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-header.js +80 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-item.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-item.js +31 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-list.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-list.js +23 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-root.d.ts +6 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-root.js +51 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-search.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-search.js +44 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-trigger.d.ts +3 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox-trigger.js +28 -0
- package/dist/lib-esm/primitives/menu-combobox/menu-combobox.module.js +4 -0
- package/dist/lib-esm/primitives/menu-combobox/types.d.ts +36 -0
- package/dist/lib-esm/text/text.module.js +1 -1
- package/package.json +3 -3
package/dist/lib-esm/index.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export * from './primitives/dropdown-menu';
|
|
|
51
51
|
export * from './primitives/icon-button';
|
|
52
52
|
export * from './primitives/inline-error/inline-error';
|
|
53
53
|
export * from './primitives/link';
|
|
54
|
+
export * from './primitives/menu-combobox';
|
|
54
55
|
export * from './primitives/notification';
|
|
55
56
|
export * from './primitives/page-header';
|
|
56
57
|
export * from './primitives/popover';
|
package/dist/lib-esm/index.js
CHANGED
|
@@ -69,6 +69,7 @@ export { DropdownMenu } from './primitives/dropdown-menu/index.js';
|
|
|
69
69
|
export { IconButton } from './primitives/icon-button/icon-button.js';
|
|
70
70
|
export { InlineError } from './primitives/inline-error/inline-error.js';
|
|
71
71
|
export { Link } from './primitives/link/link.js';
|
|
72
|
+
export { MenuCombobox } from './primitives/menu-combobox/index.js';
|
|
72
73
|
export { Notification } from './primitives/notification/index.js';
|
|
73
74
|
export { PageHeader } from './primitives/page-header/page-header.js';
|
|
74
75
|
export { Popover } from './primitives/popover/index.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const MenuCombobox: {
|
|
2
|
+
Root: {
|
|
3
|
+
(props: import("./types").MenuComboboxRootProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
displayName: string;
|
|
5
|
+
};
|
|
6
|
+
Trigger: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxTriggerProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
Content: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxContentProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
8
|
+
Header: (({ children, className, ...rest }: import("react").HTMLAttributes<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element) & {
|
|
9
|
+
MenuCloseButton: import("react").ForwardRefExoticComponent<Omit<import("./menu-combobox-header").MenuComboboxHeaderMenuCloseButtonProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
10
|
+
TextContent: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
11
|
+
subtitle?: string;
|
|
12
|
+
title: string;
|
|
13
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
14
|
+
};
|
|
15
|
+
Search: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxSearchProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
16
|
+
List: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxListProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
17
|
+
Item: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxItemProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
18
|
+
Empty: import("react").ForwardRefExoticComponent<Omit<import("./types").MenuComboboxEmptyProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
19
|
+
};
|
|
20
|
+
export type { MenuComboboxHeaderMenuCloseButtonProps, MenuComboboxHeaderTextContentProps, } from './menu-combobox-header';
|
|
21
|
+
export type { MenuComboboxContentProps } from './types';
|
|
22
|
+
export type { MenuComboboxEmptyProps } from './types';
|
|
23
|
+
export type { MenuComboboxItemProps } from './types';
|
|
24
|
+
export type { MenuComboboxListProps } from './types';
|
|
25
|
+
export type { MenuComboboxRootProps } from './types';
|
|
26
|
+
export type { MenuComboboxSearchProps } from './types';
|
|
27
|
+
export type { MenuComboboxTriggerProps } from './types';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MenuComboboxContent } from './menu-combobox-content.js';
|
|
2
|
+
import { MenuComboboxEmpty } from './menu-combobox-empty.js';
|
|
3
|
+
import { MenuComboboxHeader } from './menu-combobox-header.js';
|
|
4
|
+
import { MenuComboboxItem } from './menu-combobox-item.js';
|
|
5
|
+
import { MenuComboboxList } from './menu-combobox-list.js';
|
|
6
|
+
import { MenuComboboxRoot } from './menu-combobox-root.js';
|
|
7
|
+
import { MenuComboboxSearch } from './menu-combobox-search.js';
|
|
8
|
+
import { MenuComboboxTrigger } from './menu-combobox-trigger.js';
|
|
9
|
+
|
|
10
|
+
const MenuCombobox = {
|
|
11
|
+
Root: MenuComboboxRoot,
|
|
12
|
+
Trigger: MenuComboboxTrigger,
|
|
13
|
+
Content: MenuComboboxContent,
|
|
14
|
+
Header: MenuComboboxHeader,
|
|
15
|
+
Search: MenuComboboxSearch,
|
|
16
|
+
List: MenuComboboxList,
|
|
17
|
+
Item: MenuComboboxItem,
|
|
18
|
+
Empty: MenuComboboxEmpty
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { MenuCombobox };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type MenuComboboxContentProps } from './types';
|
|
2
|
+
/** Menu panel that contains the search input and items. */
|
|
3
|
+
export declare const MenuComboboxContent: import("react").ForwardRefExoticComponent<Omit<MenuComboboxContentProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Space2 } from '@box/blueprint-web-assets/tokens/px-tokens';
|
|
3
|
+
import { Menu } from '@ariakit/react';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { forwardRef, useMemo } from 'react';
|
|
6
|
+
import { useBlueprintModernization } from '../../blueprint-modernization-context/useBlueprintModernization.js';
|
|
7
|
+
import { useMenuComboboxContext } from './menu-combobox-context.js';
|
|
8
|
+
import styles from './menu-combobox.module.js';
|
|
9
|
+
|
|
10
|
+
const GUTTER = parseInt(Space2, 10);
|
|
11
|
+
/* Force-fill the viewport when fullscreen; `pointerEvents: 'none'` lets clicks reach the
|
|
12
|
+
* trigger while closed, the inner content re-enables them via SCSS. */
|
|
13
|
+
const FULLSCREEN_WRAPPER_STYLE = {
|
|
14
|
+
position: 'fixed',
|
|
15
|
+
top: 0,
|
|
16
|
+
left: 0,
|
|
17
|
+
right: 0,
|
|
18
|
+
bottom: 0,
|
|
19
|
+
width: '100vw',
|
|
20
|
+
height: '100dvh',
|
|
21
|
+
transform: 'none',
|
|
22
|
+
pointerEvents: 'none'
|
|
23
|
+
};
|
|
24
|
+
const noopUpdatePosition = () => {
|
|
25
|
+
/* Skip Ariakit positioning when fullscreen so it doesn't override the wrapper style. */
|
|
26
|
+
};
|
|
27
|
+
/** Menu panel that contains the search input and items. */
|
|
28
|
+
const MenuComboboxContent = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
29
|
+
const {
|
|
30
|
+
children,
|
|
31
|
+
className,
|
|
32
|
+
portalElement,
|
|
33
|
+
...rest
|
|
34
|
+
} = props;
|
|
35
|
+
const {
|
|
36
|
+
isFullScreenEnabled
|
|
37
|
+
} = useMenuComboboxContext();
|
|
38
|
+
const {
|
|
39
|
+
enableModernizedComponents
|
|
40
|
+
} = useBlueprintModernization();
|
|
41
|
+
const gutter = isFullScreenEnabled ? 0 : GUTTER;
|
|
42
|
+
const wrapperProps = useMemo(() => isFullScreenEnabled ? {
|
|
43
|
+
style: FULLSCREEN_WRAPPER_STYLE
|
|
44
|
+
} : undefined, [isFullScreenEnabled]);
|
|
45
|
+
return jsx(Menu, {
|
|
46
|
+
ref: forwardedRef,
|
|
47
|
+
portal: true,
|
|
48
|
+
portalElement: portalElement,
|
|
49
|
+
gutter: gutter,
|
|
50
|
+
wrapperProps: wrapperProps,
|
|
51
|
+
updatePosition: isFullScreenEnabled ? noopUpdatePosition : undefined,
|
|
52
|
+
...rest,
|
|
53
|
+
className: clsx(styles.content, className),
|
|
54
|
+
"data-menu-fullscreen": isFullScreenEnabled ? 'true' : 'false',
|
|
55
|
+
"data-modern": enableModernizedComponents ? 'true' : 'false',
|
|
56
|
+
children: children
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
MenuComboboxContent.displayName = 'MenuComboboxContent';
|
|
60
|
+
|
|
61
|
+
export { MenuComboboxContent };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type MenuComboboxContextValue = {
|
|
2
|
+
searchPlaceholder: string | undefined;
|
|
3
|
+
isFullScreenEnabled: boolean;
|
|
4
|
+
/** Imperatively close the menu. */
|
|
5
|
+
setOpen: (open: boolean) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const MenuComboboxContext: import("react").Context<MenuComboboxContextValue>;
|
|
8
|
+
export declare const useMenuComboboxContext: () => MenuComboboxContextValue;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useContext, createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const defaultValue = {
|
|
4
|
+
searchPlaceholder: undefined,
|
|
5
|
+
isFullScreenEnabled: false,
|
|
6
|
+
setOpen: () => {
|
|
7
|
+
/* no-op outside of a MenuCombobox.Root */
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const MenuComboboxContext = /*#__PURE__*/createContext(defaultValue);
|
|
11
|
+
const useMenuComboboxContext = () => useContext(MenuComboboxContext);
|
|
12
|
+
|
|
13
|
+
export { MenuComboboxContext, useMenuComboboxContext };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type MenuComboboxEmptyProps } from './types';
|
|
2
|
+
/** Shown when the filtered list has no matches. */
|
|
3
|
+
export declare const MenuComboboxEmpty: import("react").ForwardRefExoticComponent<Omit<MenuComboboxEmptyProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { useBlueprintModernization } from '../../blueprint-modernization-context/useBlueprintModernization.js';
|
|
5
|
+
import styles from './menu-combobox.module.js';
|
|
6
|
+
|
|
7
|
+
/** Shown when the filtered list has no matches. */
|
|
8
|
+
const MenuComboboxEmpty = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
9
|
+
const {
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
...rest
|
|
13
|
+
} = props;
|
|
14
|
+
const {
|
|
15
|
+
enableModernizedComponents
|
|
16
|
+
} = useBlueprintModernization();
|
|
17
|
+
return jsx("div", {
|
|
18
|
+
ref: forwardedRef,
|
|
19
|
+
role: "status",
|
|
20
|
+
...rest,
|
|
21
|
+
className: clsx(styles.empty, enableModernizedComponents && styles.emptyModern, className),
|
|
22
|
+
children: children
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
MenuComboboxEmpty.displayName = 'MenuComboboxEmpty';
|
|
26
|
+
|
|
27
|
+
export { MenuComboboxEmpty };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type HTMLAttributes } from 'react';
|
|
2
|
+
import { type IconButtonProps } from '../icon-button';
|
|
3
|
+
export type MenuComboboxHeaderMenuCloseButtonProps = Omit<IconButtonProps, 'icon' | 'variant' | 'size'>;
|
|
4
|
+
export type MenuComboboxHeaderTextContentProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
|
|
5
|
+
/** Secondary line below the title. */
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
/** Primary line. */
|
|
8
|
+
title: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const MenuComboboxHeader: (({ children, className, ...rest }: HTMLAttributes<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element) & {
|
|
11
|
+
MenuCloseButton: import("react").ForwardRefExoticComponent<Omit<MenuComboboxHeaderMenuCloseButtonProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
12
|
+
TextContent: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
13
|
+
/** Secondary line below the title. */
|
|
14
|
+
subtitle?: string;
|
|
15
|
+
/** Primary line. */
|
|
16
|
+
title: string;
|
|
17
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { XMark as XMark$1 } from '@box/blueprint-web-assets/icons/Fill';
|
|
3
|
+
import { XMark } from '@box/blueprint-web-assets/icons/Medium';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { forwardRef, useCallback } from 'react';
|
|
6
|
+
import { useBlueprintModernization } from '../../blueprint-modernization-context/useBlueprintModernization.js';
|
|
7
|
+
import { IconButton } from '../icon-button/icon-button.js';
|
|
8
|
+
import { Text } from '../../text/text.js';
|
|
9
|
+
import { composeEventHandlers } from '../../utils/composeEventHandlers.js';
|
|
10
|
+
import { useMenuComboboxContext } from './menu-combobox-context.js';
|
|
11
|
+
import styles from './menu-combobox.module.js';
|
|
12
|
+
|
|
13
|
+
const MenuCloseButton = /*#__PURE__*/forwardRef(({
|
|
14
|
+
onClick,
|
|
15
|
+
className,
|
|
16
|
+
...rest
|
|
17
|
+
}, ref) => {
|
|
18
|
+
const {
|
|
19
|
+
setOpen
|
|
20
|
+
} = useMenuComboboxContext();
|
|
21
|
+
const {
|
|
22
|
+
enableModernizedComponents
|
|
23
|
+
} = useBlueprintModernization();
|
|
24
|
+
const handleCloseClick = useCallback(() => {
|
|
25
|
+
setOpen(false);
|
|
26
|
+
}, [setOpen]);
|
|
27
|
+
const CloseIcon = enableModernizedComponents ? XMark : XMark$1;
|
|
28
|
+
return jsx(IconButton, {
|
|
29
|
+
ref: ref,
|
|
30
|
+
...rest,
|
|
31
|
+
className: clsx(styles.menuCloseButton, className),
|
|
32
|
+
icon: CloseIcon,
|
|
33
|
+
onClick: composeEventHandlers(handleCloseClick, onClick),
|
|
34
|
+
variant: "small-utility"
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
MenuCloseButton.displayName = 'MenuComboboxHeaderMenuCloseButton';
|
|
38
|
+
const TextContent = /*#__PURE__*/forwardRef(({
|
|
39
|
+
title,
|
|
40
|
+
subtitle,
|
|
41
|
+
className,
|
|
42
|
+
...rest
|
|
43
|
+
}, ref) => {
|
|
44
|
+
return jsxs("div", {
|
|
45
|
+
ref: ref,
|
|
46
|
+
...rest,
|
|
47
|
+
className: clsx(styles.headerTextContent, className),
|
|
48
|
+
children: [jsx(Text, {
|
|
49
|
+
as: "span",
|
|
50
|
+
className: styles.headerEllipsis,
|
|
51
|
+
variant: "bodyLargeBold",
|
|
52
|
+
children: title
|
|
53
|
+
}), subtitle && jsx(Text, {
|
|
54
|
+
as: "span",
|
|
55
|
+
className: styles.headerEllipsis,
|
|
56
|
+
color: "textOnLightSecondary",
|
|
57
|
+
variant: "caption",
|
|
58
|
+
children: subtitle
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
TextContent.displayName = 'MenuComboboxHeaderTextContent';
|
|
63
|
+
const MenuComboboxHeaderPrimitive = ({
|
|
64
|
+
children,
|
|
65
|
+
className,
|
|
66
|
+
...rest
|
|
67
|
+
}) => {
|
|
68
|
+
return jsx("div", {
|
|
69
|
+
...rest,
|
|
70
|
+
className: clsx(styles.menuHeader, className),
|
|
71
|
+
role: "presentation",
|
|
72
|
+
children: children
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const MenuComboboxHeader = Object.assign(MenuComboboxHeaderPrimitive, {
|
|
76
|
+
MenuCloseButton,
|
|
77
|
+
TextContent
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export { MenuComboboxHeader };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { ComboboxItem } from '@ariakit/react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import { Text } from '../../text/text.js';
|
|
6
|
+
import styles from './menu-combobox.module.js';
|
|
7
|
+
|
|
8
|
+
/** A filterable menu item. */
|
|
9
|
+
const MenuComboboxItem = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
10
|
+
const {
|
|
11
|
+
children,
|
|
12
|
+
className,
|
|
13
|
+
...rest
|
|
14
|
+
} = props;
|
|
15
|
+
return jsx(ComboboxItem, {
|
|
16
|
+
ref: forwardedRef,
|
|
17
|
+
focusOnHover: true,
|
|
18
|
+
setValueOnClick: false,
|
|
19
|
+
...rest,
|
|
20
|
+
className: clsx(styles.item, className),
|
|
21
|
+
children: jsx(Text, {
|
|
22
|
+
as: "span",
|
|
23
|
+
className: styles.itemLabel,
|
|
24
|
+
variant: "bodyDefault",
|
|
25
|
+
children: children
|
|
26
|
+
})
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
MenuComboboxItem.displayName = 'MenuComboboxItem';
|
|
30
|
+
|
|
31
|
+
export { MenuComboboxItem };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { ComboboxList } from '@ariakit/react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import styles from './menu-combobox.module.js';
|
|
6
|
+
|
|
7
|
+
/** Scrollable list of combobox items. */
|
|
8
|
+
const MenuComboboxList = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
9
|
+
const {
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
...rest
|
|
13
|
+
} = props;
|
|
14
|
+
return jsx(ComboboxList, {
|
|
15
|
+
ref: forwardedRef,
|
|
16
|
+
...rest,
|
|
17
|
+
className: clsx(styles.list, className),
|
|
18
|
+
children: children
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
MenuComboboxList.displayName = 'MenuComboboxList';
|
|
22
|
+
|
|
23
|
+
export { MenuComboboxList };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { ComboboxProvider, MenuProvider } from '@ariakit/react';
|
|
3
|
+
import { useState, useCallback, startTransition, useMemo } from 'react';
|
|
4
|
+
import { MenuComboboxContext } from './menu-combobox-context.js';
|
|
5
|
+
|
|
6
|
+
/** Root provider that wires the combobox + menu state together. */
|
|
7
|
+
const MenuComboboxRoot = props => {
|
|
8
|
+
const {
|
|
9
|
+
children,
|
|
10
|
+
open: controlledOpen,
|
|
11
|
+
onOpenChange,
|
|
12
|
+
defaultOpen = false,
|
|
13
|
+
onSearchValueChange,
|
|
14
|
+
searchPlaceholder,
|
|
15
|
+
isFullScreenEnabled = false
|
|
16
|
+
} = props;
|
|
17
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
18
|
+
const isControlled = controlledOpen !== undefined;
|
|
19
|
+
const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
|
|
20
|
+
const handleSetOpen = useCallback(nextOpen => {
|
|
21
|
+
if (!isControlled) {
|
|
22
|
+
setUncontrolledOpen(nextOpen);
|
|
23
|
+
}
|
|
24
|
+
onOpenChange?.(nextOpen);
|
|
25
|
+
}, [isControlled, onOpenChange]);
|
|
26
|
+
const handleSetValue = useCallback(value => {
|
|
27
|
+
startTransition(() => {
|
|
28
|
+
onSearchValueChange?.(value);
|
|
29
|
+
});
|
|
30
|
+
}, [onSearchValueChange]);
|
|
31
|
+
const contextValue = useMemo(() => ({
|
|
32
|
+
searchPlaceholder,
|
|
33
|
+
isFullScreenEnabled,
|
|
34
|
+
setOpen: handleSetOpen
|
|
35
|
+
}), [searchPlaceholder, isFullScreenEnabled, handleSetOpen]);
|
|
36
|
+
return jsx(MenuComboboxContext.Provider, {
|
|
37
|
+
value: contextValue,
|
|
38
|
+
children: jsx(ComboboxProvider, {
|
|
39
|
+
resetValueOnHide: true,
|
|
40
|
+
setValue: handleSetValue,
|
|
41
|
+
children: jsx(MenuProvider, {
|
|
42
|
+
open: isOpen,
|
|
43
|
+
setOpen: handleSetOpen,
|
|
44
|
+
children: children
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
MenuComboboxRoot.displayName = 'MenuComboboxRoot';
|
|
50
|
+
|
|
51
|
+
export { MenuComboboxRoot };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type MenuComboboxSearchProps } from './types';
|
|
2
|
+
/** Filterable search input rendered inside the menu panel. */
|
|
3
|
+
export declare const MenuComboboxSearch: import("react").ForwardRefExoticComponent<Omit<MenuComboboxSearchProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Combobox } from '@ariakit/react';
|
|
3
|
+
import { Search as Search$1 } from '@box/blueprint-web-assets/icons/Fill';
|
|
4
|
+
import { Search } from '@box/blueprint-web-assets/icons/Medium';
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
import { forwardRef } from 'react';
|
|
7
|
+
import { useBlueprintModernization } from '../../blueprint-modernization-context/useBlueprintModernization.js';
|
|
8
|
+
import { useMenuComboboxContext } from './menu-combobox-context.js';
|
|
9
|
+
import styles from './menu-combobox.module.js';
|
|
10
|
+
|
|
11
|
+
/** Filterable search input rendered inside the menu panel. */
|
|
12
|
+
const MenuComboboxSearch = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
13
|
+
const {
|
|
14
|
+
className,
|
|
15
|
+
placeholder,
|
|
16
|
+
'aria-label': ariaLabel,
|
|
17
|
+
...rest
|
|
18
|
+
} = props;
|
|
19
|
+
const {
|
|
20
|
+
searchPlaceholder: rootSearchPlaceholder
|
|
21
|
+
} = useMenuComboboxContext();
|
|
22
|
+
const {
|
|
23
|
+
enableModernizedComponents
|
|
24
|
+
} = useBlueprintModernization();
|
|
25
|
+
const SearchIcon = enableModernizedComponents ? Search : Search$1;
|
|
26
|
+
const resolvedPlaceholder = placeholder ?? rootSearchPlaceholder;
|
|
27
|
+
return jsxs("span", {
|
|
28
|
+
className: styles.searchWrapper,
|
|
29
|
+
children: [jsx(SearchIcon, {
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
className: styles.searchIcon
|
|
32
|
+
}), jsx(Combobox, {
|
|
33
|
+
ref: forwardedRef,
|
|
34
|
+
"aria-label": ariaLabel,
|
|
35
|
+
autoSelect: true,
|
|
36
|
+
...rest,
|
|
37
|
+
className: clsx(styles.search, enableModernizedComponents && styles.searchModern, className),
|
|
38
|
+
placeholder: resolvedPlaceholder
|
|
39
|
+
})]
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
MenuComboboxSearch.displayName = 'MenuComboboxSearch';
|
|
43
|
+
|
|
44
|
+
export { MenuComboboxSearch };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type MenuComboboxTriggerProps } from './types';
|
|
2
|
+
/** Connects the menu disclosure to a single interactive child (asChild pattern). */
|
|
3
|
+
export declare const MenuComboboxTrigger: import("react").ForwardRefExoticComponent<Omit<MenuComboboxTriggerProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { MenuButton } from '@ariakit/react';
|
|
3
|
+
import { forwardRef, Children, isValidElement } from 'react';
|
|
4
|
+
|
|
5
|
+
/** Connects the menu disclosure to a single interactive child (asChild pattern). */
|
|
6
|
+
const MenuComboboxTrigger = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
7
|
+
const {
|
|
8
|
+
children,
|
|
9
|
+
render: renderProp,
|
|
10
|
+
...rest
|
|
11
|
+
} = props;
|
|
12
|
+
const elements = Children.toArray(children).filter(isValidElement);
|
|
13
|
+
if (process.env.NODE_ENV !== 'production' && !renderProp && elements.length !== 1) {
|
|
14
|
+
// eslint-disable-next-line no-console
|
|
15
|
+
console.warn('MenuCombobox.Trigger expects a single element child so disclosure props can be merged into it. ' + `Received ${elements.length} element(s).`);
|
|
16
|
+
}
|
|
17
|
+
const renderFromChild = elements.length === 1 ? elements[0] : undefined;
|
|
18
|
+
const render = renderProp ?? renderFromChild;
|
|
19
|
+
return jsx(MenuButton, {
|
|
20
|
+
ref: forwardedRef,
|
|
21
|
+
...rest,
|
|
22
|
+
render: render,
|
|
23
|
+
children: renderFromChild ? undefined : children
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
MenuComboboxTrigger.displayName = 'MenuComboboxTrigger';
|
|
27
|
+
|
|
28
|
+
export { MenuComboboxTrigger };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import '../../index.css';
|
|
2
|
+
var styles = {"content":"bp_menu_combobox_module_content--6ad69","searchWrapper":"bp_menu_combobox_module_searchWrapper--6ad69","searchIcon":"bp_menu_combobox_module_searchIcon--6ad69","search":"bp_menu_combobox_module_search--6ad69","searchModern":"bp_menu_combobox_module_searchModern--6ad69","list":"bp_menu_combobox_module_list--6ad69","item":"bp_menu_combobox_module_item--6ad69","itemLabel":"bp_menu_combobox_module_itemLabel--6ad69","empty":"bp_menu_combobox_module_empty--6ad69","emptyModern":"bp_menu_combobox_module_emptyModern--6ad69","menuHeader":"bp_menu_combobox_module_menuHeader--6ad69","headerTextContent":"bp_menu_combobox_module_headerTextContent--6ad69","headerEllipsis":"bp_menu_combobox_module_headerEllipsis--6ad69","menuCloseButton":"bp_menu_combobox_module_menuCloseButton--6ad69"};
|
|
3
|
+
|
|
4
|
+
export { styles as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ComboboxItemProps as AriakitComboboxItemProps, type ComboboxListProps as AriakitComboboxListProps, type ComboboxProps as AriakitComboboxProps, type MenuButtonProps as AriakitMenuButtonProps, type MenuProps as AriakitMenuProps } from '@ariakit/react';
|
|
2
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
|
+
export interface MenuComboboxRootProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
/** Controlled open state. Pair with `onOpenChange`. */
|
|
6
|
+
open?: boolean;
|
|
7
|
+
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
/** @default false */
|
|
9
|
+
defaultOpen?: boolean;
|
|
10
|
+
/** Called as the search input value changes; use it to filter the rendered items. */
|
|
11
|
+
onSearchValueChange?: (value: string) => void;
|
|
12
|
+
/** Default placeholder for `MenuCombobox.Search`. */
|
|
13
|
+
searchPlaceholder?: string;
|
|
14
|
+
/** Render the panel as a full-screen mobile surface. @default false */
|
|
15
|
+
isFullScreenEnabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface MenuComboboxTriggerProps extends Omit<AriakitMenuButtonProps, 'store'> {
|
|
18
|
+
/** A single interactive element to merge disclosure behavior into (asChild pattern). */
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export type MenuComboboxContentProps = Omit<AriakitMenuProps, 'store'>;
|
|
22
|
+
export interface MenuComboboxSearchProps extends Omit<AriakitComboboxProps, 'store'> {
|
|
23
|
+
/** Required, localized accessible name for the search input. */
|
|
24
|
+
'aria-label': string;
|
|
25
|
+
/** Overrides `searchPlaceholder` from `MenuCombobox.Root`. */
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface MenuComboboxListProps extends Omit<AriakitComboboxListProps, 'store'> {
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}
|
|
31
|
+
export interface MenuComboboxItemProps extends Omit<AriakitComboboxItemProps, 'store'> {
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
export interface MenuComboboxEmptyProps extends ComponentProps<'div'> {
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../index.css';
|
|
2
|
-
var styles = {"textReset":"bp_text_module_textReset--
|
|
2
|
+
var styles = {"textReset":"bp_text_module_textReset--1bfe8","breakWord":"bp_text_module_breakWord--1bfe8","textOnLightDefault":"bp_text_module_textOnLightDefault--1bfe8","textOnLightSecondary":"bp_text_module_textOnLightSecondary--1bfe8","textOnLightLink":"bp_text_module_textOnLightLink--1bfe8","textOnLightError":"bp_text_module_textOnLightError--1bfe8","textOnDarkDefault":"bp_text_module_textOnDarkDefault--1bfe8","titleMondo":"bp_text_module_titleMondo--1bfe8","titleXLarge":"bp_text_module_titleXLarge--1bfe8","titleLarge":"bp_text_module_titleLarge--1bfe8","titleMedium":"bp_text_module_titleMedium--1bfe8","titleSmall":"bp_text_module_titleSmall--1bfe8","subtitle":"bp_text_module_subtitle--1bfe8","bodyLargeBold":"bp_text_module_bodyLargeBold--1bfe8","bodyLarge":"bp_text_module_bodyLarge--1bfe8","bodyDefaultBold":"bp_text_module_bodyDefaultBold--1bfe8","bodyDefaultSemibold":"bp_text_module_bodyDefaultSemibold--1bfe8","bodyDefault":"bp_text_module_bodyDefault--1bfe8","bodySmallSemibold":"bp_text_module_bodySmallSemibold--1bfe8","bodySmall":"bp_text_module_bodySmall--1bfe8","captionBold":"bp_text_module_captionBold--1bfe8","caption":"bp_text_module_caption--1bfe8","labelBold":"bp_text_module_labelBold--1bfe8","label":"bp_text_module_label--1bfe8","linkDefault":"bp_text_module_linkDefault--1bfe8","notificationDefault":"bp_text_module_notificationDefault--1bfe8","metricLarge":"bp_text_module_metricLarge--1bfe8","metricMedium":"bp_text_module_metricMedium--1bfe8","metricSmall":"bp_text_module_metricSmall--1bfe8"};
|
|
3
3
|
|
|
4
4
|
export { styles as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@ariakit/react": "0.4.21",
|
|
49
49
|
"@ariakit/react-core": "0.4.21",
|
|
50
|
-
"@box/blueprint-web-assets": "^4.114.
|
|
50
|
+
"@box/blueprint-web-assets": "^4.114.6",
|
|
51
51
|
"@internationalized/date": "^3.12.0",
|
|
52
52
|
"@radix-ui/react-accordion": "1.1.2",
|
|
53
53
|
"@radix-ui/react-checkbox": "1.0.4",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"type-fest": "^3.2.0"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@box/storybook-utils": "^0.17.
|
|
80
|
+
"@box/storybook-utils": "^0.17.48",
|
|
81
81
|
"@figma/code-connect": "1.4.4",
|
|
82
82
|
"@types/react": "^18.0.0",
|
|
83
83
|
"@types/react-dom": "^18.0.0",
|