@bsol-oss/react-datatable5 12.0.0-beta.7 → 12.0.0-beta.71

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.
Files changed (53) hide show
  1. package/README.md +192 -0
  2. package/dist/index.d.ts +282 -83
  3. package/dist/index.js +1637 -475
  4. package/dist/index.mjs +1645 -483
  5. package/dist/types/components/DataTable/DataTable.d.ts +3 -1
  6. package/dist/types/components/DataTable/DataTableServer.d.ts +6 -4
  7. package/dist/types/components/DataTable/DefaultTable.d.ts +6 -9
  8. package/dist/types/components/DataTable/context/DataTableContext.d.ts +21 -3
  9. package/dist/types/components/DataTable/context/useDataTableContext.d.ts +2 -2
  10. package/dist/types/components/DataTable/controls/ReloadButton.d.ts +1 -2
  11. package/dist/types/components/DataTable/controls/ResetFilteringButton.d.ts +1 -4
  12. package/dist/types/components/DataTable/controls/ResetSelectionButton.d.ts +1 -4
  13. package/dist/types/components/DataTable/controls/ResetSortingButton.d.ts +1 -4
  14. package/dist/types/components/DataTable/controls/TableControls.d.ts +10 -2
  15. package/dist/types/components/DataTable/display/TableBody.d.ts +1 -2
  16. package/dist/types/components/DataTable/display/TableCardContainer.d.ts +6 -3
  17. package/dist/types/components/DataTable/display/TableDataDisplay.d.ts +6 -1
  18. package/dist/types/components/DataTable/display/TableFooter.d.ts +1 -5
  19. package/dist/types/components/DataTable/display/TableHeader.d.ts +46 -8
  20. package/dist/types/components/DataTable/useDataTableServer.d.ts +55 -3
  21. package/dist/types/components/DatePicker/DatePicker.d.ts +23 -0
  22. package/dist/types/components/DatePicker/DateTimePicker.d.ts +11 -0
  23. package/dist/types/components/DatePicker/DurationPicker.d.ts +12 -0
  24. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +16 -0
  25. package/dist/types/components/DatePicker/PickerDemo.d.ts +1 -0
  26. package/dist/types/components/DatePicker/UniversalPicker.d.ts +9 -0
  27. package/dist/types/components/DatePicker/index.d.ts +7 -0
  28. package/dist/types/components/Filter/TagFilter.d.ts +5 -1
  29. package/dist/types/components/Form/SchemaFormContext.d.ts +8 -1
  30. package/dist/types/components/Form/components/core/DefaultForm.d.ts +1 -0
  31. package/dist/types/components/Form/components/core/FormRoot.d.ts +9 -2
  32. package/dist/types/components/Form/components/fields/CustomInput.d.ts +8 -0
  33. package/dist/types/components/Form/components/fields/DatePicker.d.ts +2 -7
  34. package/dist/types/components/Form/components/fields/DateTimePicker.d.ts +2 -0
  35. package/dist/types/components/Form/components/fields/EnumPicker.d.ts +2 -1
  36. package/dist/types/components/Form/components/fields/FilePicker.d.ts +2 -5
  37. package/dist/types/components/Form/components/fields/StringInputField.d.ts +19 -5
  38. package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +12 -0
  39. package/dist/types/components/Form/components/fields/TimePicker.d.ts +7 -0
  40. package/dist/types/components/Form/components/fields/types.d.ts +6 -0
  41. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +19 -1
  42. package/dist/types/components/Form/components/viewers/CustomViewer.d.ts +8 -0
  43. package/dist/types/components/Form/components/viewers/DateTimeViewer.d.ts +7 -0
  44. package/dist/types/components/Form/components/viewers/TextAreaViewer.d.ts +12 -0
  45. package/dist/types/components/Form/components/viewers/TimeViewer.d.ts +7 -0
  46. package/dist/types/components/Form/utils/translateWrapper.d.ts +6 -0
  47. package/dist/types/components/Form/utils/useFormI18n.d.ts +53 -0
  48. package/dist/types/components/Form/utils/validateData.d.ts +9 -0
  49. package/dist/types/components/Form/utils/validation.d.ts +104 -0
  50. package/dist/types/components/TextArea/TextArea.d.ts +22 -0
  51. package/dist/types/components/TimePicker/TimePicker.d.ts +21 -0
  52. package/dist/types/index.d.ts +18 -2
  53. package/package.json +9 -2
package/dist/index.js CHANGED
@@ -29,7 +29,12 @@ var gr = require('react-icons/gr');
29
29
  var reactI18next = require('react-i18next');
30
30
  var axios = require('axios');
31
31
  var reactHookForm = require('react-hook-form');
32
+ var Ajv = require('ajv');
33
+ var addFormats = require('ajv-formats');
34
+ var addErrors = require('ajv-errors');
32
35
  var dayjs = require('dayjs');
36
+ var utc = require('dayjs/plugin/utc');
37
+ var timezone = require('dayjs/plugin/timezone');
33
38
  var ti = require('react-icons/ti');
34
39
 
35
40
  function _interopNamespaceDefault(e) {
@@ -57,6 +62,56 @@ const DataTableContext = React.createContext({
57
62
  setGlobalFilter: () => { },
58
63
  type: "client",
59
64
  translate: {},
65
+ data: [],
66
+ columns: [],
67
+ columnOrder: [],
68
+ columnFilters: [],
69
+ density: "sm",
70
+ sorting: [],
71
+ setPagination: function () {
72
+ throw new Error("Function not implemented.");
73
+ },
74
+ setSorting: function () {
75
+ throw new Error("Function not implemented.");
76
+ },
77
+ setColumnFilters: function () {
78
+ throw new Error("Function not implemented.");
79
+ },
80
+ setRowSelection: function () {
81
+ throw new Error("Function not implemented.");
82
+ },
83
+ setColumnOrder: function () {
84
+ throw new Error("Function not implemented.");
85
+ },
86
+ setDensity: function () {
87
+ throw new Error("Function not implemented.");
88
+ },
89
+ setColumnVisibility: function () {
90
+ throw new Error("Function not implemented.");
91
+ },
92
+ pagination: {
93
+ pageIndex: 0,
94
+ pageSize: 10,
95
+ },
96
+ rowSelection: {},
97
+ columnVisibility: {},
98
+ tableLabel: {
99
+ view: "View",
100
+ edit: "Edit",
101
+ filterButtonText: "Filter",
102
+ filterTitle: "Filter",
103
+ filterReset: "Reset",
104
+ filterClose: "Close",
105
+ reloadTooltip: "Reload",
106
+ reloadButtonText: "Reload",
107
+ resetSelection: "Reset Selection",
108
+ resetSorting: "Reset Sorting",
109
+ rowCountText: "Row Count",
110
+ hasErrorText: "Has Error",
111
+ globalFilterPlaceholder: "Search",
112
+ trueLabel: "True",
113
+ falseLabel: "False",
114
+ },
60
115
  });
61
116
 
62
117
  const useDataTableContext = () => {
@@ -112,11 +167,13 @@ const TableSorter = () => {
112
167
  }) }))) }));
113
168
  };
114
169
 
115
- const ResetSortingButton = ({ text = "Reset Sorting", }) => {
170
+ const ResetSortingButton = () => {
116
171
  const { table } = useDataTableContext();
172
+ const { tableLabel } = useDataTableContext();
173
+ const { resetSorting } = tableLabel;
117
174
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
118
175
  table.resetSorting();
119
- }, children: text }));
176
+ }, children: resetSorting }));
120
177
  };
121
178
 
122
179
  const EditSortingButton = ({ text, icon = jsxRuntime.jsx(md.MdOutlineSort, {}), title = "Edit Sorting", }) => {
@@ -144,7 +201,7 @@ const monthNamesFull = [
144
201
  "November",
145
202
  "December",
146
203
  ];
147
- const weekdayNamesShort$1 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
204
+ const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
148
205
  function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, selected = [], firstDayOfWeek = 0, }) {
149
206
  const [hoveredDate, setHoveredDate] = React.useState();
150
207
  const onMouseLeave = () => {
@@ -179,7 +236,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
179
236
  offset: 12,
180
237
  }), children: ">>" })] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", gap: 4, children: calendars.map((calendar) => (jsxRuntime.jsxs(react.Grid, { gap: 4, children: [jsxRuntime.jsxs(react.Grid, { justifyContent: "center", children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
181
238
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
182
- return (jsxRuntime.jsx(react.Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort$1[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
239
+ return (jsxRuntime.jsx(react.Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
183
240
  }) }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
184
241
  const key = `${calendar.month}${calendar.year}${windex}${index}`;
185
242
  if (!dateObj) {
@@ -300,8 +357,17 @@ const Tag = React__namespace.forwardRef(function Tag(props, ref) {
300
357
  return (jsxRuntime.jsxs(react.Tag.Root, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.Tag.StartElement, { children: startElement })), jsxRuntime.jsx(react.Tag.Label, { children: children }), endElement && (jsxRuntime.jsx(react.Tag.EndElement, { children: endElement })), closable && (jsxRuntime.jsx(react.Tag.EndElement, { children: jsxRuntime.jsx(react.Tag.CloseTrigger, { onClick: onClose }) }))] }));
301
358
  });
302
359
 
303
- const TagFilter = ({ availableTags, selectedTags, onTagChange, }) => {
360
+ const TagFilter = ({ availableTags, selectedTags, onTagChange, selectOne = false, }) => {
304
361
  const toggleTag = (tag) => {
362
+ if (selectOne) {
363
+ if (selectedTags.includes(tag)) {
364
+ onTagChange([]);
365
+ }
366
+ else {
367
+ onTagChange([tag]);
368
+ }
369
+ return;
370
+ }
305
371
  if (selectedTags.includes(tag)) {
306
372
  onTagChange(selectedTags.filter((t) => t !== tag));
307
373
  }
@@ -309,10 +375,14 @@ const TagFilter = ({ availableTags, selectedTags, onTagChange, }) => {
309
375
  onTagChange([...selectedTags, tag]);
310
376
  }
311
377
  };
312
- return (jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => (jsxRuntime.jsx(Tag, { variant: selectedTags.includes(tag) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(tag) ? true : undefined, onClick: () => toggleTag(tag), children: tag }))) }));
378
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => {
379
+ const { label, value } = tag;
380
+ return (jsxRuntime.jsx(Tag, { variant: selectedTags.includes(value) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(value) ? true : undefined, onClick: () => toggleTag(value), children: label ?? value }));
381
+ }) }));
313
382
  };
314
383
 
315
384
  const Filter = ({ column }) => {
385
+ const { tableLabel } = useDataTableContext();
316
386
  const { filterVariant } = column.columnDef.meta ?? {};
317
387
  const displayName = column.columnDef.meta?.displayName ?? column.id;
318
388
  const filterOptions = column.columnDef.meta?.filterOptions ?? [];
@@ -327,10 +397,14 @@ const Filter = ({ column }) => {
327
397
  if (filterVariant === "select") {
328
398
  return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onValueChange: (details) => {
329
399
  column.setFilterValue(details.value);
330
- }, children: jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: "0.5rem", children: filterOptions.map((item) => (jsxRuntime.jsx(Radio, { value: item, children: item }, item))) }) })] }, column.id));
400
+ }, children: jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: "0.5rem", children: [filterOptions.length === 0 && jsxRuntime.jsx(react.Text, { children: "No filter options" }), filterOptions.length > 0 &&
401
+ filterOptions.map((item) => (jsxRuntime.jsx(Radio, { value: item.value, children: item.label }, item.value)))] }) })] }, column.id));
331
402
  }
332
403
  if (filterVariant === "tag") {
333
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: filterOptions, selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
404
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
405
+ label: item.label,
406
+ value: item.value,
407
+ })), selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
334
408
  if (tags.length === 0) {
335
409
  return column.setFilterValue(undefined);
336
410
  }
@@ -338,7 +412,11 @@ const Filter = ({ column }) => {
338
412
  } })] }, column.id));
339
413
  }
340
414
  if (filterVariant === "boolean") {
341
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: ["true", "false"], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
415
+ const { trueLabel, falseLabel } = tableLabel;
416
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: [
417
+ { label: trueLabel, value: "true" },
418
+ { label: falseLabel, value: "false" },
419
+ ], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
342
420
  if (tags.length === 0) {
343
421
  return column.setFilterValue(undefined);
344
422
  }
@@ -393,17 +471,20 @@ const TableFilter = () => {
393
471
  }) }));
394
472
  };
395
473
 
396
- const ResetFilteringButton = ({ text = "Reset Filtering", }) => {
474
+ const ResetFilteringButton = () => {
397
475
  const { table } = useDataTableContext();
476
+ const { tableLabel } = useDataTableContext();
477
+ const { filterReset } = tableLabel;
398
478
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
399
479
  table.resetColumnFilters();
400
- }, children: text }));
480
+ }, children: filterReset }));
401
481
  };
402
482
 
403
483
  const FilterDialog = ({ icon = jsxRuntime.jsx(md.MdFilterAlt, {}), }) => {
404
484
  const filterModal = react.useDisclosure();
405
- const { translate } = useDataTableContext();
406
- return (jsxRuntime.jsxs(DialogRoot, { size: ["full", "full", "md", "md"], open: filterModal.open, children: [jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { as: react.Box, variant: "ghost", onClick: filterModal.onOpen, children: [icon, " ", translate.t("filterDialog.buttonText")] }) }), jsxRuntime.jsxs(DialogContent, { children: [jsxRuntime.jsx(DialogHeader, { children: jsxRuntime.jsx(DialogTitle, { children: translate.t("filterDialog.title") }) }), jsxRuntime.jsx(DialogBody, { display: "flex", flexFlow: "column", children: jsxRuntime.jsx(TableFilter, {}) }), jsxRuntime.jsxs(DialogFooter, { children: [jsxRuntime.jsx(ResetFilteringButton, { text: translate.t("filterDialog.reset") }), jsxRuntime.jsx(react.Button, { onClick: filterModal.onClose, variant: "subtle", children: translate.t("filterDialog.close") })] }), jsxRuntime.jsx(DialogCloseTrigger, { onClick: filterModal.onClose })] })] }));
485
+ const { tableLabel } = useDataTableContext();
486
+ const { filterButtonText, filterTitle, filterClose } = tableLabel;
487
+ return (jsxRuntime.jsxs(DialogRoot, { size: ["full", "full", "md", "md"], open: filterModal.open, children: [jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { as: react.Box, variant: "ghost", onClick: filterModal.onOpen, children: [icon, " ", filterButtonText] }) }), jsxRuntime.jsxs(DialogContent, { children: [jsxRuntime.jsx(DialogHeader, { children: jsxRuntime.jsx(DialogTitle, { children: filterTitle }) }), jsxRuntime.jsx(DialogBody, { display: "flex", flexFlow: "column", children: jsxRuntime.jsx(TableFilter, {}) }), jsxRuntime.jsxs(DialogFooter, { children: [jsxRuntime.jsx(ResetFilteringButton, {}), jsxRuntime.jsx(react.Button, { onClick: filterModal.onClose, variant: "subtle", children: filterClose })] }), jsxRuntime.jsx(DialogCloseTrigger, { onClick: filterModal.onClose })] })] }));
407
488
  };
408
489
 
409
490
  const MenuContent = React__namespace.forwardRef(function MenuContent(props, ref) {
@@ -522,11 +603,13 @@ const Pagination = () => {
522
603
  }, children: jsxRuntime.jsxs(react.HStack, { children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), jsxRuntime.jsx(PaginationItems, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) }));
523
604
  };
524
605
 
525
- const ResetSelectionButton = ({ text = "Reset Selection", }) => {
606
+ const ResetSelectionButton = () => {
526
607
  const { table } = useDataTableContext();
608
+ const { tableLabel } = useDataTableContext();
609
+ const { resetSelection } = tableLabel;
527
610
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
528
611
  table.resetRowSelection();
529
- }, children: text }));
612
+ }, children: resetSelection }));
530
613
  };
531
614
 
532
615
  const RowCountText = () => {
@@ -2441,8 +2524,8 @@ react.CheckboxCard.Indicator;
2441
2524
  function ColumnCard({ columnId }) {
2442
2525
  const ref = React.useRef(null);
2443
2526
  const [dragging, setDragging] = React.useState(false); // NEW
2444
- const { table } = useDataTableContext();
2445
- const displayName = columnId;
2527
+ const { table, translate } = useDataTableContext();
2528
+ const displayName = translate.t(columnId);
2446
2529
  const column = table.getColumn(columnId);
2447
2530
  invariant(column);
2448
2531
  React.useEffect(() => {
@@ -2457,7 +2540,7 @@ function ColumnCard({ columnId }) {
2457
2540
  onDrop: () => setDragging(false), // NEW
2458
2541
  });
2459
2542
  }, [columnId, table]);
2460
- return (jsxRuntime.jsxs(react.Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsxRuntime.jsx(react.Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsxRuntime.jsx(fa6.FaGripLinesVertical, { color: "gray.400" }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "space-between", alignItems: "center", children: jsxRuntime.jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2543
+ return (jsxRuntime.jsxs(react.Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsxRuntime.jsx(react.Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsxRuntime.jsx(fa6.FaGripLinesVertical, { color: "colorPalette.400" }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "space-between", alignItems: "center", children: jsxRuntime.jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2461
2544
  }
2462
2545
  function CardContainer({ location, children }) {
2463
2546
  const ref = React.useRef(null);
@@ -2476,7 +2559,6 @@ function CardContainer({ location, children }) {
2476
2559
  onDrop: () => setIsDraggedOver(false),
2477
2560
  });
2478
2561
  }, [location]);
2479
- // const isDark = (location + location) % 2 === 1;
2480
2562
  function getColor(isDraggedOver) {
2481
2563
  if (isDraggedOver) {
2482
2564
  return {
@@ -2486,7 +2568,6 @@ function CardContainer({ location, children }) {
2486
2568
  },
2487
2569
  };
2488
2570
  }
2489
- // return isDark ? "lightgrey" : "white";
2490
2571
  return {
2491
2572
  backgroundColor: undefined,
2492
2573
  _dark: {
@@ -2537,8 +2618,9 @@ const TableViewer = () => {
2537
2618
 
2538
2619
  const ViewDialog = ({ icon = jsxRuntime.jsx(io.IoMdEye, {}) }) => {
2539
2620
  const viewModel = react.useDisclosure();
2540
- const { translate } = useDataTableContext();
2541
- return (jsxRuntime.jsxs(DialogRoot, { children: [jsxRuntime.jsx(react.DialogBackdrop, {}), jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { as: react.Box, variant: "ghost", onClick: viewModel.onOpen, children: [icon, " ", translate.t("viewDialog.buttonText")] }) }), jsxRuntime.jsxs(DialogContent, { children: [jsxRuntime.jsx(DialogCloseTrigger, {}), jsxRuntime.jsx(DialogHeader, { children: jsxRuntime.jsx(DialogTitle, { children: translate.t("viewDialog.title") }) }), jsxRuntime.jsx(DialogBody, { children: jsxRuntime.jsx(TableViewer, {}) }), jsxRuntime.jsx(DialogFooter, {})] })] }));
2621
+ const { tableLabel } = useDataTableContext();
2622
+ const { view } = tableLabel;
2623
+ return (jsxRuntime.jsxs(DialogRoot, { children: [jsxRuntime.jsx(react.DialogBackdrop, {}), jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { as: react.Box, variant: "ghost", onClick: viewModel.onOpen, children: [icon, " ", view] }) }), jsxRuntime.jsxs(DialogContent, { children: [jsxRuntime.jsx(DialogCloseTrigger, {}), jsxRuntime.jsx(DialogHeader, { children: jsxRuntime.jsx(DialogTitle, { children: view }) }), jsxRuntime.jsx(DialogBody, { children: jsxRuntime.jsx(TableViewer, {}) }), jsxRuntime.jsx(DialogFooter, {})] })] }));
2542
2624
  };
2543
2625
 
2544
2626
  const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
@@ -2589,7 +2671,7 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
2589
2671
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "null" });
2590
2672
  }
2591
2673
  return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
2592
- return (jsxRuntime.jsxs(react.Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsxRuntime.jsx(react.Text, { color: "gray.400", children: getColumn({ field }) }), typeof value === "object" ? (jsxRuntime.jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsxRuntime.jsx(react.Text, { children: JSON.stringify(value) }))] }, field));
2674
+ return (jsxRuntime.jsxs(react.Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsxRuntime.jsx(react.Text, { color: "colorPalette.400", children: getColumn({ field }) }), typeof value === "object" ? (jsxRuntime.jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsxRuntime.jsx(react.Text, { children: JSON.stringify(value) }))] }, field));
2593
2675
  }) }));
2594
2676
  };
2595
2677
 
@@ -2639,7 +2721,7 @@ const CellRenderer = ({ cell }) => {
2639
2721
  paddingY: 2,
2640
2722
  }, object: value })] }, cell.id));
2641
2723
  }
2642
- return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: 'gray.400', children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
2724
+ return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
2643
2725
  };
2644
2726
  const DataDisplay = ({ variant = "" }) => {
2645
2727
  const { table, translate } = useDataTableContext();
@@ -2761,7 +2843,23 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
2761
2843
  *
2762
2844
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
2763
2845
  */
2764
- function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, translate, children, }) {
2846
+ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, translate, children, tableLabel = {
2847
+ view: "View",
2848
+ edit: "Edit",
2849
+ filterButtonText: "Filter",
2850
+ filterTitle: "Filter",
2851
+ filterReset: "Reset",
2852
+ filterClose: "Close",
2853
+ reloadTooltip: "Reload",
2854
+ reloadButtonText: "Reload",
2855
+ resetSelection: "Reset Selection",
2856
+ resetSorting: "Reset Sorting",
2857
+ rowCountText: "Row Count",
2858
+ hasErrorText: "Has Error",
2859
+ globalFilterPlaceholder: "Search",
2860
+ trueLabel: "True",
2861
+ falseLabel: "False",
2862
+ }, }) {
2765
2863
  const table = reactTable.useReactTable({
2766
2864
  _features: [DensityFeature],
2767
2865
  data: data,
@@ -2814,7 +2912,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
2814
2912
  setGlobalFilter,
2815
2913
  type: "client",
2816
2914
  translate,
2817
- columns,
2915
+ columns: columns,
2818
2916
  sorting,
2819
2917
  setSorting,
2820
2918
  columnFilters,
@@ -2829,6 +2927,8 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
2829
2927
  setDensity,
2830
2928
  columnVisibility,
2831
2929
  setColumnVisibility,
2930
+ data,
2931
+ tableLabel,
2832
2932
  }, children: children }));
2833
2933
  }
2834
2934
 
@@ -2843,10 +2943,26 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
2843
2943
  *
2844
2944
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
2845
2945
  */
2846
- function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, }) {
2946
+ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel = {
2947
+ view: "View",
2948
+ edit: "Edit",
2949
+ filterButtonText: "Filter",
2950
+ filterTitle: "Filter",
2951
+ filterReset: "Reset",
2952
+ filterClose: "Close",
2953
+ reloadTooltip: "Reload",
2954
+ reloadButtonText: "Reload",
2955
+ resetSelection: "Reset Selection",
2956
+ resetSorting: "Reset Sorting",
2957
+ rowCountText: "Row Count",
2958
+ hasErrorText: "Has Error",
2959
+ globalFilterPlaceholder: "Search",
2960
+ trueLabel: "True",
2961
+ falseLabel: "False",
2962
+ }, }) {
2847
2963
  const table = reactTable.useReactTable({
2848
2964
  _features: [DensityFeature],
2849
- data: query.data?.data ?? [],
2965
+ data: (query.data?.data ?? []),
2850
2966
  rowCount: query.data?.count ?? 0,
2851
2967
  columns: columns,
2852
2968
  getCoreRowModel: reactTable.getCoreRowModel(),
@@ -2892,12 +3008,12 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
2892
3008
  // for tanstack-table ts bug end
2893
3009
  });
2894
3010
  return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
2895
- table: { ...table },
3011
+ table: table,
2896
3012
  globalFilter,
2897
3013
  setGlobalFilter,
2898
3014
  type: "server",
2899
3015
  translate,
2900
- columns,
3016
+ columns: columns,
2901
3017
  sorting,
2902
3018
  setSorting,
2903
3019
  columnFilters,
@@ -2912,98 +3028,11 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
2912
3028
  setDensity,
2913
3029
  columnVisibility,
2914
3030
  setColumnVisibility,
3031
+ data: query.data?.data ?? [],
3032
+ tableLabel,
2915
3033
  }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
2916
3034
  }
2917
3035
 
2918
- const Checkbox = React__namespace.forwardRef(function Checkbox(props, ref) {
2919
- const { icon, children, inputProps, rootRef, ...rest } = props;
2920
- return (jsxRuntime.jsxs(react.Checkbox.Root, { ref: rootRef, ...rest, children: [jsxRuntime.jsx(react.Checkbox.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsx(react.Checkbox.Control, { children: icon || jsxRuntime.jsx(react.Checkbox.Indicator, {}) }), children != null && (jsxRuntime.jsx(react.Checkbox.Label, { children: children }))] }));
2921
- });
2922
-
2923
- const TableBody = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, alwaysShowSelector = true, canResize = true, }) => {
2924
- "use no memo";
2925
- const { table } = useDataTableContext();
2926
- const SELECTION_BOX_WIDTH = 20;
2927
- const [hoveredRow, setHoveredRow] = React.useState(-1);
2928
- const handleRowHover = (index) => {
2929
- setHoveredRow(index);
2930
- };
2931
- const getTdProps = (cell) => {
2932
- const tdProps = cell.column.getIsPinned()
2933
- ? {
2934
- left: showSelector
2935
- ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
2936
- : `${cell.column.getStart("left")}px`,
2937
- background: pinnedBgColor.light,
2938
- position: "sticky",
2939
- zIndex: -1,
2940
- _dark: {
2941
- backgroundColor: pinnedBgColor.dark,
2942
- },
2943
- }
2944
- : {};
2945
- return tdProps;
2946
- };
2947
- const getTrProps = ({ hoveredRow, index, }) => {
2948
- if (hoveredRow === -1) {
2949
- return {};
2950
- }
2951
- if (hoveredRow === index) {
2952
- return {
2953
- opacity: "1",
2954
- };
2955
- }
2956
- return {
2957
- opacity: "0.8",
2958
- };
2959
- };
2960
- return (jsxRuntime.jsx(react.Table.Body, { children: table.getRowModel().rows.map((row, index) => {
2961
- return (jsxRuntime.jsxs(react.Table.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsxRuntime.jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow, alwaysShowSelector: alwaysShowSelector })), row.getVisibleCells().map((cell, index) => {
2962
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
2963
- // styling resize and pinning start
2964
- flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`, backgroundColor: "white", ...getTdProps(cell), _dark: {
2965
- backgroundColor: "gray.950",
2966
- }, children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
2967
- })] }, `chakra-table-row-${row.id}`));
2968
- }) }));
2969
- };
2970
- const TableRowSelector = ({ index, row, hoveredRow, pinnedBgColor = { light: "gray.50", dark: "gray.700" }, alwaysShowSelector = true, }) => {
2971
- const { table } = useDataTableContext();
2972
- const SELECTION_BOX_WIDTH = 20;
2973
- const isCheckBoxVisible = (current_index, current_row) => {
2974
- if (alwaysShowSelector) {
2975
- return true;
2976
- }
2977
- if (current_row.getIsSelected()) {
2978
- return true;
2979
- }
2980
- if (hoveredRow == current_index) {
2981
- return true;
2982
- }
2983
- return false;
2984
- };
2985
- return (jsxRuntime.jsxs(react.Table.Cell, { padding: `${table.getDensityValue()}px`, ...(table.getIsSomeColumnsPinned("left")
2986
- ? {
2987
- left: `0px`,
2988
- backgroundColor: pinnedBgColor.light,
2989
- position: "sticky",
2990
- zIndex: 1,
2991
- _dark: { backgroundColor: pinnedBgColor.dark },
2992
- }
2993
- : {}),
2994
- // styling resize and pinning end
2995
- display: "grid", children: [!isCheckBoxVisible(index, row) && (jsxRuntime.jsx(react.Box, { as: "span", margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` })), isCheckBoxVisible(index, row) && (jsxRuntime.jsx(react.Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: row.getIsSelected(),
2996
- disabled: !row.getCanSelect(),
2997
- onChange: row.getToggleSelectedHandler() }) }))] }));
2998
- };
2999
-
3000
- const Tooltip = React__namespace.forwardRef(function Tooltip(props, ref) {
3001
- const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
3002
- if (disabled)
3003
- return children;
3004
- return (jsxRuntime.jsxs(react.Tooltip.Root, { ...rest, children: [jsxRuntime.jsx(react.Tooltip.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Tooltip.Positioner, { children: jsxRuntime.jsxs(react.Tooltip.Content, { ref: ref, ...contentProps, children: [showArrow && (jsxRuntime.jsx(react.Tooltip.Arrow, { children: jsxRuntime.jsx(react.Tooltip.ArrowTip, {}) })), content] }) }) })] }));
3005
- });
3006
-
3007
3036
  const InputGroup = React__namespace.forwardRef(function InputGroup(props, ref) {
3008
3037
  const { startElement, startElementProps, endElement, endElementProps, children, startOffset = "6px", endOffset = "6px", ...rest } = props;
3009
3038
  return (jsxRuntime.jsxs(react.Group, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.InputElement, { pointerEvents: "none", ...startElementProps, children: startElement })), React__namespace.cloneElement(children, {
@@ -3017,7 +3046,8 @@ const InputGroup = React__namespace.forwardRef(function InputGroup(props, ref) {
3017
3046
  });
3018
3047
 
3019
3048
  const GlobalFilter = () => {
3020
- const { table } = useDataTableContext();
3049
+ const { table, tableLabel } = useDataTableContext();
3050
+ const { globalFilterPlaceholder } = tableLabel;
3021
3051
  const [searchTerm, setSearchTerm] = React.useState("");
3022
3052
  const debouncedSearchTerm = usehooks.useDebounce(searchTerm, 500);
3023
3053
  React.useEffect(() => {
@@ -3026,42 +3056,31 @@ const GlobalFilter = () => {
3026
3056
  };
3027
3057
  searchHN();
3028
3058
  }, [debouncedSearchTerm]);
3029
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(InputGroup, { flex: "1", startElement: jsxRuntime.jsx(md.MdSearch, {}), children: jsxRuntime.jsx(react.Input, { placeholder: "Outline", variant: "outline", onChange: (e) => {
3059
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(InputGroup, { flex: "1", startElement: jsxRuntime.jsx(md.MdSearch, {}), children: jsxRuntime.jsx(react.Input, { placeholder: globalFilterPlaceholder, variant: "outline", onChange: (e) => {
3030
3060
  setSearchTerm(e.target.value);
3031
3061
  } }) }) }));
3032
3062
  };
3033
3063
 
3034
- const ReloadButton = ({ text = "Reload", variant = "icon", }) => {
3064
+ const Tooltip = React__namespace.forwardRef(function Tooltip(props, ref) {
3065
+ const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
3066
+ if (disabled)
3067
+ return children;
3068
+ return (jsxRuntime.jsxs(react.Tooltip.Root, { ...rest, children: [jsxRuntime.jsx(react.Tooltip.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Tooltip.Positioner, { children: jsxRuntime.jsxs(react.Tooltip.Content, { ref: ref, ...contentProps, children: [showArrow && (jsxRuntime.jsx(react.Tooltip.Arrow, { children: jsxRuntime.jsx(react.Tooltip.ArrowTip, {}) })), content] }) }) })] }));
3069
+ });
3070
+
3071
+ const ReloadButton = ({ variant = "icon", }) => {
3035
3072
  const { url } = useDataTableServerContext();
3036
3073
  const queryClient = reactQuery.useQueryClient();
3074
+ const { tableLabel } = useDataTableContext();
3075
+ const { reloadTooltip, reloadButtonText } = tableLabel;
3037
3076
  if (variant === "icon") {
3038
- return (jsxRuntime.jsx(Tooltip, { showArrow: true, content: "This is the tooltip content", children: jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => {
3077
+ return (jsxRuntime.jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => {
3039
3078
  queryClient.invalidateQueries({ queryKey: [url] });
3040
3079
  }, "aria-label": "refresh", children: jsxRuntime.jsx(io5.IoReload, {}) }) }));
3041
3080
  }
3042
3081
  return (jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3043
3082
  queryClient.invalidateQueries({ queryKey: [url] });
3044
- }, children: [jsxRuntime.jsx(io5.IoReload, {}), " ", text] }));
3045
- };
3046
-
3047
- const FilterOptions = ({ column }) => {
3048
- const { table } = useDataTableContext();
3049
- const tableColumn = table.getColumn(column);
3050
- const options = tableColumn?.columnDef.meta?.filterOptions ?? [];
3051
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: options.map((option) => {
3052
- const selected = table.getColumn(column)?.getFilterValue() === option;
3053
- return (jsxRuntime.jsxs(react.Button, { size: "sm", onClick: () => {
3054
- if (selected) {
3055
- table.setColumnFilters((state) => {
3056
- return state.filter((filter) => {
3057
- return filter.id !== column;
3058
- });
3059
- });
3060
- return;
3061
- }
3062
- table.getColumn(column)?.setFilterValue(option);
3063
- }, variant: selected ? "solid" : "outline", display: "flex", gap: "0.25rem", children: [option, selected && jsxRuntime.jsx(md.MdClose, {})] }, option));
3064
- }) }));
3083
+ }, children: [jsxRuntime.jsx(io5.IoReload, {}), " ", reloadButtonText] }));
3065
3084
  };
3066
3085
 
3067
3086
  const TableFilterTags = () => {
@@ -3075,16 +3094,99 @@ const TableFilterTags = () => {
3075
3094
  }) }));
3076
3095
  };
3077
3096
 
3078
- const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, }) => {
3079
- const { translate } = useDataTableContext();
3080
- return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto 1fr auto", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", children: [jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsxRuntime.jsx(react.Spinner, { size: "sm" }), hasError && (jsxRuntime.jsx(Tooltip, { content: translate.t("hasError"), children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.5rem", children: filterOptions.map((column) => {
3081
- return (jsxRuntime.jsxs(react.Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [showFilterName && jsxRuntime.jsxs(react.Text, { children: [column, ":"] }), jsxRuntime.jsx(FilterOptions, { column: column })] }, column));
3082
- }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { overflow: "auto", backgroundColor: "gray.50", _dark: {
3083
- backgroundColor: "gray.900",
3084
- }, children: children }), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsxs(react.Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && (jsxRuntime.jsxs(react.Flex, { children: [jsxRuntime.jsx(react.Text, { paddingRight: "0.5rem", children: translate.t("rowcount.total") }), jsxRuntime.jsx(RowCountText, {})] }))] }), jsxRuntime.jsx(react.Box, { justifySelf: "end", children: showPagination && jsxRuntime.jsx(Pagination, {}) })] })] }));
3097
+ const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
3098
+ const { tableLabel, table } = useDataTableContext();
3099
+ const { rowCountText, hasErrorText } = tableLabel;
3100
+ return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsxRuntime.jsx(react.Spinner, { size: "sm" }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
3101
+ const { column, options } = option;
3102
+ const tableColumn = table.getColumn(column);
3103
+ return (jsxRuntime.jsxs(react.Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
3104
+ if (tags.length === 0) {
3105
+ return tableColumn?.setFilterValue(undefined);
3106
+ }
3107
+ tableColumn?.setFilterValue(tags);
3108
+ } })] }, column));
3109
+ }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsxs(react.Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && (jsxRuntime.jsxs(react.Flex, { children: [jsxRuntime.jsx(react.Text, { paddingRight: "0.5rem", children: rowCountText }), jsxRuntime.jsx(RowCountText, {})] }))] }), jsxRuntime.jsx(react.Box, { justifySelf: "end", children: showPagination && jsxRuntime.jsx(Pagination, {}) })] }))] }));
3110
+ };
3111
+
3112
+ const EmptyState = React__namespace.forwardRef(function EmptyState(props, ref) {
3113
+ const { title, description, icon, children, ...rest } = props;
3114
+ return (jsxRuntime.jsx(react.EmptyState.Root, { ref: ref, ...rest, children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [icon && (jsxRuntime.jsx(react.EmptyState.Indicator, { children: icon })), description ? (jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })) : (jsxRuntime.jsx(react.EmptyState.Title, { children: title })), children] }) }));
3115
+ });
3116
+
3117
+ const EmptyResult = (jsxRuntime.jsx(EmptyState, { icon: jsxRuntime.jsx(hi.HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxRuntime.jsxs(react.List.Root, { variant: "marker", children: [jsxRuntime.jsx(react.List.Item, { children: "Try removing filters" }), jsxRuntime.jsx(react.List.Item, { children: "Try different keywords" })] }) }));
3118
+ const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
3119
+ const { table } = useDataTableContext();
3120
+ if (table.getRowModel().rows.length <= 0) {
3121
+ return emptyComponent;
3122
+ }
3123
+ return (jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: "outline", width: canResize ? table.getCenterTotalSize() : undefined, display: "grid", alignContent: "start", overflowY: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...props, children: children }));
3124
+ };
3125
+
3126
+ const Checkbox = React__namespace.forwardRef(function Checkbox(props, ref) {
3127
+ const { icon, children, inputProps, rootRef, ...rest } = props;
3128
+ return (jsxRuntime.jsxs(react.Checkbox.Root, { ref: rootRef, ...rest, children: [jsxRuntime.jsx(react.Checkbox.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsx(react.Checkbox.Control, { children: icon || jsxRuntime.jsx(react.Checkbox.Indicator, {}) }), children != null && (jsxRuntime.jsx(react.Checkbox.Label, { children: children }))] }));
3129
+ });
3130
+
3131
+ const TableBody = ({ showSelector = false, canResize = true, }) => {
3132
+ "use no memo";
3133
+ const { table } = useDataTableContext();
3134
+ const SELECTION_BOX_WIDTH = 20;
3135
+ const [hoveredRow, setHoveredRow] = React.useState(-1);
3136
+ const handleRowHover = (index) => {
3137
+ setHoveredRow(index);
3138
+ };
3139
+ const getTdProps = (cell) => {
3140
+ const tdProps = cell.column.getIsPinned()
3141
+ ? {
3142
+ left: showSelector
3143
+ ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3144
+ : `${cell.column.getStart("left")}px`,
3145
+ position: "relative",
3146
+ }
3147
+ : {};
3148
+ return tdProps;
3149
+ };
3150
+ const getTrProps = ({ hoveredRow, index, }) => {
3151
+ if (hoveredRow === -1) {
3152
+ return {};
3153
+ }
3154
+ if (hoveredRow === index) {
3155
+ return {
3156
+ opacity: "1",
3157
+ };
3158
+ }
3159
+ return {
3160
+ opacity: "0.8",
3161
+ };
3162
+ };
3163
+ return (jsxRuntime.jsx(react.Table.Body, { children: table.getRowModel().rows.map((row, index) => {
3164
+ return (jsxRuntime.jsxs(react.Table.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsxRuntime.jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow })), row.getVisibleCells().map((cell, index) => {
3165
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
3166
+ // styling resize and pinning start
3167
+ flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`,
3168
+ // this is to avoid the cell from being too wide
3169
+ minWidth: `0`, color: {
3170
+ base: "colorPalette.900",
3171
+ _dark: "colorPalette.100",
3172
+ },
3173
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(cell), children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3174
+ })] }, `chakra-table-row-${row.id}`));
3175
+ }) }));
3176
+ };
3177
+ const TableRowSelector = ({ row, }) => {
3178
+ const { table } = useDataTableContext();
3179
+ const SELECTION_BOX_WIDTH = 20;
3180
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
3181
+ base: "colorPalette.900",
3182
+ _dark: "colorPalette.100",
3183
+ },
3184
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: row.getIsSelected(),
3185
+ disabled: !row.getCanSelect(),
3186
+ onCheckedChange: row.getToggleSelectedHandler() }) }));
3085
3187
  };
3086
3188
 
3087
- const TableFooter = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, alwaysShowSelector = true, }) => {
3189
+ const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
3088
3190
  const table = useDataTableContext().table;
3089
3191
  const SELECTION_BOX_WIDTH = 20;
3090
3192
  const [hoveredCheckBox, setHoveredCheckBox] = React.useState(false);
@@ -3103,65 +3205,62 @@ const TableFooter = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, s
3103
3205
  }
3104
3206
  return false;
3105
3207
  };
3106
- const getThProps = (header) => {
3107
- const thProps = header.column.getIsPinned()
3108
- ? {
3109
- left: showSelector
3110
- ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3111
- : `${header.getStart("left") + table.getDensityValue() * 2}px`,
3112
- background: pinnedBgColor.light,
3113
- position: "sticky",
3114
- zIndex: 1,
3115
- _dark: {
3116
- backgroundColor: pinnedBgColor.dark,
3117
- },
3118
- }
3119
- : {};
3120
- return thProps;
3121
- };
3122
- return (jsxRuntime.jsx(react.Table.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: "flex", children: [showSelector && (jsxRuntime.jsxs(react.Table.Header
3123
- // styling resize and pinning start
3124
- , {
3125
- // styling resize and pinning start
3126
- padding: `${table.getDensityValue()}px`, ...(table.getIsSomeColumnsPinned("left")
3127
- ? {
3128
- left: `0px`,
3129
- backgroundColor: pinnedBgColor.light,
3130
- position: "sticky",
3131
- zIndex: 1,
3132
- _dark: { backgroundColor: pinnedBgColor.dark },
3133
- }
3134
- : {}),
3135
- // styling resize and pinning end
3136
- onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsxRuntime.jsx(react.Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3208
+ return (jsxRuntime.jsx(react.Table.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: "flex", children: [showSelector && (jsxRuntime.jsxs(react.Table.Header, { padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsxRuntime.jsx(react.Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3137
3209
  // indeterminate: table.getIsSomeRowsSelected(),
3138
3210
  onChange: table.getToggleAllRowsSelectedHandler() }) })), !isCheckBoxVisible() && (jsxRuntime.jsx(react.Box, { as: "span", margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }))] })), footerGroup.headers.map((header) => (jsxRuntime.jsx(react.Table.Cell, { padding: "0", columnSpan: `${header.colSpan}`,
3139
3211
  // styling resize and pinning start
3140
- maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: "grid", ...getThProps(header), children: jsxRuntime.jsx(react.MenuRoot, { children: jsxRuntime.jsx(react.MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Box, { padding: `${table.getDensityValue()}px`, display: "flex", alignItems: "center", justifyContent: "start", borderRadius: "0rem", _hover: { backgroundColor: "gray.100" }, children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3212
+ maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: "grid", children: jsxRuntime.jsx(react.MenuRoot, { children: jsxRuntime.jsx(react.MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Box, { padding: `${table.getDensityValue()}px`, display: "flex", alignItems: "center", justifyContent: "start", borderRadius: "0rem", children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3141
3213
  ? null
3142
- : reactTable.flexRender(header.column.columnDef.footer, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && (
3143
- // <UpDownIcon />
3144
- jsxRuntime.jsx(jsxRuntime.Fragment, {})), header.column.getIsSorted() === "asc" && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3214
+ : reactTable.flexRender(header.column.columnDef.footer, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && jsxRuntime.jsx(jsxRuntime.Fragment, {}), header.column.getIsSorted() === "asc" && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3145
3215
  };
3146
3216
 
3147
- const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, isSticky = true, alwaysShowSelector = true, tHeadProps = {}, }) => {
3217
+ // Default text values
3218
+ const DEFAULT_HEADER_TEXTS = {
3219
+ pinColumn: "Pin Column",
3220
+ cancelPin: "Cancel Pin",
3221
+ sortAscending: "Sort Ascending",
3222
+ sortDescending: "Sort Descending",
3223
+ clearSorting: "Clear Sorting",
3224
+ };
3225
+ /**
3226
+ * TableHeader component with configurable text strings.
3227
+ *
3228
+ * @example
3229
+ * // Using default texts
3230
+ * <TableHeader />
3231
+ *
3232
+ * @example
3233
+ * // Customizing default texts for all columns
3234
+ * <TableHeader
3235
+ * defaultTexts={{
3236
+ * pinColumn: "Pin This Column",
3237
+ * sortAscending: "Sort A-Z"
3238
+ * }}
3239
+ * />
3240
+ *
3241
+ * @example
3242
+ * // Customizing texts per column via meta
3243
+ * const columns = [
3244
+ * columnHelper.accessor("name", {
3245
+ * header: "Name",
3246
+ * meta: {
3247
+ * headerTexts: {
3248
+ * pinColumn: "Pin Name Column",
3249
+ * sortAscending: "Sort Names A-Z"
3250
+ * }
3251
+ * }
3252
+ * })
3253
+ * ];
3254
+ */
3255
+ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true, tableHeaderProps = {}, tableRowProps = {}, defaultTexts = {}, }) => {
3148
3256
  const { table } = useDataTableContext();
3149
3257
  const SELECTION_BOX_WIDTH = 20;
3150
- const [hoveredCheckBox, setHoveredCheckBox] = React.useState(false);
3151
- const handleRowHover = (isHovered) => {
3152
- setHoveredCheckBox(isHovered);
3153
- };
3154
- const isCheckBoxVisible = () => {
3155
- if (alwaysShowSelector) {
3156
- return true;
3157
- }
3158
- if (table.getIsAllRowsSelected()) {
3159
- return true;
3160
- }
3161
- if (hoveredCheckBox) {
3162
- return true;
3163
- }
3164
- return false;
3258
+ // Merge default texts with provided defaults
3259
+ const mergedDefaultTexts = { ...DEFAULT_HEADER_TEXTS, ...defaultTexts };
3260
+ // Helper function to get text for a specific header
3261
+ const getHeaderText = (header, key) => {
3262
+ const columnMeta = header.column.columnDef.meta;
3263
+ return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3165
3264
  };
3166
3265
  const getThProps = (header) => {
3167
3266
  const thProps = header.column.getIsPinned()
@@ -3169,12 +3268,8 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3169
3268
  left: showSelector
3170
3269
  ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3171
3270
  : `${header.getStart("left")}px`,
3172
- background: pinnedBgColor.light,
3173
3271
  position: "sticky",
3174
3272
  zIndex: 100 + 1,
3175
- _dark: {
3176
- backgroundColor: pinnedBgColor.dark,
3177
- },
3178
3273
  }
3179
3274
  : {};
3180
3275
  return thProps;
@@ -3183,21 +3278,13 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3183
3278
  position: "sticky",
3184
3279
  top: 0,
3185
3280
  };
3186
- return (jsxRuntime.jsx(react.Table.Header, { ...(isSticky ? stickyProps : {}), ...tHeadProps, children: table.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: "flex", children: [showSelector && (jsxRuntime.jsxs(react.Table.ColumnHeader
3187
- // styling resize and pinning start
3188
- , { ...(table.getIsSomeColumnsPinned("left")
3189
- ? {
3190
- left: `0px`,
3191
- backgroundColor: pinnedBgColor.light,
3192
- position: "sticky",
3193
- zIndex: 1,
3194
- _dark: { backgroundColor: pinnedBgColor.dark },
3195
- }
3196
- : {}),
3197
- // styling resize and pinning end
3198
- padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsxRuntime.jsx(react.Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3199
- // indeterminate: table.getIsSomeRowsSelected(),
3200
- onChange: table.getToggleAllRowsSelectedHandler() }) })), !isCheckBoxVisible() && (jsxRuntime.jsx(react.Box, { as: "span", margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }))] })), headerGroup.headers.map((header) => {
3281
+ return (jsxRuntime.jsx(react.Table.Header, { ...(isSticky ? stickyProps : {}), bgColor: "transparent", ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: "flex", bgColor: "transparent", ...tableRowProps, children: [showSelector && (jsxRuntime.jsx(react.Table.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
3282
+ base: "colorPalette.900",
3283
+ _dark: "colorPalette.100",
3284
+ },
3285
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: table.getIsAllRowsSelected(),
3286
+ // indeterminate: table.getIsSomeRowsSelected(),
3287
+ onChange: table.getToggleAllRowsSelectedHandler() }) })), headerGroup.headers.map((header) => {
3201
3288
  const resizeProps = {
3202
3289
  onMouseDown: header.getResizeHandler(),
3203
3290
  onTouchStart: header.getResizeHandler(),
@@ -3205,18 +3292,32 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3205
3292
  };
3206
3293
  return (jsxRuntime.jsxs(react.Table.ColumnHeader, { padding: 0, columnSpan: `${header.colSpan}`,
3207
3294
  // styling resize and pinning start
3208
- flex: `${canResize ? "0" : "1"} 0 ${header.column.getSize()}px`, display: "grid", gridTemplateColumns: "1fr auto", zIndex: 1500 + header.index, ...getThProps(header), children: [jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Flex, { padding: `${table.getDensityValue()}px`, alignItems: "center", justifyContent: "start", borderRadius: "0rem", overflow: "auto", _hover: {
3209
- backgroundColor: "gray.100",
3210
- _dark: {
3211
- backgroundColor: "gray.700",
3295
+ flex: `${canResize ? "0" : "1"} 0 ${header.column.getSize()}px`, display: "grid", gridTemplateColumns: "1fr auto", zIndex: 1500 + header.index, color: {
3296
+ base: "colorPalette.800",
3297
+ _dark: "colorPalette.200",
3298
+ },
3299
+ bg: { base: "colorPalette.100", _dark: "colorPalette.900" }, ...getThProps(header), children: [jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Flex, { padding: `${table.getDensityValue()}px`, alignItems: "center", justifyContent: "start", borderRadius: "0rem", overflow: "auto", color: {
3300
+ base: "colorPalette.800",
3301
+ _dark: "colorPalette.200",
3302
+ _hover: {
3303
+ base: "colorPalette.700",
3304
+ _dark: "colorPalette.300",
3305
+ },
3306
+ },
3307
+ bg: {
3308
+ base: "colorPalette.100",
3309
+ _dark: "colorPalette.900",
3310
+ _hover: {
3311
+ base: "colorPalette.200",
3312
+ _dark: "colorPalette.800",
3212
3313
  },
3213
3314
  }, children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3214
3315
  ? null
3215
3316
  : reactTable.flexRender(header.column.columnDef.header, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && jsxRuntime.jsx(jsxRuntime.Fragment, {}), header.column.getIsSorted() === "asc" && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) }), jsxRuntime.jsx(react.Box, { children: header.column.getIsFiltered() && jsxRuntime.jsx(md.MdFilterListAlt, {}) })] }) }) }), jsxRuntime.jsxs(MenuContent, { children: [!header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "pin-column", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3216
3317
  header.column.pin("left");
3217
- }, children: [jsxRuntime.jsx(md.MdPushPin, {}), "Pin Column"] }) })), header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3318
+ }, children: [jsxRuntime.jsx(md.MdPushPin, {}), getHeaderText(header, "pinColumn")] }) })), header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3218
3319
  header.column.pin(false);
3219
- }, children: [jsxRuntime.jsx(md.MdCancel, {}), "Cancel Pin"] }) })), header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3320
+ }, children: [jsxRuntime.jsx(md.MdCancel, {}), getHeaderText(header, "cancelPin")] }) })), header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3220
3321
  table.setSorting((state) => {
3221
3322
  return [
3222
3323
  ...state.filter((column) => {
@@ -3225,7 +3326,7 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3225
3326
  { id: header.id, desc: false },
3226
3327
  ];
3227
3328
  });
3228
- }, children: [jsxRuntime.jsx(gr.GrAscend, {}), "Sort Ascending"] }) }), jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3329
+ }, children: [jsxRuntime.jsx(gr.GrAscend, {}), getHeaderText(header, "sortAscending")] }) }), jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3229
3330
  table.setSorting((state) => {
3230
3331
  return [
3231
3332
  ...state.filter((column) => {
@@ -3234,42 +3335,30 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3234
3335
  { id: header.id, desc: true },
3235
3336
  ];
3236
3337
  });
3237
- }, children: [jsxRuntime.jsx(gr.GrDescend, {}), "Sort Descending"] }) }), header.column.getIsSorted() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3338
+ }, children: [jsxRuntime.jsx(gr.GrDescend, {}), getHeaderText(header, "sortDescending")] }) }), header.column.getIsSorted() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "clear-sorting", children: jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3238
3339
  header.column.clearSorting();
3239
- }, children: [jsxRuntime.jsx(md.MdClear, {}), "Clear Sorting"] }) }))] }))] })] }), canResize && (jsxRuntime.jsx(react.Box, { borderRight: "0.2rem solid", borderRightColor: header.column.getIsResizing() ? "gray.700" : "transparent", position: "relative", right: "0.1rem", width: "2px", height: "100%", userSelect: "none", style: { touchAction: "none" }, _hover: {
3340
+ }, children: [jsxRuntime.jsx(md.MdClear, {}), getHeaderText(header, "clearSorting")] }) }))] }))] })] }), canResize && (jsxRuntime.jsx(react.Box, { borderRight: "0.2rem solid", borderRightColor: header.column.getIsResizing()
3341
+ ? "colorPalette.700"
3342
+ : "transparent", position: "relative", right: "0.1rem", width: "2px", height: "100%", userSelect: "none", style: { touchAction: "none" }, _hover: {
3240
3343
  borderRightColor: header.column.getIsResizing()
3241
- ? "gray.700"
3242
- : "gray.400",
3344
+ ? "colorPalette.700"
3345
+ : "colorPalette.400",
3243
3346
  }, ...resizeProps }))] }, `chakra-table-header-${header.id}`));
3244
3347
  })] }, `chakra-table-headergroup-${headerGroup.id}`))) }));
3245
3348
  };
3246
3349
 
3247
- const EmptyState = React__namespace.forwardRef(function EmptyState(props, ref) {
3248
- const { title, description, icon, children, ...rest } = props;
3249
- return (jsxRuntime.jsx(react.EmptyState.Root, { ref: ref, ...rest, children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [icon && (jsxRuntime.jsx(react.EmptyState.Indicator, { children: icon })), description ? (jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })) : (jsxRuntime.jsx(react.EmptyState.Title, { children: title })), children] }) }));
3250
- });
3251
-
3252
- const EmptyResult = (jsxRuntime.jsx(EmptyState, { icon: jsxRuntime.jsx(hi.HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxRuntime.jsxs(react.List.Root, { variant: "marker", children: [jsxRuntime.jsx(react.List.Item, { children: "Try removing filters" }), jsxRuntime.jsx(react.List.Item, { children: "Try different keywords" })] }) }));
3253
- const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
3254
- const { table } = useDataTableContext();
3255
- if (table.getRowModel().rows.length <= 0) {
3256
- return emptyComponent;
3257
- }
3258
- return (jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: "outline", width: canResize ? table.getCenterTotalSize() : undefined, display: "grid", alignContent: "start", overflowY: "auto", ...props, children: children }));
3259
- };
3260
-
3261
- const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, controlProps = {}, tableFooterProps = {}, variant = "", }) => {
3350
+ const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = "", }) => {
3262
3351
  if (variant === "greedy") {
3263
3352
  return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { canResize: false, ...{ ...tableProps }, children: [jsxRuntime.jsx(TableHeader, { canResize: false, ...tableHeaderProps }), jsxRuntime.jsx(TableBody, { canResize: false, ...tableBodyProps }), showFooter && (jsxRuntime.jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
3264
3353
  }
3265
3354
  return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { ...tableProps, children: [jsxRuntime.jsx(TableHeader, { ...tableHeaderProps }), jsxRuntime.jsx(TableBody, { ...tableBodyProps }), showFooter && jsxRuntime.jsx(TableFooter, { ...tableFooterProps })] }) }));
3266
3355
  };
3267
3356
 
3268
- const TableCardContainer = ({ children, variant = "", ...props }) => {
3357
+ const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
3269
3358
  if (variant === "carousel") {
3270
- return (jsxRuntime.jsx(react.Flex, { overflow: "scroll", gap: "1rem", children: children }));
3359
+ return (jsxRuntime.jsx(react.Flex, { overflow: "auto", gap: gap, direction: direction, ...props, children: children }));
3271
3360
  }
3272
- return (jsxRuntime.jsx(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(20rem, 1fr))", gap: "0.5rem", ...props, children: children }));
3361
+ return (jsxRuntime.jsx(react.Grid, { gridTemplateColumns: gridTemplateColumns, gap: gap, ...props, children: children }));
3273
3362
  };
3274
3363
 
3275
3364
  const DefaultCardTitle = () => {
@@ -3298,8 +3387,8 @@ const TableComponent = ({ render = () => {
3298
3387
  };
3299
3388
 
3300
3389
  const TableLoadingComponent = ({ render, }) => {
3301
- const { loading } = useDataTableContext();
3302
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(loading) });
3390
+ const { query } = useDataTableServerContext();
3391
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(query.isLoading) });
3303
3392
  };
3304
3393
 
3305
3394
  const SelectAllRowsToggle = ({ selectAllIcon = jsxRuntime.jsx(md.MdOutlineChecklist, {}), clearAllIcon = jsxRuntime.jsx(md.MdClear, {}), selectAllText = "", clearAllText = "", }) => {
@@ -3385,50 +3474,43 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3385
3474
  };
3386
3475
  };
3387
3476
 
3388
- const useDataTableServer = ({ url, default: { sorting: defaultSorting = [], pagination: defaultPagination = {
3389
- pageIndex: 0, //initial page index
3390
- pageSize: 10, //default page size
3391
- }, rowSelection: defaultRowSelection = {}, columnFilters: defaultColumnFilters = [], columnOrder: defaultColumnOrder = [], columnVisibility: defaultColumnVisibility = {}, globalFilter: defaultGlobalFilter = "", density: defaultDensity = "sm", } = {
3392
- sorting: [],
3393
- pagination: {
3477
+ const useDataTableServer = (props) => {
3478
+ const { url, default: defaultProps, keyPrefix, placeholderData, queryFn: customQueryFn, } = props;
3479
+ const { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, } = defaultProps || {};
3480
+ const [sorting, setSorting] = React.useState(defaultSorting || []);
3481
+ const [columnFilters, setColumnFilters] = React.useState(defaultColumnFilters || []); // can set initial column filter state here
3482
+ const [pagination, setPagination] = React.useState(defaultPagination || {
3394
3483
  pageIndex: 0, //initial page index
3395
- pageSize: 10, //age size
3396
- },
3397
- rowSelection: {},
3398
- columnFilters: [],
3399
- columnOrder: [],
3400
- columnVisibility: {},
3401
- globalFilter: "",
3402
- density: "sm",
3403
- }, keyPrefix, }) => {
3404
- const [sorting, setSorting] = React.useState(defaultSorting);
3405
- const [columnFilters, setColumnFilters] = React.useState(defaultColumnFilters); // can set initial column filter state here
3406
- const [pagination, setPagination] = React.useState(defaultPagination);
3407
- const [rowSelection, setRowSelection] = React.useState(defaultRowSelection);
3408
- const [columnOrder, setColumnOrder] = React.useState(defaultColumnOrder);
3409
- const [globalFilter, setGlobalFilter] = React.useState(defaultGlobalFilter);
3410
- const [density, setDensity] = React.useState(defaultDensity);
3411
- const [columnVisibility, setColumnVisibility] = React.useState(defaultColumnVisibility);
3484
+ pageSize: 10, //default page size
3485
+ });
3486
+ const [rowSelection, setRowSelection] = React.useState(defaultRowSelection || {});
3487
+ const [columnOrder, setColumnOrder] = React.useState(defaultColumnOrder || []);
3488
+ const [globalFilter, setGlobalFilter] = React.useState(defaultGlobalFilter || "");
3489
+ const [density, setDensity] = React.useState(defaultDensity || "sm");
3490
+ const [columnVisibility, setColumnVisibility] = React.useState(defaultColumnVisibility || {});
3491
+ const { pageSize, pageIndex } = pagination;
3412
3492
  const params = {
3413
- offset: pagination.pageIndex * pagination.pageSize,
3414
- limit: pagination.pageSize,
3493
+ offset: pageIndex * pageSize,
3494
+ limit: pageSize,
3415
3495
  sorting,
3416
3496
  where: columnFilters,
3417
3497
  searching: globalFilter,
3418
3498
  };
3499
+ const defaultQueryFn = async () => {
3500
+ if (!url) {
3501
+ throw new Error("url is required");
3502
+ }
3503
+ const response = await axios.get(url, {
3504
+ params,
3505
+ });
3506
+ return response.data;
3507
+ };
3419
3508
  const query = reactQuery.useQuery({
3420
3509
  queryKey: [url, JSON.stringify(params)],
3421
- queryFn: () => {
3422
- return axios
3423
- .get(url, {
3424
- params,
3425
- })
3426
- .then((res) => res.data);
3427
- },
3428
- placeholderData: {
3429
- count: 0,
3430
- data: [],
3431
- },
3510
+ queryFn: customQueryFn !== undefined
3511
+ ? () => customQueryFn(params)
3512
+ : defaultQueryFn,
3513
+ placeholderData,
3432
3514
  });
3433
3515
  const translate = reactI18next.useTranslation("", { keyPrefix });
3434
3516
  return {
@@ -3518,7 +3600,71 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3518
3600
  return columns;
3519
3601
  };
3520
3602
 
3521
- const AccordionItemTrigger = React__namespace.forwardRef(function AccordionItemTrigger(props, ref) {
3603
+ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
3604
+ const { columns, translate, data } = useDataTableContext();
3605
+ const columnsMap = Object.fromEntries(columns.map((def) => {
3606
+ const { accessorKey, id } = def;
3607
+ if (accessorKey) {
3608
+ return [accessorKey, def];
3609
+ }
3610
+ return [id, def];
3611
+ }));
3612
+ const columnHeaders = Object.keys(columnsMap);
3613
+ const totalWidths = columns
3614
+ .map(({ size }) => {
3615
+ if (!!size === false) {
3616
+ return 0;
3617
+ }
3618
+ if (typeof size === "number") {
3619
+ return size;
3620
+ }
3621
+ return 0;
3622
+ })
3623
+ .reduce((previous, current) => previous + current, 0);
3624
+ const columnWidths = columns
3625
+ .map(({ size }) => {
3626
+ if (!!size === false) {
3627
+ return "1fr";
3628
+ }
3629
+ return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
3630
+ })
3631
+ .join(" ");
3632
+ console.log({ columnWidths }, "hadfg");
3633
+ const cellProps = {
3634
+ flex: "1 0 0%",
3635
+ overflow: "auto",
3636
+ paddingX: "2",
3637
+ py: "1",
3638
+ color: { base: "colorPalette.900", _dark: "colorPalette.100" },
3639
+ bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
3640
+ borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
3641
+ borderBottomWidth: "1px",
3642
+ ...{ colorPalette },
3643
+ };
3644
+ if (data.length <= 0) {
3645
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyComponent });
3646
+ }
3647
+ return (jsxRuntime.jsxs(react.Grid, { templateColumns: `${columnWidths}`, overflow: "auto", borderWidth: "1px", color: { base: "colorPalette.900", _dark: "colorPalette.100" }, borderColor: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: [jsxRuntime.jsx(react.Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: columnHeaders.map((header) => {
3648
+ return (jsxRuntime.jsx(react.Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
3649
+ }) }), data.map((record) => {
3650
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: columnHeaders.map((header) => {
3651
+ const { cell } = columnsMap[header];
3652
+ const value = record[header];
3653
+ if (!!record === false) {
3654
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
3655
+ }
3656
+ if (cell) {
3657
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }));
3658
+ }
3659
+ if (typeof value === "object") {
3660
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
3661
+ }
3662
+ return jsxRuntime.jsx(react.Box, { ...cellProps, children: value });
3663
+ }) }));
3664
+ })] }));
3665
+ };
3666
+
3667
+ const AccordionItemTrigger = React__namespace.forwardRef(function AccordionItemTrigger(props, ref) {
3522
3668
  const { children, indicatorPlacement = "end", ...rest } = props;
3523
3669
  return (jsxRuntime.jsxs(react.Accordion.ItemTrigger, { ...rest, ref: ref, children: [indicatorPlacement === "start" && (jsxRuntime.jsx(react.Accordion.ItemIndicator, { rotate: { base: "-90deg", _open: "0deg" }, children: jsxRuntime.jsx(lu.LuChevronDown, {}) })), jsxRuntime.jsx(react.HStack, { gap: "4", flex: "1", textAlign: "start", width: "full", children: children }), indicatorPlacement === "end" && (jsxRuntime.jsx(react.Accordion.ItemIndicator, { children: jsxRuntime.jsx(lu.LuChevronDown, {}) }))] }));
3524
3670
  });
@@ -3539,6 +3685,12 @@ const SchemaFormContext = React.createContext({
3539
3685
  onSubmit: async () => { },
3540
3686
  rowNumber: 0,
3541
3687
  requestOptions: {},
3688
+ timezone: 'Asia/Hong_Kong',
3689
+ displayConfig: {
3690
+ showSubmitButton: true,
3691
+ showResetButton: true,
3692
+ showTitle: true,
3693
+ },
3542
3694
  });
3543
3695
 
3544
3696
  const useSchemaContext = () => {
@@ -3549,6 +3701,24 @@ const clearEmptyString = (object) => {
3549
3701
  return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3550
3702
  };
3551
3703
 
3704
+ const validateData = (data, schema) => {
3705
+ const ajv = new Ajv({
3706
+ strict: false,
3707
+ allErrors: true,
3708
+ });
3709
+ addFormats(ajv);
3710
+ addErrors(ajv);
3711
+ const validate = ajv.compile(schema);
3712
+ const validationResult = validate(data);
3713
+ const errors = validate.errors;
3714
+ console.log(errors, data);
3715
+ return {
3716
+ isValid: validationResult,
3717
+ validate,
3718
+ errors,
3719
+ };
3720
+ };
3721
+
3552
3722
  const idPickerSanityCheck = (column, foreign_key) => {
3553
3723
  if (!!foreign_key == false) {
3554
3724
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3564,7 +3734,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
3564
3734
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
3565
3735
  }
3566
3736
  };
3567
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, }) => {
3737
+ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
3738
+ showSubmitButton: true,
3739
+ showResetButton: true,
3740
+ showTitle: true,
3741
+ }, }) => {
3568
3742
  const [isSuccess, setIsSuccess] = React.useState(false);
3569
3743
  const [isError, setIsError] = React.useState(false);
3570
3744
  const [isSubmiting, setIsSubmiting] = React.useState(false);
@@ -3597,11 +3771,13 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3597
3771
  error,
3598
3772
  setError,
3599
3773
  getUpdatedData,
3774
+ customErrorRenderer,
3775
+ displayConfig,
3600
3776
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
3601
3777
  };
3602
3778
 
3603
3779
  function removeIndex(str) {
3604
- return str.replace(/\.\d+\./g, '.');
3780
+ return str.replace(/\.\d+\./g, ".");
3605
3781
  }
3606
3782
 
3607
3783
  const ArrayRenderer = ({ schema, column, prefix, }) => {
@@ -3613,13 +3789,17 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3613
3789
  const isRequired = required?.some((columnId) => columnId === column);
3614
3790
  const { formState: { errors }, setValue, watch, } = reactHookForm.useFormContext();
3615
3791
  const fields = (watch(colLabel) ?? []);
3616
- return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), fields.map((field, index) => (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", children: [jsxRuntime.jsx(react.Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: jsxRuntime.jsx(SchemaRenderer, { column: `${index}`,
3617
- prefix: `${colLabel}.`,
3618
- schema: items }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { variant: "ghost", onClick: () => {
3619
- setValue(colLabel, fields.filter((_, curIndex) => {
3620
- return curIndex === index;
3621
- }));
3622
- }, children: translate.t(removeIndex(`${colLabel}.remove`)) }) })] }, `${colLabel}.${index}`))), jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(react.Button, { onClick: () => {
3792
+ return (jsxRuntime.jsxs(react.Flex, { gridRow, gridColumn, flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 2, children: fields.map((field, index) => (jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
3793
+ base: "colorPalette.200",
3794
+ _dark: "colorPalette.800",
3795
+ }, children: [jsxRuntime.jsx(react.Grid, { gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsxRuntime.jsx(SchemaRenderer, { column: `${index}`,
3796
+ prefix: `${colLabel}.`,
3797
+ // @ts-expect-error find suitable types
3798
+ schema: { showLabel: false, ...(items ?? {}) } }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { variant: "ghost", onClick: () => {
3799
+ setValue(colLabel, fields.filter((_, curIndex) => {
3800
+ return curIndex !== index;
3801
+ }));
3802
+ }, children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(cg.CgTrash, {}) }) }) })] }, `${colLabel}.${index}`))) }), jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(react.Button, { onClick: () => {
3623
3803
  if (type === "number") {
3624
3804
  setValue(colLabel, [...fields, 0]);
3625
3805
  return;
@@ -3633,7 +3813,7 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3633
3813
  return;
3634
3814
  }
3635
3815
  setValue(colLabel, [...fields, {}]);
3636
- }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
3816
+ }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3637
3817
  };
3638
3818
 
3639
3819
  const Field = React__namespace.forwardRef(function Field(props, ref) {
@@ -3644,37 +3824,36 @@ const Field = React__namespace.forwardRef(function Field(props, ref) {
3644
3824
  const BooleanPicker = ({ schema, column, prefix }) => {
3645
3825
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
3646
3826
  const { translate } = useSchemaContext();
3647
- const { required, gridColumn, gridRow } = schema;
3827
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
3648
3828
  const isRequired = required?.some((columnId) => columnId === column);
3649
3829
  const colLabel = `${prefix}${column}`;
3650
3830
  const value = watch(colLabel);
3651
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3831
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3652
3832
  gridRow, children: [jsxRuntime.jsx(CheckboxCard, { checked: value, variant: "surface", onChange: () => {
3653
3833
  setValue(colLabel, !value);
3654
- } }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
3834
+ } }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3835
+ };
3836
+
3837
+ const CustomInput = ({ column, schema, prefix }) => {
3838
+ const formContext = reactHookForm.useFormContext();
3839
+ const { inputRender } = schema;
3840
+ return (inputRender &&
3841
+ inputRender({
3842
+ column,
3843
+ schema,
3844
+ prefix,
3845
+ formContext,
3846
+ }));
3655
3847
  };
3656
3848
 
3657
- const monthNamesShort = [
3658
- "Jan",
3659
- "Feb",
3660
- "Mar",
3661
- "Apr",
3662
- "May",
3663
- "Jun",
3664
- "Jul",
3665
- "Aug",
3666
- "Sep",
3667
- "Oct",
3668
- "Nov",
3669
- "Dec",
3670
- ];
3671
- const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
3672
3849
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
3850
+ const { labels } = React.useContext(DatePickerContext);
3851
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel } = labels;
3673
3852
  if (calendars.length) {
3674
3853
  return (jsxRuntime.jsxs(react.Grid, { children: [jsxRuntime.jsxs(react.Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({
3675
3854
  calendars,
3676
3855
  offset: 12,
3677
- }), children: "<<" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({ calendars }), children: "Back" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({ calendars }), children: "Next" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({
3856
+ }), children: "<<" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({ calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({
3678
3857
  calendars,
3679
3858
  offset: 12,
3680
3859
  }), children: ">>" })] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", children: calendars.map((calendar) => (jsxRuntime.jsxs(react.Grid, { gap: 4, children: [jsxRuntime.jsxs(react.Grid, { justifyContent: "center", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxRuntime.jsxs(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
@@ -3717,9 +3896,52 @@ const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firs
3717
3896
  }
3718
3897
  return null;
3719
3898
  };
3899
+ const DatePickerContext = React.createContext({
3900
+ labels: {
3901
+ monthNamesShort: [
3902
+ "Jan",
3903
+ "Feb",
3904
+ "Mar",
3905
+ "Apr",
3906
+ "May",
3907
+ "Jun",
3908
+ "Jul",
3909
+ "Aug",
3910
+ "Sep",
3911
+ "Oct",
3912
+ "Nov",
3913
+ "Dec",
3914
+ ],
3915
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
3916
+ backButtonLabel: "Back",
3917
+ forwardButtonLabel: "Next",
3918
+ },
3919
+ });
3720
3920
  let DatePicker$1 = class DatePicker extends React.Component {
3721
3921
  render() {
3722
- return (jsxRuntime.jsx(Dayzed, { onDateSelected: this.props.onDateSelected, selected: this.props.selected, firstDayOfWeek: this.props.firstDayOfWeek, showOutsideDays: this.props.showOutsideDays, date: this.props.date, minDate: this.props.minDate, maxDate: this.props.maxDate, monthsToDisplay: this.props.monthsToDisplay, render: (dayzedData) => (jsxRuntime.jsx(Calendar, { ...dayzedData, firstDayOfWeek: this.props.firstDayOfWeek })) }));
3922
+ const { labels = {
3923
+ monthNamesShort: [
3924
+ "Jan",
3925
+ "Feb",
3926
+ "Mar",
3927
+ "Apr",
3928
+ "May",
3929
+ "Jun",
3930
+ "Jul",
3931
+ "Aug",
3932
+ "Sep",
3933
+ "Oct",
3934
+ "Nov",
3935
+ "Dec",
3936
+ ],
3937
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
3938
+ backButtonLabel: "Back",
3939
+ forwardButtonLabel: "Next",
3940
+ }, } = this.props;
3941
+ return (jsxRuntime.jsx(DatePickerContext.Provider, { value: { labels }, children: jsxRuntime.jsx(Dayzed, { onDateSelected: this.props.onDateSelected, selected: this.props.selected, firstDayOfWeek: this.props.firstDayOfWeek, showOutsideDays: this.props.showOutsideDays, date: this.props.date, minDate: this.props.minDate, maxDate: this.props.maxDate, monthsToDisplay: this.props.monthsToDisplay, render:
3942
+ // @ts-expect-error - Dayzed types need to be fixed
3943
+ (dayzedData) => (jsxRuntime.jsx(Calendar, { ...dayzedData,
3944
+ firstDayOfWeek: this.props.firstDayOfWeek })) }) }));
3723
3945
  }
3724
3946
  };
3725
3947
 
@@ -3741,28 +3963,144 @@ const PopoverRoot = react.Popover.Root;
3741
3963
  const PopoverBody = react.Popover.Body;
3742
3964
  const PopoverTrigger = react.Popover.Trigger;
3743
3965
 
3966
+ /**
3967
+ * Custom hook to simplify i18n translation for form fields.
3968
+ * Automatically handles colLabel construction and removeIndex logic.
3969
+ *
3970
+ * @param column - The column name
3971
+ * @param prefix - The prefix for the field (usually empty string or parent path)
3972
+ * @returns Object with translation helper functions
3973
+ *
3974
+ * @example
3975
+ * ```tsx
3976
+ * const formI18n = useFormI18n(column, prefix);
3977
+ *
3978
+ * // Get field label
3979
+ * <Field label={formI18n.label()} />
3980
+ *
3981
+ * // Get error message
3982
+ * <Text>{formI18n.required()}</Text>
3983
+ *
3984
+ * // Get custom translation key
3985
+ * <Text>{formI18n.t('add_more')}</Text>
3986
+ *
3987
+ * // Access the raw colLabel
3988
+ * const colLabel = formI18n.colLabel;
3989
+ * ```
3990
+ */
3991
+ const useFormI18n = (column, prefix = "") => {
3992
+ const { translate } = useSchemaContext();
3993
+ const colLabel = `${prefix}${column}`;
3994
+ return {
3995
+ /**
3996
+ * The constructed column label (prefix + column)
3997
+ */
3998
+ colLabel,
3999
+ /**
4000
+ * Get the field label translation
4001
+ * Equivalent to: translate.t(removeIndex(`${colLabel}.field_label`))
4002
+ */
4003
+ label: (options) => {
4004
+ return translate.t(removeIndex(`${colLabel}.field_label`), options);
4005
+ },
4006
+ /**
4007
+ * Get the required error message translation
4008
+ * Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
4009
+ */
4010
+ required: (options) => {
4011
+ return translate.t(removeIndex(`${colLabel}.field_required`), options);
4012
+ },
4013
+ /**
4014
+ * Get a translation for any custom key relative to the field
4015
+ * Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
4016
+ *
4017
+ * @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
4018
+ * @param options - Optional translation options (e.g., defaultValue, interpolation variables)
4019
+ */
4020
+ t: (key, options) => {
4021
+ return translate.t(removeIndex(`${colLabel}.${key}`), options);
4022
+ },
4023
+ /**
4024
+ * Access to the original translate object for edge cases
4025
+ */
4026
+ translate,
4027
+ };
4028
+ };
4029
+
4030
+ dayjs.extend(utc);
4031
+ dayjs.extend(timezone);
3744
4032
  const DatePicker = ({ column, schema, prefix }) => {
3745
4033
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
3746
- const { translate } = useSchemaContext();
3747
- const { required, gridColumn, gridRow } = schema;
4034
+ const { timezone } = useSchemaContext();
4035
+ const formI18n = useFormI18n(column, prefix);
4036
+ const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", dateFormat = "YYYY-MM-DD", } = schema;
3748
4037
  const isRequired = required?.some((columnId) => columnId === column);
3749
- const colLabel = `${prefix}${column}`;
4038
+ const colLabel = formI18n.colLabel;
3750
4039
  const [open, setOpen] = React.useState(false);
3751
4040
  const selectedDate = watch(colLabel);
3752
- const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
3753
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3754
- gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { size: "sm", variant: "outline", onClick: () => {
4041
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
4042
+ React.useEffect(() => {
4043
+ try {
4044
+ if (selectedDate) {
4045
+ // Parse the selectedDate as UTC or in a specific timezone to avoid +8 hour shift
4046
+ // For example, parse as UTC:
4047
+ const parsedDate = dayjs(selectedDate).tz(timezone);
4048
+ if (!parsedDate.isValid())
4049
+ return;
4050
+ // Format according to dateFormat from schema
4051
+ const formatted = parsedDate.format(dateFormat);
4052
+ // Update the form value only if different to avoid loops
4053
+ if (formatted !== selectedDate) {
4054
+ setValue(colLabel, formatted, {
4055
+ shouldValidate: true,
4056
+ shouldDirty: true,
4057
+ });
4058
+ }
4059
+ }
4060
+ }
4061
+ catch (e) {
4062
+ console.error(e);
4063
+ }
4064
+ }, [selectedDate, dateFormat, colLabel, setValue]);
4065
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4066
+ gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
3755
4067
  setOpen(true);
3756
- }, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1
3757
- // @ts-expect-error TODO: find appropriate types
3758
- , {
3759
- // @ts-expect-error TODO: find appropriate types
3760
- selected: new Date(selectedDate),
3761
- // @ts-expect-error TODO: find appropriate types
3762
- onDateSelected: ({ date }) => {
3763
- setValue(colLabel, dayjs(date).format("YYYY-MM-DD"));
4068
+ }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4069
+ setValue(colLabel, dayjs(date).format(dateFormat));
3764
4070
  setOpen(false);
3765
- } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4071
+ }, labels: {
4072
+ monthNamesShort: [
4073
+ formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
4074
+ formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
4075
+ formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
4076
+ formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
4077
+ formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
4078
+ formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
4079
+ formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
4080
+ formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
4081
+ formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
4082
+ formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
4083
+ formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
4084
+ formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
4085
+ ],
4086
+ weekdayNamesShort: [
4087
+ formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
4088
+ formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
4089
+ formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
4090
+ formI18n.translate.t(`common.weekday_4`, {
4091
+ defaultValue: "Wed",
4092
+ }),
4093
+ formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
4094
+ formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
4095
+ formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
4096
+ ],
4097
+ backButtonLabel: formI18n.translate.t(`common.back_button`, {
4098
+ defaultValue: "Back",
4099
+ }),
4100
+ forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
4101
+ defaultValue: "Forward",
4102
+ }),
4103
+ } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
3766
4104
  };
3767
4105
 
3768
4106
  function filterArray(array, searchTerm) {
@@ -3775,12 +4113,12 @@ function filterArray(array, searchTerm) {
3775
4113
  });
3776
4114
  }
3777
4115
 
3778
- const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
4116
+ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
3779
4117
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
3780
4118
  const { translate } = useSchemaContext();
3781
- const { required } = schema;
4119
+ const { required, variant } = schema;
3782
4120
  const isRequired = required?.some((columnId) => columnId === column);
3783
- const { gridColumn, gridRow, renderDisplay } = schema;
4121
+ const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
3784
4122
  const [searchText, setSearchText] = React.useState();
3785
4123
  const [limit, setLimit] = React.useState(10);
3786
4124
  const [openSearchResult, setOpenSearchResult] = React.useState();
@@ -3795,28 +4133,61 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3795
4133
  setSearchText(event.target.value);
3796
4134
  setLimit(10);
3797
4135
  };
3798
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4136
+ if (variant === "radio") {
4137
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4138
+ gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
4139
+ return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
4140
+ if (!isMultiple) {
4141
+ setOpenSearchResult(false);
4142
+ setValue(colLabel, item);
4143
+ return;
4144
+ }
4145
+ const newSet = new Set([...(watchEnums ?? []), item]);
4146
+ setValue(colLabel, [...newSet]);
4147
+ }, value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
4148
+ ? renderDisplay(item)
4149
+ : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
4150
+ }) }) }) }));
4151
+ }
4152
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3799
4153
  gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
3800
4154
  const item = enumValue;
3801
- if (item === undefined) {
3802
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "undefined" });
4155
+ if (!!item === false) {
4156
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3803
4157
  }
3804
- return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
3805
- // setSelectedEnums((state) => state.filter((id) => id != item));
4158
+ return (jsxRuntime.jsx(Tag, { size: "lg", closable: true, onClick: () => {
3806
4159
  setValue(column, watchEnums.filter((id) => id != item));
3807
4160
  }, children: !!renderDisplay === true
3808
4161
  ? renderDisplay(item)
3809
- : translate.t(removeIndex(`${colLabel}.${item}`)) }));
3810
- }), jsxRuntime.jsx(Tag, { cursor: "pointer", onClick: () => {
4162
+ : translate.t(removeIndex(`${colLabel}.${item}`)) }, item));
4163
+ }), jsxRuntime.jsx(Tag, { size: "lg", cursor: "pointer", onClick: () => {
3811
4164
  setOpenSearchResult(true);
3812
- }, children: translate.t(removeIndex(`${colLabel}.addMore`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4165
+ }, children: translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
3813
4166
  setOpenSearchResult(true);
3814
- }, children: watchEnum === undefined
4167
+ }, justifyContent: "start", children: !!watchEnum === false
3815
4168
  ? ""
3816
- : translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${column}.typeToSearch`), onChange: (event) => {
4169
+ : translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
3817
4170
  onSearchChange(event);
3818
4171
  setOpenSearchResult(true);
3819
- }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(react.Text, { children: `${translate.t(`${column}.total`)}: ${count}, ${translate.t(`${column}.showing`)} ${limit}` }), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: filterArray(dataList, searchText ?? "").map((item) => {
4172
+ }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: "auto", maxHeight: "20rem", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: dataList
4173
+ .filter((item) => {
4174
+ const searchTerm = (searchText || "").toLowerCase();
4175
+ if (!searchTerm)
4176
+ return true;
4177
+ // Check if the original enum value contains the search text
4178
+ const enumValueMatch = item
4179
+ .toLowerCase()
4180
+ .includes(searchTerm);
4181
+ // Check if the display value (translation) contains the search text
4182
+ const displayValue = !!renderDisplay === true
4183
+ ? renderDisplay(item)
4184
+ : translate.t(removeIndex(`${colLabel}.${item}`));
4185
+ // Convert to string and check if it includes the search term
4186
+ const displayValueString = String(displayValue).toLowerCase();
4187
+ const displayValueMatch = displayValueString.includes(searchTerm);
4188
+ return enumValueMatch || displayValueMatch;
4189
+ })
4190
+ .map((item) => {
3820
4191
  const selected = isMultiple
3821
4192
  ? watchEnums.some((enumValue) => item === enumValue)
3822
4193
  : watchEnum == item;
@@ -3828,10 +4199,10 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3828
4199
  }
3829
4200
  const newSet = new Set([...(watchEnums ?? []), item]);
3830
4201
  setValue(colLabel, [...newSet]);
3831
- }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
4202
+ }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
3832
4203
  ? renderDisplay(item)
3833
4204
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
3834
- }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: translate.t(removeIndex(`${colLabel}.emptySearchResult`)) })) }))] })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4205
+ }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3835
4206
  };
3836
4207
 
3837
4208
  function isEnteringWindow(_ref) {
@@ -4183,17 +4554,17 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
4183
4554
  const filesArray = [...event.target.files];
4184
4555
  onDrop({ files: filesArray });
4185
4556
  };
4186
- return (jsxRuntime.jsxs(react.Grid, { ...getColor(isDraggedOver), ref: ref, cursor: "pointer", onClick: handleClick, borderStyle: "dashed", borderColor: "gray.400", alignContent: "center", justifyContent: "center", borderWidth: 1, borderRadius: 4, ...gridProps, children: [children, !!children === false && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(react.Flex, { children: placeholder }), jsxRuntime.jsx(react.Input, { type: "file", multiple: true, style: { display: "none" }, ref: fileInput, onChange: handleChange })] }))] }));
4557
+ return (jsxRuntime.jsxs(react.Grid, { ...getColor(isDraggedOver), ref: ref, cursor: "pointer", onClick: handleClick, borderStyle: "dashed", borderColor: "colorPalette.400", alignContent: "center", justifyContent: "center", borderWidth: 1, borderRadius: 4, ...gridProps, children: [children, !!children === false && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(react.Flex, { children: placeholder }), jsxRuntime.jsx(react.Input, { type: "file", multiple: true, style: { display: "none" }, ref: fileInput, onChange: handleChange })] }))] }));
4187
4558
  };
4188
4559
 
4189
4560
  const FilePicker = ({ column, schema, prefix }) => {
4190
4561
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4191
4562
  const { translate } = useSchemaContext();
4192
- const { required, gridColumn, gridRow } = schema;
4563
+ const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
4193
4564
  const isRequired = required?.some((columnId) => columnId === column);
4194
4565
  const currentFiles = (watch(column) ?? []);
4195
4566
  const colLabel = `${prefix}${column}`;
4196
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.fieldLabel`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4567
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4197
4568
  const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4198
4569
  setValue(colLabel, [...currentFiles, ...newFiles]);
4199
4570
  }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
@@ -4201,10 +4572,19 @@ const FilePicker = ({ column, schema, prefix }) => {
4201
4572
  setValue(column, currentFiles.filter(({ name }) => {
4202
4573
  return name !== file.name;
4203
4574
  }));
4204
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4205
- }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4575
+ }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4576
+ }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4206
4577
  };
4207
4578
 
4579
+ const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
4580
+ const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
4581
+ return (jsxRuntime.jsxs(react.Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsxs(react.Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsxRuntime.jsx(react.Popover.Arrow, { children: jsxRuntime.jsx(react.Popover.ArrowTip, {}) })), content] }) }) })] }));
4582
+ });
4583
+ const InfoTip = React__namespace.forwardRef(function InfoTip(props, ref) {
4584
+ const { children, ...rest } = props;
4585
+ return (jsxRuntime.jsx(ToggleTip, { content: children, ...rest, ref: ref, children: jsxRuntime.jsx(react.IconButton, { variant: "ghost", "aria-label": "info", size: "2xs", colorPalette: "colorPalette", children: jsxRuntime.jsx(hi.HiOutlineInformationCircle, {}) }) }));
4586
+ });
4587
+
4208
4588
  const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
4209
4589
  if (serverUrl === undefined || serverUrl.length == 0) {
4210
4590
  throw new Error("The serverUrl is missing");
@@ -4235,25 +4615,40 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
4235
4615
 
4236
4616
  const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4237
4617
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4238
- const { serverUrl, idMap, setIdMap, translate, schema: parentSchema, } = useSchemaContext();
4239
- const { required, gridColumn, gridRow, renderDisplay, foreign_key } = schema;
4618
+ const { serverUrl, idMap, setIdMap, schema: parentSchema, } = useSchemaContext();
4619
+ const formI18n = useFormI18n(column, prefix);
4620
+ const { required, gridColumn = "span 12", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
4240
4621
  const isRequired = required?.some((columnId) => columnId === column);
4241
- const { table, column: column_ref, display_column, } = foreign_key;
4242
- const [searchText, setSearchText] = React.useState();
4622
+ const { table, column: column_ref, display_column, customQueryFn, } = foreign_key;
4623
+ const [searchText, setSearchText] = React.useState("");
4243
4624
  const [limit, setLimit] = React.useState(10);
4244
4625
  const [openSearchResult, setOpenSearchResult] = React.useState();
4245
4626
  const [page, setPage] = React.useState(0);
4246
4627
  const ref = React.useRef(null);
4247
- const colLabel = `${prefix}${column}`;
4628
+ const colLabel = formI18n.colLabel;
4629
+ const watchId = watch(colLabel);
4630
+ const watchIds = isMultiple ? (watch(colLabel) ?? []) : [];
4631
+ // Query for search results
4248
4632
  const query = reactQuery.useQuery({
4249
4633
  queryKey: [`idpicker`, { column, searchText, limit, page }],
4250
4634
  queryFn: async () => {
4635
+ if (customQueryFn) {
4636
+ const { data, idMap } = await customQueryFn({
4637
+ searching: searchText ?? "",
4638
+ limit: limit,
4639
+ offset: page * limit,
4640
+ });
4641
+ setIdMap((state) => {
4642
+ return { ...state, ...idMap };
4643
+ });
4644
+ return data;
4645
+ }
4251
4646
  const data = await getTableData({
4252
4647
  serverUrl,
4253
4648
  searching: searchText ?? "",
4254
4649
  in_table: table,
4255
4650
  limit: limit,
4256
- offset: page * 10,
4651
+ offset: page * limit,
4257
4652
  });
4258
4653
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
4259
4654
  return [
@@ -4268,27 +4663,38 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4268
4663
  });
4269
4664
  return data;
4270
4665
  },
4271
- enabled: (searchText ?? "")?.length > 0,
4666
+ enabled: openSearchResult === true,
4272
4667
  staleTime: 300000,
4273
4668
  });
4274
- const { isLoading, isFetching, data, isPending, isError } = query;
4275
- const dataList = data?.data ?? [];
4276
- const count = data?.count ?? 0;
4277
- const isDirty = (searchText?.length ?? 0) > 0;
4278
- const watchId = watch(colLabel);
4279
- const watchIds = (watch(colLabel) ?? []);
4280
- reactQuery.useQuery({
4669
+ // Query for currently selected items (to display them properly)
4670
+ const queryDefault = reactQuery.useQuery({
4281
4671
  queryKey: [
4282
- `idpicker`,
4283
- { form: parentSchema.title, column, searchText, limit, page },
4672
+ `idpicker-default`,
4673
+ { form: parentSchema.title, column, id: isMultiple ? watchIds : watchId },
4284
4674
  ],
4285
4675
  queryFn: async () => {
4676
+ if (customQueryFn) {
4677
+ const { data, idMap } = await customQueryFn({
4678
+ searching: watchIds.join(","),
4679
+ limit: isMultiple ? watchIds.length : 1,
4680
+ offset: 0,
4681
+ });
4682
+ setIdMap((state) => {
4683
+ return { ...state, ...idMap };
4684
+ });
4685
+ return data;
4686
+ }
4687
+ if (!watchId && (!watchIds || watchIds.length === 0)) {
4688
+ return { data: [] };
4689
+ }
4690
+ const searchValue = isMultiple ? watchIds.join(",") : watchId;
4286
4691
  const data = await getTableData({
4287
4692
  serverUrl,
4288
- searching: watchId,
4693
+ searching: searchValue,
4289
4694
  in_table: table,
4290
- limit: limit,
4291
- offset: page * 10,
4695
+ where: [{ id: column_ref, value: isMultiple ? watchIds : watchId }],
4696
+ limit: isMultiple ? watchIds.length : 1,
4697
+ offset: 0,
4292
4698
  });
4293
4699
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
4294
4700
  return [
@@ -4303,12 +4709,45 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4303
4709
  });
4304
4710
  return data;
4305
4711
  },
4712
+ enabled: isMultiple
4713
+ ? Array.isArray(watchIds) && watchIds.length > 0
4714
+ : !!watchId,
4306
4715
  });
4716
+ // Effect to load selected values when component mounts
4717
+ React.useEffect(() => {
4718
+ if (isMultiple ? watchIds.length > 0 : !!watchId) {
4719
+ queryDefault.refetch();
4720
+ }
4721
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4722
+ }, []);
4723
+ // Effect to trigger initial data fetch when popover opens
4724
+ React.useEffect(() => {
4725
+ if (openSearchResult) {
4726
+ // Reset search text when opening the popover
4727
+ setSearchText("");
4728
+ // Reset page to first page
4729
+ setPage(0);
4730
+ // Fetch initial data
4731
+ query.refetch();
4732
+ }
4733
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4734
+ }, [openSearchResult]);
4307
4735
  const onSearchChange = async (event) => {
4308
4736
  setSearchText(event.target.value);
4309
4737
  setPage(0);
4310
- setLimit(10);
4738
+ query.refetch();
4739
+ };
4740
+ const handleLimitChange = (event) => {
4741
+ const newLimit = Number(event.target.value);
4742
+ setLimit(newLimit);
4743
+ // Reset to first page when changing limit
4744
+ setPage(0);
4745
+ // Trigger a new search with the updated limit
4746
+ query.refetch();
4311
4747
  };
4748
+ const { isLoading, isFetching, data, isPending, isError } = query;
4749
+ const dataList = data?.data ?? [];
4750
+ const count = data?.count ?? 0;
4312
4751
  const getPickedValue = () => {
4313
4752
  if (Object.keys(idMap).length <= 0) {
4314
4753
  return "";
@@ -4317,52 +4756,67 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4317
4756
  if (record === undefined) {
4318
4757
  return "";
4319
4758
  }
4759
+ if (!!renderDisplay === true) {
4760
+ return renderDisplay(record);
4761
+ }
4320
4762
  return record[display_column];
4321
4763
  };
4322
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(removeIndex(`${column}.fieldLabel`)))}`, required: isRequired, alignItems: "stretch", gridColumn,
4764
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4323
4765
  gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchIds.map((id) => {
4324
4766
  const item = idMap[id];
4325
4767
  if (item === undefined) {
4326
- return (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
4768
+ return (jsxRuntime.jsx(react.Text, { children: formI18n.t('undefined') }, id));
4327
4769
  }
4328
4770
  return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
4329
- setValue(column, watchIds.filter((id) => id != item[column_ref]));
4771
+ setValue(colLabel, watchIds.filter((itemId) => itemId !== item[column_ref]));
4330
4772
  }, children: !!renderDisplay === true
4331
4773
  ? renderDisplay(item)
4332
4774
  : item[display_column] }, id));
4333
4775
  }), jsxRuntime.jsx(Tag, { cursor: "pointer", onClick: () => {
4334
4776
  setOpenSearchResult(true);
4335
- }, children: translate.t(removeIndex(`${colLabel}.addMore`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4777
+ }, children: formI18n.t('add_more') })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4336
4778
  setOpenSearchResult(true);
4337
- }, children: getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4338
- onSearchChange(event);
4339
- setOpenSearchResult(true);
4340
- }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), (isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsx(react.Text, { justifySelf: "center", children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` }), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children:
4341
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4342
- dataList.map((item) => {
4343
- const selected = isMultiple
4344
- ? watchIds.some((id) => item[column_ref] === id)
4345
- : watchId === item[column_ref];
4346
- return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
4347
- if (!isMultiple) {
4348
- setOpenSearchResult(false);
4349
- setValue(colLabel, item[column_ref]);
4350
- return;
4351
- }
4352
- const newSet = new Set([
4353
- ...(watchIds ?? []),
4354
- item[column_ref],
4355
- ]);
4356
- setValue(colLabel, [...newSet]);
4357
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
4358
- ? renderDisplay(item)
4359
- : item[display_column] }, item[column_ref]));
4360
- }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.emptySearchResult`)) })) }))] }), jsxRuntime.jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: 10, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4779
+ }, justifyContent: "start", children: queryDefault.isLoading ? jsxRuntime.jsx(react.Spinner, { size: "sm" }) : getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: formI18n.t('type_to_search'), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsxRuntime.jsx(PopoverTitle, {}), openSearchResult && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", children: [jsxRuntime.jsx(InfoTip, { children: `${formI18n.t('total')} ${count}, ${formI18n.t('showing')} ${limit} ${formI18n.t('per_page', { defaultValue: 'per page' })}` }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/", " ", count > 0
4780
+ ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}`
4781
+ : "0"] })] })] }), jsxRuntime.jsx(react.Box, { children: jsxRuntime.jsxs("select", { value: limit, onChange: handleLimitChange, style: {
4782
+ padding: "4px 8px",
4783
+ borderRadius: "4px",
4784
+ border: "1px solid #ccc",
4785
+ fontSize: "14px",
4786
+ }, children: [jsxRuntime.jsx("option", { value: "5", children: "5" }), jsxRuntime.jsx("option", { value: "10", children: "10" }), jsxRuntime.jsx("option", { value: "20", children: "20" }), jsxRuntime.jsx("option", { value: "30", children: "30" })] }) })] }), jsxRuntime.jsx(react.Grid, { overflowY: "auto", children: dataList.length > 0 ? (jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", gap: 1, children: dataList.map((item) => {
4787
+ const selected = isMultiple
4788
+ ? watchIds.some((id) => item[column_ref] === id)
4789
+ : watchId === item[column_ref];
4790
+ return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
4791
+ if (!isMultiple) {
4792
+ setOpenSearchResult(false);
4793
+ setValue(colLabel, item[column_ref]);
4794
+ return;
4795
+ }
4796
+ // For multiple selection, don't add if already selected
4797
+ if (selected)
4798
+ return;
4799
+ const newSet = new Set([
4800
+ ...(watchIds ?? []),
4801
+ item[column_ref],
4802
+ ]);
4803
+ setValue(colLabel, [...newSet]);
4804
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
4805
+ ? {
4806
+ color: "colorPalette.400/50",
4807
+ fontWeight: "bold",
4808
+ }
4809
+ : {}), children: !!renderDisplay === true
4810
+ ? renderDisplay(item)
4811
+ : item[display_column] }, item[column_ref]));
4812
+ }) })) : (jsxRuntime.jsx(react.Text, { children: searchText
4813
+ ? formI18n.t('empty_search_result')
4814
+ : formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
4361
4815
  };
4362
4816
 
4363
4817
  const NumberInputRoot = React__namespace.forwardRef(function NumberInput(props, ref) {
4364
4818
  const { children, ...rest } = props;
4365
- return (jsxRuntime.jsxs(react.NumberInput.Root, { ref: ref, variant: "outline", ...rest, children: [children, jsxRuntime.jsxs(react.NumberInput.Control, { children: [jsxRuntime.jsx(react.NumberInput.IncrementTrigger, {}), jsxRuntime.jsx(react.NumberInput.DecrementTrigger, {})] })] }));
4819
+ return (jsxRuntime.jsx(react.NumberInput.Root, { ref: ref, variant: "outline", ...rest, children: children }));
4366
4820
  });
4367
4821
  const NumberInputField$1 = react.NumberInput.Input;
4368
4822
  react.NumberInput.Scrubber;
@@ -4371,17 +4825,17 @@ react.NumberInput.Label;
4371
4825
  const NumberInputField = ({ schema, column, prefix, }) => {
4372
4826
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4373
4827
  const { translate } = useSchemaContext();
4374
- const { required, gridColumn, gridRow } = schema;
4828
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4375
4829
  const isRequired = required?.some((columnId) => columnId === column);
4376
4830
  const colLabel = `${prefix}${column}`;
4377
4831
  const value = watch(`${colLabel}`);
4378
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(NumberInputRoot, { children: jsxRuntime.jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4832
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(NumberInputRoot, { children: jsxRuntime.jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4379
4833
  setValue(`${colLabel}`, Number(event.target.value));
4380
- } }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4834
+ } }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4381
4835
  };
4382
4836
 
4383
4837
  const ObjectInput = ({ schema, column, prefix }) => {
4384
- const { properties, gridRow, gridColumn = "1/span 12", required } = schema;
4838
+ const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
4385
4839
  const { translate } = useSchemaContext();
4386
4840
  const colLabel = `${prefix}${column}`;
4387
4841
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4389,25 +4843,28 @@ const ObjectInput = ({ schema, column, prefix }) => {
4389
4843
  if (properties === undefined) {
4390
4844
  throw new Error(`properties is undefined when using ObjectInput`);
4391
4845
  }
4392
- return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: Object.keys(properties ?? {}).map((key) => {
4846
+ return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4847
+ base: "colorPalette.200",
4848
+ _dark: "colorPalette.800",
4849
+ }, gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: Object.keys(properties ?? {}).map((key) => {
4393
4850
  return (
4394
4851
  // @ts-expect-error find suitable types
4395
4852
  jsxRuntime.jsx(ColumnRenderer, { column: `${key}`,
4396
4853
  prefix: `${prefix}${column}.`,
4397
4854
  properties }, `form-${colLabel}-${key}`));
4398
- }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4855
+ }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4399
4856
  };
4400
4857
 
4401
4858
  const RecordInput$1 = ({ column, schema, prefix }) => {
4402
4859
  const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
4403
4860
  const { translate } = useSchemaContext();
4404
- const { required, gridColumn, gridRow } = schema;
4861
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4405
4862
  const isRequired = required?.some((columnId) => columnId === column);
4406
4863
  const entries = Object.entries(getValues(column) ?? {});
4407
4864
  const [showNewEntries, setShowNewEntries] = React.useState(false);
4408
4865
  const [newKey, setNewKey] = React.useState();
4409
4866
  const [newValue, setNewValue] = React.useState();
4410
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.fieldLabel`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4867
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4411
4868
  return (jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
4412
4869
  const filtered = entries.filter(([target]) => {
4413
4870
  return target !== key;
@@ -4447,16 +4904,16 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
4447
4904
  setShowNewEntries(true);
4448
4905
  setNewKey(undefined);
4449
4906
  setNewValue(undefined);
4450
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
4907
+ }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4451
4908
  };
4452
4909
 
4453
4910
  const StringInputField = ({ column, schema, prefix, }) => {
4454
4911
  const { register, formState: { errors }, } = reactHookForm.useFormContext();
4455
4912
  const { translate } = useSchemaContext();
4456
- const { required, gridColumn, gridRow } = schema;
4913
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4457
4914
  const isRequired = required?.some((columnId) => columnId === column);
4458
4915
  const colLabel = `${prefix}${column}`;
4459
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }) }));
4916
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4460
4917
  };
4461
4918
 
4462
4919
  const RadioCardItem = React__namespace.forwardRef(function RadioCardItem(props, ref) {
@@ -4554,9 +5011,574 @@ const TagPicker = ({ column, schema, prefix }) => {
4554
5011
  }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4555
5012
  };
4556
5013
 
5014
+ 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) => {
5015
+ const contentEditableRef = React.useRef(null);
5016
+ const isControlled = value !== undefined;
5017
+ // Handle input changes
5018
+ const handleInput = (e) => {
5019
+ const text = e.currentTarget.textContent || "";
5020
+ // Check maxLength if specified
5021
+ if (maxLength && text.length > maxLength) {
5022
+ e.currentTarget.textContent = text.slice(0, maxLength);
5023
+ // Move cursor to end
5024
+ const selection = window.getSelection();
5025
+ if (selection) {
5026
+ selection.selectAllChildren(e.currentTarget);
5027
+ selection.collapseToEnd();
5028
+ }
5029
+ return;
5030
+ }
5031
+ onChange?.(text);
5032
+ };
5033
+ // Handle paste events to strip formatting and respect maxLength
5034
+ const handlePaste = (e) => {
5035
+ e.preventDefault();
5036
+ const text = e.clipboardData.getData('text/plain');
5037
+ const currentText = e.currentTarget.textContent || "";
5038
+ let pasteText = text;
5039
+ if (maxLength) {
5040
+ const remainingLength = maxLength - currentText.length;
5041
+ pasteText = text.slice(0, remainingLength);
5042
+ }
5043
+ document.execCommand('insertText', false, pasteText);
5044
+ };
5045
+ // Set initial content
5046
+ React.useEffect(() => {
5047
+ if (contentEditableRef.current && !isControlled) {
5048
+ const initialValue = defaultValue || "";
5049
+ if (contentEditableRef.current.textContent !== initialValue) {
5050
+ contentEditableRef.current.textContent = initialValue;
5051
+ }
5052
+ }
5053
+ }, [defaultValue, isControlled]);
5054
+ // Update content when value changes (controlled mode)
5055
+ React.useEffect(() => {
5056
+ if (contentEditableRef.current && isControlled && value !== undefined) {
5057
+ if (contentEditableRef.current.textContent !== value) {
5058
+ contentEditableRef.current.textContent = value;
5059
+ }
5060
+ }
5061
+ }, [value, isControlled]);
5062
+ // Auto focus
5063
+ React.useEffect(() => {
5064
+ if (autoFocus && contentEditableRef.current) {
5065
+ contentEditableRef.current.focus();
5066
+ }
5067
+ }, [autoFocus]);
5068
+ // Forward ref
5069
+ React.useEffect(() => {
5070
+ if (typeof ref === 'function') {
5071
+ ref(contentEditableRef.current);
5072
+ }
5073
+ else if (ref) {
5074
+ ref.current = contentEditableRef.current;
5075
+ }
5076
+ }, [ref]);
5077
+ const textareaElement = (jsxRuntime.jsx(react.Box, { ref: contentEditableRef, contentEditable: !disabled && !readOnly, onInput: handleInput, onPaste: handlePaste, onFocus: onFocus, onBlur: onBlur, className: className, minHeight: `${rows * 1.5}em`, padding: "2", border: "1px solid", borderColor: invalid ? "red.500" : "gray.200", borderRadius: "md", outline: "none", _focus: {
5078
+ borderColor: invalid ? "red.500" : "blue.500",
5079
+ boxShadow: `0 0 0 1px ${invalid ? "red.500" : "blue.500"}`,
5080
+ }, _disabled: {
5081
+ opacity: 0.6,
5082
+ cursor: "not-allowed",
5083
+ bg: "gray.50",
5084
+ }, _empty: {
5085
+ _before: {
5086
+ content: placeholder ? `"${placeholder}"` : undefined,
5087
+ color: "gray.400",
5088
+ pointerEvents: "none",
5089
+ }
5090
+ }, whiteSpace: "pre-wrap", overflowWrap: "break-word", overflow: "auto", maxHeight: `${rows * 4}em`, suppressContentEditableWarning: true, ...props }));
5091
+ // If we have additional field props, wrap in Field component
5092
+ if (label || helperText || errorText || required) {
5093
+ return (jsxRuntime.jsxs(react.Field.Root, { invalid: invalid, required: required, children: [label && (jsxRuntime.jsxs(react.Field.Label, { children: [label, required && jsxRuntime.jsx(react.Field.RequiredIndicator, {})] })), textareaElement, helperText && jsxRuntime.jsx(react.Field.HelperText, { children: helperText }), errorText && jsxRuntime.jsx(react.Field.ErrorText, { children: errorText })] }));
5094
+ }
5095
+ return textareaElement;
5096
+ });
5097
+ Textarea.displayName = "Textarea";
5098
+
5099
+ const TextAreaInput = ({ column, schema, prefix, }) => {
5100
+ const { register, formState: { errors }, } = reactHookForm.useFormContext();
5101
+ const { translate } = useSchemaContext();
5102
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5103
+ const isRequired = required?.some((columnId) => columnId === column);
5104
+ const colLabel = `${prefix}${column}`;
5105
+ const form = reactHookForm.useFormContext();
5106
+ const { setValue, watch } = form;
5107
+ const watchValue = watch(colLabel);
5108
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", children: [jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5109
+ };
5110
+
5111
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
5112
+ am: "am",
5113
+ pm: "pm",
5114
+ }, onChange = (_newValue) => { }, timezone = "Asia/Hong_Kong", }) {
5115
+ const handleClear = () => {
5116
+ setHour(null);
5117
+ setMinute(null);
5118
+ setMeridiem(null);
5119
+ setInputValue("");
5120
+ setShowInput(false);
5121
+ onChange({ hour: null, minute: null, meridiem: null });
5122
+ };
5123
+ const getTimeString = (hour, minute, meridiem) => {
5124
+ if (hour === null || minute === null || meridiem === null) {
5125
+ return "";
5126
+ }
5127
+ // if the hour is 24, set the hour to 0
5128
+ if (hour === 24) {
5129
+ return dayjs().tz(timezone).hour(0).minute(minute).format("HH:mmZ");
5130
+ }
5131
+ // use dayjs to format the time at current timezone
5132
+ // if meridiem is pm, add 12 hours
5133
+ let newHour = hour;
5134
+ if (meridiem === "pm" && hour !== 12) {
5135
+ newHour = hour + 12;
5136
+ }
5137
+ // if the hour is 12, set the meridiem to am, and set the hour to 0
5138
+ else if (meridiem === "am" && hour === 12) {
5139
+ newHour = 0;
5140
+ }
5141
+ return dayjs().tz(timezone).hour(newHour).minute(minute).format("HH:mmZ");
5142
+ };
5143
+ const stringTime = getTimeString(hour, minute, meridiem);
5144
+ const [inputValue, setInputValue] = React.useState("");
5145
+ const [showInput, setShowInput] = React.useState(false);
5146
+ const handleBlur = (text) => {
5147
+ // ignore all non-numeric characters
5148
+ if (!text) {
5149
+ return;
5150
+ }
5151
+ const value = text.replace(/[^0-9apm]/g, "");
5152
+ if (value === "") {
5153
+ handleClear();
5154
+ return;
5155
+ }
5156
+ // if the value is a valid time, parse it and set the hour, minute, and meridiem
5157
+ // if the value is not a valid time, set the stringTime to the value
5158
+ // first two characters are the hour
5159
+ // next two characters are the minute
5160
+ // final two characters are the meridiem
5161
+ const hour = parseInt(value.slice(0, 2));
5162
+ const minute = parseInt(value.slice(2, 4));
5163
+ const meridiem = value.slice(4, 6);
5164
+ // validate the hour and minute
5165
+ if (isNaN(hour) || isNaN(minute)) {
5166
+ setInputValue("");
5167
+ return;
5168
+ }
5169
+ // if the hour is larger than 24, set the hour to 24
5170
+ if (hour > 24) {
5171
+ setInputValue("");
5172
+ return;
5173
+ }
5174
+ let newHour = hour;
5175
+ let newMinute = minute;
5176
+ let newMeridiem = meridiem;
5177
+ // if the hour is 24, set the meridiem to am, and set the hour to 0
5178
+ if (hour === 24) {
5179
+ newMeridiem = "am";
5180
+ newHour = 0;
5181
+ }
5182
+ // if the hour is greater than 12, set the meridiem to pm, and subtract 12 from the hour
5183
+ else if (hour > 12) {
5184
+ newMeridiem = "pm";
5185
+ newHour = hour - 12;
5186
+ }
5187
+ // if the hour is 12, set the meridiem to pm, and set the hour to 12
5188
+ else if (hour === 12) {
5189
+ newMeridiem = "pm";
5190
+ newHour = 12;
5191
+ }
5192
+ // if the hour is 0, set the meridiem to am, and set the hour to 12
5193
+ else if (hour === 0) {
5194
+ newMeridiem = "am";
5195
+ newHour = 12;
5196
+ }
5197
+ else {
5198
+ newMeridiem = meridiem ?? "am";
5199
+ newHour = hour;
5200
+ }
5201
+ if (minute > 59) {
5202
+ newMinute = 0;
5203
+ }
5204
+ else {
5205
+ newMinute = minute;
5206
+ }
5207
+ onChange({
5208
+ hour: newHour,
5209
+ minute: newMinute,
5210
+ meridiem: newMeridiem,
5211
+ });
5212
+ setShowInput(false);
5213
+ };
5214
+ const handleKeyDown = (e) => {
5215
+ if (e.key === "Enter") {
5216
+ handleBlur(e.currentTarget.value);
5217
+ }
5218
+ };
5219
+ const inputRef = React.useRef(null);
5220
+ return (jsxRuntime.jsxs(react.Grid, { justifyContent: "center", alignItems: "center", templateColumns: "200px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsxRuntime.jsx(react.Input, { onKeyDown: handleKeyDown, onChange: (e) => {
5221
+ setInputValue(e.currentTarget.value);
5222
+ }, onBlur: (e) => {
5223
+ handleBlur(e.currentTarget.value);
5224
+ }, onFocus: (e) => {
5225
+ e.currentTarget.select();
5226
+ }, value: inputValue, display: showInput ? undefined : "none", ref: inputRef }), jsxRuntime.jsxs(react.Button, { onClick: () => {
5227
+ setShowInput(true);
5228
+ setInputValue(dayjs(`1970-01-01T${getTimeString(hour, minute, meridiem)}`, "hh:mmZ").format("HH:mm"));
5229
+ inputRef.current?.focus();
5230
+ }, display: showInput ? "none" : "flex", alignItems: "center", justifyContent: "start", variant: "outline", gap: 2, children: [jsxRuntime.jsx(react.Icon, { size: "sm", children: jsxRuntime.jsx(bs.BsClock, {}) }), jsxRuntime.jsx(react.Text, { fontSize: "sm", children: stringTime
5231
+ ? dayjs(`1970-01-01T${stringTime}`, "hh:mmZ").format("hh:mm a")
5232
+ : "" })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }));
5233
+ }
5234
+
5235
+ dayjs.extend(timezone);
5236
+ const TimePicker = ({ column, schema, prefix }) => {
5237
+ const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5238
+ const { translate, timezone } = useSchemaContext();
5239
+ const { required, gridColumn = "span 12", gridRow = "span 1", timeFormat = "HH:mm:ssZ", displayTimeFormat = "hh:mm A", } = schema;
5240
+ const isRequired = required?.some((columnId) => columnId === column);
5241
+ const colLabel = `${prefix}${column}`;
5242
+ const [open, setOpen] = React.useState(false);
5243
+ const value = watch(colLabel);
5244
+ const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
5245
+ ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
5246
+ : "";
5247
+ // Parse the initial time parts from the time string (HH:mm:ssZ)
5248
+ const parseTime = (time) => {
5249
+ if (!time)
5250
+ return { hour: 12, minute: 0, meridiem: "am" };
5251
+ const parsed = dayjs(`1970-01-01T${time}`).tz(timezone);
5252
+ if (!parsed.isValid()) {
5253
+ return { hour: 12, minute: 0, meridiem: "am" };
5254
+ }
5255
+ let hour = parsed.hour();
5256
+ const minute = parsed.minute();
5257
+ const meridiem = hour >= 12 ? "pm" : "am";
5258
+ if (hour === 0)
5259
+ hour = 12;
5260
+ else if (hour > 12)
5261
+ hour -= 12;
5262
+ return { hour, minute, meridiem };
5263
+ };
5264
+ const initialTime = parseTime(value);
5265
+ const [hour, setHour] = React.useState(initialTime.hour);
5266
+ const [minute, setMinute] = React.useState(initialTime.minute);
5267
+ const [meridiem, setMeridiem] = React.useState(initialTime.meridiem);
5268
+ React.useEffect(() => {
5269
+ const { hour, minute, meridiem } = parseTime(value);
5270
+ setHour(hour);
5271
+ setMinute(minute);
5272
+ setMeridiem(meridiem);
5273
+ }, [value]);
5274
+ const getTimeString = (hour, minute, meridiem) => {
5275
+ if (hour === null || minute === null || meridiem === null)
5276
+ return null;
5277
+ let newHour = hour;
5278
+ if (meridiem === "pm" && hour !== 12) {
5279
+ newHour = hour + 12;
5280
+ }
5281
+ return dayjs().tz(timezone).hour(newHour).minute(minute).second(0).format(timeFormat);
5282
+ };
5283
+ // Handle changes to time parts
5284
+ const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
5285
+ setHour(newHour);
5286
+ setMinute(newMinute);
5287
+ setMeridiem(newMeridiem);
5288
+ const timeString = getTimeString(newHour, newMinute, newMeridiem);
5289
+ setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
5290
+ };
5291
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5292
+ gridRow, children: [jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5293
+ setOpen(true);
5294
+ }, justifyContent: "start", children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5295
+ am: translate.t(`common.am`, { defaultValue: "AM" }),
5296
+ pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5297
+ } }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5298
+ };
5299
+
5300
+ function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
5301
+ // Refs for focus management
5302
+ const hourInputRef = React.useRef(null);
5303
+ const minuteInputRef = React.useRef(null);
5304
+ const secondInputRef = React.useRef(null);
5305
+ // Centralized handler for key events, value changes, and focus management
5306
+ const handleKeyDown = (e, field) => {
5307
+ const input = e.target;
5308
+ const value = input.value;
5309
+ // Handle navigation between fields
5310
+ if (e.key === "Tab") {
5311
+ return;
5312
+ }
5313
+ if (e.key === ":" && field === "hour") {
5314
+ e.preventDefault();
5315
+ minuteInputRef.current?.focus();
5316
+ return;
5317
+ }
5318
+ if (e.key === ":" && field === "minute") {
5319
+ e.preventDefault();
5320
+ secondInputRef.current?.focus();
5321
+ return;
5322
+ }
5323
+ if (e.key === "Backspace" && value === "") {
5324
+ e.preventDefault();
5325
+ if (field === "minute") {
5326
+ hourInputRef.current?.focus();
5327
+ }
5328
+ else if (field === "second") {
5329
+ minuteInputRef.current?.focus();
5330
+ }
5331
+ return;
5332
+ }
5333
+ // Handle number inputs
5334
+ if (field === "hour") {
5335
+ if (e.key.match(/^[0-9]$/)) {
5336
+ const newValue = value + e.key;
5337
+ const numValue = parseInt(newValue, 10);
5338
+ if (numValue > 23) {
5339
+ const digitValue = parseInt(e.key, 10);
5340
+ setHour(digitValue);
5341
+ onChange({ hour: digitValue, minute, second });
5342
+ return;
5343
+ }
5344
+ if (numValue >= 0 && numValue <= 23) {
5345
+ setHour(numValue);
5346
+ onChange({ hour: numValue, minute, second });
5347
+ e.preventDefault();
5348
+ minuteInputRef.current?.focus();
5349
+ }
5350
+ }
5351
+ }
5352
+ else if (field === "minute") {
5353
+ if (e.key.match(/^[0-9]$/)) {
5354
+ const newValue = value + e.key;
5355
+ const numValue = parseInt(newValue, 10);
5356
+ if (numValue > 59) {
5357
+ const digitValue = parseInt(e.key, 10);
5358
+ setMinute(digitValue);
5359
+ onChange({ hour, minute: digitValue, second });
5360
+ return;
5361
+ }
5362
+ if (numValue >= 0 && numValue <= 59) {
5363
+ setMinute(numValue);
5364
+ onChange({ hour, minute: numValue, second });
5365
+ e.preventDefault();
5366
+ secondInputRef.current?.focus();
5367
+ }
5368
+ }
5369
+ }
5370
+ else if (field === "second") {
5371
+ if (e.key.match(/^[0-9]$/)) {
5372
+ const newValue = value + e.key;
5373
+ const numValue = parseInt(newValue, 10);
5374
+ if (numValue > 59) {
5375
+ const digitValue = parseInt(e.key, 10);
5376
+ setSecond(digitValue);
5377
+ onChange({ hour, minute, second: digitValue });
5378
+ return;
5379
+ }
5380
+ if (numValue >= 0 && numValue <= 59) {
5381
+ setSecond(numValue);
5382
+ onChange({ hour, minute, second: numValue });
5383
+ }
5384
+ }
5385
+ }
5386
+ };
5387
+ const handleClear = () => {
5388
+ setHour(null);
5389
+ setMinute(null);
5390
+ setSecond(null);
5391
+ onChange({ hour: null, minute: null, second: null });
5392
+ hourInputRef.current?.focus();
5393
+ };
5394
+ return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 10px 60px auto", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsx(react.Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Text, { children: ":" }), jsxRuntime.jsx(react.Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Text, { children: ":" }), jsxRuntime.jsx(react.Input, { ref: secondInputRef, type: "text", value: second === null ? "" : second.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "second"), placeholder: "SS", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }) }));
5395
+ }
5396
+
5397
+ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds = false, labels = {
5398
+ monthNamesShort: [
5399
+ "Jan",
5400
+ "Feb",
5401
+ "Mar",
5402
+ "Apr",
5403
+ "May",
5404
+ "Jun",
5405
+ "Jul",
5406
+ "Aug",
5407
+ "Sep",
5408
+ "Oct",
5409
+ "Nov",
5410
+ "Dec",
5411
+ ],
5412
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
5413
+ backButtonLabel: "Back",
5414
+ forwardButtonLabel: "Next",
5415
+ }, timezone = "Asia/Hong_Kong", }) {
5416
+ const [selectedDate, setSelectedDate] = React.useState(value || "");
5417
+ // Time state for 12-hour format
5418
+ const [hour12, setHour12] = React.useState(value ? dayjs(value).hour() % 12 || 12 : null);
5419
+ const [minute, setMinute] = React.useState(value ? dayjs(value).minute() : null);
5420
+ const [meridiem, setMeridiem] = React.useState(value ? (dayjs(value).hour() >= 12 ? "pm" : "am") : null);
5421
+ // Time state for 24-hour format
5422
+ const [hour24, setHour24] = React.useState(value ? dayjs(value).hour() : null);
5423
+ const [second, setSecond] = React.useState(value ? dayjs(value).second() : null);
5424
+ const handleDateChange = (date) => {
5425
+ setSelectedDate(date);
5426
+ updateDateTime(dayjs(date).tz(timezone).toISOString());
5427
+ };
5428
+ const handleTimeChange = (timeData) => {
5429
+ if (format === "iso-date-time") {
5430
+ setHour24(timeData.hour);
5431
+ setMinute(timeData.minute);
5432
+ if (showSeconds)
5433
+ setSecond(timeData.second);
5434
+ }
5435
+ else {
5436
+ setHour12(timeData.hour);
5437
+ setMinute(timeData.minute);
5438
+ setMeridiem(timeData.meridiem);
5439
+ }
5440
+ updateDateTime(dayjs(selectedDate).tz(timezone).toISOString(), timeData);
5441
+ };
5442
+ const updateDateTime = (date, timeData) => {
5443
+ if (!date) {
5444
+ onChange?.(undefined);
5445
+ return;
5446
+ }
5447
+ // use dayjs to convert the date to the timezone
5448
+ const newDate = dayjs(date).tz(timezone).toDate();
5449
+ if (format === "iso-date-time") {
5450
+ const h = timeData?.hour ?? hour24;
5451
+ const m = timeData?.minute ?? minute;
5452
+ const s = showSeconds ? timeData?.second ?? second : 0;
5453
+ if (h !== null)
5454
+ newDate.setHours(h);
5455
+ if (m !== null)
5456
+ newDate.setMinutes(m);
5457
+ if (s !== null)
5458
+ newDate.setSeconds(s);
5459
+ }
5460
+ else {
5461
+ const h = timeData?.hour ?? hour12;
5462
+ const m = timeData?.minute ?? minute;
5463
+ const mer = timeData?.meridiem ?? meridiem;
5464
+ if (h !== null && mer !== null) {
5465
+ let hour24 = h;
5466
+ if (mer === "am" && h === 12)
5467
+ hour24 = 0;
5468
+ else if (mer === "pm" && h < 12)
5469
+ hour24 = h + 12;
5470
+ newDate.setHours(hour24);
5471
+ }
5472
+ if (m !== null)
5473
+ newDate.setMinutes(m);
5474
+ newDate.setSeconds(0);
5475
+ }
5476
+ onChange?.(dayjs(newDate).tz(timezone).toISOString());
5477
+ };
5478
+ const handleClear = () => {
5479
+ setSelectedDate("");
5480
+ setHour12(null);
5481
+ setHour24(null);
5482
+ setMinute(null);
5483
+ setSecond(null);
5484
+ setMeridiem(null);
5485
+ onChange?.(undefined);
5486
+ };
5487
+ const isISO = format === "iso-date-time";
5488
+ return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsxRuntime.jsx(DatePicker$1, { selected: selectedDate
5489
+ ? dayjs(selectedDate).tz(timezone).toDate()
5490
+ : new Date(), onDateSelected: ({ date }) => handleDateChange(dayjs(date).tz(timezone).toISOString()), monthsToDisplay: 1, labels: labels }), jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsxRuntime.jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: second, setSecond: setSecond, onChange: handleTimeChange })) : (jsxRuntime.jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsxRuntime.jsx(react.Icon, { as: fa6.FaTrash }) })] }), selectedDate && (jsxRuntime.jsxs(react.Flex, { gap: 2, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).format(isISO
5491
+ ? showSeconds
5492
+ ? "YYYY-MM-DD HH:mm:ss"
5493
+ : "YYYY-MM-DD HH:mm"
5494
+ : "YYYY-MM-DD hh:mm A ") }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).tz(timezone).format("Z") }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: timezone })] }))] }));
5495
+ }
5496
+
5497
+ dayjs.extend(utc);
5498
+ dayjs.extend(timezone);
5499
+ const DateTimePicker = ({ column, schema, prefix, }) => {
5500
+ const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5501
+ const { timezone } = useSchemaContext();
5502
+ const formI18n = useFormI18n(column, prefix);
5503
+ const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
5504
+ // with timezone
5505
+ dateFormat = "YYYY-MM-DD[T]HH:mm:ssZ", } = schema;
5506
+ const isRequired = required?.some((columnId) => columnId === column);
5507
+ const colLabel = formI18n.colLabel;
5508
+ const [open, setOpen] = React.useState(false);
5509
+ const selectedDate = watch(colLabel);
5510
+ const displayDate = dayjs(selectedDate)
5511
+ .tz(timezone)
5512
+ .format(displayDateFormat);
5513
+ React.useEffect(() => {
5514
+ try {
5515
+ if (selectedDate) {
5516
+ // Parse the selectedDate as UTC or in a specific timezone to avoid +8 hour shift
5517
+ // For example, parse as UTC:
5518
+ const parsedDate = dayjs(selectedDate).tz(timezone);
5519
+ if (!parsedDate.isValid())
5520
+ return;
5521
+ // Format according to dateFormat from schema
5522
+ const formatted = parsedDate.format(dateFormat);
5523
+ // Update the form value only if different to avoid loops
5524
+ if (formatted !== selectedDate) {
5525
+ setValue(colLabel, formatted, {
5526
+ shouldValidate: true,
5527
+ shouldDirty: true,
5528
+ });
5529
+ }
5530
+ }
5531
+ }
5532
+ catch (e) {
5533
+ console.error(e);
5534
+ }
5535
+ }, [selectedDate, dateFormat, colLabel, setValue]);
5536
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
5537
+ gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5538
+ setOpen(true);
5539
+ }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { minW: "450px", children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5540
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5541
+ }, timezone: timezone, labels: {
5542
+ monthNamesShort: [
5543
+ formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
5544
+ formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
5545
+ formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
5546
+ formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
5547
+ formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
5548
+ formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
5549
+ formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
5550
+ formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
5551
+ formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
5552
+ formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
5553
+ formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
5554
+ formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
5555
+ ],
5556
+ weekdayNamesShort: [
5557
+ formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
5558
+ formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
5559
+ formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
5560
+ formI18n.translate.t(`common.weekday_4`, {
5561
+ defaultValue: "Wed",
5562
+ }),
5563
+ formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
5564
+ formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
5565
+ formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
5566
+ ],
5567
+ backButtonLabel: formI18n.translate.t(`common.back_button`, {
5568
+ defaultValue: "Back",
5569
+ }),
5570
+ forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
5571
+ defaultValue: "Forward",
5572
+ }),
5573
+ } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
5574
+ };
5575
+
4557
5576
  const SchemaRenderer = ({ schema, prefix, column, }) => {
4558
5577
  const colSchema = schema;
4559
- const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5578
+ const { type, variant, properties: innerProperties, foreign_key, format, items, } = schema;
5579
+ if (variant === "custom-input") {
5580
+ return jsxRuntime.jsx(CustomInput, { schema: colSchema, prefix, column });
5581
+ }
4560
5582
  if (type === "string") {
4561
5583
  if ((schema.enum ?? []).length > 0) {
4562
5584
  return jsxRuntime.jsx(EnumPicker, { schema: colSchema, prefix, column });
@@ -4565,9 +5587,18 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
4565
5587
  idPickerSanityCheck(column, foreign_key);
4566
5588
  return jsxRuntime.jsx(IdPicker, { schema: colSchema, prefix, column });
4567
5589
  }
4568
- if (variant === "date-picker") {
5590
+ if (format === "date") {
4569
5591
  return jsxRuntime.jsx(DatePicker, { schema: colSchema, prefix, column });
4570
5592
  }
5593
+ if (format === "time") {
5594
+ return jsxRuntime.jsx(TimePicker, { schema: colSchema, prefix, column });
5595
+ }
5596
+ if (format === "date-time") {
5597
+ return jsxRuntime.jsx(DateTimePicker, { schema: colSchema, prefix, column });
5598
+ }
5599
+ if (variant === "text-area") {
5600
+ return jsxRuntime.jsx(TextAreaInput, { schema: colSchema, prefix, column });
5601
+ }
4571
5602
  return jsxRuntime.jsx(StringInputField, { schema: colSchema, prefix, column });
4572
5603
  }
4573
5604
  if (type === "number" || type === "integer") {
@@ -4593,6 +5624,15 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
4593
5624
  if (variant === "file-picker") {
4594
5625
  return jsxRuntime.jsx(FilePicker, { schema: colSchema, prefix, column });
4595
5626
  }
5627
+ if (variant === "enum-picker") {
5628
+ const { items } = colSchema;
5629
+ const { enum: enumItems } = items;
5630
+ const enumSchema = {
5631
+ type: "string",
5632
+ enum: enumItems,
5633
+ };
5634
+ return (jsxRuntime.jsx(EnumPicker, { isMultiple: true, schema: enumSchema, prefix, column }));
5635
+ }
4596
5636
  if (items) {
4597
5637
  return jsxRuntime.jsx(ArrayRenderer, { schema: colSchema, prefix, column });
4598
5638
  }
@@ -4614,85 +5654,95 @@ const ColumnRenderer = ({ column, properties, prefix, }) => {
4614
5654
  };
4615
5655
 
4616
5656
  const ArrayViewer = ({ schema, column, prefix }) => {
4617
- const { gridRow, gridColumn = "1/span 12", required, items } = schema;
5657
+ const { gridColumn = "span 12", gridRow = "span 1", required, items, } = schema;
4618
5658
  const { translate } = useSchemaContext();
4619
5659
  const colLabel = `${prefix}${column}`;
4620
5660
  const isRequired = required?.some((columnId) => columnId === column);
4621
5661
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4622
5662
  const values = watch(colLabel) ?? [];
4623
- return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), values.map((field, index) => (jsxRuntime.jsx(react.Flex, { flexFlow: "column", children: jsxRuntime.jsx(react.Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: jsxRuntime.jsx(SchemaViewer, { column: `${index}`,
4624
- prefix: `${colLabel}.`,
4625
- schema: items }) }) }, `form-${prefix}${column}.${index}`))), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5663
+ return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: values.map((field, index) => (jsxRuntime.jsx(react.Flex, { flexFlow: "column", bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: "2", borderRadius: "md", borderWidth: "thin", borderColor: {
5664
+ base: "colorPalette.200",
5665
+ _dark: "colorPalette.800",
5666
+ }, children: jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsxRuntime.jsx(SchemaViewer, { column: `${index}`,
5667
+ prefix: `${colLabel}.`,
5668
+ // @ts-expect-error find suitable types
5669
+ schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4626
5670
  };
4627
5671
 
4628
5672
  const BooleanViewer = ({ schema, column, prefix, }) => {
4629
5673
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4630
5674
  const { translate } = useSchemaContext();
4631
- const { required, gridColumn, gridRow } = schema;
5675
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4632
5676
  const isRequired = required?.some((columnId) => columnId === column);
4633
5677
  const colLabel = `${prefix}${column}`;
4634
5678
  const value = watch(colLabel);
4635
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5679
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4636
5680
  gridRow, children: [jsxRuntime.jsx(react.Text, { children: value
4637
5681
  ? translate.t(removeIndex(`${colLabel}.true`))
4638
- : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5682
+ : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5683
+ };
5684
+
5685
+ const CustomViewer = ({ column, schema, prefix }) => {
5686
+ const formContext = reactHookForm.useFormContext();
5687
+ const { inputViewerRender } = schema;
5688
+ return (inputViewerRender &&
5689
+ inputViewerRender({
5690
+ column,
5691
+ schema,
5692
+ prefix,
5693
+ formContext,
5694
+ }));
4639
5695
  };
4640
5696
 
4641
5697
  const DateViewer = ({ column, schema, prefix }) => {
4642
5698
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4643
- const { translate } = useSchemaContext();
4644
- const { required, gridColumn, gridRow } = schema;
5699
+ const { translate, timezone } = useSchemaContext();
5700
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", } = schema;
4645
5701
  const isRequired = required?.some((columnId) => columnId === column);
4646
5702
  const colLabel = `${prefix}${column}`;
4647
5703
  const selectedDate = watch(colLabel);
4648
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4649
- gridRow, children: [jsxRuntime.jsxs(react.Text, { children: [" ", selectedDate !== undefined ? selectedDate : ""] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
5704
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
5705
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5706
+ gridRow, children: [jsxRuntime.jsxs(react.Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4650
5707
  };
4651
5708
 
4652
5709
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
4653
5710
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4654
- const { translate } = useSchemaContext();
5711
+ const formI18n = useFormI18n(column, prefix);
4655
5712
  const { required } = schema;
4656
5713
  const isRequired = required?.some((columnId) => columnId === column);
4657
- const { gridColumn, gridRow, renderDisplay } = schema;
4658
- const colLabel = `${prefix}${column}`;
5714
+ const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
5715
+ const colLabel = formI18n.colLabel;
4659
5716
  const watchEnum = watch(colLabel);
4660
5717
  const watchEnums = (watch(colLabel) ?? []);
4661
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5718
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4662
5719
  gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 1, children: watchEnums.map((enumValue) => {
4663
5720
  const item = enumValue;
4664
5721
  if (item === undefined) {
4665
5722
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "undefined" });
4666
5723
  }
4667
- return (jsxRuntime.jsx(Tag, { closable: true, children: !!renderDisplay === true
5724
+ return (jsxRuntime.jsx(Tag, { size: "lg", children: !!renderDisplay === true
4668
5725
  ? renderDisplay(item)
4669
- : translate.t(removeIndex(`${colLabel}.${item}`)) }));
4670
- }) })), !isMultiple && (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5726
+ : formI18n.t(item) }, item));
5727
+ }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: formI18n.t(watchEnum) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
4671
5728
  };
4672
5729
 
4673
5730
  const FileViewer = ({ column, schema, prefix }) => {
4674
- const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
5731
+ const { watch } = reactHookForm.useFormContext();
4675
5732
  const { translate } = useSchemaContext();
4676
- const { required, gridColumn, gridRow } = schema;
5733
+ const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
4677
5734
  const isRequired = required?.some((columnId) => columnId === column);
4678
5735
  const currentFiles = (watch(column) ?? []);
4679
5736
  const colLabel = `${prefix}${column}`;
4680
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.fieldLabel`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4681
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4682
- setValue(colLabel, [...currentFiles, ...newFiles]);
4683
- }, placeholder: translate.t(`${colLabel}.fileDropzone`) }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4684
- return (jsxRuntime.jsx(react.Card.Root, { variant: "subtle", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4685
- setValue(column, currentFiles.filter(({ name }) => {
4686
- return name !== file.name;
4687
- }));
4688
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4689
- }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5737
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
5738
+ return (jsxRuntime.jsx(react.Card.Root, { variant: "subtle", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name })] }) }, file.name));
5739
+ }) }) }));
4690
5740
  };
4691
5741
 
4692
5742
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4693
5743
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4694
5744
  const { idMap, translate } = useSchemaContext();
4695
- const { required, gridColumn, gridRow, renderDisplay, foreign_key } = schema;
5745
+ const { required, gridColumn = "span 12", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
4696
5746
  const isRequired = required?.some((columnId) => columnId === column);
4697
5747
  const { display_column } = foreign_key;
4698
5748
  const colLabel = `${prefix}${column}`;
@@ -4708,7 +5758,7 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4708
5758
  }
4709
5759
  return record[display_column];
4710
5760
  };
4711
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5761
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4712
5762
  gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", gap: 1, children: watchIds.map((id) => {
4713
5763
  const item = idMap[id];
4714
5764
  if (item === undefined) {
@@ -4717,21 +5767,21 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4717
5767
  return (jsxRuntime.jsx(Tag, { closable: true, children: !!renderDisplay === true
4718
5768
  ? renderDisplay(item)
4719
5769
  : item[display_column] }, id));
4720
- }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5770
+ }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4721
5771
  };
4722
5772
 
4723
5773
  const NumberViewer = ({ schema, column, prefix, }) => {
4724
5774
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4725
5775
  const { translate } = useSchemaContext();
4726
- const { required, gridColumn, gridRow } = schema;
5776
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4727
5777
  const isRequired = required?.some((columnId) => columnId === column);
4728
5778
  const colLabel = `${prefix}${column}`;
4729
5779
  const value = watch(colLabel);
4730
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(react.Text, { children: value }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5780
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(react.Text, { children: value }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4731
5781
  };
4732
5782
 
4733
5783
  const ObjectViewer = ({ schema, column, prefix }) => {
4734
- const { properties, gridRow, gridColumn = "1/span 12", required } = schema;
5784
+ const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
4735
5785
  const { translate } = useSchemaContext();
4736
5786
  const colLabel = `${prefix}${column}`;
4737
5787
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4739,25 +5789,28 @@ const ObjectViewer = ({ schema, column, prefix }) => {
4739
5789
  if (properties === undefined) {
4740
5790
  throw new Error(`properties is undefined when using ObjectInput`);
4741
5791
  }
4742
- return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: Object.keys(properties ?? {}).map((key) => {
5792
+ return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: "1", borderRadius: "md", borderWidth: "thin", borderColor: {
5793
+ base: "colorPalette.200",
5794
+ _dark: "colorPalette.800",
5795
+ }, children: Object.keys(properties ?? {}).map((key) => {
4743
5796
  return (
4744
5797
  // @ts-expect-error find suitable types
4745
5798
  jsxRuntime.jsx(ColumnViewer, { column: `${key}`,
4746
5799
  prefix: `${prefix}${column}.`,
4747
5800
  properties }, `form-objectviewer-${colLabel}-${key}`));
4748
- }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5801
+ }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4749
5802
  };
4750
5803
 
4751
5804
  const RecordInput = ({ column, schema, prefix }) => {
4752
5805
  const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
4753
5806
  const { translate } = useSchemaContext();
4754
- const { required, gridColumn, gridRow } = schema;
5807
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4755
5808
  const isRequired = required?.some((columnId) => columnId === column);
4756
5809
  const entries = Object.entries(getValues(column) ?? {});
4757
5810
  const [showNewEntries, setShowNewEntries] = React.useState(false);
4758
5811
  const [newKey, setNewKey] = React.useState();
4759
5812
  const [newValue, setNewValue] = React.useState();
4760
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.fieldLabel`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
5813
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4761
5814
  return (jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
4762
5815
  const filtered = entries.filter(([target]) => {
4763
5816
  return target !== key;
@@ -4797,7 +5850,17 @@ const RecordInput = ({ column, schema, prefix }) => {
4797
5850
  setShowNewEntries(true);
4798
5851
  setNewKey(undefined);
4799
5852
  setNewValue(undefined);
4800
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
5853
+ }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5854
+ };
5855
+
5856
+ const StringViewer = ({ column, schema, prefix, }) => {
5857
+ const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5858
+ const { translate } = useSchemaContext();
5859
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5860
+ const isRequired = required?.some((columnId) => columnId === column);
5861
+ const colLabel = `${prefix}${column}`;
5862
+ const value = watch(colLabel);
5863
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Text, { children: value }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4801
5864
  };
4802
5865
 
4803
5866
  const TagViewer = ({ column, schema, prefix }) => {
@@ -4885,19 +5948,50 @@ const TagViewer = ({ column, schema, prefix }) => {
4885
5948
  }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4886
5949
  };
4887
5950
 
4888
- const StringViewer = ({ column, schema, prefix, }) => {
5951
+ const TextAreaViewer = ({ column, schema, prefix, }) => {
4889
5952
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4890
5953
  const { translate } = useSchemaContext();
4891
- const { required, gridColumn, gridRow } = schema;
5954
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4892
5955
  const isRequired = required?.some((columnId) => columnId === column);
4893
5956
  const colLabel = `${prefix}${column}`;
4894
5957
  const value = watch(colLabel);
4895
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Text, { children: value }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }) }));
5958
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsxRuntime.jsx(react.Text, { whiteSpace: "pre-wrap", children: value }), " ", errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5959
+ };
5960
+
5961
+ const TimeViewer = ({ column, schema, prefix }) => {
5962
+ const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5963
+ const { translate, timezone } = useSchemaContext();
5964
+ const { required, gridColumn = "span 12", gridRow = "span 1", displayTimeFormat = "hh:mm A", } = schema;
5965
+ const isRequired = required?.some((columnId) => columnId === column);
5966
+ const colLabel = `${prefix}${column}`;
5967
+ const selectedDate = watch(colLabel);
5968
+ const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
5969
+ .tz(timezone)
5970
+ .isValid()
5971
+ ? dayjs(`1970-01-01T${selectedDate}`).tz(timezone).format(displayTimeFormat)
5972
+ : "";
5973
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5974
+ gridRow, children: [jsxRuntime.jsx(react.Text, { children: displayedTime }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5975
+ };
5976
+
5977
+ const DateTimeViewer = ({ column, schema, prefix }) => {
5978
+ const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5979
+ const { translate, timezone } = useSchemaContext();
5980
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss", } = schema;
5981
+ const isRequired = required?.some((columnId) => columnId === column);
5982
+ const colLabel = `${prefix}${column}`;
5983
+ const selectedDate = watch(colLabel);
5984
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
5985
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5986
+ gridRow, children: [jsxRuntime.jsxs(react.Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4896
5987
  };
4897
5988
 
4898
5989
  const SchemaViewer = ({ schema, prefix, column, }) => {
4899
5990
  const colSchema = schema;
4900
- const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5991
+ const { type, variant, properties: innerProperties, foreign_key, items, format, } = schema;
5992
+ if (variant === "custom-input") {
5993
+ return jsxRuntime.jsx(CustomViewer, { schema: colSchema, prefix, column });
5994
+ }
4901
5995
  if (type === "string") {
4902
5996
  if ((schema.enum ?? []).length > 0) {
4903
5997
  return jsxRuntime.jsx(EnumViewer, { schema: colSchema, prefix, column });
@@ -4906,9 +6000,18 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
4906
6000
  idPickerSanityCheck(column, foreign_key);
4907
6001
  return jsxRuntime.jsx(IdViewer, { schema: colSchema, prefix, column });
4908
6002
  }
4909
- if (variant === "date-picker") {
6003
+ if (format === "time") {
6004
+ return jsxRuntime.jsx(TimeViewer, { schema: colSchema, prefix, column });
6005
+ }
6006
+ if (format === "date") {
4910
6007
  return jsxRuntime.jsx(DateViewer, { schema: colSchema, prefix, column });
4911
6008
  }
6009
+ if (format === "date-time") {
6010
+ return jsxRuntime.jsx(DateTimeViewer, { schema: colSchema, prefix, column });
6011
+ }
6012
+ if (variant === "text-area") {
6013
+ return jsxRuntime.jsx(TextAreaViewer, { schema: colSchema, prefix, column });
6014
+ }
4912
6015
  return jsxRuntime.jsx(StringViewer, { schema: colSchema, prefix, column });
4913
6016
  }
4914
6017
  if (type === "number" || type === "integer") {
@@ -4934,6 +6037,15 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
4934
6037
  if (variant === "file-picker") {
4935
6038
  return jsxRuntime.jsx(FileViewer, { schema: colSchema, prefix, column });
4936
6039
  }
6040
+ if (variant === "enum-picker") {
6041
+ const { items } = schema;
6042
+ const { enum: enumItems } = items;
6043
+ const enumSchema = {
6044
+ type: "string",
6045
+ enum: enumItems,
6046
+ };
6047
+ return (jsxRuntime.jsx(EnumViewer, { isMultiple: true, schema: enumSchema, prefix, column }));
6048
+ }
4937
6049
  if (items) {
4938
6050
  return jsxRuntime.jsx(ArrayViewer, { schema: colSchema, prefix, column });
4939
6051
  }
@@ -4957,10 +6069,20 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
4957
6069
  };
4958
6070
 
4959
6071
  const SubmitButton = () => {
4960
- const { translate, setValidatedData, setIsError, setIsConfirming } = useSchemaContext();
6072
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
4961
6073
  const methods = reactHookForm.useFormContext();
4962
6074
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4963
6075
  const onValid = (data) => {
6076
+ const { isValid, errors } = validateData(data, schema);
6077
+ if (!isValid) {
6078
+ setError({
6079
+ type: "validation",
6080
+ errors,
6081
+ });
6082
+ setIsError(true);
6083
+ return;
6084
+ }
6085
+ // If validation passes, proceed to confirmation
4964
6086
  setValidatedData(data);
4965
6087
  setIsError(false);
4966
6088
  setIsConfirming(true);
@@ -4971,7 +6093,8 @@ const SubmitButton = () => {
4971
6093
  };
4972
6094
 
4973
6095
  const FormBody = () => {
4974
- const { schema, requestUrl, order, ignore, include, onSubmit, rowNumber, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, } = useSchemaContext();
6096
+ const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, displayConfig, } = useSchemaContext();
6097
+ const { showSubmitButton, showResetButton } = displayConfig;
4975
6098
  const methods = reactHookForm.useFormContext();
4976
6099
  const { properties } = schema;
4977
6100
  const onBeforeSubmit = () => {
@@ -4987,6 +6110,26 @@ const FormBody = () => {
4987
6110
  const onSubmitSuccess = () => {
4988
6111
  setIsSuccess(true);
4989
6112
  };
6113
+ const validateFormData = (data) => {
6114
+ try {
6115
+ const { isValid, errors } = validateData(data, schema);
6116
+ return {
6117
+ isValid,
6118
+ errors,
6119
+ };
6120
+ }
6121
+ catch (error) {
6122
+ return {
6123
+ isValid: false,
6124
+ errors: [
6125
+ {
6126
+ field: "validation",
6127
+ message: error instanceof Error ? error.message : "Unknown error",
6128
+ },
6129
+ ],
6130
+ };
6131
+ }
6132
+ };
4990
6133
  const defaultOnSubmit = async (promise) => {
4991
6134
  try {
4992
6135
  onBeforeSubmit();
@@ -5011,12 +6154,28 @@ const FormBody = () => {
5011
6154
  };
5012
6155
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5013
6156
  const onFormSubmit = async (data) => {
6157
+ // Validate data using AJV before submission
6158
+ const validationResult = validateFormData(data);
6159
+ if (!validationResult.isValid) {
6160
+ // Set validation errors
6161
+ const validationErrorMessage = {
6162
+ type: "validation",
6163
+ errors: validationResult.errors,
6164
+ message: translate.t("validation_error"),
6165
+ };
6166
+ onSubmitError(validationErrorMessage);
6167
+ return;
6168
+ }
5014
6169
  if (onSubmit === undefined) {
5015
6170
  await defaultOnSubmit(defaultSubmitPromise(data));
5016
6171
  return;
5017
6172
  }
5018
6173
  await defaultOnSubmit(onSubmit(data));
5019
6174
  };
6175
+ // Custom error renderer for validation errors with i18n support
6176
+ const renderValidationErrors = (validationErrors) => {
6177
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxRuntime.jsxs(react.Alert.Root, { status: "error", display: "flex", alignItems: "center", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Description, { children: err.message }) })] }, index))) }));
6178
+ };
5020
6179
  const renderColumns = ({ order, keys, ignore, include, }) => {
5021
6180
  const included = include.length > 0 ? include : keys;
5022
6181
  const not_exist = included.filter((columnA) => !order.some((columnB) => columnA === columnB));
@@ -5031,7 +6190,7 @@ const FormBody = () => {
5031
6190
  include,
5032
6191
  });
5033
6192
  if (isSuccess) {
5034
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submitSuccess") })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
6193
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submit_success") }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
5035
6194
  setIsError(false);
5036
6195
  setIsSubmiting(false);
5037
6196
  setIsSuccess(false);
@@ -5039,10 +6198,10 @@ const FormBody = () => {
5039
6198
  setValidatedData(undefined);
5040
6199
  const data = await getUpdatedData();
5041
6200
  methods.reset(data);
5042
- }, formNoValidate: true, children: translate.t("submitAgain") }) })] }));
6201
+ }, formNoValidate: true, children: translate.t("submit_again") }) })] }));
5043
6202
  }
5044
6203
  if (isConfirming) {
5045
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat(${rowNumber ?? "auto-fit"}, auto)`, children: ordered.map((column) => {
6204
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: "repeat(12, max-content)", autoFlow: "row", children: ordered.map((column) => {
5046
6205
  return (jsxRuntime.jsx(ColumnViewer
5047
6206
  // @ts-expect-error find suitable types
5048
6207
  , {
@@ -5052,17 +6211,19 @@ const FormBody = () => {
5052
6211
  setIsConfirming(false);
5053
6212
  }, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
5054
6213
  onFormSubmit(validatedData);
5055
- }, children: translate.t("confirm") })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(react.Alert.Root, { status: "error", children: jsxRuntime.jsx(react.Alert.Title, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsxs(AccordionItemTrigger, { children: [jsxRuntime.jsx(react.Alert.Indicator, {}), `${error}`] }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) }) }) }))] }));
6214
+ }, children: translate.t("confirm") })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
6215
+ error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
5056
6216
  }
5057
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat(${rowNumber ?? "auto-fit"}, auto)`, children: ordered.map((column) => {
6217
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
5058
6218
  return (jsxRuntime.jsx(ColumnRenderer
5059
6219
  // @ts-expect-error find suitable types
5060
6220
  , {
5061
6221
  // @ts-expect-error find suitable types
5062
6222
  properties: properties, prefix: ``, column }, `form-input-${column}`));
5063
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6223
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
5064
6224
  methods.reset();
5065
- }, variant: "subtle", children: translate.t("reset") }), jsxRuntime.jsx(SubmitButton, {})] })] }));
6225
+ }, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
6226
+ error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
5066
6227
  };
5067
6228
 
5068
6229
  const FormTitle = () => {
@@ -5071,7 +6232,8 @@ const FormTitle = () => {
5071
6232
  };
5072
6233
 
5073
6234
  const DefaultForm = ({ formConfig, }) => {
5074
- return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
6235
+ const { showTitle } = formConfig.displayConfig ?? {};
6236
+ return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
5075
6237
  };
5076
6238
 
5077
6239
  const useForm = ({ preLoadedValues, keyPrefix }) => {
@@ -5116,7 +6278,6 @@ exports.EditSortingButton = EditSortingButton;
5116
6278
  exports.EmptyState = EmptyState$1;
5117
6279
  exports.ErrorAlert = ErrorAlert;
5118
6280
  exports.FilterDialog = FilterDialog;
5119
- exports.FilterOptions = FilterOptions;
5120
6281
  exports.FormBody = FormBody;
5121
6282
  exports.FormRoot = FormRoot;
5122
6283
  exports.FormTitle = FormTitle;
@@ -5135,6 +6296,7 @@ exports.TableCardContainer = TableCardContainer;
5135
6296
  exports.TableCards = TableCards;
5136
6297
  exports.TableComponent = TableComponent;
5137
6298
  exports.TableControls = TableControls;
6299
+ exports.TableDataDisplay = TableDataDisplay;
5138
6300
  exports.TableFilter = TableFilter;
5139
6301
  exports.TableFilterTags = TableFilterTags;
5140
6302
  exports.TableFooter = TableFooter;