tp-react-elements 3.0.18 → 3.0.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.
@@ -1,3 +1,3 @@
1
- var DateInput = {};
1
+ var Month = {};
2
2
 
3
- export { DateInput as __exports };
3
+ export { Month as __exports };
@@ -1,3 +1,3 @@
1
- var Month = {};
1
+ var DateInput = {};
2
2
 
3
- export { Month as __exports };
3
+ export { DateInput as __exports };
@@ -1,3 +1,3 @@
1
- var DefinedRange = {};
1
+ var Calendar = {};
2
2
 
3
- export { DefinedRange as __exports };
3
+ export { Calendar as __exports };
@@ -1,3 +1,3 @@
1
- var Calendar = {};
1
+ var DefinedRange = {};
2
2
 
3
- export { Calendar as __exports };
3
+ export { DefinedRange as __exports };
@@ -1,13 +1,5 @@
1
1
  import { jsx, Fragment } from 'react/jsx-runtime';
2
2
  import require$$0__default, { lazy, Suspense } from 'react';
3
- import FormCheckBox from '../FormComponents/FormCheckBox/FormCheckBox.esm.js';
4
- import FormCheckBoxGroup from '../FormComponents/FormCheckBoxGroup/FormCheckBoxGroup.esm.js';
5
- import FormNumberField from '../FormComponents/FormNumberField/FormNumberField.esm.js';
6
- import FormNumberFieldDecimal from '../FormComponents/FormNumberField/FormNumberFieldDecimal.esm.js';
7
- import FormRadioGroup from '../FormComponents/FormRadioGroup/FormRadioGroup.esm.js';
8
- import FormTextAreaField from '../FormComponents/FormTextAreaField/FormTextAreaField.esm.js';
9
- import FormTextField from '../FormComponents/FormTextField/FormTextField.esm.js';
10
- import PasswordField from '../FormComponents/PasswordField/PasswordField.esm.js';
11
3
  import SingleSelect from '../FormComponents/Select/SingleSelect.esm.js';
12
4
  import MultiSelectAutocomplete from '../FormComponents/Select/MultiSelectAutocomplete.esm.js';
13
5
  import SingleSelectNonAutoComplete from '../FormComponents/Select/SingleSelectNonAutoComplete.esm.js';
@@ -19,6 +11,14 @@ import RichTextEditorWrapper from '../FormComponents/RichTextEditor/RichTextEdit
19
11
  import SingleSelectSearchApi from '../FormComponents/Select/SingleSelectSearchApi.esm.js';
20
12
  import MultiSelectSearchApi from '../FormComponents/Select/MultiSelectSearchApi.esm.js';
21
13
  import DatetimepickerWrapper from '../FormComponents/DatePicker/DatetimepickerWrapper.esm.js';
14
+ import FormTextAreaField from '../FormComponents/FormTextAreaField/FormTextAreaField.esm.js';
15
+ import FormCheckBox from '../FormComponents/FormCheckBox/FormCheckBox.esm.js';
16
+ import FormRadioGroup from '../FormComponents/FormRadioGroup/FormRadioGroup.esm.js';
17
+ import FormCheckBoxGroup from '../FormComponents/FormCheckBoxGroup/FormCheckBoxGroup.esm.js';
18
+ import FormNumberFieldDecimal from '../FormComponents/FormNumberField/FormNumberFieldDecimal.esm.js';
19
+ import FormNumberField from '../FormComponents/FormNumberField/FormNumberField.esm.js';
20
+ import PasswordField from '../FormComponents/PasswordField/PasswordField.esm.js';
21
+ import FormTextField from '../FormComponents/FormTextField/FormTextField.esm.js';
22
22
 
23
23
  // Lazy-loaded heavy components
24
24
  // const RichTextEditorWrapper = lazy(() =>
@@ -1,9 +1,3 @@
1
- export { default as FormNumberField } from './FormNumberField/FormNumberField.esm.js';
2
- export { default as FormNumberFieldDecimal } from './FormNumberField/FormNumberFieldDecimal.esm.js';
3
- export { default as FormTextAreaField } from './FormTextAreaField/FormTextAreaField.esm.js';
4
- export { default as FormTextField } from './FormTextField/FormTextField.esm.js';
5
- export { default as PasswordField } from './PasswordField/PasswordField.esm.js';
6
- export { default as FormCheckBox } from './FormCheckBox/FormCheckBox.esm.js';
7
1
  export { default as SingleSelect } from './Select/SingleSelect.esm.js';
8
2
  export { default as SingleSelectNonAutoComplete } from './Select/SingleSelectNonAutoComplete.esm.js';
9
3
  export { default as SingleSelectSearchApi } from './Select/SingleSelectSearchApi.esm.js';
@@ -11,33 +5,22 @@ export { default as MultiSelectSearchApi } from './Select/MultiSelectSearchApi.e
11
5
  export { default as MultiSelectV1 } from './Select/MultiSelectv1.esm.js';
12
6
  export { default as MultiSelectTable } from './Select/MultiSelectTable.esm.js';
13
7
  export { default as SearchableSelect } from './Select/SearchableSelect.esm.js';
14
- export { default as FormCheckBoxGroup } from './FormCheckBoxGroup/FormCheckBoxGroup.esm.js';
15
- export { default as FormRadioGroup } from './FormRadioGroup/FormRadioGroup.esm.js';
16
8
  export { default as DatepickerWrapperV2 } from './DatePicker/DatepickerWrapperV2.esm.js';
17
- export { default as Monthpickerrender } from './DatePicker/Monthpickerrender.esm.js';
18
- import 'react/jsx-runtime';
19
- import 'react';
20
- import '@mui/material';
21
- import '@mui/icons-material/CalendarToday';
22
- import '@mui/icons-material/ChevronLeft';
23
- import '@mui/icons-material/ChevronRight';
24
- import 'react-hook-form';
25
9
  export { default as FormBottomField } from './FormBottomField/FormBottomField.esm.js';
26
- import 'dayjs';
27
- export { default as YearPickerField } from './YearPickerField/YearPickerField.esm.js';
28
- export { default as TimePicker } from './TimePicker/TimePicker.esm.js';
10
+ export { default as FormCheckBox } from './FormCheckBox/FormCheckBox.esm.js';
11
+ export { default as FormCheckBoxGroup } from './FormCheckBoxGroup/FormCheckBoxGroup.esm.js';
12
+ export { default as FormErrorField } from './FormErrorField/FormErrorField.esm.js';
13
+ export { default as FormNumberField } from './FormNumberField/FormNumberField.esm.js';
14
+ export { default as FormNumberFieldDecimal } from './FormNumberField/FormNumberFieldDecimal.esm.js';
15
+ export { default as FormRadioGroup } from './FormRadioGroup/FormRadioGroup.esm.js';
29
16
  export { default as FormRenderFileUpload } from './FileUpload/FormRenderFileUpload.esm.js';
30
17
  export { default as FormRenderMultiFileUpload } from './FileUpload/FormRenderMultiFileUpload.esm.js';
31
- import '@mui/icons-material/Visibility';
32
- import '@mui/icons-material/Close';
33
- import '@mui/icons-material/NavigateBefore';
34
- import '@mui/icons-material/NavigateNext';
35
- import '@mui/icons-material/Delete';
36
- import '@mui/icons-material/UploadFile';
37
- import '@mui/icons-material/PictureAsPdf';
38
- import '@mui/icons-material/TableChart';
39
- import '@mui/icons-material/Description';
40
- export { default as FormErrorField } from './FormErrorField/FormErrorField.esm.js';
18
+ export { default as FormTextAreaField } from './FormTextAreaField/FormTextAreaField.esm.js';
19
+ export { default as FormTextField } from './FormTextField/FormTextField.esm.js';
41
20
  export { default as HelperText } from './HelperText/HelperText.esm.js';
21
+ export { default as Monthpickerrender } from './DatePicker/Monthpickerrender.esm.js';
22
+ export { default as PasswordField } from './PasswordField/PasswordField.esm.js';
42
23
  export { default as RichTextEditor } from './RichTextEditor/RichTextEditor.esm.js';
43
24
  export { default as RichTextEditorWrapper } from './RichTextEditor/RichTextEditorWrapper.esm.js';
25
+ export { default as TimePicker } from './TimePicker/TimePicker.esm.js';
26
+ export { default as YearPickerField } from './YearPickerField/YearPickerField.esm.js';
@@ -1,3 +1,4 @@
1
+ import { type SearchOption } from '../../components/FormComponents/Select/SingleSelectSearchApi';
1
2
  import type { MRT_ColumnFiltersState } from 'material-react-table';
2
3
  /**
3
4
  * Describes one server-side filter chip.
@@ -117,6 +118,71 @@ export type ServerFilterDef = {
117
118
  * chips like the date picker. Default: `false` (multi-select).
118
119
  */
119
120
  single?: boolean;
121
+ } | {
122
+ /**
123
+ * Single-select chip backed by `SingleSelectSearchApi` — options load
124
+ * from a remote API as the user types (debounced), instead of a fixed
125
+ * list. Use this over `searchableDropdown` when the option set is too
126
+ * large/dynamic to enumerate upfront (customers, products by ID, etc.).
127
+ * Selected value is stored in `filterValues[filterKey]`, same as
128
+ * `dropdown`/`searchableDropdown`.
129
+ */
130
+ type: 'singleSelectSearch';
131
+ id: string;
132
+ label: string;
133
+ filterKey: string;
134
+ /** Preferred — consumer-supplied fetch (handles auth). Receives search text + AbortSignal. */
135
+ fetchOptions?: (searchText: string, signal: AbortSignal) => Promise<SearchOption[]>;
136
+ /** Fallback base API URL, used only when `fetchOptions` is omitted. */
137
+ api?: string;
138
+ jwtHeader?: any;
139
+ /** Query param name for the fallback `api` path. Default: `'searchvalue'`. */
140
+ searchValue?: string;
141
+ /** Minimum characters before the search fires. Default: `3`. */
142
+ minSearchLength?: number;
143
+ /** Debounce delay in ms. Default: `300`. */
144
+ debounceMs?: number;
145
+ /**
146
+ * Pre-known option(s) so a restored `filterValues[filterKey]` (e.g. a
147
+ * filter set before this chip was last opened) shows its label
148
+ * immediately without a search round-trip.
149
+ */
150
+ options?: SearchOption[];
151
+ placeholder?: string;
152
+ /** Show this chip in the filter bar on first render. Default: `false`. */
153
+ defaultVisible?: boolean;
154
+ } | {
155
+ /**
156
+ * Multi-select chip backed by `MultiSelectSearchApi` — same remote-API
157
+ * search as `singleSelectSearch`, but multiple values can be picked.
158
+ * Selected values are joined as a comma-separated string in
159
+ * `filterValues[filterKey]` (e.g. `"P001,P004"`), same convention as
160
+ * `multiSelect`. Split on `","` in your `fetchPage` handler.
161
+ */
162
+ type: 'multiSelectSearch';
163
+ id: string;
164
+ label: string;
165
+ filterKey: string;
166
+ /** Preferred — consumer-supplied fetch (handles auth). Receives search text + AbortSignal. */
167
+ fetchOptions?: (searchText: string, signal: AbortSignal) => Promise<SearchOption[]>;
168
+ /** Fallback base API URL, used only when `fetchOptions` is omitted. */
169
+ api?: string;
170
+ jwtHeader?: any;
171
+ /** Query param name for the fallback `api` path. Default: `'searchvalue'`. */
172
+ searchValue?: string;
173
+ /** Minimum characters before the search fires. Default: `3`. */
174
+ minSearchLength?: number;
175
+ /** Debounce delay in ms. Default: `300`. */
176
+ debounceMs?: number;
177
+ /** Pre-known option(s) so restored selections show their labels immediately. */
178
+ options?: SearchOption[];
179
+ /** Chips shown individually before collapsing into "N selected". Default: `2`. */
180
+ maxChips?: number;
181
+ /** Caps how many options can be selected at once. Default: no limit. */
182
+ maxSelections?: number;
183
+ placeholder?: string;
184
+ /** Show this chip in the filter bar on first render. Default: `false`. */
185
+ defaultVisible?: boolean;
120
186
  };
121
187
  interface AvailableColumn {
122
188
  id: string;
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { memo, useState, useEffect, useCallback } from 'react';
2
+ import { memo, useState, useEffect, useCallback, useMemo } from 'react';
3
3
  import { useForm } from 'react-hook-form';
4
4
  import dayjs from 'dayjs';
5
5
  import customParseFormat from 'dayjs/plugin/customParseFormat';
@@ -9,6 +9,8 @@ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
9
9
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
10
10
  import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
11
11
  import SingleSelectNonAutoComplete from '../FormComponents/Select/SingleSelectNonAutoComplete.esm.js';
12
+ import SingleSelectSearchApi from '../FormComponents/Select/SingleSelectSearchApi.esm.js';
13
+ import MultiSelectSearchApi from '../FormComponents/Select/MultiSelectSearchApi.esm.js';
12
14
  import { TextField, InputAdornment, IconButton, Box, Typography, Tooltip, Button, Popover, Stack, List, ListItemButton, ListItemText, Checkbox, Divider } from '@mui/material';
13
15
  import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
14
16
  import TuneIcon from '@mui/icons-material/Tune';
@@ -33,6 +35,8 @@ const TYPE_PILL = {
33
35
  searchableDropdown: { label: 'Search', color: '#bf360c', bg: '#fbe9e7' },
34
36
  multiSelect: { label: 'Multi', color: '#0277bd', bg: '#e1f5fe' },
35
37
  monthPicker: { label: 'Month', color: '#6a1b9a', bg: '#f3e5f5' },
38
+ singleSelectSearch: { label: 'API', color: '#ad1457', bg: '#fce4ec' },
39
+ multiSelectSearch: { label: 'API Multi', color: '#ad1457', bg: '#fce4ec' },
36
40
  };
37
41
  // Column filter type pills (used in COLUMN FILTERS section of Manage Filters)
38
42
  const COLUMN_TYPE_PILL = {
@@ -407,6 +411,80 @@ const MonthPickerChip = ({ label, value, onApply, onRemove, chipStyle, baseId, s
407
411
  borderTop: '1px solid', borderColor: 'divider',
408
412
  }, children: jsx(Button, { size: "small", variant: "contained", disableElevation: true, onClick: handleApply, children: "Apply" }) }))] })] }));
409
413
  };
414
+ const SingleSelectSearchChip = ({ label, value, onApply, onRemove, fetchOptions, api, jwtHeader, searchValue, minSearchLength, debounceMs, options, placeholder, chipStyle, baseId, }) => {
415
+ const [anchor, setAnchor] = useState(null);
416
+ // Captured from onChangeFn's fullOption when the user selects — the chip's
417
+ // own display text, since the committed filter value is just a raw id.
418
+ const [selectedLabel, setSelectedLabel] = useState('');
419
+ const active = Boolean(value);
420
+ const rhf = useForm({ defaultValues: { select: value || '' } });
421
+ const { register, control, getValues, clearErrors, watch, setValue: rhfSetValue } = rhf;
422
+ // Sync form value when external value changes (e.g. Clear All) — clear the
423
+ // cached label too so a stale one never outlives its filter value.
424
+ useEffect(() => {
425
+ rhfSetValue('select', value || '');
426
+ if (!value)
427
+ setSelectedLabel('');
428
+ }, [value]); // eslint-disable-line react-hooks/exhaustive-deps
429
+ const item = useMemo(() => ({
430
+ name: 'select',
431
+ label,
432
+ inputType: 'single-select-search',
433
+ placeholder: placeholder ?? 'Type to search…',
434
+ api,
435
+ jwtHeader,
436
+ searchValue,
437
+ options,
438
+ onChangeFn: (v, fullOption) => {
439
+ setSelectedLabel(fullOption?.label ?? (v != null ? String(v) : ''));
440
+ onApply(v != null ? String(v) : '');
441
+ setAnchor(null);
442
+ },
443
+ }), [label, placeholder, api, jwtHeader, searchValue, options, onApply]);
444
+ const chipText = active ? `${label}: ${selectedLabel || value}` : label;
445
+ return (jsxs(Fragment, { children: [jsx(Tooltip, { title: active ? chipText : '', placement: "top", arrow: true, children: jsx(Button, { id: baseId ? `${baseId}_chip` : undefined, variant: "outlined", size: "small", onClick: (e) => setAnchor(e.currentTarget), startIcon: jsx(SearchIcon, { sx: { fontSize: '14px !important', mr: -0.25 } }), endIcon: jsx(CloseIcon, { id: baseId ? `${baseId}_remove_icon` : undefined, sx: { fontSize: '12px !important' }, onClick: (e) => { e.stopPropagation(); onRemove(); } }), sx: chipSx(active, chipStyle), children: jsx(ChipLabel, { text: chipText }) }) }), jsx(Popover, { open: Boolean(anchor), anchorEl: anchor, onClose: () => setAnchor(null), anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, PaperProps: { sx: { mt: 0.75, borderRadius: 2, boxShadow: 6, p: 1.5, width: 280 } }, children: jsx(SingleSelectSearchApi, { props: { item, register, control, errors: {}, getValues, clearErrors, setValue: rhfSetValue, watch }, variant: "outlined", fetchOptions: fetchOptions, minSearchLength: minSearchLength, debounceMs: debounceMs }) })] }));
446
+ };
447
+ const MultiSelectSearchChip = ({ label, value, onApply, onRemove, fetchOptions, api, jwtHeader, searchValue, minSearchLength, debounceMs, options, maxChips, maxSelections, placeholder, chipStyle, baseId, }) => {
448
+ const [anchor, setAnchor] = useState(null);
449
+ const [selectedOptions, setSelectedOptions] = useState([]);
450
+ const committedValues = value ? value.split(',').filter(Boolean) : [];
451
+ const active = committedValues.length > 0;
452
+ const rhf = useForm({ defaultValues: { select: committedValues } });
453
+ const { register, control, getValues, clearErrors, watch, setValue: rhfSetValue } = rhf;
454
+ useEffect(() => {
455
+ rhfSetValue('select', value ? value.split(',').filter(Boolean) : []);
456
+ if (!value)
457
+ setSelectedOptions([]);
458
+ }, [value]); // eslint-disable-line react-hooks/exhaustive-deps
459
+ const item = useMemo(() => ({
460
+ name: 'select',
461
+ label,
462
+ inputType: 'multi-select-search',
463
+ placeholder: placeholder ?? 'Type to search…',
464
+ api,
465
+ jwtHeader,
466
+ searchValue,
467
+ options,
468
+ onChangeFn: (values, fullOptions) => {
469
+ setSelectedOptions(fullOptions ?? []);
470
+ onApply((values ?? []).join(','));
471
+ },
472
+ }), [label, placeholder, api, jwtHeader, searchValue, options, onApply]);
473
+ const chipText = (() => {
474
+ if (!active)
475
+ return label;
476
+ if (selectedOptions.length > 0) {
477
+ if (selectedOptions.length === 1)
478
+ return `${label}: ${selectedOptions[0].label}`;
479
+ if (selectedOptions.length === 2)
480
+ return `${label}: ${selectedOptions.map((o) => o.label).join(', ')}`;
481
+ return `${label}: ${selectedOptions.length} selected`;
482
+ }
483
+ // Labels not yet cached (e.g. restored value before any onChangeFn call) — fall back to the count.
484
+ return `${label}: ${committedValues.length} selected`;
485
+ })();
486
+ return (jsxs(Fragment, { children: [jsx(Tooltip, { title: active ? chipText : '', placement: "top", arrow: true, children: jsx(Button, { id: baseId ? `${baseId}_chip` : undefined, variant: "outlined", size: "small", onClick: (e) => setAnchor(e.currentTarget), startIcon: jsx(SearchIcon, { sx: { fontSize: '14px !important', mr: -0.25 } }), endIcon: jsx(CloseIcon, { id: baseId ? `${baseId}_remove_icon` : undefined, sx: { fontSize: '12px !important' }, onClick: (e) => { e.stopPropagation(); onRemove(); } }), sx: chipSx(active, chipStyle), children: jsx(ChipLabel, { text: chipText }) }) }), jsx(Popover, { open: Boolean(anchor), anchorEl: anchor, onClose: () => setAnchor(null), anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, PaperProps: { sx: { mt: 0.75, borderRadius: 2, boxShadow: 6, p: 1.5, width: 300 } }, children: jsx(MultiSelectSearchApi, { props: { item, register, control, errors: {}, getValues, clearErrors, setValue: rhfSetValue, watch }, variant: "outlined", fetchOptions: fetchOptions, minSearchLength: minSearchLength, debounceMs: debounceMs, maxChips: maxChips, maxSelections: maxSelections }) })] }));
487
+ };
410
488
  const GlobalSearchInput = memo(({ value, onChange, chipStyle, placeholder = 'Search…' }) => {
411
489
  const [draft, setDraft] = useState(value);
412
490
  // Keep local draft in sync when the external value changes elsewhere
@@ -522,7 +600,9 @@ const DynamicFilterBar = ({ serverFilterDefs, visibleFilterIds, onToggleFilter,
522
600
  def?.type === 'dropdown' ||
523
601
  def?.type === 'searchableDropdown' ||
524
602
  def?.type === 'multiSelect' ||
525
- def?.type === 'monthPicker') {
603
+ def?.type === 'monthPicker' ||
604
+ def?.type === 'singleSelectSearch' ||
605
+ def?.type === 'multiSelectSearch') {
526
606
  onFilterValuesChange({ ...filterValues, [def.filterKey]: '' });
527
607
  }
528
608
  else if (def?.type === 'date') {
@@ -565,6 +645,12 @@ const DynamicFilterBar = ({ serverFilterDefs, visibleFilterIds, onToggleFilter,
565
645
  if (def?.type === 'monthPicker') {
566
646
  return (jsx(MonthPickerChip, { label: def.label, value: filterValues[def.filterKey] ?? '', onApply: (v) => onFilterValuesChange({ ...filterValues, [def.filterKey]: v }), onRemove: () => removeFilter(id), chipStyle: chipStyle, baseId: gridId ? `${gridId}_${id}` : undefined, single: def.single }, id));
567
647
  }
648
+ if (def?.type === 'singleSelectSearch') {
649
+ return (jsx(SingleSelectSearchChip, { label: def.label, value: filterValues[def.filterKey] ?? '', onApply: (v) => onFilterValuesChange({ ...filterValues, [def.filterKey]: v }), onRemove: () => removeFilter(id), fetchOptions: def.fetchOptions, api: def.api, jwtHeader: def.jwtHeader, searchValue: def.searchValue, minSearchLength: def.minSearchLength, debounceMs: def.debounceMs, options: def.options, placeholder: def.placeholder, chipStyle: chipStyle, baseId: gridId ? `${gridId}_${id}` : undefined }, id));
650
+ }
651
+ if (def?.type === 'multiSelectSearch') {
652
+ return (jsx(MultiSelectSearchChip, { label: def.label, value: filterValues[def.filterKey] ?? '', onApply: (v) => onFilterValuesChange({ ...filterValues, [def.filterKey]: v }), onRemove: () => removeFilter(id), fetchOptions: def.fetchOptions, api: def.api, jwtHeader: def.jwtHeader, searchValue: def.searchValue, minSearchLength: def.minSearchLength, debounceMs: def.debounceMs, options: def.options, maxChips: def.maxChips, maxSelections: def.maxSelections, placeholder: def.placeholder, chipStyle: chipStyle, baseId: gridId ? `${gridId}_${id}` : undefined }, id));
653
+ }
568
654
  if (def?.type === 'date') {
569
655
  return (jsx(DatePickerChip, { label: def.label, value: getColValue(def.columnKey), onApply: (v) => applyColFilter(def.columnKey, v), onRemove: () => removeFilter(id), chipStyle: chipStyle, baseId: gridId ? `${gridId}_${id}` : undefined }, id));
570
656
  }
@@ -390,19 +390,19 @@ function GenericPaginatedGrid({ columns, fetchPage, queryKey, serverFilterDefs,
390
390
  .map((d) => d.id);
391
391
  // Column filter chips with defaultVisible: true.
392
392
  // Mirror the same exclusion rules used by availableColumns:
393
- // • must have an accessorKey
393
+ // • must have a filter identifier (accessorKey, falling back to id)
394
394
  // • must not have enableColumnFilter: false
395
395
  // • must not be managed by a server-side 'date' filter def
396
396
  const serverManagedColKeys = new Set(serverFilterDefs
397
397
  .filter((d) => d.type === 'date')
398
398
  .map((d) => d.columnKey));
399
399
  const markedCols = columns
400
- .filter((c) => 'accessorKey' in c &&
401
- c.accessorKey &&
400
+ .map((c) => ({ c, key: c.accessorKey ?? c.id }))
401
+ .filter(({ c, key }) => !!key &&
402
402
  c.defaultVisible &&
403
403
  c.enableColumnFilter !== false &&
404
- !serverManagedColKeys.has(c.accessorKey))
405
- .map((c) => c.accessorKey);
404
+ !serverManagedColKeys.has(key))
405
+ .map(({ key }) => key);
406
406
  const marked = [...markedServer, ...markedCols];
407
407
  return marked.length > 0
408
408
  ? marked
@@ -563,23 +563,33 @@ function GenericPaginatedGrid({ columns, fetchPage, queryKey, serverFilterDefs,
563
563
  const getColumnCanGlobalFilter = useCallback(() => true, []);
564
564
  // ── Derive column list for filter chip picker ──────────────────────────────
565
565
  //
566
+ // A column's filter identifier is its `accessorKey` when set, falling back to
567
+ // its `id` — TanStack Table's `row.getValue(columnId)` resolves correctly
568
+ // either way, whether the column was defined via `accessorKey` or via
569
+ // `accessorFn` + an explicit `id` (the standard pattern for a computed/mapped
570
+ // display column, e.g. a status label derived from two boolean fields). Using
571
+ // `accessorKey`-only here would silently exclude every such computed column
572
+ // from Manage Filters even when it has a real `filterType`/`options` already
573
+ // configured — a real, previously-observed gap across several grids.
574
+ //
566
575
  // A column is excluded from the "Column Filters" section of Manage Filters
567
576
  // when ANY of the following are true:
568
- // 1. It has no accessorKey (computed / display columns).
569
- // 2. Its accessorKey is already handled by a server-side 'date' filter def.
577
+ // 1. It has neither `accessorKey` nor `id` (no stable filter identifier).
578
+ // 2. That identifier is already handled by a server-side 'date' filter def.
570
579
  // 3. Its MRT `enableColumnFilter` prop is explicitly set to `false` —
571
- // use this for numeric/computed columns that don't need a filter chip.
580
+ // use this for numeric/computed columns that don't need a filter chip
581
+ // (e.g. an actions column).
572
582
  const availableColumns = useMemo(() => {
573
583
  const serverManagedColKeys = new Set(serverFilterDefs
574
584
  .filter((d) => d.type === 'date')
575
585
  .map((d) => d.columnKey));
576
586
  return columns
577
- .filter((c) => 'accessorKey' in c &&
578
- c.accessorKey &&
579
- !serverManagedColKeys.has(c.accessorKey) &&
587
+ .map((c) => ({ c, key: c.accessorKey ?? c.id }))
588
+ .filter(({ c, key }) => !!key &&
589
+ !serverManagedColKeys.has(key) &&
580
590
  c.enableColumnFilter !== false)
581
- .map((c) => ({
582
- id: c.accessorKey,
591
+ .map(({ c, key }) => ({
592
+ id: key,
583
593
  label: c.header,
584
594
  // Pass filterType directly from TPColumnDef (no meta unwrapping needed)
585
595
  filterType: c.filterType,
@@ -4,6 +4,7 @@
4
4
  import type { TPColumnDef, InvoiceDetail } from './types';
5
5
  import type { PagedResult } from './GenericPaginatedGrid';
6
6
  import type { ServerFilterDef } from './DynamicFilterBar';
7
+ import type { SearchOption } from '../../components/FormComponents/Select/SingleSelectSearchApi';
7
8
  export interface EmployeeRow {
8
9
  id: number;
9
10
  name: string;
@@ -20,6 +21,10 @@ export declare const employeeColumns: TPColumnDef<EmployeeRow>[];
20
21
  export declare const employeeFilterDefs: ServerFilterDef[];
21
22
  export declare const employeeDefaultFilters: Record<string, string>;
22
23
  export declare function fetchEmployeePage(filters: Record<string, string>, pageIndex: number, pageSize?: number): Promise<PagedResult<EmployeeRow>>;
24
+ /** Mock remote search — simulates network latency + case-insensitive filtering. */
25
+ export declare function searchManagers(text: string, signal: AbortSignal): Promise<SearchOption[]>;
26
+ export declare function searchLocations(text: string, signal: AbortSignal): Promise<SearchOption[]>;
27
+ export declare const employeeSearchFilterDefs: ServerFilterDef[];
23
28
  export interface ProductRow {
24
29
  sku: string;
25
30
  title: string;
@@ -1,4 +1,4 @@
1
- import { __exports as Calendar } from '../../../../../_virtual/index.esm6.js';
1
+ import { __exports as Calendar } from '../../../../../_virtual/index.esm5.js';
2
2
  import require$$0__default from 'react';
3
3
  import { __require as requirePropTypes } from '../../../../prop-types/index.esm.js';
4
4
  import { __require as requireDayCell } from '../DayCell/index.esm.js';
@@ -1,4 +1,4 @@
1
- import { __exports as DateInput } from '../../../../../_virtual/index.esm12.js';
1
+ import { __exports as DateInput } from '../../../../../_virtual/index.esm14.js';
2
2
  import require$$0__default from 'react';
3
3
  import { __require as requirePropTypes } from '../../../../prop-types/index.esm.js';
4
4
  import { __require as requireClassnames } from '../../../../classnames/index.esm.js';
@@ -1,4 +1,4 @@
1
- import { __exports as DefinedRange } from '../../../../../_virtual/index.esm5.js';
1
+ import { __exports as DefinedRange } from '../../../../../_virtual/index.esm6.js';
2
2
  import require$$0__default from 'react';
3
3
  import { __require as requirePropTypes } from '../../../../prop-types/index.esm.js';
4
4
  import { __require as requireStyles } from '../../styles.esm.js';
@@ -1,4 +1,4 @@
1
- import { __exports as Month } from '../../../../../_virtual/index.esm14.js';
1
+ import { __exports as Month } from '../../../../../_virtual/index.esm12.js';
2
2
  import require$$0__default from 'react';
3
3
  import { __require as requirePropTypes } from '../../../../prop-types/index.esm.js';
4
4
  import { __require as requireDayCell } from '../DayCell/index.esm.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tp-react-elements",
3
- "version": "3.0.18",
3
+ "version": "3.0.21",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "React form components library built with React Hook Form and Yup",