@stratakit/structures
Version:
Medium-sized component structures for the Strata design system
239 lines (238 loc) • 7.03 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { Button as ButtonAk } from "@ariakit/react/button";
import {
Menu,
MenuButton,
MenuItem,
MenuItemCheckbox,
MenuProvider,
useMenuContext
} from "@ariakit/react/menu";
import { usePopoverContext } from "@ariakit/react/popover";
import { useStoreState } from "@ariakit/react/store";
import { Button, Kbd } from "@stratakit/bricks";
import {
DisclosureArrow,
Dot,
predefinedSymbols
} from "@stratakit/bricks/secret-internals";
import { Icon } from "@stratakit/foundations";
import {
forwardRef,
usePopoverApi
} from "@stratakit/foundations/secret-internals";
import cx from "classnames";
import { Checkmark } from "./~utils.icons.js";
import * as ListItem from "./~utils.ListItem.js";
function DropdownMenuRoot(props) {
const {
children,
placement,
open: openProp,
setOpen: setOpenProp,
defaultOpen: defaultOpenProp
} = props;
return /* @__PURE__ */ jsx(
MenuProvider,
{
placement,
defaultOpen: defaultOpenProp,
open: openProp,
setOpen: setOpenProp,
popover: usePopoverContext(),
children
}
);
}
DEV: DropdownMenuRoot.displayName = "DropdownMenu.Root";
const DropdownMenuContent = forwardRef(
(props, forwardedRef) => {
const context = useMenuContext();
const open = useStoreState(context, "open");
const popoverElement = useStoreState(context, "popoverElement");
const popoverProps = usePopoverApi({ element: popoverElement, open });
return /* @__PURE__ */ jsx(
Menu,
{
portal: true,
unmountOnHide: true,
...props,
gutter: 4,
style: { ...popoverProps.style, ...props.style },
wrapperProps: { popover: popoverProps.popover },
className: cx("\u{1F95D}-dropdown-menu", props.className),
ref: forwardedRef
}
);
}
);
DEV: DropdownMenuContent.displayName = "DropdownMenu.Content";
const DropdownMenuButton = forwardRef(
(props, forwardedRef) => {
const { accessibleWhenDisabled = true, children, ...rest } = props;
const open = useStoreState(useMenuContext(), (state) => state?.open);
return /* @__PURE__ */ jsx(
MenuButton,
{
accessibleWhenDisabled: true,
...rest,
render: props.render ?? /* @__PURE__ */ jsxs(Button, { accessibleWhenDisabled, children: [
children,
/* @__PURE__ */ jsx(DisclosureArrow, {})
] }),
className: cx("\u{1F95D}-dropdown-menu-button", props.className),
"data-has-popover-open": open || void 0,
ref: forwardedRef
}
);
}
);
DEV: DropdownMenuButton.displayName = "DropdownMenu.Button";
const DropdownMenuItem = forwardRef(
(props, forwardedRef) => {
const { label, shortcuts, icon, unstable_dot, ...rest } = props;
const dotId = React.useId();
return /* @__PURE__ */ jsxs(
MenuItem,
{
accessibleWhenDisabled: true,
render: /* @__PURE__ */ jsx(
ListItem.Root,
{
render: /* @__PURE__ */ jsx(
ButtonAk,
{
accessibleWhenDisabled: true,
"aria-describedby": dotId,
...rest,
className: cx("\u{1F95D}-dropdown-menu-item", props.className),
ref: forwardedRef
}
)
}
),
children: [
icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
/* @__PURE__ */ jsx(ListItem.Content, { render: /* @__PURE__ */ jsx("span", {}), children: label }),
shortcuts ? /* @__PURE__ */ jsx(DropdownMenuItemShortcuts, { shortcuts }) : null,
unstable_dot ? /* @__PURE__ */ jsx(
ListItem.Decoration,
{
render: /* @__PURE__ */ jsx(Dot, { id: dotId, className: "\u{1F95D}-dropdown-menu-item-dot", children: unstable_dot })
}
) : null
]
}
);
}
);
DEV: DropdownMenuItem.displayName = "DropdownMenu.Item";
const DropdownMenuItemShortcuts = forwardRef((props, forwardedRef) => {
const { shortcuts, ...rest } = props;
const shortcutKeys = React.useMemo(() => {
return shortcuts.split("+").map((key) => ({
key: key.trim(),
isSymbol: key in predefinedSymbols
}));
}, [shortcuts]);
return /* @__PURE__ */ jsx(
ListItem.Decoration,
{
render: /* @__PURE__ */ jsx("span", {}),
...rest,
className: cx("\u{1F95D}-dropdown-menu-item-shortcuts", props.className),
ref: forwardedRef,
children: shortcutKeys.map(({ key, isSymbol }, index) => {
if (isSymbol) {
return /* @__PURE__ */ jsx(
Kbd,
{
variant: "ghost",
symbol: key
},
`${key + index}`
);
}
return /* @__PURE__ */ jsx(Kbd, { variant: "ghost", children: key }, `${key + index}`);
})
}
);
});
DEV: DropdownMenuItemShortcuts.displayName = "DropdownMenuItemShortcuts";
const DropdownMenuIcon = forwardRef(
(props, forwardedRef) => {
const { icon, ...rest } = props;
return /* @__PURE__ */ jsx(
ListItem.Decoration,
{
render: /* @__PURE__ */ jsx(
Icon,
{
href: typeof icon === "string" ? icon : void 0,
render: React.isValidElement(icon) ? icon : void 0,
...rest,
ref: forwardedRef
}
)
}
);
}
);
DEV: DropdownMenuIcon.displayName = "DropdownMenuIcon";
const DropdownMenuCheckboxItem = forwardRef((props, forwardedRef) => {
const {
label,
icon,
defaultChecked,
checked,
onChange,
name,
value = defaultChecked ? "on" : void 0,
// For defaultChecked to work
...rest
} = props;
return /* @__PURE__ */ jsxs(
MenuItemCheckbox,
{
accessibleWhenDisabled: true,
defaultChecked,
checked,
name,
value,
onChange,
render: /* @__PURE__ */ jsx(
ListItem.Root,
{
render: /* @__PURE__ */ jsx(
ButtonAk,
{
accessibleWhenDisabled: true,
...rest,
className: cx("\u{1F95D}-dropdown-menu-item", props.className),
ref: forwardedRef
}
)
}
),
children: [
icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
/* @__PURE__ */ jsx(ListItem.Content, { render: /* @__PURE__ */ jsx("span", {}), children: label }),
/* @__PURE__ */ jsx(
ListItem.Decoration,
{
render: /* @__PURE__ */ jsx(Checkmark, { className: "\u{1F95D}-dropdown-menu-checkmark" })
}
)
]
}
);
});
DEV: DropdownMenuCheckboxItem.displayName = "DropdownMenu.CheckboxItem";
export {
DropdownMenuButton as Button,
DropdownMenuCheckboxItem as CheckboxItem,
DropdownMenuContent as Content,
DropdownMenuItem as Item,
DropdownMenuRoot as Root
};