@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
JavaScript
/**
* @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
};