braid-design-system
Version:
Themeable design system for the SEEK Group
117 lines (116 loc) • 4.36 kB
JavaScript
import { jsxs, jsx } from "react/jsx-runtime";
import assert from "assert";
import { useContext, cloneElement } from "react";
import { Box } from "../Box/Box.mjs";
import { useDisclosure } from "../Disclosure/useDisclosure.mjs";
import { Spread } from "../Spread/Spread.mjs";
import { Stack } from "../Stack/Stack.mjs";
import { Text } from "../Text/Text.mjs";
import { badgeSlotSpace } from "../private/badgeSlotSpace.mjs";
import { buildDataAttributes } from "../private/buildDataAttributes.mjs";
import { defaultSize } from "./Accordion.mjs";
import { AccordionContext, validTones } from "./AccordionContext.mjs";
import { button, focusRing } from "./AccordionItem.css.mjs";
import { IconChevron } from "../icons/IconChevron/IconChevron.mjs";
const itemSpaceForSize = {
xsmall: "small",
small: "small",
standard: "medium",
large: "medium"
};
const AccordionItem = ({
id,
label,
children,
badge,
size: sizeProp,
tone: toneProp,
weight: weightProp,
icon,
data,
...restProps
}) => {
const accordionContext = useContext(AccordionContext);
assert(
!(accordionContext && sizeProp),
"Size cannot be set on AccordionItem when inside Accordion. Size should be set on Accordion instead."
);
assert(
!(accordionContext && toneProp),
"Tone cannot be set on AccordionItem when inside Accordion. Tone should be set on Accordion instead."
);
assert(
!(accordionContext && weightProp),
"Weight cannot be set on AccordionItem when inside Accordion. Weight should be set on Accordion instead."
);
assert(
toneProp === void 0 || validTones.includes(toneProp),
`The 'tone' prop should be one of the following: ${validTones.map((x) => `"${x}"`).join(", ")}`
);
assert(
// @ts-expect-error
!badge || badge.type.__isBadge__,
`AccordionItem badge prop can only be an instance of Badge. e.g. <AccordionItem badge={<Badge>New</Badge>}>`
);
assert(
!badge || badge.props.bleedY === void 0,
"Badge elements cannot set the 'bleedY' prop when passed to an AccordionItem component"
);
assert(
!icon || icon.props.size === void 0 && icon.props.tone === void 0,
"Icons cannot set the 'size' or 'tone' prop when passed to an AccordionItem component"
);
const size = (accordionContext == null ? void 0 : accordionContext.size) ?? sizeProp ?? defaultSize;
const tone = (accordionContext == null ? void 0 : accordionContext.tone) ?? toneProp ?? "neutral";
const weight = (accordionContext == null ? void 0 : accordionContext.weight) ?? weightProp ?? "medium";
const itemSpace = itemSpaceForSize[size] ?? "none";
assert(
typeof label === "undefined" || typeof label === "string",
"Label must be a string"
);
const { expanded, buttonProps, contentProps } = useDisclosure({
id,
...restProps.expanded !== void 0 ? {
onToggle: restProps.onToggle,
expanded: restProps.expanded
} : {
onToggle: restProps.onToggle
}
});
if (process.env.NODE_ENV !== "production") {
buildDataAttributes({ data, validateRestProps: restProps });
}
return /* @__PURE__ */ jsxs(Stack, { space: itemSpace, data, children: [
/* @__PURE__ */ jsx(Box, { position: "relative", display: "flex", children: /* @__PURE__ */ jsx(
Box,
{
component: "button",
type: "button",
cursor: "pointer",
className: [button, focusRing],
width: "full",
textAlign: "left",
...buttonProps,
children: /* @__PURE__ */ jsx(Box, { component: "span", position: "relative", children: /* @__PURE__ */ jsxs(Spread, { component: "span", space: itemSpace, children: [
/* @__PURE__ */ jsxs(Text, { size, weight, tone, icon, children: [
badge ? /* @__PURE__ */ jsx(Box, { component: "span", paddingRight: badgeSlotSpace, children: label }) : label,
badge ? cloneElement(badge, {}) : null
] }),
/* @__PURE__ */ jsx(
Text,
{
size,
weight,
tone: tone === "neutral" ? "secondary" : tone,
children: /* @__PURE__ */ jsx(IconChevron, { direction: expanded ? "up" : "down" })
}
)
] }) })
}
) }),
/* @__PURE__ */ jsx(Box, { display: expanded ? "block" : "none", ...contentProps, children })
] });
};
export {
AccordionItem
};