@rufous/ui 0.3.20 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +54 -21
- package/dist/main.d.cts +17 -4
- package/dist/main.d.ts +17 -4
- package/dist/main.js +54 -21
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -4773,6 +4773,7 @@ function DataGrid({
|
|
|
4773
4773
|
const menuRef = (0, import_react23.useRef)(null);
|
|
4774
4774
|
const [showManageColumns, setShowManageColumns] = (0, import_react23.useState)(false);
|
|
4775
4775
|
const [showAdvancedFilter, setShowAdvancedFilter] = (0, import_react23.useState)(false);
|
|
4776
|
+
const [focusFilterIdx, setFocusFilterIdx] = (0, import_react23.useState)(-1);
|
|
4776
4777
|
const filterableColumnsProp = initialColumnsProp.filter((c) => c.filterable !== false);
|
|
4777
4778
|
const initialFilterCol = String(filterableColumnsProp[0]?.field || filterableColumnsProp[0]?.key || "");
|
|
4778
4779
|
const [advancedFilters, setAdvancedFilters] = (0, import_react23.useState)([
|
|
@@ -4821,9 +4822,13 @@ function DataGrid({
|
|
|
4821
4822
|
return next;
|
|
4822
4823
|
});
|
|
4823
4824
|
}, [initialColumnsProp]);
|
|
4825
|
+
const onFiltersChangeRef = (0, import_react23.useRef)(onFiltersChange);
|
|
4824
4826
|
(0, import_react23.useEffect)(() => {
|
|
4825
|
-
onFiltersChange
|
|
4826
|
-
}
|
|
4827
|
+
onFiltersChangeRef.current = onFiltersChange;
|
|
4828
|
+
});
|
|
4829
|
+
(0, import_react23.useEffect)(() => {
|
|
4830
|
+
onFiltersChangeRef.current?.(advancedFilters);
|
|
4831
|
+
}, [advancedFilters]);
|
|
4827
4832
|
const handleSort = (fieldKey, dir) => {
|
|
4828
4833
|
if (dir !== void 0) {
|
|
4829
4834
|
setSortField(fieldKey);
|
|
@@ -5092,6 +5097,7 @@ function DataGrid({
|
|
|
5092
5097
|
if (!firstCol) return prev;
|
|
5093
5098
|
return [{ column: String(firstCol.field), operator: getDefaultOperator(firstCol.type), value: "", logic: "AND" }];
|
|
5094
5099
|
});
|
|
5100
|
+
setFocusFilterIdx(-1);
|
|
5095
5101
|
setShowAdvancedFilter(false);
|
|
5096
5102
|
};
|
|
5097
5103
|
const activeMenuCol = activeMenu ? resolvedColumns.find((c) => String(c.field) === activeMenu) : null;
|
|
@@ -5143,7 +5149,18 @@ function DataGrid({
|
|
|
5143
5149
|
},
|
|
5144
5150
|
col.headerName,
|
|
5145
5151
|
col.sortable !== false && /* @__PURE__ */ import_react23.default.createElement("span", { className: `dg-sort-icon${isSorted ? " dg-sort-icon--active" : ""}` }, isSorted && sortDirection === "asc" && /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.ChevronUp, { size: 14 }), isSorted && sortDirection === "desc" && /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.ChevronDown, { size: 14 }), !isSorted && /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.ChevronsUpDown, { size: 14 }))
|
|
5146
|
-
), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-th-actions${isFiltered ? " dg-th-actions--filtered" : ""}` }, isFiltered && /* @__PURE__ */ import_react23.default.createElement(
|
|
5152
|
+
), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-th-actions${isFiltered ? " dg-th-actions--filtered" : ""}` }, isFiltered && /* @__PURE__ */ import_react23.default.createElement(
|
|
5153
|
+
"button",
|
|
5154
|
+
{
|
|
5155
|
+
className: "dg-th-filter-btn",
|
|
5156
|
+
onClick: () => {
|
|
5157
|
+
const idx2 = advancedFilters.findIndex((f) => f.column === colField);
|
|
5158
|
+
setFocusFilterIdx(idx2);
|
|
5159
|
+
setShowAdvancedFilter(true);
|
|
5160
|
+
}
|
|
5161
|
+
},
|
|
5162
|
+
/* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Filter, { size: 11 })
|
|
5163
|
+
), !col.disableColumnMenu && /* @__PURE__ */ import_react23.default.createElement(
|
|
5147
5164
|
"button",
|
|
5148
5165
|
{
|
|
5149
5166
|
className: "dg-th-menu-btn",
|
|
@@ -5372,7 +5389,7 @@ function DataGrid({
|
|
|
5372
5389
|
className: "dg-filter-input",
|
|
5373
5390
|
placeholder: "Value\u2026",
|
|
5374
5391
|
value: f.value,
|
|
5375
|
-
autoFocus: idx === advancedFilters.length - 1,
|
|
5392
|
+
autoFocus: focusFilterIdx >= 0 ? idx === focusFilterIdx : idx === advancedFilters.length - 1,
|
|
5376
5393
|
onChange: (e) => setAdvancedFilters((p) => p.map((fi, i) => i === idx ? { ...fi, value: e.target.value } : fi))
|
|
5377
5394
|
}
|
|
5378
5395
|
));
|
|
@@ -9550,7 +9567,9 @@ function SmartSelect({
|
|
|
9550
9567
|
value,
|
|
9551
9568
|
onChange,
|
|
9552
9569
|
onSearchChange,
|
|
9570
|
+
searchResults = [],
|
|
9553
9571
|
debounceMs = 300,
|
|
9572
|
+
searchThreshold = 10,
|
|
9554
9573
|
getOptionLabel,
|
|
9555
9574
|
getOptionValue,
|
|
9556
9575
|
getOptionSubLabel,
|
|
@@ -9588,14 +9607,20 @@ function SmartSelect({
|
|
|
9588
9607
|
return flattenTree(options, getOptionChildren);
|
|
9589
9608
|
}, [options, getOptionChildren]);
|
|
9590
9609
|
const flatOptionsList = (0, import_react51.useMemo)(() => flatItems.map((f) => f.option), [flatItems]);
|
|
9610
|
+
const displayOptions = (0, import_react51.useMemo)(() => {
|
|
9611
|
+
if (!searchResults.length) return flatOptionsList;
|
|
9612
|
+
const localKeys = new Set(flatOptionsList.map((o) => getValue(o)));
|
|
9613
|
+
const serverOnly = searchResults.filter((o) => !localKeys.has(getValue(o)));
|
|
9614
|
+
return [...flatOptionsList, ...serverOnly];
|
|
9615
|
+
}, [flatOptionsList, searchResults, getValue]);
|
|
9591
9616
|
const depthMap = (0, import_react51.useMemo)(() => {
|
|
9592
9617
|
const map = /* @__PURE__ */ new Map();
|
|
9593
9618
|
flatItems.forEach(({ option, depth }) => map.set(getValue(option), depth));
|
|
9594
9619
|
return map;
|
|
9595
9620
|
}, [flatItems, getValue]);
|
|
9596
9621
|
const lookup = (0, import_react51.useMemo)(
|
|
9597
|
-
() => buildLookup(
|
|
9598
|
-
[
|
|
9622
|
+
() => buildLookup(displayOptions, getOptionChildren, getValue),
|
|
9623
|
+
[displayOptions, getOptionChildren, getValue]
|
|
9599
9624
|
);
|
|
9600
9625
|
const selectedKeys = (0, import_react51.useMemo)(() => {
|
|
9601
9626
|
if (multiple) {
|
|
@@ -9607,21 +9632,27 @@ function SmartSelect({
|
|
|
9607
9632
|
if (!onSearchChange) return;
|
|
9608
9633
|
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
9609
9634
|
if (!inputValue) {
|
|
9610
|
-
onSearchChange("");
|
|
9635
|
+
onSearchChange("", 0);
|
|
9611
9636
|
return;
|
|
9612
9637
|
}
|
|
9613
|
-
const
|
|
9614
|
-
|
|
9615
|
-
)
|
|
9616
|
-
|
|
9638
|
+
const q = inputValue.toLowerCase();
|
|
9639
|
+
let localCount = 0;
|
|
9640
|
+
for (const opt of flatOptionsList) {
|
|
9641
|
+
if (getOptionLabel(opt).toLowerCase().includes(q) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q)) {
|
|
9642
|
+
localCount++;
|
|
9643
|
+
if (localCount >= searchThreshold) break;
|
|
9644
|
+
}
|
|
9645
|
+
}
|
|
9646
|
+
if (localCount >= searchThreshold) return;
|
|
9647
|
+
const needed = searchThreshold - localCount;
|
|
9617
9648
|
if (debounceMs <= 0) {
|
|
9618
|
-
onSearchChange(inputValue);
|
|
9649
|
+
onSearchChange(inputValue, needed);
|
|
9619
9650
|
} else {
|
|
9620
9651
|
debounceTimer.current = setTimeout(() => {
|
|
9621
|
-
onSearchChange(inputValue);
|
|
9652
|
+
onSearchChange(inputValue, needed);
|
|
9622
9653
|
}, debounceMs);
|
|
9623
9654
|
}
|
|
9624
|
-
}, [onSearchChange, debounceMs, flatOptionsList, getOptionLabel, getOptionSubLabel]);
|
|
9655
|
+
}, [onSearchChange, debounceMs, searchThreshold, flatOptionsList, getOptionLabel, getOptionSubLabel]);
|
|
9625
9656
|
const handleChange = (0, import_react51.useCallback)((_, newValue) => {
|
|
9626
9657
|
if (!multiple || !allowChildNodesSelection || !getOptionChildren) {
|
|
9627
9658
|
onChange?.(newValue);
|
|
@@ -9708,10 +9739,12 @@ function SmartSelect({
|
|
|
9708
9739
|
if (multiple) {
|
|
9709
9740
|
const selected = opts.filter((o) => selectedKeys.has(getValue(o)));
|
|
9710
9741
|
const unselected = opts.filter((o) => !selectedKeys.has(getValue(o)));
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9742
|
+
if (!inputValue) return [...selected, ...unselected];
|
|
9743
|
+
const q2 = inputValue.toLowerCase();
|
|
9744
|
+
const filteredUnselected = unselected.filter(
|
|
9745
|
+
(opt) => getOptionLabel(opt).toLowerCase().includes(q2) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q2)
|
|
9746
|
+
).slice(0, searchThreshold);
|
|
9747
|
+
return [...selected, ...filteredUnselected];
|
|
9715
9748
|
}
|
|
9716
9749
|
if (value != null) {
|
|
9717
9750
|
const selectedLabel = getOptionLabel(value);
|
|
@@ -9727,12 +9760,12 @@ function SmartSelect({
|
|
|
9727
9760
|
const q = inputValue.toLowerCase();
|
|
9728
9761
|
return opts.filter(
|
|
9729
9762
|
(opt) => getOptionLabel(opt).toLowerCase().includes(q) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q)
|
|
9730
|
-
);
|
|
9731
|
-
}, [filterOptionsProp, multiple, selectedKeys, getValue, getOptionLabel, getOptionSubLabel, value]);
|
|
9763
|
+
).slice(0, searchThreshold);
|
|
9764
|
+
}, [filterOptionsProp, multiple, selectedKeys, getValue, getOptionLabel, getOptionSubLabel, value, searchThreshold]);
|
|
9732
9765
|
return /* @__PURE__ */ import_react51.default.createElement(
|
|
9733
9766
|
Autocomplete,
|
|
9734
9767
|
{
|
|
9735
|
-
options:
|
|
9768
|
+
options: displayOptions,
|
|
9736
9769
|
value: value ?? (multiple ? [] : null),
|
|
9737
9770
|
onChange: handleChange,
|
|
9738
9771
|
onInputChange: handleInputChange,
|
package/dist/main.d.cts
CHANGED
|
@@ -1909,15 +1909,28 @@ interface SmartSelectProps<T = any> {
|
|
|
1909
1909
|
/** Called when selection changes */
|
|
1910
1910
|
onChange?: (value: T | T[] | null) => void;
|
|
1911
1911
|
/**
|
|
1912
|
-
* Called when
|
|
1913
|
-
*
|
|
1912
|
+
* Called when local matches fall below `searchThreshold`.
|
|
1913
|
+
* Receives the current query and how many more records are needed to fill the threshold.
|
|
1914
|
+
* Use this to trigger an API / server search and update `searchResults`.
|
|
1914
1915
|
*/
|
|
1915
|
-
onSearchChange?: (query: string) => void;
|
|
1916
|
+
onSearchChange?: (query: string, needed: number) => void;
|
|
1917
|
+
/**
|
|
1918
|
+
* Results returned by the API for the current query.
|
|
1919
|
+
* Merged with local matches (duplicates excluded) to fill up to `searchThreshold`.
|
|
1920
|
+
* Reset this to [] when the query is cleared.
|
|
1921
|
+
*/
|
|
1922
|
+
searchResults?: T[];
|
|
1916
1923
|
/**
|
|
1917
1924
|
* Debounce delay in ms before `onSearchChange` fires.
|
|
1918
1925
|
* Defaults to 300 ms. Pass 0 to disable debouncing.
|
|
1919
1926
|
*/
|
|
1920
1927
|
debounceMs?: number;
|
|
1928
|
+
/**
|
|
1929
|
+
* Max results to show when a query is active.
|
|
1930
|
+
* If local matches are fewer than this, `onSearchChange` fires with how many more are needed.
|
|
1931
|
+
* Defaults to 10. Pass 0 to always call the API.
|
|
1932
|
+
*/
|
|
1933
|
+
searchThreshold?: number;
|
|
1921
1934
|
/** Primary display label for an option (required) */
|
|
1922
1935
|
getOptionLabel: (option: T) => string;
|
|
1923
1936
|
/** Unique key for an option — defaults to the label string */
|
|
@@ -1971,7 +1984,7 @@ interface SmartSelectProps<T = any> {
|
|
|
1971
1984
|
style?: CSSProperties;
|
|
1972
1985
|
sx?: SxProp;
|
|
1973
1986
|
}
|
|
1974
|
-
declare function SmartSelect<T = any>({ options, value, onChange, onSearchChange, debounceMs, getOptionLabel, getOptionValue, getOptionSubLabel, getOptionChildren, multiple, allowChildNodesSelection, loading, loadingText, filterOptions: filterOptionsProp, renderOption: renderOptionProp, limitTags, label, placeholder, variant, size, disabled, error, helperText, fullWidth, required, className, style, sx, }: SmartSelectProps<T>): React__default.JSX.Element;
|
|
1987
|
+
declare function SmartSelect<T = any>({ options, value, onChange, onSearchChange, searchResults, debounceMs, searchThreshold, getOptionLabel, getOptionValue, getOptionSubLabel, getOptionChildren, multiple, allowChildNodesSelection, loading, loadingText, filterOptions: filterOptionsProp, renderOption: renderOptionProp, limitTags, label, placeholder, variant, size, disabled, error, helperText, fullWidth, required, className, style, sx, }: SmartSelectProps<T>): React__default.JSX.Element;
|
|
1975
1988
|
|
|
1976
1989
|
type ToolbarButton = 'undo' | 'redo' | 'ai' | 'paragraph' | 'fontsize' | 'font' | 'color' | 'bold' | 'italic' | 'strike' | 'link' | 'lineheight' | 'ul' | 'ol' | 'align' | 'indent' | 'outdent' | 'table' | 'image' | 'video' | 'cut' | 'copy' | 'paste' | 'specialchars' | 'code' | 'fullscreen' | 'tts' | 'stt' | 'translate' | 'todo' | '|';
|
|
1977
1990
|
type EditorVariant = 'default' | 'basic';
|
package/dist/main.d.ts
CHANGED
|
@@ -1909,15 +1909,28 @@ interface SmartSelectProps<T = any> {
|
|
|
1909
1909
|
/** Called when selection changes */
|
|
1910
1910
|
onChange?: (value: T | T[] | null) => void;
|
|
1911
1911
|
/**
|
|
1912
|
-
* Called when
|
|
1913
|
-
*
|
|
1912
|
+
* Called when local matches fall below `searchThreshold`.
|
|
1913
|
+
* Receives the current query and how many more records are needed to fill the threshold.
|
|
1914
|
+
* Use this to trigger an API / server search and update `searchResults`.
|
|
1914
1915
|
*/
|
|
1915
|
-
onSearchChange?: (query: string) => void;
|
|
1916
|
+
onSearchChange?: (query: string, needed: number) => void;
|
|
1917
|
+
/**
|
|
1918
|
+
* Results returned by the API for the current query.
|
|
1919
|
+
* Merged with local matches (duplicates excluded) to fill up to `searchThreshold`.
|
|
1920
|
+
* Reset this to [] when the query is cleared.
|
|
1921
|
+
*/
|
|
1922
|
+
searchResults?: T[];
|
|
1916
1923
|
/**
|
|
1917
1924
|
* Debounce delay in ms before `onSearchChange` fires.
|
|
1918
1925
|
* Defaults to 300 ms. Pass 0 to disable debouncing.
|
|
1919
1926
|
*/
|
|
1920
1927
|
debounceMs?: number;
|
|
1928
|
+
/**
|
|
1929
|
+
* Max results to show when a query is active.
|
|
1930
|
+
* If local matches are fewer than this, `onSearchChange` fires with how many more are needed.
|
|
1931
|
+
* Defaults to 10. Pass 0 to always call the API.
|
|
1932
|
+
*/
|
|
1933
|
+
searchThreshold?: number;
|
|
1921
1934
|
/** Primary display label for an option (required) */
|
|
1922
1935
|
getOptionLabel: (option: T) => string;
|
|
1923
1936
|
/** Unique key for an option — defaults to the label string */
|
|
@@ -1971,7 +1984,7 @@ interface SmartSelectProps<T = any> {
|
|
|
1971
1984
|
style?: CSSProperties;
|
|
1972
1985
|
sx?: SxProp;
|
|
1973
1986
|
}
|
|
1974
|
-
declare function SmartSelect<T = any>({ options, value, onChange, onSearchChange, debounceMs, getOptionLabel, getOptionValue, getOptionSubLabel, getOptionChildren, multiple, allowChildNodesSelection, loading, loadingText, filterOptions: filterOptionsProp, renderOption: renderOptionProp, limitTags, label, placeholder, variant, size, disabled, error, helperText, fullWidth, required, className, style, sx, }: SmartSelectProps<T>): React__default.JSX.Element;
|
|
1987
|
+
declare function SmartSelect<T = any>({ options, value, onChange, onSearchChange, searchResults, debounceMs, searchThreshold, getOptionLabel, getOptionValue, getOptionSubLabel, getOptionChildren, multiple, allowChildNodesSelection, loading, loadingText, filterOptions: filterOptionsProp, renderOption: renderOptionProp, limitTags, label, placeholder, variant, size, disabled, error, helperText, fullWidth, required, className, style, sx, }: SmartSelectProps<T>): React__default.JSX.Element;
|
|
1975
1988
|
|
|
1976
1989
|
type ToolbarButton = 'undo' | 'redo' | 'ai' | 'paragraph' | 'fontsize' | 'font' | 'color' | 'bold' | 'italic' | 'strike' | 'link' | 'lineheight' | 'ul' | 'ol' | 'align' | 'indent' | 'outdent' | 'table' | 'image' | 'video' | 'cut' | 'copy' | 'paste' | 'specialchars' | 'code' | 'fullscreen' | 'tts' | 'stt' | 'translate' | 'todo' | '|';
|
|
1977
1990
|
type EditorVariant = 'default' | 'basic';
|
package/dist/main.js
CHANGED
|
@@ -4628,6 +4628,7 @@ function DataGrid({
|
|
|
4628
4628
|
const menuRef = useRef10(null);
|
|
4629
4629
|
const [showManageColumns, setShowManageColumns] = useState9(false);
|
|
4630
4630
|
const [showAdvancedFilter, setShowAdvancedFilter] = useState9(false);
|
|
4631
|
+
const [focusFilterIdx, setFocusFilterIdx] = useState9(-1);
|
|
4631
4632
|
const filterableColumnsProp = initialColumnsProp.filter((c) => c.filterable !== false);
|
|
4632
4633
|
const initialFilterCol = String(filterableColumnsProp[0]?.field || filterableColumnsProp[0]?.key || "");
|
|
4633
4634
|
const [advancedFilters, setAdvancedFilters] = useState9([
|
|
@@ -4676,9 +4677,13 @@ function DataGrid({
|
|
|
4676
4677
|
return next;
|
|
4677
4678
|
});
|
|
4678
4679
|
}, [initialColumnsProp]);
|
|
4680
|
+
const onFiltersChangeRef = useRef10(onFiltersChange);
|
|
4679
4681
|
useEffect9(() => {
|
|
4680
|
-
onFiltersChange
|
|
4681
|
-
}
|
|
4682
|
+
onFiltersChangeRef.current = onFiltersChange;
|
|
4683
|
+
});
|
|
4684
|
+
useEffect9(() => {
|
|
4685
|
+
onFiltersChangeRef.current?.(advancedFilters);
|
|
4686
|
+
}, [advancedFilters]);
|
|
4682
4687
|
const handleSort = (fieldKey, dir) => {
|
|
4683
4688
|
if (dir !== void 0) {
|
|
4684
4689
|
setSortField(fieldKey);
|
|
@@ -4947,6 +4952,7 @@ function DataGrid({
|
|
|
4947
4952
|
if (!firstCol) return prev;
|
|
4948
4953
|
return [{ column: String(firstCol.field), operator: getDefaultOperator(firstCol.type), value: "", logic: "AND" }];
|
|
4949
4954
|
});
|
|
4955
|
+
setFocusFilterIdx(-1);
|
|
4950
4956
|
setShowAdvancedFilter(false);
|
|
4951
4957
|
};
|
|
4952
4958
|
const activeMenuCol = activeMenu ? resolvedColumns.find((c) => String(c.field) === activeMenu) : null;
|
|
@@ -4998,7 +5004,18 @@ function DataGrid({
|
|
|
4998
5004
|
},
|
|
4999
5005
|
col.headerName,
|
|
5000
5006
|
col.sortable !== false && /* @__PURE__ */ React75.createElement("span", { className: `dg-sort-icon${isSorted ? " dg-sort-icon--active" : ""}` }, isSorted && sortDirection === "asc" && /* @__PURE__ */ React75.createElement(ChevronUp, { size: 14 }), isSorted && sortDirection === "desc" && /* @__PURE__ */ React75.createElement(ChevronDown, { size: 14 }), !isSorted && /* @__PURE__ */ React75.createElement(ChevronsUpDown, { size: 14 }))
|
|
5001
|
-
), /* @__PURE__ */ React75.createElement("div", { className: `dg-th-actions${isFiltered ? " dg-th-actions--filtered" : ""}` }, isFiltered && /* @__PURE__ */ React75.createElement(
|
|
5007
|
+
), /* @__PURE__ */ React75.createElement("div", { className: `dg-th-actions${isFiltered ? " dg-th-actions--filtered" : ""}` }, isFiltered && /* @__PURE__ */ React75.createElement(
|
|
5008
|
+
"button",
|
|
5009
|
+
{
|
|
5010
|
+
className: "dg-th-filter-btn",
|
|
5011
|
+
onClick: () => {
|
|
5012
|
+
const idx2 = advancedFilters.findIndex((f) => f.column === colField);
|
|
5013
|
+
setFocusFilterIdx(idx2);
|
|
5014
|
+
setShowAdvancedFilter(true);
|
|
5015
|
+
}
|
|
5016
|
+
},
|
|
5017
|
+
/* @__PURE__ */ React75.createElement(Filter, { size: 11 })
|
|
5018
|
+
), !col.disableColumnMenu && /* @__PURE__ */ React75.createElement(
|
|
5002
5019
|
"button",
|
|
5003
5020
|
{
|
|
5004
5021
|
className: "dg-th-menu-btn",
|
|
@@ -5227,7 +5244,7 @@ function DataGrid({
|
|
|
5227
5244
|
className: "dg-filter-input",
|
|
5228
5245
|
placeholder: "Value\u2026",
|
|
5229
5246
|
value: f.value,
|
|
5230
|
-
autoFocus: idx === advancedFilters.length - 1,
|
|
5247
|
+
autoFocus: focusFilterIdx >= 0 ? idx === focusFilterIdx : idx === advancedFilters.length - 1,
|
|
5231
5248
|
onChange: (e) => setAdvancedFilters((p) => p.map((fi, i) => i === idx ? { ...fi, value: e.target.value } : fi))
|
|
5232
5249
|
}
|
|
5233
5250
|
));
|
|
@@ -9474,7 +9491,9 @@ function SmartSelect({
|
|
|
9474
9491
|
value,
|
|
9475
9492
|
onChange,
|
|
9476
9493
|
onSearchChange,
|
|
9494
|
+
searchResults = [],
|
|
9477
9495
|
debounceMs = 300,
|
|
9496
|
+
searchThreshold = 10,
|
|
9478
9497
|
getOptionLabel,
|
|
9479
9498
|
getOptionValue,
|
|
9480
9499
|
getOptionSubLabel,
|
|
@@ -9512,14 +9531,20 @@ function SmartSelect({
|
|
|
9512
9531
|
return flattenTree(options, getOptionChildren);
|
|
9513
9532
|
}, [options, getOptionChildren]);
|
|
9514
9533
|
const flatOptionsList = useMemo3(() => flatItems.map((f) => f.option), [flatItems]);
|
|
9534
|
+
const displayOptions = useMemo3(() => {
|
|
9535
|
+
if (!searchResults.length) return flatOptionsList;
|
|
9536
|
+
const localKeys = new Set(flatOptionsList.map((o) => getValue(o)));
|
|
9537
|
+
const serverOnly = searchResults.filter((o) => !localKeys.has(getValue(o)));
|
|
9538
|
+
return [...flatOptionsList, ...serverOnly];
|
|
9539
|
+
}, [flatOptionsList, searchResults, getValue]);
|
|
9515
9540
|
const depthMap = useMemo3(() => {
|
|
9516
9541
|
const map = /* @__PURE__ */ new Map();
|
|
9517
9542
|
flatItems.forEach(({ option, depth }) => map.set(getValue(option), depth));
|
|
9518
9543
|
return map;
|
|
9519
9544
|
}, [flatItems, getValue]);
|
|
9520
9545
|
const lookup = useMemo3(
|
|
9521
|
-
() => buildLookup(
|
|
9522
|
-
[
|
|
9546
|
+
() => buildLookup(displayOptions, getOptionChildren, getValue),
|
|
9547
|
+
[displayOptions, getOptionChildren, getValue]
|
|
9523
9548
|
);
|
|
9524
9549
|
const selectedKeys = useMemo3(() => {
|
|
9525
9550
|
if (multiple) {
|
|
@@ -9531,21 +9556,27 @@ function SmartSelect({
|
|
|
9531
9556
|
if (!onSearchChange) return;
|
|
9532
9557
|
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
9533
9558
|
if (!inputValue) {
|
|
9534
|
-
onSearchChange("");
|
|
9559
|
+
onSearchChange("", 0);
|
|
9535
9560
|
return;
|
|
9536
9561
|
}
|
|
9537
|
-
const
|
|
9538
|
-
|
|
9539
|
-
)
|
|
9540
|
-
|
|
9562
|
+
const q = inputValue.toLowerCase();
|
|
9563
|
+
let localCount = 0;
|
|
9564
|
+
for (const opt of flatOptionsList) {
|
|
9565
|
+
if (getOptionLabel(opt).toLowerCase().includes(q) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q)) {
|
|
9566
|
+
localCount++;
|
|
9567
|
+
if (localCount >= searchThreshold) break;
|
|
9568
|
+
}
|
|
9569
|
+
}
|
|
9570
|
+
if (localCount >= searchThreshold) return;
|
|
9571
|
+
const needed = searchThreshold - localCount;
|
|
9541
9572
|
if (debounceMs <= 0) {
|
|
9542
|
-
onSearchChange(inputValue);
|
|
9573
|
+
onSearchChange(inputValue, needed);
|
|
9543
9574
|
} else {
|
|
9544
9575
|
debounceTimer.current = setTimeout(() => {
|
|
9545
|
-
onSearchChange(inputValue);
|
|
9576
|
+
onSearchChange(inputValue, needed);
|
|
9546
9577
|
}, debounceMs);
|
|
9547
9578
|
}
|
|
9548
|
-
}, [onSearchChange, debounceMs, flatOptionsList, getOptionLabel, getOptionSubLabel]);
|
|
9579
|
+
}, [onSearchChange, debounceMs, searchThreshold, flatOptionsList, getOptionLabel, getOptionSubLabel]);
|
|
9549
9580
|
const handleChange = useCallback11((_, newValue) => {
|
|
9550
9581
|
if (!multiple || !allowChildNodesSelection || !getOptionChildren) {
|
|
9551
9582
|
onChange?.(newValue);
|
|
@@ -9632,10 +9663,12 @@ function SmartSelect({
|
|
|
9632
9663
|
if (multiple) {
|
|
9633
9664
|
const selected = opts.filter((o) => selectedKeys.has(getValue(o)));
|
|
9634
9665
|
const unselected = opts.filter((o) => !selectedKeys.has(getValue(o)));
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9666
|
+
if (!inputValue) return [...selected, ...unselected];
|
|
9667
|
+
const q2 = inputValue.toLowerCase();
|
|
9668
|
+
const filteredUnselected = unselected.filter(
|
|
9669
|
+
(opt) => getOptionLabel(opt).toLowerCase().includes(q2) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q2)
|
|
9670
|
+
).slice(0, searchThreshold);
|
|
9671
|
+
return [...selected, ...filteredUnselected];
|
|
9639
9672
|
}
|
|
9640
9673
|
if (value != null) {
|
|
9641
9674
|
const selectedLabel = getOptionLabel(value);
|
|
@@ -9651,12 +9684,12 @@ function SmartSelect({
|
|
|
9651
9684
|
const q = inputValue.toLowerCase();
|
|
9652
9685
|
return opts.filter(
|
|
9653
9686
|
(opt) => getOptionLabel(opt).toLowerCase().includes(q) || (getOptionSubLabel?.(opt) ?? "").toLowerCase().includes(q)
|
|
9654
|
-
);
|
|
9655
|
-
}, [filterOptionsProp, multiple, selectedKeys, getValue, getOptionLabel, getOptionSubLabel, value]);
|
|
9687
|
+
).slice(0, searchThreshold);
|
|
9688
|
+
}, [filterOptionsProp, multiple, selectedKeys, getValue, getOptionLabel, getOptionSubLabel, value, searchThreshold]);
|
|
9656
9689
|
return /* @__PURE__ */ React108.createElement(
|
|
9657
9690
|
Autocomplete,
|
|
9658
9691
|
{
|
|
9659
|
-
options:
|
|
9692
|
+
options: displayOptions,
|
|
9660
9693
|
value: value ?? (multiple ? [] : null),
|
|
9661
9694
|
onChange: handleChange,
|
|
9662
9695
|
onInputChange: handleInputChange,
|