UNPKG

@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

298 lines (297 loc) 10.6 kB
/** * @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 p from "react"; import s from "prop-types"; import { Button as K } from "../Button.mjs"; import { Keys as r, dispatchEvent as l, getActiveElement as f, validatePackage as M, getLicenseMessage as A, svgIconPropType as R, classNames as u, uDropDownButton as c, WatermarkOverlay as T, ZIndexContext as L, createPropsContext as z, withIdHOC as U, withPropsContext as Z, withUnstyledHOC as $, withZIndexContext as W } from "@progress/kendo-react-common"; import { navigate as _ } from "./utils/navigation.mjs"; import { DropDownButtonItem as H } from "./DropDownButtonItem.mjs"; import { ButtonItem as X } from "./ButtonItem.mjs"; import { Popup as j } from "@progress/kendo-react-popup"; import { getAnchorAlign as q, getPopupAlign as G } from "./utils/popup.mjs"; import { packageMetadata as C } from "../package-metadata.mjs"; const J = 12e3, Q = 2e3, m = class m extends p.Component { constructor(i) { super(i), this.state = { opened: !1, focused: !1, focusedIndex: -1 }, this.mainButton = null, this.list = null, this.skipFocus = !1, this.showLicenseWatermark = !1, this.buttonsData = [], this.onKeyDown = (t) => { const { focusedIndex: e } = this.state; if (t.altKey) { !this.opened && t.keyCode === r.down ? (t.preventDefault(), this.setOpen(!0, t), this.setState({ focusedIndex: 0 })) : this.opened && t.keyCode === r.up && (t.preventDefault(), this.setState({ focusedIndex: -1 }), this.setOpen(!1, t)); return; } const o = { ...this.state }; if (t.keyCode === r.enter || t.keyCode === r.space) { t.preventDefault(), e >= 0 && this.dispatchClickEvent(t, e); const a = !this.opened; this.setState({ focused: !0, focusedIndex: a ? 0 : -1 }), this.setOpen(a, t); return; } if (this.opened && t.keyCode === r.esc) { this.setState({ focusedIndex: -1 }), this.setOpen(!1, t); return; } if (this.opened) { const a = _(e, t.keyCode, t.altKey, this.buttonsData.length); o.focusedIndex = a; const h = t.keyCode === r.up || t.keyCode === r.down || t.keyCode === r.left || t.keyCode === r.right; !t.altKey && (h || t.keyCode === r.home || t.keyCode === r.end) && t.preventDefault(); } this.setState(o); }, this.switchFocus = (t) => { this.skipFocus = !0, t(), window.setTimeout(() => this.skipFocus = !1, 0); }, this.handleFocus = (t) => { this.skipFocus || (this.setState({ focused: !0, focusedIndex: this.opened ? 0 : -1 }), l(this.props.onFocus, t, this, void 0)); }, this.handleButtonBlur = (t) => { this.opened || (this.setState({ focused: !1 }), l(this.props.onBlur, t, this, void 0)); }, this.handleMenuBlur = (t) => { this.skipFocus || (this.setState({ focused: !1, focusedIndex: -1 }), l(this.props.onBlur, t, this, void 0), setTimeout(() => { this.setOpen(!1, t); }, 0)); }, this.setOpen = (t, e) => { this.opened !== t && (this.openedDuringOnChange = t, this.setState({ opened: t }), e ? this.dispatchPopupEvent(e, t) : this.openedDuringOnChange = void 0); }, this.onItemClick = (t, e) => { this.setState({ focusedIndex: -1 }), this.dispatchClickEvent(t, e), this.setOpen(!1, t); }, this.onItemDown = (t) => { f(document) === this.list && t.preventDefault(); }, this.mouseDown = (t) => { t.preventDefault(); const e = f(document); this.element && e !== this.element && e !== this.list && this.element.focus(); }, this.onPopupClose = (t) => { var o; const e = f(document); this.element && this.element.removeAttribute("tabindex"), (e === this.list || (o = this.list) != null && o.contains(e)) && this.switchFocus(() => { this.element && this.element.focus({ preventScroll: !0 }); }), this.props.popupSettings && this.props.popupSettings.onClose && this.props.popupSettings.onClose.call(void 0, t); }, this.listRef = (t) => { this.list = t, t && this.state.focused && this.switchFocus(() => { t.focus({ preventScroll: !0 }), this.element && (this.element.tabIndex = -1); }); }, this.onClickMainButton = (t) => { if (l(this.props.onClick, t, this, void 0), !this.buttonsData.length) return; const e = !this.opened; this.setState({ focused: !0, focusedIndex: e ? 0 : -1 }), this.setOpen(e, t); }, this.dispatchPopupEvent = (t, e) => { l(e ? this.props.onOpen : this.props.onClose, t, this, void 0), this.openedDuringOnChange = void 0; }, this.showLicenseWatermark = !M(C, { component: "DropDownButton" }), this.licenseMessage = A(C); } get guid() { return this.props.id + "-accessibility-id"; } get opened() { return this.openedDuringOnChange !== void 0 ? this.openedDuringOnChange : this.props.opened === void 0 ? this.state.opened : this.props.opened; } /** * @hidden */ render() { const i = this.isRtl(), t = this.props.unstyled && this.props.unstyled.uDropDownButton, e = i ? "rtl" : void 0, { id: o, style: a, tabIndex: h, disabled: n, size: D, rounded: y, fillMode: I, themeColor: k, ariaLabel: w, title: b, accessKey: B, icon: O, svgIcon: x, iconClass: E, buttonClass: S, className: P, imageUrl: F, startIcon: v, endIcon: N } = this.props; return this.buttonsData = this.props.items || p.Children.toArray(this.props.children).filter((d) => d && d.type === H).map((d) => d.props), /* @__PURE__ */ p.createElement(p.Fragment, null, /* @__PURE__ */ p.createElement( K, { id: o, size: D, style: a, rounded: y, fillMode: I, themeColor: k, onClick: this.onClickMainButton, onMouseDown: this.mouseDown, onKeyDown: this.onKeyDown, onFocus: this.handleFocus, onBlur: this.handleButtonBlur, "aria-disabled": n ? "true" : void 0, tabIndex: h, accessKey: B, icon: O, svgIcon: x, iconClass: E, className: u( S, P, c.wrapper({ c: t, focused: this.state.focused, disabled: n }) ), imageUrl: F, dir: e, ref: (d) => { this.mainButton = (d == null ? void 0 : d.element) || null; }, type: "button", "aria-expanded": this.opened ? "true" : "false", "aria-label": w, "aria-controls": this.opened ? this.guid : void 0, title: b, startIcon: v, endIcon: N }, this.props.text ), this.showLicenseWatermark && /* @__PURE__ */ p.createElement(T, { message: this.licenseMessage }), this.renderPopup(i)); } /** * @hidden */ componentDidMount() { (this.props.dir === void 0 && this.isRtl() || this.opened) && this.forceUpdate(); } /** * The DOM element of main button. */ get element() { return this.mainButton; } dispatchClickEvent(i, t) { this.isItemDisabled(t) || l(this.props.onItemClick, i, this, { item: this.buttonsData[t], itemIndex: t }); } renderPopup(i) { const { popupSettings: t = {}, _zIndex: e, unstyled: o } = this.props, a = e ? e + Q : J, h = o && o.uDropDownButton, { focusedIndex: n } = this.state; return /* @__PURE__ */ p.createElement(L.Provider, { value: a }, /* @__PURE__ */ p.createElement( j, { anchor: this.mainButton, show: this.opened, animate: t.animate, popupClass: u(c.popup({ c: h }), t.popupClass), anchorAlign: t.anchorAlign || q(i), popupAlign: t.popupAlign || G(i), style: i ? { direction: "rtl" } : void 0, onClose: this.onPopupClose }, /* @__PURE__ */ p.createElement( "ul", { role: "list", id: this.guid, tabIndex: -1, "aria-activedescendant": n >= 0 ? `${this.guid}-${n}` : void 0, ref: this.listRef, onKeyDown: this.onKeyDown, onBlur: this.handleMenuBlur, className: u( c.ul({ c: h, size: this.props.size }) ) }, this.renderChildItems() ) )); } renderChildItems() { const { item: i, itemRender: t, textField: e, unstyled: o } = this.props, a = o && o.uDropDownButton; return this.buttonsData.length > 0 ? this.buttonsData.map((h, n) => /* @__PURE__ */ p.createElement( X, { className: u( c.item({ c: a }), h.className, { "k-first": n === 0 }, { "k-last": n === this.buttonsData.length - 1 } ), dataItem: h, textField: e, focused: this.state.focusedIndex === n, onClick: this.onItemClick, onDown: this.onItemDown, render: t, item: i, index: n, key: n, id: `${this.guid}-${n}` } )) : null; } isItemDisabled(i) { return this.buttonsData[i] ? this.buttonsData[i].disabled : this.props.disabled; } isRtl() { return this.props.dir !== void 0 ? this.props.dir === "rtl" : !!this.mainButton && getComputedStyle(this.mainButton).direction === "rtl"; } }; m.propTypes = { accessKey: s.string, ariaLabel: s.string, title: s.string, onFocus: s.func, onBlur: s.func, onClick: s.func, onItemClick: s.func, onOpen: s.func, onClose: s.func, items: s.arrayOf(s.any), textField: s.string, tabIndex: s.number, disabled: s.bool, icon: s.string, svgIcon: R, iconClass: s.string, imageUrl: s.string, popupSettings: s.object, itemRender: s.func, item: s.func, className: s.string, buttonClass: s.string, dir: s.string }, m.defaultProps = { size: "medium", rounded: "medium", fillMode: "solid", themeColor: "base" }; let g = m; const V = z(), Y = U( Z( V, $(W(g)) ) ); Y.displayName = "KendoReactDropDownButton"; export { Y as DropDownButton, V as DropDownButtonPropsContext, g as DropDownButtonWithoutContext };