@progress/kendo-react-buttons
Version:
All you need in React Button in one package: disabled/enabled states, built-in styles and more. KendoReact Buttons package
312 lines (311 loc) • 8.83 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import * as t from "react";
import o from "prop-types";
import { useZIndexContext as Ce, useId as V, useDir as ye, dispatchEvent as b, getActiveElement as Ie, Keys as c, classNames as D, kendoThemeMaps as ve, ZIndexContext as Ee, getTabIndex as xe, IconWrap as De, svgIconPropType as Ne } from "@progress/kendo-react-common";
import { FloatingActionButtonItem as we } from "./FloatingActionButtonItem.mjs";
import { position as Re, getTextDirectionClass as Ae, getAnchorAlign as Fe, getPopupAlign as Oe } from "./utils.mjs";
import { Popup as ze } from "@progress/kendo-react-popup";
const Te = 2, Be = 100, Y = t.forwardRef(
(M, ee) => {
const {
align: u = h.align,
alignOffset: P,
className: $,
disabled: d,
icon: N,
svgIcon: w,
iconClass: K,
id: S,
items: n,
item: te,
text: C,
positionMode: R = h.positionMode,
size: y = h.size,
style: oe,
rounded: I = h.rounded,
themeColor: A = h.themeColor,
overlayStyle: ae,
tabIndex: ne,
accessKey: se,
popupSettings: v = {},
modal: le,
onClick: F,
onItemClick: W,
onFocus: O,
onBlur: Z,
onKeyDown: q,
onOpen: _,
onClose: H,
...ie
} = M, j = Ce(), L = j ? j + Te : Be, X = t.useRef(null), l = t.useRef(null), re = t.useRef(null), ce = t.useRef(null), U = t.useCallback(() => {
l.current && l.current.focus();
}, []), f = t.useCallback(
() => ({
element: l.current,
focus: U
}),
[U]
);
t.useImperativeHandle(X, f), t.useImperativeHandle(
ee,
() => X.current
);
const [i, r] = t.useState(!1), [E, p] = t.useState(!1), [g, s] = t.useState(-1), ue = V() + "-button-id", z = ye(l, M.dir), k = z === "rtl", x = V() + "-list-id";
t.useEffect(() => {
Re(l, u, P, k);
}, [l, u, P, k]), t.useEffect(() => {
E && l && l.current && l.current.focus();
}, [E, l]);
const m = t.useCallback(
(e, a) => {
n && b(a ? _ : H, e, f(), void 0);
},
[_, H, n]
), G = t.useCallback(
(e) => {
!e.target || d || (!n && F ? b(
F,
e,
f(),
void 0
) : (r(!i), p(!0), s(i ? -1 : 0), m(e, !i)));
},
[r, p, s, F, m, i, n, d]
), de = t.useCallback(
(e) => {
p(!0), s(i ? 0 : -1), O && b(
O,
e,
f(),
void 0
);
},
[O, p, s]
), fe = t.useCallback(
(e) => {
p(!1), r(!1), s(-1), b(
Z,
e,
f(),
void 0
), i && m(e, !1);
},
[Z, p, r, s, m]
), pe = t.useCallback((e) => {
e.preventDefault();
}, []), T = t.useCallback(
(e, a) => {
n && (n[a].disabled || b(W, e, f(), {
itemProps: n[a],
itemIndex: a
}));
},
[W]
), me = t.useCallback(
(e, a) => {
!e.target || !n || (s(a), r(!1), T(e, a), m(e, !1));
},
[s, r, T, m]
), be = t.useCallback(
(e) => {
Ie(document) === l.current && e.preventDefault();
},
[l]
), ge = t.useCallback(
(e) => {
const a = g, B = n ? n.length : -1;
if (e.altKey) {
!i && e.keyCode === c.down && (e.preventDefault(), r(!0), s(0)), i && e.keyCode === c.up && (e.preventDefault(), r(!1), s(-1));
return;
}
switch (e.keyCode) {
case c.enter:
case c.space:
a >= 0 && T(e, a), n || G(e), e.preventDefault(), r(!i), s(i ? -1 : 0);
break;
case c.esc:
e.preventDefault(), r(!1), s(-1);
break;
case c.home:
e.preventDefault(), s(0);
break;
case c.end:
e.preventDefault(), s(B - 1);
break;
case c.down:
case c.right:
e.preventDefault(), s(a + 1 >= B ? 0 : a + 1);
break;
case c.up:
case c.left:
e.preventDefault(), s(a - 1 < 0 ? B - 1 : a - 1);
break;
}
b(
q,
e,
f(),
void 0
);
},
[q, g, s, k, r]
), ke = t.useMemo(
() => D(
"k-fab k-fab-solid",
{
"k-fab-sm": y === "small",
"k-fab-md": y === "medium",
"k-fab-lg": y === "large",
"k-disabled": d,
"k-pos-absolute": R === "absolute",
"k-pos-fixed": R === "fixed",
"k-focus": E,
[`k-rounded-${ve.roundedMap[I] || I}`]: I,
[`k-fab-solid-${A}`]: A
},
`k-${u.vertical}-${u.horizontal}`,
$
),
[A, y, I, d, R, u, E, $]
), he = n && n.map((e, a) => /* @__PURE__ */ t.createElement(
we,
{
...e,
key: a,
index: a,
id: `${x}-${a}`,
disabled: d || e.disabled,
focused: g === a,
dataItem: e,
item: te,
className: D(e.className, Ae(z || "ltr", u.horizontal)),
onClick: me,
onDown: be
}
)), J = !!((N || w) && !C), Q = (l.current ? l.current.offsetWidth : 0) / 2 - 32 / 2;
return /* @__PURE__ */ t.createElement(Ee.Provider, { value: L }, /* @__PURE__ */ t.createElement(t.Fragment, null, /* @__PURE__ */ t.createElement(
"button",
{
ref: l,
id: S || ue,
role: "button",
type: "button",
"aria-disabled": d,
"aria-expanded": n ? i : void 0,
"aria-haspopup": !!n,
"aria-label": `${C || ""} floatingactionbutton`,
"aria-owns": n ? x : void 0,
"aria-activedescendant": g >= 0 && n ? `${x}-${g}` : void 0,
tabIndex: xe(ne, d),
accessKey: se,
dir: z,
disabled: d,
className: ke,
style: oe,
onClick: G,
onMouseDown: pe,
onFocus: de,
onBlur: fe,
onKeyDown: ge,
...ie
},
N || w ? /* @__PURE__ */ t.createElement(De, { className: "k-fab-icon", name: N, icon: w }) : K ? /* @__PURE__ */ t.createElement("span", { role: "presentation", className: K }) : null,
C && /* @__PURE__ */ t.createElement("span", { className: "k-fab-text" }, C)
), le && i && /* @__PURE__ */ t.createElement(
"div",
{
className: "k-overlay",
style: {
zIndex: L,
...ae
}
}
), /* @__PURE__ */ t.createElement(
ze,
{
ref: ce,
anchor: l.current,
show: i,
animate: v.animate,
popupClass: D("k-popup-transparent k-fab-popup", v.popupClass),
anchorAlign: v.anchorAlign || Fe(u, k),
popupAlign: v.popupAlign || Oe(u, k),
style: { boxShadow: "none" }
},
/* @__PURE__ */ t.createElement(
"ul",
{
ref: re,
role: "menu",
"aria-labelledby": S,
id: x,
className: D("k-fab-items", {
"k-fab-items-bottom": u.vertical !== "bottom",
"k-fab-items-top": u.vertical === "bottom"
}),
style: {
paddingLeft: J ? Q : void 0,
paddingRight: J ? Q : void 0
}
},
he
)
)));
}
);
Y.propTypes = {
className: o.string,
style: o.object,
id: o.string,
dir: o.string,
tabIndex: o.number,
accessKey: o.string,
disabled: o.bool,
icon: o.string,
svgIcon: Ne,
iconClass: o.string,
text: o.string,
alignOffset: o.shape({
x: o.oneOfType([o.number, o.string]).isRequired,
y: o.oneOfType([o.number, o.string]).isRequired
}),
align: o.shape({
vertical: o.oneOf(["top", "middle", "bottom"]).isRequired,
horizontal: o.oneOf(["start", "center", "end"]).isRequired
}),
positionMode: o.oneOf(["absolute", "fixed"]),
size: o.oneOf([null, "small", "medium", "large"]),
rounded: o.oneOf([null, "small", "medium", "large", "full"]),
themeColor: o.oneOf([
null,
"primary",
"secondary",
"tertiary",
"info",
"success",
"warning",
"error",
"dark",
"light",
"inverse"
]),
modal: o.bool,
overlayStyle: o.object
};
const h = {
align: { vertical: "bottom", horizontal: "end" },
size: "medium",
rounded: "full",
themeColor: "primary",
positionMode: "fixed"
};
Y.displayName = "KendoFloatingActionButton";
export {
Y as FloatingActionButton
};