@frontify/fondue
Version:
Design system of Frontify
127 lines (126 loc) • 5.5 kB
JavaScript
import { jsx as l, Fragment as D, jsxs as F } from "react/jsx-runtime";
import { useAccordion as N, useAccordionItem as P } from "@react-aria/accordion";
import { useFocusRing as O } from "@react-aria/focus";
import { mergeProps as R } from "@react-aria/utils";
import { Item as T } from "@react-stately/collections";
import { useTreeState as _ } from "@react-stately/tree";
import { Children as p, useRef as w, useEffect as L, isValidElement as v } from "react";
import { FOCUS_STYLE_NO_OFFSET as U } from "../../utilities/focusStyle.es.js";
import { merge as C } from "../../utilities/merge.es.js";
import { AccordionHeader as M } from "./AccordionHeader.es.js";
import { CollapsibleWrap as S } from "../CollapsibleWrap/CollapsibleWrap.es.js";
const V = "fondue-accordion", I = "fondue-accordion-item", j = ({
item: e,
state: t,
header: r,
padding: o = !0,
divider: i = !1,
headerComponent: n = M,
"data-test-id": c = I
}) => {
var d, u;
const { active: s, ...f } = r, y = w(null), { buttonProps: h, regionProps: m } = P({ item: e }, t, y), A = t.expandedKeys.has(e.key), { isFocusVisible: k, focusProps: g } = O();
return /* @__PURE__ */ F(
"div",
{
className: C([
k ? `${U} tw-relative tw-rounded` : "",
i && "tw-divide-y tw-divide-black-10"
]),
children: [
/* @__PURE__ */ l(
"button",
{
...R(h, g),
"data-test-id": c,
ref: y,
onClick: (a) => {
r.onClick && r.onClick(), h.onClick && h.onClick(a);
},
onKeyUp: (a) => {
r.onClick && a.key === "Enter" && r.onClick(), h.onKeyUp && h.onKeyUp(a);
},
className: "tw-w-full focus-visible:tw-outline-none",
children: /* @__PURE__ */ l(n, { isOpen: A, ...f })
}
),
/* @__PURE__ */ l(S, { isOpen: A, preventInitialAnimation: s, children: /* @__PURE__ */ l("div", { ...m, className: C([o && "tw-px-8 tw-pb-6", "tw-mt-2"]), children: (u = (d = e.props).children) == null ? void 0 : u.call(d) }) })
]
},
e.key
);
}, W = (e) => {
const t = p.map(e, (o, i) => {
const { header: n, children: c } = o.props;
return /* @__PURE__ */ l(T, { textValue: n.children, children: c ? () => c : null }, i);
}), r = t.map((o) => o.key).filter((o, i) => {
var n, c;
return o && !!((c = (n = e[i]) == null ? void 0 : n.props.header) != null && c.active);
}) || [];
return { children: t, defaultExpandedKeys: r };
}, H = ({ children: e }) => p.toArray(e).reduce((t, r) => v(r) && !r.props.header ? (console.warn("Use `AccordionItem` as children of `Accordion` and set the `header` prop accordingly."), t) : (v(r) && t.push(r), t), []), Y = ({ children: e }) => /* @__PURE__ */ l(D, { children: e });
Y.displayName = "FondueAccordionItem";
const $ = (e) => {
var r, o, i;
const t = p.toArray(e);
return ((i = (o = (r = t[t.length - 1]) == null ? void 0 : r.props) == null ? void 0 : o.header) == null ? void 0 : i.active) === !0;
}, q = (e) => {
const { divider: t = !0, border: r = !0, "data-test-id": o = V } = e, i = H(e), n = W(i), c = w(null), s = _(n), f = w({ firstRender: !0, childLength: p.toArray(e.children).length }), y = p.toArray(e.children).length;
L(() => {
$(e.children) && !f.current.firstRender && p.toArray(e.children).length > f.current.childLength && s.toggleKey(n.defaultExpandedKeys[n.defaultExpandedKeys.length - 1]), f.current = { firstRender: !1, childLength: p.toArray(e.children).length };
}, [n.defaultExpandedKeys, y, e.children, s]);
const {
// @react-aria prevents default action for onMouseDown as implemented here: https://github.com/adobe/react-spectrum/blob/e14523fedd93ac1a4ede355aed70988af572ae74/packages/%40react-aria/selection/src/useSelectableCollection.ts#L370
// This makes it impossible to edit or select text in input fields inside the accordion
// onKeydown automatically navigates away from child elements, including dropdown menus etc.
// Focus should only be passed if the accordion item itself is focused
// eslint-disable-next-line @typescript-eslint/no-unused-vars
accordionProps: { onMouseDown: h, onKeyDown: m, ...A }
// @react-aria enable by default typeahead which result in an event fired up on keypress and select the section
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
} = N({ ...n, disallowTypeAhead: !0 }, s, c), g = { ...A, onKeyDown: (d) => {
const u = d.target.dataset.key, a = s.selectionManager.focusedKey === u;
u && a && (m == null || m(d));
} };
return /* @__PURE__ */ l(
"div",
{
...g,
ref: c,
"data-test-id": o,
className: C([
t && "tw-divide-y tw-divide-black-10",
r && "tw-border-t tw-border-b tw-border-black-10"
]),
children: [...s.collection].map((d, u) => {
const {
header: a,
padding: b,
headerComponent: K,
divider: x,
"data-test-id": E = I
} = i[u].props;
return /* @__PURE__ */ l(
j,
{
item: d,
state: s,
divider: x,
header: a,
padding: b,
headerComponent: K,
"data-test-id": E
},
d.key
);
})
}
);
};
q.displayName = "FondueAccordion";
export {
q as Accordion,
Y as AccordionItem
};
//# sourceMappingURL=Accordion.es.js.map