@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
313 lines (312 loc) • 8.86 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 ye, useId as Y, useDir as Ie, dispatchEvent as b, getActiveElement as ve, Keys as c, classNames as N, kendoThemeMaps as Ee, ZIndexContext as xe, getTabIndex as De, svgIconPropType as Ne, IconWrap as we } from "@progress/kendo-react-common";
import { FloatingActionButtonItem as Re } from "./FloatingActionButtonItem.mjs";
import { position as Ae, getTextDirectionClass as Fe, getAnchorAlign as Oe, getPopupAlign as ze } from "./utils.mjs";
import { Popup as Te } from "@progress/kendo-react-popup";
const Be = 2, Me = 100, ee = t.forwardRef(
(P, te) => {
const {
align: u = h.align,
alignOffset: $,
className: K,
disabled: d,
icon: w,
svgIcon: R,
iconClass: S,
id: W,
items: n,
item: oe,
text: C,
positionMode: A = h.positionMode,
size: y = h.size,
style: ae,
rounded: I = h.rounded,
themeColor: F = h.themeColor,
overlayStyle: ne,
tabIndex: se,
accessKey: le,
popupSettings: v = {},
modal: ie,
onClick: O,
onItemClick: Z,
onFocus: z,
onBlur: q,
onKeyDown: _,
onOpen: H,
onClose: j,
...re
} = P, L = ye(), X = L ? L + Be : Me, U = t.useRef(null), l = t.useRef(null), ce = t.useRef(null), ue = t.useRef(null), G = t.useCallback(() => {
l.current && l.current.focus();
}, []), f = t.useCallback(
() => ({
element: l.current,
focus: G
}),
[G]
);
t.useImperativeHandle(U, f), t.useImperativeHandle(
te,
() => U.current
);
const [i, r] = t.useState(!1), [E, p] = t.useState(!1), [g, s] = t.useState(-1), de = Y() + "-button-id", T = Ie(l, P.dir), k = T === "rtl", x = Y() + "-list-id";
t.useEffect(() => {
Ae(l, u, $, k);
}, [l, u, $, k]), t.useEffect(() => {
E && l && l.current && l.current.focus();
}, [E, l]);
const m = t.useCallback(
(e, a) => {
n && b(a ? H : j, e, f(), void 0);
},
[H, j, n]
), J = t.useCallback(
(e) => {
!e.target || d || (!n && O ? b(
O,
e,
f(),
void 0
) : (r(!i), p(!0), s(i ? -1 : 0), m(e, !i)));
},
[r, p, s, O, m, i, n, d]
), fe = t.useCallback(
(e) => {
p(!0), s(i ? 0 : -1), z && b(
z,
e,
f(),
void 0
);
},
[z, p, s]
), pe = t.useCallback(
(e) => {
p(!1), r(!1), s(-1), b(
q,
e,
f(),
void 0
), i && m(e, !1);
},
[q, p, r, s, m]
), me = t.useCallback((e) => {
e.preventDefault();
}, []), B = t.useCallback(
(e, a) => {
n && (n[a].disabled || b(Z, e, f(), {
itemProps: n[a],
itemIndex: a
}));
},
[Z]
), be = t.useCallback(
(e, a) => {
!e.target || !n || (s(a), r(!1), B(e, a), m(e, !1));
},
[s, r, B, m]
), ge = t.useCallback(
(e) => {
ve(document) === l.current && e.preventDefault();
},
[l]
), ke = t.useCallback(
(e) => {
const a = g, M = 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 && B(e, a), n || J(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(M - 1);
break;
case c.down:
case c.right:
e.preventDefault(), s(a + 1 >= M ? 0 : a + 1);
break;
case c.up:
case c.left:
e.preventDefault(), s(a - 1 < 0 ? M - 1 : a - 1);
break;
}
b(
_,
e,
f(),
void 0
);
},
[_, g, s, k, r]
), he = t.useMemo(
() => N(
"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": A === "absolute",
"k-pos-fixed": A === "fixed",
"k-focus": E,
[`k-rounded-${Ee.roundedMap[I] || I}`]: I,
[`k-fab-solid-${F}`]: F
},
`k-${u.vertical}-${u.horizontal}`,
K
),
[F, y, I, d, A, u, E, K]
), Ce = n && n.map((e, a) => /* @__PURE__ */ t.createElement(
Re,
{
...e,
key: a,
index: a,
id: `${x}-${a}`,
disabled: d || e.disabled,
focused: g === a,
dataItem: e,
item: oe,
className: N(e.className, Fe(T || "ltr", u.horizontal)),
onClick: be,
onDown: ge
}
)), Q = !!((w || R) && !C), V = (l.current ? l.current.offsetWidth : 0) / 2 - 32 / 2;
let D;
return w || R ? D = /* @__PURE__ */ t.createElement(we, { className: "k-fab-icon", name: w, icon: R }) : S ? D = /* @__PURE__ */ t.createElement("span", { role: "presentation", className: S }) : D = null, /* @__PURE__ */ t.createElement(xe.Provider, { value: X }, /* @__PURE__ */ t.createElement(t.Fragment, null, /* @__PURE__ */ t.createElement(
"button",
{
ref: l,
id: W || de,
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: De(se, d),
accessKey: le,
dir: T,
disabled: d,
className: he,
style: ae,
onClick: J,
onMouseDown: me,
onFocus: fe,
onBlur: pe,
onKeyDown: ke,
...re
},
D,
C && /* @__PURE__ */ t.createElement("span", { className: "k-fab-text" }, C)
), ie && i && /* @__PURE__ */ t.createElement(
"div",
{
className: "k-overlay",
style: {
zIndex: X,
...ne
}
}
), /* @__PURE__ */ t.createElement(
Te,
{
ref: ue,
anchor: l.current,
show: i,
animate: v.animate,
popupClass: N("k-popup-transparent k-fab-popup", v.popupClass),
anchorAlign: v.anchorAlign || Oe(u, k),
popupAlign: v.popupAlign || ze(u, k),
style: { boxShadow: "none" }
},
/* @__PURE__ */ t.createElement(
"ul",
{
ref: ce,
role: "menu",
"aria-labelledby": W,
id: x,
className: N("k-fab-items", {
"k-fab-items-bottom": u.vertical !== "bottom",
"k-fab-items-top": u.vertical === "bottom"
}),
style: {
paddingLeft: Q ? V : void 0,
paddingRight: Q ? V : void 0
}
},
Ce
)
)));
}
);
ee.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"
};
ee.displayName = "KendoFloatingActionButton";
export {
ee as FloatingActionButton
};