UNPKG

@progress/kendo-react-data-tools

Version:

Includes React Pager & React Filter component, an intuitive interface to create complex filter descriptions. KendoReact Data Tools package

224 lines (223 loc) 9.63 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ "use client"; import * as f from "react"; import g from "prop-types"; import { disableNavigatableContainer as v, focusFirstFocusableChild as y, validatePackage as x, getLicenseMessage as F, Navigation as C, getActiveElement as b, enableNavigatableContainer as A, classNames as T, WatermarkOverlay as G } from "@progress/kendo-react-common"; import { Group as L } from "./Group.mjs"; import { packageMetadata as W } from "../package-metadata.mjs"; const s = { // Wrapper elements for filter field/operator/value (used in Expression rows) filterFieldWrapper: ".k-filter-field", filterOperatorWrapper: ".k-filter-operator", filterValueWrapper: ".k-filter-value", // Toolbar container elements filterToolbar: ".k-filter-toolbar", toolbarElement: ".k-toolbar", groupToolbar: ".k-filter-group-main > .k-filter-toolbar > .k-toolbar", subGroupToolbar: ".k-filter-lines .k-filter-toolbar > .k-toolbar" }, k = class k extends f.Component { constructor(r) { super(r), this.wrapperRef = f.createRef(), this.showLicenseWatermark = !1, this.onFilterChange = (i) => { const o = { filter: i.nextFilter, syntheticEvent: i.syntheticEvent, nativeEvent: i.nativeEvent, target: this }; this.props.onChange.call(void 0, o); }, this.onGroupRemove = (i) => { const o = { filter: { ...this.props.value, filters: [] }, syntheticEvent: i.syntheticEvent, nativeEvent: i.nativeEvent, target: this }; this.props.onChange.call(void 0, o); }, this.navigateVertical = (i, o, e) => { if (!e) return; const t = e.classList.contains("k-filter-field") || e.classList.contains("k-filter-operator") || e.classList.contains("k-filter-value"), a = e.closest(s.toolbarElement), n = Array.from(o.getElementsByClassName("k-toolbar")), l = n.findIndex((h) => h === a), u = i === "up" ? l - 1 : l + 1, p = n[u]; if (!o.getElementsByClassName("k-filter-lines")[0] || !p) return; a && t && v(a, [ s.filterFieldWrapper, s.filterOperatorWrapper, s.filterValueWrapper ]), p.querySelectorAll( `${s.filterFieldWrapper}, ${s.filterOperatorWrapper}, ${s.filterValueWrapper}` ).forEach((h, m) => { h.tabIndex = m === 0 ? 0 : -1; }); const d = p.querySelector( `${s.filterFieldWrapper}, ${s.filterOperatorWrapper}, ${s.filterValueWrapper}` ); d ? d.focus() : y(p); }, this.onKeyDown = (i) => { var o; (o = this.navigation) == null || o.triggerKeyboardEvent(i); }, this.showLicenseWatermark = !x(W, { component: "Filter" }), this.licenseMessage = F(W); } /** * @hidden */ componentDidMount() { this.wrapperRef && (this.navigation = new C({ tabIndex: 0, root: this.wrapperRef, selectors: [".k-filter"], keyboardEvents: { keydown: { Tab: (r, i, o) => { const e = r.getElementsByClassName( "k-filter-lines" )[0]; e && v(e); }, Escape: (r, i, o) => { const e = b(document) || null, t = e == null ? void 0 : e.closest(s.toolbarElement), a = r.querySelector(s.groupToolbar), n = t == null ? void 0 : t.querySelector(".k-toolbar-button-group"), l = t === a || !!n, { isTextInput: u, isCombobox: p } = this.classifyActive(e); if (!l && t && e !== t) if (o.preventDefault(), v(t, [ s.filterFieldWrapper, s.filterOperatorWrapper, s.filterValueWrapper ]), u || p) { const c = e == null ? void 0 : e.closest( `${s.filterFieldWrapper}, ${s.filterOperatorWrapper}, ${s.filterValueWrapper}` ); c && c.focus(); } else y(t); }, ArrowUp: (r, i, o) => { const e = b(document) || null; if (!e) return; const { isPopup: t, isTextInput: a, isCombobox: n, isWrapper: l } = this.classifyActive(e); (t || a || n) && !l || (o.preventDefault(), this.navigateVertical("up", r, e)); }, ArrowDown: (r, i, o) => { const e = b(document) || null; if (!e) return; const { isPopup: t, isTextInput: a, isCombobox: n, isWrapper: l } = this.classifyActive(e); (t || a || n) && !l || (o.preventDefault(), this.navigateVertical("down", r, e)); }, ArrowRight: (r, i, o) => { const e = b(document) || null; if (!e) return; const { isTextInput: t } = this.classifyActive(e); if (t) return; o.preventDefault(); const a = e == null ? void 0 : e.nextElementSibling, n = e == null ? void 0 : e.closest(s.toolbarElement), l = r.querySelector(s.groupToolbar), u = n == null ? void 0 : n.querySelector(".k-toolbar-button-group"); e && a && !(n === l || !!u) && a.focus(); }, ArrowLeft: (r, i, o) => { const e = b(document) || null; if (!e) return; const { isTextInput: t } = this.classifyActive(e); if (t) return; o.preventDefault(); const a = e == null ? void 0 : e.previousElementSibling, n = e == null ? void 0 : e.closest(s.toolbarElement), l = r.querySelector(s.groupToolbar), u = n == null ? void 0 : n.querySelector(".k-toolbar-button-group"); e && a && !(n === l || !!u) && a.focus(); }, Enter: (r, i, o) => { var p; o.preventDefault(); const e = b(document) || null; if (!e) return; const t = e == null ? void 0 : e.closest(s.toolbarElement), a = r.getElementsByClassName("k-toolbar"), n = r.querySelector(s.groupToolbar), l = t == null ? void 0 : t.querySelector( ".k-toolbar-button-group" ); if (t === n || !!l) { const c = t == null ? void 0 : t.lastElementChild; c && e === c && c.click(); return; } if (t && e) { const c = e.classList.contains("k-filter-field") || e.classList.contains("k-filter-operator") || e.classList.contains("k-filter-value"), w = t.querySelector('button[title="Remove"]'); if (e === w) { const h = Array.from(a).findIndex((R) => R === t) - 1, m = (p = a[h]) == null ? void 0 : p.lastElementChild; e.click(), m && m.focus(); } else c && (A(t, [ s.filterFieldWrapper, s.filterOperatorWrapper, s.filterValueWrapper ]), y(e)); } } } } })); } /** * @hidden */ render() { return /* @__PURE__ */ f.createElement( "div", { className: T("k-filter", this.props.className), style: this.props.style, ref: this.wrapperRef, onKeyDown: this.onKeyDown }, /* @__PURE__ */ f.createElement("ul", { role: "tree", className: "k-filter-container", "aria-label": this.props.ariaLabel }, /* @__PURE__ */ f.createElement("li", { role: "treeitem", "aria-selected": !1, className: "k-filter-group-main" }, /* @__PURE__ */ f.createElement( L, { filter: this.props.value, fields: this.props.fields, ariaLabel: this.props.ariaLabelGroup, ariaLabelExpression: this.props.ariaLabelExpression, onChange: this.onFilterChange, onRemove: this.onGroupRemove, defaultGroupFilter: this.props.defaultGroupFilter || { logic: "and", filters: [] } } ))), this.showLicenseWatermark && /* @__PURE__ */ f.createElement(G, { message: this.licenseMessage }) ); } /** * Classifies the currently active element for navigation decisions. */ classifyActive(r) { var n, l; if (!r) return { isTextInput: !1, isCombobox: !1, isWrapper: !1, isPopup: !1 }; const i = r.tagName === "INPUT" || r.tagName === "TEXTAREA", o = ((n = r.getAttribute) == null ? void 0 : n.call(r, "role")) === "combobox", e = r.classList, t = !!e && (e.contains("k-filter-field") || e.contains("k-filter-operator") || e.contains("k-filter-value")), a = !!((l = r.closest) != null && l.call(r, ".k-animation-container, .k-popup")); return { isTextInput: i, isCombobox: o, isWrapper: t, isPopup: a }; } }; k.propTypes = { className: g.string, style: g.object, fields: function(r, i) { const o = r[i]; if (o === void 0) return new Error(`Property '${i}' is missing.`); if (Array.isArray(o)) { if (Object.keys(o.reduce((e, t) => ({ ...e, [t.name]: 1 }), {})).length !== o.length) return new Error(`Property '${i}' needs to contain objects with unique 'name' field.`); } else return new Error(`Property '${i}' needs to be Array<FieldSettings>.`); return null; }, ariaLabelGroup: g.string, ariaLabelExpression: g.string, value: g.object.isRequired, onChange: g.func.isRequired }; let E = k; export { E as Filter, s as selectors };