@bsol-oss/react-datatable5 12.0.0-beta.84 → 12.0.0-beta.85
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/README.md +1 -0
- package/dist/index.js +140 -201
- package/dist/index.mjs +143 -204
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -575,7 +575,7 @@ const PaginationItems = (props) => {
|
|
|
575
575
|
return page.type === "ellipsis" ? (jsxRuntime.jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsxRuntime.jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
|
|
576
576
|
}) }));
|
|
577
577
|
};
|
|
578
|
-
|
|
578
|
+
React__namespace.forwardRef(function PaginationPageText(props, ref) {
|
|
579
579
|
const { format = "compact", ...rest } = props;
|
|
580
580
|
const { page, totalPages, pageRange, count } = react.usePaginationContext();
|
|
581
581
|
const content = React__namespace.useMemo(() => {
|
|
@@ -4176,16 +4176,6 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4176
4176
|
}, monthsToDisplay: 2 })] }) })] }) }));
|
|
4177
4177
|
};
|
|
4178
4178
|
|
|
4179
|
-
function filterArray(array, searchTerm) {
|
|
4180
|
-
// Convert the search term to lower case for case-insensitive comparison
|
|
4181
|
-
const lowerCaseSearchTerm = searchTerm.toLowerCase();
|
|
4182
|
-
// Use the filter method to return an array of matching items
|
|
4183
|
-
return array.filter((item) => {
|
|
4184
|
-
// Convert each item to a string and check if it includes the search term
|
|
4185
|
-
return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
|
|
4186
|
-
});
|
|
4187
|
-
}
|
|
4188
|
-
|
|
4189
4179
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4190
4180
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4191
4181
|
const { enumPickerLabels } = useSchemaContext();
|
|
@@ -4193,89 +4183,74 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4193
4183
|
const { required, variant } = schema;
|
|
4194
4184
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4195
4185
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
4196
|
-
const [searchText, setSearchText] = React.useState();
|
|
4197
|
-
const [limit, setLimit] = React.useState(10);
|
|
4198
|
-
const [openSearchResult, setOpenSearchResult] = React.useState();
|
|
4199
|
-
const ref = React.useRef(null);
|
|
4200
4186
|
const colLabel = formI18n.colLabel;
|
|
4201
4187
|
const watchEnum = watch(colLabel);
|
|
4202
4188
|
const watchEnums = (watch(colLabel) ?? []);
|
|
4203
4189
|
const dataList = schema.enum ?? [];
|
|
4204
|
-
|
|
4205
|
-
const
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4190
|
+
// Current value for combobox (array format)
|
|
4191
|
+
const currentValue = isMultiple
|
|
4192
|
+
? watchEnums.filter((val) => val != null && val !== '')
|
|
4193
|
+
: watchEnum
|
|
4194
|
+
? [watchEnum]
|
|
4195
|
+
: [];
|
|
4196
|
+
// Transform enum data for combobox collection
|
|
4197
|
+
const comboboxItems = React.useMemo(() => {
|
|
4198
|
+
return dataList.map((item) => ({
|
|
4199
|
+
label: !!renderDisplay === true
|
|
4200
|
+
? String(renderDisplay(item))
|
|
4201
|
+
: formI18n.t(item),
|
|
4202
|
+
value: item,
|
|
4203
|
+
}));
|
|
4204
|
+
}, [dataList, renderDisplay, formI18n]);
|
|
4205
|
+
// Use filter hook for combobox
|
|
4206
|
+
const { contains } = react.useFilter({ sensitivity: 'base' });
|
|
4207
|
+
// Create collection for combobox
|
|
4208
|
+
const { collection, filter } = react.useListCollection({
|
|
4209
|
+
initialItems: comboboxItems,
|
|
4210
|
+
itemToString: (item) => item.label,
|
|
4211
|
+
itemToValue: (item) => item.value,
|
|
4212
|
+
filter: contains,
|
|
4213
|
+
});
|
|
4214
|
+
// Handle input value change (search)
|
|
4215
|
+
const handleInputValueChange = (details) => {
|
|
4216
|
+
filter(details.inputValue);
|
|
4217
|
+
};
|
|
4218
|
+
// Handle value change
|
|
4219
|
+
const handleValueChange = (details) => {
|
|
4220
|
+
if (isMultiple) {
|
|
4221
|
+
setValue(colLabel, details.value);
|
|
4222
|
+
}
|
|
4223
|
+
else {
|
|
4224
|
+
setValue(colLabel, details.value[0] || '');
|
|
4225
|
+
}
|
|
4209
4226
|
};
|
|
4210
4227
|
if (variant === 'radio') {
|
|
4211
4228
|
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4212
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.RadioGroup.Root, {
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
}
|
|
4219
|
-
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
4220
|
-
setValue(colLabel, [...newSet]);
|
|
4221
|
-
}, value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
|
|
4229
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.RadioGroup.Root, { value: !isMultiple ? watchEnum : undefined, onValueChange: (details) => {
|
|
4230
|
+
if (!isMultiple) {
|
|
4231
|
+
setValue(colLabel, details.value);
|
|
4232
|
+
}
|
|
4233
|
+
}, children: jsxRuntime.jsx(react.HStack, { gap: "6", children: dataList.map((item) => {
|
|
4234
|
+
return (jsxRuntime.jsxs(react.RadioGroup.Item, { value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
|
|
4222
4235
|
? renderDisplay(item)
|
|
4223
4236
|
: formI18n.t(item) })] }, `${colLabel}-${item}`));
|
|
4224
4237
|
}) }) }) }));
|
|
4225
4238
|
}
|
|
4226
4239
|
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4227
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
}, justifyContent: 'start', children: !!watchEnum === false ? '' : formI18n.t(watchEnum ?? 'null') })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search'), onChange: (event) => {
|
|
4242
|
-
onSearchChange(event);
|
|
4243
|
-
setOpenSearchResult(true);
|
|
4244
|
-
}, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${count}, ${enumPickerLabels?.showing ?? formI18n.t('showing')} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', children: dataList
|
|
4245
|
-
.filter((item) => {
|
|
4246
|
-
const searchTerm = (searchText || '').toLowerCase();
|
|
4247
|
-
if (!searchTerm)
|
|
4248
|
-
return true;
|
|
4249
|
-
// Check if the original enum value contains the search text
|
|
4250
|
-
const enumValueMatch = item
|
|
4251
|
-
.toLowerCase()
|
|
4252
|
-
.includes(searchTerm);
|
|
4253
|
-
// Check if the display value (translation) contains the search text
|
|
4254
|
-
const displayValue = !!renderDisplay === true
|
|
4255
|
-
? renderDisplay(item)
|
|
4256
|
-
: formI18n.t(item);
|
|
4257
|
-
// Convert to string and check if it includes the search term
|
|
4258
|
-
const displayValueString = String(displayValue).toLowerCase();
|
|
4259
|
-
const displayValueMatch = displayValueString.includes(searchTerm);
|
|
4260
|
-
return enumValueMatch || displayValueMatch;
|
|
4261
|
-
})
|
|
4262
|
-
.map((item) => {
|
|
4263
|
-
const selected = isMultiple
|
|
4264
|
-
? watchEnums.some((enumValue) => item === enumValue)
|
|
4265
|
-
: watchEnum == item;
|
|
4266
|
-
return (jsxRuntime.jsx(react.Box, { cursor: 'pointer', onClick: () => {
|
|
4267
|
-
if (!isMultiple) {
|
|
4268
|
-
setOpenSearchResult(false);
|
|
4269
|
-
setValue(colLabel, item);
|
|
4270
|
-
return;
|
|
4271
|
-
}
|
|
4272
|
-
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
4273
|
-
setValue(colLabel, [...newSet]);
|
|
4274
|
-
}, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
|
|
4275
|
-
? renderDisplay(item)
|
|
4276
|
-
: formI18n.t(item) }, `${colLabel}-${item}`));
|
|
4277
|
-
}) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: enumPickerLabels?.emptySearchResult ??
|
|
4278
|
-
formI18n.t('empty_search_result') })) }))] })] }) })] })] }));
|
|
4240
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((enumValue) => {
|
|
4241
|
+
if (!enumValue) {
|
|
4242
|
+
return null;
|
|
4243
|
+
}
|
|
4244
|
+
return (jsxRuntime.jsx(Tag, { size: "lg", closable: true, onClick: () => {
|
|
4245
|
+
const newValue = currentValue.filter((val) => val !== enumValue);
|
|
4246
|
+
setValue(colLabel, newValue);
|
|
4247
|
+
}, children: !!renderDisplay === true
|
|
4248
|
+
? renderDisplay(enumValue)
|
|
4249
|
+
: formI18n.t(enumValue) }, enumValue));
|
|
4250
|
+
}) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [!isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
|
|
4251
|
+
setValue(colLabel, '');
|
|
4252
|
+
} })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [showTotalAndLimit && (jsxRuntime.jsx(react.Text, { p: 2, fontSize: "sm", color: "fg.muted", children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${collection.items.length}` })), collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: enumPickerLabels?.emptySearchResult ??
|
|
4253
|
+
formI18n.t('empty_search_result') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value))) }))] }) }) })] })] }));
|
|
4279
4254
|
};
|
|
4280
4255
|
|
|
4281
4256
|
function isEnteringWindow(_ref) {
|
|
@@ -4667,9 +4642,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4667
4642
|
: files;
|
|
4668
4643
|
const handleFileClick = (file) => {
|
|
4669
4644
|
if (multiple) {
|
|
4670
|
-
const currentSelection = Array.isArray(selectedFile)
|
|
4671
|
-
? selectedFile
|
|
4672
|
-
: [];
|
|
4645
|
+
const currentSelection = Array.isArray(selectedFile) ? selectedFile : [];
|
|
4673
4646
|
const isAlreadySelected = currentSelection.some((f) => f.id === file.id);
|
|
4674
4647
|
const newSelection = isAlreadySelected
|
|
4675
4648
|
? currentSelection.filter((f) => f.id !== file.id)
|
|
@@ -5036,15 +5009,6 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5036
5009
|
}) })] }));
|
|
5037
5010
|
};
|
|
5038
5011
|
|
|
5039
|
-
const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
|
|
5040
|
-
const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
|
|
5041
|
-
return (jsxRuntime.jsxs(react.Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsxs(react.Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsxRuntime.jsx(react.Popover.Arrow, { children: jsxRuntime.jsx(react.Popover.ArrowTip, {}) })), content] }) }) })] }));
|
|
5042
|
-
});
|
|
5043
|
-
const InfoTip = React__namespace.forwardRef(function InfoTip(props, ref) {
|
|
5044
|
-
const { children, ...rest } = props;
|
|
5045
|
-
return (jsxRuntime.jsx(ToggleTip, { content: children, ...rest, ref: ref, children: jsxRuntime.jsx(react.IconButton, { variant: "ghost", "aria-label": "info", size: "2xs", colorPalette: "colorPalette", children: jsxRuntime.jsx(hi.HiOutlineInformationCircle, {}) }) }));
|
|
5046
|
-
});
|
|
5047
|
-
|
|
5048
5012
|
const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
|
|
5049
5013
|
if (serverUrl === undefined || serverUrl.length == 0) {
|
|
5050
5014
|
throw new Error("The serverUrl is missing");
|
|
@@ -5081,10 +5045,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5081
5045
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5082
5046
|
const { table, column: column_ref, display_column, customQueryFn, } = foreign_key;
|
|
5083
5047
|
const [searchText, setSearchText] = React.useState('');
|
|
5084
|
-
const [limit
|
|
5085
|
-
const [openSearchResult, setOpenSearchResult] = React.useState();
|
|
5086
|
-
const [page, setPage] = React.useState(0);
|
|
5087
|
-
const ref = React.useRef(null);
|
|
5048
|
+
const [limit] = React.useState(50); // Increased limit for combobox
|
|
5088
5049
|
const colLabel = formI18n.colLabel;
|
|
5089
5050
|
const watchedValue = watch(colLabel);
|
|
5090
5051
|
const watchId = !isMultiple ? watchedValue : undefined;
|
|
@@ -5099,22 +5060,25 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5099
5060
|
: [];
|
|
5100
5061
|
// Use watched values if they exist (including empty string for single select),
|
|
5101
5062
|
// otherwise fall back to initial values from getValues()
|
|
5102
|
-
// This ensures the query can trigger on mount with initial values
|
|
5103
|
-
// For single: use watchId if it's not undefined/null, otherwise use initialId
|
|
5104
|
-
// For multiple: use watchIds if watchedValue is defined, otherwise use initialIds
|
|
5105
5063
|
const currentId = watchId !== undefined && watchId !== null ? watchId : initialId;
|
|
5106
5064
|
const currentIds = watchedValue !== undefined && watchedValue !== null && isMultiple
|
|
5107
5065
|
? watchIds
|
|
5108
5066
|
: initialIds;
|
|
5109
|
-
//
|
|
5067
|
+
// Current value for combobox (array format)
|
|
5068
|
+
const currentValue = isMultiple
|
|
5069
|
+
? currentIds.filter((id) => id != null && id !== '')
|
|
5070
|
+
: currentId
|
|
5071
|
+
? [currentId]
|
|
5072
|
+
: [];
|
|
5073
|
+
// Query for search results (async loading)
|
|
5110
5074
|
const query = reactQuery.useQuery({
|
|
5111
|
-
queryKey: [`idpicker`, { column, searchText, limit
|
|
5075
|
+
queryKey: [`idpicker`, { column, searchText, limit }],
|
|
5112
5076
|
queryFn: async () => {
|
|
5113
5077
|
if (customQueryFn) {
|
|
5114
5078
|
const { data, idMap } = await customQueryFn({
|
|
5115
5079
|
searching: searchText ?? '',
|
|
5116
5080
|
limit: limit,
|
|
5117
|
-
offset:
|
|
5081
|
+
offset: 0,
|
|
5118
5082
|
});
|
|
5119
5083
|
setIdMap((state) => {
|
|
5120
5084
|
return { ...state, ...idMap };
|
|
@@ -5126,7 +5090,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5126
5090
|
searching: searchText ?? '',
|
|
5127
5091
|
in_table: table,
|
|
5128
5092
|
limit: limit,
|
|
5129
|
-
offset:
|
|
5093
|
+
offset: 0,
|
|
5130
5094
|
});
|
|
5131
5095
|
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5132
5096
|
return [
|
|
@@ -5141,12 +5105,11 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5141
5105
|
});
|
|
5142
5106
|
return data;
|
|
5143
5107
|
},
|
|
5144
|
-
enabled:
|
|
5108
|
+
enabled: true, // Always enabled for combobox
|
|
5145
5109
|
staleTime: 300000,
|
|
5146
5110
|
});
|
|
5147
5111
|
// Query for currently selected items (to display them properly)
|
|
5148
|
-
|
|
5149
|
-
const queryDefault = reactQuery.useQuery({
|
|
5112
|
+
reactQuery.useQuery({
|
|
5150
5113
|
queryKey: [
|
|
5151
5114
|
`idpicker-default`,
|
|
5152
5115
|
{
|
|
@@ -5156,11 +5119,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5156
5119
|
},
|
|
5157
5120
|
],
|
|
5158
5121
|
queryFn: async () => {
|
|
5159
|
-
// Use current values (which include initial) for the query
|
|
5160
5122
|
const queryId = currentId;
|
|
5161
5123
|
const queryIds = currentIds;
|
|
5162
5124
|
if (customQueryFn) {
|
|
5163
|
-
// For customQueryFn, pass where clause to fetch specific IDs
|
|
5164
5125
|
const { data, idMap } = await customQueryFn({
|
|
5165
5126
|
searching: '',
|
|
5166
5127
|
limit: isMultiple ? queryIds.length : 1,
|
|
@@ -5175,10 +5136,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5175
5136
|
if (!queryId && (!queryIds || queryIds.length === 0)) {
|
|
5176
5137
|
return { data: [] };
|
|
5177
5138
|
}
|
|
5178
|
-
const searchValue = isMultiple ? queryIds.join(',') : queryId;
|
|
5179
5139
|
const data = await getTableData({
|
|
5180
5140
|
serverUrl,
|
|
5181
|
-
searching:
|
|
5141
|
+
searching: '',
|
|
5182
5142
|
in_table: table,
|
|
5183
5143
|
where: [{ id: column_ref, value: isMultiple ? queryIds : queryId }],
|
|
5184
5144
|
limit: isMultiple ? queryIds.length : 1,
|
|
@@ -5201,101 +5161,80 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5201
5161
|
? Array.isArray(currentIds) && currentIds.length > 0
|
|
5202
5162
|
: !!currentId,
|
|
5203
5163
|
});
|
|
5204
|
-
// Effect to trigger initial data fetch when popover opens
|
|
5205
|
-
React.useEffect(() => {
|
|
5206
|
-
if (openSearchResult) {
|
|
5207
|
-
// Reset search text when opening the popover
|
|
5208
|
-
setSearchText('');
|
|
5209
|
-
// Reset page to first page
|
|
5210
|
-
setPage(0);
|
|
5211
|
-
// Fetch initial data
|
|
5212
|
-
query.refetch();
|
|
5213
|
-
}
|
|
5214
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5215
|
-
}, [openSearchResult]);
|
|
5216
|
-
const onSearchChange = async (event) => {
|
|
5217
|
-
setSearchText(event.target.value);
|
|
5218
|
-
setPage(0);
|
|
5219
|
-
query.refetch();
|
|
5220
|
-
};
|
|
5221
|
-
const handleLimitChange = (event) => {
|
|
5222
|
-
const newLimit = Number(event.target.value);
|
|
5223
|
-
setLimit(newLimit);
|
|
5224
|
-
// Reset to first page when changing limit
|
|
5225
|
-
setPage(0);
|
|
5226
|
-
// Trigger a new search with the updated limit
|
|
5227
|
-
query.refetch();
|
|
5228
|
-
};
|
|
5229
5164
|
const { isLoading, isFetching, data, isPending, isError } = query;
|
|
5230
5165
|
const dataList = data?.data ?? [];
|
|
5231
|
-
|
|
5232
|
-
const
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5166
|
+
// Transform data for combobox collection
|
|
5167
|
+
const comboboxItems = React.useMemo(() => {
|
|
5168
|
+
return dataList.map((item) => ({
|
|
5169
|
+
label: !!renderDisplay === true
|
|
5170
|
+
? String(renderDisplay(item))
|
|
5171
|
+
: String(item[display_column] ?? ''),
|
|
5172
|
+
value: String(item[column_ref]),
|
|
5173
|
+
raw: item,
|
|
5174
|
+
}));
|
|
5175
|
+
}, [dataList, display_column, column_ref, renderDisplay]);
|
|
5176
|
+
// Use filter hook for combobox
|
|
5177
|
+
const { contains } = react.useFilter({ sensitivity: 'base' });
|
|
5178
|
+
// Create collection for combobox
|
|
5179
|
+
const { collection, filter, set } = react.useListCollection({
|
|
5180
|
+
initialItems: comboboxItems,
|
|
5181
|
+
itemToString: (item) => item.label,
|
|
5182
|
+
itemToValue: (item) => item.value,
|
|
5183
|
+
filter: contains,
|
|
5184
|
+
});
|
|
5185
|
+
// Handle input value change (search)
|
|
5186
|
+
const handleInputValueChange = (details) => {
|
|
5187
|
+
setSearchText(details.inputValue);
|
|
5188
|
+
// Filter will be applied after data is fetched
|
|
5189
|
+
};
|
|
5190
|
+
// Handle value change
|
|
5191
|
+
const handleValueChange = (details) => {
|
|
5192
|
+
if (isMultiple) {
|
|
5193
|
+
setValue(colLabel, details.value);
|
|
5240
5194
|
}
|
|
5241
|
-
|
|
5242
|
-
|
|
5195
|
+
else {
|
|
5196
|
+
setValue(colLabel, details.value[0] || '');
|
|
5243
5197
|
}
|
|
5244
|
-
return record[display_column];
|
|
5245
5198
|
};
|
|
5199
|
+
// Debounce search to avoid too many API calls and update collection after data loads
|
|
5200
|
+
React.useEffect(() => {
|
|
5201
|
+
const timer = setTimeout(() => {
|
|
5202
|
+
if (searchText !== undefined) {
|
|
5203
|
+
query.refetch();
|
|
5204
|
+
}
|
|
5205
|
+
}, 300);
|
|
5206
|
+
return () => clearTimeout(timer);
|
|
5207
|
+
}, [searchText, query]);
|
|
5208
|
+
// Update collection and filter when data changes
|
|
5209
|
+
React.useEffect(() => {
|
|
5210
|
+
if (dataList.length > 0) {
|
|
5211
|
+
set(comboboxItems);
|
|
5212
|
+
// Apply filter to the collection
|
|
5213
|
+
if (searchText) {
|
|
5214
|
+
filter(searchText);
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
}, [dataList, comboboxItems, set, filter, searchText]);
|
|
5246
5218
|
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5247
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
border: '1px solid #ccc',
|
|
5267
|
-
fontSize: '14px',
|
|
5268
|
-
}, children: [jsxRuntime.jsx("option", { value: "5", children: "5" }), jsxRuntime.jsx("option", { value: "10", children: "10" }), jsxRuntime.jsx("option", { value: "20", children: "20" }), jsxRuntime.jsx("option", { value: "30", children: "30" })] }) })] }), jsxRuntime.jsx(react.Grid, { overflowY: 'auto', children: dataList.length > 0 ? (jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', gap: 1, children: dataList.map((item) => {
|
|
5269
|
-
const selected = isMultiple
|
|
5270
|
-
? watchIds.some((id) => item[column_ref] === id)
|
|
5271
|
-
: watchId === item[column_ref];
|
|
5272
|
-
return (jsxRuntime.jsx(react.Box, { cursor: 'pointer', onClick: () => {
|
|
5273
|
-
if (!isMultiple) {
|
|
5274
|
-
setOpenSearchResult(false);
|
|
5275
|
-
setValue(colLabel, item[column_ref]);
|
|
5276
|
-
return;
|
|
5277
|
-
}
|
|
5278
|
-
// For multiple selection, don't add if already selected
|
|
5279
|
-
if (selected)
|
|
5280
|
-
return;
|
|
5281
|
-
const newSet = new Set([
|
|
5282
|
-
...(watchIds ?? []),
|
|
5283
|
-
item[column_ref],
|
|
5284
|
-
]);
|
|
5285
|
-
setValue(colLabel, [...newSet]);
|
|
5286
|
-
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
5287
|
-
? {
|
|
5288
|
-
color: 'colorPalette.400/50',
|
|
5289
|
-
fontWeight: 'bold',
|
|
5290
|
-
}
|
|
5291
|
-
: {}), children: !!renderDisplay === true
|
|
5292
|
-
? renderDisplay(item)
|
|
5293
|
-
: item[display_column] }, item[column_ref]));
|
|
5294
|
-
}) })) : (jsxRuntime.jsx(react.Text, { children: searchText
|
|
5295
|
-
? idPickerLabels?.emptySearchResult ??
|
|
5296
|
-
formI18n.t('empty_search_result')
|
|
5297
|
-
: idPickerLabels?.initialResults ??
|
|
5298
|
-
formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] })] }));
|
|
5219
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5220
|
+
const item = idMap[id];
|
|
5221
|
+
if (item === undefined) {
|
|
5222
|
+
return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
|
|
5223
|
+
}
|
|
5224
|
+
return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
|
|
5225
|
+
const newValue = currentValue.filter((itemId) => itemId !== id);
|
|
5226
|
+
setValue(colLabel, newValue);
|
|
5227
|
+
}, children: !!renderDisplay === true
|
|
5228
|
+
? renderDisplay(item)
|
|
5229
|
+
: item[display_column] }, id));
|
|
5230
|
+
}) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && (jsxRuntime.jsx(react.Spinner, { size: "xs" })), isError && (jsxRuntime.jsx(react.Icon, { color: "fg.error", children: jsxRuntime.jsx(bi.BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
|
|
5231
|
+
setValue(colLabel, '');
|
|
5232
|
+
} })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isFetching || isLoading || isPending ? (jsxRuntime.jsxs(react.HStack, { p: 2, justify: "center", children: [jsxRuntime.jsx(react.Spinner, { size: "xs" }), jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.loading ?? formI18n.t('loading') })] })) : isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.loadingFailed ??
|
|
5233
|
+
formI18n.t('loading_failed') })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
|
|
5234
|
+
? idPickerLabels?.emptySearchResult ??
|
|
5235
|
+
formI18n.t('empty_search_result')
|
|
5236
|
+
: idPickerLabels?.initialResults ??
|
|
5237
|
+
formI18n.t('initial_results') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value))) })) }) }) })] })] }));
|
|
5299
5238
|
};
|
|
5300
5239
|
|
|
5301
5240
|
const NumberInputRoot = React__namespace.forwardRef(function NumberInput(props, ref) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Image, Alert, Field as Field$1, Popover, Tabs, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading, Skeleton } from '@chakra-ui/react';
|
|
2
|
+
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Image, Alert, Field as Field$1, Popover, useFilter, useListCollection, Combobox, Tabs, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading, Skeleton } from '@chakra-ui/react';
|
|
3
3
|
import { AiOutlineColumnWidth } from 'react-icons/ai';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, { createContext, useContext, useState, useEffect, useRef, forwardRef } from 'react';
|
|
5
|
+
import React__default, { createContext, useContext, useState, useEffect, useRef, useMemo, forwardRef } from 'react';
|
|
6
6
|
import { LuX, LuCheck, LuChevronRight, LuSearch, LuImage, LuFile } from 'react-icons/lu';
|
|
7
7
|
import { MdOutlineSort, MdFilterAlt, MdSearch, MdOutlineChecklist, MdClear, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdDateRange } from 'react-icons/md';
|
|
8
8
|
import { FaUpDown, FaGripLinesVertical, FaTrash } from 'react-icons/fa6';
|
|
@@ -21,7 +21,7 @@ import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
|
21
21
|
import { IoReload } from 'react-icons/io5';
|
|
22
22
|
import { useDebounce } from '@uidotdev/usehooks';
|
|
23
23
|
import { BsExclamationCircleFill, BsClock } from 'react-icons/bs';
|
|
24
|
-
import { HiColorSwatch
|
|
24
|
+
import { HiColorSwatch } from 'react-icons/hi';
|
|
25
25
|
import { flexRender, createColumnHelper, makeStateUpdater, functionalUpdate, useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel } from '@tanstack/react-table';
|
|
26
26
|
import { GrAscend, GrDescend } from 'react-icons/gr';
|
|
27
27
|
import { useTranslation } from 'react-i18next';
|
|
@@ -555,7 +555,7 @@ const PaginationItems = (props) => {
|
|
|
555
555
|
return page.type === "ellipsis" ? (jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
|
|
556
556
|
}) }));
|
|
557
557
|
};
|
|
558
|
-
|
|
558
|
+
React.forwardRef(function PaginationPageText(props, ref) {
|
|
559
559
|
const { format = "compact", ...rest } = props;
|
|
560
560
|
const { page, totalPages, pageRange, count } = usePaginationContext();
|
|
561
561
|
const content = React.useMemo(() => {
|
|
@@ -4156,16 +4156,6 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4156
4156
|
}, monthsToDisplay: 2 })] }) })] }) }));
|
|
4157
4157
|
};
|
|
4158
4158
|
|
|
4159
|
-
function filterArray(array, searchTerm) {
|
|
4160
|
-
// Convert the search term to lower case for case-insensitive comparison
|
|
4161
|
-
const lowerCaseSearchTerm = searchTerm.toLowerCase();
|
|
4162
|
-
// Use the filter method to return an array of matching items
|
|
4163
|
-
return array.filter((item) => {
|
|
4164
|
-
// Convert each item to a string and check if it includes the search term
|
|
4165
|
-
return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
|
|
4166
|
-
});
|
|
4167
|
-
}
|
|
4168
|
-
|
|
4169
4159
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4170
4160
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4171
4161
|
const { enumPickerLabels } = useSchemaContext();
|
|
@@ -4173,89 +4163,74 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4173
4163
|
const { required, variant } = schema;
|
|
4174
4164
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4175
4165
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
4176
|
-
const [searchText, setSearchText] = useState();
|
|
4177
|
-
const [limit, setLimit] = useState(10);
|
|
4178
|
-
const [openSearchResult, setOpenSearchResult] = useState();
|
|
4179
|
-
const ref = useRef(null);
|
|
4180
4166
|
const colLabel = formI18n.colLabel;
|
|
4181
4167
|
const watchEnum = watch(colLabel);
|
|
4182
4168
|
const watchEnums = (watch(colLabel) ?? []);
|
|
4183
4169
|
const dataList = schema.enum ?? [];
|
|
4184
|
-
|
|
4185
|
-
const
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4170
|
+
// Current value for combobox (array format)
|
|
4171
|
+
const currentValue = isMultiple
|
|
4172
|
+
? watchEnums.filter((val) => val != null && val !== '')
|
|
4173
|
+
: watchEnum
|
|
4174
|
+
? [watchEnum]
|
|
4175
|
+
: [];
|
|
4176
|
+
// Transform enum data for combobox collection
|
|
4177
|
+
const comboboxItems = useMemo(() => {
|
|
4178
|
+
return dataList.map((item) => ({
|
|
4179
|
+
label: !!renderDisplay === true
|
|
4180
|
+
? String(renderDisplay(item))
|
|
4181
|
+
: formI18n.t(item),
|
|
4182
|
+
value: item,
|
|
4183
|
+
}));
|
|
4184
|
+
}, [dataList, renderDisplay, formI18n]);
|
|
4185
|
+
// Use filter hook for combobox
|
|
4186
|
+
const { contains } = useFilter({ sensitivity: 'base' });
|
|
4187
|
+
// Create collection for combobox
|
|
4188
|
+
const { collection, filter } = useListCollection({
|
|
4189
|
+
initialItems: comboboxItems,
|
|
4190
|
+
itemToString: (item) => item.label,
|
|
4191
|
+
itemToValue: (item) => item.value,
|
|
4192
|
+
filter: contains,
|
|
4193
|
+
});
|
|
4194
|
+
// Handle input value change (search)
|
|
4195
|
+
const handleInputValueChange = (details) => {
|
|
4196
|
+
filter(details.inputValue);
|
|
4197
|
+
};
|
|
4198
|
+
// Handle value change
|
|
4199
|
+
const handleValueChange = (details) => {
|
|
4200
|
+
if (isMultiple) {
|
|
4201
|
+
setValue(colLabel, details.value);
|
|
4202
|
+
}
|
|
4203
|
+
else {
|
|
4204
|
+
setValue(colLabel, details.value[0] || '');
|
|
4205
|
+
}
|
|
4189
4206
|
};
|
|
4190
4207
|
if (variant === 'radio') {
|
|
4191
4208
|
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4192
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(RadioGroup$1.Root, {
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
}
|
|
4199
|
-
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
4200
|
-
setValue(colLabel, [...newSet]);
|
|
4201
|
-
}, value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
|
|
4209
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(RadioGroup$1.Root, { value: !isMultiple ? watchEnum : undefined, onValueChange: (details) => {
|
|
4210
|
+
if (!isMultiple) {
|
|
4211
|
+
setValue(colLabel, details.value);
|
|
4212
|
+
}
|
|
4213
|
+
}, children: jsx(HStack, { gap: "6", children: dataList.map((item) => {
|
|
4214
|
+
return (jsxs(RadioGroup$1.Item, { value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
|
|
4202
4215
|
? renderDisplay(item)
|
|
4203
4216
|
: formI18n.t(item) })] }, `${colLabel}-${item}`));
|
|
4204
4217
|
}) }) }) }));
|
|
4205
4218
|
}
|
|
4206
4219
|
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4207
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
}, justifyContent: 'start', children: !!watchEnum === false ? '' : formI18n.t(watchEnum ?? 'null') })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { portalled: false, children: jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsx(Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search'), onChange: (event) => {
|
|
4222
|
-
onSearchChange(event);
|
|
4223
|
-
setOpenSearchResult(true);
|
|
4224
|
-
}, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), showTotalAndLimit && (jsx(Text, { children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${count}, ${enumPickerLabels?.showing ?? formI18n.t('showing')} ${limit}` })), jsxs(Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsx(Flex, { flexFlow: 'column wrap', children: dataList
|
|
4225
|
-
.filter((item) => {
|
|
4226
|
-
const searchTerm = (searchText || '').toLowerCase();
|
|
4227
|
-
if (!searchTerm)
|
|
4228
|
-
return true;
|
|
4229
|
-
// Check if the original enum value contains the search text
|
|
4230
|
-
const enumValueMatch = item
|
|
4231
|
-
.toLowerCase()
|
|
4232
|
-
.includes(searchTerm);
|
|
4233
|
-
// Check if the display value (translation) contains the search text
|
|
4234
|
-
const displayValue = !!renderDisplay === true
|
|
4235
|
-
? renderDisplay(item)
|
|
4236
|
-
: formI18n.t(item);
|
|
4237
|
-
// Convert to string and check if it includes the search term
|
|
4238
|
-
const displayValueString = String(displayValue).toLowerCase();
|
|
4239
|
-
const displayValueMatch = displayValueString.includes(searchTerm);
|
|
4240
|
-
return enumValueMatch || displayValueMatch;
|
|
4241
|
-
})
|
|
4242
|
-
.map((item) => {
|
|
4243
|
-
const selected = isMultiple
|
|
4244
|
-
? watchEnums.some((enumValue) => item === enumValue)
|
|
4245
|
-
: watchEnum == item;
|
|
4246
|
-
return (jsx(Box, { cursor: 'pointer', onClick: () => {
|
|
4247
|
-
if (!isMultiple) {
|
|
4248
|
-
setOpenSearchResult(false);
|
|
4249
|
-
setValue(colLabel, item);
|
|
4250
|
-
return;
|
|
4251
|
-
}
|
|
4252
|
-
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
4253
|
-
setValue(colLabel, [...newSet]);
|
|
4254
|
-
}, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
|
|
4255
|
-
? renderDisplay(item)
|
|
4256
|
-
: formI18n.t(item) }, `${colLabel}-${item}`));
|
|
4257
|
-
}) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Fragment, { children: enumPickerLabels?.emptySearchResult ??
|
|
4258
|
-
formI18n.t('empty_search_result') })) }))] })] }) })] })] }));
|
|
4220
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((enumValue) => {
|
|
4221
|
+
if (!enumValue) {
|
|
4222
|
+
return null;
|
|
4223
|
+
}
|
|
4224
|
+
return (jsx(Tag, { size: "lg", closable: true, onClick: () => {
|
|
4225
|
+
const newValue = currentValue.filter((val) => val !== enumValue);
|
|
4226
|
+
setValue(colLabel, newValue);
|
|
4227
|
+
}, children: !!renderDisplay === true
|
|
4228
|
+
? renderDisplay(enumValue)
|
|
4229
|
+
: formI18n.t(enumValue) }, enumValue));
|
|
4230
|
+
}) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxs(Combobox.IndicatorGroup, { children: [!isMultiple && currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
|
|
4231
|
+
setValue(colLabel, '');
|
|
4232
|
+
} })), jsx(Combobox.Trigger, {})] })] }), jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [showTotalAndLimit && (jsx(Text, { p: 2, fontSize: "sm", color: "fg.muted", children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${collection.items.length}` })), collection.items.length === 0 ? (jsx(Combobox.Empty, { children: enumPickerLabels?.emptySearchResult ??
|
|
4233
|
+
formI18n.t('empty_search_result') })) : (jsx(Fragment, { children: collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value))) }))] }) }) })] })] }));
|
|
4259
4234
|
};
|
|
4260
4235
|
|
|
4261
4236
|
function isEnteringWindow(_ref) {
|
|
@@ -4647,9 +4622,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4647
4622
|
: files;
|
|
4648
4623
|
const handleFileClick = (file) => {
|
|
4649
4624
|
if (multiple) {
|
|
4650
|
-
const currentSelection = Array.isArray(selectedFile)
|
|
4651
|
-
? selectedFile
|
|
4652
|
-
: [];
|
|
4625
|
+
const currentSelection = Array.isArray(selectedFile) ? selectedFile : [];
|
|
4653
4626
|
const isAlreadySelected = currentSelection.some((f) => f.id === file.id);
|
|
4654
4627
|
const newSelection = isAlreadySelected
|
|
4655
4628
|
? currentSelection.filter((f) => f.id !== file.id)
|
|
@@ -5016,15 +4989,6 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5016
4989
|
}) })] }));
|
|
5017
4990
|
};
|
|
5018
4991
|
|
|
5019
|
-
const ToggleTip = React.forwardRef(function ToggleTip(props, ref) {
|
|
5020
|
-
const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
|
|
5021
|
-
return (jsxs(Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsx(Popover.Trigger, { asChild: true, children: children }), jsx(Portal, { disabled: !portalled, container: portalRef, children: jsx(Popover.Positioner, { children: jsxs(Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsx(Popover.Arrow, { children: jsx(Popover.ArrowTip, {}) })), content] }) }) })] }));
|
|
5022
|
-
});
|
|
5023
|
-
const InfoTip = React.forwardRef(function InfoTip(props, ref) {
|
|
5024
|
-
const { children, ...rest } = props;
|
|
5025
|
-
return (jsx(ToggleTip, { content: children, ...rest, ref: ref, children: jsx(IconButton, { variant: "ghost", "aria-label": "info", size: "2xs", colorPalette: "colorPalette", children: jsx(HiOutlineInformationCircle, {}) }) }));
|
|
5026
|
-
});
|
|
5027
|
-
|
|
5028
4992
|
const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
|
|
5029
4993
|
if (serverUrl === undefined || serverUrl.length == 0) {
|
|
5030
4994
|
throw new Error("The serverUrl is missing");
|
|
@@ -5061,10 +5025,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5061
5025
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5062
5026
|
const { table, column: column_ref, display_column, customQueryFn, } = foreign_key;
|
|
5063
5027
|
const [searchText, setSearchText] = useState('');
|
|
5064
|
-
const [limit
|
|
5065
|
-
const [openSearchResult, setOpenSearchResult] = useState();
|
|
5066
|
-
const [page, setPage] = useState(0);
|
|
5067
|
-
const ref = useRef(null);
|
|
5028
|
+
const [limit] = useState(50); // Increased limit for combobox
|
|
5068
5029
|
const colLabel = formI18n.colLabel;
|
|
5069
5030
|
const watchedValue = watch(colLabel);
|
|
5070
5031
|
const watchId = !isMultiple ? watchedValue : undefined;
|
|
@@ -5079,22 +5040,25 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5079
5040
|
: [];
|
|
5080
5041
|
// Use watched values if they exist (including empty string for single select),
|
|
5081
5042
|
// otherwise fall back to initial values from getValues()
|
|
5082
|
-
// This ensures the query can trigger on mount with initial values
|
|
5083
|
-
// For single: use watchId if it's not undefined/null, otherwise use initialId
|
|
5084
|
-
// For multiple: use watchIds if watchedValue is defined, otherwise use initialIds
|
|
5085
5043
|
const currentId = watchId !== undefined && watchId !== null ? watchId : initialId;
|
|
5086
5044
|
const currentIds = watchedValue !== undefined && watchedValue !== null && isMultiple
|
|
5087
5045
|
? watchIds
|
|
5088
5046
|
: initialIds;
|
|
5089
|
-
//
|
|
5047
|
+
// Current value for combobox (array format)
|
|
5048
|
+
const currentValue = isMultiple
|
|
5049
|
+
? currentIds.filter((id) => id != null && id !== '')
|
|
5050
|
+
: currentId
|
|
5051
|
+
? [currentId]
|
|
5052
|
+
: [];
|
|
5053
|
+
// Query for search results (async loading)
|
|
5090
5054
|
const query = useQuery({
|
|
5091
|
-
queryKey: [`idpicker`, { column, searchText, limit
|
|
5055
|
+
queryKey: [`idpicker`, { column, searchText, limit }],
|
|
5092
5056
|
queryFn: async () => {
|
|
5093
5057
|
if (customQueryFn) {
|
|
5094
5058
|
const { data, idMap } = await customQueryFn({
|
|
5095
5059
|
searching: searchText ?? '',
|
|
5096
5060
|
limit: limit,
|
|
5097
|
-
offset:
|
|
5061
|
+
offset: 0,
|
|
5098
5062
|
});
|
|
5099
5063
|
setIdMap((state) => {
|
|
5100
5064
|
return { ...state, ...idMap };
|
|
@@ -5106,7 +5070,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5106
5070
|
searching: searchText ?? '',
|
|
5107
5071
|
in_table: table,
|
|
5108
5072
|
limit: limit,
|
|
5109
|
-
offset:
|
|
5073
|
+
offset: 0,
|
|
5110
5074
|
});
|
|
5111
5075
|
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5112
5076
|
return [
|
|
@@ -5121,12 +5085,11 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5121
5085
|
});
|
|
5122
5086
|
return data;
|
|
5123
5087
|
},
|
|
5124
|
-
enabled:
|
|
5088
|
+
enabled: true, // Always enabled for combobox
|
|
5125
5089
|
staleTime: 300000,
|
|
5126
5090
|
});
|
|
5127
5091
|
// Query for currently selected items (to display them properly)
|
|
5128
|
-
|
|
5129
|
-
const queryDefault = useQuery({
|
|
5092
|
+
useQuery({
|
|
5130
5093
|
queryKey: [
|
|
5131
5094
|
`idpicker-default`,
|
|
5132
5095
|
{
|
|
@@ -5136,11 +5099,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5136
5099
|
},
|
|
5137
5100
|
],
|
|
5138
5101
|
queryFn: async () => {
|
|
5139
|
-
// Use current values (which include initial) for the query
|
|
5140
5102
|
const queryId = currentId;
|
|
5141
5103
|
const queryIds = currentIds;
|
|
5142
5104
|
if (customQueryFn) {
|
|
5143
|
-
// For customQueryFn, pass where clause to fetch specific IDs
|
|
5144
5105
|
const { data, idMap } = await customQueryFn({
|
|
5145
5106
|
searching: '',
|
|
5146
5107
|
limit: isMultiple ? queryIds.length : 1,
|
|
@@ -5155,10 +5116,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5155
5116
|
if (!queryId && (!queryIds || queryIds.length === 0)) {
|
|
5156
5117
|
return { data: [] };
|
|
5157
5118
|
}
|
|
5158
|
-
const searchValue = isMultiple ? queryIds.join(',') : queryId;
|
|
5159
5119
|
const data = await getTableData({
|
|
5160
5120
|
serverUrl,
|
|
5161
|
-
searching:
|
|
5121
|
+
searching: '',
|
|
5162
5122
|
in_table: table,
|
|
5163
5123
|
where: [{ id: column_ref, value: isMultiple ? queryIds : queryId }],
|
|
5164
5124
|
limit: isMultiple ? queryIds.length : 1,
|
|
@@ -5181,101 +5141,80 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5181
5141
|
? Array.isArray(currentIds) && currentIds.length > 0
|
|
5182
5142
|
: !!currentId,
|
|
5183
5143
|
});
|
|
5184
|
-
// Effect to trigger initial data fetch when popover opens
|
|
5185
|
-
useEffect(() => {
|
|
5186
|
-
if (openSearchResult) {
|
|
5187
|
-
// Reset search text when opening the popover
|
|
5188
|
-
setSearchText('');
|
|
5189
|
-
// Reset page to first page
|
|
5190
|
-
setPage(0);
|
|
5191
|
-
// Fetch initial data
|
|
5192
|
-
query.refetch();
|
|
5193
|
-
}
|
|
5194
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5195
|
-
}, [openSearchResult]);
|
|
5196
|
-
const onSearchChange = async (event) => {
|
|
5197
|
-
setSearchText(event.target.value);
|
|
5198
|
-
setPage(0);
|
|
5199
|
-
query.refetch();
|
|
5200
|
-
};
|
|
5201
|
-
const handleLimitChange = (event) => {
|
|
5202
|
-
const newLimit = Number(event.target.value);
|
|
5203
|
-
setLimit(newLimit);
|
|
5204
|
-
// Reset to first page when changing limit
|
|
5205
|
-
setPage(0);
|
|
5206
|
-
// Trigger a new search with the updated limit
|
|
5207
|
-
query.refetch();
|
|
5208
|
-
};
|
|
5209
5144
|
const { isLoading, isFetching, data, isPending, isError } = query;
|
|
5210
5145
|
const dataList = data?.data ?? [];
|
|
5211
|
-
|
|
5212
|
-
const
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5146
|
+
// Transform data for combobox collection
|
|
5147
|
+
const comboboxItems = useMemo(() => {
|
|
5148
|
+
return dataList.map((item) => ({
|
|
5149
|
+
label: !!renderDisplay === true
|
|
5150
|
+
? String(renderDisplay(item))
|
|
5151
|
+
: String(item[display_column] ?? ''),
|
|
5152
|
+
value: String(item[column_ref]),
|
|
5153
|
+
raw: item,
|
|
5154
|
+
}));
|
|
5155
|
+
}, [dataList, display_column, column_ref, renderDisplay]);
|
|
5156
|
+
// Use filter hook for combobox
|
|
5157
|
+
const { contains } = useFilter({ sensitivity: 'base' });
|
|
5158
|
+
// Create collection for combobox
|
|
5159
|
+
const { collection, filter, set } = useListCollection({
|
|
5160
|
+
initialItems: comboboxItems,
|
|
5161
|
+
itemToString: (item) => item.label,
|
|
5162
|
+
itemToValue: (item) => item.value,
|
|
5163
|
+
filter: contains,
|
|
5164
|
+
});
|
|
5165
|
+
// Handle input value change (search)
|
|
5166
|
+
const handleInputValueChange = (details) => {
|
|
5167
|
+
setSearchText(details.inputValue);
|
|
5168
|
+
// Filter will be applied after data is fetched
|
|
5169
|
+
};
|
|
5170
|
+
// Handle value change
|
|
5171
|
+
const handleValueChange = (details) => {
|
|
5172
|
+
if (isMultiple) {
|
|
5173
|
+
setValue(colLabel, details.value);
|
|
5220
5174
|
}
|
|
5221
|
-
|
|
5222
|
-
|
|
5175
|
+
else {
|
|
5176
|
+
setValue(colLabel, details.value[0] || '');
|
|
5223
5177
|
}
|
|
5224
|
-
return record[display_column];
|
|
5225
5178
|
};
|
|
5179
|
+
// Debounce search to avoid too many API calls and update collection after data loads
|
|
5180
|
+
useEffect(() => {
|
|
5181
|
+
const timer = setTimeout(() => {
|
|
5182
|
+
if (searchText !== undefined) {
|
|
5183
|
+
query.refetch();
|
|
5184
|
+
}
|
|
5185
|
+
}, 300);
|
|
5186
|
+
return () => clearTimeout(timer);
|
|
5187
|
+
}, [searchText, query]);
|
|
5188
|
+
// Update collection and filter when data changes
|
|
5189
|
+
useEffect(() => {
|
|
5190
|
+
if (dataList.length > 0) {
|
|
5191
|
+
set(comboboxItems);
|
|
5192
|
+
// Apply filter to the collection
|
|
5193
|
+
if (searchText) {
|
|
5194
|
+
filter(searchText);
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
}, [dataList, comboboxItems, set, filter, searchText]);
|
|
5226
5198
|
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5227
|
-
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
border: '1px solid #ccc',
|
|
5247
|
-
fontSize: '14px',
|
|
5248
|
-
}, children: [jsx("option", { value: "5", children: "5" }), jsx("option", { value: "10", children: "10" }), jsx("option", { value: "20", children: "20" }), jsx("option", { value: "30", children: "30" })] }) })] }), jsx(Grid, { overflowY: 'auto', children: dataList.length > 0 ? (jsx(Flex, { flexFlow: 'column wrap', gap: 1, children: dataList.map((item) => {
|
|
5249
|
-
const selected = isMultiple
|
|
5250
|
-
? watchIds.some((id) => item[column_ref] === id)
|
|
5251
|
-
: watchId === item[column_ref];
|
|
5252
|
-
return (jsx(Box, { cursor: 'pointer', onClick: () => {
|
|
5253
|
-
if (!isMultiple) {
|
|
5254
|
-
setOpenSearchResult(false);
|
|
5255
|
-
setValue(colLabel, item[column_ref]);
|
|
5256
|
-
return;
|
|
5257
|
-
}
|
|
5258
|
-
// For multiple selection, don't add if already selected
|
|
5259
|
-
if (selected)
|
|
5260
|
-
return;
|
|
5261
|
-
const newSet = new Set([
|
|
5262
|
-
...(watchIds ?? []),
|
|
5263
|
-
item[column_ref],
|
|
5264
|
-
]);
|
|
5265
|
-
setValue(colLabel, [...newSet]);
|
|
5266
|
-
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
5267
|
-
? {
|
|
5268
|
-
color: 'colorPalette.400/50',
|
|
5269
|
-
fontWeight: 'bold',
|
|
5270
|
-
}
|
|
5271
|
-
: {}), children: !!renderDisplay === true
|
|
5272
|
-
? renderDisplay(item)
|
|
5273
|
-
: item[display_column] }, item[column_ref]));
|
|
5274
|
-
}) })) : (jsx(Text, { children: searchText
|
|
5275
|
-
? idPickerLabels?.emptySearchResult ??
|
|
5276
|
-
formI18n.t('empty_search_result')
|
|
5277
|
-
: idPickerLabels?.initialResults ??
|
|
5278
|
-
formI18n.t('initial_results') })) }), jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] })] }));
|
|
5199
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5200
|
+
const item = idMap[id];
|
|
5201
|
+
if (item === undefined) {
|
|
5202
|
+
return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
|
|
5203
|
+
}
|
|
5204
|
+
return (jsx(Tag, { closable: true, onClick: () => {
|
|
5205
|
+
const newValue = currentValue.filter((itemId) => itemId !== id);
|
|
5206
|
+
setValue(colLabel, newValue);
|
|
5207
|
+
}, children: !!renderDisplay === true
|
|
5208
|
+
? renderDisplay(item)
|
|
5209
|
+
: item[display_column] }, id));
|
|
5210
|
+
}) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && (jsx(Spinner, { size: "xs" })), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
|
|
5211
|
+
setValue(colLabel, '');
|
|
5212
|
+
} })), jsx(Combobox.Trigger, {})] })] }), jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isFetching || isLoading || isPending ? (jsxs(HStack, { p: 2, justify: "center", children: [jsx(Spinner, { size: "xs" }), jsx(Text, { fontSize: "sm", children: idPickerLabels?.loading ?? formI18n.t('loading') })] })) : isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.loadingFailed ??
|
|
5213
|
+
formI18n.t('loading_failed') })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
|
|
5214
|
+
? idPickerLabels?.emptySearchResult ??
|
|
5215
|
+
formI18n.t('empty_search_result')
|
|
5216
|
+
: idPickerLabels?.initialResults ??
|
|
5217
|
+
formI18n.t('initial_results') })) : (jsx(Fragment, { children: collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value))) })) }) }) })] })] }));
|
|
5279
5218
|
};
|
|
5280
5219
|
|
|
5281
5220
|
const NumberInputRoot = React.forwardRef(function NumberInput$1(props, ref) {
|