@bsol-oss/react-datatable5 12.0.0-beta.6 → 12.0.0-beta.61

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 (74) hide show
  1. package/README.md +192 -0
  2. package/dist/index.d.ts +212 -91
  3. package/dist/index.js +1399 -426
  4. package/dist/index.mjs +1405 -432
  5. package/dist/types/components/DataTable/DataTable.d.ts +4 -2
  6. package/dist/types/components/DataTable/DataTableServer.d.ts +4 -2
  7. package/dist/types/components/DataTable/DefaultTable.d.ts +9 -12
  8. package/dist/types/components/DataTable/context/DataTableContext.d.ts +22 -3
  9. package/dist/types/components/DataTable/context/useDataTableContext.d.ts +2 -2
  10. package/dist/types/components/DataTable/controls/DensityFeature.d.ts +23 -0
  11. package/dist/types/components/DataTable/controls/DensityToggleButton.d.ts +6 -0
  12. package/dist/types/components/DataTable/controls/EditSortingButton.d.ts +7 -0
  13. package/dist/types/components/DataTable/controls/FilterDialog.d.ts +5 -0
  14. package/dist/types/components/DataTable/controls/PageSizeControl.d.ts +4 -0
  15. package/dist/types/components/DataTable/controls/Pagination.d.ts +1 -0
  16. package/dist/types/components/DataTable/controls/ReloadButton.d.ts +4 -0
  17. package/dist/types/components/DataTable/controls/ResetFilteringButton.d.ts +1 -0
  18. package/dist/types/components/DataTable/controls/ResetSelectionButton.d.ts +1 -0
  19. package/dist/types/components/DataTable/controls/ResetSortingButton.d.ts +1 -0
  20. package/dist/types/components/DataTable/controls/RowCountText.d.ts +1 -0
  21. package/dist/types/components/DataTable/controls/SelectAllRowsToggle.d.ts +8 -0
  22. package/dist/types/components/DataTable/controls/TableControls.d.ts +29 -0
  23. package/dist/types/components/DataTable/controls/TableFilterTags.d.ts +1 -0
  24. package/dist/types/components/DataTable/controls/TableFilters.d.ts +1 -0
  25. package/dist/types/components/DataTable/controls/TableSelector.d.ts +1 -0
  26. package/dist/types/components/DataTable/controls/TableSorter.d.ts +1 -0
  27. package/dist/types/components/DataTable/controls/TableViewer.d.ts +1 -0
  28. package/dist/types/components/DataTable/controls/ViewDialog.d.ts +5 -0
  29. package/dist/types/components/DataTable/display/CardHeader.d.ts +13 -0
  30. package/dist/types/components/DataTable/display/DataDisplay.d.ts +6 -0
  31. package/dist/types/components/DataTable/display/EmptyState.d.ts +5 -0
  32. package/dist/types/components/DataTable/display/ErrorAlert.d.ts +4 -0
  33. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +9 -0
  34. package/dist/types/components/DataTable/display/Table.d.ts +10 -0
  35. package/dist/types/components/DataTable/display/TableBody.d.ts +20 -0
  36. package/dist/types/components/DataTable/display/TableCardContainer.d.ts +10 -0
  37. package/dist/types/components/DataTable/display/TableCards.d.ts +11 -0
  38. package/dist/types/components/DataTable/display/TableComponent.d.ts +6 -0
  39. package/dist/types/components/DataTable/display/TableDataDisplay.d.ts +6 -0
  40. package/dist/types/components/DataTable/display/TableFooter.d.ts +5 -0
  41. package/dist/types/components/DataTable/display/TableHeader.d.ts +51 -0
  42. package/dist/types/components/DataTable/display/TableLoadingComponent.d.ts +5 -0
  43. package/dist/types/components/DataTable/display/TextCell.d.ts +10 -0
  44. package/dist/types/components/DataTable/useDataTable.d.ts +1 -1
  45. package/dist/types/components/DatePicker/DatePicker.d.ts +23 -0
  46. package/dist/types/components/DatePicker/DateTimePicker.d.ts +11 -0
  47. package/dist/types/components/DatePicker/DurationPicker.d.ts +12 -0
  48. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +16 -0
  49. package/dist/types/components/DatePicker/PickerDemo.d.ts +1 -0
  50. package/dist/types/components/DatePicker/UniversalPicker.d.ts +9 -0
  51. package/dist/types/components/DatePicker/index.d.ts +7 -0
  52. package/dist/types/components/Filter/TagFilter.d.ts +5 -1
  53. package/dist/types/components/Form/SchemaFormContext.d.ts +3 -1
  54. package/dist/types/components/Form/components/core/DefaultForm.d.ts +2 -1
  55. package/dist/types/components/Form/components/core/FormRoot.d.ts +4 -2
  56. package/dist/types/components/Form/components/fields/CustomInput.d.ts +8 -0
  57. package/dist/types/components/Form/components/fields/DatePicker.d.ts +2 -7
  58. package/dist/types/components/Form/components/fields/DateTimePicker.d.ts +2 -0
  59. package/dist/types/components/Form/components/fields/EnumPicker.d.ts +2 -1
  60. package/dist/types/components/Form/components/fields/FilePicker.d.ts +2 -5
  61. package/dist/types/components/Form/components/fields/StringInputField.d.ts +2 -5
  62. package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +12 -0
  63. package/dist/types/components/Form/components/fields/TimePicker.d.ts +7 -0
  64. package/dist/types/components/Form/components/fields/types.d.ts +6 -0
  65. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +19 -1
  66. package/dist/types/components/Form/components/viewers/CustomViewer.d.ts +8 -0
  67. package/dist/types/components/Form/components/viewers/DateTimeViewer.d.ts +7 -0
  68. package/dist/types/components/Form/components/viewers/TextAreaViewer.d.ts +12 -0
  69. package/dist/types/components/Form/components/viewers/TimeViewer.d.ts +7 -0
  70. package/dist/types/components/Form/utils/translateWrapper.d.ts +6 -0
  71. package/dist/types/components/Form/utils/validation.d.ts +104 -0
  72. package/dist/types/components/TimePicker/TimePicker.d.ts +20 -0
  73. package/dist/types/index.d.ts +48 -33
  74. package/package.json +9 -2
package/dist/index.mjs CHANGED
@@ -1,23 +1,23 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Checkbox as Checkbox$1, Table as Table$1, Tooltip as Tooltip$1, Group, InputElement, Icon, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, List, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Textarea, Center, AlertRoot, AlertIndicator, AlertContent, AlertTitle, AlertDescription, Heading } from '@chakra-ui/react';
3
3
  import { AiOutlineColumnWidth } from 'react-icons/ai';
4
4
  import * as React from 'react';
5
5
  import React__default, { createContext, useContext, useState, useEffect, useRef } from 'react';
6
6
  import { LuX, LuCheck, LuChevronRight, LuChevronDown } from 'react-icons/lu';
7
- import { MdOutlineSort, MdFilterAlt, MdSearch, MdClose, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist } from 'react-icons/md';
8
- import { FaUpDown, FaGripLinesVertical } from 'react-icons/fa6';
7
+ import { MdOutlineSort, MdFilterAlt, MdSearch, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist, MdDateRange } from 'react-icons/md';
8
+ import { FaUpDown, FaGripLinesVertical, FaTrash } from 'react-icons/fa6';
9
9
  import { BiDownArrow, BiUpArrow, BiError } from 'react-icons/bi';
10
- import { CgClose } from 'react-icons/cg';
10
+ import { CgClose, CgTrash } from 'react-icons/cg';
11
11
  import Dayzed from '@bsol-oss/dayzed-react19';
12
12
  import { HiMiniEllipsisHorizontal, HiChevronLeft, HiChevronRight } from 'react-icons/hi2';
13
- import { IoMdEye, IoMdCheckbox } from 'react-icons/io';
13
+ import { IoMdEye, IoMdCheckbox, IoMdClock } from 'react-icons/io';
14
14
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
15
15
  import { bind, bindAll } from 'bind-event-listener';
16
16
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
17
17
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
18
18
  import rafSchd from 'raf-schd';
19
19
  import invariant from 'tiny-invariant';
20
- import { HiColorSwatch } from 'react-icons/hi';
20
+ import { HiColorSwatch, HiOutlineInformationCircle } from 'react-icons/hi';
21
21
  import { flexRender, makeStateUpdater, functionalUpdate, useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel, createColumnHelper } from '@tanstack/react-table';
22
22
  import { rankItem } from '@tanstack/match-sorter-utils';
23
23
  import { BsExclamationCircleFill } from 'react-icons/bs';
@@ -29,7 +29,12 @@ import { useTranslation } from 'react-i18next';
29
29
  import axios from 'axios';
30
30
  import { FormProvider, useFormContext, useForm as useForm$1 } from 'react-hook-form';
31
31
  import dayjs from 'dayjs';
32
+ import utc from 'dayjs/plugin/utc';
33
+ import timezone from 'dayjs/plugin/timezone';
32
34
  import { TiDeleteOutline } from 'react-icons/ti';
35
+ import Ajv from 'ajv';
36
+ import addFormats from 'ajv-formats';
37
+ import addErrors from 'ajv-errors';
33
38
 
34
39
  const DataTableContext = createContext({
35
40
  table: {},
@@ -37,6 +42,56 @@ const DataTableContext = createContext({
37
42
  setGlobalFilter: () => { },
38
43
  type: "client",
39
44
  translate: {},
45
+ data: [],
46
+ columns: [],
47
+ columnOrder: [],
48
+ columnFilters: [],
49
+ density: "sm",
50
+ sorting: [],
51
+ setPagination: function () {
52
+ throw new Error("Function not implemented.");
53
+ },
54
+ setSorting: function () {
55
+ throw new Error("Function not implemented.");
56
+ },
57
+ setColumnFilters: function () {
58
+ throw new Error("Function not implemented.");
59
+ },
60
+ setRowSelection: function () {
61
+ throw new Error("Function not implemented.");
62
+ },
63
+ setColumnOrder: function () {
64
+ throw new Error("Function not implemented.");
65
+ },
66
+ setDensity: function () {
67
+ throw new Error("Function not implemented.");
68
+ },
69
+ setColumnVisibility: function () {
70
+ throw new Error("Function not implemented.");
71
+ },
72
+ pagination: {
73
+ pageIndex: 0,
74
+ pageSize: 10,
75
+ },
76
+ rowSelection: {},
77
+ columnVisibility: {},
78
+ tableLabel: {
79
+ view: "View",
80
+ edit: "Edit",
81
+ filterButtonText: "Filter",
82
+ filterTitle: "Filter",
83
+ filterReset: "Reset",
84
+ filterClose: "Close",
85
+ reloadTooltip: "Reload",
86
+ reloadButtonText: "Reload",
87
+ resetSelection: "Reset Selection",
88
+ resetSorting: "Reset Sorting",
89
+ rowCountText: "Row Count",
90
+ hasErrorText: "Has Error",
91
+ globalFilterPlaceholder: "Search",
92
+ trueLabel: "True",
93
+ falseLabel: "False",
94
+ },
40
95
  });
41
96
 
42
97
  const useDataTableContext = () => {
@@ -92,11 +147,13 @@ const TableSorter = () => {
92
147
  }) }))) }));
93
148
  };
94
149
 
95
- const ResetSortingButton = ({ text = "Reset Sorting", }) => {
150
+ const ResetSortingButton = () => {
96
151
  const { table } = useDataTableContext();
152
+ const { tableLabel } = useDataTableContext();
153
+ const { resetSorting } = tableLabel;
97
154
  return (jsx(Button$1, { onClick: () => {
98
155
  table.resetSorting();
99
- }, children: text }));
156
+ }, children: resetSorting }));
100
157
  };
101
158
 
102
159
  const EditSortingButton = ({ text, icon = jsx(MdOutlineSort, {}), title = "Edit Sorting", }) => {
@@ -124,7 +181,7 @@ const monthNamesFull = [
124
181
  "November",
125
182
  "December",
126
183
  ];
127
- const weekdayNamesShort$1 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
184
+ const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
128
185
  function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, selected = [], firstDayOfWeek = 0, }) {
129
186
  const [hoveredDate, setHoveredDate] = useState();
130
187
  const onMouseLeave = () => {
@@ -159,7 +216,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
159
216
  offset: 12,
160
217
  }), children: ">>" })] }), jsx(Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", gap: 4, children: calendars.map((calendar) => (jsxs(Grid, { gap: 4, children: [jsxs(Grid, { justifyContent: "center", children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsx(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
161
218
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
162
- return (jsx(Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort$1[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
219
+ return (jsx(Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
163
220
  }) }), jsx(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
164
221
  const key = `${calendar.month}${calendar.year}${windex}${index}`;
165
222
  if (!dateObj) {
@@ -280,8 +337,17 @@ const Tag = React.forwardRef(function Tag(props, ref) {
280
337
  return (jsxs(Tag$1.Root, { ref: ref, ...rest, children: [startElement && (jsx(Tag$1.StartElement, { children: startElement })), jsx(Tag$1.Label, { children: children }), endElement && (jsx(Tag$1.EndElement, { children: endElement })), closable && (jsx(Tag$1.EndElement, { children: jsx(Tag$1.CloseTrigger, { onClick: onClose }) }))] }));
281
338
  });
282
339
 
283
- const TagFilter = ({ availableTags, selectedTags, onTagChange, }) => {
340
+ const TagFilter = ({ availableTags, selectedTags, onTagChange, selectOne = false, }) => {
284
341
  const toggleTag = (tag) => {
342
+ if (selectOne) {
343
+ if (selectedTags.includes(tag)) {
344
+ onTagChange([]);
345
+ }
346
+ else {
347
+ onTagChange([tag]);
348
+ }
349
+ return;
350
+ }
285
351
  if (selectedTags.includes(tag)) {
286
352
  onTagChange(selectedTags.filter((t) => t !== tag));
287
353
  }
@@ -289,10 +355,14 @@ const TagFilter = ({ availableTags, selectedTags, onTagChange, }) => {
289
355
  onTagChange([...selectedTags, tag]);
290
356
  }
291
357
  };
292
- return (jsx(Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => (jsx(Tag, { variant: selectedTags.includes(tag) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(tag) ? true : undefined, onClick: () => toggleTag(tag), children: tag }))) }));
358
+ return (jsx(Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => {
359
+ const { label, value } = tag;
360
+ return (jsx(Tag, { variant: selectedTags.includes(value) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(value) ? true : undefined, onClick: () => toggleTag(value), children: label ?? value }));
361
+ }) }));
293
362
  };
294
363
 
295
364
  const Filter = ({ column }) => {
365
+ const { tableLabel } = useDataTableContext();
296
366
  const { filterVariant } = column.columnDef.meta ?? {};
297
367
  const displayName = column.columnDef.meta?.displayName ?? column.id;
298
368
  const filterOptions = column.columnDef.meta?.filterOptions ?? [];
@@ -307,10 +377,14 @@ const Filter = ({ column }) => {
307
377
  if (filterVariant === "select") {
308
378
  return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onValueChange: (details) => {
309
379
  column.setFilterValue(details.value);
310
- }, children: jsx(Flex, { flexFlow: "wrap", gap: "0.5rem", children: filterOptions.map((item) => (jsx(Radio, { value: item, children: item }, item))) }) })] }, column.id));
380
+ }, children: jsxs(Flex, { flexFlow: "wrap", gap: "0.5rem", children: [filterOptions.length === 0 && jsx(Text, { children: "No filter options" }), filterOptions.length > 0 &&
381
+ filterOptions.map((item) => (jsx(Radio, { value: item.value, children: item.label }, item.value)))] }) })] }, column.id));
311
382
  }
312
383
  if (filterVariant === "tag") {
313
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: filterOptions, selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
384
+ return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
385
+ label: item.label,
386
+ value: item.value,
387
+ })), selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
314
388
  if (tags.length === 0) {
315
389
  return column.setFilterValue(undefined);
316
390
  }
@@ -318,7 +392,11 @@ const Filter = ({ column }) => {
318
392
  } })] }, column.id));
319
393
  }
320
394
  if (filterVariant === "boolean") {
321
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: ["true", "false"], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
395
+ const { trueLabel, falseLabel } = tableLabel;
396
+ return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: [
397
+ { label: trueLabel, value: "true" },
398
+ { label: falseLabel, value: "false" },
399
+ ], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
322
400
  if (tags.length === 0) {
323
401
  return column.setFilterValue(undefined);
324
402
  }
@@ -373,17 +451,20 @@ const TableFilter = () => {
373
451
  }) }));
374
452
  };
375
453
 
376
- const ResetFilteringButton = ({ text = "Reset Filtering", }) => {
454
+ const ResetFilteringButton = () => {
377
455
  const { table } = useDataTableContext();
456
+ const { tableLabel } = useDataTableContext();
457
+ const { filterReset } = tableLabel;
378
458
  return (jsx(Button$1, { onClick: () => {
379
459
  table.resetColumnFilters();
380
- }, children: text }));
460
+ }, children: filterReset }));
381
461
  };
382
462
 
383
463
  const FilterDialog = ({ icon = jsx(MdFilterAlt, {}), }) => {
384
464
  const filterModal = useDisclosure();
385
- const { translate } = useDataTableContext();
386
- return (jsxs(DialogRoot, { size: ["full", "full", "md", "md"], open: filterModal.open, children: [jsx(DialogTrigger, { asChild: true, children: jsxs(Button$1, { as: Box, variant: "ghost", onClick: filterModal.onOpen, children: [icon, " ", translate.t("filterDialog.buttonText")] }) }), jsxs(DialogContent, { children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: translate.t("filterDialog.title") }) }), jsx(DialogBody, { display: "flex", flexFlow: "column", children: jsx(TableFilter, {}) }), jsxs(DialogFooter, { children: [jsx(ResetFilteringButton, { text: translate.t("filterDialog.reset") }), jsx(Button$1, { onClick: filterModal.onClose, variant: "subtle", children: translate.t("filterDialog.close") })] }), jsx(DialogCloseTrigger, { onClick: filterModal.onClose })] })] }));
465
+ const { tableLabel } = useDataTableContext();
466
+ const { filterButtonText, filterTitle, filterClose } = tableLabel;
467
+ return (jsxs(DialogRoot, { size: ["full", "full", "md", "md"], open: filterModal.open, children: [jsx(DialogTrigger, { asChild: true, children: jsxs(Button$1, { as: Box, variant: "ghost", onClick: filterModal.onOpen, children: [icon, " ", filterButtonText] }) }), jsxs(DialogContent, { children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: filterTitle }) }), jsx(DialogBody, { display: "flex", flexFlow: "column", children: jsx(TableFilter, {}) }), jsxs(DialogFooter, { children: [jsx(ResetFilteringButton, {}), jsx(Button$1, { onClick: filterModal.onClose, variant: "subtle", children: filterClose })] }), jsx(DialogCloseTrigger, { onClick: filterModal.onClose })] })] }));
387
468
  };
388
469
 
389
470
  const MenuContent = React.forwardRef(function MenuContent(props, ref) {
@@ -502,11 +583,13 @@ const Pagination = () => {
502
583
  }, children: jsxs(HStack, { children: [jsx(PaginationPrevTrigger, {}), jsx(PaginationItems, {}), jsx(PaginationNextTrigger, {})] }) }));
503
584
  };
504
585
 
505
- const ResetSelectionButton = ({ text = "Reset Selection", }) => {
586
+ const ResetSelectionButton = () => {
506
587
  const { table } = useDataTableContext();
588
+ const { tableLabel } = useDataTableContext();
589
+ const { resetSelection } = tableLabel;
507
590
  return (jsx(Button$1, { onClick: () => {
508
591
  table.resetRowSelection();
509
- }, children: text }));
592
+ }, children: resetSelection }));
510
593
  };
511
594
 
512
595
  const RowCountText = () => {
@@ -2421,8 +2504,8 @@ CheckboxCard$1.Indicator;
2421
2504
  function ColumnCard({ columnId }) {
2422
2505
  const ref = useRef(null);
2423
2506
  const [dragging, setDragging] = useState(false); // NEW
2424
- const { table } = useDataTableContext();
2425
- const displayName = columnId;
2507
+ const { table, translate } = useDataTableContext();
2508
+ const displayName = translate.t(columnId);
2426
2509
  const column = table.getColumn(columnId);
2427
2510
  invariant(column);
2428
2511
  useEffect(() => {
@@ -2437,7 +2520,7 @@ function ColumnCard({ columnId }) {
2437
2520
  onDrop: () => setDragging(false), // NEW
2438
2521
  });
2439
2522
  }, [columnId, table]);
2440
- return (jsxs(Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsx(Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsx(FaGripLinesVertical, { color: "gray.400" }) }), jsx(Flex, { justifyContent: "space-between", alignItems: "center", children: jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2523
+ return (jsxs(Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsx(Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsx(FaGripLinesVertical, { color: "colorPalette.400" }) }), jsx(Flex, { justifyContent: "space-between", alignItems: "center", children: jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2441
2524
  }
2442
2525
  function CardContainer({ location, children }) {
2443
2526
  const ref = useRef(null);
@@ -2456,7 +2539,6 @@ function CardContainer({ location, children }) {
2456
2539
  onDrop: () => setIsDraggedOver(false),
2457
2540
  });
2458
2541
  }, [location]);
2459
- // const isDark = (location + location) % 2 === 1;
2460
2542
  function getColor(isDraggedOver) {
2461
2543
  if (isDraggedOver) {
2462
2544
  return {
@@ -2466,7 +2548,6 @@ function CardContainer({ location, children }) {
2466
2548
  },
2467
2549
  };
2468
2550
  }
2469
- // return isDark ? "lightgrey" : "white";
2470
2551
  return {
2471
2552
  backgroundColor: undefined,
2472
2553
  _dark: {
@@ -2517,8 +2598,9 @@ const TableViewer = () => {
2517
2598
 
2518
2599
  const ViewDialog = ({ icon = jsx(IoMdEye, {}) }) => {
2519
2600
  const viewModel = useDisclosure();
2520
- const { translate } = useDataTableContext();
2521
- return (jsxs(DialogRoot, { children: [jsx(DialogBackdrop, {}), jsx(DialogTrigger, { asChild: true, children: jsxs(Button$1, { as: Box, variant: "ghost", onClick: viewModel.onOpen, children: [icon, " ", translate.t("viewDialog.buttonText")] }) }), jsxs(DialogContent, { children: [jsx(DialogCloseTrigger, {}), jsx(DialogHeader, { children: jsx(DialogTitle, { children: translate.t("viewDialog.title") }) }), jsx(DialogBody, { children: jsx(TableViewer, {}) }), jsx(DialogFooter, {})] })] }));
2601
+ const { tableLabel } = useDataTableContext();
2602
+ const { view } = tableLabel;
2603
+ return (jsxs(DialogRoot, { children: [jsx(DialogBackdrop, {}), jsx(DialogTrigger, { asChild: true, children: jsxs(Button$1, { as: Box, variant: "ghost", onClick: viewModel.onOpen, children: [icon, " ", view] }) }), jsxs(DialogContent, { children: [jsx(DialogCloseTrigger, {}), jsx(DialogHeader, { children: jsx(DialogTitle, { children: view }) }), jsx(DialogBody, { children: jsx(TableViewer, {}) }), jsx(DialogFooter, {})] })] }));
2522
2604
  };
2523
2605
 
2524
2606
  const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
@@ -2569,7 +2651,7 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
2569
2651
  return jsx(Fragment, { children: "null" });
2570
2652
  }
2571
2653
  return (jsx(Grid, { rowGap: 1, padding: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
2572
- return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsx(Text, { color: "gray.400", children: getColumn({ field }) }), typeof value === "object" ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsx(Text, { children: JSON.stringify(value) }))] }, field));
2654
+ return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsx(Text, { color: "colorPalette.400", children: getColumn({ field }) }), typeof value === "object" ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsx(Text, { children: JSON.stringify(value) }))] }, field));
2573
2655
  }) }));
2574
2656
  };
2575
2657
 
@@ -2619,7 +2701,7 @@ const CellRenderer = ({ cell }) => {
2619
2701
  paddingY: 2,
2620
2702
  }, object: value })] }, cell.id));
2621
2703
  }
2622
- return (jsxs(Box, { gridColumn, gridRow, children: [jsx(Box, { color: 'gray.400', children: getLabel({ columnId: cell.column.id }) }), jsx(Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
2704
+ return (jsxs(Box, { gridColumn, gridRow, children: [jsx(Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsx(Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
2623
2705
  };
2624
2706
  const DataDisplay = ({ variant = "" }) => {
2625
2707
  const { table, translate } = useDataTableContext();
@@ -2741,7 +2823,23 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
2741
2823
  *
2742
2824
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
2743
2825
  */
2744
- 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, }) {
2826
+ 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 = {
2827
+ view: "View",
2828
+ edit: "Edit",
2829
+ filterButtonText: "Filter",
2830
+ filterTitle: "Filter",
2831
+ filterReset: "Reset",
2832
+ filterClose: "Close",
2833
+ reloadTooltip: "Reload",
2834
+ reloadButtonText: "Reload",
2835
+ resetSelection: "Reset Selection",
2836
+ resetSorting: "Reset Sorting",
2837
+ rowCountText: "Row Count",
2838
+ hasErrorText: "Has Error",
2839
+ globalFilterPlaceholder: "Search",
2840
+ trueLabel: "True",
2841
+ falseLabel: "False",
2842
+ }, }) {
2745
2843
  const table = useReactTable({
2746
2844
  _features: [DensityFeature],
2747
2845
  data: data,
@@ -2794,6 +2892,23 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
2794
2892
  setGlobalFilter,
2795
2893
  type: "client",
2796
2894
  translate,
2895
+ columns: columns,
2896
+ sorting,
2897
+ setSorting,
2898
+ columnFilters,
2899
+ setColumnFilters,
2900
+ pagination,
2901
+ setPagination,
2902
+ rowSelection,
2903
+ setRowSelection,
2904
+ columnOrder,
2905
+ setColumnOrder,
2906
+ density,
2907
+ setDensity,
2908
+ columnVisibility,
2909
+ setColumnVisibility,
2910
+ data,
2911
+ tableLabel,
2797
2912
  }, children: children }));
2798
2913
  }
2799
2914
 
@@ -2808,10 +2923,26 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
2808
2923
  *
2809
2924
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
2810
2925
  */
2811
- 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, }) {
2926
+ 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 = {
2927
+ view: "View",
2928
+ edit: "Edit",
2929
+ filterButtonText: "Filter",
2930
+ filterTitle: "Filter",
2931
+ filterReset: "Reset",
2932
+ filterClose: "Close",
2933
+ reloadTooltip: "Reload",
2934
+ reloadButtonText: "Reload",
2935
+ resetSelection: "Reset Selection",
2936
+ resetSorting: "Reset Sorting",
2937
+ rowCountText: "Row Count",
2938
+ hasErrorText: "Has Error",
2939
+ globalFilterPlaceholder: "Search",
2940
+ trueLabel: "True",
2941
+ falseLabel: "False",
2942
+ }, }) {
2812
2943
  const table = useReactTable({
2813
2944
  _features: [DensityFeature],
2814
- data: query.data?.data ?? [],
2945
+ data: (query.data?.data ?? []),
2815
2946
  rowCount: query.data?.count ?? 0,
2816
2947
  columns: columns,
2817
2948
  getCoreRowModel: getCoreRowModel(),
@@ -2857,103 +2988,31 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
2857
2988
  // for tanstack-table ts bug end
2858
2989
  });
2859
2990
  return (jsx(DataTableContext.Provider, { value: {
2860
- table: { ...table },
2991
+ table: table,
2861
2992
  globalFilter,
2862
2993
  setGlobalFilter,
2863
2994
  type: "server",
2864
2995
  translate,
2996
+ columns: columns,
2997
+ sorting,
2998
+ setSorting,
2999
+ columnFilters,
3000
+ setColumnFilters,
3001
+ pagination,
3002
+ setPagination,
3003
+ rowSelection,
3004
+ setRowSelection,
3005
+ columnOrder,
3006
+ setColumnOrder,
3007
+ density,
3008
+ setDensity,
3009
+ columnVisibility,
3010
+ setColumnVisibility,
3011
+ data: query.data?.data ?? [],
3012
+ tableLabel,
2865
3013
  }, children: jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
2866
3014
  }
2867
3015
 
2868
- const Checkbox = React.forwardRef(function Checkbox(props, ref) {
2869
- const { icon, children, inputProps, rootRef, ...rest } = props;
2870
- return (jsxs(Checkbox$1.Root, { ref: rootRef, ...rest, children: [jsx(Checkbox$1.HiddenInput, { ref: ref, ...inputProps }), jsx(Checkbox$1.Control, { children: icon || jsx(Checkbox$1.Indicator, {}) }), children != null && (jsx(Checkbox$1.Label, { children: children }))] }));
2871
- });
2872
-
2873
- const TableBody = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, alwaysShowSelector = true, canResize = true, }) => {
2874
- "use no memo";
2875
- const { table } = useDataTableContext();
2876
- const SELECTION_BOX_WIDTH = 20;
2877
- const [hoveredRow, setHoveredRow] = useState(-1);
2878
- const handleRowHover = (index) => {
2879
- setHoveredRow(index);
2880
- };
2881
- const getTdProps = (cell) => {
2882
- const tdProps = cell.column.getIsPinned()
2883
- ? {
2884
- left: showSelector
2885
- ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
2886
- : `${cell.column.getStart("left")}px`,
2887
- background: pinnedBgColor.light,
2888
- position: "sticky",
2889
- zIndex: -1,
2890
- _dark: {
2891
- backgroundColor: pinnedBgColor.dark,
2892
- },
2893
- }
2894
- : {};
2895
- return tdProps;
2896
- };
2897
- const getTrProps = ({ hoveredRow, index, }) => {
2898
- if (hoveredRow === -1) {
2899
- return {};
2900
- }
2901
- if (hoveredRow === index) {
2902
- return {
2903
- opacity: "1",
2904
- };
2905
- }
2906
- return {
2907
- opacity: "0.8",
2908
- };
2909
- };
2910
- return (jsx(Table$1.Body, { children: table.getRowModel().rows.map((row, index) => {
2911
- return (jsxs(Table$1.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow, alwaysShowSelector: alwaysShowSelector })), row.getVisibleCells().map((cell, index) => {
2912
- return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`,
2913
- // styling resize and pinning start
2914
- flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`, backgroundColor: "white", ...getTdProps(cell), _dark: {
2915
- backgroundColor: "gray.950",
2916
- }, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
2917
- })] }, `chakra-table-row-${row.id}`));
2918
- }) }));
2919
- };
2920
- const TableRowSelector = ({ index, row, hoveredRow, pinnedBgColor = { light: "gray.50", dark: "gray.700" }, alwaysShowSelector = true, }) => {
2921
- const { table } = useDataTableContext();
2922
- const SELECTION_BOX_WIDTH = 20;
2923
- const isCheckBoxVisible = (current_index, current_row) => {
2924
- if (alwaysShowSelector) {
2925
- return true;
2926
- }
2927
- if (current_row.getIsSelected()) {
2928
- return true;
2929
- }
2930
- if (hoveredRow == current_index) {
2931
- return true;
2932
- }
2933
- return false;
2934
- };
2935
- return (jsxs(Table$1.Cell, { padding: `${table.getDensityValue()}px`, ...(table.getIsSomeColumnsPinned("left")
2936
- ? {
2937
- left: `0px`,
2938
- backgroundColor: pinnedBgColor.light,
2939
- position: "sticky",
2940
- zIndex: 1,
2941
- _dark: { backgroundColor: pinnedBgColor.dark },
2942
- }
2943
- : {}),
2944
- // styling resize and pinning end
2945
- display: "grid", children: [!isCheckBoxVisible(index, row) && (jsx(Box, { as: "span", margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` })), isCheckBoxVisible(index, row) && (jsx(Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: row.getIsSelected(),
2946
- disabled: !row.getCanSelect(),
2947
- onChange: row.getToggleSelectedHandler() }) }))] }));
2948
- };
2949
-
2950
- const Tooltip = React.forwardRef(function Tooltip(props, ref) {
2951
- const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
2952
- if (disabled)
2953
- return children;
2954
- return (jsxs(Tooltip$1.Root, { ...rest, children: [jsx(Tooltip$1.Trigger, { asChild: true, children: children }), jsx(Portal, { disabled: !portalled, container: portalRef, children: jsx(Tooltip$1.Positioner, { children: jsxs(Tooltip$1.Content, { ref: ref, ...contentProps, children: [showArrow && (jsx(Tooltip$1.Arrow, { children: jsx(Tooltip$1.ArrowTip, {}) })), content] }) }) })] }));
2955
- });
2956
-
2957
3016
  const InputGroup = React.forwardRef(function InputGroup(props, ref) {
2958
3017
  const { startElement, startElementProps, endElement, endElementProps, children, startOffset = "6px", endOffset = "6px", ...rest } = props;
2959
3018
  return (jsxs(Group, { ref: ref, ...rest, children: [startElement && (jsx(InputElement, { pointerEvents: "none", ...startElementProps, children: startElement })), React.cloneElement(children, {
@@ -2967,7 +3026,8 @@ const InputGroup = React.forwardRef(function InputGroup(props, ref) {
2967
3026
  });
2968
3027
 
2969
3028
  const GlobalFilter = () => {
2970
- const { table } = useDataTableContext();
3029
+ const { table, tableLabel } = useDataTableContext();
3030
+ const { globalFilterPlaceholder } = tableLabel;
2971
3031
  const [searchTerm, setSearchTerm] = useState("");
2972
3032
  const debouncedSearchTerm = useDebounce(searchTerm, 500);
2973
3033
  useEffect(() => {
@@ -2976,42 +3036,31 @@ const GlobalFilter = () => {
2976
3036
  };
2977
3037
  searchHN();
2978
3038
  }, [debouncedSearchTerm]);
2979
- return (jsx(Fragment, { children: jsx(InputGroup, { flex: "1", startElement: jsx(MdSearch, {}), children: jsx(Input, { placeholder: "Outline", variant: "outline", onChange: (e) => {
3039
+ return (jsx(Fragment, { children: jsx(InputGroup, { flex: "1", startElement: jsx(MdSearch, {}), children: jsx(Input, { placeholder: globalFilterPlaceholder, variant: "outline", onChange: (e) => {
2980
3040
  setSearchTerm(e.target.value);
2981
3041
  } }) }) }));
2982
3042
  };
2983
3043
 
2984
- const ReloadButton = ({ text = "Reload", variant = "icon", }) => {
3044
+ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
3045
+ const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
3046
+ if (disabled)
3047
+ return children;
3048
+ return (jsxs(Tooltip$1.Root, { ...rest, children: [jsx(Tooltip$1.Trigger, { asChild: true, children: children }), jsx(Portal, { disabled: !portalled, container: portalRef, children: jsx(Tooltip$1.Positioner, { children: jsxs(Tooltip$1.Content, { ref: ref, ...contentProps, children: [showArrow && (jsx(Tooltip$1.Arrow, { children: jsx(Tooltip$1.ArrowTip, {}) })), content] }) }) })] }));
3049
+ });
3050
+
3051
+ const ReloadButton = ({ variant = "icon", }) => {
2985
3052
  const { url } = useDataTableServerContext();
2986
3053
  const queryClient = useQueryClient();
3054
+ const { tableLabel } = useDataTableContext();
3055
+ const { reloadTooltip, reloadButtonText } = tableLabel;
2987
3056
  if (variant === "icon") {
2988
- return (jsx(Tooltip, { showArrow: true, content: "This is the tooltip content", children: jsx(Button, { variant: "ghost", onClick: () => {
3057
+ return (jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsx(Button, { variant: "ghost", onClick: () => {
2989
3058
  queryClient.invalidateQueries({ queryKey: [url] });
2990
3059
  }, "aria-label": "refresh", children: jsx(IoReload, {}) }) }));
2991
3060
  }
2992
3061
  return (jsxs(Button, { variant: "ghost", onClick: () => {
2993
3062
  queryClient.invalidateQueries({ queryKey: [url] });
2994
- }, children: [jsx(IoReload, {}), " ", text] }));
2995
- };
2996
-
2997
- const FilterOptions = ({ column }) => {
2998
- const { table } = useDataTableContext();
2999
- const tableColumn = table.getColumn(column);
3000
- const options = tableColumn?.columnDef.meta?.filterOptions ?? [];
3001
- return (jsx(Fragment, { children: options.map((option) => {
3002
- const selected = table.getColumn(column)?.getFilterValue() === option;
3003
- return (jsxs(Button$1, { size: "sm", onClick: () => {
3004
- if (selected) {
3005
- table.setColumnFilters((state) => {
3006
- return state.filter((filter) => {
3007
- return filter.id !== column;
3008
- });
3009
- });
3010
- return;
3011
- }
3012
- table.getColumn(column)?.setFilterValue(option);
3013
- }, variant: selected ? "solid" : "outline", display: "flex", gap: "0.25rem", children: [option, selected && jsx(MdClose, {})] }, option));
3014
- }) }));
3063
+ }, children: [jsx(IoReload, {}), " ", reloadButtonText] }));
3015
3064
  };
3016
3065
 
3017
3066
  const TableFilterTags = () => {
@@ -3025,16 +3074,99 @@ const TableFilterTags = () => {
3025
3074
  }) }));
3026
3075
  };
3027
3076
 
3028
- const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsx(Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterOptions = [], extraItems = jsx(Fragment, {}), loading = false, hasError = false, }) => {
3029
- const { translate } = useDataTableContext();
3030
- return (jsxs(Grid, { templateRows: "auto 1fr auto", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", children: [jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsxs(Flex, { justifyContent: "space-between", children: [jsx(Box, { children: showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }) }), jsxs(Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsx(Spinner, { size: "sm" }), hasError && (jsx(Tooltip, { content: translate.t("hasError"), children: jsx(Icon, { as: BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterOptions.length > 0 && (jsx(Flex, { flexFlow: "column", gap: "0.5rem", children: filterOptions.map((column) => {
3031
- return (jsxs(Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [showFilterName && jsxs(Text, { children: [column, ":"] }), jsx(FilterOptions, { column: column })] }, column));
3032
- }) })), showFilterTags && (jsx(Flex, { children: jsx(TableFilterTags, {}) }))] }), jsx(Grid, { overflow: "auto", backgroundColor: "gray.50", _dark: {
3033
- backgroundColor: "gray.900",
3034
- }, children: children }), jsxs(Flex, { justifyContent: "space-between", children: [jsxs(Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && (jsxs(Flex, { children: [jsx(Text, { paddingRight: "0.5rem", children: translate.t("rowcount.total") }), jsx(RowCountText, {})] }))] }), jsx(Box, { justifySelf: "end", children: showPagination && jsx(Pagination, {}) })] })] }));
3077
+ const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsx(Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsx(Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
3078
+ const { tableLabel, table } = useDataTableContext();
3079
+ const { rowCountText, hasErrorText } = tableLabel;
3080
+ return (jsxs(Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsxs(Flex, { justifyContent: "space-between", children: [jsx(Box, { children: showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }) }), jsxs(Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsx(Spinner, { size: "sm" }), hasError && (jsx(Tooltip, { content: hasErrorText, children: jsx(Icon, { as: BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsx(Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
3081
+ const { column, options } = option;
3082
+ const tableColumn = table.getColumn(column);
3083
+ return (jsxs(Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsx(Text, { children: tableColumn?.columnDef.meta?.displayName })), jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
3084
+ if (tags.length === 0) {
3085
+ return tableColumn?.setFilterValue(undefined);
3086
+ }
3087
+ tableColumn?.setFilterValue(tags);
3088
+ } })] }, column));
3089
+ }) })), showFilterTags && (jsx(Flex, { children: jsx(TableFilterTags, {}) }))] }), jsx(Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxs(Flex, { justifyContent: "space-between", children: [jsxs(Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && (jsxs(Flex, { children: [jsx(Text, { paddingRight: "0.5rem", children: rowCountText }), jsx(RowCountText, {})] }))] }), jsx(Box, { justifySelf: "end", children: showPagination && jsx(Pagination, {}) })] }))] }));
3090
+ };
3091
+
3092
+ const EmptyState = React.forwardRef(function EmptyState(props, ref) {
3093
+ const { title, description, icon, children, ...rest } = props;
3094
+ return (jsx(EmptyState$2.Root, { ref: ref, ...rest, children: jsxs(EmptyState$2.Content, { children: [icon && (jsx(EmptyState$2.Indicator, { children: icon })), description ? (jsxs(VStack, { textAlign: "center", children: [jsx(EmptyState$2.Title, { children: title }), jsx(EmptyState$2.Description, { children: description })] })) : (jsx(EmptyState$2.Title, { children: title })), children] }) }));
3095
+ });
3096
+
3097
+ const EmptyResult = (jsx(EmptyState, { icon: jsx(HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxs(List.Root, { variant: "marker", children: [jsx(List.Item, { children: "Try removing filters" }), jsx(List.Item, { children: "Try different keywords" })] }) }));
3098
+ const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
3099
+ const { table } = useDataTableContext();
3100
+ if (table.getRowModel().rows.length <= 0) {
3101
+ return emptyComponent;
3102
+ }
3103
+ return (jsx(Table$1.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 }));
3104
+ };
3105
+
3106
+ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
3107
+ const { icon, children, inputProps, rootRef, ...rest } = props;
3108
+ return (jsxs(Checkbox$1.Root, { ref: rootRef, ...rest, children: [jsx(Checkbox$1.HiddenInput, { ref: ref, ...inputProps }), jsx(Checkbox$1.Control, { children: icon || jsx(Checkbox$1.Indicator, {}) }), children != null && (jsx(Checkbox$1.Label, { children: children }))] }));
3109
+ });
3110
+
3111
+ const TableBody = ({ showSelector = false, canResize = true, }) => {
3112
+ "use no memo";
3113
+ const { table } = useDataTableContext();
3114
+ const SELECTION_BOX_WIDTH = 20;
3115
+ const [hoveredRow, setHoveredRow] = useState(-1);
3116
+ const handleRowHover = (index) => {
3117
+ setHoveredRow(index);
3118
+ };
3119
+ const getTdProps = (cell) => {
3120
+ const tdProps = cell.column.getIsPinned()
3121
+ ? {
3122
+ left: showSelector
3123
+ ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3124
+ : `${cell.column.getStart("left")}px`,
3125
+ position: "relative",
3126
+ }
3127
+ : {};
3128
+ return tdProps;
3129
+ };
3130
+ const getTrProps = ({ hoveredRow, index, }) => {
3131
+ if (hoveredRow === -1) {
3132
+ return {};
3133
+ }
3134
+ if (hoveredRow === index) {
3135
+ return {
3136
+ opacity: "1",
3137
+ };
3138
+ }
3139
+ return {
3140
+ opacity: "0.8",
3141
+ };
3142
+ };
3143
+ return (jsx(Table$1.Body, { children: table.getRowModel().rows.map((row, index) => {
3144
+ return (jsxs(Table$1.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow })), row.getVisibleCells().map((cell, index) => {
3145
+ return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`,
3146
+ // styling resize and pinning start
3147
+ flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`,
3148
+ // this is to avoid the cell from being too wide
3149
+ minWidth: `0`, color: {
3150
+ base: "colorPalette.900",
3151
+ _dark: "colorPalette.100",
3152
+ },
3153
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(cell), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3154
+ })] }, `chakra-table-row-${row.id}`));
3155
+ }) }));
3156
+ };
3157
+ const TableRowSelector = ({ row, }) => {
3158
+ const { table } = useDataTableContext();
3159
+ const SELECTION_BOX_WIDTH = 20;
3160
+ return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
3161
+ base: "colorPalette.900",
3162
+ _dark: "colorPalette.100",
3163
+ },
3164
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: row.getIsSelected(),
3165
+ disabled: !row.getCanSelect(),
3166
+ onCheckedChange: row.getToggleSelectedHandler() }) }));
3035
3167
  };
3036
3168
 
3037
- const TableFooter = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, alwaysShowSelector = true, }) => {
3169
+ const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
3038
3170
  const table = useDataTableContext().table;
3039
3171
  const SELECTION_BOX_WIDTH = 20;
3040
3172
  const [hoveredCheckBox, setHoveredCheckBox] = useState(false);
@@ -3053,65 +3185,62 @@ const TableFooter = ({ pinnedBgColor = { light: "gray.50", dark: "gray.700" }, s
3053
3185
  }
3054
3186
  return false;
3055
3187
  };
3056
- const getThProps = (header) => {
3057
- const thProps = header.column.getIsPinned()
3058
- ? {
3059
- left: showSelector
3060
- ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3061
- : `${header.getStart("left") + table.getDensityValue() * 2}px`,
3062
- background: pinnedBgColor.light,
3063
- position: "sticky",
3064
- zIndex: 1,
3065
- _dark: {
3066
- backgroundColor: pinnedBgColor.dark,
3067
- },
3068
- }
3069
- : {};
3070
- return thProps;
3071
- };
3072
- return (jsx(Table$1.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxs(Table$1.Row, { display: "flex", children: [showSelector && (jsxs(Table$1.Header
3073
- // styling resize and pinning start
3074
- , {
3075
- // styling resize and pinning start
3076
- padding: `${table.getDensityValue()}px`, ...(table.getIsSomeColumnsPinned("left")
3077
- ? {
3078
- left: `0px`,
3079
- backgroundColor: pinnedBgColor.light,
3080
- position: "sticky",
3081
- zIndex: 1,
3082
- _dark: { backgroundColor: pinnedBgColor.dark },
3083
- }
3084
- : {}),
3085
- // styling resize and pinning end
3086
- onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsx(Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3188
+ return (jsx(Table$1.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxs(Table$1.Row, { display: "flex", children: [showSelector && (jsxs(Table$1.Header, { padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsx(Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3087
3189
  // indeterminate: table.getIsSomeRowsSelected(),
3088
3190
  onChange: table.getToggleAllRowsSelectedHandler() }) })), !isCheckBoxVisible() && (jsx(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) => (jsx(Table$1.Cell, { padding: "0", columnSpan: `${header.colSpan}`,
3089
3191
  // styling resize and pinning start
3090
- maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: "grid", ...getThProps(header), children: jsx(MenuRoot$1, { children: jsx(MenuTrigger$1, { asChild: true, children: jsx(Box, { padding: `${table.getDensityValue()}px`, display: "flex", alignItems: "center", justifyContent: "start", borderRadius: "0rem", _hover: { backgroundColor: "gray.100" }, children: jsxs(Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3192
+ maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: "grid", children: jsx(MenuRoot$1, { children: jsx(MenuTrigger$1, { asChild: true, children: jsx(Box, { padding: `${table.getDensityValue()}px`, display: "flex", alignItems: "center", justifyContent: "start", borderRadius: "0rem", children: jsxs(Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3091
3193
  ? null
3092
- : flexRender(header.column.columnDef.footer, header.getContext()), jsx(Box, { children: header.column.getCanSort() && (jsxs(Fragment, { children: [header.column.getIsSorted() === false && (
3093
- // <UpDownIcon />
3094
- jsx(Fragment, {})), header.column.getIsSorted() === "asc" && (jsx(BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsx(BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3194
+ : flexRender(header.column.columnDef.footer, header.getContext()), jsx(Box, { children: header.column.getCanSort() && (jsxs(Fragment, { children: [header.column.getIsSorted() === false && jsx(Fragment, {}), header.column.getIsSorted() === "asc" && (jsx(BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsx(BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3095
3195
  };
3096
3196
 
3097
- const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dark: "gray.700" }, showSelector = false, isSticky = true, alwaysShowSelector = true, tHeadProps = {}, }) => {
3197
+ // Default text values
3198
+ const DEFAULT_HEADER_TEXTS = {
3199
+ pinColumn: "Pin Column",
3200
+ cancelPin: "Cancel Pin",
3201
+ sortAscending: "Sort Ascending",
3202
+ sortDescending: "Sort Descending",
3203
+ clearSorting: "Clear Sorting",
3204
+ };
3205
+ /**
3206
+ * TableHeader component with configurable text strings.
3207
+ *
3208
+ * @example
3209
+ * // Using default texts
3210
+ * <TableHeader />
3211
+ *
3212
+ * @example
3213
+ * // Customizing default texts for all columns
3214
+ * <TableHeader
3215
+ * defaultTexts={{
3216
+ * pinColumn: "Pin This Column",
3217
+ * sortAscending: "Sort A-Z"
3218
+ * }}
3219
+ * />
3220
+ *
3221
+ * @example
3222
+ * // Customizing texts per column via meta
3223
+ * const columns = [
3224
+ * columnHelper.accessor("name", {
3225
+ * header: "Name",
3226
+ * meta: {
3227
+ * headerTexts: {
3228
+ * pinColumn: "Pin Name Column",
3229
+ * sortAscending: "Sort Names A-Z"
3230
+ * }
3231
+ * }
3232
+ * })
3233
+ * ];
3234
+ */
3235
+ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true, tableHeaderProps = {}, tableRowProps = {}, defaultTexts = {}, }) => {
3098
3236
  const { table } = useDataTableContext();
3099
3237
  const SELECTION_BOX_WIDTH = 20;
3100
- const [hoveredCheckBox, setHoveredCheckBox] = useState(false);
3101
- const handleRowHover = (isHovered) => {
3102
- setHoveredCheckBox(isHovered);
3103
- };
3104
- const isCheckBoxVisible = () => {
3105
- if (alwaysShowSelector) {
3106
- return true;
3107
- }
3108
- if (table.getIsAllRowsSelected()) {
3109
- return true;
3110
- }
3111
- if (hoveredCheckBox) {
3112
- return true;
3113
- }
3114
- return false;
3238
+ // Merge default texts with provided defaults
3239
+ const mergedDefaultTexts = { ...DEFAULT_HEADER_TEXTS, ...defaultTexts };
3240
+ // Helper function to get text for a specific header
3241
+ const getHeaderText = (header, key) => {
3242
+ const columnMeta = header.column.columnDef.meta;
3243
+ return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3115
3244
  };
3116
3245
  const getThProps = (header) => {
3117
3246
  const thProps = header.column.getIsPinned()
@@ -3119,12 +3248,8 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3119
3248
  left: showSelector
3120
3249
  ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3121
3250
  : `${header.getStart("left")}px`,
3122
- background: pinnedBgColor.light,
3123
3251
  position: "sticky",
3124
3252
  zIndex: 100 + 1,
3125
- _dark: {
3126
- backgroundColor: pinnedBgColor.dark,
3127
- },
3128
3253
  }
3129
3254
  : {};
3130
3255
  return thProps;
@@ -3133,21 +3258,13 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3133
3258
  position: "sticky",
3134
3259
  top: 0,
3135
3260
  };
3136
- return (jsx(Table$1.Header, { ...(isSticky ? stickyProps : {}), ...tHeadProps, children: table.getHeaderGroups().map((headerGroup) => (jsxs(Table$1.Row, { display: "flex", children: [showSelector && (jsxs(Table$1.ColumnHeader
3137
- // styling resize and pinning start
3138
- , { ...(table.getIsSomeColumnsPinned("left")
3139
- ? {
3140
- left: `0px`,
3141
- backgroundColor: pinnedBgColor.light,
3142
- position: "sticky",
3143
- zIndex: 1,
3144
- _dark: { backgroundColor: pinnedBgColor.dark },
3145
- }
3146
- : {}),
3147
- // styling resize and pinning end
3148
- padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: "grid", children: [isCheckBoxVisible() && (jsx(Box, { margin: "0rem", display: "grid", justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: table.getIsAllRowsSelected(),
3149
- // indeterminate: table.getIsSomeRowsSelected(),
3150
- onChange: table.getToggleAllRowsSelectedHandler() }) })), !isCheckBoxVisible() && (jsx(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) => {
3261
+ return (jsx(Table$1.Header, { ...(isSticky ? stickyProps : {}), bgColor: "transparent", ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxs(Table$1.Row, { display: "flex", bgColor: "transparent", ...tableRowProps, children: [showSelector && (jsx(Table$1.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
3262
+ base: "colorPalette.900",
3263
+ _dark: "colorPalette.100",
3264
+ },
3265
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: table.getIsAllRowsSelected(),
3266
+ // indeterminate: table.getIsSomeRowsSelected(),
3267
+ onChange: table.getToggleAllRowsSelectedHandler() }) })), headerGroup.headers.map((header) => {
3151
3268
  const resizeProps = {
3152
3269
  onMouseDown: header.getResizeHandler(),
3153
3270
  onTouchStart: header.getResizeHandler(),
@@ -3155,18 +3272,32 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3155
3272
  };
3156
3273
  return (jsxs(Table$1.ColumnHeader, { padding: 0, columnSpan: `${header.colSpan}`,
3157
3274
  // styling resize and pinning start
3158
- flex: `${canResize ? "0" : "1"} 0 ${header.column.getSize()}px`, display: "grid", gridTemplateColumns: "1fr auto", zIndex: 1500 + header.index, ...getThProps(header), children: [jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsx(Flex, { padding: `${table.getDensityValue()}px`, alignItems: "center", justifyContent: "start", borderRadius: "0rem", overflow: "auto", _hover: {
3159
- backgroundColor: "gray.100",
3160
- _dark: {
3161
- backgroundColor: "gray.700",
3275
+ flex: `${canResize ? "0" : "1"} 0 ${header.column.getSize()}px`, display: "grid", gridTemplateColumns: "1fr auto", zIndex: 1500 + header.index, color: {
3276
+ base: "colorPalette.800",
3277
+ _dark: "colorPalette.200",
3278
+ },
3279
+ bg: { base: "colorPalette.100", _dark: "colorPalette.900" }, ...getThProps(header), children: [jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsx(Flex, { padding: `${table.getDensityValue()}px`, alignItems: "center", justifyContent: "start", borderRadius: "0rem", overflow: "auto", color: {
3280
+ base: "colorPalette.800",
3281
+ _dark: "colorPalette.200",
3282
+ _hover: {
3283
+ base: "colorPalette.700",
3284
+ _dark: "colorPalette.300",
3285
+ },
3286
+ },
3287
+ bg: {
3288
+ base: "colorPalette.100",
3289
+ _dark: "colorPalette.900",
3290
+ _hover: {
3291
+ base: "colorPalette.200",
3292
+ _dark: "colorPalette.800",
3162
3293
  },
3163
3294
  }, children: jsxs(Flex, { gap: "0.5rem", alignItems: "center", children: [header.isPlaceholder
3164
3295
  ? null
3165
3296
  : flexRender(header.column.columnDef.header, header.getContext()), jsx(Box, { children: header.column.getCanSort() && (jsxs(Fragment, { children: [header.column.getIsSorted() === false && jsx(Fragment, {}), header.column.getIsSorted() === "asc" && (jsx(BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsx(BiDownArrow, {}))] })) }), jsx(Box, { children: header.column.getIsFiltered() && jsx(MdFilterListAlt, {}) })] }) }) }), jsxs(MenuContent, { children: [!header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "pin-column", children: jsxs(Button, { variant: "ghost", onClick: () => {
3166
3297
  header.column.pin("left");
3167
- }, children: [jsx(MdPushPin, {}), "Pin Column"] }) })), header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxs(Button, { variant: "ghost", onClick: () => {
3298
+ }, children: [jsx(MdPushPin, {}), getHeaderText(header, "pinColumn")] }) })), header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxs(Button, { variant: "ghost", onClick: () => {
3168
3299
  header.column.pin(false);
3169
- }, children: [jsx(MdCancel, {}), "Cancel Pin"] }) })), header.column.getCanSort() && (jsxs(Fragment, { children: [jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxs(Button, { variant: "ghost", onClick: () => {
3300
+ }, children: [jsx(MdCancel, {}), getHeaderText(header, "cancelPin")] }) })), header.column.getCanSort() && (jsxs(Fragment, { children: [jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxs(Button, { variant: "ghost", onClick: () => {
3170
3301
  table.setSorting((state) => {
3171
3302
  return [
3172
3303
  ...state.filter((column) => {
@@ -3175,7 +3306,7 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3175
3306
  { id: header.id, desc: false },
3176
3307
  ];
3177
3308
  });
3178
- }, children: [jsx(GrAscend, {}), "Sort Ascending"] }) }), jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxs(Button, { variant: "ghost", onClick: () => {
3309
+ }, children: [jsx(GrAscend, {}), getHeaderText(header, "sortAscending")] }) }), jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxs(Button, { variant: "ghost", onClick: () => {
3179
3310
  table.setSorting((state) => {
3180
3311
  return [
3181
3312
  ...state.filter((column) => {
@@ -3184,42 +3315,30 @@ const TableHeader = ({ canResize = true, pinnedBgColor = { light: "gray.50", dar
3184
3315
  { id: header.id, desc: true },
3185
3316
  ];
3186
3317
  });
3187
- }, children: [jsx(GrDescend, {}), "Sort Descending"] }) }), header.column.getIsSorted() && (jsx(MenuItem, { asChild: true, value: "sort-descend", children: jsxs(Button, { variant: "ghost", onClick: () => {
3318
+ }, children: [jsx(GrDescend, {}), getHeaderText(header, "sortDescending")] }) }), header.column.getIsSorted() && (jsx(MenuItem, { asChild: true, value: "clear-sorting", children: jsxs(Button, { variant: "ghost", onClick: () => {
3188
3319
  header.column.clearSorting();
3189
- }, children: [jsx(MdClear, {}), "Clear Sorting"] }) }))] }))] })] }), canResize && (jsx(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: {
3320
+ }, children: [jsx(MdClear, {}), getHeaderText(header, "clearSorting")] }) }))] }))] })] }), canResize && (jsx(Box, { borderRight: "0.2rem solid", borderRightColor: header.column.getIsResizing()
3321
+ ? "colorPalette.700"
3322
+ : "transparent", position: "relative", right: "0.1rem", width: "2px", height: "100%", userSelect: "none", style: { touchAction: "none" }, _hover: {
3190
3323
  borderRightColor: header.column.getIsResizing()
3191
- ? "gray.700"
3192
- : "gray.400",
3324
+ ? "colorPalette.700"
3325
+ : "colorPalette.400",
3193
3326
  }, ...resizeProps }))] }, `chakra-table-header-${header.id}`));
3194
3327
  })] }, `chakra-table-headergroup-${headerGroup.id}`))) }));
3195
3328
  };
3196
3329
 
3197
- const EmptyState = React.forwardRef(function EmptyState(props, ref) {
3198
- const { title, description, icon, children, ...rest } = props;
3199
- return (jsx(EmptyState$2.Root, { ref: ref, ...rest, children: jsxs(EmptyState$2.Content, { children: [icon && (jsx(EmptyState$2.Indicator, { children: icon })), description ? (jsxs(VStack, { textAlign: "center", children: [jsx(EmptyState$2.Title, { children: title }), jsx(EmptyState$2.Description, { children: description })] })) : (jsx(EmptyState$2.Title, { children: title })), children] }) }));
3200
- });
3201
-
3202
- const EmptyResult = (jsx(EmptyState, { icon: jsx(HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxs(List.Root, { variant: "marker", children: [jsx(List.Item, { children: "Try removing filters" }), jsx(List.Item, { children: "Try different keywords" })] }) }));
3203
- const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
3204
- const { table } = useDataTableContext();
3205
- if (table.getRowModel().rows.length <= 0) {
3206
- return emptyComponent;
3207
- }
3208
- return (jsx(Table$1.Root, { stickyHeader: true, variant: "outline", width: canResize ? table.getCenterTotalSize() : undefined, display: "grid", alignContent: "start", overflowY: "auto", ...props, children: children }));
3209
- };
3210
-
3211
- const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, controlProps = {}, tableFooterProps = {}, variant = "", }) => {
3330
+ const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = "", }) => {
3212
3331
  if (variant === "greedy") {
3213
3332
  return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { canResize: false, ...{ ...tableProps }, children: [jsx(TableHeader, { canResize: false, ...tableHeaderProps }), jsx(TableBody, { canResize: false, ...tableBodyProps }), showFooter && (jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
3214
3333
  }
3215
3334
  return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { ...tableProps, children: [jsx(TableHeader, { ...tableHeaderProps }), jsx(TableBody, { ...tableBodyProps }), showFooter && jsx(TableFooter, { ...tableFooterProps })] }) }));
3216
3335
  };
3217
3336
 
3218
- const TableCardContainer = ({ children, variant = "", ...props }) => {
3337
+ const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
3219
3338
  if (variant === "carousel") {
3220
- return (jsx(Flex, { overflow: "scroll", gap: "1rem", children: children }));
3339
+ return (jsx(Flex, { overflow: "auto", gap: gap, direction: direction, ...props, children: children }));
3221
3340
  }
3222
- return (jsx(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(20rem, 1fr))", gap: "0.5rem", ...props, children: children }));
3341
+ return (jsx(Grid, { gridTemplateColumns: gridTemplateColumns, gap: gap, ...props, children: children }));
3223
3342
  };
3224
3343
 
3225
3344
  const DefaultCardTitle = () => {
@@ -3248,8 +3367,8 @@ const TableComponent = ({ render = () => {
3248
3367
  };
3249
3368
 
3250
3369
  const TableLoadingComponent = ({ render, }) => {
3251
- const { loading } = useDataTableContext();
3252
- return jsx(Fragment, { children: render(loading) });
3370
+ const { query } = useDataTableServerContext();
3371
+ return jsx(Fragment, { children: render(query.isLoading) });
3253
3372
  };
3254
3373
 
3255
3374
  const SelectAllRowsToggle = ({ selectAllIcon = jsx(MdOutlineChecklist, {}), clearAllIcon = jsx(MdClear, {}), selectAllText = "", clearAllText = "", }) => {
@@ -3468,6 +3587,70 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3468
3587
  return columns;
3469
3588
  };
3470
3589
 
3590
+ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
3591
+ const { columns, translate, data } = useDataTableContext();
3592
+ const columnsMap = Object.fromEntries(columns.map((def) => {
3593
+ const { accessorKey, id } = def;
3594
+ if (accessorKey) {
3595
+ return [accessorKey, def];
3596
+ }
3597
+ return [id, def];
3598
+ }));
3599
+ const columnHeaders = Object.keys(columnsMap);
3600
+ const totalWidths = columns
3601
+ .map(({ size }) => {
3602
+ if (!!size === false) {
3603
+ return 0;
3604
+ }
3605
+ if (typeof size === "number") {
3606
+ return size;
3607
+ }
3608
+ return 0;
3609
+ })
3610
+ .reduce((previous, current) => previous + current, 0);
3611
+ const columnWidths = columns
3612
+ .map(({ size }) => {
3613
+ if (!!size === false) {
3614
+ return "1fr";
3615
+ }
3616
+ return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
3617
+ })
3618
+ .join(" ");
3619
+ console.log({ columnWidths }, "hadfg");
3620
+ const cellProps = {
3621
+ flex: "1 0 0%",
3622
+ overflow: "auto",
3623
+ paddingX: "2",
3624
+ py: "1",
3625
+ color: { base: "colorPalette.900", _dark: "colorPalette.100" },
3626
+ bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
3627
+ borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
3628
+ borderBottomWidth: "1px",
3629
+ ...{ colorPalette },
3630
+ };
3631
+ if (data.length <= 0) {
3632
+ return jsx(Fragment, { children: emptyComponent });
3633
+ }
3634
+ return (jsxs(Grid, { templateColumns: `${columnWidths}`, overflow: "auto", borderWidth: "1px", color: { base: "colorPalette.900", _dark: "colorPalette.100" }, borderColor: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: [jsx(Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: columnHeaders.map((header) => {
3635
+ return (jsx(Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
3636
+ }) }), data.map((record) => {
3637
+ return (jsx(Fragment, { children: columnHeaders.map((header) => {
3638
+ const { cell } = columnsMap[header];
3639
+ const value = record[header];
3640
+ if (!!record === false) {
3641
+ return (jsx(Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
3642
+ }
3643
+ if (cell) {
3644
+ return (jsx(Box, { ...cellProps, children: cell({ row: { original: record } }) }));
3645
+ }
3646
+ if (typeof value === "object") {
3647
+ return (jsx(Box, { ...cellProps, children: jsx(RecordDisplay, { object: value }) }));
3648
+ }
3649
+ return jsx(Box, { ...cellProps, children: value });
3650
+ }) }));
3651
+ })] }));
3652
+ };
3653
+
3471
3654
  const AccordionItemTrigger = React.forwardRef(function AccordionItemTrigger(props, ref) {
3472
3655
  const { children, indicatorPlacement = "end", ...rest } = props;
3473
3656
  return (jsxs(Accordion.ItemTrigger, { ...rest, ref: ref, children: [indicatorPlacement === "start" && (jsx(Accordion.ItemIndicator, { rotate: { base: "-90deg", _open: "0deg" }, children: jsx(LuChevronDown, {}) })), jsx(HStack, { gap: "4", flex: "1", textAlign: "start", width: "full", children: children }), indicatorPlacement === "end" && (jsx(Accordion.ItemIndicator, { children: jsx(LuChevronDown, {}) }))] }));
@@ -3489,6 +3672,7 @@ const SchemaFormContext = createContext({
3489
3672
  onSubmit: async () => { },
3490
3673
  rowNumber: 0,
3491
3674
  requestOptions: {},
3675
+ timezone: 'Asia/Hong_Kong',
3492
3676
  });
3493
3677
 
3494
3678
  const useSchemaContext = () => {
@@ -3514,7 +3698,7 @@ const idPickerSanityCheck = (column, foreign_key) => {
3514
3698
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
3515
3699
  }
3516
3700
  };
3517
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, }) => {
3701
+ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, }) => {
3518
3702
  const [isSuccess, setIsSuccess] = useState(false);
3519
3703
  const [isError, setIsError] = useState(false);
3520
3704
  const [isSubmiting, setIsSubmiting] = useState(false);
@@ -3547,11 +3731,12 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3547
3731
  error,
3548
3732
  setError,
3549
3733
  getUpdatedData,
3734
+ customErrorRenderer,
3550
3735
  }, children: jsx(FormProvider, { ...form, children: children }) }));
3551
3736
  };
3552
3737
 
3553
3738
  function removeIndex(str) {
3554
- return str.replace(/\.\d+\./g, '.');
3739
+ return str.replace(/\.\d+\./g, ".");
3555
3740
  }
3556
3741
 
3557
3742
  const ArrayRenderer = ({ schema, column, prefix, }) => {
@@ -3563,13 +3748,17 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3563
3748
  const isRequired = required?.some((columnId) => columnId === column);
3564
3749
  const { formState: { errors }, setValue, watch, } = useFormContext();
3565
3750
  const fields = (watch(colLabel) ?? []);
3566
- return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsx("span", { children: "*" })] }), fields.map((field, index) => (jsxs(Flex, { flexFlow: "column", children: [jsx(Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: jsx(SchemaRenderer, { column: `${index}`,
3567
- prefix: `${colLabel}.`,
3568
- schema: items }) }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { variant: "ghost", onClick: () => {
3569
- setValue(colLabel, fields.filter((_, curIndex) => {
3570
- return curIndex === index;
3571
- }));
3572
- }, children: translate.t(removeIndex(`${colLabel}.remove`)) }) })] }, `${colLabel}.${index}`))), jsx(Flex, { children: jsx(Button$1, { onClick: () => {
3751
+ return (jsxs(Flex, { gridRow, gridColumn, flexFlow: "column", gap: 2, children: [jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: "column", gap: 2, children: fields.map((field, index) => (jsxs(Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
3752
+ base: "colorPalette.200",
3753
+ _dark: "colorPalette.800",
3754
+ }, children: [jsx(Grid, { gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsx(SchemaRenderer, { column: `${index}`,
3755
+ prefix: `${colLabel}.`,
3756
+ // @ts-expect-error find suitable types
3757
+ schema: { showLabel: false, ...(items ?? {}) } }) }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { variant: "ghost", onClick: () => {
3758
+ setValue(colLabel, fields.filter((_, curIndex) => {
3759
+ return curIndex !== index;
3760
+ }));
3761
+ }, children: jsx(Icon, { children: jsx(CgTrash, {}) }) }) })] }, `${colLabel}.${index}`))) }), jsx(Flex, { children: jsx(Button$1, { onClick: () => {
3573
3762
  if (type === "number") {
3574
3763
  setValue(colLabel, [...fields, 0]);
3575
3764
  return;
@@ -3583,7 +3772,7 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3583
3772
  return;
3584
3773
  }
3585
3774
  setValue(colLabel, [...fields, {}]);
3586
- }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
3775
+ }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3587
3776
  };
3588
3777
 
3589
3778
  const Field = React.forwardRef(function Field(props, ref) {
@@ -3594,37 +3783,36 @@ const Field = React.forwardRef(function Field(props, ref) {
3594
3783
  const BooleanPicker = ({ schema, column, prefix }) => {
3595
3784
  const { watch, formState: { errors }, setValue, } = useFormContext();
3596
3785
  const { translate } = useSchemaContext();
3597
- const { required, gridColumn, gridRow } = schema;
3786
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
3598
3787
  const isRequired = required?.some((columnId) => columnId === column);
3599
3788
  const colLabel = `${prefix}${column}`;
3600
3789
  const value = watch(colLabel);
3601
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3790
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3602
3791
  gridRow, children: [jsx(CheckboxCard, { checked: value, variant: "surface", onChange: () => {
3603
3792
  setValue(colLabel, !value);
3604
- } }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
3793
+ } }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3794
+ };
3795
+
3796
+ const CustomInput = ({ column, schema, prefix }) => {
3797
+ const formContext = useFormContext();
3798
+ const { inputRender } = schema;
3799
+ return (inputRender &&
3800
+ inputRender({
3801
+ column,
3802
+ schema,
3803
+ prefix,
3804
+ formContext,
3805
+ }));
3605
3806
  };
3606
3807
 
3607
- const monthNamesShort = [
3608
- "Jan",
3609
- "Feb",
3610
- "Mar",
3611
- "Apr",
3612
- "May",
3613
- "Jun",
3614
- "Jul",
3615
- "Aug",
3616
- "Sep",
3617
- "Oct",
3618
- "Nov",
3619
- "Dec",
3620
- ];
3621
- const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
3622
3808
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
3809
+ const { labels } = useContext(DatePickerContext);
3810
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel } = labels;
3623
3811
  if (calendars.length) {
3624
3812
  return (jsxs(Grid, { children: [jsxs(Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...getBackProps({
3625
3813
  calendars,
3626
3814
  offset: 12,
3627
- }), children: "<<" }), jsx(Button$1, { variant: "ghost", ...getBackProps({ calendars }), children: "Back" }), jsx(Button$1, { variant: "ghost", ...getForwardProps({ calendars }), children: "Next" }), jsx(Button$1, { variant: "ghost", ...getForwardProps({
3815
+ }), children: "<<" }), jsx(Button$1, { variant: "ghost", ...getBackProps({ calendars }), children: backButtonLabel }), jsx(Button$1, { variant: "ghost", ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsx(Button$1, { variant: "ghost", ...getForwardProps({
3628
3816
  calendars,
3629
3817
  offset: 12,
3630
3818
  }), children: ">>" })] }), jsx(Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", children: calendars.map((calendar) => (jsxs(Grid, { gap: 4, children: [jsxs(Grid, { justifyContent: "center", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxs(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
@@ -3667,9 +3855,52 @@ const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firs
3667
3855
  }
3668
3856
  return null;
3669
3857
  };
3858
+ const DatePickerContext = createContext({
3859
+ labels: {
3860
+ monthNamesShort: [
3861
+ "Jan",
3862
+ "Feb",
3863
+ "Mar",
3864
+ "Apr",
3865
+ "May",
3866
+ "Jun",
3867
+ "Jul",
3868
+ "Aug",
3869
+ "Sep",
3870
+ "Oct",
3871
+ "Nov",
3872
+ "Dec",
3873
+ ],
3874
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
3875
+ backButtonLabel: "Back",
3876
+ forwardButtonLabel: "Next",
3877
+ },
3878
+ });
3670
3879
  let DatePicker$1 = class DatePicker extends React__default.Component {
3671
3880
  render() {
3672
- return (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) => (jsx(Calendar, { ...dayzedData, firstDayOfWeek: this.props.firstDayOfWeek })) }));
3881
+ const { labels = {
3882
+ monthNamesShort: [
3883
+ "Jan",
3884
+ "Feb",
3885
+ "Mar",
3886
+ "Apr",
3887
+ "May",
3888
+ "Jun",
3889
+ "Jul",
3890
+ "Aug",
3891
+ "Sep",
3892
+ "Oct",
3893
+ "Nov",
3894
+ "Dec",
3895
+ ],
3896
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
3897
+ backButtonLabel: "Back",
3898
+ forwardButtonLabel: "Next",
3899
+ }, } = this.props;
3900
+ return (jsx(DatePickerContext.Provider, { value: { labels }, children: 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:
3901
+ // @ts-expect-error - Dayzed types need to be fixed
3902
+ (dayzedData) => (jsx(Calendar, { ...dayzedData,
3903
+ firstDayOfWeek: this.props.firstDayOfWeek })) }) }));
3673
3904
  }
3674
3905
  };
3675
3906
 
@@ -3691,28 +3922,86 @@ const PopoverRoot = Popover.Root;
3691
3922
  const PopoverBody = Popover.Body;
3692
3923
  const PopoverTrigger = Popover.Trigger;
3693
3924
 
3925
+ function translateWrapper({ prefix, column, label, translate, }) {
3926
+ return translate.t(removeIndex(`${prefix}${column}.${label}`));
3927
+ }
3928
+
3929
+ dayjs.extend(utc);
3930
+ dayjs.extend(timezone);
3694
3931
  const DatePicker = ({ column, schema, prefix }) => {
3695
3932
  const { watch, formState: { errors }, setValue, } = useFormContext();
3696
- const { translate } = useSchemaContext();
3697
- const { required, gridColumn, gridRow } = schema;
3933
+ const { translate, timezone } = useSchemaContext();
3934
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", dateFormat = "YYYY-MM-DD", } = schema;
3698
3935
  const isRequired = required?.some((columnId) => columnId === column);
3699
3936
  const colLabel = `${prefix}${column}`;
3700
3937
  const [open, setOpen] = useState(false);
3701
3938
  const selectedDate = watch(colLabel);
3702
- const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
3703
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3704
- gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsx(Button, { size: "sm", variant: "outline", onClick: () => {
3939
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
3940
+ useEffect(() => {
3941
+ try {
3942
+ if (selectedDate) {
3943
+ // Parse the selectedDate as UTC or in a specific timezone to avoid +8 hour shift
3944
+ // For example, parse as UTC:
3945
+ const parsedDate = dayjs(selectedDate).tz(timezone);
3946
+ if (!parsedDate.isValid())
3947
+ return;
3948
+ // Format according to dateFormat from schema
3949
+ const formatted = parsedDate.format(dateFormat);
3950
+ // Update the form value only if different to avoid loops
3951
+ if (formatted !== selectedDate) {
3952
+ setValue(colLabel, formatted, {
3953
+ shouldValidate: true,
3954
+ shouldDirty: true,
3955
+ });
3956
+ }
3957
+ }
3958
+ }
3959
+ catch (e) {
3960
+ console.error(e);
3961
+ }
3962
+ }, [selectedDate, dateFormat, colLabel, setValue]);
3963
+ const customTranslate = (label) => {
3964
+ return translateWrapper({ prefix, column, label, translate });
3965
+ };
3966
+ return (jsxs(Field, { label: `${customTranslate(`field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn,
3967
+ gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
3705
3968
  setOpen(true);
3706
- }, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1
3707
- // @ts-expect-error TODO: find appropriate types
3708
- , {
3709
- // @ts-expect-error TODO: find appropriate types
3710
- selected: new Date(selectedDate),
3711
- // @ts-expect-error TODO: find appropriate types
3712
- onDateSelected: ({ date }) => {
3713
- setValue(colLabel, dayjs(date).format("YYYY-MM-DD"));
3969
+ }, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
3970
+ setValue(colLabel, dayjs(date).format(dateFormat));
3714
3971
  setOpen(false);
3715
- } })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
3972
+ }, labels: {
3973
+ monthNamesShort: [
3974
+ translate.t(`common.month_1`, { defaultValue: "January" }),
3975
+ translate.t(`common.month_2`, { defaultValue: "February" }),
3976
+ translate.t(`common.month_3`, { defaultValue: "March" }),
3977
+ translate.t(`common.month_4`, { defaultValue: "April" }),
3978
+ translate.t(`common.month_5`, { defaultValue: "May" }),
3979
+ translate.t(`common.month_6`, { defaultValue: "June" }),
3980
+ translate.t(`common.month_7`, { defaultValue: "July" }),
3981
+ translate.t(`common.month_8`, { defaultValue: "August" }),
3982
+ translate.t(`common.month_9`, { defaultValue: "September" }),
3983
+ translate.t(`common.month_10`, { defaultValue: "October" }),
3984
+ translate.t(`common.month_11`, { defaultValue: "November" }),
3985
+ translate.t(`common.month_12`, { defaultValue: "December" }),
3986
+ ],
3987
+ weekdayNamesShort: [
3988
+ translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
3989
+ translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
3990
+ translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
3991
+ translate.t(`common.weekday_4`, {
3992
+ defaultValue: "Wed",
3993
+ }),
3994
+ translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
3995
+ translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
3996
+ translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
3997
+ ],
3998
+ backButtonLabel: translate.t(`common.back_button`, {
3999
+ defaultValue: "Back",
4000
+ }),
4001
+ forwardButtonLabel: translate.t(`common.forward_button`, {
4002
+ defaultValue: "Forward",
4003
+ }),
4004
+ } })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: customTranslate(`field_required`) }))] }));
3716
4005
  };
3717
4006
 
3718
4007
  function filterArray(array, searchTerm) {
@@ -3725,12 +4014,12 @@ function filterArray(array, searchTerm) {
3725
4014
  });
3726
4015
  }
3727
4016
 
3728
- const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
4017
+ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
3729
4018
  const { watch, formState: { errors }, setValue, } = useFormContext();
3730
4019
  const { translate } = useSchemaContext();
3731
- const { required } = schema;
4020
+ const { required, variant } = schema;
3732
4021
  const isRequired = required?.some((columnId) => columnId === column);
3733
- const { gridColumn, gridRow, renderDisplay } = schema;
4022
+ const { gridColumn = "span 4", gridRow = "span 1", renderDisplay } = schema;
3734
4023
  const [searchText, setSearchText] = useState();
3735
4024
  const [limit, setLimit] = useState(10);
3736
4025
  const [openSearchResult, setOpenSearchResult] = useState();
@@ -3745,28 +4034,61 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3745
4034
  setSearchText(event.target.value);
3746
4035
  setLimit(10);
3747
4036
  };
3748
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4037
+ if (variant === "radio") {
4038
+ return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4039
+ gridRow, children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
4040
+ return (jsxs(RadioGroup$1.Item, { onClick: () => {
4041
+ if (!isMultiple) {
4042
+ setOpenSearchResult(false);
4043
+ setValue(colLabel, item);
4044
+ return;
4045
+ }
4046
+ const newSet = new Set([...(watchEnums ?? []), item]);
4047
+ setValue(colLabel, [...newSet]);
4048
+ }, value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
4049
+ ? renderDisplay(item)
4050
+ : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
4051
+ }) }) }) }));
4052
+ }
4053
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3749
4054
  gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
3750
4055
  const item = enumValue;
3751
- if (item === undefined) {
3752
- return jsx(Fragment, { children: "undefined" });
4056
+ if (!!item === false) {
4057
+ return jsx(Fragment, {});
3753
4058
  }
3754
4059
  return (jsx(Tag, { closable: true, onClick: () => {
3755
- // setSelectedEnums((state) => state.filter((id) => id != item));
3756
4060
  setValue(column, watchEnums.filter((id) => id != item));
3757
4061
  }, children: !!renderDisplay === true
3758
4062
  ? renderDisplay(item)
3759
4063
  : translate.t(removeIndex(`${colLabel}.${item}`)) }));
3760
4064
  }), jsx(Tag, { cursor: "pointer", onClick: () => {
3761
4065
  setOpenSearchResult(true);
3762
- }, children: translate.t(removeIndex(`${colLabel}.addMore`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
4066
+ }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
3763
4067
  setOpenSearchResult(true);
3764
- }, children: watchEnum === undefined
4068
+ }, justifyContent: "start", children: !!watchEnum === false
3765
4069
  ? ""
3766
- : translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(`${column}.typeToSearch`), onChange: (event) => {
4070
+ : translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
3767
4071
  onSearchChange(event);
3768
4072
  setOpenSearchResult(true);
3769
- }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), jsx(Text, { children: `${translate.t(`${column}.total`)}: ${count}, ${translate.t(`${column}.showing`)} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children: filterArray(dataList, searchText ?? "").map((item) => {
4073
+ }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), showTotalAndLimit && (jsx(Text, { children: `${translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxs(Grid, { overflow: "auto", maxHeight: "20rem", children: [jsx(Flex, { flexFlow: "column wrap", children: dataList
4074
+ .filter((item) => {
4075
+ const searchTerm = (searchText || "").toLowerCase();
4076
+ if (!searchTerm)
4077
+ return true;
4078
+ // Check if the original enum value contains the search text
4079
+ const enumValueMatch = item
4080
+ .toLowerCase()
4081
+ .includes(searchTerm);
4082
+ // Check if the display value (translation) contains the search text
4083
+ const displayValue = !!renderDisplay === true
4084
+ ? renderDisplay(item)
4085
+ : translate.t(removeIndex(`${colLabel}.${item}`));
4086
+ // Convert to string and check if it includes the search term
4087
+ const displayValueString = String(displayValue).toLowerCase();
4088
+ const displayValueMatch = displayValueString.includes(searchTerm);
4089
+ return enumValueMatch || displayValueMatch;
4090
+ })
4091
+ .map((item) => {
3770
4092
  const selected = isMultiple
3771
4093
  ? watchEnums.some((enumValue) => item === enumValue)
3772
4094
  : watchEnum == item;
@@ -3778,10 +4100,10 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3778
4100
  }
3779
4101
  const newSet = new Set([...(watchEnums ?? []), item]);
3780
4102
  setValue(colLabel, [...newSet]);
3781
- }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
4103
+ }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
3782
4104
  ? renderDisplay(item)
3783
4105
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
3784
- }) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Fragment, { children: translate.t(removeIndex(`${colLabel}.emptySearchResult`)) })) }))] })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4106
+ }) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Fragment, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3785
4107
  };
3786
4108
 
3787
4109
  function isEnteringWindow(_ref) {
@@ -4133,17 +4455,17 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
4133
4455
  const filesArray = [...event.target.files];
4134
4456
  onDrop({ files: filesArray });
4135
4457
  };
4136
- return (jsxs(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 && (jsxs(Fragment, { children: [jsx(Flex, { children: placeholder }), jsx(Input, { type: "file", multiple: true, style: { display: "none" }, ref: fileInput, onChange: handleChange })] }))] }));
4458
+ return (jsxs(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 && (jsxs(Fragment, { children: [jsx(Flex, { children: placeholder }), jsx(Input, { type: "file", multiple: true, style: { display: "none" }, ref: fileInput, onChange: handleChange })] }))] }));
4137
4459
  };
4138
4460
 
4139
4461
  const FilePicker = ({ column, schema, prefix }) => {
4140
4462
  const { setValue, formState: { errors }, watch, } = useFormContext();
4141
4463
  const { translate } = useSchemaContext();
4142
- const { required, gridColumn, gridRow } = schema;
4464
+ const { required, gridColumn = "span 4", gridRow = "span 1", } = schema;
4143
4465
  const isRequired = required?.some((columnId) => columnId === column);
4144
4466
  const currentFiles = (watch(column) ?? []);
4145
4467
  const colLabel = `${prefix}${column}`;
4146
- return (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: [jsx(FileDropzone, { onDrop: ({ files }) => {
4468
+ return (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: [jsx(FileDropzone, { onDrop: ({ files }) => {
4147
4469
  const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4148
4470
  setValue(colLabel, [...currentFiles, ...newFiles]);
4149
4471
  }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
@@ -4151,10 +4473,19 @@ const FilePicker = ({ column, schema, prefix }) => {
4151
4473
  setValue(column, currentFiles.filter(({ name }) => {
4152
4474
  return name !== file.name;
4153
4475
  }));
4154
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4155
- }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4476
+ }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4477
+ }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4156
4478
  };
4157
4479
 
4480
+ const ToggleTip = React.forwardRef(function ToggleTip(props, ref) {
4481
+ const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
4482
+ return (jsxs(Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsx(Popover.Trigger, { asChild: true, children: children }), jsx(Portal, { disabled: !portalled, container: portalRef, children: jsx(Popover.Positioner, { children: jsxs(Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsx(Popover.Arrow, { children: jsx(Popover.ArrowTip, {}) })), content] }) }) })] }));
4483
+ });
4484
+ const InfoTip = React.forwardRef(function InfoTip(props, ref) {
4485
+ const { children, ...rest } = props;
4486
+ return (jsx(ToggleTip, { content: children, ...rest, ref: ref, children: jsx(IconButton, { variant: "ghost", "aria-label": "info", size: "2xs", colorPalette: "colorPalette", children: jsx(HiOutlineInformationCircle, {}) }) }));
4487
+ });
4488
+
4158
4489
  const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
4159
4490
  if (serverUrl === undefined || serverUrl.length == 0) {
4160
4491
  throw new Error("The serverUrl is missing");
@@ -4186,15 +4517,18 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
4186
4517
  const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4187
4518
  const { watch, formState: { errors }, setValue, } = useFormContext();
4188
4519
  const { serverUrl, idMap, setIdMap, translate, schema: parentSchema, } = useSchemaContext();
4189
- const { required, gridColumn, gridRow, renderDisplay, foreign_key } = schema;
4520
+ const { required, gridColumn = "span 4", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
4190
4521
  const isRequired = required?.some((columnId) => columnId === column);
4191
4522
  const { table, column: column_ref, display_column, } = foreign_key;
4192
- const [searchText, setSearchText] = useState();
4523
+ const [searchText, setSearchText] = useState("");
4193
4524
  const [limit, setLimit] = useState(10);
4194
4525
  const [openSearchResult, setOpenSearchResult] = useState();
4195
4526
  const [page, setPage] = useState(0);
4196
4527
  const ref = useRef(null);
4197
4528
  const colLabel = `${prefix}${column}`;
4529
+ const watchId = watch(colLabel);
4530
+ const watchIds = isMultiple ? (watch(colLabel) ?? []) : [];
4531
+ // Query for search results
4198
4532
  const query = useQuery({
4199
4533
  queryKey: [`idpicker`, { column, searchText, limit, page }],
4200
4534
  queryFn: async () => {
@@ -4203,7 +4537,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4203
4537
  searching: searchText ?? "",
4204
4538
  in_table: table,
4205
4539
  limit: limit,
4206
- offset: page * 10,
4540
+ offset: page * limit,
4207
4541
  });
4208
4542
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
4209
4543
  return [
@@ -4218,27 +4552,27 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4218
4552
  });
4219
4553
  return data;
4220
4554
  },
4221
- enabled: (searchText ?? "")?.length > 0,
4555
+ enabled: openSearchResult === true,
4222
4556
  staleTime: 300000,
4223
4557
  });
4224
- const { isLoading, isFetching, data, isPending, isError } = query;
4225
- const dataList = data?.data ?? [];
4226
- const count = data?.count ?? 0;
4227
- const isDirty = (searchText?.length ?? 0) > 0;
4228
- const watchId = watch(colLabel);
4229
- const watchIds = (watch(colLabel) ?? []);
4230
- useQuery({
4558
+ // Query for currently selected items (to display them properly)
4559
+ const queryDefault = useQuery({
4231
4560
  queryKey: [
4232
- `idpicker`,
4233
- { form: parentSchema.title, column, searchText, limit, page },
4561
+ `idpicker-default`,
4562
+ { form: parentSchema.title, column, id: isMultiple ? watchIds : watchId },
4234
4563
  ],
4235
4564
  queryFn: async () => {
4565
+ if (!watchId && (!watchIds || watchIds.length === 0)) {
4566
+ return { data: [] };
4567
+ }
4568
+ const searchValue = isMultiple ? watchIds.join(",") : watchId;
4236
4569
  const data = await getTableData({
4237
4570
  serverUrl,
4238
- searching: watchId,
4571
+ searching: searchValue,
4239
4572
  in_table: table,
4240
- limit: limit,
4241
- offset: page * 10,
4573
+ where: [{ id: column_ref, value: isMultiple ? watchIds : watchId }],
4574
+ limit: isMultiple ? watchIds.length : 1,
4575
+ offset: 0,
4242
4576
  });
4243
4577
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
4244
4578
  return [
@@ -4253,12 +4587,45 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4253
4587
  });
4254
4588
  return data;
4255
4589
  },
4590
+ enabled: isMultiple
4591
+ ? Array.isArray(watchIds) && watchIds.length > 0
4592
+ : !!watchId,
4256
4593
  });
4594
+ // Effect to load selected values when component mounts
4595
+ useEffect(() => {
4596
+ if (isMultiple ? watchIds.length > 0 : !!watchId) {
4597
+ queryDefault.refetch();
4598
+ }
4599
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4600
+ }, []);
4601
+ // Effect to trigger initial data fetch when popover opens
4602
+ useEffect(() => {
4603
+ if (openSearchResult) {
4604
+ // Reset search text when opening the popover
4605
+ setSearchText("");
4606
+ // Reset page to first page
4607
+ setPage(0);
4608
+ // Fetch initial data
4609
+ query.refetch();
4610
+ }
4611
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4612
+ }, [openSearchResult]);
4257
4613
  const onSearchChange = async (event) => {
4258
4614
  setSearchText(event.target.value);
4259
4615
  setPage(0);
4260
- setLimit(10);
4616
+ query.refetch();
4617
+ };
4618
+ const handleLimitChange = (event) => {
4619
+ const newLimit = Number(event.target.value);
4620
+ setLimit(newLimit);
4621
+ // Reset to first page when changing limit
4622
+ setPage(0);
4623
+ // Trigger a new search with the updated limit
4624
+ query.refetch();
4261
4625
  };
4626
+ const { isLoading, isFetching, data, isPending, isError } = query;
4627
+ const dataList = data?.data ?? [];
4628
+ const count = data?.count ?? 0;
4262
4629
  const getPickedValue = () => {
4263
4630
  if (Object.keys(idMap).length <= 0) {
4264
4631
  return "";
@@ -4267,52 +4634,62 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4267
4634
  if (record === undefined) {
4268
4635
  return "";
4269
4636
  }
4637
+ if (!!renderDisplay === true) {
4638
+ return renderDisplay(record);
4639
+ }
4270
4640
  return record[display_column];
4271
4641
  };
4272
- return (jsxs(Field, { label: `${translate.t(removeIndex(removeIndex(`${column}.fieldLabel`)))}`, required: isRequired, alignItems: "stretch", gridColumn,
4642
+ return (jsxs(Field, { label: `${translate.t(removeIndex(removeIndex(`${column}.field_label`)))}`, required: isRequired, alignItems: "stretch", gridColumn,
4273
4643
  gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: "wrap", gap: 1, children: [watchIds.map((id) => {
4274
4644
  const item = idMap[id];
4275
4645
  if (item === undefined) {
4276
4646
  return (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
4277
4647
  }
4278
4648
  return (jsx(Tag, { closable: true, onClick: () => {
4279
- setValue(column, watchIds.filter((id) => id != item[column_ref]));
4649
+ setValue(colLabel, watchIds.filter((itemId) => itemId !== item[column_ref]));
4280
4650
  }, children: !!renderDisplay === true
4281
4651
  ? renderDisplay(item)
4282
4652
  : item[display_column] }, id));
4283
4653
  }), jsx(Tag, { cursor: "pointer", onClick: () => {
4284
4654
  setOpenSearchResult(true);
4285
- }, children: translate.t(removeIndex(`${colLabel}.addMore`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
4655
+ }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
4286
4656
  setOpenSearchResult(true);
4287
- }, children: getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4288
- onSearchChange(event);
4289
- setOpenSearchResult(true);
4290
- }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxs(Fragment, { children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), (isFetching || isLoading || isPending) && jsx(Spinner, {}), isError && (jsx(Icon, { color: "red.400", children: jsx(BiError, {}) })), jsx(Text, { justifySelf: "center", children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children:
4291
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4292
- dataList.map((item) => {
4293
- const selected = isMultiple
4294
- ? watchIds.some((id) => item[column_ref] === id)
4295
- : watchId === item[column_ref];
4296
- return (jsx(Box, { cursor: "pointer", onClick: () => {
4297
- if (!isMultiple) {
4298
- setOpenSearchResult(false);
4299
- setValue(colLabel, item[column_ref]);
4300
- return;
4301
- }
4302
- const newSet = new Set([
4303
- ...(watchIds ?? []),
4304
- item[column_ref],
4305
- ]);
4306
- setValue(colLabel, [...newSet]);
4307
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
4308
- ? renderDisplay(item)
4309
- : item[display_column] }, item[column_ref]));
4310
- }) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.emptySearchResult`)) })) }))] }), jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: 10, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4657
+ }, justifyContent: "start", children: queryDefault.isLoading ? jsx(Spinner, { size: "sm" }) : getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.type_to_search`)), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsx(PopoverTitle, {}), openSearchResult && (jsxs(Fragment, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, {}), isError && (jsx(Icon, { color: "red.400", children: jsx(BiError, {}) })), jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxs(Flex, { alignItems: "center", gap: "2", children: [jsx(InfoTip, { children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit} ${translate.t(removeIndex(`${colLabel}.per_page`), "per page")}` }), jsxs(Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxs(Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/ ", count > 0 ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}` : '0'] })] })] }), jsx(Box, { children: jsxs("select", { value: limit, onChange: handleLimitChange, style: {
4658
+ padding: "4px 8px",
4659
+ borderRadius: "4px",
4660
+ border: "1px solid #ccc",
4661
+ fontSize: "14px",
4662
+ }, children: [jsx("option", { value: "5", children: "5" }), jsx("option", { value: "10", children: "10" }), jsx("option", { value: "20", children: "20" }), jsx("option", { value: "30", children: "30" })] }) })] }), jsx(Grid, { overflowY: "auto", children: dataList.length > 0 ? (jsx(Flex, { flexFlow: "column wrap", gap: 1, children: dataList.map((item) => {
4663
+ const selected = isMultiple
4664
+ ? watchIds.some((id) => item[column_ref] === id)
4665
+ : watchId === item[column_ref];
4666
+ return (jsx(Box, { cursor: "pointer", onClick: () => {
4667
+ if (!isMultiple) {
4668
+ setOpenSearchResult(false);
4669
+ setValue(colLabel, item[column_ref]);
4670
+ return;
4671
+ }
4672
+ // For multiple selection, don't add if already selected
4673
+ if (selected)
4674
+ return;
4675
+ const newSet = new Set([
4676
+ ...(watchIds ?? []),
4677
+ item[column_ref],
4678
+ ]);
4679
+ setValue(colLabel, [...newSet]);
4680
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
4681
+ ? { color: "colorPalette.400/50", fontWeight: "bold" }
4682
+ : {}), children: !!renderDisplay === true
4683
+ ? renderDisplay(item)
4684
+ : item[display_column] }, item[column_ref]));
4685
+ }) })) : (jsx(Text, { children: searchText
4686
+ ? translate.t(removeIndex(`${colLabel}.empty_search_result`))
4687
+ : translate.t(removeIndex(`${colLabel}.initial_results`)) })) }), jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4311
4688
  };
4312
4689
 
4313
4690
  const NumberInputRoot = React.forwardRef(function NumberInput$1(props, ref) {
4314
4691
  const { children, ...rest } = props;
4315
- return (jsxs(NumberInput.Root, { ref: ref, variant: "outline", ...rest, children: [children, jsxs(NumberInput.Control, { children: [jsx(NumberInput.IncrementTrigger, {}), jsx(NumberInput.DecrementTrigger, {})] })] }));
4692
+ return (jsx(NumberInput.Root, { ref: ref, variant: "outline", ...rest, children: children }));
4316
4693
  });
4317
4694
  const NumberInputField$1 = NumberInput.Input;
4318
4695
  NumberInput.Scrubber;
@@ -4321,17 +4698,17 @@ NumberInput.Label;
4321
4698
  const NumberInputField = ({ schema, column, prefix, }) => {
4322
4699
  const { setValue, formState: { errors }, watch, } = useFormContext();
4323
4700
  const { translate } = useSchemaContext();
4324
- const { required, gridColumn, gridRow } = schema;
4701
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4325
4702
  const isRequired = required?.some((columnId) => columnId === column);
4326
4703
  const colLabel = `${prefix}${column}`;
4327
4704
  const value = watch(`${colLabel}`);
4328
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(NumberInputRoot, { children: jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4705
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(NumberInputRoot, { children: jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4329
4706
  setValue(`${colLabel}`, Number(event.target.value));
4330
- } }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4707
+ } }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4331
4708
  };
4332
4709
 
4333
4710
  const ObjectInput = ({ schema, column, prefix }) => {
4334
- const { properties, gridRow, gridColumn = "1/span 12", required } = schema;
4711
+ const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
4335
4712
  const { translate } = useSchemaContext();
4336
4713
  const colLabel = `${prefix}${column}`;
4337
4714
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4339,25 +4716,28 @@ const ObjectInput = ({ schema, column, prefix }) => {
4339
4716
  if (properties === undefined) {
4340
4717
  throw new Error(`properties is undefined when using ObjectInput`);
4341
4718
  }
4342
- return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsx("span", { children: "*" })] }), jsx(Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: Object.keys(properties ?? {}).map((key) => {
4719
+ return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] })), jsx(Grid, { bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4720
+ base: "colorPalette.200",
4721
+ _dark: "colorPalette.800",
4722
+ }, gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: Object.keys(properties ?? {}).map((key) => {
4343
4723
  return (
4344
4724
  // @ts-expect-error find suitable types
4345
4725
  jsx(ColumnRenderer, { column: `${key}`,
4346
4726
  prefix: `${prefix}${column}.`,
4347
4727
  properties }, `form-${colLabel}-${key}`));
4348
- }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
4728
+ }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4349
4729
  };
4350
4730
 
4351
4731
  const RecordInput$1 = ({ column, schema, prefix }) => {
4352
4732
  const { formState: { errors }, setValue, getValues, } = useFormContext();
4353
4733
  const { translate } = useSchemaContext();
4354
- const { required, gridColumn, gridRow } = schema;
4734
+ const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4355
4735
  const isRequired = required?.some((columnId) => columnId === column);
4356
4736
  const entries = Object.entries(getValues(column) ?? {});
4357
4737
  const [showNewEntries, setShowNewEntries] = useState(false);
4358
4738
  const [newKey, setNewKey] = useState();
4359
4739
  const [newValue, setNewValue] = useState();
4360
- return (jsxs(Field, { label: `${translate.t(`${column}.fieldLabel`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4740
+ return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4361
4741
  return (jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
4362
4742
  const filtered = entries.filter(([target]) => {
4363
4743
  return target !== key;
@@ -4397,16 +4777,16 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
4397
4777
  setShowNewEntries(true);
4398
4778
  setNewKey(undefined);
4399
4779
  setNewValue(undefined);
4400
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
4780
+ }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4401
4781
  };
4402
4782
 
4403
4783
  const StringInputField = ({ column, schema, prefix, }) => {
4404
4784
  const { register, formState: { errors }, } = useFormContext();
4405
4785
  const { translate } = useSchemaContext();
4406
- const { required, gridColumn, gridRow } = schema;
4786
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4407
4787
  const isRequired = required?.some((columnId) => columnId === column);
4408
4788
  const colLabel = `${prefix}${column}`;
4409
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }) }));
4789
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4410
4790
  };
4411
4791
 
4412
4792
  const RadioCardItem = React.forwardRef(function RadioCardItem(props, ref) {
@@ -4504,9 +4884,459 @@ const TagPicker = ({ column, schema, prefix }) => {
4504
4884
  }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4505
4885
  };
4506
4886
 
4887
+ const TextAreaInput = ({ column, schema, prefix, }) => {
4888
+ const { register, formState: { errors }, } = useFormContext();
4889
+ const { translate } = useSchemaContext();
4890
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4891
+ const isRequired = required?.some((columnId) => columnId === column);
4892
+ const colLabel = `${prefix}${column}`;
4893
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Textarea, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4894
+ };
4895
+
4896
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
4897
+ am: "am",
4898
+ pm: "pm",
4899
+ }, onChange = (_newValue) => { }, }) {
4900
+ // Refs for focus management
4901
+ const hourInputRef = useRef(null);
4902
+ const minuteInputRef = useRef(null);
4903
+ useRef(null);
4904
+ // Centralized handler for key events, value changes, and focus management
4905
+ const handleKeyDown = (e, field) => {
4906
+ const input = e.target;
4907
+ const value = input.value;
4908
+ // Handle navigation between fields
4909
+ if (e.key === "Tab") {
4910
+ // Tab is handled by the browser, no need to override
4911
+ return;
4912
+ }
4913
+ if (e.key === ":" && field === "hour") {
4914
+ e.preventDefault();
4915
+ minuteInputRef.current?.focus();
4916
+ return;
4917
+ }
4918
+ if (e.key === "Backspace" && value === "") {
4919
+ e.preventDefault();
4920
+ if (field === "minute") {
4921
+ hourInputRef.current?.focus();
4922
+ }
4923
+ else if (field === "meridiem") {
4924
+ minuteInputRef.current?.focus();
4925
+ }
4926
+ return;
4927
+ }
4928
+ // Handle number inputs
4929
+ if (field === "hour") {
4930
+ if (e.key.match(/^[0-9]$/)) {
4931
+ const newValue = value + e.key;
4932
+ const numValue = parseInt(newValue, 10);
4933
+ console.log("newValue", newValue, numValue);
4934
+ if (numValue > 12) {
4935
+ const digitValue = parseInt(e.key, 10);
4936
+ setHour(digitValue);
4937
+ onChange({ hour: digitValue, minute, meridiem });
4938
+ return;
4939
+ }
4940
+ // Auto-advance to minutes if we have a valid hour (1-12)
4941
+ if (numValue >= 1 && numValue <= 12) {
4942
+ // Set the hour value
4943
+ setHour(numValue);
4944
+ onChange({ hour: numValue, minute, meridiem });
4945
+ // Move to minute input
4946
+ e.preventDefault();
4947
+ minuteInputRef.current?.focus();
4948
+ }
4949
+ }
4950
+ }
4951
+ else if (field === "minute") {
4952
+ if (e.key.match(/^[0-9]$/)) {
4953
+ const newValue = value + e.key;
4954
+ const numValue = parseInt(newValue, 10);
4955
+ console.log("newValue minute", newValue, numValue, numValue > 60, numValue >= 0 && numValue <= 59, e.key);
4956
+ if (numValue > 60) {
4957
+ const digitValue = parseInt(e.key, 10);
4958
+ setMinute(digitValue);
4959
+ onChange({ hour, minute: digitValue, meridiem });
4960
+ return;
4961
+ }
4962
+ // Auto-advance to meridiem if we have a valid minute (0-59)
4963
+ if (numValue >= 0 && numValue <= 59) {
4964
+ // Set the minute value
4965
+ setMinute(numValue);
4966
+ onChange({ hour, minute: numValue, meridiem });
4967
+ }
4968
+ }
4969
+ }
4970
+ };
4971
+ // Handle meridiem button click
4972
+ const handleMeridiemClick = (newMeridiem) => {
4973
+ setMeridiem(newMeridiem);
4974
+ onChange({ hour, minute, meridiem: newMeridiem });
4975
+ };
4976
+ const handleClear = () => {
4977
+ setHour(null);
4978
+ setMinute(null);
4979
+ setMeridiem(null);
4980
+ onChange({ hour: null, minute: null, meridiem: null });
4981
+ // Focus the hour field after clearing
4982
+ hourInputRef.current?.focus();
4983
+ };
4984
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 90px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsx(Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsxs(Flex, { gap: "1", children: [jsx(Button$1, { size: "sm", colorScheme: meridiem === "am" ? "blue" : "gray", variant: meridiem === "am" ? "solid" : "outline", onClick: () => handleMeridiemClick("am"), width: "40px", children: meridiemLabel.am }), jsx(Button$1, { size: "sm", colorScheme: meridiem === "pm" ? "blue" : "gray", variant: meridiem === "pm" ? "solid" : "outline", onClick: () => handleMeridiemClick("pm"), width: "40px", children: meridiemLabel.pm })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }) }));
4985
+ }
4986
+
4987
+ dayjs.extend(timezone);
4988
+ const TimePicker = ({ column, schema, prefix }) => {
4989
+ const { watch, formState: { errors }, setValue, } = useFormContext();
4990
+ const { translate, timezone } = useSchemaContext();
4991
+ const { required, gridColumn = "span 4", gridRow = "span 1", timeFormat = "HH:mm:ssZ", displayTimeFormat = "hh:mm A", } = schema;
4992
+ const isRequired = required?.some((columnId) => columnId === column);
4993
+ const colLabel = `${prefix}${column}`;
4994
+ const [open, setOpen] = useState(false);
4995
+ const value = watch(colLabel);
4996
+ const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
4997
+ ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
4998
+ : "";
4999
+ // Parse the initial time parts from the ISO time string (HH:mm:ss)
5000
+ const parseTime = (isoTime) => {
5001
+ if (!isoTime)
5002
+ return { hour: 12, minute: 0, meridiem: "am" };
5003
+ const parsed = dayjs(`1970-01-01T${isoTime}`).tz(timezone);
5004
+ if (!parsed.isValid())
5005
+ return { hour: 12, minute: 0, meridiem: "am" };
5006
+ let hour = parsed.hour();
5007
+ const minute = parsed.minute();
5008
+ const meridiem = hour >= 12 ? "pm" : "am";
5009
+ if (hour === 0)
5010
+ hour = 12;
5011
+ else if (hour > 12)
5012
+ hour -= 12;
5013
+ return { hour, minute, meridiem };
5014
+ };
5015
+ const initialTime = parseTime(value);
5016
+ const [hour, setHour] = useState(initialTime.hour);
5017
+ const [minute, setMinute] = useState(initialTime.minute);
5018
+ const [meridiem, setMeridiem] = useState(initialTime.meridiem);
5019
+ useEffect(() => {
5020
+ const { hour, minute, meridiem } = parseTime(value);
5021
+ setHour(hour);
5022
+ setMinute(minute);
5023
+ setMeridiem(meridiem);
5024
+ }, [value]);
5025
+ // Convert hour, minute, meridiem to 24-hour ISO time string
5026
+ const toIsoTime = (hour, minute, meridiem) => {
5027
+ if (hour === null || minute === null || meridiem === null)
5028
+ return null;
5029
+ let h = hour;
5030
+ if (meridiem === "am" && hour === 12)
5031
+ h = 0;
5032
+ else if (meridiem === "pm" && hour < 12)
5033
+ h = hour + 12;
5034
+ return dayjs(`1970-01-01T${h.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:00`)
5035
+ .tz(timezone)
5036
+ .format(timeFormat);
5037
+ };
5038
+ // Handle changes to time parts
5039
+ const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
5040
+ setHour(newHour);
5041
+ setMinute(newMinute);
5042
+ setMeridiem(newMeridiem);
5043
+ const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
5044
+ setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
5045
+ };
5046
+ const containerRef = useRef(null);
5047
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5048
+ gridRow, children: [jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5049
+ setOpen(true);
5050
+ }, justifyContent: "start", children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { ref: containerRef, children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5051
+ am: translate.t(`common.am`, { defaultValue: "AM" }),
5052
+ pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5053
+ } }) }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5054
+ };
5055
+
5056
+ function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
5057
+ // Refs for focus management
5058
+ const hourInputRef = useRef(null);
5059
+ const minuteInputRef = useRef(null);
5060
+ const secondInputRef = useRef(null);
5061
+ // Centralized handler for key events, value changes, and focus management
5062
+ const handleKeyDown = (e, field) => {
5063
+ const input = e.target;
5064
+ const value = input.value;
5065
+ // Handle navigation between fields
5066
+ if (e.key === "Tab") {
5067
+ return;
5068
+ }
5069
+ if (e.key === ":" && field === "hour") {
5070
+ e.preventDefault();
5071
+ minuteInputRef.current?.focus();
5072
+ return;
5073
+ }
5074
+ if (e.key === ":" && field === "minute") {
5075
+ e.preventDefault();
5076
+ secondInputRef.current?.focus();
5077
+ return;
5078
+ }
5079
+ if (e.key === "Backspace" && value === "") {
5080
+ e.preventDefault();
5081
+ if (field === "minute") {
5082
+ hourInputRef.current?.focus();
5083
+ }
5084
+ else if (field === "second") {
5085
+ minuteInputRef.current?.focus();
5086
+ }
5087
+ return;
5088
+ }
5089
+ // Handle number inputs
5090
+ if (field === "hour") {
5091
+ if (e.key.match(/^[0-9]$/)) {
5092
+ const newValue = value + e.key;
5093
+ const numValue = parseInt(newValue, 10);
5094
+ if (numValue > 23) {
5095
+ const digitValue = parseInt(e.key, 10);
5096
+ setHour(digitValue);
5097
+ onChange({ hour: digitValue, minute, second });
5098
+ return;
5099
+ }
5100
+ if (numValue >= 0 && numValue <= 23) {
5101
+ setHour(numValue);
5102
+ onChange({ hour: numValue, minute, second });
5103
+ e.preventDefault();
5104
+ minuteInputRef.current?.focus();
5105
+ }
5106
+ }
5107
+ }
5108
+ else if (field === "minute") {
5109
+ if (e.key.match(/^[0-9]$/)) {
5110
+ const newValue = value + e.key;
5111
+ const numValue = parseInt(newValue, 10);
5112
+ if (numValue > 59) {
5113
+ const digitValue = parseInt(e.key, 10);
5114
+ setMinute(digitValue);
5115
+ onChange({ hour, minute: digitValue, second });
5116
+ return;
5117
+ }
5118
+ if (numValue >= 0 && numValue <= 59) {
5119
+ setMinute(numValue);
5120
+ onChange({ hour, minute: numValue, second });
5121
+ e.preventDefault();
5122
+ secondInputRef.current?.focus();
5123
+ }
5124
+ }
5125
+ }
5126
+ else if (field === "second") {
5127
+ if (e.key.match(/^[0-9]$/)) {
5128
+ const newValue = value + e.key;
5129
+ const numValue = parseInt(newValue, 10);
5130
+ if (numValue > 59) {
5131
+ const digitValue = parseInt(e.key, 10);
5132
+ setSecond(digitValue);
5133
+ onChange({ hour, minute, second: digitValue });
5134
+ return;
5135
+ }
5136
+ if (numValue >= 0 && numValue <= 59) {
5137
+ setSecond(numValue);
5138
+ onChange({ hour, minute, second: numValue });
5139
+ }
5140
+ }
5141
+ }
5142
+ };
5143
+ const handleClear = () => {
5144
+ setHour(null);
5145
+ setMinute(null);
5146
+ setSecond(null);
5147
+ onChange({ hour: null, minute: null, second: null });
5148
+ hourInputRef.current?.focus();
5149
+ };
5150
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 10px 60px auto", gap: "2", width: "auto", minWidth: "300px", children: [jsx(Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: secondInputRef, type: "text", value: second === null ? "" : second.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "second"), placeholder: "SS", maxLength: 2, textAlign: "center" }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }) }));
5151
+ }
5152
+
5153
+ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds = false, labels = {
5154
+ monthNamesShort: [
5155
+ "Jan",
5156
+ "Feb",
5157
+ "Mar",
5158
+ "Apr",
5159
+ "May",
5160
+ "Jun",
5161
+ "Jul",
5162
+ "Aug",
5163
+ "Sep",
5164
+ "Oct",
5165
+ "Nov",
5166
+ "Dec",
5167
+ ],
5168
+ weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
5169
+ backButtonLabel: "Back",
5170
+ forwardButtonLabel: "Next",
5171
+ }, timezone = "Asia/Hong_Kong", }) {
5172
+ const [selectedDate, setSelectedDate] = useState(value || "");
5173
+ // Time state for 12-hour format
5174
+ const [hour12, setHour12] = useState(value ? dayjs(value).hour() % 12 || 12 : null);
5175
+ const [minute, setMinute] = useState(value ? dayjs(value).minute() : null);
5176
+ const [meridiem, setMeridiem] = useState(value ? (dayjs(value).hour() >= 12 ? "pm" : "am") : null);
5177
+ // Time state for 24-hour format
5178
+ const [hour24, setHour24] = useState(value ? dayjs(value).hour() : null);
5179
+ const [second, setSecond] = useState(value ? dayjs(value).second() : null);
5180
+ const handleDateChange = (date) => {
5181
+ setSelectedDate(date);
5182
+ updateDateTime(dayjs(date).tz(timezone).toISOString());
5183
+ };
5184
+ const handleTimeChange = (timeData) => {
5185
+ if (format === "iso-date-time") {
5186
+ setHour24(timeData.hour);
5187
+ setMinute(timeData.minute);
5188
+ if (showSeconds)
5189
+ setSecond(timeData.second);
5190
+ }
5191
+ else {
5192
+ setHour12(timeData.hour);
5193
+ setMinute(timeData.minute);
5194
+ setMeridiem(timeData.meridiem);
5195
+ }
5196
+ updateDateTime(dayjs(selectedDate).tz(timezone).toISOString(), timeData);
5197
+ };
5198
+ const updateDateTime = (date, timeData) => {
5199
+ if (!date) {
5200
+ onChange?.(undefined);
5201
+ return;
5202
+ }
5203
+ // use dayjs to convert the date to the timezone
5204
+ const newDate = dayjs(date).tz(timezone).toDate();
5205
+ if (format === "iso-date-time") {
5206
+ const h = timeData?.hour ?? hour24;
5207
+ const m = timeData?.minute ?? minute;
5208
+ const s = showSeconds ? timeData?.second ?? second : 0;
5209
+ if (h !== null)
5210
+ newDate.setHours(h);
5211
+ if (m !== null)
5212
+ newDate.setMinutes(m);
5213
+ if (s !== null)
5214
+ newDate.setSeconds(s);
5215
+ }
5216
+ else {
5217
+ const h = timeData?.hour ?? hour12;
5218
+ const m = timeData?.minute ?? minute;
5219
+ const mer = timeData?.meridiem ?? meridiem;
5220
+ if (h !== null && mer !== null) {
5221
+ let hour24 = h;
5222
+ if (mer === "am" && h === 12)
5223
+ hour24 = 0;
5224
+ else if (mer === "pm" && h < 12)
5225
+ hour24 = h + 12;
5226
+ newDate.setHours(hour24);
5227
+ }
5228
+ if (m !== null)
5229
+ newDate.setMinutes(m);
5230
+ newDate.setSeconds(0);
5231
+ }
5232
+ onChange?.(dayjs(newDate).tz(timezone).toISOString());
5233
+ };
5234
+ const handleClear = () => {
5235
+ setSelectedDate("");
5236
+ setHour12(null);
5237
+ setHour24(null);
5238
+ setMinute(null);
5239
+ setSecond(null);
5240
+ setMeridiem(null);
5241
+ onChange?.(undefined);
5242
+ };
5243
+ const isISO = format === "iso-date-time";
5244
+ return (jsxs(Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsx(DatePicker$1, { selected: selectedDate
5245
+ ? dayjs(selectedDate).tz(timezone).toDate()
5246
+ : new Date(), onDateSelected: ({ date }) => handleDateChange(dayjs(date).tz(timezone).toISOString()), monthsToDisplay: 1, labels: labels }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: second, setSecond: setSecond, onChange: handleTimeChange })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), selectedDate && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).format(isISO
5247
+ ? showSeconds
5248
+ ? "YYYY-MM-DD HH:mm:ss"
5249
+ : "YYYY-MM-DD HH:mm"
5250
+ : "YYYY-MM-DD hh:mm A ") }), jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).tz(timezone).format("Z") }), jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: timezone })] }))] }));
5251
+ }
5252
+
5253
+ dayjs.extend(utc);
5254
+ dayjs.extend(timezone);
5255
+ const DateTimePicker = ({ column, schema, prefix, }) => {
5256
+ const { watch, formState: { errors }, setValue, } = useFormContext();
5257
+ const { translate, timezone } = useSchemaContext();
5258
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
5259
+ // with timezone
5260
+ dateFormat = "YYYY-MM-DD[T]HH:mm:ssZ", } = schema;
5261
+ const isRequired = required?.some((columnId) => columnId === column);
5262
+ const colLabel = `${prefix}${column}`;
5263
+ const [open, setOpen] = useState(false);
5264
+ const selectedDate = watch(colLabel);
5265
+ const displayDate = dayjs(selectedDate)
5266
+ .tz(timezone)
5267
+ .format(displayDateFormat);
5268
+ useEffect(() => {
5269
+ try {
5270
+ if (selectedDate) {
5271
+ // Parse the selectedDate as UTC or in a specific timezone to avoid +8 hour shift
5272
+ // For example, parse as UTC:
5273
+ const parsedDate = dayjs(selectedDate).tz(timezone);
5274
+ if (!parsedDate.isValid())
5275
+ return;
5276
+ // Format according to dateFormat from schema
5277
+ const formatted = parsedDate.format(dateFormat);
5278
+ // Update the form value only if different to avoid loops
5279
+ if (formatted !== selectedDate) {
5280
+ setValue(colLabel, formatted, {
5281
+ shouldValidate: true,
5282
+ shouldDirty: true,
5283
+ });
5284
+ }
5285
+ }
5286
+ }
5287
+ catch (e) {
5288
+ console.error(e);
5289
+ }
5290
+ }, [selectedDate, dateFormat, colLabel, setValue]);
5291
+ const customTranslate = (label) => {
5292
+ return translateWrapper({ prefix, column, label, translate });
5293
+ };
5294
+ return (jsxs(Field, { label: `${customTranslate(`field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn,
5295
+ gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5296
+ setOpen(true);
5297
+ }, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsx(PopoverContent, { minW: "450px", children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5298
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5299
+ }, timezone: timezone, labels: {
5300
+ monthNamesShort: [
5301
+ translate.t(`common.month_1`, { defaultValue: "January" }),
5302
+ translate.t(`common.month_2`, { defaultValue: "February" }),
5303
+ translate.t(`common.month_3`, { defaultValue: "March" }),
5304
+ translate.t(`common.month_4`, { defaultValue: "April" }),
5305
+ translate.t(`common.month_5`, { defaultValue: "May" }),
5306
+ translate.t(`common.month_6`, { defaultValue: "June" }),
5307
+ translate.t(`common.month_7`, { defaultValue: "July" }),
5308
+ translate.t(`common.month_8`, { defaultValue: "August" }),
5309
+ translate.t(`common.month_9`, { defaultValue: "September" }),
5310
+ translate.t(`common.month_10`, { defaultValue: "October" }),
5311
+ translate.t(`common.month_11`, { defaultValue: "November" }),
5312
+ translate.t(`common.month_12`, { defaultValue: "December" }),
5313
+ ],
5314
+ weekdayNamesShort: [
5315
+ translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
5316
+ translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
5317
+ translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
5318
+ translate.t(`common.weekday_4`, {
5319
+ defaultValue: "Wed",
5320
+ }),
5321
+ translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
5322
+ translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
5323
+ translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
5324
+ ],
5325
+ backButtonLabel: translate.t(`common.back_button`, {
5326
+ defaultValue: "Back",
5327
+ }),
5328
+ forwardButtonLabel: translate.t(`common.forward_button`, {
5329
+ defaultValue: "Forward",
5330
+ }),
5331
+ } })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: customTranslate(`field_required`) }))] }));
5332
+ };
5333
+
4507
5334
  const SchemaRenderer = ({ schema, prefix, column, }) => {
4508
5335
  const colSchema = schema;
4509
- const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5336
+ const { type, variant, properties: innerProperties, foreign_key, format, items, } = schema;
5337
+ if (variant === "custom-input") {
5338
+ return jsx(CustomInput, { schema: colSchema, prefix, column });
5339
+ }
4510
5340
  if (type === "string") {
4511
5341
  if ((schema.enum ?? []).length > 0) {
4512
5342
  return jsx(EnumPicker, { schema: colSchema, prefix, column });
@@ -4515,9 +5345,18 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
4515
5345
  idPickerSanityCheck(column, foreign_key);
4516
5346
  return jsx(IdPicker, { schema: colSchema, prefix, column });
4517
5347
  }
4518
- if (variant === "date-picker") {
5348
+ if (format === "date") {
4519
5349
  return jsx(DatePicker, { schema: colSchema, prefix, column });
4520
5350
  }
5351
+ if (format === "time") {
5352
+ return jsx(TimePicker, { schema: colSchema, prefix, column });
5353
+ }
5354
+ if (format === "date-time") {
5355
+ return jsx(DateTimePicker, { schema: colSchema, prefix, column });
5356
+ }
5357
+ if (variant === "text-area") {
5358
+ return jsx(TextAreaInput, { schema: colSchema, prefix, column });
5359
+ }
4521
5360
  return jsx(StringInputField, { schema: colSchema, prefix, column });
4522
5361
  }
4523
5362
  if (type === "number" || type === "integer") {
@@ -4564,39 +5403,56 @@ const ColumnRenderer = ({ column, properties, prefix, }) => {
4564
5403
  };
4565
5404
 
4566
5405
  const ArrayViewer = ({ schema, column, prefix }) => {
4567
- const { gridRow, gridColumn = "1/span 12", required, items } = schema;
5406
+ const { gridColumn = "span 12", gridRow = "span 1", required, items, } = schema;
4568
5407
  const { translate } = useSchemaContext();
4569
5408
  const colLabel = `${prefix}${column}`;
4570
5409
  const isRequired = required?.some((columnId) => columnId === column);
4571
5410
  const { watch, formState: { errors }, } = useFormContext();
4572
5411
  const values = watch(colLabel) ?? [];
4573
- return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsx("span", { children: "*" })] }), values.map((field, index) => (jsx(Flex, { flexFlow: "column", children: jsx(Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: jsx(SchemaViewer, { column: `${index}`,
4574
- prefix: `${colLabel}.`,
4575
- schema: items }) }) }, `form-${prefix}${column}.${index}`))), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5412
+ return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: "column", gap: 1, children: values.map((field, index) => (jsx(Flex, { flexFlow: "column", bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: "2", borderRadius: "md", borderWidth: "thin", borderColor: {
5413
+ base: "colorPalette.200",
5414
+ _dark: "colorPalette.800",
5415
+ }, children: jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsx(SchemaViewer, { column: `${index}`,
5416
+ prefix: `${colLabel}.`,
5417
+ // @ts-expect-error find suitable types
5418
+ schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4576
5419
  };
4577
5420
 
4578
5421
  const BooleanViewer = ({ schema, column, prefix, }) => {
4579
5422
  const { watch, formState: { errors }, } = useFormContext();
4580
5423
  const { translate } = useSchemaContext();
4581
- const { required, gridColumn, gridRow } = schema;
5424
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4582
5425
  const isRequired = required?.some((columnId) => columnId === column);
4583
5426
  const colLabel = `${prefix}${column}`;
4584
5427
  const value = watch(colLabel);
4585
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5428
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4586
5429
  gridRow, children: [jsx(Text, { children: value
4587
5430
  ? translate.t(removeIndex(`${colLabel}.true`))
4588
- : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5431
+ : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5432
+ };
5433
+
5434
+ const CustomViewer = ({ column, schema, prefix }) => {
5435
+ const formContext = useFormContext();
5436
+ const { inputViewerRender } = schema;
5437
+ return (inputViewerRender &&
5438
+ inputViewerRender({
5439
+ column,
5440
+ schema,
5441
+ prefix,
5442
+ formContext,
5443
+ }));
4589
5444
  };
4590
5445
 
4591
5446
  const DateViewer = ({ column, schema, prefix }) => {
4592
5447
  const { watch, formState: { errors }, } = useFormContext();
4593
- const { translate } = useSchemaContext();
4594
- const { required, gridColumn, gridRow } = schema;
5448
+ const { translate, timezone } = useSchemaContext();
5449
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", } = schema;
4595
5450
  const isRequired = required?.some((columnId) => columnId === column);
4596
5451
  const colLabel = `${prefix}${column}`;
4597
5452
  const selectedDate = watch(colLabel);
4598
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4599
- gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? selectedDate : ""] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
5453
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
5454
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5455
+ gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4600
5456
  };
4601
5457
 
4602
5458
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
@@ -4604,45 +5460,41 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
4604
5460
  const { translate } = useSchemaContext();
4605
5461
  const { required } = schema;
4606
5462
  const isRequired = required?.some((columnId) => columnId === column);
4607
- const { gridColumn, gridRow, renderDisplay } = schema;
5463
+ const { gridColumn = "span 4", gridRow = "span 1", renderDisplay } = schema;
4608
5464
  const colLabel = `${prefix}${column}`;
4609
5465
  const watchEnum = watch(colLabel);
4610
5466
  const watchEnums = (watch(colLabel) ?? []);
4611
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5467
+ const customTranslate = (label) => {
5468
+ return translateWrapper({ prefix, column, label, translate });
5469
+ };
5470
+ return (jsxs(Field, { label: `${customTranslate(`field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn,
4612
5471
  gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: "wrap", gap: 1, children: watchEnums.map((enumValue) => {
4613
5472
  const item = enumValue;
4614
5473
  if (item === undefined) {
4615
5474
  return jsx(Fragment, { children: "undefined" });
4616
5475
  }
4617
- return (jsx(Tag, { closable: true, children: !!renderDisplay === true
5476
+ return (jsx(Tag, { children: !!renderDisplay === true
4618
5477
  ? renderDisplay(item)
4619
- : translate.t(removeIndex(`${colLabel}.${item}`)) }));
4620
- }) })), !isMultiple && (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5478
+ : customTranslate(item) }));
5479
+ }) })), !isMultiple && jsx(Text, { children: customTranslate(watchEnum) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: customTranslate(`field_required`) }))] }));
4621
5480
  };
4622
5481
 
4623
5482
  const FileViewer = ({ column, schema, prefix }) => {
4624
- const { setValue, formState: { errors }, watch, } = useFormContext();
5483
+ const { watch } = useFormContext();
4625
5484
  const { translate } = useSchemaContext();
4626
- const { required, gridColumn, gridRow } = schema;
5485
+ const { required, gridColumn = "span 4", gridRow = "span 1", } = schema;
4627
5486
  const isRequired = required?.some((columnId) => columnId === column);
4628
5487
  const currentFiles = (watch(column) ?? []);
4629
5488
  const colLabel = `${prefix}${column}`;
4630
- return (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: [jsx(FileDropzone, { onDrop: ({ files }) => {
4631
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4632
- setValue(colLabel, [...currentFiles, ...newFiles]);
4633
- }, placeholder: translate.t(`${colLabel}.fileDropzone`) }), jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4634
- return (jsx(Card.Root, { variant: "subtle", children: jsxs(Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4635
- setValue(column, currentFiles.filter(({ name }) => {
4636
- return name !== file.name;
4637
- }));
4638
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4639
- }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5489
+ return (jsx(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
5490
+ return (jsx(Card.Root, { variant: "subtle", children: jsxs(Card.Body, { gap: "2", display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name })] }) }, file.name));
5491
+ }) }) }));
4640
5492
  };
4641
5493
 
4642
5494
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4643
5495
  const { watch, formState: { errors }, } = useFormContext();
4644
5496
  const { idMap, translate } = useSchemaContext();
4645
- const { required, gridColumn, gridRow, renderDisplay, foreign_key } = schema;
5497
+ const { required, gridColumn = "span 4", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
4646
5498
  const isRequired = required?.some((columnId) => columnId === column);
4647
5499
  const { display_column } = foreign_key;
4648
5500
  const colLabel = `${prefix}${column}`;
@@ -4658,7 +5510,7 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4658
5510
  }
4659
5511
  return record[display_column];
4660
5512
  };
4661
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.fieldLabel`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5513
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4662
5514
  gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: "wrap", gap: 1, children: watchIds.map((id) => {
4663
5515
  const item = idMap[id];
4664
5516
  if (item === undefined) {
@@ -4667,21 +5519,21 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
4667
5519
  return (jsx(Tag, { closable: true, children: !!renderDisplay === true
4668
5520
  ? renderDisplay(item)
4669
5521
  : item[display_column] }, id));
4670
- }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5522
+ }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4671
5523
  };
4672
5524
 
4673
5525
  const NumberViewer = ({ schema, column, prefix, }) => {
4674
5526
  const { watch, formState: { errors }, } = useFormContext();
4675
5527
  const { translate } = useSchemaContext();
4676
- const { required, gridColumn, gridRow } = schema;
5528
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4677
5529
  const isRequired = required?.some((columnId) => columnId === column);
4678
5530
  const colLabel = `${prefix}${column}`;
4679
5531
  const value = watch(colLabel);
4680
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: value }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5532
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: value }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4681
5533
  };
4682
5534
 
4683
5535
  const ObjectViewer = ({ schema, column, prefix }) => {
4684
- const { properties, gridRow, gridColumn = "1/span 12", required } = schema;
5536
+ const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
4685
5537
  const { translate } = useSchemaContext();
4686
5538
  const colLabel = `${prefix}${column}`;
4687
5539
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4689,25 +5541,28 @@ const ObjectViewer = ({ schema, column, prefix }) => {
4689
5541
  if (properties === undefined) {
4690
5542
  throw new Error(`properties is undefined when using ObjectInput`);
4691
5543
  }
4692
- return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, isRequired && jsx("span", { children: "*" })] }), jsx(Grid, { gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat("auto-fit", auto)`, children: Object.keys(properties ?? {}).map((key) => {
5544
+ return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] })), jsx(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: {
5545
+ base: "colorPalette.200",
5546
+ _dark: "colorPalette.800",
5547
+ }, children: Object.keys(properties ?? {}).map((key) => {
4693
5548
  return (
4694
5549
  // @ts-expect-error find suitable types
4695
5550
  jsx(ColumnViewer, { column: `${key}`,
4696
5551
  prefix: `${prefix}${column}.`,
4697
5552
  properties }, `form-objectviewer-${colLabel}-${key}`));
4698
- }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }));
5553
+ }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4699
5554
  };
4700
5555
 
4701
5556
  const RecordInput = ({ column, schema, prefix }) => {
4702
5557
  const { formState: { errors }, setValue, getValues, } = useFormContext();
4703
5558
  const { translate } = useSchemaContext();
4704
- const { required, gridColumn, gridRow } = schema;
5559
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4705
5560
  const isRequired = required?.some((columnId) => columnId === column);
4706
5561
  const entries = Object.entries(getValues(column) ?? {});
4707
5562
  const [showNewEntries, setShowNewEntries] = useState(false);
4708
5563
  const [newKey, setNewKey] = useState();
4709
5564
  const [newValue, setNewValue] = useState();
4710
- return (jsxs(Field, { label: `${translate.t(`${column}.fieldLabel`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
5565
+ return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4711
5566
  return (jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
4712
5567
  const filtered = entries.filter(([target]) => {
4713
5568
  return target !== key;
@@ -4747,7 +5602,17 @@ const RecordInput = ({ column, schema, prefix }) => {
4747
5602
  setShowNewEntries(true);
4748
5603
  setNewKey(undefined);
4749
5604
  setNewValue(undefined);
4750
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.fieldRequired`) }))] }));
5605
+ }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5606
+ };
5607
+
5608
+ const StringViewer = ({ column, schema, prefix, }) => {
5609
+ const { watch, formState: { errors }, } = useFormContext();
5610
+ const { translate } = useSchemaContext();
5611
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
5612
+ const isRequired = required?.some((columnId) => columnId === column);
5613
+ const colLabel = `${prefix}${column}`;
5614
+ const value = watch(colLabel);
5615
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4751
5616
  };
4752
5617
 
4753
5618
  const TagViewer = ({ column, schema, prefix }) => {
@@ -4835,19 +5700,50 @@ const TagViewer = ({ column, schema, prefix }) => {
4835
5700
  }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4836
5701
  };
4837
5702
 
4838
- const StringViewer = ({ column, schema, prefix, }) => {
5703
+ const TextAreaViewer = ({ column, schema, prefix, }) => {
4839
5704
  const { watch, formState: { errors }, } = useFormContext();
4840
5705
  const { translate } = useSchemaContext();
4841
- const { required, gridColumn, gridRow } = schema;
5706
+ const { required, gridColumn = "span 4", gridRow = "span 1" } = schema;
4842
5707
  const isRequired = required?.some((columnId) => columnId === column);
4843
5708
  const colLabel = `${prefix}${column}`;
4844
5709
  const value = watch(colLabel);
4845
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.fieldLabel`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.fieldRequired`)) }))] }) }));
5710
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), " ", errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5711
+ };
5712
+
5713
+ const TimeViewer = ({ column, schema, prefix }) => {
5714
+ const { watch, formState: { errors }, } = useFormContext();
5715
+ const { translate, timezone } = useSchemaContext();
5716
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayTimeFormat = "hh:mm A", } = schema;
5717
+ const isRequired = required?.some((columnId) => columnId === column);
5718
+ const colLabel = `${prefix}${column}`;
5719
+ const selectedDate = watch(colLabel);
5720
+ const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
5721
+ .tz(timezone)
5722
+ .isValid()
5723
+ ? dayjs(`1970-01-01T${selectedDate}`).tz(timezone).format(displayTimeFormat)
5724
+ : "";
5725
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5726
+ gridRow, children: [jsx(Text, { children: displayedTime }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5727
+ };
5728
+
5729
+ const DateTimeViewer = ({ column, schema, prefix }) => {
5730
+ const { watch, formState: { errors }, } = useFormContext();
5731
+ const { translate, timezone } = useSchemaContext();
5732
+ const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss", } = schema;
5733
+ const isRequired = required?.some((columnId) => columnId === column);
5734
+ const colLabel = `${prefix}${column}`;
5735
+ const selectedDate = watch(colLabel);
5736
+ const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
5737
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5738
+ gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4846
5739
  };
4847
5740
 
4848
5741
  const SchemaViewer = ({ schema, prefix, column, }) => {
4849
5742
  const colSchema = schema;
4850
- const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5743
+ const { type, variant, properties: innerProperties, foreign_key, items, format, } = schema;
5744
+ if (variant === "custom-input") {
5745
+ return jsx(CustomViewer, { schema: colSchema, prefix, column });
5746
+ }
4851
5747
  if (type === "string") {
4852
5748
  if ((schema.enum ?? []).length > 0) {
4853
5749
  return jsx(EnumViewer, { schema: colSchema, prefix, column });
@@ -4856,9 +5752,18 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
4856
5752
  idPickerSanityCheck(column, foreign_key);
4857
5753
  return jsx(IdViewer, { schema: colSchema, prefix, column });
4858
5754
  }
4859
- if (variant === "date-picker") {
5755
+ if (format === "time") {
5756
+ return jsx(TimeViewer, { schema: colSchema, prefix, column });
5757
+ }
5758
+ if (format === "date") {
4860
5759
  return jsx(DateViewer, { schema: colSchema, prefix, column });
4861
5760
  }
5761
+ if (format === "date-time") {
5762
+ return jsx(DateTimeViewer, { schema: colSchema, prefix, column });
5763
+ }
5764
+ if (variant === "text-area") {
5765
+ return jsx(TextAreaViewer, { schema: colSchema, prefix, column });
5766
+ }
4862
5767
  return jsx(StringViewer, { schema: colSchema, prefix, column });
4863
5768
  }
4864
5769
  if (type === "number" || type === "integer") {
@@ -4907,10 +5812,24 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
4907
5812
  };
4908
5813
 
4909
5814
  const SubmitButton = () => {
4910
- const { translate, setValidatedData, setIsError, setIsConfirming } = useSchemaContext();
5815
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
4911
5816
  const methods = useFormContext();
4912
5817
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4913
5818
  const onValid = (data) => {
5819
+ // Validate data using AJV before proceeding to confirmation
5820
+ const validate = new Ajv({
5821
+ strict: false,
5822
+ allErrors: true,
5823
+ }).compile(schema);
5824
+ const validationResult = validate(data);
5825
+ // @ts-expect-error TODO: find appropriate type
5826
+ const errors = validationResult.errors;
5827
+ if (errors && errors.length > 0) {
5828
+ setError(errors);
5829
+ setIsError(true);
5830
+ return;
5831
+ }
5832
+ // If validation passes, proceed to confirmation
4914
5833
  setValidatedData(data);
4915
5834
  setIsError(false);
4916
5835
  setIsConfirming(true);
@@ -4921,7 +5840,7 @@ const SubmitButton = () => {
4921
5840
  };
4922
5841
 
4923
5842
  const FormBody = () => {
4924
- const { schema, requestUrl, order, ignore, include, onSubmit, rowNumber, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, } = useSchemaContext();
5843
+ const { schema, requestUrl, order, ignore, include, onSubmit, rowNumber, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, } = useSchemaContext();
4925
5844
  const methods = useFormContext();
4926
5845
  const { properties } = schema;
4927
5846
  const onBeforeSubmit = () => {
@@ -4937,6 +5856,39 @@ const FormBody = () => {
4937
5856
  const onSubmitSuccess = () => {
4938
5857
  setIsSuccess(true);
4939
5858
  };
5859
+ // Enhanced validation function using AJV with i18n support
5860
+ const validateFormData = (data) => {
5861
+ try {
5862
+ const ajv = new Ajv({
5863
+ strict: false,
5864
+ allErrors: true,
5865
+ });
5866
+ addFormats(ajv);
5867
+ addErrors(ajv);
5868
+ const validate = ajv.compile(schema);
5869
+ const validationResult = validate(data);
5870
+ const errors = validate.errors;
5871
+ console.log({
5872
+ isValid: validationResult,
5873
+ errors,
5874
+ }, "plkdfs");
5875
+ return {
5876
+ isValid: validationResult,
5877
+ errors,
5878
+ };
5879
+ }
5880
+ catch (error) {
5881
+ return {
5882
+ isValid: false,
5883
+ errors: [
5884
+ {
5885
+ field: "validation",
5886
+ message: error instanceof Error ? error.message : "Unknown error",
5887
+ },
5888
+ ],
5889
+ };
5890
+ }
5891
+ };
4940
5892
  const defaultOnSubmit = async (promise) => {
4941
5893
  try {
4942
5894
  onBeforeSubmit();
@@ -4961,12 +5913,31 @@ const FormBody = () => {
4961
5913
  };
4962
5914
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4963
5915
  const onFormSubmit = async (data) => {
5916
+ // Validate data using AJV before submission
5917
+ const validationResult = validateFormData(data);
5918
+ if (!validationResult.isValid) {
5919
+ // Set validation errors
5920
+ const validationErrorMessage = {
5921
+ type: "validation",
5922
+ errors: validationResult.errors,
5923
+ message: translate.t("validation_error"),
5924
+ };
5925
+ onSubmitError(validationErrorMessage);
5926
+ return;
5927
+ }
4964
5928
  if (onSubmit === undefined) {
4965
5929
  await defaultOnSubmit(defaultSubmitPromise(data));
4966
5930
  return;
4967
5931
  }
4968
5932
  await defaultOnSubmit(onSubmit(data));
4969
5933
  };
5934
+ // Custom error renderer for validation errors with i18n support
5935
+ const renderValidationErrors = (validationErrors) => {
5936
+ return (jsx(AccordionRoot, { backgroundColor: {
5937
+ base: "red.50",
5938
+ _dark: "red.950",
5939
+ }, p: "4", colorPalette: "red", collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "validation-errors", children: [jsx(AccordionItemTrigger, { children: translate.t("validation_error") }), jsx(AccordionItemContent, { display: "flex", flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxs(AlertRoot, { status: "error", display: "flex", alignItems: "center", children: [jsx(AlertIndicator, {}), jsxs(AlertContent, { children: [jsx(AlertTitle, { fontWeight: "bold", children: err.instancePath }), jsx(AlertDescription, { children: err.message }), err.params !== undefined && (jsx(AlertDescription, { whiteSpace: "pre-wrap", wordBreak: "break-all", children: JSON.stringify(err.data, null, 2) }))] })] }))) })] }) }));
5940
+ };
4970
5941
  const renderColumns = ({ order, keys, ignore, include, }) => {
4971
5942
  const included = include.length > 0 ? include : keys;
4972
5943
  const not_exist = included.filter((columnA) => !order.some((columnB) => columnA === columnB));
@@ -4981,7 +5952,7 @@ const FormBody = () => {
4981
5952
  include,
4982
5953
  });
4983
5954
  if (isSuccess) {
4984
- return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Title, { children: translate.t("submitSuccess") })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
5955
+ return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Title, { children: translate.t("submit_success") })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
4985
5956
  setIsError(false);
4986
5957
  setIsSubmiting(false);
4987
5958
  setIsSuccess(false);
@@ -4989,10 +5960,10 @@ const FormBody = () => {
4989
5960
  setValidatedData(undefined);
4990
5961
  const data = await getUpdatedData();
4991
5962
  methods.reset(data);
4992
- }, formNoValidate: true, children: translate.t("submitAgain") }) })] }));
5963
+ }, formNoValidate: true, children: translate.t("submit_again") }) })] }));
4993
5964
  }
4994
5965
  if (isConfirming) {
4995
- return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat(${rowNumber ?? "auto-fit"}, auto)`, children: ordered.map((column) => {
5966
+ return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: "repeat(12, max-content)", autoFlow: "row", children: ordered.map((column) => {
4996
5967
  return (jsx(ColumnViewer
4997
5968
  // @ts-expect-error find suitable types
4998
5969
  , {
@@ -5002,9 +5973,10 @@ const FormBody = () => {
5002
5973
  setIsConfirming(false);
5003
5974
  }, variant: "subtle", children: translate.t("cancel") }), jsx(Button$1, { onClick: () => {
5004
5975
  onFormSubmit(validatedData);
5005
- }, children: translate.t("confirm") })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && (jsx(Fragment, { children: jsx(Alert.Root, { status: "error", children: jsx(Alert.Title, { children: jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "b", children: [jsxs(AccordionItemTrigger, { children: [jsx(Alert.Indicator, {}), `${error}`] }), jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) }) }) }))] }));
5976
+ }, children: translate.t("confirm") })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
5977
+ error?.errors ? (renderValidationErrors(error.errors)) : (jsx(Alert.Root, { status: "error", children: jsx(Alert.Title, { children: jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "b", children: [jsxs(AccordionItemTrigger, { children: [jsx(Alert.Indicator, {}), `${error}`] }), jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) }) })) })) }))] }));
5006
5978
  }
5007
- return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: `repeat(${rowNumber ?? "auto-fit"}, auto)`, children: ordered.map((column) => {
5979
+ return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
5008
5980
  return (jsx(ColumnRenderer
5009
5981
  // @ts-expect-error find suitable types
5010
5982
  , {
@@ -5012,7 +5984,8 @@ const FormBody = () => {
5012
5984
  properties: properties, prefix: ``, column }, `form-input-${column}`));
5013
5985
  }) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [jsx(Button$1, { onClick: () => {
5014
5986
  methods.reset();
5015
- }, variant: "subtle", children: translate.t("reset") }), jsx(SubmitButton, {})] })] }));
5987
+ }, variant: "subtle", children: translate.t("reset") }), jsx(SubmitButton, {})] }), isError && error?.type === "validation" && (jsx(Box, { mt: 4, children: error?.errors &&
5988
+ renderValidationErrors(error.errors) }))] }));
5016
5989
  };
5017
5990
 
5018
5991
  const FormTitle = () => {
@@ -5020,8 +5993,8 @@ const FormTitle = () => {
5020
5993
  return jsx(Heading, { children: translate.t("title") });
5021
5994
  };
5022
5995
 
5023
- const DefaultForm = ({ formConfig, }) => {
5024
- return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
5996
+ const DefaultForm = ({ formConfig, showTitle = true, }) => {
5997
+ return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
5025
5998
  };
5026
5999
 
5027
6000
  const useForm = ({ preLoadedValues, keyPrefix }) => {
@@ -5054,4 +6027,4 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
5054
6027
  }
5055
6028
  };
5056
6029
 
5057
- export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FilterOptions, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
6030
+ export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };