@progress/kendo-react-grid
Version: 
React Data Grid (Table) provides 100+ ready-to-use data grid features. KendoReact Grid package
275 lines (274 loc) • 11.5 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 Oe from "react-dom";
import { useDocument as Ve, SvgIcon as Ue, useAsyncFocusBlur as ze, classNames as Ke, getActiveElement as _e } from "@progress/kendo-react-common";
import { GridColumnMenuItem as He } from "../columnMenu/GridColumnMenuItem.mjs";
import { GridColumnMenuItemContent as je } from "../columnMenu/GridColumnMenuItemContent.mjs";
import { GridColumnMenuItemGroup as qe } from "../columnMenu/GridColumnMenuItemGroup.mjs";
import { GridContext as Je } from "../utils/GridContext.mjs";
import { filterIcon as me, filterClearIcon as Qe } from "@progress/kendo-svg-icons";
import { getFilterType as de, operatorMap as V, defaultHideSecondFilter as We, IsUnaryFilter as b, getDefaultOperator as Xe, booleanFilterValues as Ye, filterLogicList as Ze } from "../filterCommon.mjs";
import { Button as k } from "@progress/kendo-react-buttons";
import { GridColumnMenuFilterUI as $e } from "../columnMenu/GridColumnMenuFilterUI.mjs";
import { toolbarFilter as M, messages as F, filterSubmitButton as ge, filterClearButton as pe, filterClearAllButton as he } from "../messages/index.mjs";
import { useLocalization as xe } from "@progress/kendo-react-intl";
import { rootFilterOrDefault as w, filterGroupByField as Re } from "../columnMenu/GridColumnMenuFilter.mjs";
import { Popup as et } from "@progress/kendo-react-popup";
import { BadgeContainer as tt, Badge as rt } from "@progress/kendo-react-indicators";
import { GridToolbarAdaptiveProvider as ot } from "./adaptiveContext/GridToolbarAdaptiveContext.mjs";
import { GridAdaptiveToolbarFilter as lt } from "./adaptiveContent/GridAdaptiveToolbarFilter.mjs";
const nt = (c) => {
  var re, oe, le, ne, ie, ae, se;
  const n = t.useContext(Je), m = n.columnsRef, U = n.filter, p = n.defaultFilter, [S, E] = t.useState(!1), [ve, h] = t.useState(!1), [d, D] = t.useState(
    (m == null ? void 0 : m.map((e) => ({ column: e, expanded: !1 }))) || []
  ), [Fe, z] = t.useState(!1), g = t.useRef(null), y = t.useRef(null), K = t.useRef(null), I = t.useRef(0), r = t.useRef(null), f = xe(), Ee = Ve(g), _ = t.useMemo(
    () => (m == null ? void 0 : m.filter((e) => {
      var o;
      return (o = e.title || e.field) == null ? void 0 : o.toLowerCase();
    })) || [],
    [m]
  );
  t.useEffect(() => {
    h(!!(p || U));
  }, [p, U]);
  const H = t.useCallback(
    (e) => {
      const o = p && p.filters.some((i) => i.field === e.field);
      return /* @__PURE__ */ t.createElement(t.Fragment, null, e.title || e.field, o && /* @__PURE__ */ t.createElement("span", { className: "k-columnmenu-indicators" }, /* @__PURE__ */ t.createElement(Ue, { key: 1, icon: me })));
    },
    [p]
  ), j = (e, o) => {
    D((i) => (r.current = o, i.map((l) => l.column.field === o.field ? { ...l, expanded: !l.expanded } : { ...l, expanded: !1 }))), B(q()), z(!Fe);
  }, q = () => {
    var o, i, l, s, ce, ue;
    let e;
    if (r != null && r.current && ((o = r == null ? void 0 : r.current) != null && o.field)) {
      const Ge = de((i = r == null ? void 0 : r.current) == null ? void 0 : i.filter), v = Xe(n.filterOperators, Ge);
      e = Re((l = r == null ? void 0 : r.current) == null ? void 0 : l.field, n.filter), e = e ? {
        ...e,
        filters: e.filters.map((O) => ({ ...O }))
      } : {
        logic: "and",
        filters: [
          {
            field: (s = r == null ? void 0 : r.current) == null ? void 0 : s.field,
            operator: v,
            value: b(v) ? null : void 0
          },
          {
            field: (ce = r == null ? void 0 : r.current) == null ? void 0 : ce.field,
            operator: v,
            value: b(v) ? null : void 0
          }
        ]
      }, e.filters.filter((O) => {
        var fe;
        return O.field === ((fe = r == null ? void 0 : r.current) == null ? void 0 : fe.field);
      }).length === 1 && e.filters.splice(1, 0, {
        field: (ue = r == null ? void 0 : r.current) == null ? void 0 : ue.field,
        operator: v
      });
    }
    return e;
  }, Ce = (e) => {
    J(0, e);
  }, be = (e) => {
    J(1, e);
  }, J = (e, o) => {
    const i = u.filters.map((l, s) => s === e ? {
      ...l,
      value: o.value || "",
      operator: o.operator || A[s].operator
    } : l);
    B({
      ...u,
      filters: i
    });
  }, [u, B] = t.useState(q()), a = u == null ? void 0 : u.filters, C = de((re = r == null ? void 0 : r.current) == null ? void 0 : re.filter), A = V(n.filterOperators[C], f), Q = V(Ye, f), ke = {
    field: (oe = r == null ? void 0 : r.current) == null ? void 0 : oe.field,
    value: a == null ? void 0 : a[0].value,
    operator: a == null ? void 0 : a[0].operator,
    operators: A,
    booleanValues: Q,
    onChange: Ce,
    filterType: C
  }, Me = {
    field: (le = r == null ? void 0 : r.current) == null ? void 0 : le.field,
    value: a == null ? void 0 : a[1].value,
    operator: a == null ? void 0 : a[1].operator,
    operators: A,
    booleanValues: Q,
    onChange: be,
    filterType: C
  }, we = (e) => {
    let o = e.target.value;
    e.target.tagName === "SPAN" && (o = e.target.parentElement.value), B({ ...u, logic: o });
  }, W = u == null ? void 0 : u.logic, X = V(Ze, f), T = {
    value: X.find((e) => e.operator === (W === null ? "" : W)),
    onChange: we,
    data: X
  }, Se = c.hideSecondFilter !== void 0 ? c.hideSecondFilter : We[C], N = c.filterUI, L = {
    firstFilterProps: ke,
    secondFilterProps: Me,
    logicData: T.data,
    logicValue: T.value,
    onLogicChange: T.onChange,
    hideSecondFilter: Se
  }, Y = () => ({
    ...u,
    filters: u == null ? void 0 : u.filters.filter((e) => e.value !== void 0 && e.value !== null && e.value !== "" || e.value === null && e.operator)
  }), P = ((ie = (ne = Y()) == null ? void 0 : ne.filters) == null ? void 0 : ie.length) !== 0 || b(a == null ? void 0 : a[0].operator) || b(a == null ? void 0 : a[1].operator), Z = (e) => {
    if (e.preventDefault(), !n.filterChange)
      return;
    const o = w(n.filter), i = {
      ...o,
      filters: o.filters.filter((l) => {
        var s;
        return l.field !== ((s = r == null ? void 0 : r.current) == null ? void 0 : s.field);
      })
    };
    P && i.filters.push(Y()), n.filterChange(i, e), h(!0), E(!1);
  }, $ = (e) => {
    if (e.preventDefault(), !n.filterChange)
      return;
    const o = w(n.filter), i = o.filters.filter((l) => {
      var s;
      return l.field !== ((s = r == null ? void 0 : r.current) == null ? void 0 : s.field);
    });
    i.length === 0 ? n.filterChange(null, e) : n.filterChange({ ...o, filters: i }, e), c.onCloseMenu && c.onCloseMenu(), h(!1), D(
      (l) => l.map((s) => ({
        ...s,
        expanded: !1
      }))
    );
  }, De = () => {
    z(!1);
  }, ye = (e) => {
    e.preventDefault(), E(!S);
  }, Ie = (e) => {
    !e.isAnchorClicked && E(!1);
  }, G = t.useMemo(() => c.show !== void 0 ? c.show : S, [c.show, S]), Be = (e) => {
    const o = _e(document);
    clearTimeout(I.current), I.current = window.setTimeout(() => {
      !n.mobileMode && o && e.relatedTarget !== g.current && y.current && !y.current.contains(o) && x();
    });
  }, x = () => {
    var e;
    c.onCloseMenu && c.onCloseMenu(), E(!1), g.current && ((e = g.current.element) == null || e.focus());
  }, Ae = () => {
    clearTimeout(I.current);
  }, { onFocus: Te, onBlur: Ne } = ze({
    onFocus: (e) => Ae(),
    onBlur: (e) => Be(e)
  }), Le = (e) => {
    var o;
    (o = K.current) == null || o.triggerMouseEvent(e);
  }, Pe = (e) => {
    var o;
    (o = K.current) == null || o.triggerKeyboardEvent(e);
  }, R = t.useCallback(
    (e) => {
      if (e.preventDefault(), !n.filterChange)
        return;
      const o = w(n.filter), i = o.filters.filter(() => !1);
      i.length === 0 ? n.filterChange(null, e) : n.filterChange({ ...o, filters: i }, e), h(!1), D(
        (l) => l.map((s) => ({
          ...s,
          expanded: !1
        }))
      );
    },
    [n, w]
  ), ee = /* @__PURE__ */ t.createElement(
    k,
    {
      ref: g,
      togglable: !0,
      selected: G,
      svgIcon: c.svgIcon ? c.svgIcon : c.icon ? void 0 : me,
      icon: c.icon,
      size: n.mobileMode ? "large" : "medium",
      className: Ke("k-toolbar-button", {
        "k-icon-button": n.mobileMode
      }),
      title: f.toLanguageString(M, F[M]),
      onClick: ye
    },
    !n.mobileMode && f.toLanguageString(M, F[M])
  ), te = /* @__PURE__ */ t.createElement(t.Fragment, null, _.map((e) => {
    var o, i;
    return e.filterable && /* @__PURE__ */ t.createElement(qe, { key: e.id }, /* @__PURE__ */ t.createElement("div", { className: "k-expander" }, /* @__PURE__ */ t.createElement(
      He,
      {
        title: H(e),
        expandable: !0,
        expanded: !!((o = d == null ? void 0 : d.find((l) => l.column.field === e.field)) != null && o.expanded),
        onClick: (l) => j(l, e)
      }
    )), /* @__PURE__ */ t.createElement(
      je,
      {
        show: !!((i = d == null ? void 0 : d.find((l) => l.column.field === e.field)) != null && i.expanded)
      },
      /* @__PURE__ */ t.createElement("form", { className: "k-filter-menu", onSubmit: Z, onReset: $ }, /* @__PURE__ */ t.createElement("div", { className: "k-filter-menu-container" }, N ? /* @__PURE__ */ t.createElement(N, { ...L }) : /* @__PURE__ */ t.createElement($e, { ...L }), /* @__PURE__ */ t.createElement("div", { className: "k-actions k-actions-stretched" }, /* @__PURE__ */ t.createElement(k, { themeColor: "primary", disabled: !P }, f.toLanguageString(
        ge,
        F[ge]
      )), /* @__PURE__ */ t.createElement(k, { type: "reset" }, f.toLanguageString(
        pe,
        F[pe]
      )))))
    ));
  }), /* @__PURE__ */ t.createElement("div", { className: "k-actions k-actions-stretched k-actions-horizontal k-column-menu-footer" }, /* @__PURE__ */ t.createElement(k, { svgIcon: Qe, onClick: R }, f.toLanguageString(he, F[he]))));
  return /* @__PURE__ */ t.createElement(t.Fragment, null, ve ? /* @__PURE__ */ t.createElement(tt, null, ee, /* @__PURE__ */ t.createElement(rt, { themeColor: "primary" })) : ee, n.mobileMode ? /* @__PURE__ */ t.createElement(ot, null, Oe.createPortal(
    /* @__PURE__ */ t.createElement(
      lt,
      {
        filtered: _,
        computedShow: G,
        expandState: d,
        FilterUI: N,
        filterUIProps: L,
        isFilterValid: P,
        renderTitle: H,
        onBackView: De,
        clear: $,
        submit: Z,
        onClose: x,
        onFilterExpand: j,
        handleClearAllFilters: R
      },
      te
    ),
    (ae = Ee()) == null ? void 0 : ae.body
  )) : /* @__PURE__ */ t.createElement(
    et,
    {
      anchor: (se = g.current) == null ? void 0 : se.element,
      show: G,
      popupClass: "k-grid-columnmenu-popup",
      onMouseDownOutside: Ie
    },
    /* @__PURE__ */ t.createElement(
      "div",
      {
        ref: y,
        onBlur: Ne,
        onFocus: Te,
        onMouseDown: Le,
        onKeyDown: Pe,
        className: "k-column-menu k-column-menu-md"
      },
      te
    )
  ));
};
nt.displayName = "KendoReactGridToolbarFilter";
export {
  nt as GridToolbarFilter
};