UNPKG

@progress/kendo-react-grid

Version:

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

390 lines (389 loc) 12.6 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2026 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import * as e from "react"; import { SegmentedControl as et } from "./SegmentedControl.mjs"; import { SpeechToTextButton as tt, Button as nt } from "@progress/kendo-react-buttons"; import { xIcon as rt, stopSmIcon as st, arrowUpOutlineIcon as at } from "@progress/kendo-svg-icons"; import { guid as ot, kendoThemeMaps as it, classNames as B, IconWrap as ce } from "@progress/kendo-react-common"; import { useLocalization as lt } from "@progress/kendo-react-intl"; import { useGridAIRequest as ct } from "../../hooks/useGridAIRequest.mjs"; import { GridContext as ut } from "../../utils/GridContext.mjs"; import { List as U } from "@progress/kendo-react-dropdowns"; import { Popup as pt } from "@progress/kendo-react-popup"; import { createListItemRender as mt, searchModeItemRender as dt, listGroupHeaderRender as ue, NoDataRender as ft } from "./listItemRenders.mjs"; import { smartBoxClearTitle as pe, messages as k, smartBoxSpeechToTextButton as y, smartBoxSubmitPromptButton as P } from "../../messages/index.mjs"; import { useSmartBoxModes as ht } from "./hooks/useSmartBoxModes.mjs"; import { useSmartBoxHistory as gt } from "./hooks/useSmartBoxHistory.mjs"; import { useSmartBoxPopup as St } from "./hooks/useSmartBoxPopup.mjs"; import { useSmartBoxGridState as kt } from "./hooks/useSmartBoxGridState.mjs"; import { useSmartBoxLabels as Ct } from "./hooks/useSmartBoxLabels.mjs"; import { useSmartBoxListData as bt } from "./hooks/useSmartBoxListData.mjs"; import { useSmartBoxSegmentedControl as xt } from "./hooks/useSmartBoxSegmentedControl.mjs"; import { useSmartBoxSearch as Rt } from "./hooks/useSmartBoxSearch.mjs"; import { useDebounce as It } from "./hooks/useDebounce.mjs"; const vt = e.forwardRef((me, de) => { var ie; const { searchConfig: fe, semanticSearchConfig: he, aiAssistantConfig: ge, activeMode: Se, dir: ke = "ltr", size: $ = "medium", placeholder: Ce, history: be, loading: xe = !1, promptSuggestionRender: K, historyItemRender: j, onOpen: Re, onClose: Ie, onFocus: C, onBlur: b, onSearch: ve, onSemanticSearch: we, onAIPromptRequest: L, onAIResponseSuccess: F, onAIResponseError: H, onAICancelRequest: x } = me, h = lt(), g = e.useContext(ut), Ee = e.useRef(`k-${ot()}`), d = e.useRef(null), S = e.useRef(null), J = e.useRef(null), [o, p] = e.useState(""), [De, R] = e.useState(!1), [Be, Q] = e.useState(void 0), [ye, X] = e.useState(null), { searchMode: i, semanticSearchMode: c, aiAssistantMode: s, selectedView: n, setSelectedViewState: z, lastSearchMode: Pe, searchHistorySettings: Y, semanticSearchHistorySettings: Z, aiAssistantHistorySettings: N, speechToTextButtonSettings: _, currentSearchDelay: Le } = ht({ searchConfigProp: fe, semanticSearchConfigProp: he, aiAssistantConfigProp: ge, activeModeProp: Se, sharedHistory: be }), { currentHistory: I, currentHistorySettings: Fe, addToHistory: T } = gt({ selectedView: n, searchHistorySettings: Y, semanticSearchHistorySettings: Z, aiAssistantHistorySettings: N }), { isOpen: q, togglePopup: a } = St({ onOpen: Re, onClose: Ie }), { columns: A, gridState: He, gridRef: ze, handleStateChange: Ne } = kt(g), O = e.useMemo( () => (s == null ? void 0 : s.promptSuggestions) || [], [s == null ? void 0 : s.promptSuggestions] ), { inputPlaceholder: Te, prefixIcon: qe } = Ct({ selectedView: n, searchMode: i, semanticSearchMode: c, aiAssistantMode: s, sharedPlaceholder: Ce }), { searchListData: f, aiAssistantListData: v, searchHistoryListData: w } = bt({ selectedView: n, searchModeEnabled: i == null ? void 0 : i.enabled, semanticSearchModeEnabled: c == null ? void 0 : c.enabled, promptSuggestions: O, currentHistory: I, currentHistorySettings: Fe }), M = xt({ searchMode: i, semanticSearchMode: c, aiAssistantMode: s, selectedView: n, lastSearchMode: Pe, setSelectedViewState: z, setInputValue: p }); e.useEffect(() => { const t = d.current; if (!t) return; Q(t.offsetWidth); const r = new ResizeObserver(() => { t && Q(t.offsetWidth); }); return r.observe(t), () => { r.disconnect(); }; }, []); const m = xe || De, V = !n, Oe = !(i != null && i.enabled) && !(c != null && c.enabled) && !(s != null && s.enabled), Ve = it.sizeMap[$] || "md", { emitSearchEvent: u } = Rt({ selectedView: n, searchMode: i, columns: A, gridContext: g, searchHistorySettings: Y, semanticSearchHistorySettings: Z, addToHistory: T, onSearch: ve, onSemanticSearch: we }), { sendRequest: ee, cancelRequest: te } = ct({ requestUrl: s == null ? void 0 : s.requestUrl, requestOptions: s == null ? void 0 : s.requestOptions, columns: A, gridState: He, gridRef: ze, onPromptRequest: (t) => { L == null || L({ requestData: t }); }, onResponseSuccess: (t) => { R(!1), F == null || F({ response: t }); }, onResponseError: (t) => { R(!1), H == null || H({ error: t }); }, onStateChange: Ne, onExportPdf: () => g == null ? void 0 : g.exportAsPdf() }); e.useImperativeHandle( de, () => ({ show: () => a(!0), hide: () => a(!1) }), [a] ); const W = It(ye, Le), ne = e.useRef(u); ne.current = u, e.useEffect(() => { W !== null && ne.current(W); }, [W]); const We = e.useCallback( (t) => { const r = t.target.value; p(r), a(!r), (n === "search" || n === "semanticSearch") && X(r); }, [a, n] ), Ge = e.useCallback(() => { C == null || C(), o || a(!0); }, [C, a, o]), Ue = e.useCallback( (t) => { var le; const r = d.current, l = (le = J.current) == null ? void 0 : le.element, D = t.relatedTarget, Ae = D && (r == null ? void 0 : r.contains(D)), Me = D && (l == null ? void 0 : l.contains(D)); !Ae && !Me && (b == null || b(), a(!1)); }, [b, a] ), $e = e.useCallback(() => { o || a(!0); }, [a, o]), re = !!((ie = s == null ? void 0 : s.requestOptions) != null && ie.url || s != null && s.requestUrl), G = e.useCallback(() => { if (m) { x == null || x(), te(), R(!1); return; } o.trim() && (re && R(!0), T("aiAssistant", o, N), a(!1), ee(o.trim()), p("")); }, [ m, o, N, a, T, ee, te, re, x ]), Ke = e.useCallback( (t) => { t.key === "Enter" && (n === "aiAssistant" ? G() : n === "semanticSearch" && u(o)); }, [n, o, u, G] ), je = e.useCallback(() => { var t; a(!q), (t = S.current) == null || t.focus(); }, [q, a]), Je = e.useCallback( (t) => { var r; t.stopPropagation(), t.preventDefault(), p(""), (r = S.current) == null || r.focus(), a(!0), u(""); }, [a, u] ), se = e.useCallback( (t) => { var r; z(t), p(""), X(null), (r = S.current) == null || r.focus(); }, [z] ), E = e.useCallback( (t) => { var r; p(t), a(!1), (r = S.current) == null || r.focus(), n !== "aiAssistant" && u(t); }, [n, a, u] ), Qe = e.useCallback((t) => { if (t.isFinal && t.alternatives.length > 0) { const r = t.alternatives[0].transcript; p((l) => l ? `${l} ${r}` : r); } }, []), Xe = e.useMemo(() => n === "aiAssistant" ? I.length === 0 && O.length === 0 : n === "search" || n === "semanticSearch" ? I.length === 0 && f.length === 0 : !1, [n, I.length, O.length, f.length]), ae = e.useCallback( (t) => { const l = (n === "aiAssistant" ? v : w)[t]; l && E(l.text); }, [n, v, w, E] ), Ye = e.useCallback( (t) => { const r = f[t]; r && se(r.mode); }, [f, se] ), oe = e.useMemo( () => mt({ historyItemRender: j, promptSuggestionRender: K, handleListItemClick: E }), [j, K, E] ), Ze = q && !Oe, _e = () => /* @__PURE__ */ e.createElement(e.Fragment, null, M.length > 0 && /* @__PURE__ */ e.createElement(et, { buttons: M, size: $, stretched: !0 }), (n === "search" || n === "semanticSearch") && f.length > 0 && /* @__PURE__ */ e.createElement( U, { data: f, textField: "text", descriptionField: "description", onClick: Ye, itemRender: dt, show: !0, wrapperCssClass: "k-list k-list-md" } ), n === "aiAssistant" && v.length > 0 && /* @__PURE__ */ e.createElement( U, { data: v, textField: "text", groupField: "group", svgIconField: "groupSvgIcon", descriptionField: "description", onClick: ae, itemRender: oe, groupHeaderItemRender: ue, showFirstGroupHeader: !0, show: !0, wrapperCssClass: "k-list k-list-md" } ), (n === "search" || n === "semanticSearch") && w.length > 0 && /* @__PURE__ */ e.createElement( U, { data: w, textField: "text", groupField: "group", svgIconField: "groupSvgIcon", descriptionField: "description", onClick: ae, itemRender: oe, groupHeaderItemRender: ue, showFirstGroupHeader: !0, show: !0, wrapperCssClass: "k-list k-list-md" } ), Xe && /* @__PURE__ */ e.createElement(ft, { selectedView: n })); return /* @__PURE__ */ e.createElement("div", { ref: d, className: "k-smart-box-wrapper", dir: ke, onBlur: Ue }, /* @__PURE__ */ e.createElement( "span", { className: B("k-smart-box", "k-input", `k-input-${Ve}`, { "k-loading": m }) }, !V && /* @__PURE__ */ e.createElement("span", { className: "k-input-prefix k-input-prefix-horizontal" }, /* @__PURE__ */ e.createElement( ce, { className: B("k-icon", { "k-accent-icon": n === "aiAssistant" || n === "semanticSearch" }), icon: qe.svgIcon, onClick: je, onMouseDown: (t) => { "preventDefault" in t && t.preventDefault(); } } )), /* @__PURE__ */ e.createElement( "input", { ref: S, type: "text", className: B("k-input-inner", { "k-disabled": V }), id: Ee.current, placeholder: Te, value: o, disabled: V, onChange: We, onFocus: Ge, onClick: $e, onKeyDown: Ke } ), o.length > 0 && (n === "search" || n === "semanticSearch") && /* @__PURE__ */ e.createElement( "span", { className: "k-clear-value", title: h.toLanguageString( pe, k[pe] ), role: "button", tabIndex: -1, onClick: Je, onMouseDown: (t) => t.preventDefault() }, /* @__PURE__ */ e.createElement(ce, { className: "k-icon", icon: rt }) ), n === "aiAssistant" && /* @__PURE__ */ e.createElement("span", { className: "k-input-suffix k-input-suffix-horizontal" }, _ && /* @__PURE__ */ e.createElement( tt, { ..._, "aria-label": h.toLanguageString( y, k[y] ), title: h.toLanguageString( y, k[y] ), onResult: Qe } ), /* @__PURE__ */ e.createElement( nt, { className: B("k-smart-box-send", { "k-processing": m, "k-active": m }), type: "button", rounded: "full", size: "small", title: h.toLanguageString( P, k[P] ), "aria-label": h.toLanguageString( P, k[P] ), "aria-disabled": o.length === 0, svgIcon: m ? st : at, disabled: o.length === 0 && !m, onClick: G } )) ), /* @__PURE__ */ e.createElement( pt, { ref: J, anchor: d.current, show: Ze, popupClass: "k-smart-box-popup", style: { width: Be }, anchorAlign: { horizontal: "left", vertical: "bottom" }, popupAlign: { horizontal: "left", vertical: "top" }, margin: { horizontal: 0, vertical: 2 }, onMouseDownOutside: (t) => { const r = t.event.target; d.current && !d.current.contains(r) && a(!1); } }, _e() )); }); vt.displayName = "KendoReactSmartBox"; export { vt as SmartBox };