@bsol-oss/react-datatable5 13.0.1-beta.6 → 13.0.1-beta.8

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 CHANGED
@@ -4393,39 +4393,31 @@ const FormRoot = ({ schema, idMap, setIdMap, form, translate, children, order =
4393
4393
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
4394
4394
  };
4395
4395
 
4396
- function removeIndex(str) {
4397
- return str.replace(/\.\d+\./g, ".");
4398
- }
4399
-
4400
4396
  /**
4401
- * Custom hook for form field labels and fallback text.
4402
- * Automatically handles colLabel construction and removeIndex logic.
4403
- * Uses schema.title when available, otherwise falls back to translate function.
4397
+ * Custom hook for form field labels.
4398
+ * Automatically handles colLabel construction.
4399
+ * Uses schema.title for labels and schema.errorMessages for error messages.
4404
4400
  *
4405
4401
  * @param column - The column name
4406
4402
  * @param prefix - The prefix for the field (usually empty string or parent path)
4407
- * @param schema - Required schema object with title property
4403
+ * @param schema - Required schema object with title and errorMessages properties
4408
4404
  * @returns Object with label helper functions
4409
4405
  *
4410
4406
  * @example
4411
4407
  * ```tsx
4412
4408
  * const formI18n = useFormI18n(column, prefix, schema);
4413
4409
  *
4414
- * // Get field label (prefers schema.title)
4410
+ * // Get field label (from schema.title)
4415
4411
  * <Field label={formI18n.label()} />
4416
4412
  *
4417
- * // Get required error message
4413
+ * // Get required error message (from schema.errorMessages?.required)
4418
4414
  * <Text>{formI18n.required()}</Text>
4419
4415
  *
4420
- * // Get custom text
4421
- * <Text>{formI18n.t('add_more')}</Text>
4422
- *
4423
4416
  * // Access the raw colLabel
4424
4417
  * const colLabel = formI18n.colLabel;
4425
4418
  * ```
4426
4419
  */
4427
4420
  const useFormI18n = (column, prefix = '', schema) => {
4428
- const { translate } = useSchemaContext();
4429
4421
  const colLabel = `${prefix}${column}`;
4430
4422
  return {
4431
4423
  /**
@@ -4433,10 +4425,10 @@ const useFormI18n = (column, prefix = '', schema) => {
4433
4425
  */
4434
4426
  colLabel,
4435
4427
  /**
4436
- * Get the field label from schema title prop, or fall back to translate function
4437
- * Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
4428
+ * Get the field label from schema title property.
4429
+ * Logs a debug message if title is missing.
4438
4430
  */
4439
- label: (options) => {
4431
+ label: () => {
4440
4432
  if (schema.title) {
4441
4433
  return schema.title;
4442
4434
  }
@@ -4452,29 +4444,36 @@ const useFormI18n = (column, prefix = '', schema) => {
4452
4444
  : undefined,
4453
4445
  },
4454
4446
  });
4455
- return translate.t(removeIndex(`${colLabel}.field_label`), options);
4447
+ // Return column name as fallback
4448
+ return column;
4456
4449
  },
4457
4450
  /**
4458
- * Get the required error message
4459
- * Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
4451
+ * Get the required error message from schema.errorMessages?.required.
4452
+ * Returns a helpful fallback message if not provided.
4460
4453
  */
4461
- required: (options) => {
4462
- return translate.t(removeIndex(`${colLabel}.field_required`), options);
4463
- },
4464
- /**
4465
- * Get text for any custom key relative to the field
4466
- * Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
4467
- *
4468
- * @param key - The key suffix (e.g., 'add_more', 'total', etc.)
4469
- * @param options - Optional options (e.g., defaultValue, interpolation variables)
4470
- */
4471
- t: (key, options) => {
4472
- return translate.t(removeIndex(`${colLabel}.${key}`), options);
4454
+ required: () => {
4455
+ const errorMessage = schema.errorMessages?.required;
4456
+ if (errorMessage) {
4457
+ return errorMessage;
4458
+ }
4459
+ // Debug log when error message is missing
4460
+ console.debug(`[Form Field Required] Missing error message for required field '${colLabel}'. Add errorMessages.required to schema for field '${colLabel}'.`, {
4461
+ fieldName: column,
4462
+ colLabel,
4463
+ prefix,
4464
+ schema: {
4465
+ type: schema.type,
4466
+ title: schema.title,
4467
+ required: schema.required,
4468
+ hasErrorMessages: !!schema.errorMessages,
4469
+ errorMessageKeys: schema.errorMessages
4470
+ ? Object.keys(schema.errorMessages)
4471
+ : undefined,
4472
+ },
4473
+ });
4474
+ // Return helpful fallback message
4475
+ return `Missing error message for required. Add errorMessages.required to schema for field '${colLabel}'`;
4473
4476
  },
4474
- /**
4475
- * Access to the original translate object for edge cases
4476
- */
4477
- translate,
4478
4477
  };
4479
4478
  };
4480
4479
 
@@ -5090,27 +5089,82 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
5090
5089
  const watchEnum = watch(colLabel);
5091
5090
  const watchEnums = (watch(colLabel) ?? []);
5092
5091
  const dataList = schema.enum ?? [];
5092
+ // Helper function to render enum value (returns ReactNode)
5093
+ // If renderDisplay is provided, use it; otherwise show the enum string value directly
5094
+ const renderEnumValue = (value) => {
5095
+ if (renderDisplay) {
5096
+ return renderDisplay(value);
5097
+ }
5098
+ // If no renderDisplay provided, show the enum string value directly
5099
+ return value;
5100
+ };
5101
+ // Helper function to get string representation for input display
5102
+ // Converts ReactNode to string for combobox input display
5103
+ const getDisplayString = (value) => {
5104
+ if (renderDisplay) {
5105
+ const rendered = renderDisplay(value);
5106
+ // If renderDisplay returns a string, use it directly
5107
+ if (typeof rendered === 'string') {
5108
+ return rendered;
5109
+ }
5110
+ // If it's a React element, try to extract text content
5111
+ // For now, fallback to the raw value if we can't extract text
5112
+ // In most cases, renderDisplay should return a string or simple element
5113
+ if (typeof rendered === 'object' &&
5114
+ rendered !== null &&
5115
+ 'props' in rendered) {
5116
+ const props = rendered.props;
5117
+ // Try to extract text from React element props
5118
+ if (props?.children) {
5119
+ const children = props.children;
5120
+ if (typeof children === 'string') {
5121
+ return children;
5122
+ }
5123
+ }
5124
+ }
5125
+ // Fallback: use raw value if we can't extract string
5126
+ return value;
5127
+ }
5128
+ return value;
5129
+ };
5130
+ // Debug log when renderDisplay is missing
5131
+ if (!renderDisplay) {
5132
+ console.debug(`[EnumPicker] Missing renderDisplay for field '${colLabel}'. Add renderDisplay function to schema for field '${colLabel}' to provide custom UI rendering. Currently showing enum string values directly.`, {
5133
+ fieldName: column,
5134
+ colLabel,
5135
+ prefix,
5136
+ enumValues: dataList,
5137
+ });
5138
+ }
5093
5139
  // Current value for combobox (array format)
5094
5140
  const currentValue = isMultiple
5095
5141
  ? watchEnums.filter((val) => val != null && val !== '')
5096
5142
  : watchEnum
5097
5143
  ? [watchEnum]
5098
5144
  : [];
5099
- // Transform enum data for combobox collection
5145
+ // Track input focus state for single selection
5146
+ const [isInputFocused, setIsInputFocused] = React.useState(false);
5147
+ // Get the selected value for single selection display
5148
+ const selectedSingleValue = !isMultiple && watchEnum ? watchEnum : null;
5149
+ const selectedSingleRendered = selectedSingleValue
5150
+ ? renderEnumValue(selectedSingleValue)
5151
+ : null;
5152
+ const isSelectedSingleValueString = typeof selectedSingleRendered === 'string';
5100
5153
  const comboboxItems = React.useMemo(() => {
5101
5154
  return dataList.map((item) => ({
5102
- label: !!renderDisplay === true
5103
- ? String(renderDisplay(item))
5104
- : formI18n.t(item),
5155
+ label: item, // Internal: used for search/filtering only
5105
5156
  value: item,
5157
+ raw: item, // Passed to renderEnumValue for UI rendering
5158
+ displayLabel: getDisplayString(item), // Used for input display when selected
5106
5159
  }));
5107
- }, [dataList, renderDisplay, formI18n]);
5160
+ }, [dataList, renderDisplay]);
5108
5161
  // Use filter hook for combobox
5109
5162
  const { contains } = react.useFilter({ sensitivity: 'base' });
5110
5163
  // Create collection for combobox
5164
+ // itemToString uses displayLabel to show rendered display in input when selected
5111
5165
  const { collection, filter } = react.useListCollection({
5112
5166
  initialItems: comboboxItems,
5113
- itemToString: (item) => item.label,
5167
+ itemToString: (item) => item.displayLabel, // Use displayLabel for selected value display
5114
5168
  itemToValue: (item) => item.value,
5115
5169
  filter: contains,
5116
5170
  });
@@ -5134,9 +5188,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
5134
5188
  setValue(colLabel, details.value);
5135
5189
  }
5136
5190
  }, children: jsxRuntime.jsx(react.HStack, { gap: "6", children: dataList.map((item) => {
5137
- 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
5138
- ? renderDisplay(item)
5139
- : formI18n.t(item) })] }, `${colLabel}-${item}`));
5191
+ 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}`));
5140
5192
  }) }) }) }));
5141
5193
  }
5142
5194
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
@@ -5147,16 +5199,31 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
5147
5199
  return (jsxRuntime.jsx(Tag, { size: "lg", closable: true, onClick: () => {
5148
5200
  const newValue = currentValue.filter((val) => val !== enumValue);
5149
5201
  setValue(colLabel, newValue);
5150
- }, children: !!renderDisplay === true
5151
- ? renderDisplay(enumValue)
5152
- : formI18n.t(enumValue) }, enumValue));
5202
+ }, children: renderEnumValue(enumValue) }, enumValue));
5153
5203
  }) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5154
5204
  ? { strategy: 'fixed', hideWhenDetached: true }
5155
- : undefined, 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: () => {
5205
+ : undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { position: "relative", children: [!isMultiple &&
5206
+ selectedSingleValue &&
5207
+ !isInputFocused &&
5208
+ !isSelectedSingleValueString &&
5209
+ selectedSingleRendered && (jsxRuntime.jsx(react.Box, { position: "absolute", left: 3, top: "50%", transform: "translateY(-50%)", pointerEvents: "none", zIndex: 1, maxWidth: "calc(100% - 60px)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: selectedSingleRendered })), jsxRuntime.jsx(react.Combobox.Input, { placeholder: !isMultiple && selectedSingleValue && !isInputFocused
5210
+ ? undefined
5211
+ : enumPickerLabels?.typeToSearch ?? 'Type to search', onFocus: () => setIsInputFocused(true), onBlur: () => setIsInputFocused(false), style: {
5212
+ color: !isMultiple &&
5213
+ selectedSingleValue &&
5214
+ !isInputFocused &&
5215
+ !isSelectedSingleValueString
5216
+ ? 'transparent'
5217
+ : undefined,
5218
+ caretColor: !isMultiple &&
5219
+ selectedSingleValue &&
5220
+ !isInputFocused &&
5221
+ !isSelectedSingleValueString
5222
+ ? 'transparent'
5223
+ : undefined,
5224
+ } }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [!isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
5156
5225
  setValue(colLabel, '');
5157
- } })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), insideDialog ? (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 ??
5158
- formI18n.t('empty_search_result') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) }))] }) })) : (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 ??
5159
- formI18n.t('empty_search_result') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) }))] }) }) }))] })] }));
5226
+ } })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), insideDialog ? (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 ?? 'Total'}: ${collection.items.length}` })), collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: enumPickerLabels?.emptySearchResult ?? 'No results found' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: renderEnumValue(item.raw) }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) }))] }) })) : (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 ?? 'Total'}: ${collection.items.length}` })), collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: enumPickerLabels?.emptySearchResult ?? 'No results found' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: renderEnumValue(item.raw) }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) }))] }) }) }))] })] }));
5160
5227
  };
5161
5228
 
5162
5229
  function isEnteringWindow(_ref) {
@@ -5771,7 +5838,7 @@ const FilePicker = ({ column, schema, prefix }) => {
5771
5838
  const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
5772
5839
  setValue(colLabel, [...currentFiles, ...newFiles]);
5773
5840
  }
5774
- }, placeholder: filePickerLabels?.fileDropzone ?? formI18n.t('fileDropzone') }) }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
5841
+ }, placeholder: filePickerLabels?.fileDropzone ?? 'Drop files here' }) }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
5775
5842
  const fileIdentifier = getFileIdentifier(file, index);
5776
5843
  const fileName = getFileName(file);
5777
5844
  const fileSize = getFileSize(file);
@@ -5882,9 +5949,7 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5882
5949
  }
5883
5950
  };
5884
5951
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5885
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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 ??
5886
- formI18n.t('browse_library') ??
5887
- '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) => {
5952
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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) => {
5888
5953
  const file = fileMap.get(fileId);
5889
5954
  const isImage = file
5890
5955
  ? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
@@ -5900,15 +5965,46 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5900
5965
  }) })] }));
5901
5966
  };
5902
5967
 
5903
- // Default renderDisplay function that stringifies JSON
5968
+ // Default renderDisplay function that intelligently displays items
5969
+ // If item is an object, tries to find common display fields (name, title, label, etc.)
5970
+ // Otherwise falls back to JSON.stringify
5904
5971
  const defaultRenderDisplay = (item) => {
5972
+ // Check if item is an object (not null, not array, not primitive)
5973
+ if (item !== null &&
5974
+ typeof item === 'object' &&
5975
+ !Array.isArray(item) &&
5976
+ !(item instanceof Date)) {
5977
+ const obj = item;
5978
+ // Try common display fields in order of preference
5979
+ const displayFields = [
5980
+ 'name',
5981
+ 'title',
5982
+ 'label',
5983
+ 'displayName',
5984
+ 'display_name',
5985
+ 'text',
5986
+ 'value',
5987
+ ];
5988
+ for (const field of displayFields) {
5989
+ if (obj[field] !== undefined && obj[field] !== null) {
5990
+ const value = obj[field];
5991
+ // Return the value if it's a string or number, otherwise stringify it
5992
+ if (typeof value === 'string' || typeof value === 'number') {
5993
+ return String(value);
5994
+ }
5995
+ }
5996
+ }
5997
+ // If no display field found, fall back to JSON.stringify
5998
+ return JSON.stringify(item);
5999
+ }
6000
+ // For non-objects (primitives, arrays, dates), use JSON.stringify
5905
6001
  return JSON.stringify(item);
5906
6002
  };
5907
6003
 
5908
6004
  const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5909
6005
  const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5910
6006
  const { idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5911
- const { renderDisplay, loadInitialValues, foreign_key, variant } = schema;
6007
+ const { renderDisplay, itemToValue: schemaItemToValue, loadInitialValues, foreign_key, variant, } = schema;
5912
6008
  // loadInitialValues should be provided in schema for id-picker fields
5913
6009
  // It's used to load the record of the id so the display is human-readable
5914
6010
  if (variant === 'id-picker' && !loadInitialValues) {
@@ -6041,17 +6137,51 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
6041
6137
  // Depend on idMapKey which only changes when items we care about change
6042
6138
  // eslint-disable-next-line react-hooks/exhaustive-deps
6043
6139
  }, [currentValueKey, idMapKey]);
6140
+ // Default itemToValue function: extract value from item using column_ref
6141
+ const defaultItemToValue = (item) => String(item[column_ref]);
6142
+ // Use schema's itemToValue if provided, otherwise use default
6143
+ const itemToValueFn = schemaItemToValue
6144
+ ? (item) => schemaItemToValue(item)
6145
+ : defaultItemToValue;
6146
+ // itemToString function: convert item to readable string using renderDisplay
6147
+ // This ensures items can always be displayed as readable strings in the combobox
6148
+ const renderFn = renderDisplay || defaultRenderDisplay;
6149
+ const itemToStringFn = (item) => {
6150
+ const rendered = renderFn(item);
6151
+ // If already a string or number, return it
6152
+ if (typeof rendered === 'string')
6153
+ return rendered;
6154
+ if (typeof rendered === 'number')
6155
+ return String(rendered);
6156
+ // For ReactNode, fall back to defaultRenderDisplay which converts to string
6157
+ return String(defaultRenderDisplay(item));
6158
+ };
6044
6159
  // Transform data for combobox collection
6045
6160
  // label is used for filtering/searching (must be a string)
6161
+ // displayLabel is used for input display when selected (string representation of rendered display)
6046
6162
  // raw item is stored for custom rendering
6047
6163
  // Also include items from idMap that match currentValue (for initial values display)
6048
6164
  const comboboxItems = React.useMemo(() => {
6049
6165
  const renderFn = renderDisplay || defaultRenderDisplay;
6166
+ // Helper to convert rendered display to string for displayLabel
6167
+ // For ReactNodes (non-string/number), we can't safely stringify due to circular refs
6168
+ // So we use the label (which is already a string) as fallback
6169
+ const getDisplayString = (rendered, fallbackLabel) => {
6170
+ if (typeof rendered === 'string')
6171
+ return rendered;
6172
+ if (typeof rendered === 'number')
6173
+ return String(rendered);
6174
+ // For ReactNode, use the fallback label (which is already a string representation)
6175
+ // The actual ReactNode will be rendered in the overlay, not in the input
6176
+ return fallbackLabel;
6177
+ };
6050
6178
  const itemsFromDataList = dataList.map((item) => {
6051
6179
  const rendered = renderFn(item);
6180
+ const label = typeof rendered === 'string' ? rendered : JSON.stringify(item); // Use string for filtering
6052
6181
  return {
6053
- label: typeof rendered === 'string' ? rendered : JSON.stringify(item), // Use string for filtering
6054
- value: String(item[column_ref]),
6182
+ label, // Use string for filtering
6183
+ displayLabel: getDisplayString(rendered, label), // String representation for input display
6184
+ value: itemToValueFn(item),
6055
6185
  raw: item,
6056
6186
  };
6057
6187
  });
@@ -6060,25 +6190,28 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
6060
6190
  const itemsFromIdMap = idMapItems
6061
6191
  .map((item) => {
6062
6192
  // Check if this item is already in itemsFromDataList
6063
- const alreadyIncluded = itemsFromDataList.some((i) => i.value === String(item[column_ref]));
6193
+ const alreadyIncluded = itemsFromDataList.some((i) => i.value === itemToValueFn(item));
6064
6194
  if (alreadyIncluded)
6065
6195
  return null;
6066
6196
  const rendered = renderFn(item);
6197
+ const label = typeof rendered === 'string' ? rendered : JSON.stringify(item);
6067
6198
  return {
6068
- label: typeof rendered === 'string' ? rendered : JSON.stringify(item),
6069
- value: String(item[column_ref]),
6199
+ label,
6200
+ displayLabel: getDisplayString(rendered, label), // String representation for input display
6201
+ value: itemToValueFn(item),
6070
6202
  raw: item,
6071
6203
  };
6072
6204
  })
6073
6205
  .filter((item) => item !== null);
6074
6206
  return [...itemsFromIdMap, ...itemsFromDataList];
6075
- }, [dataList, column_ref, renderDisplay, idMapItems]);
6207
+ }, [dataList, column_ref, renderDisplay, idMapItems, itemToValueFn]);
6076
6208
  // Use filter hook for combobox
6077
6209
  const { contains } = react.useFilter({ sensitivity: 'base' });
6078
6210
  // Create collection for combobox
6211
+ // itemToString uses displayLabel to show rendered display in input when selected
6079
6212
  const { collection, filter, set } = react.useListCollection({
6080
6213
  initialItems: comboboxItems,
6081
- itemToString: (item) => item.label,
6214
+ itemToString: (item) => item.displayLabel, // Use displayLabel for selected value display
6082
6215
  itemToValue: (item) => item.value,
6083
6216
  filter: contains,
6084
6217
  });
@@ -6133,6 +6266,8 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
6133
6266
  idPickerLabels,
6134
6267
  insideDialog: insideDialog ?? false,
6135
6268
  renderDisplay,
6269
+ itemToValue: itemToValueFn,
6270
+ itemToString: itemToStringFn,
6136
6271
  loadInitialValues: loadInitialValues ??
6137
6272
  (async () => ({ data: { data: [], count: 0 }, idMap: {} })), // Fallback if not provided
6138
6273
  column_ref,
@@ -6143,60 +6278,69 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
6143
6278
 
6144
6279
  const IdPickerSingle = ({ column, schema, prefix, }) => {
6145
6280
  const formI18n = useFormI18n(column, prefix, schema);
6146
- const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
6281
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
6147
6282
  const isRequired = required?.some((columnId) => columnId === column);
6148
- const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
6283
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, collection, filter, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, itemToValue, itemToString, errors, setValue, } = useIdPickerData({
6149
6284
  column,
6150
6285
  schema,
6151
6286
  prefix,
6152
6287
  isMultiple: false,
6153
6288
  });
6154
- const handleInputValueChange = (details) => {
6155
- setSearchText(details.inputValue);
6156
- };
6157
- const handleValueChange = (details) => {
6158
- setValue(colLabel, details.value[0] || '');
6159
- };
6160
- const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
6161
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6162
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { mb: 2, children: (() => {
6163
- const id = currentValue[0];
6164
- const item = idMap[id];
6165
- // Show loading skeleton while fetching initial values
6166
- if (item === undefined &&
6167
- (isLoadingInitialValues || isFetchingInitialValues) &&
6168
- missingIds.includes(id)) {
6169
- return jsxRuntime.jsx(react.Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
6170
- }
6171
- // Only show "not found" if we're not loading and item is still missing
6172
- if (item === undefined) {
6173
- return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
6174
- }
6175
- return jsxRuntime.jsx(react.Text, { fontSize: "sm", children: renderDisplayFunction(item) });
6176
- })() })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: false, closeOnSelect: true, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
6177
- ? { strategy: 'fixed', hideWhenDetached: true }
6178
- : undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { 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, {}) })), currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
6179
- setValue(colLabel, '');
6180
- } })), 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 ? (
6289
+ // Get the selected value for single selection display
6290
+ const selectedId = currentValue.length > 0 ? currentValue[0] : null;
6291
+ const selectedItem = selectedId
6292
+ ? idMap[selectedId]
6293
+ : undefined;
6294
+ // Use itemToValue to get the combobox value from the selected item, or use the ID directly
6295
+ const comboboxValue = selectedItem
6296
+ ? itemToString(selectedItem)
6297
+ : selectedId || '';
6298
+ // itemToString is available from the hook and can be used to get a readable string
6299
+ // representation of any item. The collection's itemToString is automatically used
6300
+ // by the combobox to display selected values.
6301
+ // Use useCombobox hook to control input value
6302
+ const combobox = react.useCombobox({
6303
+ collection,
6304
+ value: [comboboxValue],
6305
+ onInputValueChange(e) {
6306
+ setSearchText(e.inputValue);
6307
+ filter(e.inputValue);
6308
+ },
6309
+ onValueChange(e) {
6310
+ setValue(colLabel, e.value[0] || '');
6311
+ // Clear the input value after selection
6312
+ setSearchText('');
6313
+ },
6314
+ multiple: false,
6315
+ closeOnSelect: true,
6316
+ openOnClick: true,
6317
+ invalid: !!errors[colLabel],
6318
+ });
6319
+ // Use renderDisplay from hook (which comes from schema) or fallback to default
6320
+ const renderDisplayFunction = renderDisplayFn || defaultRenderDisplay;
6321
+ // Get the selected value for single selection display (already computed above)
6322
+ const selectedRendered = selectedItem
6323
+ ? renderDisplayFunction(selectedItem)
6324
+ : null;
6325
+ return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6326
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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: () => {
6327
+ setValue(colLabel, '');
6328
+ }, 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 ? (
6329
+ // Show skeleton items to prevent UI shift
6330
+ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
6331
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
6332
+ : idPickerLabels?.initialResults ??
6333
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [renderDisplayFunction(item.raw), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: 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 ? (
6181
6334
  // Show skeleton items to prevent UI shift
6182
6335
  jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
6183
6336
  ? idPickerLabels?.emptySearchResult ?? 'No results found'
6184
6337
  : idPickerLabels?.initialResults ??
6185
- 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6186
- ? renderDisplayFunction(item.raw)
6187
- : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: 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 ? (
6188
- // Show skeleton items to prevent UI shift
6189
- jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
6190
- ? idPickerLabels?.emptySearchResult ?? 'No results found'
6191
- : idPickerLabels?.initialResults ??
6192
- 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6193
- ? renderDisplayFunction(item.raw)
6194
- : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
6338
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsx(react.Combobox.Item, { item: item, children: renderDisplayFunction(item.raw) }, item.value ?? `item-${index}`))) })) }) }) }))] }) }));
6195
6339
  };
6196
6340
 
6197
6341
  const IdPickerMultiple = ({ column, schema, prefix, }) => {
6198
6342
  const formI18n = useFormI18n(column, prefix, schema);
6199
- const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
6343
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
6200
6344
  const isRequired = required?.some((columnId) => columnId === column);
6201
6345
  const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
6202
6346
  column,
@@ -6210,7 +6354,8 @@ const IdPickerMultiple = ({ column, schema, prefix, }) => {
6210
6354
  const handleValueChange = (details) => {
6211
6355
  setValue(colLabel, details.value);
6212
6356
  };
6213
- const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
6357
+ // Use renderDisplay from hook (which comes from schema) or fallback to default
6358
+ const renderDisplayFunction = renderDisplayFn || defaultRenderDisplay;
6214
6359
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6215
6360
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
6216
6361
  const item = idMap[id];
@@ -6235,16 +6380,12 @@ const IdPickerMultiple = ({ column, schema, prefix, }) => {
6235
6380
  jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
6236
6381
  ? idPickerLabels?.emptySearchResult ?? 'No results found'
6237
6382
  : idPickerLabels?.initialResults ??
6238
- 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6239
- ? renderDisplayFunction(item.raw)
6240
- : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: 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 ? (
6383
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [renderDisplayFunction(item.raw), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: 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 ? (
6241
6384
  // Show skeleton items to prevent UI shift
6242
6385
  jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
6243
6386
  ? idPickerLabels?.emptySearchResult ?? 'No results found'
6244
6387
  : idPickerLabels?.initialResults ??
6245
- 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6246
- ? renderDisplayFunction(item.raw)
6247
- : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
6388
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [renderDisplayFunction(item.raw), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
6248
6389
  };
6249
6390
 
6250
6391
  const NumberInputRoot = React__namespace.forwardRef(function NumberInput(props, ref) {
@@ -7381,7 +7522,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7381
7522
  backButtonLabel: 'Back',
7382
7523
  forwardButtonLabel: 'Next',
7383
7524
  }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, defaultDate, defaultTime, }) {
7384
- console.log('[DateTimePicker] Component initialized with props:', {
7525
+ console.debug('[DateTimePicker] Component initialized with props:', {
7385
7526
  value,
7386
7527
  format,
7387
7528
  showSeconds,
@@ -7400,13 +7541,13 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7400
7541
  const [selectedDate, setSelectedDate] = React.useState(getDateString(value));
7401
7542
  // Helper to get time values from value prop with timezone
7402
7543
  const getTimeFromValue = React.useCallback((val) => {
7403
- console.log('[DateTimePicker] getTimeFromValue called:', {
7544
+ console.debug('[DateTimePicker] getTimeFromValue called:', {
7404
7545
  val,
7405
7546
  timezone,
7406
7547
  showSeconds,
7407
7548
  });
7408
7549
  if (!val) {
7409
- console.log('[DateTimePicker] No value provided, returning nulls');
7550
+ console.debug('[DateTimePicker] No value provided, returning nulls');
7410
7551
  return {
7411
7552
  hour12: null,
7412
7553
  minute: null,
@@ -7416,7 +7557,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7416
7557
  };
7417
7558
  }
7418
7559
  const dateObj = dayjs(val).tz(timezone);
7419
- console.log('[DateTimePicker] Parsed date object:', {
7560
+ console.debug('[DateTimePicker] Parsed date object:', {
7420
7561
  original: val,
7421
7562
  timezone,
7422
7563
  isValid: dateObj.isValid(),
@@ -7426,7 +7567,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7426
7567
  second: dateObj.second(),
7427
7568
  });
7428
7569
  if (!dateObj.isValid()) {
7429
- console.log('[DateTimePicker] Invalid date object, returning nulls');
7570
+ console.debug('[DateTimePicker] Invalid date object, returning nulls');
7430
7571
  return {
7431
7572
  hour12: null,
7432
7573
  minute: null,
@@ -7447,11 +7588,11 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7447
7588
  hour24: hour24Value,
7448
7589
  second: secondValue,
7449
7590
  };
7450
- console.log('[DateTimePicker] Extracted time values:', result);
7591
+ console.debug('[DateTimePicker] Extracted time values:', result);
7451
7592
  return result;
7452
7593
  }, [timezone, showSeconds]);
7453
7594
  const initialTime = getTimeFromValue(value);
7454
- console.log('[DateTimePicker] Initial time from value:', {
7595
+ console.debug('[DateTimePicker] Initial time from value:', {
7455
7596
  value,
7456
7597
  initialTime,
7457
7598
  });
@@ -7528,14 +7669,14 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7528
7669
  const [second, setSecond] = React.useState(initialTimeValues.second);
7529
7670
  // Sync selectedDate and time states when value prop changes
7530
7671
  React.useEffect(() => {
7531
- console.log('[DateTimePicker] useEffect triggered - value changed:', {
7672
+ console.debug('[DateTimePicker] useEffect triggered - value changed:', {
7532
7673
  value,
7533
7674
  timezone,
7534
7675
  format,
7535
7676
  });
7536
7677
  // If value is null, undefined, or invalid, clear date but keep default time values
7537
7678
  if (!value || value === null || value === undefined) {
7538
- console.log('[DateTimePicker] Value is null/undefined, clearing date but keeping default time');
7679
+ console.debug('[DateTimePicker] Value is null/undefined, clearing date but keeping default time');
7539
7680
  setSelectedDate('');
7540
7681
  // Keep default time values instead of clearing them
7541
7682
  if (format === 'iso-date-time') {
@@ -7557,7 +7698,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7557
7698
  // Check if value is valid
7558
7699
  const dateObj = dayjs(value).tz(timezone);
7559
7700
  if (!dateObj.isValid()) {
7560
- console.log('[DateTimePicker] Invalid value, clearing date but keeping default time');
7701
+ console.debug('[DateTimePicker] Invalid value, clearing date but keeping default time');
7561
7702
  setSelectedDate('');
7562
7703
  // Keep default time values instead of clearing them
7563
7704
  if (format === 'iso-date-time') {
@@ -7577,10 +7718,10 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7577
7718
  return;
7578
7719
  }
7579
7720
  const dateString = getDateString(value);
7580
- console.log('[DateTimePicker] Setting selectedDate:', dateString);
7721
+ console.debug('[DateTimePicker] Setting selectedDate:', dateString);
7581
7722
  setSelectedDate(dateString);
7582
7723
  const timeData = getTimeFromValue(value);
7583
- console.log('[DateTimePicker] Updating time states:', {
7724
+ console.debug('[DateTimePicker] Updating time states:', {
7584
7725
  timeData,
7585
7726
  });
7586
7727
  setHour12(timeData.hour12);
@@ -7590,7 +7731,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7590
7731
  setSecond(timeData.second);
7591
7732
  }, [value, getTimeFromValue, getDateString, timezone]);
7592
7733
  const handleDateChange = (date) => {
7593
- console.log('[DateTimePicker] handleDateChange called:', {
7734
+ console.debug('[DateTimePicker] handleDateChange called:', {
7594
7735
  date,
7595
7736
  timezone,
7596
7737
  showSeconds,
@@ -7598,7 +7739,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7598
7739
  });
7599
7740
  // If date is empty or invalid, clear all fields
7600
7741
  if (!date || date === '') {
7601
- console.log('[DateTimePicker] Empty date, clearing all fields');
7742
+ console.debug('[DateTimePicker] Empty date, clearing all fields');
7602
7743
  setSelectedDate('');
7603
7744
  setHour12(null);
7604
7745
  setMinute(null);
@@ -7611,7 +7752,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7611
7752
  setSelectedDate(date);
7612
7753
  // Parse the date string (YYYY-MM-DD) in the specified timezone
7613
7754
  const dateObj = dayjs.tz(date, timezone);
7614
- console.log('[DateTimePicker] Parsed date object:', {
7755
+ console.debug('[DateTimePicker] Parsed date object:', {
7615
7756
  date,
7616
7757
  timezone,
7617
7758
  isValid: dateObj.isValid(),
@@ -7637,7 +7778,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7637
7778
  if (!hasTimeValues) {
7638
7779
  // Use defaultTime if provided, otherwise default to 00:00
7639
7780
  if (defaultTime) {
7640
- console.log('[DateTimePicker] No time values set, using defaultTime');
7781
+ console.debug('[DateTimePicker] No time values set, using defaultTime');
7641
7782
  if (format === 'iso-date-time') {
7642
7783
  const defaultTime24 = defaultTime;
7643
7784
  setHour24(defaultTime24.hour ?? 0);
@@ -7664,7 +7805,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7664
7805
  }
7665
7806
  }
7666
7807
  else {
7667
- console.log('[DateTimePicker] No time values set, defaulting to 00:00');
7808
+ console.debug('[DateTimePicker] No time values set, defaulting to 00:00');
7668
7809
  if (format === 'iso-date-time') {
7669
7810
  setHour24(0);
7670
7811
  setMinute(0);
@@ -7692,17 +7833,17 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7692
7833
  // When showSeconds is false, ignore seconds from the date
7693
7834
  if (!showSeconds) {
7694
7835
  const dateWithoutSeconds = dateObj.second(0).millisecond(0).toISOString();
7695
- console.log('[DateTimePicker] Updating date without seconds:', dateWithoutSeconds);
7836
+ console.debug('[DateTimePicker] Updating date without seconds:', dateWithoutSeconds);
7696
7837
  updateDateTime(dateWithoutSeconds, timeDataToUse);
7697
7838
  }
7698
7839
  else {
7699
7840
  const dateWithSeconds = dateObj.toISOString();
7700
- console.log('[DateTimePicker] Updating date with seconds:', dateWithSeconds);
7841
+ console.debug('[DateTimePicker] Updating date with seconds:', dateWithSeconds);
7701
7842
  updateDateTime(dateWithSeconds, timeDataToUse);
7702
7843
  }
7703
7844
  };
7704
7845
  const handleTimeChange = (timeData) => {
7705
- console.log('[DateTimePicker] handleTimeChange called:', {
7846
+ console.debug('[DateTimePicker] handleTimeChange called:', {
7706
7847
  timeData,
7707
7848
  format,
7708
7849
  selectedDate,
@@ -7710,7 +7851,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7710
7851
  });
7711
7852
  if (format === 'iso-date-time') {
7712
7853
  const data = timeData;
7713
- console.log('[DateTimePicker] ISO format - setting 24-hour time:', data);
7854
+ console.debug('[DateTimePicker] ISO format - setting 24-hour time:', data);
7714
7855
  setHour24(data.hour);
7715
7856
  setMinute(data.minute);
7716
7857
  if (showSeconds) {
@@ -7723,7 +7864,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7723
7864
  }
7724
7865
  else {
7725
7866
  const data = timeData;
7726
- console.log('[DateTimePicker] 12-hour format - setting time:', data);
7867
+ console.debug('[DateTimePicker] 12-hour format - setting time:', data);
7727
7868
  setHour12(data.hour);
7728
7869
  setMinute(data.minute);
7729
7870
  setMeridiem(data.meridiem);
@@ -7732,7 +7873,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7732
7873
  if (!selectedDate || !dayjs(selectedDate).isValid()) {
7733
7874
  // If effectiveDefaultDate is available, use it instead of clearing
7734
7875
  if (effectiveDefaultDate && dayjs(effectiveDefaultDate).isValid()) {
7735
- console.log('[DateTimePicker] No valid selectedDate, using effectiveDefaultDate:', effectiveDefaultDate);
7876
+ console.debug('[DateTimePicker] No valid selectedDate, using effectiveDefaultDate:', effectiveDefaultDate);
7736
7877
  setSelectedDate(effectiveDefaultDate);
7737
7878
  const dateObj = dayjs(effectiveDefaultDate).tz(timezone);
7738
7879
  if (dateObj.isValid()) {
@@ -7751,7 +7892,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7751
7892
  return;
7752
7893
  }
7753
7894
  else {
7754
- console.log('[DateTimePicker] No valid selectedDate and no effectiveDefaultDate, keeping time values but no date');
7895
+ console.debug('[DateTimePicker] No valid selectedDate and no effectiveDefaultDate, keeping time values but no date');
7755
7896
  // Keep the time values that were just set, but don't set a date
7756
7897
  // This should rarely happen as effectiveDefaultDate always defaults to today
7757
7898
  setSelectedDate('');
@@ -7775,14 +7916,14 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7775
7916
  }
7776
7917
  };
7777
7918
  const updateDateTime = (date, timeData) => {
7778
- console.log('[DateTimePicker] updateDateTime called:', {
7919
+ console.debug('[DateTimePicker] updateDateTime called:', {
7779
7920
  date,
7780
7921
  timeData,
7781
7922
  format,
7782
7923
  currentStates: { hour12, minute, meridiem, hour24, second },
7783
7924
  });
7784
7925
  if (!date || date === null || date === undefined) {
7785
- console.log('[DateTimePicker] No date provided, clearing all fields and calling onChange(undefined)');
7926
+ console.debug('[DateTimePicker] No date provided, clearing all fields and calling onChange(undefined)');
7786
7927
  setSelectedDate('');
7787
7928
  setHour12(null);
7788
7929
  setMinute(null);
@@ -7820,11 +7961,11 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7820
7961
  : 0;
7821
7962
  // If all time values are null, clear the value
7822
7963
  if (h === null && m === null && (showSeconds ? s === null : true)) {
7823
- console.log('[DateTimePicker] All time values are null, clearing value');
7964
+ console.debug('[DateTimePicker] All time values are null, clearing value');
7824
7965
  onChange?.(undefined);
7825
7966
  return;
7826
7967
  }
7827
- console.log('[DateTimePicker] ISO format - setting time on date:', {
7968
+ console.debug('[DateTimePicker] ISO format - setting time on date:', {
7828
7969
  h,
7829
7970
  m,
7830
7971
  s,
@@ -7838,7 +7979,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7838
7979
  }
7839
7980
  else {
7840
7981
  const data = timeData;
7841
- console.log('[DateTimePicker] Processing 12-hour format:', {
7982
+ console.debug('[DateTimePicker] Processing 12-hour format:', {
7842
7983
  'data !== undefined': data !== undefined,
7843
7984
  'data?.hour': data?.hour,
7844
7985
  'data?.minute': data?.minute,
@@ -7851,14 +7992,14 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7851
7992
  const h = data !== undefined ? data.hour : hour12;
7852
7993
  const m = data !== undefined ? data.minute : minute;
7853
7994
  const mer = data !== undefined ? data.meridiem : meridiem;
7854
- console.log('[DateTimePicker] Resolved time values:', { h, m, mer });
7995
+ console.debug('[DateTimePicker] Resolved time values:', { h, m, mer });
7855
7996
  // If all time values are null, clear the value
7856
7997
  if (h === null && m === null && mer === null) {
7857
- console.log('[DateTimePicker] All time values are null, clearing value');
7998
+ console.debug('[DateTimePicker] All time values are null, clearing value');
7858
7999
  onChange?.(undefined);
7859
8000
  return;
7860
8001
  }
7861
- console.log('[DateTimePicker] 12-hour format - converting time:', {
8002
+ console.debug('[DateTimePicker] 12-hour format - converting time:', {
7862
8003
  h,
7863
8004
  m,
7864
8005
  mer,
@@ -7869,7 +8010,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7869
8010
  hour24 = 0;
7870
8011
  else if (mer === 'pm' && h < 12)
7871
8012
  hour24 = h + 12;
7872
- console.log('[DateTimePicker] Converted to 24-hour:', {
8013
+ console.debug('[DateTimePicker] Converted to 24-hour:', {
7873
8014
  h,
7874
8015
  mer,
7875
8016
  hour24,
@@ -7877,7 +8018,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7877
8018
  newDate.setHours(hour24);
7878
8019
  }
7879
8020
  else {
7880
- console.log('[DateTimePicker] Skipping hour update - h or mer is null:', {
8021
+ console.debug('[DateTimePicker] Skipping hour update - h or mer is null:', {
7881
8022
  h,
7882
8023
  mer,
7883
8024
  });
@@ -7886,12 +8027,12 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7886
8027
  newDate.setMinutes(m);
7887
8028
  }
7888
8029
  else {
7889
- console.log('[DateTimePicker] Skipping minute update - m is null');
8030
+ console.debug('[DateTimePicker] Skipping minute update - m is null');
7890
8031
  }
7891
8032
  newDate.setSeconds(0);
7892
8033
  }
7893
8034
  const finalISO = dayjs(newDate).tz(timezone).toISOString();
7894
- console.log('[DateTimePicker] Final ISO string to emit:', {
8035
+ console.debug('[DateTimePicker] Final ISO string to emit:', {
7895
8036
  newDate: newDate.toISOString(),
7896
8037
  timezone,
7897
8038
  finalISO,
@@ -7926,7 +8067,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7926
8067
  : undefined;
7927
8068
  // Log current state before render
7928
8069
  React.useEffect(() => {
7929
- console.log('[DateTimePicker] Current state before render:', {
8070
+ console.debug('[DateTimePicker] Current state before render:', {
7930
8071
  isISO,
7931
8072
  hour12,
7932
8073
  minute,
@@ -8186,7 +8327,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
8186
8327
  const value = watch(colLabel);
8187
8328
  const formI18n = useFormI18n(column, prefix, schema);
8188
8329
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
8189
- gridRow, children: [jsxRuntime.jsx(react.Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
8330
+ gridRow, children: [jsxRuntime.jsx(react.Text, { children: value ? 'True' : 'False' }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
8190
8331
  };
8191
8332
 
8192
8333
  const CustomViewer = ({ column, schema, prefix }) => {
@@ -8225,16 +8366,15 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
8225
8366
  const colLabel = formI18n.colLabel;
8226
8367
  const watchEnum = watch(colLabel);
8227
8368
  const watchEnums = (watch(colLabel) ?? []);
8369
+ const renderDisplayFunction = renderDisplay || defaultRenderDisplay;
8228
8370
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
8229
8371
  gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, children: watchEnums.map((enumValue) => {
8230
8372
  const item = enumValue;
8231
8373
  if (item === undefined) {
8232
8374
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "undefined" });
8233
8375
  }
8234
- return (jsxRuntime.jsx(Tag, { size: "lg", children: !!renderDisplay === true
8235
- ? renderDisplay(item)
8236
- : formI18n.t(item) }, item));
8237
- }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: formI18n.t(watchEnum) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
8376
+ return (jsxRuntime.jsx(Tag, { size: "lg", children: renderDisplayFunction(item) }, item));
8377
+ }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: renderDisplayFunction(watchEnum) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
8238
8378
  };
8239
8379
 
8240
8380
  const FileViewer = ({ column, schema, prefix }) => {