@bsol-oss/react-datatable5 13.0.1 → 13.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +20 -16
- package/dist/index.mjs +20 -16
- package/dist/types/components/Form/utils/useFormLabel.d.ts +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3917,6 +3917,10 @@ const useFormLabel = (column, prefix = '', schema) => {
|
|
|
3917
3917
|
// Return column name as fallback
|
|
3918
3918
|
return column;
|
|
3919
3919
|
},
|
|
3920
|
+
/**
|
|
3921
|
+
* Helper text from JSON Schema `description` (shown below the control).
|
|
3922
|
+
*/
|
|
3923
|
+
helperText: schema.description,
|
|
3920
3924
|
};
|
|
3921
3925
|
};
|
|
3922
3926
|
|
|
@@ -3997,7 +4001,7 @@ const BooleanPicker = ({ schema, column, prefix }) => {
|
|
|
3997
4001
|
const value = watch(colLabel);
|
|
3998
4002
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
3999
4003
|
const fieldError = getNestedError(errors, colLabel);
|
|
4000
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4004
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4001
4005
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
4002
4006
|
setValue(colLabel, !value);
|
|
4003
4007
|
} }) }));
|
|
@@ -4118,7 +4122,7 @@ const DatePicker = ({ column, schema, prefix }) => {
|
|
|
4118
4122
|
console.error(e);
|
|
4119
4123
|
}
|
|
4120
4124
|
}, [selectedDate, dateFormat, colLabel, setValue, timezone]);
|
|
4121
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4125
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4122
4126
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsxRuntime.jsx("input", { type: "hidden", name: colLabel, value: selectedDate ?? '', readOnly: true, "aria-hidden": true }), jsxRuntime.jsx(DatePickerInput, { value: selectedDate, onChange: (d) => {
|
|
4123
4127
|
setValue(colLabel, d, {
|
|
4124
4128
|
shouldValidate: true,
|
|
@@ -4215,7 +4219,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4215
4219
|
console.error(e);
|
|
4216
4220
|
}
|
|
4217
4221
|
}, [selectedDateRange, dateFormat, colLabel, setValue, timezone]);
|
|
4218
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4222
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4219
4223
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
4220
4224
|
setOpen(true);
|
|
4221
4225
|
}, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), getDisplayText()] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(RangeDatePicker, { selected: selectedDates, timezone: timezone, onDateSelected: ({ selected }) => {
|
|
@@ -4346,7 +4350,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4346
4350
|
}
|
|
4347
4351
|
};
|
|
4348
4352
|
if (variant === 'radio') {
|
|
4349
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4353
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4350
4354
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsx(react.RadioGroup.Root, { value: !isMultiple ? watchEnum : undefined, onValueChange: (details) => {
|
|
4351
4355
|
if (!isMultiple) {
|
|
4352
4356
|
setValue(colLabel, details.value);
|
|
@@ -4355,7 +4359,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4355
4359
|
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: renderEnumValue(item) })] }, `${colLabel}-${item}`));
|
|
4356
4360
|
}) }) }) }));
|
|
4357
4361
|
}
|
|
4358
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4362
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4359
4363
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((enumValue) => {
|
|
4360
4364
|
if (!enumValue) {
|
|
4361
4365
|
return null;
|
|
@@ -4967,7 +4971,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4967
4971
|
const getImageUrl = (file) => {
|
|
4968
4972
|
return URL.createObjectURL(file);
|
|
4969
4973
|
};
|
|
4970
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4974
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4971
4975
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
|
|
4972
4976
|
// file-picker variant: Store File objects directly (no ID conversion)
|
|
4973
4977
|
if (isSingleSelect) {
|
|
@@ -5066,7 +5070,7 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5066
5070
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5067
5071
|
}, [currentFileIds.join(',')]);
|
|
5068
5072
|
if (!onFetchFiles) {
|
|
5069
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5073
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5070
5074
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: "Media library browser requires onFetchFiles" }) }));
|
|
5071
5075
|
}
|
|
5072
5076
|
const handleImageError = (fileIdentifier) => {
|
|
@@ -5092,7 +5096,7 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5092
5096
|
setValue(colLabel, newFileIds);
|
|
5093
5097
|
}
|
|
5094
5098
|
};
|
|
5095
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5099
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5096
5100
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ?? 'Browse from Library' }) }), jsxRuntime.jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ?? formI18n.label() ?? 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, colLabel: colLabel }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
|
|
5097
5101
|
const file = fileMap.get(fileId);
|
|
5098
5102
|
const isImage = file
|
|
@@ -5505,7 +5509,7 @@ const IdPickerSingle = ({ column, schema, prefix, }) => {
|
|
|
5505
5509
|
? renderDisplayFunction(selectedItem)
|
|
5506
5510
|
: null;
|
|
5507
5511
|
const fieldError = getNestedError(errors, colLabel);
|
|
5508
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5512
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5509
5513
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsxs(react.Combobox.RootProvider, { value: combobox, width: "100%", children: [jsxRuntime.jsx(react.Show, { when: selectedId && selectedRendered, children: jsxRuntime.jsxs(react.HStack, { justifyContent: 'space-between', children: [jsxRuntime.jsx(react.Box, { children: selectedRendered }), currentValue.length > 0 && (jsxRuntime.jsx(react.Button, { variant: "ghost", size: "sm", onClick: () => {
|
|
5510
5514
|
setValue(colLabel, '');
|
|
5511
5515
|
}, children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(bi.BiX, {}) }) }))] }) }), jsxRuntime.jsx(react.Show, { when: !selectedId || !selectedRendered, children: jsxRuntime.jsxs(react.Combobox.Control, { position: "relative", children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? '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, {}) })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }) }), insideDialog ? (jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
|
|
@@ -5540,7 +5544,7 @@ const IdPickerMultiple = ({ column, schema, prefix, }) => {
|
|
|
5540
5544
|
// Use renderDisplay from hook (which comes from schema) or fallback to default
|
|
5541
5545
|
const renderDisplayFunction = renderDisplayFn || defaultRenderDisplay;
|
|
5542
5546
|
const fieldError = getNestedError(errors, colLabel);
|
|
5543
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5547
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5544
5548
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5545
5549
|
const item = idMap[id];
|
|
5546
5550
|
// Show loading skeleton while fetching initial values
|
|
@@ -5586,7 +5590,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
|
|
|
5586
5590
|
const stringValue = value !== undefined && value !== null && value !== ''
|
|
5587
5591
|
? String(value)
|
|
5588
5592
|
: undefined;
|
|
5589
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsxs(react.NumberInput.Root, { value: stringValue, onValueChange: (details) => {
|
|
5593
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn, gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsxs(react.NumberInput.Root, { value: stringValue, onValueChange: (details) => {
|
|
5590
5594
|
// Store as string or number based on configuration, default to number
|
|
5591
5595
|
// Handle empty values properly - if value is empty string, store undefined
|
|
5592
5596
|
if (details.value === '' || details.value === undefined) {
|
|
@@ -5631,7 +5635,7 @@ const RecordInput = ({ column, schema, prefix }) => {
|
|
|
5631
5635
|
const [newValue, setNewValue] = React.useState();
|
|
5632
5636
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5633
5637
|
const fieldError = errors[column]?.message;
|
|
5634
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [entries.map(([key, value]) => {
|
|
5638
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [entries.map(([key, value]) => {
|
|
5635
5639
|
return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
|
|
5636
5640
|
const filtered = entries.filter(([target]) => {
|
|
5637
5641
|
return target !== key;
|
|
@@ -5681,7 +5685,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
|
|
|
5681
5685
|
const colLabel = `${prefix}${column}`;
|
|
5682
5686
|
const fieldError = getNestedError(errors, colLabel);
|
|
5683
5687
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5684
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5688
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5685
5689
|
};
|
|
5686
5690
|
|
|
5687
5691
|
const Textarea = React__namespace.forwardRef(function Textarea({ value, onChange, ...props }, ref) {
|
|
@@ -5701,7 +5705,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
|
|
|
5701
5705
|
const fieldError = getNestedError(errors, colLabel);
|
|
5702
5706
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5703
5707
|
const watchValue = watch(colLabel);
|
|
5704
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5708
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5705
5709
|
};
|
|
5706
5710
|
|
|
5707
5711
|
dayjs.extend(utc);
|
|
@@ -5849,7 +5853,7 @@ const TimePicker = ({ column, schema, prefix }) => {
|
|
|
5849
5853
|
const timeString = getTimeString(newHour, newMinute, newMeridiem);
|
|
5850
5854
|
setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
|
|
5851
5855
|
};
|
|
5852
|
-
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5856
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5853
5857
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
5854
5858
|
setOpen(true);
|
|
5855
5859
|
}, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), value ? displayedTime : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsxRuntime.jsx(react.Popover.Body, { overflow: "visible", children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: startTime, selectedDate: selectedDate, timezone: timezone, portalled: false, labels: timePickerLabels }) }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { format: "12h", hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: startTime, selectedDate: selectedDate, timezone: timezone, portalled: false, labels: timePickerLabels }) }) }) }) }))] }) }));
|
|
@@ -5972,7 +5976,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
|
5972
5976
|
}
|
|
5973
5977
|
}, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels, portalled: !insideDialog, showQuickActions: dateTimePicker?.showQuickActions ?? false, quickActionLabels: dateTimePickerLabels?.quickActionLabels ??
|
|
5974
5978
|
dateTimePicker?.quickActionLabels, showTimezoneSelector: dateTimePicker?.showTimezoneSelector ?? false }));
|
|
5975
|
-
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5979
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5976
5980
|
gridRow, errorText: jsxRuntime.jsx(jsxRuntime.Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsxRuntime.jsx("input", { type: "hidden", name: colLabel, value: selectedDate ?? '', readOnly: true, "aria-hidden": true }), dateTimePickerContent] }));
|
|
5977
5981
|
};
|
|
5978
5982
|
|
package/dist/index.mjs
CHANGED
|
@@ -3897,6 +3897,10 @@ const useFormLabel = (column, prefix = '', schema) => {
|
|
|
3897
3897
|
// Return column name as fallback
|
|
3898
3898
|
return column;
|
|
3899
3899
|
},
|
|
3900
|
+
/**
|
|
3901
|
+
* Helper text from JSON Schema `description` (shown below the control).
|
|
3902
|
+
*/
|
|
3903
|
+
helperText: schema.description,
|
|
3900
3904
|
};
|
|
3901
3905
|
};
|
|
3902
3906
|
|
|
@@ -3977,7 +3981,7 @@ const BooleanPicker = ({ schema, column, prefix }) => {
|
|
|
3977
3981
|
const value = watch(colLabel);
|
|
3978
3982
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
3979
3983
|
const fieldError = getNestedError(errors, colLabel);
|
|
3980
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
3984
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
3981
3985
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
3982
3986
|
setValue(colLabel, !value);
|
|
3983
3987
|
} }) }));
|
|
@@ -4098,7 +4102,7 @@ const DatePicker = ({ column, schema, prefix }) => {
|
|
|
4098
4102
|
console.error(e);
|
|
4099
4103
|
}
|
|
4100
4104
|
}, [selectedDate, dateFormat, colLabel, setValue, timezone]);
|
|
4101
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4105
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4102
4106
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsx("input", { type: "hidden", name: colLabel, value: selectedDate ?? '', readOnly: true, "aria-hidden": true }), jsx(DatePickerInput, { value: selectedDate, onChange: (d) => {
|
|
4103
4107
|
setValue(colLabel, d, {
|
|
4104
4108
|
shouldValidate: true,
|
|
@@ -4195,7 +4199,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4195
4199
|
console.error(e);
|
|
4196
4200
|
}
|
|
4197
4201
|
}, [selectedDateRange, dateFormat, colLabel, setValue, timezone]);
|
|
4198
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4202
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4199
4203
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
4200
4204
|
setOpen(true);
|
|
4201
4205
|
}, justifyContent: 'start', children: [jsx(MdDateRange, {}), getDisplayText()] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsx(Popover.Body, { children: jsx(RangeDatePicker, { selected: selectedDates, timezone: timezone, onDateSelected: ({ selected }) => {
|
|
@@ -4326,7 +4330,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4326
4330
|
}
|
|
4327
4331
|
};
|
|
4328
4332
|
if (variant === 'radio') {
|
|
4329
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4333
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4330
4334
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsx(RadioGroup$1.Root, { value: !isMultiple ? watchEnum : undefined, onValueChange: (details) => {
|
|
4331
4335
|
if (!isMultiple) {
|
|
4332
4336
|
setValue(colLabel, details.value);
|
|
@@ -4335,7 +4339,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4335
4339
|
return (jsxs(RadioGroup$1.Item, { value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: renderEnumValue(item) })] }, `${colLabel}-${item}`));
|
|
4336
4340
|
}) }) }) }));
|
|
4337
4341
|
}
|
|
4338
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4342
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4339
4343
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [isMultiple && currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((enumValue) => {
|
|
4340
4344
|
if (!enumValue) {
|
|
4341
4345
|
return null;
|
|
@@ -4947,7 +4951,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4947
4951
|
const getImageUrl = (file) => {
|
|
4948
4952
|
return URL.createObjectURL(file);
|
|
4949
4953
|
};
|
|
4950
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4954
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4951
4955
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsx(VStack, { align: "stretch", gap: 2, children: jsx(FileDropzone, { onDrop: ({ files }) => {
|
|
4952
4956
|
// file-picker variant: Store File objects directly (no ID conversion)
|
|
4953
4957
|
if (isSingleSelect) {
|
|
@@ -5046,7 +5050,7 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5046
5050
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5047
5051
|
}, [currentFileIds.join(',')]);
|
|
5048
5052
|
if (!onFetchFiles) {
|
|
5049
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5053
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5050
5054
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsx(Text, { color: "fg.muted", children: "Media library browser requires onFetchFiles" }) }));
|
|
5051
5055
|
}
|
|
5052
5056
|
const handleImageError = (fileIdentifier) => {
|
|
@@ -5072,7 +5076,7 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
5072
5076
|
setValue(colLabel, newFileIds);
|
|
5073
5077
|
}
|
|
5074
5078
|
};
|
|
5075
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5079
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5076
5080
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsx(VStack, { align: "stretch", gap: 2, children: jsx(Button$1, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ?? 'Browse from Library' }) }), jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ?? formI18n.label() ?? 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, colLabel: colLabel }), jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
|
|
5077
5081
|
const file = fileMap.get(fileId);
|
|
5078
5082
|
const isImage = file
|
|
@@ -5485,7 +5489,7 @@ const IdPickerSingle = ({ column, schema, prefix, }) => {
|
|
|
5485
5489
|
? renderDisplayFunction(selectedItem)
|
|
5486
5490
|
: null;
|
|
5487
5491
|
const fieldError = getNestedError(errors, colLabel);
|
|
5488
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5492
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5489
5493
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxs(Combobox.RootProvider, { value: combobox, width: "100%", children: [jsx(Show, { when: selectedId && selectedRendered, children: jsxs(HStack, { justifyContent: 'space-between', children: [jsx(Box, { children: selectedRendered }), currentValue.length > 0 && (jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => {
|
|
5490
5494
|
setValue(colLabel, '');
|
|
5491
5495
|
}, children: jsx(Icon, { children: jsx(BiX, {}) }) }))] }) }), jsx(Show, { when: !selectedId || !selectedRendered, children: jsxs(Combobox.Control, { position: "relative", children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), jsx(Combobox.Trigger, {})] })] }) }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
|
|
@@ -5520,7 +5524,7 @@ const IdPickerMultiple = ({ column, schema, prefix, }) => {
|
|
|
5520
5524
|
// Use renderDisplay from hook (which comes from schema) or fallback to default
|
|
5521
5525
|
const renderDisplayFunction = renderDisplayFn || defaultRenderDisplay;
|
|
5522
5526
|
const fieldError = getNestedError(errors, colLabel);
|
|
5523
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5527
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5524
5528
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5525
5529
|
const item = idMap[id];
|
|
5526
5530
|
// Show loading skeleton while fetching initial values
|
|
@@ -5566,7 +5570,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
|
|
|
5566
5570
|
const stringValue = value !== undefined && value !== null && value !== ''
|
|
5567
5571
|
? String(value)
|
|
5568
5572
|
: undefined;
|
|
5569
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxs(NumberInput.Root, { value: stringValue, onValueChange: (details) => {
|
|
5573
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn, gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxs(NumberInput.Root, { value: stringValue, onValueChange: (details) => {
|
|
5570
5574
|
// Store as string or number based on configuration, default to number
|
|
5571
5575
|
// Handle empty values properly - if value is empty string, store undefined
|
|
5572
5576
|
if (details.value === '' || details.value === undefined) {
|
|
@@ -5611,7 +5615,7 @@ const RecordInput = ({ column, schema, prefix }) => {
|
|
|
5611
5615
|
const [newValue, setNewValue] = useState();
|
|
5612
5616
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5613
5617
|
const fieldError = errors[column]?.message;
|
|
5614
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [entries.map(([key, value]) => {
|
|
5618
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [entries.map(([key, value]) => {
|
|
5615
5619
|
return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
|
|
5616
5620
|
const filtered = entries.filter(([target]) => {
|
|
5617
5621
|
return target !== key;
|
|
@@ -5661,7 +5665,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
|
|
|
5661
5665
|
const colLabel = `${prefix}${column}`;
|
|
5662
5666
|
const fieldError = getNestedError(errors, colLabel);
|
|
5663
5667
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5664
|
-
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5668
|
+
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5665
5669
|
};
|
|
5666
5670
|
|
|
5667
5671
|
const Textarea = React.forwardRef(function Textarea({ value, onChange, ...props }, ref) {
|
|
@@ -5681,7 +5685,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
|
|
|
5681
5685
|
const fieldError = getNestedError(errors, colLabel);
|
|
5682
5686
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
5683
5687
|
const watchValue = watch(colLabel);
|
|
5684
|
-
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError, invalid: !!fieldError, children: jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5688
|
+
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError, invalid: !!fieldError, children: jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5685
5689
|
};
|
|
5686
5690
|
|
|
5687
5691
|
dayjs.extend(utc);
|
|
@@ -5829,7 +5833,7 @@ const TimePicker = ({ column, schema, prefix }) => {
|
|
|
5829
5833
|
const timeString = getTimeString(newHour, newMinute, newMeridiem);
|
|
5830
5834
|
setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
|
|
5831
5835
|
};
|
|
5832
|
-
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5836
|
+
return (jsx(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5833
5837
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
5834
5838
|
setOpen(true);
|
|
5835
5839
|
}, justifyContent: 'start', children: [jsx(IoMdClock, {}), value ? displayedTime : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: startTime, selectedDate: selectedDate, timezone: timezone, portalled: false, labels: timePickerLabels }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { format: "12h", hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: startTime, selectedDate: selectedDate, timezone: timezone, portalled: false, labels: timePickerLabels }) }) }) }) }))] }) }));
|
|
@@ -5952,7 +5956,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
|
5952
5956
|
}
|
|
5953
5957
|
}, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels, portalled: !insideDialog, showQuickActions: dateTimePicker?.showQuickActions ?? false, quickActionLabels: dateTimePickerLabels?.quickActionLabels ??
|
|
5954
5958
|
dateTimePicker?.quickActionLabels, showTimezoneSelector: dateTimePicker?.showTimezoneSelector ?? false }));
|
|
5955
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5959
|
+
return (jsxs(Field, { label: formI18n.label(), helperText: formI18n.helperText, required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5956
5960
|
gridRow, errorText: jsx(Fragment, { children: fieldError }), invalid: !!fieldError, children: [jsx("input", { type: "hidden", name: colLabel, value: selectedDate ?? '', readOnly: true, "aria-hidden": true }), dateTimePickerContent] }));
|
|
5957
5961
|
};
|
|
5958
5962
|
|
|
@@ -9,4 +9,8 @@ export declare const useFormLabel: (column: string, prefix: string | undefined,
|
|
|
9
9
|
* Logs a debug message if title is missing.
|
|
10
10
|
*/
|
|
11
11
|
label: () => string;
|
|
12
|
+
/**
|
|
13
|
+
* Helper text from JSON Schema `description` (shown below the control).
|
|
14
|
+
*/
|
|
15
|
+
helperText: string | undefined;
|
|
12
16
|
};
|