UNPKG

@progress/kendo-react-grid

Version:

React Data Grid (Table) provides 100+ ready-to-use data grid features. KendoReact Grid package

313 lines (312 loc) 13.2 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 r from "react"; import Ae from "react-dom"; import { useDocument as Le, SvgIcon as Oe, IconWrap as Te, useAsyncFocusBlur as Ge, classNames as Pe, clone as Ve, getActiveElement as qe } from "@progress/kendo-react-common"; import { GridColumnMenuItem as ze } from "../columnMenu/GridColumnMenuItem.mjs"; import { GridColumnMenuItemContent as Ke } from "../columnMenu/GridColumnMenuItemContent.mjs"; import { GridColumnMenuItemGroup as je } from "../columnMenu/GridColumnMenuItemGroup.mjs"; import { GridContext as He } from "../utils/GridContext.mjs"; import { filterIcon as ie, searchIcon as We, xIcon as _e, filterClearIcon as $e } from "@progress/kendo-svg-icons"; import { filterBy as ce } from "@progress/kendo-data-query"; import { Button as b } from "@progress/kendo-react-buttons"; import { Input as Je, Checkbox as se } from "@progress/kendo-react-inputs"; import { filterClearButton as B, messages as g, searchPlaceholder as ue, toolbarCheckboxFilter as D, filterCheckAll as fe, filterSelectedItems as me, filterSubmitButton as de, filterClearAllButton as ge } from "../messages/index.mjs"; import { useLocalization as Qe } from "@progress/kendo-react-intl"; import { getNestedValue as he } from "../utils/index.mjs"; import { isArrayEqual as Ue } from "../columnMenu/GridColumnMenuCheckboxFilter.mjs"; import { GridAdaptiveToolbarCheckboxFilter as Xe } from "./adaptiveContent/GridAdaptiveToolbarCheckboxFilter.mjs"; import { Popup as Ye } from "@progress/kendo-react-popup"; import { BadgeContainer as Ze, Badge as Re } from "@progress/kendo-react-indicators"; import { GridToolbarAdaptiveProvider as et } from "./adaptiveContext/GridToolbarAdaptiveContext.mjs"; const tt = { uniqueData: !0 }, rt = (a) => { var ae, oe; const { uniqueData: h = tt.uniqueData, svgIcon: P, icon: V } = a, i = r.useContext(He), k = i.columnsRef, v = i.defaultFilter, [S, x] = r.useState(!1), p = r.useRef(null), I = r.useRef(null), q = r.useRef(null), N = r.useRef(0), m = Qe(), o = r.useRef(null), ke = Le(p), y = () => v ? Ve(v) : { filters: [], logic: "and" }, Ee = () => { var n; const e = (n = o == null ? void 0 : o.current) == null ? void 0 : n.field; return y().filters.findIndex( (s) => s.filters && s.filters.length > 0 && s.filters[0].field === e ); }, E = (e, t) => { var s; const l = ((s = o == null ? void 0 : o.current) == null ? void 0 : s.field) || "", n = e.map((u) => he(l, u)); return t ? n.filter((u, w) => n.indexOf(u) === w) : n; }, c = r.useRef(Ee()), [pe, F] = r.useState(!1), [d, z] = r.useState( (k == null ? void 0 : k.map((e) => ({ column: e, expanded: !1 }))) || [] ), [K, j] = r.useState(""), [M, C] = r.useState(E(a.data, h) || []), [H, W] = r.useState(E(a.data, !1) || []), [f, _] = r.useState(y()), [Ce, $] = r.useState(!1), be = m.toLanguageString(B, g[B]), J = r.useMemo( () => (k == null ? void 0 : k.filter((e) => { var t; return (t = e.title || e.field) == null ? void 0 : t.toLowerCase(); })) || [], [k] ); r.useEffect(() => { v && F(!0); }, [v]), r.useEffect(() => { var l; const e = ((l = o == null ? void 0 : o.current) == null ? void 0 : l.field) || "", t = a.data.map((n) => he(e, n)); Ue(t, H) || (C(t), W(t)); }, [H, a.data]), r.useEffect(() => { d.find((e) => e.expanded) && C(E(a.data, h) || []); }, [d, a.data, h]); const Q = r.useCallback( (e) => { const t = f.filters.some((l) => l.field === e.field); return /* @__PURE__ */ r.createElement(r.Fragment, null, e.title || e.field, t && /* @__PURE__ */ r.createElement("span", { className: "k-columnmenu-indicators" }, /* @__PURE__ */ r.createElement(Oe, { key: 1, icon: ie }))); }, [f] ), U = r.useCallback((e, t) => { z((l) => (o.current = t, l.map((n) => n.column.field === t.field ? { ...n, expanded: !n.expanded } : { ...n, expanded: !1 }))), C(E(a.data, h) || []), W(E(a.data, h) || []), $(!Ce); }, []), X = (e) => { var n; const t = a.searchBoxFilterOperator ? a.searchBoxFilterOperator : "startswith", l = { logic: "and", filters: [ { field: (n = o == null ? void 0 : o.current) == null ? void 0 : n.field, operator: t, value: e.target.value, ignoreCase: !0 } ] }; j(e.target.value), C(E(ce(a.data || [], l), h)); }, ve = () => { var l; const e = a.searchBoxFilterOperator ? a.searchBoxFilterOperator : "startswith", t = { logic: "and", filters: [ { field: (l = o == null ? void 0 : o.current) == null ? void 0 : l.field, operator: e, value: "", ignoreCase: !0 } ] }; j(""), C(E(ce(a.data || [], t), h)); }, Y = () => { let e = !1; if (f) { const t = [...f.filters]; return c.current === -1 ? !1 : (e = M.every((l) => c.current !== -1 && t[c.current].filters ? t[c.current].filters.findIndex( (s) => s.value === l ) >= 0 : !1), e); } return e; }, A = (e, t) => { var w; const l = ((w = o == null ? void 0 : o.current) == null ? void 0 : w.field) || "", n = { ...f }, s = [...f.filters]; let u = []; if (c.current !== -1 && n.filters[c.current].filters && t !== "all" && (u = n.filters[c.current].filters), e.value && t === "all") M.forEach((G) => { u.push({ field: l, operator: "eq", value: G }); }); else if (e.value) u.push({ field: l, operator: "eq", value: t }); else if (f) { const G = u.findIndex((ye) => ye.value === t); u.splice(G, 1); } n.logic = "and", c.current !== -1 ? s[c.current] = { logic: "or", filters: u } : s.push({ logic: "or", filters: u }), (!e.value && t === "all" || u.length === 0) && s.splice(c.current, 1), n.filters = s, _(n); }, L = []; if (f) { const e = [...f.filters]; c.current = e.findIndex((t) => { var l; return t.filters && t.filters.length > 0 ? t.filters[0].field === ((l = o == null ? void 0 : o.current) == null ? void 0 : l.field) : !1; }), c.current !== -1 && e[c.current].filters.length > 0 && e[c.current].filters.forEach((t) => { var l; t.field === ((l = o == null ? void 0 : o.current) == null ? void 0 : l.field) && L.push(t.value); }); } const O = L.filter((e, t) => L.indexOf(e) === t), Z = (e) => { if (e.preventDefault(), !i.filterChange) return; const t = f || null; t !== null && t.filters.length > 0 ? (c.current >= 0 && t.filters.splice(c.current, 1), i.filterChange(t, e)) : i.filterChange(null, e), a.onCloseMenu && a.onCloseMenu(), F(!1); }, R = (e) => { if (e.preventDefault(), !i.filterChange) return; const t = f || null; i.filterChange(t, e), a.onCloseMenu && a.onCloseMenu(), F(!0), x(!1); }, ee = a.searchBox ? /* @__PURE__ */ r.createElement(a.searchBox, { value: K, onChange: X }) : /* @__PURE__ */ r.createElement( "div", { className: `k-searchbox k-textbox k-input k-input-solid ${i != null && i.mobileMode ? "k-input-lg" : "k-input-md"}` }, /* @__PURE__ */ r.createElement(Te, { className: "k-input-icon", name: "search", icon: We }), /* @__PURE__ */ r.createElement( Je, { className: "k-input-inner", type: "text", placeholder: m.toLanguageString(ue, g[ue]), value: K, onChange: (e) => X(e.nativeEvent) } ), /* @__PURE__ */ r.createElement( b, { type: "button", rounded: null, className: "k-input-button", onClick: ve, icon: "x", "aria-label": be, svgIcon: _e } ) ), xe = () => { $(!1); }, Fe = (e) => { e.preventDefault(), x(!S); }, Me = (e) => { !e.isAnchorClicked && x(!1); }, T = r.useMemo(() => a.show !== void 0 ? a.show : S, [a.show, S]), we = (e) => { const t = qe(document); clearTimeout(N.current), N.current = window.setTimeout(() => { !i.mobileMode && t && e.relatedTarget !== p.current && I.current && !I.current.contains(t) && te(); }); }, te = () => { var e; a.onCloseMenu && a.onCloseMenu(), x(!1), p.current && ((e = p.current.element) == null || e.focus()); }, Be = () => { clearTimeout(N.current); }, { onFocus: De, onBlur: Se } = Ge({ onFocus: (e) => Be(), onBlur: (e) => we(e) }), Ie = (e) => { var t; (t = q.current) == null || t.triggerMouseEvent(e); }, Ne = (e) => { var t; (t = q.current) == null || t.triggerKeyboardEvent(e); }, re = (e) => { if (e.preventDefault(), !i.filterChange) return; const t = f || null; t !== null && t.filters.length > 0 ? (t.filters = [], i.filterChange(t, e)) : i.filterChange(null, e), _(y()), F(!1), z( (l) => l.map((n) => ({ ...n, expanded: !1 })) ); }, ne = /* @__PURE__ */ r.createElement( b, { ref: p, togglable: !0, selected: T, svgIcon: P || (V ? void 0 : ie), icon: V, size: i.mobileMode ? "large" : "medium", className: Pe("k-toolbar-button", { "k-icon-button": i.mobileMode }), title: m.toLanguageString(D, g[D]), onClick: Fe }, !i.mobileMode && m.toLanguageString(D, g[D]) ), le = /* @__PURE__ */ r.createElement(r.Fragment, null, J.map((e) => { var t, l; return e.filterable && /* @__PURE__ */ r.createElement(je, { key: e.id }, /* @__PURE__ */ r.createElement("div", { className: "k-expander" }, /* @__PURE__ */ r.createElement( ze, { title: Q(e), expandable: !0, expanded: !!((t = d == null ? void 0 : d.find((n) => n.column.field === e.field)) != null && t.expanded), onClick: (n) => U(n, e) } )), /* @__PURE__ */ r.createElement( Ke, { show: !!((l = d == null ? void 0 : d.find((n) => n.column.field === e.field)) != null && l.expanded) }, /* @__PURE__ */ r.createElement("form", { className: "k-filter-menu", onSubmit: R, onReset: Z }, /* @__PURE__ */ r.createElement("div", { className: "k-filter-menu-container" }, ee, /* @__PURE__ */ r.createElement("ul", { className: "k-multicheck-wrap" }, /* @__PURE__ */ r.createElement("li", { className: "k-item k-check-all-wrap" }, /* @__PURE__ */ r.createElement( se, { label: m.toLanguageString( fe, g[fe] ), onChange: (n) => A(n, "all"), checked: Y() } )), M.map((n, s) => /* @__PURE__ */ r.createElement("li", { className: "k-item", key: s }, /* @__PURE__ */ r.createElement( se, { label: String(n), onChange: (u) => A(u, n), checked: O.includes(n) } )))), /* @__PURE__ */ r.createElement("div", { className: "k-filter-selected-items" }, O.length + " " + m.toLanguageString( me, g[me] )), /* @__PURE__ */ r.createElement("div", { className: "k-actions k-hstack k-justify-content-stretch" }, /* @__PURE__ */ r.createElement(b, { themeColor: "primary", type: "submit" }, m.toLanguageString( de, g[de] )), /* @__PURE__ */ r.createElement(b, { className: "k-button", type: "reset" }, m.toLanguageString( B, g[B] ))))) )); }), /* @__PURE__ */ r.createElement("div", { className: "k-actions k-actions-stretched k-actions-horizontal k-column-menu-footer" }, /* @__PURE__ */ r.createElement(b, { svgIcon: $e, onClick: re }, m.toLanguageString(ge, g[ge])))); return /* @__PURE__ */ r.createElement(r.Fragment, null, pe ? /* @__PURE__ */ r.createElement(Ze, null, ne, /* @__PURE__ */ r.createElement(Re, { themeColor: "primary" })) : ne, i.mobileMode ? /* @__PURE__ */ r.createElement(et, null, Ae.createPortal( /* @__PURE__ */ r.createElement( Xe, { filtered: J, computedShow: T, expandState: d, currentData: M, uniqueFilterValues: O, searchBox: ee, renderTitle: Q, onBackView: xe, isAllSelected: Y, handleCheckBoxChange: A, clear: Z, submit: R, onClose: te, onFilterExpand: U, handleClearAllFilters: re }, le ), (ae = ke()) == null ? void 0 : ae.body )) : /* @__PURE__ */ r.createElement( Ye, { anchor: (oe = p.current) == null ? void 0 : oe.element, show: T, popupClass: "k-grid-columnmenu-popup", onMouseDownOutside: Me }, /* @__PURE__ */ r.createElement( "div", { ref: I, onBlur: Se, onFocus: De, onMouseDown: Ie, onKeyDown: Ne, className: "k-column-menu k-column-menu-md" }, le ) )); }; rt.displayName = "KendoReactGridToolbarCheckboxFilter"; export { rt as GridToolbarCheckboxFilter };