UNPKG

@progress/kendo-react-grid

Version:

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

398 lines (397 loc) 12.7 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 { SpeechToTextButton as et, Button as tt, SegmentedControl 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 { List as $ } from "@progress/kendo-react-dropdowns"; import { Popup as ct } from "@progress/kendo-react-popup"; import { createListItemRender as ut, searchModeItemRender as pt, listGroupHeaderRender as ue, NoDataRender as mt } from "./listItemRenders.mjs"; import { smartBoxClearTitle as pe, messages as k, smartBoxSpeechToTextButton as P, smartBoxSubmitPromptButton as L } from "../../messages/index.mjs"; import { useGridAIRequest as dt } from "../../hooks/useGridAIRequest.mjs"; import { GridContext as ft } from "../../utils/GridContext.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 vt } from "./hooks/useDebounce.mjs"; const It = e.forwardRef((me, de) => { var ie; const { searchConfig: fe, semanticSearchConfig: he, aiAssistantConfig: ge, activeMode: Se, dir: ke = "ltr", size: K = "medium", placeholder: Ce, history: be, loading: xe = !1, promptSuggestionRender: j, historyItemRender: J, onOpen: Re, onClose: ve, onFocus: C, onBlur: b, onSearch: Ie, onSemanticSearch: we, onAIPromptRequest: F, onAIResponseSuccess: H, onAIResponseError: z, onAICancelRequest: x } = me, h = lt(), g = e.useContext(ft), Ee = e.useRef(`k-${ot()}`), d = e.useRef(null), S = e.useRef(null), M = e.useRef(null), [o, p] = e.useState(""), [De, R] = e.useState(!1), [ye, Q] = e.useState(void 0), [Be, X] = e.useState(null), { searchMode: i, semanticSearchMode: c, aiAssistantMode: s, selectedView: n, setSelectedViewState: N, lastSearchMode: Pe, searchHistorySettings: Y, semanticSearchHistorySettings: Z, aiAssistantHistorySettings: T, speechToTextButtonSettings: _, currentSearchDelay: Le } = ht({ searchConfigProp: fe, semanticSearchConfigProp: he, aiAssistantConfigProp: ge, activeModeProp: Se, sharedHistory: be }), { currentHistory: v, currentHistorySettings: Fe, addToHistory: q } = gt({ selectedView: n, searchHistorySettings: Y, semanticSearchHistorySettings: Z, aiAssistantHistorySettings: T }), { isOpen: O, togglePopup: a } = St({ onOpen: Re, onClose: ve }), { columns: A, gridState: He, gridRef: ze, handleStateChange: Ne } = kt(g), V = 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: I, searchHistoryListData: w } = bt({ selectedView: n, searchModeEnabled: i == null ? void 0 : i.enabled, semanticSearchModeEnabled: c == null ? void 0 : c.enabled, promptSuggestions: V, currentHistory: v, currentHistorySettings: Fe }), E = xt({ searchMode: i, semanticSearchMode: c, aiAssistantMode: s, selectedView: n, lastSearchMode: Pe, setSelectedViewState: N, 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, W = !n, Oe = !(i != null && i.enabled) && !(c != null && c.enabled) && !(s != null && s.enabled), Ve = it.sizeMap[K] || "md", { emitSearchEvent: u } = Rt({ selectedView: n, searchMode: i, columns: A, gridContext: g, searchHistorySettings: Y, semanticSearchHistorySettings: Z, addToHistory: q, onSearch: Ie, onSemanticSearch: we }), { sendRequest: ee, cancelRequest: te } = dt({ requestUrl: s == null ? void 0 : s.requestUrl, requestOptions: s == null ? void 0 : s.requestOptions, columns: A, gridState: He, gridRef: ze, onPromptRequest: (t) => { F == null || F({ requestData: t }); }, onResponseSuccess: (t) => { R(!1), H == null || H({ response: t }); }, onResponseError: (t) => { R(!1), z == null || z({ error: t }); }, onStateChange: Ne, onExportPdf: () => g == null ? void 0 : g.exportAsPdf() }); e.useImperativeHandle( de, () => ({ show: () => a(!0), hide: () => a(!1) }), [a] ); const G = vt(Be, Le), ne = e.useRef(u); ne.current = u, e.useEffect(() => { G !== null && ne.current(G); }, [G]); 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 = M.current) == null ? void 0 : le.element, y = t.relatedTarget, _e = y && (r == null ? void 0 : r.contains(y)), Ae = y && (l == null ? void 0 : l.contains(y)); !_e && !Ae && (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), U = e.useCallback(() => { if (m) { x == null || x(), te(), R(!1); return; } o.trim() && (re && R(!0), q("aiAssistant", o, T), a(!1), ee(o.trim()), p("")); }, [ m, o, T, a, q, ee, te, re, x ]), Ke = e.useCallback( (t) => { t.key === "Enter" && (n === "aiAssistant" ? U() : n === "semanticSearch" && u(o)); }, [n, o, u, U] ), je = e.useCallback(() => { var t; a(!O), (t = S.current) == null || t.focus(); }, [O, 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; N(t), p(""), X(null), (r = S.current) == null || r.focus(); }, [N] ), D = e.useCallback( (t) => { var r; p(t), a(!1), (r = S.current) == null || r.focus(), n !== "aiAssistant" && u(t); }, [n, a, u] ), Me = e.useCallback((t) => { if (t.isFinal && t.alternatives.length > 0) { const r = t.alternatives[0].transcript; p((l) => l ? `${l} ${r}` : r); } }, []), Qe = e.useMemo(() => n === "aiAssistant" ? v.length === 0 && V.length === 0 : n === "search" || n === "semanticSearch" ? v.length === 0 && f.length === 0 : !1, [n, v.length, V.length, f.length]), ae = e.useCallback( (t) => { const l = (n === "aiAssistant" ? I : w)[t]; l && D(l.text); }, [n, I, w, D] ), Xe = e.useCallback( (t) => { const r = f[t]; r && se(r.mode); }, [f, se] ), oe = e.useMemo( () => ut({ historyItemRender: J, promptSuggestionRender: j, handleListItemClick: D }), [J, j, D] ), Ye = O && !Oe, Ze = () => /* @__PURE__ */ e.createElement(e.Fragment, null, E.items.length > 0 && /* @__PURE__ */ e.createElement( nt, { items: E.items, value: E.value, onChange: E.onChange, size: K, layoutMode: "stretch" } ), (n === "search" || n === "semanticSearch") && f.length > 0 && /* @__PURE__ */ e.createElement( $, { data: f, textField: "text", descriptionField: "description", onClick: Xe, itemRender: pt, show: !0, wrapperCssClass: "k-list k-list-md" } ), n === "aiAssistant" && I.length > 0 && /* @__PURE__ */ e.createElement( $, { data: I, 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( $, { 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" } ), Qe && /* @__PURE__ */ e.createElement(mt, { 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 }) }, !W && /* @__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": W }), id: Ee.current, placeholder: Te, value: o, disabled: W, 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( et, { ..._, "aria-label": h.toLanguageString( P, k[P] ), title: h.toLanguageString( P, k[P] ), onResult: Me } ), /* @__PURE__ */ e.createElement( tt, { className: B("k-smart-box-send", { "k-processing": m, "k-active": m }), type: "button", rounded: "full", size: "small", title: h.toLanguageString( L, k[L] ), "aria-label": h.toLanguageString( L, k[L] ), "aria-disabled": o.length === 0, svgIcon: m ? st : at, disabled: o.length === 0 && !m, onClick: U } )) ), /* @__PURE__ */ e.createElement( ct, { ref: M, anchor: d.current, show: Ye, popupClass: "k-smart-box-popup", style: { width: ye }, 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); } }, Ze() )); }); It.displayName = "KendoReactSmartBox"; export { It as SmartBox };