UNPKG

@primer/react-brand

Version:

Primer Brand is a GitHub's design system for creating React-based marketing websites and digital experiences.

289 lines (288 loc) • 8.79 kB
import e from "../node_modules/clsx/dist/clsx.js"; import { useId as t } from "../hooks/useId.js"; import { Text as n } from "../Text/Text.js"; import { CheckIcon as r, ChevronDownIcon as i } from "../node_modules/@primer/octicons-react/dist/index.esm.js"; import { Button as a } from "../Button/Button.js"; import { ThemeProvider as o } from "../ThemeProvider/ThemeProvider.js"; import { useTheme as s } from "../ThemeProvider/useTheme.js"; import { useOnClickOutside as c } from "../hooks/useOnClickOutside.js"; import { useKeyboardEscape as l } from "../hooks/useKeyboardEscape.js"; import { useAnchoredPosition as u } from "../hooks/useAnchoredPosition.js"; import '../packages/design-tokens/lib/design-tokens/css/tokens/functional/components/action-menu/colors-with-modes-B69RzUbe.css';/* empty css */ import d from "./ActionMenu.module.js"; import f, { Children as p, cloneElement as m, forwardRef as h, isValidElement as g, memo as _, useCallback as v, useEffect as y, useMemo as b, useRef as x, useState as S } from "react"; import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime"; import { FocusKeys as E, focusZone as D } from "@primer/behaviors"; //#region src/ActionMenu/ActionMenu.tsx var O = { root: "ActionMenu", get button() { return `${this.root}-button`; }, get overlay() { return `${this.root}-overlay`; }, get list() { return `${this.root}-list`; }, get item() { return `${this.root}-list-item`; } }, k = [ "inside-top", "inside-bottom", "inside-left", "inside-right", "inside-center", "outside-top", "outside-bottom", "outside-left", "outside-right" ], A = ["small", "medium"], j = ["default", "split-button"], M = f.createContext({}), N = () => f.useContext(M), P = ({ size: e, children: t }) => { let [n, r] = S(e); return /* @__PURE__ */ w(M.Provider, { value: { size: n, setSize: r }, children: t }); }, F = _(({ id: n, children: r, "data-testid": i, disabled: a, open: o = !1, selectionVariant: s = "none", menuAlignment: f = "end", size: h = "medium", menuSide: _, onSelect: b, mode: C = "default" }) => { let [k, A] = S(o), j = x(null), M = x(null), N = t(n); c(j, () => A(!1), M), l(v(() => { A(!1); }, [])); let F = v(() => { A(!k); }, [k]), L = v((e) => { b && b(e), F(); }, [b, F]), R = v((e) => { L(e), F(), M.current?.focus(); }, [ L, F, M ]); y(() => { if (k && j.current) { let e = j.current, t = C === "split-button", n = t ? (e) => e.tagName === "A" : void 0; D(j.current, { bindKeys: E.ArrowVertical, focusableElementFilter: n, focusInStrategy: t ? "first" : void 0 }), e.addEventListener("keydown", (e) => { if (e.key === "Enter") { let t = e.target, n = t.tagName === "A" ? t.closest("li") : t; if (!n || n.getAttribute("aria-disabled") === "true") return; let r = n.getAttribute("data-value"); r && (L(r), A(!1), setTimeout(() => { M.current?.focus(); }, 10)); } }); let r = t ? "a" : "li", i = j.current.querySelector(r); i && setTimeout(() => { i.focus(); }, 10); let a = e.querySelectorAll(r)[e.querySelectorAll(r).length - 1]; a.addEventListener("keydown", (e) => { let t = e; t.key === "ArrowDown" && (t.preventDefault(), i?.focus()); }), i?.addEventListener("keydown", (e) => { let t = e; t.key === "ArrowUp" && (t.preventDefault(), a.focus()); }), e.addEventListener("keydown", (e) => { e.key === "Escape" && M.current?.focus(); }); } }, [ k, j, C, R, F, L ]); let { position: B } = u({ floatingElementRef: j, anchorElementRef: M, align: f, allowOutOfBounds: !0, side: _ }, [k]), { Button: V, Overlay: H } = p.toArray(r).reduce((t, n) => (g(n) && n.type === I ? t.Button = m(n, { onClick: F, ref: M, className: e(n.props.className, d[`ActionMenu__button--${C}`], k), menuOpen: k, disabled: a, id: `${N}-button`, size: h, _mode: C }) : g(n) && n.type === z && (t.Overlay = m(n, { ref: j, className: e(d.ActionMenu__menu, B && d["ActionMenu__menu--visible"], B && d[`ActionMenu__menu--pos-${B.anchorSide}`], d[`ActionMenu__menu--${h}`], C === "split-button" && "ActionMenu__menu--split"), style: { top: `${B?.top ?? 0}px`, left: `${B?.left ?? 0}px` }, id: `${N}-menu`, children: p.map(n.props.children, (e) => g(e) ? m(e, { handler: R, type: C === "split-button" ? "link" : s }) : e) })), t), {}); return /* @__PURE__ */ w(P, { size: h, children: /* @__PURE__ */ T("div", { id: N, className: e(d.ActionMenu, a && d["ActionMenu--disabled"]), "data-testid": i || O.root, children: [V, k ? H : null] }) }); }), I = h(({ as: t, href: n, children: r, className: o, "data-testid": s, disabled: c, menuOpen: l, size: u, _mode: f = "default", onClick: p, leadingVisual: m, variant: h = "primary", ...g }, _) => f === "split-button" ? /* @__PURE__ */ T("div", { className: e(d.ActionMenu__button, d[`ActionMenu__button--${u}`], o), children: [/* @__PURE__ */ w(a, { as: t, href: n, className: e(d["ActionMenu__innerButton--split-button"], d[`ActionMenu__innerButton--${h}`], d[`ActionMenu__innerButton--${u}`], c && d["ActionMenu__innerButton--disabled"]), variant: h, "aria-disabled": c, "data-testid": s || O.button, size: u, leadingVisual: m, children: /* @__PURE__ */ w("span", { className: d["ActionMenu__button-text"], children: r }) }), /* @__PURE__ */ w(a, { ref: _, as: "button", className: d["ActionMenu__innerButton--split-button"], variant: h, "aria-haspopup": "true", "aria-label": "Menu", size: u, "aria-expanded": l ? "true" : "false", onClick: p, disabled: c, ...g, children: /* @__PURE__ */ w(i, { className: d["ActionMenu__inner-button-dropdown-icon"] }) })] }) : /* @__PURE__ */ w(a, { ref: _, className: e(d.ActionMenu__button, d[`ActionMenu__button--${u}`], o), "aria-haspopup": "true", "aria-expanded": l ? "true" : "false", disabled: c, "data-testid": s || O.button, size: u, trailingVisual: /* @__PURE__ */ w(i, {}), onClick: p, ...g, children: /* @__PURE__ */ w("span", { className: d["ActionMenu__button-text"], children: r }) })), L = { none: "menuitem", single: "menuitemradio", link: "menuitem" }, R = ({ as: t, children: i, className: a, disabled: o, handler: s, selected: c, type: l, value: u, onClick: p, onKeyDown: m, leadingVisual: h, ...g }) => { let { size: _ } = N(), y = v((e) => { p?.(e), o || s?.(String(u)); }, [ s, u, o, p ]), x = v((e) => { m?.(e), !o && e.key === "Enter" && s?.(String(u)); }, [ s, u, o, m ]), S = b(() => ({ className: e(d.ActionMenu__item, l === "single" && d[`ActionMenu__item--selection-type-${l}`], _ && d[`ActionMenu__item--${_}`], a), role: L[l || "single"], "aria-disabled": o, tabIndex: -1, "data-value": u, ...g }), [ g, l, _, a, o, u ]), E = b(() => /* @__PURE__ */ T(C, { children: [ f.isValidElement(h) ? f.cloneElement(h, { width: h.props.width || 20, height: h.props.width || 20 }) : null, l === "single" && /* @__PURE__ */ w("span", { className: d["ActionMenu__item-leadingVisual"], children: c && /* @__PURE__ */ w(r, { className: e(d["ActionMenu__item-icon"], o && d["ActionMenu__item-icon--disabled"]), size: 16 }) }), /* @__PURE__ */ w("span", { className: d["ActionMenu__item-text"], children: /* @__PURE__ */ w(n, { variant: o ? "muted" : "default", size: _ === "medium" ? "200" : "100", className: e(o && d["ActionMenu__item-content--disabled"]), children: i }) }) ] }), [ h, i, c, o, _, l ]); return t === "a" ? /* @__PURE__ */ w("li", { role: "menuitem", ...S, onClick: p, onKeyDown: m, children: /* @__PURE__ */ w("a", { className: e(d["ActionMenu__item-anchor"], o && d["ActionMenu__item--disabled"]), href: g.href, children: E }) }) : /* @__PURE__ */ w("li", { role: "menuitem", ...S, "aria-checked": l === "none" ? void 0 : c ? "true" : "false", onClick: y, onKeyDown: x, children: E }); }, z = h(({ children: t, className: n, "data-testid": r, menuOpen: i, ...a }, c) => { let { colorMode: l } = s(); return /* @__PURE__ */ w(o, { colorMode: n?.includes("ActionMenu__menu--split") ? "light" : l, children: /* @__PURE__ */ w("ul", { ref: c, className: e(n), role: "menu", "data-testid": r || O.list, ...a, children: t }) }); }), B = Object.assign(F, { Button: I, Item: R, Overlay: z, testIds: O }); //#endregion export { B as ActionMenu, j as ActionMenuButtonModes, P as ActionMenuProvider, A as ActionMenuSizes, k as actionMenuOverlaySides, N as useActionMenuContext }; //# sourceMappingURL=ActionMenu.js.map