@bsol-oss/react-datatable5 13.0.1-beta.0 → 13.0.1-beta.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.d.ts CHANGED
@@ -817,12 +817,25 @@ interface TimePickerLabels {
817
817
  placeholder?: string;
818
818
  emptyMessage?: string;
819
819
  }
820
+ interface LoadInitialValuesParams {
821
+ ids: string[];
822
+ foreign_key: ForeignKeyProps;
823
+ setIdMap: React__default.Dispatch<React__default.SetStateAction<Record<string, object>>>;
824
+ }
825
+ interface LoadInitialValuesResult {
826
+ data: {
827
+ data: Record<string, any>[];
828
+ count: number;
829
+ };
830
+ idMap: Record<string, object>;
831
+ }
820
832
  interface CustomJSONSchema7 extends JSONSchema7 {
821
833
  gridColumn?: string;
822
834
  gridRow?: string;
823
835
  foreign_key?: ForeignKeyProps;
824
836
  variant?: string;
825
837
  renderDisplay?: (item: unknown) => ReactNode;
838
+ loadInitialValues?: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
826
839
  inputRender?: (props: {
827
840
  column: string;
828
841
  schema: CustomJSONSchema7;
@@ -844,6 +857,24 @@ interface CustomJSONSchema7 extends JSONSchema7 {
844
857
  numberStorageType?: 'string' | 'number';
845
858
  errorMessages?: Partial<Record<ValidationErrorType | string, string>>;
846
859
  filePicker?: FilePickerProps;
860
+ tagPicker?: {
861
+ queryFn?: (params: {
862
+ in_table: string;
863
+ where?: {
864
+ id: string;
865
+ value: string[];
866
+ }[];
867
+ limit?: number;
868
+ offset?: number;
869
+ searching?: string;
870
+ }) => Promise<{
871
+ data: {
872
+ data: any[];
873
+ count: number;
874
+ };
875
+ idMap?: Record<string, object>;
876
+ }>;
877
+ };
847
878
  }
848
879
  declare const defaultRenderDisplay: (item: unknown) => ReactNode;
849
880
  interface TagPickerProps {
@@ -869,7 +900,6 @@ interface FilePickerProps {
869
900
 
870
901
  interface FormRootProps<TData extends FieldValues> {
871
902
  schema: CustomJSONSchema7;
872
- serverUrl: string;
873
903
  requestUrl?: string;
874
904
  idMap: Record<string, object>;
875
905
  setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
@@ -913,7 +943,7 @@ declare const idPickerSanityCheck: (column: string, foreign_key?: {
913
943
  table?: string | undefined;
914
944
  column?: string | undefined;
915
945
  } | undefined) => void;
916
- declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
946
+ declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
917
947
 
918
948
  interface DefaultFormProps<TData extends FieldValues> {
919
949
  formConfig: Omit<FormRootProps<TData>, "children">;
@@ -1388,4 +1418,4 @@ declare module '@tanstack/react-table' {
1388
1418
  }
1389
1419
  }
1390
1420
 
1391
- export { CalendarDisplay, type CalendarDisplayProps, type CalendarEvent, type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, DatePickerInput, type DatePickerInputProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, type FormButtonLabels, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, MediaLibraryBrowser, type MediaLibraryBrowserProps, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerLabels, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, SelectAllRowsToggle, type SelectAllRowsToggleProps, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type TimePickerLabels, type Translate, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
1421
+ export { CalendarDisplay, type CalendarDisplayProps, type CalendarEvent, type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, DatePickerInput, type DatePickerInputProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, type FormButtonLabels, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, type LoadInitialValuesParams, type LoadInitialValuesResult, MediaLibraryBrowser, type MediaLibraryBrowserProps, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerLabels, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, SelectAllRowsToggle, type SelectAllRowsToggleProps, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type TimePickerLabels, type Translate, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
package/dist/index.js CHANGED
@@ -4036,7 +4036,6 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
4036
4036
  //@ts-expect-error TODO: find appropriate type
4037
4037
  const SchemaFormContext = React.createContext({
4038
4038
  schema: {},
4039
- serverUrl: '',
4040
4039
  requestUrl: '',
4041
4040
  order: [],
4042
4041
  ignore: [],
@@ -4276,7 +4275,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
4276
4275
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
4277
4276
  }
4278
4277
  };
4279
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
4278
+ const FormRoot = ({ schema, idMap, setIdMap, form, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
4280
4279
  showSubmitButton: true,
4281
4280
  showResetButton: true,
4282
4281
  showTitle: true,
@@ -4317,9 +4316,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4317
4316
  }
4318
4317
  };
4319
4318
  const defaultSubmitPromise = (data) => {
4319
+ if (!requestOptions.url) {
4320
+ throw new Error('requestOptions.url is required when onSubmit is not provided');
4321
+ }
4320
4322
  const options = {
4321
4323
  method: 'POST',
4322
- url: `${serverUrl}`,
4323
4324
  data: clearEmptyString(data),
4324
4325
  ...requestOptions,
4325
4326
  };
@@ -4337,7 +4338,6 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4337
4338
  };
4338
4339
  return (jsxRuntime.jsx(SchemaFormContext.Provider, { value: {
4339
4340
  schema,
4340
- serverUrl,
4341
4341
  order,
4342
4342
  ignore,
4343
4343
  include,
@@ -5618,34 +5618,6 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5618
5618
  }) })] }));
5619
5619
  };
5620
5620
 
5621
- const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
5622
- if (serverUrl === undefined || serverUrl.length == 0) {
5623
- throw new Error("The serverUrl is missing");
5624
- }
5625
- if (in_table === undefined || in_table.length == 0) {
5626
- throw new Error("The in_table is missing");
5627
- }
5628
- const options = {
5629
- method: "GET",
5630
- url: `${serverUrl}/api/g/${in_table}`,
5631
- params: {
5632
- searching,
5633
- where,
5634
- limit,
5635
- offset
5636
- },
5637
- };
5638
- try {
5639
- const { data } = await axios.request(options);
5640
- console.log(data);
5641
- return data;
5642
- }
5643
- catch (error) {
5644
- console.error(error);
5645
- throw error;
5646
- }
5647
- };
5648
-
5649
5621
  // Default renderDisplay function that stringifies JSON
5650
5622
  const defaultRenderDisplay = (item) => {
5651
5623
  return JSON.stringify(item);
@@ -5653,8 +5625,13 @@ const defaultRenderDisplay = (item) => {
5653
5625
 
5654
5626
  const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5655
5627
  const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5656
- const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5657
- const { renderDisplay, foreign_key } = schema;
5628
+ const { idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5629
+ const { renderDisplay, loadInitialValues: schemaLoadInitialValues, foreign_key, variant, } = schema;
5630
+ // loadInitialValues must be provided in schema for id-picker fields
5631
+ // It's used to load the record of the id so the display is human-readable
5632
+ if (variant === 'id-picker' && !schemaLoadInitialValues) {
5633
+ throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'. Please provide loadInitialValues function in the schema to load records for human-readable display.`);
5634
+ }
5658
5635
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5659
5636
  const [searchText, setSearchText] = React.useState('');
5660
5637
  const [debouncedSearchText, setDebouncedSearchText] = React.useState('');
@@ -5707,48 +5684,16 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5707
5684
  if (missingIds.length === 0) {
5708
5685
  return { data: [], count: 0 };
5709
5686
  }
5710
- if (customQueryFn) {
5711
- const { data, idMap } = await customQueryFn({
5712
- searching: '',
5713
- limit: missingIds.length,
5714
- offset: 0,
5715
- where: [
5716
- {
5717
- id: column_ref,
5718
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5719
- },
5720
- ],
5721
- });
5722
- setIdMap((state) => {
5723
- return { ...state, ...idMap };
5724
- });
5725
- return data;
5687
+ // Use schema's loadInitialValues (required for id-picker)
5688
+ if (!schemaLoadInitialValues) {
5689
+ throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'.`);
5726
5690
  }
5727
- const data = await getTableData({
5728
- serverUrl,
5729
- searching: '',
5730
- in_table: table,
5731
- limit: missingIds.length,
5732
- offset: 0,
5733
- where: [
5734
- {
5735
- id: column_ref,
5736
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5737
- },
5738
- ],
5739
- });
5740
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5741
- return [
5742
- item[column_ref],
5743
- {
5744
- ...item,
5745
- },
5746
- ];
5747
- }));
5748
- setIdMap((state) => {
5749
- return { ...state, ...newMap };
5691
+ const result = await schemaLoadInitialValues({
5692
+ ids: missingIds,
5693
+ foreign_key: foreign_key,
5694
+ setIdMap,
5750
5695
  });
5751
- return data;
5696
+ return result.data;
5752
5697
  },
5753
5698
  enabled: missingIds.length > 0, // Only fetch if there are missing IDs
5754
5699
  staleTime: 300000,
@@ -5758,35 +5703,21 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5758
5703
  const query = reactQuery.useQuery({
5759
5704
  queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
5760
5705
  queryFn: async () => {
5761
- if (customQueryFn) {
5762
- const { data, idMap } = await customQueryFn({
5763
- searching: debouncedSearchText ?? '',
5764
- limit: limit,
5765
- offset: 0,
5766
- });
5767
- setIdMap((state) => {
5768
- return { ...state, ...idMap };
5769
- });
5770
- return data;
5706
+ // customQueryFn is required when serverUrl is not available
5707
+ if (!customQueryFn) {
5708
+ throw new Error(`customQueryFn is required in foreign_key for table ${table}. serverUrl has been removed.`);
5771
5709
  }
5772
- const data = await getTableData({
5773
- serverUrl,
5710
+ const { data, idMap } = await customQueryFn({
5774
5711
  searching: debouncedSearchText ?? '',
5775
- in_table: table,
5776
5712
  limit: limit,
5777
5713
  offset: 0,
5778
5714
  });
5779
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5780
- return [
5781
- item[column_ref],
5782
- {
5783
- ...item,
5784
- },
5785
- ];
5786
- }));
5787
- setIdMap((state) => {
5788
- return { ...state, ...newMap };
5789
- });
5715
+ // Update idMap with returned values
5716
+ if (idMap && Object.keys(idMap).length > 0) {
5717
+ setIdMap((state) => {
5718
+ return { ...state, ...idMap };
5719
+ });
5720
+ }
5790
5721
  return data;
5791
5722
  },
5792
5723
  enabled: true, // Always enabled for combobox
@@ -5910,6 +5841,7 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5910
5841
  idPickerLabels,
5911
5842
  insideDialog: insideDialog ?? false,
5912
5843
  renderDisplay,
5844
+ loadInitialValues: schemaLoadInitialValues, // Required for id-picker, checked above
5913
5845
  column_ref,
5914
5846
  errors,
5915
5847
  setValue,
@@ -6203,31 +6135,35 @@ react.RadioCard.ItemIndicator;
6203
6135
 
6204
6136
  const TagPicker = ({ column, schema, prefix }) => {
6205
6137
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
6206
- const { serverUrl } = useSchemaContext();
6207
6138
  if (schema.properties == undefined) {
6208
- throw new Error("schema properties undefined when using DatePicker");
6139
+ throw new Error('schema properties undefined when using DatePicker');
6209
6140
  }
6210
- const { gridColumn, gridRow, in_table, object_id_column } = schema;
6141
+ const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
6211
6142
  if (in_table === undefined) {
6212
- throw new Error("in_table is undefined when using TagPicker");
6143
+ throw new Error('in_table is undefined when using TagPicker');
6213
6144
  }
6214
6145
  if (object_id_column === undefined) {
6215
- throw new Error("object_id_column is undefined when using TagPicker");
6146
+ throw new Error('object_id_column is undefined when using TagPicker');
6147
+ }
6148
+ if (!tagPicker?.queryFn) {
6149
+ throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
6216
6150
  }
6217
6151
  const query = reactQuery.useQuery({
6218
6152
  queryKey: [`tagpicker`, in_table],
6219
6153
  queryFn: async () => {
6220
- return await getTableData({
6221
- serverUrl,
6222
- in_table: "tables_tags_view",
6154
+ const result = await tagPicker.queryFn({
6155
+ in_table: 'tables_tags_view',
6223
6156
  where: [
6224
6157
  {
6225
- id: "table_name",
6158
+ id: 'table_name',
6226
6159
  value: [in_table],
6227
6160
  },
6228
6161
  ],
6229
6162
  limit: 100,
6163
+ offset: 0,
6164
+ searching: '',
6230
6165
  });
6166
+ return result.data || { data: [] };
6231
6167
  },
6232
6168
  staleTime: 10000,
6233
6169
  });
@@ -6235,17 +6171,19 @@ const TagPicker = ({ column, schema, prefix }) => {
6235
6171
  const existingTagsQuery = reactQuery.useQuery({
6236
6172
  queryKey: [`existing`, { in_table, object_id_column }, object_id],
6237
6173
  queryFn: async () => {
6238
- return await getTableData({
6239
- serverUrl,
6174
+ const result = await tagPicker.queryFn({
6240
6175
  in_table: in_table,
6241
6176
  where: [
6242
6177
  {
6243
6178
  id: object_id_column,
6244
- value: object_id[0],
6179
+ value: [object_id[0]],
6245
6180
  },
6246
6181
  ],
6247
6182
  limit: 100,
6183
+ offset: 0,
6184
+ searching: '',
6248
6185
  });
6186
+ return result.data || { data: [] };
6249
6187
  },
6250
6188
  enabled: object_id != undefined,
6251
6189
  staleTime: 10000,
@@ -6256,9 +6194,9 @@ const TagPicker = ({ column, schema, prefix }) => {
6256
6194
  if (!!object_id === false) {
6257
6195
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
6258
6196
  }
6259
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 4, gridColumn,
6197
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 4, gridColumn,
6260
6198
  gridRow, children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
6261
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
6199
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
6262
6200
  const existedTags = Object.values(all_tags)
6263
6201
  .filter(({ id }) => {
6264
6202
  return existingTagList.some(({ tag_id }) => tag_id === id);
@@ -6270,20 +6208,20 @@ const TagPicker = ({ column, schema, prefix }) => {
6270
6208
  tagIds.value,
6271
6209
  ]);
6272
6210
  setValue(`${column}.${parent_tag_name}.old`, existedTags);
6273
- }, children: jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6211
+ }, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6274
6212
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
6275
- return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
6213
+ return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
6276
6214
  }
6277
- return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
6215
+ return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
6278
6216
  }) }) })), !is_mutually_exclusive && (jsxRuntime.jsx(react.CheckboxGroup, { onValueChange: (tagIds) => {
6279
6217
  setValue(`${column}.${parent_tag_name}.current`, tagIds);
6280
- }, children: jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6218
+ }, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6281
6219
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
6282
- return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
6220
+ return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
6283
6221
  }
6284
- return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
6222
+ return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
6285
6223
  }) }) }))] }, `tag-${parent_tag_name}`));
6286
- }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
6224
+ }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
6287
6225
  };
6288
6226
 
6289
6227
  const Textarea = React.forwardRef(({ value, defaultValue, placeholder, onChange, onFocus, onBlur, disabled = false, readOnly = false, className, rows = 4, maxLength, autoFocus = false, invalid = false, required = false, label, helperText, errorText, ...props }, ref) => {
@@ -7965,31 +7903,35 @@ const StringViewer = ({ column, schema, prefix, }) => {
7965
7903
 
7966
7904
  const TagViewer = ({ column, schema, prefix }) => {
7967
7905
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
7968
- const { serverUrl } = useSchemaContext();
7969
7906
  if (schema.properties == undefined) {
7970
- throw new Error("schema properties undefined when using DatePicker");
7907
+ throw new Error('schema properties undefined when using DatePicker');
7971
7908
  }
7972
- const { gridColumn, gridRow, in_table, object_id_column } = schema;
7909
+ const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
7973
7910
  if (in_table === undefined) {
7974
- throw new Error("in_table is undefined when using TagPicker");
7911
+ throw new Error('in_table is undefined when using TagPicker');
7975
7912
  }
7976
7913
  if (object_id_column === undefined) {
7977
- throw new Error("object_id_column is undefined when using TagPicker");
7914
+ throw new Error('object_id_column is undefined when using TagPicker');
7915
+ }
7916
+ if (!tagPicker?.queryFn) {
7917
+ throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
7978
7918
  }
7979
7919
  const query = reactQuery.useQuery({
7980
7920
  queryKey: [`tagpicker`, in_table],
7981
7921
  queryFn: async () => {
7982
- return await getTableData({
7983
- serverUrl,
7984
- in_table: "tables_tags_view",
7922
+ const result = await tagPicker.queryFn({
7923
+ in_table: 'tables_tags_view',
7985
7924
  where: [
7986
7925
  {
7987
- id: "table_name",
7926
+ id: 'table_name',
7988
7927
  value: [in_table],
7989
7928
  },
7990
7929
  ],
7991
7930
  limit: 100,
7931
+ offset: 0,
7932
+ searching: '',
7992
7933
  });
7934
+ return result.data || { data: [] };
7993
7935
  },
7994
7936
  staleTime: 10000,
7995
7937
  });
@@ -7997,17 +7939,19 @@ const TagViewer = ({ column, schema, prefix }) => {
7997
7939
  const existingTagsQuery = reactQuery.useQuery({
7998
7940
  queryKey: [`existing`, { in_table, object_id_column }, object_id],
7999
7941
  queryFn: async () => {
8000
- return await getTableData({
8001
- serverUrl,
7942
+ const result = await tagPicker.queryFn({
8002
7943
  in_table: in_table,
8003
7944
  where: [
8004
7945
  {
8005
7946
  id: object_id_column,
8006
- value: object_id[0],
7947
+ value: [object_id[0]],
8007
7948
  },
8008
7949
  ],
8009
7950
  limit: 100,
7951
+ offset: 0,
7952
+ searching: '',
8010
7953
  });
7954
+ return result.data || { data: [] };
8011
7955
  },
8012
7956
  enabled: object_id != undefined,
8013
7957
  staleTime: 10000,
@@ -8018,9 +7962,9 @@ const TagViewer = ({ column, schema, prefix }) => {
8018
7962
  if (!!object_id === false) {
8019
7963
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
8020
7964
  }
8021
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 4, gridColumn,
7965
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 4, gridColumn,
8022
7966
  gridRow, children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
8023
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
7967
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 2, children: [jsxRuntime.jsx(react.Text, { children: parent_tag_name }), is_mutually_exclusive && (jsxRuntime.jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
8024
7968
  const existedTags = Object.values(all_tags)
8025
7969
  .filter(({ id }) => {
8026
7970
  return existingTagList.some(({ tag_id }) => tag_id === id);
@@ -8032,20 +7976,20 @@ const TagViewer = ({ column, schema, prefix }) => {
8032
7976
  tagIds.value,
8033
7977
  ]);
8034
7978
  setValue(`${column}.${parent_tag_name}.old`, existedTags);
8035
- }, children: jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
7979
+ }, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
8036
7980
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
8037
- return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
7981
+ return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
8038
7982
  }
8039
- return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
7983
+ return (jsxRuntime.jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
8040
7984
  }) }) })), !is_mutually_exclusive && (jsxRuntime.jsx(react.CheckboxGroup, { onValueChange: (tagIds) => {
8041
7985
  setValue(`${column}.${parent_tag_name}.current`, tagIds);
8042
- }, children: jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
7986
+ }, children: jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
8043
7987
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
8044
- return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
7988
+ return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
8045
7989
  }
8046
- return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
7990
+ return (jsxRuntime.jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
8047
7991
  }) }) }))] }, `tag-${parent_tag_name}`));
8048
- }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
7992
+ }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
8049
7993
  };
8050
7994
 
8051
7995
  const TextAreaViewer = ({ column, schema, prefix, }) => {
package/dist/index.mjs CHANGED
@@ -4016,7 +4016,6 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
4016
4016
  //@ts-expect-error TODO: find appropriate type
4017
4017
  const SchemaFormContext = createContext({
4018
4018
  schema: {},
4019
- serverUrl: '',
4020
4019
  requestUrl: '',
4021
4020
  order: [],
4022
4021
  ignore: [],
@@ -4256,7 +4255,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
4256
4255
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
4257
4256
  }
4258
4257
  };
4259
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
4258
+ const FormRoot = ({ schema, idMap, setIdMap, form, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
4260
4259
  showSubmitButton: true,
4261
4260
  showResetButton: true,
4262
4261
  showTitle: true,
@@ -4297,9 +4296,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4297
4296
  }
4298
4297
  };
4299
4298
  const defaultSubmitPromise = (data) => {
4299
+ if (!requestOptions.url) {
4300
+ throw new Error('requestOptions.url is required when onSubmit is not provided');
4301
+ }
4300
4302
  const options = {
4301
4303
  method: 'POST',
4302
- url: `${serverUrl}`,
4303
4304
  data: clearEmptyString(data),
4304
4305
  ...requestOptions,
4305
4306
  };
@@ -4317,7 +4318,6 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4317
4318
  };
4318
4319
  return (jsx(SchemaFormContext.Provider, { value: {
4319
4320
  schema,
4320
- serverUrl,
4321
4321
  order,
4322
4322
  ignore,
4323
4323
  include,
@@ -5598,34 +5598,6 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5598
5598
  }) })] }));
5599
5599
  };
5600
5600
 
5601
- const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
5602
- if (serverUrl === undefined || serverUrl.length == 0) {
5603
- throw new Error("The serverUrl is missing");
5604
- }
5605
- if (in_table === undefined || in_table.length == 0) {
5606
- throw new Error("The in_table is missing");
5607
- }
5608
- const options = {
5609
- method: "GET",
5610
- url: `${serverUrl}/api/g/${in_table}`,
5611
- params: {
5612
- searching,
5613
- where,
5614
- limit,
5615
- offset
5616
- },
5617
- };
5618
- try {
5619
- const { data } = await axios.request(options);
5620
- console.log(data);
5621
- return data;
5622
- }
5623
- catch (error) {
5624
- console.error(error);
5625
- throw error;
5626
- }
5627
- };
5628
-
5629
5601
  // Default renderDisplay function that stringifies JSON
5630
5602
  const defaultRenderDisplay = (item) => {
5631
5603
  return JSON.stringify(item);
@@ -5633,8 +5605,13 @@ const defaultRenderDisplay = (item) => {
5633
5605
 
5634
5606
  const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5635
5607
  const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
5636
- const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5637
- const { renderDisplay, foreign_key } = schema;
5608
+ const { idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5609
+ const { renderDisplay, loadInitialValues: schemaLoadInitialValues, foreign_key, variant, } = schema;
5610
+ // loadInitialValues must be provided in schema for id-picker fields
5611
+ // It's used to load the record of the id so the display is human-readable
5612
+ if (variant === 'id-picker' && !schemaLoadInitialValues) {
5613
+ throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'. Please provide loadInitialValues function in the schema to load records for human-readable display.`);
5614
+ }
5638
5615
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5639
5616
  const [searchText, setSearchText] = useState('');
5640
5617
  const [debouncedSearchText, setDebouncedSearchText] = useState('');
@@ -5687,48 +5664,16 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5687
5664
  if (missingIds.length === 0) {
5688
5665
  return { data: [], count: 0 };
5689
5666
  }
5690
- if (customQueryFn) {
5691
- const { data, idMap } = await customQueryFn({
5692
- searching: '',
5693
- limit: missingIds.length,
5694
- offset: 0,
5695
- where: [
5696
- {
5697
- id: column_ref,
5698
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5699
- },
5700
- ],
5701
- });
5702
- setIdMap((state) => {
5703
- return { ...state, ...idMap };
5704
- });
5705
- return data;
5667
+ // Use schema's loadInitialValues (required for id-picker)
5668
+ if (!schemaLoadInitialValues) {
5669
+ throw new Error(`loadInitialValues is required in schema for IdPicker field '${column}'.`);
5706
5670
  }
5707
- const data = await getTableData({
5708
- serverUrl,
5709
- searching: '',
5710
- in_table: table,
5711
- limit: missingIds.length,
5712
- offset: 0,
5713
- where: [
5714
- {
5715
- id: column_ref,
5716
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5717
- },
5718
- ],
5719
- });
5720
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5721
- return [
5722
- item[column_ref],
5723
- {
5724
- ...item,
5725
- },
5726
- ];
5727
- }));
5728
- setIdMap((state) => {
5729
- return { ...state, ...newMap };
5671
+ const result = await schemaLoadInitialValues({
5672
+ ids: missingIds,
5673
+ foreign_key: foreign_key,
5674
+ setIdMap,
5730
5675
  });
5731
- return data;
5676
+ return result.data;
5732
5677
  },
5733
5678
  enabled: missingIds.length > 0, // Only fetch if there are missing IDs
5734
5679
  staleTime: 300000,
@@ -5738,35 +5683,21 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5738
5683
  const query = useQuery({
5739
5684
  queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
5740
5685
  queryFn: async () => {
5741
- if (customQueryFn) {
5742
- const { data, idMap } = await customQueryFn({
5743
- searching: debouncedSearchText ?? '',
5744
- limit: limit,
5745
- offset: 0,
5746
- });
5747
- setIdMap((state) => {
5748
- return { ...state, ...idMap };
5749
- });
5750
- return data;
5686
+ // customQueryFn is required when serverUrl is not available
5687
+ if (!customQueryFn) {
5688
+ throw new Error(`customQueryFn is required in foreign_key for table ${table}. serverUrl has been removed.`);
5751
5689
  }
5752
- const data = await getTableData({
5753
- serverUrl,
5690
+ const { data, idMap } = await customQueryFn({
5754
5691
  searching: debouncedSearchText ?? '',
5755
- in_table: table,
5756
5692
  limit: limit,
5757
5693
  offset: 0,
5758
5694
  });
5759
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5760
- return [
5761
- item[column_ref],
5762
- {
5763
- ...item,
5764
- },
5765
- ];
5766
- }));
5767
- setIdMap((state) => {
5768
- return { ...state, ...newMap };
5769
- });
5695
+ // Update idMap with returned values
5696
+ if (idMap && Object.keys(idMap).length > 0) {
5697
+ setIdMap((state) => {
5698
+ return { ...state, ...idMap };
5699
+ });
5700
+ }
5770
5701
  return data;
5771
5702
  },
5772
5703
  enabled: true, // Always enabled for combobox
@@ -5890,6 +5821,7 @@ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5890
5821
  idPickerLabels,
5891
5822
  insideDialog: insideDialog ?? false,
5892
5823
  renderDisplay,
5824
+ loadInitialValues: schemaLoadInitialValues, // Required for id-picker, checked above
5893
5825
  column_ref,
5894
5826
  errors,
5895
5827
  setValue,
@@ -6183,31 +6115,35 @@ RadioCard.ItemIndicator;
6183
6115
 
6184
6116
  const TagPicker = ({ column, schema, prefix }) => {
6185
6117
  const { watch, formState: { errors }, setValue, } = useFormContext();
6186
- const { serverUrl } = useSchemaContext();
6187
6118
  if (schema.properties == undefined) {
6188
- throw new Error("schema properties undefined when using DatePicker");
6119
+ throw new Error('schema properties undefined when using DatePicker');
6189
6120
  }
6190
- const { gridColumn, gridRow, in_table, object_id_column } = schema;
6121
+ const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
6191
6122
  if (in_table === undefined) {
6192
- throw new Error("in_table is undefined when using TagPicker");
6123
+ throw new Error('in_table is undefined when using TagPicker');
6193
6124
  }
6194
6125
  if (object_id_column === undefined) {
6195
- throw new Error("object_id_column is undefined when using TagPicker");
6126
+ throw new Error('object_id_column is undefined when using TagPicker');
6127
+ }
6128
+ if (!tagPicker?.queryFn) {
6129
+ throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
6196
6130
  }
6197
6131
  const query = useQuery({
6198
6132
  queryKey: [`tagpicker`, in_table],
6199
6133
  queryFn: async () => {
6200
- return await getTableData({
6201
- serverUrl,
6202
- in_table: "tables_tags_view",
6134
+ const result = await tagPicker.queryFn({
6135
+ in_table: 'tables_tags_view',
6203
6136
  where: [
6204
6137
  {
6205
- id: "table_name",
6138
+ id: 'table_name',
6206
6139
  value: [in_table],
6207
6140
  },
6208
6141
  ],
6209
6142
  limit: 100,
6143
+ offset: 0,
6144
+ searching: '',
6210
6145
  });
6146
+ return result.data || { data: [] };
6211
6147
  },
6212
6148
  staleTime: 10000,
6213
6149
  });
@@ -6215,17 +6151,19 @@ const TagPicker = ({ column, schema, prefix }) => {
6215
6151
  const existingTagsQuery = useQuery({
6216
6152
  queryKey: [`existing`, { in_table, object_id_column }, object_id],
6217
6153
  queryFn: async () => {
6218
- return await getTableData({
6219
- serverUrl,
6154
+ const result = await tagPicker.queryFn({
6220
6155
  in_table: in_table,
6221
6156
  where: [
6222
6157
  {
6223
6158
  id: object_id_column,
6224
- value: object_id[0],
6159
+ value: [object_id[0]],
6225
6160
  },
6226
6161
  ],
6227
6162
  limit: 100,
6163
+ offset: 0,
6164
+ searching: '',
6228
6165
  });
6166
+ return result.data || { data: [] };
6229
6167
  },
6230
6168
  enabled: object_id != undefined,
6231
6169
  staleTime: 10000,
@@ -6236,9 +6174,9 @@ const TagPicker = ({ column, schema, prefix }) => {
6236
6174
  if (!!object_id === false) {
6237
6175
  return jsx(Fragment, {});
6238
6176
  }
6239
- return (jsxs(Flex, { flexFlow: "column", gap: 4, gridColumn,
6177
+ return (jsxs(Flex, { flexFlow: 'column', gap: 4, gridColumn,
6240
6178
  gridRow, children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
6241
- return (jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
6179
+ return (jsxs(Flex, { flexFlow: 'column', gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
6242
6180
  const existedTags = Object.values(all_tags)
6243
6181
  .filter(({ id }) => {
6244
6182
  return existingTagList.some(({ tag_id }) => tag_id === id);
@@ -6250,20 +6188,20 @@ const TagPicker = ({ column, schema, prefix }) => {
6250
6188
  tagIds.value,
6251
6189
  ]);
6252
6190
  setValue(`${column}.${parent_tag_name}.old`, existedTags);
6253
- }, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6191
+ }, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6254
6192
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
6255
- return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
6193
+ return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
6256
6194
  }
6257
- return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
6195
+ return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
6258
6196
  }) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
6259
6197
  setValue(`${column}.${parent_tag_name}.current`, tagIds);
6260
- }, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6198
+ }, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
6261
6199
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
6262
- return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
6200
+ return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
6263
6201
  }
6264
- return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
6202
+ return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
6265
6203
  }) }) }))] }, `tag-${parent_tag_name}`));
6266
- }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
6204
+ }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
6267
6205
  };
6268
6206
 
6269
6207
  const Textarea = forwardRef(({ value, defaultValue, placeholder, onChange, onFocus, onBlur, disabled = false, readOnly = false, className, rows = 4, maxLength, autoFocus = false, invalid = false, required = false, label, helperText, errorText, ...props }, ref) => {
@@ -7945,31 +7883,35 @@ const StringViewer = ({ column, schema, prefix, }) => {
7945
7883
 
7946
7884
  const TagViewer = ({ column, schema, prefix }) => {
7947
7885
  const { watch, formState: { errors }, setValue, } = useFormContext();
7948
- const { serverUrl } = useSchemaContext();
7949
7886
  if (schema.properties == undefined) {
7950
- throw new Error("schema properties undefined when using DatePicker");
7887
+ throw new Error('schema properties undefined when using DatePicker');
7951
7888
  }
7952
- const { gridColumn, gridRow, in_table, object_id_column } = schema;
7889
+ const { gridColumn, gridRow, in_table, object_id_column, tagPicker } = schema;
7953
7890
  if (in_table === undefined) {
7954
- throw new Error("in_table is undefined when using TagPicker");
7891
+ throw new Error('in_table is undefined when using TagPicker');
7955
7892
  }
7956
7893
  if (object_id_column === undefined) {
7957
- throw new Error("object_id_column is undefined when using TagPicker");
7894
+ throw new Error('object_id_column is undefined when using TagPicker');
7895
+ }
7896
+ if (!tagPicker?.queryFn) {
7897
+ throw new Error('tagPicker.queryFn is required in schema. serverUrl has been removed.');
7958
7898
  }
7959
7899
  const query = useQuery({
7960
7900
  queryKey: [`tagpicker`, in_table],
7961
7901
  queryFn: async () => {
7962
- return await getTableData({
7963
- serverUrl,
7964
- in_table: "tables_tags_view",
7902
+ const result = await tagPicker.queryFn({
7903
+ in_table: 'tables_tags_view',
7965
7904
  where: [
7966
7905
  {
7967
- id: "table_name",
7906
+ id: 'table_name',
7968
7907
  value: [in_table],
7969
7908
  },
7970
7909
  ],
7971
7910
  limit: 100,
7911
+ offset: 0,
7912
+ searching: '',
7972
7913
  });
7914
+ return result.data || { data: [] };
7973
7915
  },
7974
7916
  staleTime: 10000,
7975
7917
  });
@@ -7977,17 +7919,19 @@ const TagViewer = ({ column, schema, prefix }) => {
7977
7919
  const existingTagsQuery = useQuery({
7978
7920
  queryKey: [`existing`, { in_table, object_id_column }, object_id],
7979
7921
  queryFn: async () => {
7980
- return await getTableData({
7981
- serverUrl,
7922
+ const result = await tagPicker.queryFn({
7982
7923
  in_table: in_table,
7983
7924
  where: [
7984
7925
  {
7985
7926
  id: object_id_column,
7986
- value: object_id[0],
7927
+ value: [object_id[0]],
7987
7928
  },
7988
7929
  ],
7989
7930
  limit: 100,
7931
+ offset: 0,
7932
+ searching: '',
7990
7933
  });
7934
+ return result.data || { data: [] };
7991
7935
  },
7992
7936
  enabled: object_id != undefined,
7993
7937
  staleTime: 10000,
@@ -7998,9 +7942,9 @@ const TagViewer = ({ column, schema, prefix }) => {
7998
7942
  if (!!object_id === false) {
7999
7943
  return jsx(Fragment, {});
8000
7944
  }
8001
- return (jsxs(Flex, { flexFlow: "column", gap: 4, gridColumn,
7945
+ return (jsxs(Flex, { flexFlow: 'column', gap: 4, gridColumn,
8002
7946
  gridRow, children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), dataList.map(({ parent_tag_name, all_tags, is_mutually_exclusive }) => {
8003
- return (jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: "surface", onValueChange: (tagIds) => {
7947
+ return (jsxs(Flex, { flexFlow: 'column', gap: 2, children: [jsx(Text, { children: parent_tag_name }), is_mutually_exclusive && (jsx(RadioCardRoot, { defaultValue: "next", variant: 'surface', onValueChange: (tagIds) => {
8004
7948
  const existedTags = Object.values(all_tags)
8005
7949
  .filter(({ id }) => {
8006
7950
  return existingTagList.some(({ tag_id }) => tag_id === id);
@@ -8012,20 +7956,20 @@ const TagViewer = ({ column, schema, prefix }) => {
8012
7956
  tagIds.value,
8013
7957
  ]);
8014
7958
  setValue(`${column}.${parent_tag_name}.old`, existedTags);
8015
- }, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
7959
+ }, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
8016
7960
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
8017
- return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", disabled: true }, `${tagName}-${id}`));
7961
+ return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', disabled: true }, `${tagName}-${id}`));
8018
7962
  }
8019
- return (jsx(RadioCardItem, { label: tagName, value: id, flex: "0 0 0%", colorPalette: "blue" }, `${tagName}-${id}`));
7963
+ return (jsx(RadioCardItem, { label: tagName, value: id, flex: '0 0 0%', colorPalette: 'blue' }, `${tagName}-${id}`));
8020
7964
  }) }) })), !is_mutually_exclusive && (jsx(CheckboxGroup, { onValueChange: (tagIds) => {
8021
7965
  setValue(`${column}.${parent_tag_name}.current`, tagIds);
8022
- }, children: jsx(Flex, { flexFlow: "wrap", gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
7966
+ }, children: jsx(Flex, { flexFlow: 'wrap', gap: 2, children: Object.entries(all_tags).map(([tagName, { id }]) => {
8023
7967
  if (existingTagList.some(({ tag_id }) => tag_id === id)) {
8024
- return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%", disabled: true, colorPalette: "blue" }, `${tagName}-${id}`));
7968
+ return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%', disabled: true, colorPalette: 'blue' }, `${tagName}-${id}`));
8025
7969
  }
8026
- return (jsx(CheckboxCard, { label: tagName, value: id, flex: "0 0 0%" }, `${tagName}-${id}`));
7970
+ return (jsx(CheckboxCard, { label: tagName, value: id, flex: '0 0 0%' }, `${tagName}-${id}`));
8027
7971
  }) }) }))] }, `tag-${parent_tag_name}`));
8028
- }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
7972
+ }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: (errors[`${column}`]?.message ?? 'No error message') }))] }));
8029
7973
  };
8030
7974
 
8031
7975
  const TextAreaViewer = ({ column, schema, prefix, }) => {
@@ -6,7 +6,6 @@ import { Translate } from './useForm';
6
6
  import { DateTimePickerLabels, IdPickerLabels, EnumPickerLabels, FilePickerLabels, FormButtonLabels, TimePickerLabels } from './components/types/CustomJSONSchema7';
7
7
  export interface SchemaFormContext<TData extends FieldValues> {
8
8
  schema: JSONSchema7;
9
- serverUrl: string;
10
9
  requestUrl: string;
11
10
  order: string[];
12
11
  ignore: string[];
@@ -7,7 +7,6 @@ import { Translate } from '../../useForm';
7
7
  import { CustomJSONSchema7, DateTimePickerLabels, IdPickerLabels, EnumPickerLabels, FilePickerLabels, FormButtonLabels, TimePickerLabels } from '../types/CustomJSONSchema7';
8
8
  export interface FormRootProps<TData extends FieldValues> {
9
9
  schema: CustomJSONSchema7;
10
- serverUrl: string;
11
10
  requestUrl?: string;
12
11
  idMap: Record<string, object>;
13
12
  setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
@@ -51,4 +50,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
51
50
  table?: string | undefined;
52
51
  column?: string | undefined;
53
52
  } | undefined) => void;
54
- export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
53
+ export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { TagPickerProps } from "../types/CustomJSONSchema7";
1
+ import { TagPickerProps } from '../types/CustomJSONSchema7';
2
2
  export interface Tag {
3
3
  id: string;
4
4
  name: string;
@@ -1,8 +1,9 @@
1
- /// <reference types="react" />
2
- import { CustomJSONSchema7 } from '../types/CustomJSONSchema7';
1
+ import React from 'react';
2
+ import { CustomJSONSchema7, LoadInitialValuesParams, LoadInitialValuesResult } from '../types/CustomJSONSchema7';
3
3
  export interface RecordType {
4
4
  [key: string]: any;
5
5
  }
6
+ export type { LoadInitialValuesParams, LoadInitialValuesResult, } from '../types/CustomJSONSchema7';
6
7
  export interface UseIdPickerDataProps {
7
8
  column: string;
8
9
  schema: CustomJSONSchema7;
@@ -39,6 +40,7 @@ export interface UseIdPickerDataReturn {
39
40
  idPickerLabels: any;
40
41
  insideDialog: boolean;
41
42
  renderDisplay: ((item: RecordType) => React.ReactNode) | undefined;
43
+ loadInitialValues: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
42
44
  column_ref: string;
43
45
  errors: any;
44
46
  setValue: (name: string, value: any) => void;
@@ -3,6 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { ForeignKeyProps } from '../fields/StringInputField';
4
4
  import { UseFormReturn } from 'react-hook-form';
5
5
  import { ValidationErrorType } from '../../utils/buildErrorMessages';
6
+ import React from 'react';
6
7
  export interface DateTimePickerLabels {
7
8
  monthNamesShort?: string[];
8
9
  weekdayNamesShort?: string[];
@@ -60,12 +61,25 @@ export interface TimePickerLabels {
60
61
  placeholder?: string;
61
62
  emptyMessage?: string;
62
63
  }
64
+ export interface LoadInitialValuesParams {
65
+ ids: string[];
66
+ foreign_key: ForeignKeyProps;
67
+ setIdMap: React.Dispatch<React.SetStateAction<Record<string, object>>>;
68
+ }
69
+ export interface LoadInitialValuesResult {
70
+ data: {
71
+ data: Record<string, any>[];
72
+ count: number;
73
+ };
74
+ idMap: Record<string, object>;
75
+ }
63
76
  export interface CustomJSONSchema7 extends JSONSchema7 {
64
77
  gridColumn?: string;
65
78
  gridRow?: string;
66
79
  foreign_key?: ForeignKeyProps;
67
80
  variant?: string;
68
81
  renderDisplay?: (item: unknown) => ReactNode;
82
+ loadInitialValues?: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
69
83
  inputRender?: (props: {
70
84
  column: string;
71
85
  schema: CustomJSONSchema7;
@@ -87,6 +101,24 @@ export interface CustomJSONSchema7 extends JSONSchema7 {
87
101
  numberStorageType?: 'string' | 'number';
88
102
  errorMessages?: Partial<Record<ValidationErrorType | string, string>>;
89
103
  filePicker?: FilePickerProps;
104
+ tagPicker?: {
105
+ queryFn?: (params: {
106
+ in_table: string;
107
+ where?: {
108
+ id: string;
109
+ value: string[];
110
+ }[];
111
+ limit?: number;
112
+ offset?: number;
113
+ searching?: string;
114
+ }) => Promise<{
115
+ data: {
116
+ data: any[];
117
+ count: number;
118
+ };
119
+ idMap?: Record<string, object>;
120
+ }>;
121
+ };
90
122
  }
91
123
  export declare const defaultRenderDisplay: (item: unknown) => ReactNode;
92
124
  export interface TagPickerProps {
@@ -1,4 +1,4 @@
1
- import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
1
+ import { CustomJSONSchema7 } from '../types/CustomJSONSchema7';
2
2
  export interface Tag {
3
3
  id: string;
4
4
  name: string;
@@ -1,5 +1,4 @@
1
1
  export interface GetTableDataConfig {
2
- serverUrl: string;
3
2
  in_table: string;
4
3
  limit?: number;
5
4
  offset?: number;
@@ -13,4 +12,4 @@ export interface GetTableResponse {
13
12
  data?: object[];
14
13
  count: number;
15
14
  }
16
- export declare const getTableData: ({ serverUrl, in_table, searching, where, limit, offset, }: GetTableDataConfig) => Promise<any>;
15
+ export declare const getTableData: ({ in_table, searching, where, limit, offset, }: GetTableDataConfig) => Promise<never>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "13.0.1-beta.0",
3
+ "version": "13.0.1-beta.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",