@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
JavaScript
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