tp-react-elements 3.0.20 → 3.0.22

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 InputRangeField = {};
2
2
 
3
- export { DateInput as __exports };
3
+ export { InputRangeField as __exports };
@@ -1,3 +1,3 @@
1
- var InputRangeField = {};
1
+ var Month = {};
2
2
 
3
- export { InputRangeField 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 DateRange = {};
2
2
 
3
- export { DefinedRange as __exports };
3
+ export { DateRange as __exports };
@@ -1,3 +1,3 @@
1
- var DateRange = {};
1
+ var DefinedRange = {};
2
2
 
3
- export { DateRange as __exports };
3
+ export { DefinedRange as __exports };
@@ -59,15 +59,20 @@ const FormActiveSwitch = ({ props }) => {
59
59
  const { control, item } = props;
60
60
  const valueActive = item.value1 ?? 'A';
61
61
  const valueInactive = item.value2 ?? 'I';
62
+ const disable = Boolean(item.disable);
62
63
  const toggleConfig = useOptionalProjectTheme()?.Styles?.Component?.TPToggleSwitch;
63
64
  if (!toggleConfig) {
64
- return (jsxs("fieldset", { className: "m-form__input", style: FIELDSET_STYLE, children: [item.label && (jsx("legend", { id: `${item.name}-label`, style: LEGEND_STYLE, children: item.label })), jsx(Controller, { name: item.name, control: control, render: ({ field }) => (jsxs("span", { className: "switch prestashop-switch fixed-width-lg", role: "radiogroup", "aria-labelledby": `${item.name}-label`, children: [jsx("input", { id: `${item.name}_on`, name: item.name, type: "radio", value: valueActive, checked: field.value === valueActive, onChange: () => field.onChange(valueActive), "aria-checked": field.value === valueActive }), jsx("label", { htmlFor: `${item.name}_on`, style: LABEL_STYLE, children: item.label1 ?? 'Active' }), jsx("input", { id: `${item.name}_off`, name: item.name, type: "radio", value: valueInactive, checked: field.value === valueInactive, onChange: () => field.onChange(valueInactive), "aria-checked": field.value === valueInactive }), jsx("label", { htmlFor: `${item.name}_off`, style: LABEL_STYLE, children: item.label2 ?? 'In Active' }), jsx("span", { className: "slide-button btn", "aria-hidden": "true" })] })) })] }));
65
+ return (jsxs("fieldset", { className: "m-form__input", style: FIELDSET_STYLE, children: [item.label && (jsx("legend", { id: `${item.name}-label`, style: LEGEND_STYLE, children: item.label })), jsx(Controller, { name: item.name, control: control, render: ({ field }) => (jsxs("span", { className: "switch prestashop-switch fixed-width-lg", role: "radiogroup", "aria-labelledby": `${item.name}-label`, "aria-disabled": disable, style: { opacity: disable ? 0.5 : 1, cursor: disable ? 'not-allowed' : undefined }, children: [jsx("input", { id: `${item.name}_on`, name: item.name, type: "radio", value: valueActive, checked: field.value === valueActive, onChange: () => !disable && field.onChange(valueActive), disabled: disable, "aria-checked": field.value === valueActive }), jsx("label", { htmlFor: `${item.name}_on`, style: LABEL_STYLE, children: item.label1 ?? 'Active' }), jsx("input", { id: `${item.name}_off`, name: item.name, type: "radio", value: valueInactive, checked: field.value === valueInactive, onChange: () => !disable && field.onChange(valueInactive), disabled: disable, "aria-checked": field.value === valueInactive }), jsx("label", { htmlFor: `${item.name}_off`, style: LABEL_STYLE, children: item.label2 ?? 'In Active' }), jsx("span", { className: "slide-button btn", "aria-hidden": "true" })] })) })] }));
65
66
  }
66
67
  const onColor = toggleConfig.onColor ?? '#00A86B';
67
68
  const offColor = toggleConfig.offColor ?? '#D5DCE6';
68
69
  return (jsx(Controller, { name: item.name, control: control, render: ({ field }) => {
69
70
  const on = field.value === valueActive;
70
- return (jsxs("div", { style: CARD_STYLE, children: [jsx("button", { type: "button", role: "switch", "aria-checked": on, "aria-labelledby": `${item.name}-label`, onClick: () => field.onChange(on ? valueInactive : valueActive), style: { ...TRACK_BASE, background: on ? onColor : offColor }, children: jsx("span", { style: { ...KNOB_BASE, left: on ? 17 : 2 } }) }), jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }, children: [jsx("span", { id: `${item.name}-label`, style: { fontSize: 12.5, fontWeight: 700, whiteSpace: 'nowrap' }, children: item.label }), jsx("span", { style: {
71
+ return (jsxs("div", { style: { ...CARD_STYLE, opacity: disable ? 0.5 : 1 }, children: [jsx("button", { type: "button", role: "switch", "aria-checked": on, "aria-labelledby": `${item.name}-label`, "aria-disabled": disable, disabled: disable, onClick: () => !disable && field.onChange(on ? valueInactive : valueActive), style: {
72
+ ...TRACK_BASE,
73
+ background: on ? onColor : offColor,
74
+ cursor: disable ? 'not-allowed' : 'pointer',
75
+ }, children: jsx("span", { style: { ...KNOB_BASE, left: on ? 17 : 2 } }) }), jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }, children: [jsx("span", { id: `${item.name}-label`, style: { fontSize: 12.5, fontWeight: 700, whiteSpace: 'nowrap' }, children: item.label }), jsx("span", { style: {
71
76
  ...BADGE_BASE,
72
77
  background: on ? '#EEF7F2' : '#F2F5F9',
73
78
  color: on ? '#00764A' : '#8A97A8',
@@ -1,5 +1,13 @@
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';
3
11
  import SingleSelect from '../FormComponents/Select/SingleSelect.esm.js';
4
12
  import MultiSelectAutocomplete from '../FormComponents/Select/MultiSelectAutocomplete.esm.js';
5
13
  import SingleSelectNonAutoComplete from '../FormComponents/Select/SingleSelectNonAutoComplete.esm.js';
@@ -11,14 +19,6 @@ import RichTextEditorWrapper from '../FormComponents/RichTextEditor/RichTextEdit
11
19
  import SingleSelectSearchApi from '../FormComponents/Select/SingleSelectSearchApi.esm.js';
12
20
  import MultiSelectSearchApi from '../FormComponents/Select/MultiSelectSearchApi.esm.js';
13
21
  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,3 +1,9 @@
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';
1
7
  export { default as SingleSelect } from './Select/SingleSelect.esm.js';
2
8
  export { default as SingleSelectNonAutoComplete } from './Select/SingleSelectNonAutoComplete.esm.js';
3
9
  export { default as SingleSelectSearchApi } from './Select/SingleSelectSearchApi.esm.js';
@@ -5,22 +11,33 @@ export { default as MultiSelectSearchApi } from './Select/MultiSelectSearchApi.e
5
11
  export { default as MultiSelectV1 } from './Select/MultiSelectv1.esm.js';
6
12
  export { default as MultiSelectTable } from './Select/MultiSelectTable.esm.js';
7
13
  export { default as SearchableSelect } from './Select/SearchableSelect.esm.js';
8
- export { default as DatepickerWrapperV2 } from './DatePicker/DatepickerWrapperV2.esm.js';
9
- export { default as FormBottomField } from './FormBottomField/FormBottomField.esm.js';
10
- export { default as FormCheckBox } from './FormCheckBox/FormCheckBox.esm.js';
11
14
  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
15
  export { default as FormRadioGroup } from './FormRadioGroup/FormRadioGroup.esm.js';
16
+ 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
+ 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';
16
29
  export { default as FormRenderFileUpload } from './FileUpload/FormRenderFileUpload.esm.js';
17
30
  export { default as FormRenderMultiFileUpload } from './FileUpload/FormRenderMultiFileUpload.esm.js';
18
- export { default as FormTextAreaField } from './FormTextAreaField/FormTextAreaField.esm.js';
19
- export { default as FormTextField } from './FormTextField/FormTextField.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';
20
41
  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';
23
42
  export { default as RichTextEditor } from './RichTextEditor/RichTextEditor.esm.js';
24
43
  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
  }
@@ -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 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 DateRange } from '../../../../../_virtual/index.esm6.js';
1
+ import { __exports as DateRange } from '../../../../../_virtual/index.esm4.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 requireCalendar } from '../Calendar/index.esm.js';
@@ -1,4 +1,4 @@
1
- import { __exports as DefinedRange } from '../../../../../_virtual/index.esm4.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 InputRangeField } from '../../../../../_virtual/index.esm13.js';
1
+ import { __exports as InputRangeField } 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
 
@@ -1,4 +1,4 @@
1
- import { __exports as Month } from '../../../../../_virtual/index.esm14.js';
1
+ import { __exports as Month } from '../../../../../_virtual/index.esm13.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.20",
3
+ "version": "3.0.22",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "React form components library built with React Hook Form and Yup",