@bsol-oss/react-datatable5 12.0.0-beta.95 → 13.0.1-beta.0

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 (37) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts +166 -41
  3. package/dist/index.js +1151 -612
  4. package/dist/index.mjs +1153 -615
  5. package/dist/types/components/DataTable/DataTable.d.ts +1 -3
  6. package/dist/types/components/DataTable/DataTableServer.d.ts +7 -9
  7. package/dist/types/components/DataTable/context/DataTableContext.d.ts +4 -6
  8. package/dist/types/components/DataTable/controls/MobileTableControls.d.ts +29 -0
  9. package/dist/types/components/DataTable/controls/TableControls.d.ts +2 -2
  10. package/dist/types/components/DataTable/display/CalendarDisplay.d.ts +84 -0
  11. package/dist/types/components/DataTable/display/DataDisplay.d.ts +0 -2
  12. package/dist/types/components/DataTable/display/MobileTableDisplay.d.ts +5 -0
  13. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +1 -3
  14. package/dist/types/components/DataTable/hooks/useIsMobile.d.ts +6 -0
  15. package/dist/types/components/DataTable/useDataTable.d.ts +3 -6
  16. package/dist/types/components/DataTable/useDataTableServer.d.ts +4 -4
  17. package/dist/types/components/DataTable/utils/getColumns.d.ts +3 -5
  18. package/dist/types/components/DatePicker/DatePicker.d.ts +7 -8
  19. package/dist/types/components/DatePicker/DateTimePicker.d.ts +3 -1
  20. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +5 -1
  21. package/dist/types/components/DatePicker/RangeDatePicker.d.ts +4 -4
  22. package/dist/types/components/DatePicker/useCalendar.d.ts +48 -0
  23. package/dist/types/components/Form/SchemaFormContext.d.ts +5 -3
  24. package/dist/types/components/Form/components/core/FormBody.d.ts +1 -2
  25. package/dist/types/components/Form/components/core/FormRoot.d.ts +6 -4
  26. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -2
  27. package/dist/types/components/Form/components/fields/IdPicker.d.ts +8 -0
  28. package/dist/types/components/Form/components/fields/IdPickerMultiple.d.ts +7 -0
  29. package/dist/types/components/Form/components/fields/IdPickerSingle.d.ts +7 -0
  30. package/dist/types/components/Form/components/fields/useIdPickerData.d.ts +46 -0
  31. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +9 -0
  32. package/dist/types/components/Form/useForm.d.ts +7 -2
  33. package/dist/types/components/Form/utils/useFormI18n.d.ts +14 -12
  34. package/dist/types/components/TimePicker/TimePicker.d.ts +4 -6
  35. package/dist/types/components/ui/provider.d.ts +1 -1
  36. package/dist/types/index.d.ts +1 -0
  37. package/package.json +1 -3
package/dist/index.js CHANGED
@@ -9,7 +9,6 @@ var md = require('react-icons/md');
9
9
  var fa6 = require('react-icons/fa6');
10
10
  var bi = require('react-icons/bi');
11
11
  var cg = require('react-icons/cg');
12
- var Dayzed = require('@bsol-oss/dayzed-react19');
13
12
  var hi2 = require('react-icons/hi2');
14
13
  var io = require('react-icons/io');
15
14
  var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
@@ -25,7 +24,6 @@ var bs = require('react-icons/bs');
25
24
  var hi = require('react-icons/hi');
26
25
  var reactTable = require('@tanstack/react-table');
27
26
  var gr = require('react-icons/gr');
28
- var reactI18next = require('react-i18next');
29
27
  var axios = require('axios');
30
28
  var reactHookForm = require('react-hook-form');
31
29
  var Ajv = require('ajv');
@@ -58,36 +56,35 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
58
56
 
59
57
  const DataTableContext = React.createContext({
60
58
  table: {},
61
- globalFilter: "",
59
+ globalFilter: '',
62
60
  setGlobalFilter: () => { },
63
- type: "client",
64
- translate: {},
61
+ type: 'client',
65
62
  data: [],
66
63
  columns: [],
67
64
  columnOrder: [],
68
65
  columnFilters: [],
69
- density: "sm",
66
+ density: 'sm',
70
67
  sorting: [],
71
68
  setPagination: function () {
72
- throw new Error("Function not implemented.");
69
+ throw new Error('Function not implemented.');
73
70
  },
74
71
  setSorting: function () {
75
- throw new Error("Function not implemented.");
72
+ throw new Error('Function not implemented.');
76
73
  },
77
74
  setColumnFilters: function () {
78
- throw new Error("Function not implemented.");
75
+ throw new Error('Function not implemented.');
79
76
  },
80
77
  setRowSelection: function () {
81
- throw new Error("Function not implemented.");
78
+ throw new Error('Function not implemented.');
82
79
  },
83
80
  setColumnOrder: function () {
84
- throw new Error("Function not implemented.");
81
+ throw new Error('Function not implemented.');
85
82
  },
86
83
  setDensity: function () {
87
- throw new Error("Function not implemented.");
84
+ throw new Error('Function not implemented.');
88
85
  },
89
86
  setColumnVisibility: function () {
90
- throw new Error("Function not implemented.");
87
+ throw new Error('Function not implemented.');
91
88
  },
92
89
  pagination: {
93
90
  pageIndex: 0,
@@ -96,21 +93,21 @@ const DataTableContext = React.createContext({
96
93
  rowSelection: {},
97
94
  columnVisibility: {},
98
95
  tableLabel: {
99
- view: "View",
100
- edit: "Edit",
101
- filterButtonText: "Filter",
102
- filterTitle: "Filter",
103
- filterReset: "Reset",
104
- filterClose: "Close",
105
- reloadTooltip: "Reload",
106
- reloadButtonText: "Reload",
107
- resetSelection: "Reset Selection",
108
- resetSorting: "Reset Sorting",
109
- rowCountText: "Row Count",
110
- hasErrorText: "Has Error",
111
- globalFilterPlaceholder: "Search",
112
- trueLabel: "True",
113
- falseLabel: "False",
96
+ view: 'View',
97
+ edit: 'Edit',
98
+ filterButtonText: 'Filter',
99
+ filterTitle: 'Filter',
100
+ filterReset: 'Reset',
101
+ filterClose: 'Close',
102
+ reloadTooltip: 'Reload',
103
+ reloadButtonText: 'Reload',
104
+ resetSelection: 'Reset Selection',
105
+ resetSorting: 'Reset Sorting',
106
+ rowCountText: '',
107
+ hasErrorText: 'Has Error',
108
+ globalFilterPlaceholder: 'Search',
109
+ trueLabel: 'True',
110
+ falseLabel: 'False',
114
111
  },
115
112
  });
116
113
 
@@ -187,6 +184,166 @@ const Radio = React__namespace.forwardRef(function Radio(props, ref) {
187
184
  });
188
185
  const RadioGroup = react.RadioGroup.Root;
189
186
 
187
+ // Helper function to check if two dates are the same day
188
+ function isSameDay(date1, date2) {
189
+ return (date1.getFullYear() === date2.getFullYear() &&
190
+ date1.getMonth() === date2.getMonth() &&
191
+ date1.getDate() === date2.getDate());
192
+ }
193
+ // Helper function to check if a date is today
194
+ function isToday(date) {
195
+ const today = new Date();
196
+ return isSameDay(date, today);
197
+ }
198
+ // Helper function to check if a date is selected
199
+ function isSelected(date, selected) {
200
+ if (!selected)
201
+ return false;
202
+ if (Array.isArray(selected)) {
203
+ return selected.some((d) => isSameDay(d, date));
204
+ }
205
+ return isSameDay(selected, date);
206
+ }
207
+ // Helper function to check if a date is selectable
208
+ function isSelectable(date, minDate, maxDate) {
209
+ if (minDate) {
210
+ // Normalize to start of day for comparison
211
+ const minDateStart = new Date(minDate);
212
+ minDateStart.setHours(0, 0, 0, 0);
213
+ const dateStart = new Date(date);
214
+ dateStart.setHours(0, 0, 0, 0);
215
+ if (dateStart < minDateStart)
216
+ return false;
217
+ }
218
+ if (maxDate) {
219
+ // Normalize to start of day for comparison
220
+ const maxDateStart = new Date(maxDate);
221
+ maxDateStart.setHours(0, 0, 0, 0);
222
+ const dateStart = new Date(date);
223
+ dateStart.setHours(0, 0, 0, 0);
224
+ if (dateStart > maxDateStart)
225
+ return false;
226
+ }
227
+ return true;
228
+ }
229
+ // Generate calendar weeks for a given month
230
+ function generateCalendarWeeks(year, month, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate) {
231
+ const weeks = [];
232
+ const firstDay = new Date(year, month, 1);
233
+ const lastDay = new Date(year, month + 1, 0);
234
+ // Get the first day of the week for the first day of the month
235
+ let firstDayWeekday = firstDay.getDay();
236
+ // Adjust for firstDayOfWeek
237
+ firstDayWeekday = (firstDayWeekday - firstDayOfWeek + 7) % 7;
238
+ // Start from the first day of the week that contains the first day of the month
239
+ const startDate = new Date(firstDay);
240
+ startDate.setDate(startDate.getDate() - firstDayWeekday);
241
+ let currentDate = new Date(startDate);
242
+ const endDate = new Date(lastDay);
243
+ // Find the last day of the week that contains the last day of the month
244
+ let lastDayWeekday = lastDay.getDay();
245
+ lastDayWeekday = (lastDayWeekday - firstDayOfWeek + 7) % 7;
246
+ endDate.setDate(endDate.getDate() + (6 - lastDayWeekday));
247
+ while (currentDate <= endDate) {
248
+ const week = [];
249
+ for (let i = 0; i < 7; i++) {
250
+ const date = new Date(currentDate);
251
+ const isCurrentMonth = date.getMonth() === month;
252
+ if (!showOutsideDays && !isCurrentMonth) {
253
+ week.push(null);
254
+ }
255
+ else {
256
+ const calendarDate = {
257
+ date,
258
+ selected: isSelected(date, selected),
259
+ selectable: isSelectable(date, minDate, maxDate) &&
260
+ (showOutsideDays || isCurrentMonth),
261
+ today: isToday(date),
262
+ isCurrentMonth,
263
+ };
264
+ week.push(calendarDate);
265
+ }
266
+ currentDate.setDate(currentDate.getDate() + 1);
267
+ }
268
+ weeks.push(week);
269
+ }
270
+ return weeks;
271
+ }
272
+ // Generate calendars for the given months
273
+ function generateCalendars(startDate, monthsToDisplay, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate) {
274
+ const calendars = [];
275
+ const currentDate = new Date(startDate);
276
+ for (let i = 0; i < monthsToDisplay; i++) {
277
+ const year = currentDate.getFullYear();
278
+ const month = currentDate.getMonth();
279
+ const weeks = generateCalendarWeeks(year, month, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate);
280
+ calendars.push({
281
+ month,
282
+ year,
283
+ weeks,
284
+ });
285
+ // Move to next month
286
+ currentDate.setMonth(month + 1);
287
+ }
288
+ return calendars;
289
+ }
290
+ function useCalendar({ selected, firstDayOfWeek = 0, showOutsideDays = true, date, minDate, maxDate, monthsToDisplay = 1, onDateSelected, }) {
291
+ const [currentDate, setCurrentDate] = React.useState(() => {
292
+ return date ? new Date(date) : new Date();
293
+ });
294
+ const calendars = React.useMemo(() => {
295
+ return generateCalendars(currentDate, monthsToDisplay, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate);
296
+ }, [
297
+ currentDate,
298
+ monthsToDisplay,
299
+ firstDayOfWeek,
300
+ showOutsideDays,
301
+ selected,
302
+ minDate,
303
+ maxDate,
304
+ ]);
305
+ const navigate = React.useCallback((offset) => {
306
+ setCurrentDate((prev) => {
307
+ const newDate = new Date(prev);
308
+ newDate.setMonth(prev.getMonth() + offset);
309
+ return newDate;
310
+ });
311
+ }, []);
312
+ const getBackProps = React.useCallback((props) => {
313
+ return {
314
+ onClick: () => {
315
+ navigate(-(props?.offset || 1));
316
+ },
317
+ };
318
+ }, [navigate]);
319
+ const getForwardProps = React.useCallback((props) => {
320
+ return {
321
+ onClick: () => {
322
+ navigate(props?.offset || 1);
323
+ },
324
+ };
325
+ }, [navigate]);
326
+ const getDateProps = React.useCallback((props) => {
327
+ return {
328
+ onClick: () => {
329
+ if (props.dateObj.selectable && onDateSelected) {
330
+ onDateSelected({
331
+ date: props.dateObj.date,
332
+ selected: selected || props.dateObj.date,
333
+ });
334
+ }
335
+ },
336
+ onMouseEnter: props.onMouseEnter,
337
+ };
338
+ }, [onDateSelected, selected]);
339
+ return {
340
+ calendars,
341
+ getBackProps,
342
+ getForwardProps,
343
+ getDateProps,
344
+ };
345
+ }
346
+
190
347
  const RangeDatePickerContext = React.createContext({
191
348
  labels: {
192
349
  monthNamesFull: [
@@ -252,7 +409,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
252
409
  if (!dateObj) {
253
410
  return jsxRuntime.jsx(react.Box, {}, key);
254
411
  }
255
- const { date, selected, selectable, today } = dateObj;
412
+ const { date, selected, selectable, today, isCurrentMonth, } = dateObj;
256
413
  const getStyle = ({ selected, unavailable, today, isInRange, }) => {
257
414
  if (unavailable) {
258
415
  return {
@@ -290,7 +447,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
290
447
  unavailable: !selectable,
291
448
  today,
292
449
  isInRange: isInRange(date),
293
- }), children: selectable ? date.getDate() : 'X' }, key));
450
+ }), opacity: isCurrentMonth ? 1 : 0.4, children: selectable ? date.getDate() : 'X' }, key));
294
451
  })) })] }, `${calendar.month}${calendar.year}`))) })] }));
295
452
  }
296
453
  return null;
@@ -313,10 +470,57 @@ const RangeDatePicker = ({ labels = {
313
470
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
314
471
  backButtonLabel: 'Back',
315
472
  forwardButtonLabel: 'Next',
316
- }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, ...rest }) => {
317
- return (jsxRuntime.jsx(RangeDatePickerContext.Provider, { value: { labels }, children: jsxRuntime.jsx(Dayzed, { onDateSelected: onDateSelected, selected: selected, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, date: date, minDate: minDate, maxDate: maxDate, monthsToDisplay: monthsToDisplay, ...rest, render: (dayzedData) => (jsxRuntime.jsx(Calendar$1, { ...dayzedData,
318
- firstDayOfWeek,
319
- selected: selected })) }) }));
473
+ }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, render, }) => {
474
+ const handleDateSelected = (obj) => {
475
+ if (onDateSelected) {
476
+ const dateObj = obj.date;
477
+ const currentSelected = Array.isArray(obj.selected)
478
+ ? obj.selected
479
+ : [obj.selected];
480
+ // Range selection logic: if one date selected, add second; if two selected, replace with new date
481
+ let newSelected;
482
+ if (currentSelected.length === 0) {
483
+ newSelected = [dateObj];
484
+ }
485
+ else if (currentSelected.length === 1) {
486
+ const firstDate = currentSelected[0];
487
+ if (dateObj < firstDate) {
488
+ newSelected = [dateObj, firstDate];
489
+ }
490
+ else {
491
+ newSelected = [firstDate, dateObj];
492
+ }
493
+ }
494
+ else {
495
+ newSelected = [dateObj];
496
+ }
497
+ // Check if date is selectable
498
+ const selectable = !minDate || dateObj >= minDate;
499
+ if (maxDate) {
500
+ const isSelectable = dateObj <= maxDate;
501
+ if (!isSelectable)
502
+ return;
503
+ }
504
+ onDateSelected({
505
+ selected: newSelected,
506
+ selectable,
507
+ date: dateObj,
508
+ });
509
+ }
510
+ };
511
+ const calendarData = useCalendar({
512
+ onDateSelected: handleDateSelected,
513
+ selected,
514
+ firstDayOfWeek,
515
+ showOutsideDays,
516
+ date,
517
+ minDate,
518
+ maxDate,
519
+ monthsToDisplay,
520
+ });
521
+ return (jsxRuntime.jsx(RangeDatePickerContext.Provider, { value: { labels }, children: render ? (render(calendarData)) : (jsxRuntime.jsx(Calendar$1, { ...calendarData,
522
+ firstDayOfWeek,
523
+ selected: selected })) }));
320
524
  };
321
525
 
322
526
  const getRangeDates = ({ selectable, date, selectedDates, }) => {
@@ -552,7 +756,7 @@ const MenuTrigger = react.Menu.Trigger;
552
756
 
553
757
  const PageSizeControl = ({ pageSizes = [10, 20, 30, 40, 50], }) => {
554
758
  const { table } = useDataTableContext();
555
- return (jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { variant: "ghost", gap: "0.5rem", children: [table.getState().pagination.pageSize, " ", jsxRuntime.jsx(bi.BiDownArrow, {})] }) }), jsxRuntime.jsx(MenuContent, { children: pageSizes.map((pageSize) => (jsxRuntime.jsx(MenuItem, { value: `chakra-table-pageSize-${pageSize}`, onClick: () => {
759
+ return (jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Button, { variant: 'ghost', gap: '0.5rem', children: table.getState().pagination.pageSize }) }), jsxRuntime.jsx(MenuContent, { children: pageSizes.map((pageSize) => (jsxRuntime.jsx(MenuItem, { value: `chakra-table-pageSize-${pageSize}`, onClick: () => {
556
760
  table.setPageSize(Number(pageSize));
557
761
  }, children: pageSize }, `chakra-table-pageSize-${pageSize}`))) })] }));
558
762
  };
@@ -580,81 +784,149 @@ const PaginationRoot = React__namespace.forwardRef(function PaginationRoot(props
580
784
  }
581
785
  const container = containerRef.current;
582
786
  let rafId = null;
583
- const calculateSiblingCount = () => {
584
- if (!container)
585
- return;
586
- const width = container.offsetWidth;
587
- if (width === 0)
588
- return;
589
- // Estimate button width based on size
590
- // These are approximate widths including padding for different button sizes
787
+ let timeoutId = null;
788
+ const measureButtonWidth = () => {
789
+ // Try to measure actual rendered buttons for accuracy
790
+ // Look for page number buttons (they contain numeric text)
791
+ const allButtons = container.querySelectorAll('button');
792
+ const pageButtons = [];
793
+ allButtons.forEach((button) => {
794
+ const text = button.textContent?.trim();
795
+ // Page buttons contain numbers, prev/next buttons contain icons
796
+ if (text && /^\d+$/.test(text)) {
797
+ pageButtons.push(button);
798
+ }
799
+ });
800
+ if (pageButtons.length > 0) {
801
+ // Measure multiple buttons and take the average for accuracy
802
+ let totalWidth = 0;
803
+ let count = 0;
804
+ pageButtons.forEach((button) => {
805
+ const width = button.offsetWidth;
806
+ if (width > 0) {
807
+ totalWidth += width;
808
+ count++;
809
+ }
810
+ });
811
+ if (count > 0) {
812
+ return Math.ceil(totalWidth / count);
813
+ }
814
+ }
815
+ // Fallback to estimated widths based on size
591
816
  const buttonWidthMap = {
592
817
  xs: 28,
593
818
  sm: 36,
594
819
  md: 40,
595
820
  lg: 44,
596
821
  };
597
- let buttonWidth = buttonWidthMap[size] || 36;
598
- // Try to measure actual button if available (for more accuracy)
599
- const buttons = container.querySelectorAll('button');
600
- if (buttons.length > 0) {
601
- const firstButton = buttons[0];
602
- if (firstButton.offsetWidth > 0) {
603
- // Use measured width, but account for text content variation
604
- const measuredWidth = firstButton.offsetWidth;
605
- // Page number buttons might be slightly wider due to text, use measured width
606
- buttonWidth = Math.max(buttonWidth, measuredWidth);
822
+ return buttonWidthMap[size] || 36;
823
+ };
824
+ const measurePrevNextWidth = () => {
825
+ const allButtons = container.querySelectorAll('button');
826
+ let prevWidth = 0;
827
+ let nextWidth = 0;
828
+ allButtons.forEach((button) => {
829
+ const html = button.innerHTML;
830
+ // Check if it's a prev/next button by looking for chevron icons or SVG
831
+ if (html.includes('chevron') ||
832
+ html.includes('Chevron') ||
833
+ button.querySelector('svg')) {
834
+ const width = button.offsetWidth;
835
+ if (width > 0) {
836
+ // First icon button is likely prev, last is next
837
+ if (prevWidth === 0) {
838
+ prevWidth = width;
839
+ }
840
+ else {
841
+ nextWidth = width;
842
+ }
843
+ }
607
844
  }
845
+ });
846
+ if (prevWidth > 0 && nextWidth > 0) {
847
+ return prevWidth + nextWidth;
608
848
  }
609
- // Account for prev/next buttons and gaps
610
- // HStack gap is typically 8px in Chakra UI
611
- const gap = 8;
612
- const prevNextWidth = buttonWidth * 2 + gap;
613
- const availableWidth = Math.max(0, width - prevNextWidth);
849
+ // Fallback: use page button width estimate
850
+ return measureButtonWidth() * 2;
851
+ };
852
+ const calculateSiblingCount = () => {
853
+ if (!container)
854
+ return;
855
+ const width = container.offsetWidth;
856
+ if (width === 0)
857
+ return;
858
+ // Measure actual button widths
859
+ const pageButtonWidth = measureButtonWidth();
860
+ const prevNextWidth = measurePrevNextWidth();
861
+ // Get computed gap from container (HStack gap)
862
+ const containerStyles = window.getComputedStyle(container);
863
+ const gap = parseFloat(containerStyles.gap) || 8;
864
+ // Account for gaps: prev button + gap + page buttons + gap + next button
865
+ // We need at least 2 gaps (before and after page buttons)
866
+ const availableWidth = Math.max(0, width - prevNextWidth - gap * 2);
614
867
  // Each page button takes buttonWidth + gap
615
- const buttonWithGap = buttonWidth + gap;
616
- const maxButtons = Math.floor(availableWidth / buttonWithGap);
617
- // Calculate sibling count
618
- // Minimum structure: [prev] [1] [current] [last] [next] = 5 buttons
619
- // With siblings: [prev] [1] [...] [current-N] ... [current] ... [current+N] [...] [last] [next]
620
- // We need: prev(1) + first(1) + ellipsis(1) + siblings*2 + current(1) + ellipsis(1) + last(1) + next(1)
621
- // Minimum: 5 buttons (prev, first, current, last, next)
622
- // With siblings: 5 + siblings*2 + ellipsis*2 (if needed)
623
- const minRequired = 5;
624
- const extraButtons = Math.max(0, maxButtons - minRequired);
625
- // Calculate sibling count
626
- // If we have enough space for ellipsis (2 buttons), account for that
868
+ const buttonWithGap = pageButtonWidth + gap;
869
+ const maxPageButtons = Math.floor(availableWidth / buttonWithGap);
870
+ // Calculate sibling count based on pagination structure
871
+ // Structure: [prev] [first] [ellipsis?] [siblings] [current] [siblings] [ellipsis?] [last] [next]
872
+ // Minimum: prev(1) + first(1) + current(1) + last(1) + next(1) = 5 buttons
873
+ // With siblings and ellipsis: 5 + siblings*2 + ellipsis*2
874
+ const minRequired = 5; // prev, first, current, last, next
875
+ const extraButtons = Math.max(0, maxPageButtons - minRequired);
627
876
  let calculated = minSiblingCount;
628
877
  if (extraButtons >= 4) {
629
- // Space for ellipsis (2) + siblings
878
+ // Enough space for ellipsis (2 buttons) + siblings on both sides
879
+ // Structure: [prev] [1] [...] [siblings] [current] [siblings] [...] [last] [next]
880
+ // Extra buttons = ellipsis(2) + siblings*2
630
881
  calculated = Math.floor((extraButtons - 2) / 2);
631
882
  }
632
883
  else if (extraButtons >= 2) {
633
884
  // Space for some siblings but not ellipsis
885
+ // Structure: [prev] [1] [siblings] [current] [siblings] [last] [next]
634
886
  calculated = Math.floor(extraButtons / 2);
635
887
  }
636
888
  // Apply max limit if provided
637
889
  if (maxSiblingCount !== undefined) {
638
890
  calculated = Math.min(calculated, maxSiblingCount);
639
891
  }
640
- setCalculatedSiblingCount(Math.max(minSiblingCount, calculated));
892
+ const finalSiblingCount = Math.max(minSiblingCount, calculated);
893
+ // Only update if value changed to avoid unnecessary re-renders
894
+ setCalculatedSiblingCount((prev) => {
895
+ if (prev !== finalSiblingCount) {
896
+ return finalSiblingCount;
897
+ }
898
+ return prev;
899
+ });
641
900
  };
642
- const resizeObserver = new ResizeObserver(() => {
643
- // Use requestAnimationFrame to debounce and ensure DOM is updated
901
+ const scheduleCalculation = () => {
902
+ // Cancel any pending calculations
644
903
  if (rafId !== null) {
645
904
  cancelAnimationFrame(rafId);
646
905
  }
647
- rafId = requestAnimationFrame(calculateSiblingCount);
648
- });
906
+ if (timeoutId !== null) {
907
+ clearTimeout(timeoutId);
908
+ }
909
+ // Use requestAnimationFrame for smooth updates
910
+ rafId = requestAnimationFrame(() => {
911
+ // Small delay to ensure DOM is fully rendered
912
+ timeoutId = setTimeout(calculateSiblingCount, 50);
913
+ });
914
+ };
915
+ const resizeObserver = new ResizeObserver(scheduleCalculation);
649
916
  resizeObserver.observe(container);
650
- // Initial calculation after a short delay to ensure buttons are rendered
651
- const timeoutId = setTimeout(calculateSiblingCount, 100);
917
+ // Initial calculation - try multiple times to ensure buttons are rendered
918
+ scheduleCalculation();
919
+ // Also try after a longer delay as fallback
920
+ const fallbackTimeout = setTimeout(calculateSiblingCount, 200);
652
921
  return () => {
653
922
  resizeObserver.disconnect();
654
923
  if (rafId !== null) {
655
924
  cancelAnimationFrame(rafId);
656
925
  }
657
- clearTimeout(timeoutId);
926
+ if (timeoutId !== null) {
927
+ clearTimeout(timeoutId);
928
+ }
929
+ clearTimeout(fallbackTimeout);
658
930
  };
659
931
  }, [size, siblingCount, minSiblingCount, maxSiblingCount]);
660
932
  const mergedRef = React__namespace.useCallback((node) => {
@@ -834,12 +1106,19 @@ const ResetSelectionButton = () => {
834
1106
  const RowCountText = () => {
835
1107
  const { table, type } = useDataTableContext();
836
1108
  const getCount = () => {
837
- if (type === "client") {
1109
+ if (type === 'client') {
838
1110
  return table.getFilteredRowModel().flatRows.length ?? 0;
839
1111
  }
840
1112
  return table.getRowCount();
841
1113
  };
842
- return jsxRuntime.jsx(react.Text, { children: getCount() });
1114
+ const totalCount = getCount();
1115
+ const { pageIndex, pageSize } = table.getState().pagination;
1116
+ if (totalCount === 0) {
1117
+ return jsxRuntime.jsx(react.Text, { children: "0 of 0" });
1118
+ }
1119
+ const start = pageIndex * pageSize + 1;
1120
+ const end = Math.min((pageIndex + 1) * pageSize, totalCount);
1121
+ return jsxRuntime.jsx(react.Text, { children: `${start}-${end} / ${totalCount}` });
843
1122
  };
844
1123
 
845
1124
  // pulling this into a separate file so adapter(s) that don't
@@ -2948,17 +3227,17 @@ const TableFilterTags = () => {
2948
3227
 
2949
3228
  const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
2950
3229
  const { tableLabel, table } = useDataTableContext();
2951
- const { rowCountText, hasErrorText } = tableLabel;
2952
- return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsxRuntime.jsx(react.Spinner, { size: "sm" }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
3230
+ const { hasErrorText } = tableLabel;
3231
+ return (jsxRuntime.jsxs(react.Grid, { templateRows: 'auto 1fr', width: fitTableWidth ? 'fit-content' : '100%', height: fitTableHeight ? 'fit-content' : '100%', gap: '0.5rem', p: 1, ...gridProps, children: [jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: 'space-between', children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: '0.5rem', alignItems: 'center', justifySelf: 'end', children: [loading && jsxRuntime.jsx(react.Spinner, { size: 'sm' }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: 'red.400' }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: '0.5rem', children: filterTagsOptions.map((option) => {
2953
3232
  const { column, options } = option;
2954
3233
  const tableColumn = table.getColumn(column);
2955
- return (jsxRuntime.jsxs(react.Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
3234
+ return (jsxRuntime.jsxs(react.Flex, { alignItems: 'center', flexFlow: 'wrap', gap: '0.5rem', children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
2956
3235
  if (tags.length === 0) {
2957
3236
  return tableColumn?.setFilterValue(undefined);
2958
3237
  }
2959
3238
  tableColumn?.setFilterValue(tags);
2960
3239
  } })] }, column));
2961
- }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsxs(react.Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && (jsxRuntime.jsxs(react.Flex, { children: [jsxRuntime.jsx(react.Text, { paddingRight: "0.5rem", children: rowCountText }), jsxRuntime.jsx(RowCountText, {})] }))] }), jsxRuntime.jsx(react.Box, { justifySelf: "end", children: showPagination && jsxRuntime.jsx(Pagination, {}) })] }))] }));
3240
+ }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Flex, { justifyContent: 'space-between', children: [jsxRuntime.jsxs(react.Flex, { gap: '1rem', alignItems: 'center', children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && jsxRuntime.jsx(RowCountText, {})] }), jsxRuntime.jsx(react.Box, { justifySelf: 'end', children: showPagination && jsxRuntime.jsx(Pagination, {}) })] }))] }));
2962
3241
  };
2963
3242
 
2964
3243
  const EmptyState$1 = React__namespace.forwardRef(function EmptyState(props, ref) {
@@ -3120,7 +3399,7 @@ const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showL
3120
3399
  if (!showLoading && table.getRowModel().rows.length <= 0) {
3121
3400
  return emptyComponent;
3122
3401
  }
3123
- return (jsxRuntime.jsx(react.Box, { ref: containerRef, width: "100%", overflow: "auto", children: jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: 'outline', width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...props, children: children }) }));
3402
+ return (jsxRuntime.jsx(react.Box, { ref: containerRef, width: "100%", overflow: "auto", children: jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', ...props, children: children }) }));
3124
3403
  };
3125
3404
 
3126
3405
  const Checkbox = React__namespace.forwardRef(function Checkbox(props, ref) {
@@ -3166,11 +3445,7 @@ const TableBody = ({ showSelector = false, canResize = true, }) => {
3166
3445
  // styling resize and pinning start
3167
3446
  flex: `${canResize ? '0' : '1'} 0 ${cell.column.getSize()}px`,
3168
3447
  // this is to avoid the cell from being too wide
3169
- minWidth: `0`, color: {
3170
- base: 'colorPalette.900',
3171
- _dark: 'colorPalette.100',
3172
- },
3173
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...getTdProps(cell), children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3448
+ minWidth: `0`, ...getTdProps(cell), children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3174
3449
  })] }, `chakra-table-row-${row.id}`));
3175
3450
  }) }));
3176
3451
  };
@@ -3180,11 +3455,7 @@ const TableRowSelector = ({ row }) => {
3180
3455
  const isSelected = isRowSelected(row.id, rowSelection);
3181
3456
  const canSelect = canRowSelect(row);
3182
3457
  const toggleHandler = createRowToggleHandler(row, rowSelection, setRowSelection);
3183
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
3184
- base: 'colorPalette.900',
3185
- _dark: 'colorPalette.100',
3186
- },
3187
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: isSelected,
3458
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: isSelected,
3188
3459
  disabled: !canSelect,
3189
3460
  onCheckedChange: toggleHandler }) }));
3190
3461
  };
@@ -3301,18 +3572,6 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3301
3572
  const columnMeta = header.column.columnDef.meta;
3302
3573
  return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3303
3574
  };
3304
- const getThProps = (header) => {
3305
- const thProps = header.column.getIsPinned()
3306
- ? {
3307
- left: showSelector
3308
- ? `${header.getStart('left') + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3309
- : `${header.getStart('left')}px`,
3310
- position: 'sticky',
3311
- zIndex: 100 + 1,
3312
- }
3313
- : {};
3314
- return thProps;
3315
- };
3316
3575
  const stickyProps = {
3317
3576
  position: 'sticky',
3318
3577
  top: 0,
@@ -3364,11 +3623,7 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3364
3623
  [header.id]: finalWidth,
3365
3624
  }));
3366
3625
  };
3367
- return (jsxRuntime.jsx(react.Table.Header, { ...(isSticky ? stickyProps : {}), bgColor: 'transparent', ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', bgColor: 'transparent', ...tableRowProps, children: [showSelector && (jsxRuntime.jsx(react.Table.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
3368
- base: 'colorPalette.900',
3369
- _dark: 'colorPalette.100',
3370
- },
3371
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
3626
+ return (jsxRuntime.jsx(react.Table.Header, { ...(isSticky ? stickyProps : {}), ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', ...tableRowProps, children: [showSelector && (jsxRuntime.jsx(react.Table.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: 'grid', justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
3372
3627
  // indeterminate: areSomeRowsSelected(table, rowSelection),
3373
3628
  onChange: createToggleAllRowsHandler(table, rowSelection, setRowSelection) }) })), headerGroup.headers.map((header) => {
3374
3629
  const resizeProps = {
@@ -3378,30 +3633,11 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3378
3633
  };
3379
3634
  return (jsxRuntime.jsxs(react.Table.ColumnHeader, { padding: 0, columnSpan: `${header.colSpan}`,
3380
3635
  // styling resize and pinning start
3381
- flex: `${canResize ? '0' : '1'} 0 ${header.column.getSize()}px`, display: 'grid', gridTemplateColumns: '1fr auto', zIndex: 1500 + header.index, color: {
3382
- base: 'colorPalette.800',
3383
- _dark: 'colorPalette.200',
3384
- },
3385
- bg: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, ...getThProps(header), children: [jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Flex, { padding: `${table.getDensityValue()}px`, alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', overflow: 'auto', color: {
3386
- base: 'colorPalette.800',
3387
- _dark: 'colorPalette.200',
3388
- _hover: {
3389
- base: 'colorPalette.700',
3390
- _dark: 'colorPalette.300',
3391
- },
3392
- },
3393
- bg: {
3394
- base: 'colorPalette.100',
3395
- _dark: 'colorPalette.900',
3396
- _hover: {
3397
- base: 'colorPalette.200',
3398
- _dark: 'colorPalette.800',
3399
- },
3400
- }, children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
3636
+ flex: `${canResize ? '0' : '1'} 0 ${header.column.getSize()}px`, display: 'grid', gridTemplateColumns: '1fr auto', zIndex: 1500 + header.index, children: [jsxRuntime.jsxs(MenuRoot, { children: [jsxRuntime.jsx(MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Flex, { padding: `${table.getDensityValue()}px`, alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', overflow: 'auto', children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
3401
3637
  ? null
3402
3638
  : reactTable.flexRender(header.column.columnDef.header, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && jsxRuntime.jsx(jsxRuntime.Fragment, {}), header.column.getIsSorted() === 'asc' && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === 'desc' && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) }), jsxRuntime.jsx(react.Box, { children: header.column.getIsFiltered() && jsxRuntime.jsx(md.MdFilterListAlt, {}) })] }) }) }), jsxRuntime.jsxs(MenuContent, { children: [!header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "pin-column", children: jsxRuntime.jsxs(Button, { variant: 'ghost', onClick: () => {
3403
3639
  header.column.pin('left');
3404
- }, children: [jsxRuntime.jsx(md.MdPushPin, {}), getHeaderText(header, 'pinColumn')] }) })), header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxRuntime.jsxs(Button, { variant: 'ghost', onClick: () => {
3640
+ }, p: 1, children: [jsxRuntime.jsx(md.MdPushPin, {}), getHeaderText(header, 'pinColumn')] }) })), header.column.getIsPinned() && (jsxRuntime.jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxRuntime.jsxs(Button, { variant: 'ghost', onClick: () => {
3405
3641
  header.column.pin(false);
3406
3642
  }, children: [jsxRuntime.jsx(md.MdCancel, {}), getHeaderText(header, 'cancelPin')] }) })), header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxRuntime.jsxs(Button, { variant: 'ghost', onClick: () => {
3407
3643
  table.setSorting((state) => {
@@ -3601,7 +3837,7 @@ const ErrorAlert = ({ showMessage = true }) => {
3601
3837
  const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: defaultPagination = {
3602
3838
  pageIndex: 0, //initial page index
3603
3839
  pageSize: 10, //default page size
3604
- }, rowSelection: defaultRowSelection = {}, columnFilters: defaultColumnFilters = [], columnOrder: defaultColumnOrder = [], columnVisibility: defaultColumnVisibility = {}, globalFilter: defaultGlobalFilter = "", density: defaultDensity = "sm", } = {
3840
+ }, rowSelection: defaultRowSelection = {}, columnFilters: defaultColumnFilters = [], columnOrder: defaultColumnOrder = [], columnVisibility: defaultColumnVisibility = {}, globalFilter: defaultGlobalFilter = '', density: defaultDensity = 'sm', } = {
3605
3841
  sorting: [],
3606
3842
  pagination: {
3607
3843
  pageIndex: 0, //initial page index
@@ -3611,9 +3847,9 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3611
3847
  columnFilters: [],
3612
3848
  columnOrder: [],
3613
3849
  columnVisibility: {},
3614
- globalFilter: "",
3615
- density: "sm",
3616
- }, keyPrefix = "", } = {
3850
+ globalFilter: '',
3851
+ density: 'sm',
3852
+ }, } = {
3617
3853
  default: {
3618
3854
  sorting: [],
3619
3855
  pagination: {
@@ -3624,8 +3860,8 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3624
3860
  columnFilters: [],
3625
3861
  columnOrder: [],
3626
3862
  columnVisibility: {},
3627
- globalFilter: "",
3628
- density: "sm",
3863
+ globalFilter: '',
3864
+ density: 'sm',
3629
3865
  },
3630
3866
  }) => {
3631
3867
  const [sorting, setSorting] = React.useState(defaultSorting);
@@ -3636,7 +3872,6 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3636
3872
  const [globalFilter, setGlobalFilter] = React.useState(defaultGlobalFilter);
3637
3873
  const [density, setDensity] = React.useState(defaultDensity);
3638
3874
  const [columnVisibility, setColumnVisibility] = React.useState(defaultColumnVisibility);
3639
- const translate = reactI18next.useTranslation("", { keyPrefix });
3640
3875
  return {
3641
3876
  sorting,
3642
3877
  setSorting,
@@ -3654,12 +3889,11 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3654
3889
  setDensity,
3655
3890
  columnVisibility,
3656
3891
  setColumnVisibility,
3657
- translate,
3658
3892
  };
3659
3893
  };
3660
3894
 
3661
3895
  const useDataTableServer = (props) => {
3662
- const { url, default: defaultProps, keyPrefix, placeholderData, queryFn: customQueryFn, } = props;
3896
+ const { url, default: defaultProps, placeholderData, queryFn: customQueryFn, } = props;
3663
3897
  const { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, } = defaultProps || {};
3664
3898
  const [sorting, setSorting] = React.useState(defaultSorting || []);
3665
3899
  const [columnFilters, setColumnFilters] = React.useState(defaultColumnFilters || []); // can set initial column filter state here
@@ -3669,8 +3903,8 @@ const useDataTableServer = (props) => {
3669
3903
  });
3670
3904
  const [rowSelection, setRowSelection] = React.useState(defaultRowSelection || {});
3671
3905
  const [columnOrder, setColumnOrder] = React.useState(defaultColumnOrder || []);
3672
- const [globalFilter, setGlobalFilter] = React.useState(defaultGlobalFilter || "");
3673
- const [density, setDensity] = React.useState(defaultDensity || "sm");
3906
+ const [globalFilter, setGlobalFilter] = React.useState(defaultGlobalFilter || '');
3907
+ const [density, setDensity] = React.useState(defaultDensity || 'sm');
3674
3908
  const [columnVisibility, setColumnVisibility] = React.useState(defaultColumnVisibility || {});
3675
3909
  const { pageSize, pageIndex } = pagination;
3676
3910
  const params = {
@@ -3682,7 +3916,7 @@ const useDataTableServer = (props) => {
3682
3916
  };
3683
3917
  const defaultQueryFn = async () => {
3684
3918
  if (!url) {
3685
- throw new Error("url is required");
3919
+ throw new Error('url is required');
3686
3920
  }
3687
3921
  const response = await axios.get(url, {
3688
3922
  params,
@@ -3696,7 +3930,6 @@ const useDataTableServer = (props) => {
3696
3930
  : defaultQueryFn,
3697
3931
  placeholderData,
3698
3932
  });
3699
- const translate = reactI18next.useTranslation("", { keyPrefix });
3700
3933
  return {
3701
3934
  sorting,
3702
3935
  setSorting,
@@ -3715,7 +3948,6 @@ const useDataTableServer = (props) => {
3715
3948
  columnVisibility,
3716
3949
  setColumnVisibility,
3717
3950
  query,
3718
- translate,
3719
3951
  };
3720
3952
  };
3721
3953
 
@@ -3734,11 +3966,8 @@ const snakeToLabel = (str) => {
3734
3966
  .join(" "); // Join with space
3735
3967
  };
3736
3968
 
3737
- const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3969
+ const RecordDisplay = ({ object, boxProps, prefix = '', }) => {
3738
3970
  const getColumn = ({ field }) => {
3739
- if (translate !== undefined) {
3740
- return translate.t(`${prefix}${field}`);
3741
- }
3742
3971
  return snakeToLabel(field);
3743
3972
  };
3744
3973
  if (object === null) {
@@ -3746,7 +3975,7 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3746
3975
  }
3747
3976
  return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow: 'auto', ...boxProps, children: Object.entries(object).map(([field, value], index) => {
3748
3977
  const uniqueKey = `${prefix}${field}-${index}`;
3749
- return (jsxRuntime.jsxs(react.Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsxRuntime.jsx(react.Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsxRuntime.jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsxRuntime.jsx(react.Text, { children: JSON.stringify(value) }))] }, uniqueKey));
3978
+ return (jsxRuntime.jsxs(react.Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsxRuntime.jsx(react.Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsxRuntime.jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.` })) : (jsxRuntime.jsx(react.Text, { children: JSON.stringify(value) }))] }, uniqueKey));
3750
3979
  }) }));
3751
3980
  };
3752
3981
 
@@ -3760,15 +3989,12 @@ const widthSanityCheck = (widthList, ignoreList, properties) => {
3760
3989
  throw new Error(`The width list is too long given from the number of remaining properties after ignore some.`);
3761
3990
  }
3762
3991
  };
3763
- const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, translate, }) => {
3992
+ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, }) => {
3764
3993
  const { properties } = schema;
3765
- idListSanityCheck("ignore", ignore, properties);
3994
+ idListSanityCheck('ignore', ignore, properties);
3766
3995
  widthSanityCheck(width, ignore, properties);
3767
- idListSanityCheck("meta", Object.keys(meta), properties);
3996
+ idListSanityCheck('meta', Object.keys(meta), properties);
3768
3997
  const getColumn = ({ column }) => {
3769
- if (translate !== undefined) {
3770
- return translate.t(`${column}`);
3771
- }
3772
3998
  return snakeToLabel(column);
3773
3999
  };
3774
4000
  const keys = Object.keys(properties);
@@ -3777,15 +4003,15 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3777
4003
  return !ignore.some((shouldIgnoreKey) => key === shouldIgnoreKey);
3778
4004
  });
3779
4005
  const columnHelper = reactTable.createColumnHelper();
3780
- // @ts-expect-error find type for unknown
3781
4006
  const columns = [
3782
4007
  ...ignored.map((column, index) => {
4008
+ // @ts-expect-error column accessor type issue with generic TData
3783
4009
  return columnHelper.accessor(column, {
3784
4010
  cell: (props) => {
3785
4011
  // @ts-expect-error find type for unknown
3786
4012
  const value = props.row.original[column];
3787
- if (typeof value === "object") {
3788
- return (jsxRuntime.jsx(react.Grid, { overflow: "auto", children: jsxRuntime.jsx(RecordDisplay, { object: value, translate }) }));
4013
+ if (typeof value === 'object') {
4014
+ return (jsxRuntime.jsx(react.Grid, { overflow: 'auto', children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
3789
4015
  }
3790
4016
  return jsxRuntime.jsx(TextCell, { children: value });
3791
4017
  },
@@ -3817,6 +4043,11 @@ const SchemaFormContext = React.createContext({
3817
4043
  include: [],
3818
4044
  onSubmit: async () => { },
3819
4045
  rowNumber: 0,
4046
+ /** Default translate fallback - returns key as-is */
4047
+ translate: {
4048
+ t: (key) => key,
4049
+ ready: true,
4050
+ },
3820
4051
  requestOptions: {},
3821
4052
  timezone: 'Asia/Hong_Kong',
3822
4053
  displayConfig: {
@@ -4049,7 +4280,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4049
4280
  showSubmitButton: true,
4050
4281
  showResetButton: true,
4051
4282
  showTitle: true,
4052
- }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, insideDialog = false, }) => {
4283
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog = false, }) => {
4053
4284
  const [isSuccess, setIsSuccess] = React.useState(false);
4054
4285
  const [isError, setIsError] = React.useState(false);
4055
4286
  const [isSubmiting, setIsSubmiting] = React.useState(false);
@@ -4140,6 +4371,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4140
4371
  enumPickerLabels,
4141
4372
  filePickerLabels,
4142
4373
  formButtonLabels,
4374
+ timePickerLabels,
4143
4375
  ajvResolver: ajvResolver(schema),
4144
4376
  insideDialog,
4145
4377
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
@@ -4150,31 +4382,33 @@ function removeIndex(str) {
4150
4382
  }
4151
4383
 
4152
4384
  /**
4153
- * Custom hook to simplify i18n translation for form fields.
4385
+ * Custom hook for form field labels and fallback text.
4154
4386
  * Automatically handles colLabel construction and removeIndex logic.
4387
+ * Uses schema.title when available, otherwise falls back to translate function.
4155
4388
  *
4156
4389
  * @param column - The column name
4157
4390
  * @param prefix - The prefix for the field (usually empty string or parent path)
4158
- * @returns Object with translation helper functions
4391
+ * @param schema - Optional schema object with title property
4392
+ * @returns Object with label helper functions
4159
4393
  *
4160
4394
  * @example
4161
4395
  * ```tsx
4162
- * const formI18n = useFormI18n(column, prefix);
4396
+ * const formI18n = useFormI18n(column, prefix, schema);
4163
4397
  *
4164
- * // Get field label
4398
+ * // Get field label (prefers schema.title)
4165
4399
  * <Field label={formI18n.label()} />
4166
4400
  *
4167
- * // Get error message
4401
+ * // Get required error message
4168
4402
  * <Text>{formI18n.required()}</Text>
4169
4403
  *
4170
- * // Get custom translation key
4404
+ * // Get custom text
4171
4405
  * <Text>{formI18n.t('add_more')}</Text>
4172
4406
  *
4173
4407
  * // Access the raw colLabel
4174
4408
  * const colLabel = formI18n.colLabel;
4175
4409
  * ```
4176
4410
  */
4177
- const useFormI18n$1 = (column, prefix = '', schema) => {
4411
+ const useFormI18n = (column, prefix = '', schema) => {
4178
4412
  const { translate } = useSchemaContext();
4179
4413
  const colLabel = `${prefix}${column}`;
4180
4414
  return {
@@ -4183,7 +4417,7 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4183
4417
  */
4184
4418
  colLabel,
4185
4419
  /**
4186
- * Get the field label from schema title prop, or fall back to translation
4420
+ * Get the field label from schema title prop, or fall back to translate function
4187
4421
  * Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
4188
4422
  */
4189
4423
  label: (options) => {
@@ -4193,18 +4427,18 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4193
4427
  return translate.t(removeIndex(`${colLabel}.field_label`), options);
4194
4428
  },
4195
4429
  /**
4196
- * Get the required error message translation
4430
+ * Get the required error message
4197
4431
  * Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
4198
4432
  */
4199
4433
  required: (options) => {
4200
4434
  return translate.t(removeIndex(`${colLabel}.field_required`), options);
4201
4435
  },
4202
4436
  /**
4203
- * Get a translation for any custom key relative to the field
4437
+ * Get text for any custom key relative to the field
4204
4438
  * Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
4205
4439
  *
4206
- * @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
4207
- * @param options - Optional translation options (e.g., defaultValue, interpolation variables)
4440
+ * @param key - The key suffix (e.g., 'add_more', 'total', etc.)
4441
+ * @param options - Optional options (e.g., defaultValue, interpolation variables)
4208
4442
  */
4209
4443
  t: (key, options) => {
4210
4444
  return translate.t(removeIndex(`${colLabel}.${key}`), options);
@@ -4222,8 +4456,9 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4222
4456
  const { type } = items;
4223
4457
  const colLabel = `${prefix}${column}`;
4224
4458
  const isRequired = required?.some((columnId) => columnId === column);
4225
- const formI18n = useFormI18n$1(column, prefix, schema);
4459
+ const formI18n = useFormI18n(column, prefix, schema);
4226
4460
  const { formState: { errors }, setValue, watch, } = reactHookForm.useFormContext();
4461
+ const { formButtonLabels } = useSchemaContext();
4227
4462
  const fields = (watch(colLabel) ?? []);
4228
4463
  return (jsxRuntime.jsxs(react.Flex, { gridRow, gridColumn, flexFlow: 'column', gap: 2, children: [jsxRuntime.jsxs(react.Box, { as: "label", children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 2, children: fields.map((field, index) => (jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4229
4464
  base: 'colorPalette.200',
@@ -4249,7 +4484,7 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4249
4484
  return;
4250
4485
  }
4251
4486
  setValue(colLabel, [...fields, {}]);
4252
- }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4487
+ }, children: formButtonLabels?.add ?? 'Add' }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4253
4488
  };
4254
4489
 
4255
4490
  const Field = React__namespace.forwardRef(function Field(props, ref) {
@@ -4263,7 +4498,7 @@ const BooleanPicker = ({ schema, column, prefix }) => {
4263
4498
  const isRequired = required?.some((columnId) => columnId === column);
4264
4499
  const colLabel = `${prefix}${column}`;
4265
4500
  const value = watch(colLabel);
4266
- const formI18n = useFormI18n$1(column, prefix, schema);
4501
+ const formI18n = useFormI18n(column, prefix, schema);
4267
4502
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4268
4503
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
4269
4504
  setValue(colLabel, !value);
@@ -4284,50 +4519,50 @@ const CustomInput = ({ column, schema, prefix }) => {
4284
4519
 
4285
4520
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
4286
4521
  const { labels } = React.useContext(DatePickerContext);
4287
- const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel } = labels;
4522
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
4288
4523
  if (calendars.length) {
4289
- return (jsxRuntime.jsxs(react.Grid, { children: [jsxRuntime.jsxs(react.Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({
4524
+ return (jsxRuntime.jsxs(react.Grid, { children: [jsxRuntime.jsxs(react.Grid, { templateColumns: 'repeat(4, auto)', justifyContent: 'center', children: [jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getBackProps({
4290
4525
  calendars,
4291
4526
  offset: 12,
4292
- }), children: "<<" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({ calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({
4527
+ }), children: '<<' }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getBackProps({ calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getForwardProps({
4293
4528
  calendars,
4294
4529
  offset: 12,
4295
- }), children: ">>" })] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", children: calendars.map((calendar) => (jsxRuntime.jsxs(react.Grid, { gap: 4, children: [jsxRuntime.jsxs(react.Grid, { justifyContent: "center", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxRuntime.jsxs(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
4530
+ }), children: '>>' })] }), jsxRuntime.jsx(react.Grid, { templateColumns: 'repeat(2, auto)', justifyContent: 'center', children: calendars.map((calendar) => (jsxRuntime.jsxs(react.Grid, { gap: 4, children: [jsxRuntime.jsxs(react.Grid, { justifyContent: 'center', children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxRuntime.jsxs(react.Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
4296
4531
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
4297
- return (jsxRuntime.jsx(react.Text, { textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
4532
+ return (jsxRuntime.jsx(react.Text, { textAlign: 'center', children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
4298
4533
  }), calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
4299
4534
  const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
4300
4535
  if (!dateObj) {
4301
4536
  return jsxRuntime.jsx(react.Grid, {}, key);
4302
4537
  }
4303
- const { date, selected, selectable, today } = dateObj;
4538
+ const { date, selected, selectable, today, isCurrentMonth, } = dateObj;
4304
4539
  const getDateColor = ({ today, selected, selectable, }) => {
4305
4540
  if (!selectable) {
4306
- return "gray";
4541
+ return 'gray';
4307
4542
  }
4308
4543
  if (selected) {
4309
- return "blue";
4544
+ return 'blue';
4310
4545
  }
4311
4546
  if (today) {
4312
- return "green";
4547
+ return 'green';
4313
4548
  }
4314
- return "";
4549
+ return '';
4315
4550
  };
4316
4551
  const getVariant = ({ today, selected, selectable, }) => {
4317
4552
  if (!selectable) {
4318
- return "surface";
4553
+ return 'surface';
4319
4554
  }
4320
4555
  if (selected) {
4321
- return "solid";
4556
+ return 'solid';
4322
4557
  }
4323
4558
  if (today) {
4324
- return "surface";
4559
+ return 'surface';
4325
4560
  }
4326
- return "ghost";
4561
+ return 'ghost';
4327
4562
  };
4328
4563
  const color = getDateColor({ today, selected, selectable });
4329
4564
  const variant = getVariant({ today, selected, selectable });
4330
- return (jsxRuntime.jsx(react.Button, { variant: variant, colorPalette: color, ...getDateProps({ dateObj }), children: selectable ? date.getDate() : "X" }, key));
4565
+ return (jsxRuntime.jsx(react.Button, { variant: variant, colorPalette: color, opacity: isCurrentMonth ? 1 : 0.4, ...getDateProps({ dateObj }), children: selectable ? date.getDate() : 'X' }, key));
4331
4566
  }))] })] }, `${calendar.month}${calendar.year}`))) })] }));
4332
4567
  }
4333
4568
  return null;
@@ -4335,50 +4570,55 @@ const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firs
4335
4570
  const DatePickerContext = React.createContext({
4336
4571
  labels: {
4337
4572
  monthNamesShort: [
4338
- "Jan",
4339
- "Feb",
4340
- "Mar",
4341
- "Apr",
4342
- "May",
4343
- "Jun",
4344
- "Jul",
4345
- "Aug",
4346
- "Sep",
4347
- "Oct",
4348
- "Nov",
4349
- "Dec",
4573
+ 'Jan',
4574
+ 'Feb',
4575
+ 'Mar',
4576
+ 'Apr',
4577
+ 'May',
4578
+ 'Jun',
4579
+ 'Jul',
4580
+ 'Aug',
4581
+ 'Sep',
4582
+ 'Oct',
4583
+ 'Nov',
4584
+ 'Dec',
4350
4585
  ],
4351
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4352
- backButtonLabel: "Back",
4353
- forwardButtonLabel: "Next",
4586
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4587
+ backButtonLabel: 'Back',
4588
+ forwardButtonLabel: 'Next',
4354
4589
  },
4355
4590
  });
4356
- let DatePicker$1 = class DatePicker extends React.Component {
4357
- render() {
4358
- const { labels = {
4359
- monthNamesShort: [
4360
- "Jan",
4361
- "Feb",
4362
- "Mar",
4363
- "Apr",
4364
- "May",
4365
- "Jun",
4366
- "Jul",
4367
- "Aug",
4368
- "Sep",
4369
- "Oct",
4370
- "Nov",
4371
- "Dec",
4372
- ],
4373
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4374
- backButtonLabel: "Back",
4375
- forwardButtonLabel: "Next",
4376
- }, } = this.props;
4377
- return (jsxRuntime.jsx(DatePickerContext.Provider, { value: { labels }, children: jsxRuntime.jsx(Dayzed, { onDateSelected: this.props.onDateSelected, selected: this.props.selected, firstDayOfWeek: this.props.firstDayOfWeek, showOutsideDays: this.props.showOutsideDays, date: this.props.date, minDate: this.props.minDate, maxDate: this.props.maxDate, monthsToDisplay: this.props.monthsToDisplay, render:
4378
- // @ts-expect-error - Dayzed types need to be fixed
4379
- (dayzedData) => (jsxRuntime.jsx(Calendar, { ...dayzedData,
4380
- firstDayOfWeek: this.props.firstDayOfWeek })) }) }));
4381
- }
4591
+ const DatePicker$1 = ({ labels = {
4592
+ monthNamesShort: [
4593
+ 'Jan',
4594
+ 'Feb',
4595
+ 'Mar',
4596
+ 'Apr',
4597
+ 'May',
4598
+ 'Jun',
4599
+ 'Jul',
4600
+ 'Aug',
4601
+ 'Sep',
4602
+ 'Oct',
4603
+ 'Nov',
4604
+ 'Dec',
4605
+ ],
4606
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4607
+ backButtonLabel: 'Back',
4608
+ forwardButtonLabel: 'Next',
4609
+ }, onDateSelected, selected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, render, }) => {
4610
+ const calendarData = useCalendar({
4611
+ onDateSelected,
4612
+ selected,
4613
+ firstDayOfWeek,
4614
+ showOutsideDays,
4615
+ date,
4616
+ minDate,
4617
+ maxDate,
4618
+ monthsToDisplay,
4619
+ });
4620
+ return (jsxRuntime.jsx(DatePickerContext.Provider, { value: { labels }, children: render ? (render(calendarData)) : (jsxRuntime.jsx(Calendar, { ...calendarData,
4621
+ firstDayOfWeek })) }));
4382
4622
  };
4383
4623
 
4384
4624
  dayjs.extend(utc);
@@ -4386,7 +4626,7 @@ dayjs.extend(timezone);
4386
4626
  const DatePicker = ({ column, schema, prefix }) => {
4387
4627
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4388
4628
  const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
4389
- const formI18n = useFormI18n$1(column, prefix, schema);
4629
+ const formI18n = useFormI18n(column, prefix, schema);
4390
4630
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4391
4631
  const isRequired = required?.some((columnId) => columnId === column);
4392
4632
  const colLabel = formI18n.colLabel;
@@ -4420,74 +4660,30 @@ const DatePicker = ({ column, schema, prefix }) => {
4420
4660
  }, [selectedDate, dateFormat, colLabel, setValue]);
4421
4661
  const datePickerLabels = {
4422
4662
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4423
- formI18n.translate.t(`common.month_1`, {
4424
- defaultValue: 'January',
4425
- }),
4426
- formI18n.translate.t(`common.month_2`, {
4427
- defaultValue: 'February',
4428
- }),
4429
- formI18n.translate.t(`common.month_3`, {
4430
- defaultValue: 'March',
4431
- }),
4432
- formI18n.translate.t(`common.month_4`, {
4433
- defaultValue: 'April',
4434
- }),
4435
- formI18n.translate.t(`common.month_5`, {
4436
- defaultValue: 'May',
4437
- }),
4438
- formI18n.translate.t(`common.month_6`, {
4439
- defaultValue: 'June',
4440
- }),
4441
- formI18n.translate.t(`common.month_7`, {
4442
- defaultValue: 'July',
4443
- }),
4444
- formI18n.translate.t(`common.month_8`, {
4445
- defaultValue: 'August',
4446
- }),
4447
- formI18n.translate.t(`common.month_9`, {
4448
- defaultValue: 'September',
4449
- }),
4450
- formI18n.translate.t(`common.month_10`, {
4451
- defaultValue: 'October',
4452
- }),
4453
- formI18n.translate.t(`common.month_11`, {
4454
- defaultValue: 'November',
4455
- }),
4456
- formI18n.translate.t(`common.month_12`, {
4457
- defaultValue: 'December',
4458
- }),
4663
+ 'January',
4664
+ 'February',
4665
+ 'March',
4666
+ 'April',
4667
+ 'May',
4668
+ 'June',
4669
+ 'July',
4670
+ 'August',
4671
+ 'September',
4672
+ 'October',
4673
+ 'November',
4674
+ 'December',
4459
4675
  ],
4460
4676
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4461
- formI18n.translate.t(`common.weekday_1`, {
4462
- defaultValue: 'Sun',
4463
- }),
4464
- formI18n.translate.t(`common.weekday_2`, {
4465
- defaultValue: 'Mon',
4466
- }),
4467
- formI18n.translate.t(`common.weekday_3`, {
4468
- defaultValue: 'Tue',
4469
- }),
4470
- formI18n.translate.t(`common.weekday_4`, {
4471
- defaultValue: 'Wed',
4472
- }),
4473
- formI18n.translate.t(`common.weekday_5`, {
4474
- defaultValue: 'Thu',
4475
- }),
4476
- formI18n.translate.t(`common.weekday_6`, {
4477
- defaultValue: 'Fri',
4478
- }),
4479
- formI18n.translate.t(`common.weekday_7`, {
4480
- defaultValue: 'Sat',
4481
- }),
4677
+ 'Sun',
4678
+ 'Mon',
4679
+ 'Tue',
4680
+ 'Wed',
4681
+ 'Thu',
4682
+ 'Fri',
4683
+ 'Sat',
4482
4684
  ],
4483
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4484
- formI18n.translate.t(`common.back_button`, {
4485
- defaultValue: 'Back',
4486
- }),
4487
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4488
- formI18n.translate.t(`common.forward_button`, {
4489
- defaultValue: 'Forward',
4490
- }),
4685
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
4686
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
4491
4687
  };
4492
4688
  const datePickerContent = (jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4493
4689
  setValue(colLabel, dayjs(date).format(dateFormat));
@@ -4504,7 +4700,7 @@ dayjs.extend(timezone);
4504
4700
  const DateRangePicker = ({ column, schema, prefix, }) => {
4505
4701
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4506
4702
  const { timezone, insideDialog } = useSchemaContext();
4507
- const formI18n = useFormI18n$1(column, prefix);
4703
+ const formI18n = useFormI18n(column, prefix);
4508
4704
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4509
4705
  const isRequired = required?.some((columnId) => columnId === column);
4510
4706
  const colLabel = formI18n.colLabel;
@@ -4602,7 +4798,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4602
4798
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
4603
4799
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4604
4800
  const { enumPickerLabels, insideDialog } = useSchemaContext();
4605
- const formI18n = useFormI18n$1(column, prefix, schema);
4801
+ const formI18n = useFormI18n(column, prefix, schema);
4606
4802
  const { required, variant } = schema;
4607
4803
  const isRequired = required?.some((columnId) => columnId === column);
4608
4804
  const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
@@ -5149,7 +5345,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
5149
5345
  }) })) }))] }));
5150
5346
  };
5151
5347
 
5152
- function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
5348
+ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, colLabel, }) {
5153
5349
  const [selectedFile, setSelectedFile] = React.useState(undefined);
5154
5350
  const [activeTab, setActiveTab] = React.useState('browse');
5155
5351
  const [uploadingFiles, setUploadingFiles] = React.useState(new Set());
@@ -5218,15 +5414,8 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5218
5414
  const showTabs = enableUpload && !!onUploadFile && !!onFetchFiles;
5219
5415
  if (!onFetchFiles && !onUploadFile)
5220
5416
  return null;
5221
- return (jsxRuntime.jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxRuntime.jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsxRuntime.jsx(DialogCloseTrigger, {})] }), jsxRuntime.jsx(DialogBody, { children: showTabs ? (jsxRuntime.jsxs(react.Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxRuntime.jsxs(react.Tabs.List, { children: [jsxRuntime.jsx(react.Tabs.Trigger, { value: "browse", children: labels?.browseTab ??
5222
- translate(removeIndex(`${colLabel}.browse_tab`)) ??
5223
- 'Browse Library' }), jsxRuntime.jsx(react.Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
5224
- translate(removeIndex(`${colLabel}.upload_tab`)) ??
5225
- 'Upload Files' })] }), jsxRuntime.jsx(react.Tabs.Content, { value: "browse", children: onFetchFiles && (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsxRuntime.jsx(react.Tabs.Content, { value: "upload", children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
5226
- translate(removeIndex(`${colLabel}.fileDropzone`)) ??
5227
- 'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsxRuntime.jsx(react.Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsxRuntime.jsx(react.Box, { py: 2, children: jsxRuntime.jsxs(react.HStack, { gap: 2, children: [jsxRuntime.jsx(react.Spinner, { size: "sm", colorPalette: "blue" }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ??
5228
- translate(removeIndex(`${colLabel}.uploading`)) ??
5229
- 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsxRuntime.jsx(react.Box, { bg: {
5417
+ return (jsxRuntime.jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxRuntime.jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsxRuntime.jsx(DialogCloseTrigger, {})] }), jsxRuntime.jsx(DialogBody, { children: showTabs ? (jsxRuntime.jsxs(react.Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxRuntime.jsxs(react.Tabs.List, { children: [jsxRuntime.jsx(react.Tabs.Trigger, { value: "browse", children: labels?.browseTab ?? 'Browse Library' }), jsxRuntime.jsx(react.Tabs.Trigger, { value: "upload", children: labels?.uploadTab ?? 'Upload Files' })] }), jsxRuntime.jsx(react.Tabs.Content, { value: "browse", children: onFetchFiles && (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsxRuntime.jsx(react.Tabs.Content, { value: "upload", children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
5418
+ 'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsxRuntime.jsx(react.Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsxRuntime.jsx(react.Box, { py: 2, children: jsxRuntime.jsxs(react.HStack, { gap: 2, children: [jsxRuntime.jsx(react.Spinner, { size: "sm", colorPalette: "blue" }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ?? 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsxRuntime.jsx(react.Box, { bg: {
5230
5419
  base: 'colorPalette.50',
5231
5420
  _dark: 'colorPalette.900/20',
5232
5421
  }, border: "1px solid", borderColor: {
@@ -5235,18 +5424,12 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5235
5424
  }, colorPalette: "red", borderRadius: "md", p: 3, children: jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: {
5236
5425
  base: 'colorPalette.600',
5237
5426
  _dark: 'colorPalette.300',
5238
- }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
5239
- translate(removeIndex(`${colLabel}.upload_failed`)) ??
5240
- 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsxs(react.HStack, { gap: 3, justify: "end", children: [jsxRuntime.jsx(react.Button, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
5241
- translate(removeIndex(`${colLabel}.cancel`)) ??
5242
- 'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ??
5243
- translate(removeIndex(`${colLabel}.select`)) ??
5244
- 'Select' })] }) })] }) }));
5427
+ }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ?? 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsxs(react.HStack, { gap: 3, justify: "end", children: [jsxRuntime.jsx(react.Button, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ?? 'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ?? 'Select' })] }) })] }) }));
5245
5428
  }
5246
5429
  const FilePicker = ({ column, schema, prefix }) => {
5247
5430
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
5248
5431
  const { filePickerLabels } = useSchemaContext();
5249
- const formI18n = useFormI18n$1(column, prefix);
5432
+ const formI18n = useFormI18n(column, prefix);
5250
5433
  const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
5251
5434
  const isRequired = required?.some((columnId) => columnId === column);
5252
5435
  const isSingleSelect = type === 'string';
@@ -5322,7 +5505,7 @@ const FilePicker = ({ column, schema, prefix }) => {
5322
5505
  const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5323
5506
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
5324
5507
  const { filePickerLabels } = useSchemaContext();
5325
- const formI18n = useFormI18n$1(column, prefix);
5508
+ const formI18n = useFormI18n(column, prefix);
5326
5509
  const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
5327
5510
  const isRequired = required?.some((columnId) => columnId === column);
5328
5511
  const isSingleSelect = type === 'string';
@@ -5418,8 +5601,8 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5418
5601
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
5419
5602
  formI18n.t('browse_library') ??
5420
5603
  'Browse from Library' }) }), jsxRuntime.jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
5421
- formI18n.t('dialog_title') ??
5422
- 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
5604
+ filePickerLabels?.dialogTitle ??
5605
+ 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, colLabel: colLabel }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
5423
5606
  const file = fileMap.get(fileId);
5424
5607
  const isImage = file
5425
5608
  ? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
@@ -5468,17 +5651,16 @@ const defaultRenderDisplay = (item) => {
5468
5651
  return JSON.stringify(item);
5469
5652
  };
5470
5653
 
5471
- const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5654
+ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5472
5655
  const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5473
5656
  const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5474
- const formI18n = useFormI18n$1(column, prefix, schema);
5475
- const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
5476
- const isRequired = required?.some((columnId) => columnId === column);
5657
+ const { renderDisplay, foreign_key } = schema;
5477
5658
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5478
5659
  const [searchText, setSearchText] = React.useState('');
5479
5660
  const [debouncedSearchText, setDebouncedSearchText] = React.useState('');
5480
5661
  const [limit] = React.useState(50); // Increased limit for combobox
5481
- const colLabel = formI18n.colLabel;
5662
+ // Get colLabel from schema context (we'll compute it here)
5663
+ const colLabel = `${prefix}${column}`;
5482
5664
  const watchedValue = watch(colLabel);
5483
5665
  const watchId = !isMultiple ? watchedValue : undefined;
5484
5666
  const watchIds = isMultiple
@@ -5677,20 +5859,6 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5677
5859
  itemToValue: (item) => item.value,
5678
5860
  filter: contains,
5679
5861
  });
5680
- // Handle input value change (search)
5681
- const handleInputValueChange = (details) => {
5682
- setSearchText(details.inputValue);
5683
- // Filter will be applied after data is fetched
5684
- };
5685
- // Handle value change
5686
- const handleValueChange = (details) => {
5687
- if (isMultiple) {
5688
- setValue(colLabel, details.value);
5689
- }
5690
- else {
5691
- setValue(colLabel, details.value[0] || '');
5692
- }
5693
- };
5694
5862
  // Track previous comboboxItems to avoid unnecessary updates
5695
5863
  const prevComboboxItemsRef = React.useRef('');
5696
5864
  const prevSearchTextRef = React.useRef('');
@@ -5720,8 +5888,106 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5720
5888
  // comboboxItems and searchText are the only dependencies we care about
5721
5889
  // eslint-disable-next-line react-hooks/exhaustive-deps
5722
5890
  }, [comboboxItems, searchText]);
5891
+ return {
5892
+ colLabel,
5893
+ currentValue,
5894
+ searchText,
5895
+ setSearchText,
5896
+ debouncedSearchText,
5897
+ isLoading,
5898
+ isFetching,
5899
+ isPending,
5900
+ isError,
5901
+ isSearching,
5902
+ isLoadingInitialValues,
5903
+ isFetchingInitialValues,
5904
+ missingIds,
5905
+ comboboxItems,
5906
+ collection,
5907
+ filter,
5908
+ set,
5909
+ idMap,
5910
+ idPickerLabels,
5911
+ insideDialog: insideDialog ?? false,
5912
+ renderDisplay,
5913
+ column_ref,
5914
+ errors,
5915
+ setValue,
5916
+ };
5917
+ };
5918
+
5919
+ const IdPickerSingle = ({ column, schema, prefix, }) => {
5920
+ const formI18n = useFormI18n(column, prefix, schema);
5921
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5922
+ const isRequired = required?.some((columnId) => columnId === column);
5923
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5924
+ column,
5925
+ schema,
5926
+ prefix,
5927
+ isMultiple: false,
5928
+ });
5929
+ const handleInputValueChange = (details) => {
5930
+ setSearchText(details.inputValue);
5931
+ };
5932
+ const handleValueChange = (details) => {
5933
+ setValue(colLabel, details.value[0] || '');
5934
+ };
5935
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5723
5936
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5724
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
5937
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { mb: 2, children: (() => {
5938
+ const id = currentValue[0];
5939
+ const item = idMap[id];
5940
+ // Show loading skeleton while fetching initial values
5941
+ if (item === undefined &&
5942
+ (isLoadingInitialValues || isFetchingInitialValues) &&
5943
+ missingIds.includes(id)) {
5944
+ return jsxRuntime.jsx(react.Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
5945
+ }
5946
+ // Only show "not found" if we're not loading and item is still missing
5947
+ if (item === undefined) {
5948
+ return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
5949
+ }
5950
+ return jsxRuntime.jsx(react.Text, { fontSize: "sm", children: renderDisplayFunction(item) });
5951
+ })() })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: false, closeOnSelect: true, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5952
+ ? { strategy: 'fixed', hideWhenDetached: true }
5953
+ : undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, { size: "xs" }), isError && (jsxRuntime.jsx(react.Icon, { color: "fg.error", children: jsxRuntime.jsx(bi.BiError, {}) })), currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
5954
+ setValue(colLabel, '');
5955
+ } })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), insideDialog ? (jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5956
+ // Show skeleton items to prevent UI shift
5957
+ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
5958
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5959
+ : idPickerLabels?.initialResults ??
5960
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
5961
+ ? renderDisplayFunction(item.raw)
5962
+ : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5963
+ // Show skeleton items to prevent UI shift
5964
+ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
5965
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5966
+ : idPickerLabels?.initialResults ??
5967
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
5968
+ ? renderDisplayFunction(item.raw)
5969
+ : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5970
+ };
5971
+
5972
+ const IdPickerMultiple = ({ column, schema, prefix, }) => {
5973
+ const formI18n = useFormI18n(column, prefix, schema);
5974
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5975
+ const isRequired = required?.some((columnId) => columnId === column);
5976
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5977
+ column,
5978
+ schema,
5979
+ prefix,
5980
+ isMultiple: true,
5981
+ });
5982
+ const handleInputValueChange = (details) => {
5983
+ setSearchText(details.inputValue);
5984
+ };
5985
+ const handleValueChange = (details) => {
5986
+ setValue(colLabel, details.value);
5987
+ };
5988
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5989
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5990
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
5725
5991
  const item = idMap[id];
5726
5992
  // Show loading skeleton while fetching initial values
5727
5993
  if (item === undefined &&
@@ -5731,34 +5997,28 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5731
5997
  }
5732
5998
  // Only show "not found" if we're not loading and item is still missing
5733
5999
  if (item === undefined) {
5734
- return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
6000
+ return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }, id));
5735
6001
  }
5736
6002
  return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
5737
6003
  const newValue = currentValue.filter((itemId) => itemId !== id);
5738
6004
  setValue(colLabel, newValue);
5739
- }, children: renderDisplay
5740
- ? renderDisplay(item)
5741
- : defaultRenderDisplay(item) }, id));
5742
- }) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
6005
+ }, children: renderDisplayFunction(item) }, id));
6006
+ }) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: true, closeOnSelect: false, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5743
6007
  ? { strategy: 'fixed', hideWhenDetached: true }
5744
- : undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, { size: "xs" }), isError && (jsxRuntime.jsx(react.Icon, { color: "fg.error", children: jsxRuntime.jsx(bi.BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
5745
- setValue(colLabel, '');
5746
- } })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), insideDialog ? (jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
6008
+ : undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, { size: "xs" }), isError && (jsxRuntime.jsx(react.Icon, { color: "fg.error", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), insideDialog ? (jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5747
6009
  // Show skeleton items to prevent UI shift
5748
6010
  jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
5749
- ? idPickerLabels?.emptySearchResult ??
5750
- formI18n.t('empty_search_result')
6011
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5751
6012
  : idPickerLabels?.initialResults ??
5752
- formI18n.t('initial_results') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplay === true
5753
- ? renderDisplay(item.raw)
5754
- : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
6013
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6014
+ ? renderDisplayFunction(item.raw)
6015
+ : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsx(react.Combobox.Content, { children: isError ? (jsxRuntime.jsx(react.Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5755
6016
  // Show skeleton items to prevent UI shift
5756
6017
  jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsxRuntime.jsx(react.Flex, { p: 2, align: "center", gap: 2, children: jsxRuntime.jsx(react.Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsxRuntime.jsx(react.Combobox.Empty, { children: searchText
5757
- ? idPickerLabels?.emptySearchResult ??
5758
- formI18n.t('empty_search_result')
6018
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5759
6019
  : idPickerLabels?.initialResults ??
5760
- formI18n.t('initial_results') })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplay === true
5761
- ? renderDisplay(item.raw)
6020
+ 'Start typing to search' })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: collection.items.map((item, index) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsx(react.Combobox.ItemText, { children: !!renderDisplayFunction === true
6021
+ ? renderDisplayFunction(item.raw)
5762
6022
  : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5763
6023
  };
5764
6024
 
@@ -5832,7 +6092,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
5832
6092
  const colLabel = `${prefix}${column}`;
5833
6093
  const value = watch(`${colLabel}`);
5834
6094
  const fieldError = getFieldError(errors, colLabel);
5835
- const formI18n = useFormI18n$1(column, prefix, schema);
6095
+ const formI18n = useFormI18n(column, prefix, schema);
5836
6096
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
5837
6097
  ? fieldError.includes('required')
5838
6098
  ? formI18n.required()
@@ -5850,7 +6110,7 @@ const ObjectInput = ({ schema, column, prefix }) => {
5850
6110
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
5851
6111
  const colLabel = `${prefix}${column}`;
5852
6112
  const isRequired = required?.some((columnId) => columnId === column);
5853
- const formI18n = useFormI18n$1(column, prefix, schema);
6113
+ const formI18n = useFormI18n(column, prefix, schema);
5854
6114
  const { formState: { errors }, } = reactHookForm.useFormContext();
5855
6115
  if (properties === undefined) {
5856
6116
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -5870,14 +6130,14 @@ const ObjectInput = ({ schema, column, prefix }) => {
5870
6130
 
5871
6131
  const RecordInput = ({ column, schema, prefix }) => {
5872
6132
  const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
5873
- const { translate } = useSchemaContext();
6133
+ const { formButtonLabels } = useSchemaContext();
5874
6134
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5875
6135
  const isRequired = required?.some((columnId) => columnId === column);
5876
6136
  const entries = Object.entries(getValues(column) ?? {});
5877
6137
  const [showNewEntries, setShowNewEntries] = React.useState(false);
5878
6138
  const [newKey, setNewKey] = React.useState();
5879
6139
  const [newValue, setNewValue] = React.useState();
5880
- const formI18n = useFormI18n$1(column, prefix, schema);
6140
+ const formI18n = useFormI18n(column, prefix, schema);
5881
6141
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`] ? formI18n.required() : undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
5882
6142
  return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
5883
6143
  const filtered = entries.filter(([target]) => {
@@ -5914,11 +6174,11 @@ const RecordInput = ({ column, schema, prefix }) => {
5914
6174
  setShowNewEntries(false);
5915
6175
  setNewKey(undefined);
5916
6176
  setNewValue(undefined);
5917
- }, children: translate.t(`${column}.save`) })] })] }) }), jsxRuntime.jsx(Button, { onClick: () => {
6177
+ }, children: formButtonLabels?.save ?? 'Save' })] })] }) }), jsxRuntime.jsx(Button, { onClick: () => {
5918
6178
  setShowNewEntries(true);
5919
6179
  setNewKey(undefined);
5920
6180
  setNewValue(undefined);
5921
- }, children: translate.t(`${column}.addNew`) })] }));
6181
+ }, children: formButtonLabels?.addNew ?? 'Add New' })] }));
5922
6182
  };
5923
6183
 
5924
6184
  const StringInputField = ({ column, schema, prefix, }) => {
@@ -5927,7 +6187,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
5927
6187
  const isRequired = required?.some((columnId) => columnId === column);
5928
6188
  const colLabel = `${prefix}${column}`;
5929
6189
  const fieldError = getFieldError(errors, colLabel);
5930
- const formI18n = useFormI18n$1(column, prefix, schema);
6190
+ const formI18n = useFormI18n(column, prefix, schema);
5931
6191
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
5932
6192
  };
5933
6193
 
@@ -6119,7 +6379,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6119
6379
  const form = reactHookForm.useFormContext();
6120
6380
  const { setValue, watch } = form;
6121
6381
  const fieldError = getFieldError(errors, colLabel);
6122
- const formI18n = useFormI18n$1(column, prefix, schema);
6382
+ const formI18n = useFormI18n(column, prefix, schema);
6123
6383
  const watchValue = watch(colLabel);
6124
6384
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
6125
6385
  ? fieldError.includes('required')
@@ -6130,18 +6390,13 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6130
6390
 
6131
6391
  dayjs.extend(utc);
6132
6392
  dayjs.extend(timezone);
6133
- function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
6134
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6135
- meridiemLabel: _meridiemLabel = {
6136
- am: 'am',
6137
- pm: 'pm',
6138
- },
6139
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6140
- onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedDate, portalled = true, }) {
6141
- // Generate time options (every 15 minutes)
6393
+ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem, onChange = () => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6394
+ placeholder: 'hh:mm AM/PM',
6395
+ emptyMessage: 'No time found',
6396
+ }, }) => {
6397
+ // Generate time options (every 15 minutes in 12-hour format)
6142
6398
  const timeOptions = React.useMemo(() => {
6143
6399
  const options = [];
6144
- const meridiemOptions = ['am', 'pm'];
6145
6400
  // Get start time for comparison if provided
6146
6401
  let startDateTime = null;
6147
6402
  let shouldFilterByDate = false;
@@ -6156,14 +6411,16 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6156
6411
  selectedDateObj.format('YYYY-MM-DD');
6157
6412
  }
6158
6413
  }
6159
- for (const mer of meridiemOptions) {
6160
- for (let h = 1; h <= 12; h++) {
6161
- for (let m = 0; m < 60; m += 15) {
6162
- const hour24 = mer === 'am' ? (h === 12 ? 0 : h) : h === 12 ? 12 : h + 12;
6163
- // Format time directly without using dayjs with dummy dates
6164
- const formattedHour = h.toString().padStart(2, '0');
6165
- const formattedMinute = m.toString().padStart(2, '0');
6166
- const displayTime = `${formattedHour}:${formattedMinute} ${mer}`;
6414
+ // Generate 12-hour format options (1-12 for hours, AM/PM)
6415
+ for (let h = 1; h <= 12; h++) {
6416
+ for (let m = 0; m < 60; m += 15) {
6417
+ for (const mer of ['am', 'pm']) {
6418
+ // Convert 12-hour to 24-hour for comparison
6419
+ let hour24 = h;
6420
+ if (mer === 'am' && h === 12)
6421
+ hour24 = 0;
6422
+ else if (mer === 'pm' && h < 12)
6423
+ hour24 = h + 12;
6167
6424
  // Filter out times that would result in negative duration (only when dates are the same)
6168
6425
  if (startDateTime && selectedDate && shouldFilterByDate) {
6169
6426
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
@@ -6206,20 +6463,23 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6206
6463
  }
6207
6464
  }
6208
6465
  }
6466
+ const hourDisplay = h.toString();
6467
+ const minuteDisplay = m.toString().padStart(2, '0');
6468
+ const timeDisplay = `${hourDisplay}:${minuteDisplay} ${mer.toUpperCase()}`;
6209
6469
  options.push({
6210
- label: displayTime,
6211
- value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
6470
+ label: timeDisplay,
6471
+ value: `${h}:${m}:${mer}`,
6212
6472
  hour: h,
6213
6473
  minute: m,
6214
6474
  meridiem: mer,
6215
- searchText: displayTime, // Use base time without duration for searching
6475
+ searchText: timeDisplay, // Use base time without duration for searching
6216
6476
  durationText,
6217
6477
  });
6218
6478
  }
6219
6479
  }
6220
6480
  }
6221
6481
  return options;
6222
- }, [timezone, startTime, selectedDate]);
6482
+ }, [startTime, selectedDate, timezone]);
6223
6483
  const { contains } = react.useFilter({ sensitivity: 'base' });
6224
6484
  const { collection, filter } = react.useListCollection({
6225
6485
  initialItems: timeOptions,
@@ -6232,7 +6492,7 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6232
6492
  if (hour === null || minute === null || meridiem === null) {
6233
6493
  return '';
6234
6494
  }
6235
- return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
6495
+ return `${hour}:${minute}:${meridiem}`;
6236
6496
  }, [hour, minute, meridiem]);
6237
6497
  // Calculate duration difference
6238
6498
  const durationDiff = React.useMemo(() => {
@@ -6243,15 +6503,14 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6243
6503
  meridiem === null) {
6244
6504
  return null;
6245
6505
  }
6246
- const hour24 = meridiem === 'am'
6247
- ? hour === 12
6248
- ? 0
6249
- : hour
6250
- : hour === 12
6251
- ? 12
6252
- : hour + 12;
6253
6506
  const startDateObj = dayjs(startTime).tz(timezone);
6254
6507
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
6508
+ // Convert 12-hour to 24-hour format
6509
+ let hour24 = hour;
6510
+ if (meridiem === 'am' && hour === 12)
6511
+ hour24 = 0;
6512
+ else if (meridiem === 'pm' && hour < 12)
6513
+ hour24 = hour + 12;
6255
6514
  const currentDateTime = selectedDateObj
6256
6515
  .hour(hour24)
6257
6516
  .minute(minute)
@@ -6316,83 +6575,54 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6316
6575
  if (!trimmedValue) {
6317
6576
  return;
6318
6577
  }
6319
- // Try to parse custom input using explicit regex patterns
6320
- const normalized = trimmedValue.toLowerCase().replace(/\s+/g, '');
6321
- // Pattern 1: 12-hour format with meridiem (e.g., "930pm", "1230am", "9:30pm", "12:30am")
6322
- // Matches: 1-2 digits hour, optional colon, 2 digits minute, am/pm
6323
- const pattern12HourWithMeridiem = /^(\d{1,2}):?(\d{2})(am|pm)$/;
6324
- const match12Hour = normalized.match(pattern12HourWithMeridiem);
6578
+ // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6579
+ const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6580
+ const match12Hour = trimmedValue.match(timePattern12Hour);
6325
6581
  if (match12Hour) {
6326
6582
  const parsedHour = parseInt(match12Hour[1], 10);
6327
6583
  const parsedMinute = parseInt(match12Hour[2], 10);
6328
- const parsedMeridiem = match12Hour[3];
6329
- // Validate hour (1-12)
6330
- if (parsedHour < 1 || parsedHour > 12) {
6331
- // Parse failed, select first result
6332
- selectFirstResult();
6333
- return;
6334
- }
6335
- // Validate minute (0-59)
6336
- if (parsedMinute < 0 || parsedMinute > 59) {
6337
- // Parse failed, select first result
6338
- selectFirstResult();
6584
+ const parsedMeridiem = match12Hour[3].toLowerCase();
6585
+ // Validate ranges
6586
+ if (parsedHour >= 1 &&
6587
+ parsedHour <= 12 &&
6588
+ parsedMinute >= 0 &&
6589
+ parsedMinute <= 59) {
6590
+ setHour(parsedHour);
6591
+ setMinute(parsedMinute);
6592
+ setMeridiem(parsedMeridiem);
6593
+ onChange({
6594
+ hour: parsedHour,
6595
+ minute: parsedMinute,
6596
+ meridiem: parsedMeridiem,
6597
+ });
6339
6598
  return;
6340
6599
  }
6341
- setHour(parsedHour);
6342
- setMinute(parsedMinute);
6343
- setMeridiem(parsedMeridiem);
6344
- onChange({
6345
- hour: parsedHour,
6346
- minute: parsedMinute,
6347
- meridiem: parsedMeridiem,
6348
- });
6349
- return;
6350
6600
  }
6351
- // Pattern 2: 24-hour format (e.g., "2130", "09:30", "21:30")
6352
- // Matches: 1-2 digits hour, optional colon, 2 digits minute
6353
- const pattern24Hour = /^(\d{1,2}):?(\d{2})$/;
6354
- const match24Hour = normalized.match(pattern24Hour);
6355
- if (match24Hour) {
6356
- let parsedHour = parseInt(match24Hour[1], 10);
6357
- const parsedMinute = parseInt(match24Hour[2], 10);
6358
- // Validate hour (0-23)
6359
- if (parsedHour < 0 || parsedHour > 23) {
6360
- // Parse failed, select first result
6361
- selectFirstResult();
6362
- return;
6363
- }
6364
- // Validate minute (0-59)
6365
- if (parsedMinute < 0 || parsedMinute > 59) {
6366
- // Parse failed, select first result
6367
- selectFirstResult();
6368
- return;
6369
- }
6370
- // Convert 24-hour to 12-hour format
6371
- let parsedMeridiem;
6372
- if (parsedHour === 0) {
6373
- parsedHour = 12;
6374
- parsedMeridiem = 'am';
6375
- }
6376
- else if (parsedHour === 12) {
6377
- parsedHour = 12;
6378
- parsedMeridiem = 'pm';
6379
- }
6380
- else if (parsedHour > 12) {
6381
- parsedHour = parsedHour - 12;
6382
- parsedMeridiem = 'pm';
6383
- }
6384
- else {
6385
- parsedMeridiem = 'am';
6601
+ // Try to parse formats like "130pm" or "130 pm" (without colon)
6602
+ const timePatternNoColon = /^(\d{1,4})\s*(am|pm|AM|PM)$/i;
6603
+ const matchNoColon = trimmedValue.match(timePatternNoColon);
6604
+ if (matchNoColon) {
6605
+ const numbersOnly = matchNoColon[1];
6606
+ const parsedMeridiem = matchNoColon[2].toLowerCase();
6607
+ if (numbersOnly.length >= 3) {
6608
+ const parsedHour = parseInt(numbersOnly.slice(0, -2), 10);
6609
+ const parsedMinute = parseInt(numbersOnly.slice(-2), 10);
6610
+ // Validate ranges
6611
+ if (parsedHour >= 1 &&
6612
+ parsedHour <= 12 &&
6613
+ parsedMinute >= 0 &&
6614
+ parsedMinute <= 59) {
6615
+ setHour(parsedHour);
6616
+ setMinute(parsedMinute);
6617
+ setMeridiem(parsedMeridiem);
6618
+ onChange({
6619
+ hour: parsedHour,
6620
+ minute: parsedMinute,
6621
+ meridiem: parsedMeridiem,
6622
+ });
6623
+ return;
6624
+ }
6386
6625
  }
6387
- setHour(parsedHour);
6388
- setMinute(parsedMinute);
6389
- setMeridiem(parsedMeridiem);
6390
- onChange({
6391
- hour: parsedHour,
6392
- minute: parsedMinute,
6393
- meridiem: parsedMeridiem,
6394
- });
6395
- return;
6396
6626
  }
6397
6627
  // Parse failed, select first result
6398
6628
  selectFirstResult();
@@ -6439,17 +6669,17 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6439
6669
  e.currentTarget?.blur();
6440
6670
  }
6441
6671
  };
6442
- return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { placeholder: "hh:mm a", onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsxRuntime.jsx(react.Combobox.IndicatorGroup, { children: jsxRuntime.jsx(react.Combobox.Trigger, {}) })] }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsxRuntime.jsx(react.Text, { flex: 1, children: item.label }), item.durationText && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", colorPalette: "blue", children: jsxRuntime.jsx(react.Tag.Label, { children: item.durationText }) }))] }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: durationDiff }) })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }) }));
6443
- }
6672
+ return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { placeholder: labels?.placeholder ?? 'hh:mm AM/PM', onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsxRuntime.jsx(react.Combobox.IndicatorGroup, { children: jsxRuntime.jsx(react.Combobox.Trigger, {}) })] }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: labels?.emptyMessage ?? 'No time found' }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsxRuntime.jsx(react.Text, { flex: 1, children: item.label }), item.durationText && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: item.durationText }) }))] }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: durationDiff }) })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }) }));
6673
+ };
6444
6674
 
6445
6675
  dayjs.extend(timezone);
6446
6676
  const TimePicker = ({ column, schema, prefix }) => {
6447
6677
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
6448
- const { timezone, insideDialog } = useSchemaContext();
6678
+ const { timezone, insideDialog, timePickerLabels } = useSchemaContext();
6449
6679
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
6450
6680
  const isRequired = required?.some((columnId) => columnId === column);
6451
6681
  const colLabel = `${prefix}${column}`;
6452
- const formI18n = useFormI18n$1(column, prefix, schema);
6682
+ const formI18n = useFormI18n(column, prefix, schema);
6453
6683
  const [open, setOpen] = React.useState(false);
6454
6684
  const value = watch(colLabel);
6455
6685
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
@@ -6507,7 +6737,7 @@ const TimePicker = ({ column, schema, prefix }) => {
6507
6737
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6508
6738
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6509
6739
  setOpen(true);
6510
- }, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsxRuntime.jsx(react.Popover.Body, { overflow: "visible", children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange }) }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange }) }) }) }) }))] }) }));
6740
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsxRuntime.jsx(react.Popover.Body, { overflow: "visible", children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) }) }))] }) }));
6511
6741
  };
6512
6742
 
6513
6743
  dayjs.extend(utc);
@@ -6641,7 +6871,10 @@ dayjs.extend(utc);
6641
6871
  dayjs.extend(timezone);
6642
6872
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6643
6873
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6644
- onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, }) {
6874
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6875
+ placeholder: 'HH:mm:ss',
6876
+ emptyMessage: 'No time found',
6877
+ }, }) {
6645
6878
  // Generate time options (every 15 minutes, seconds always 0)
6646
6879
  const timeOptions = React.useMemo(() => {
6647
6880
  const options = [];
@@ -6904,7 +7137,7 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
6904
7137
  e.currentTarget?.blur();
6905
7138
  }
6906
7139
  };
6907
- return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { placeholder: "HH:mm:ss", onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsxRuntime.jsx(react.Combobox.IndicatorGroup, { children: jsxRuntime.jsx(react.Combobox.Trigger, {}) })] }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsxRuntime.jsx(react.Text, { flex: 1, children: item.label }), item.durationText && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: item.durationText }) }))] }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: durationDiff }) })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }) }));
7140
+ return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { placeholder: labels.placeholder, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsxRuntime.jsx(react.Combobox.IndicatorGroup, { children: jsxRuntime.jsx(react.Combobox.Trigger, {}) })] }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: labels.emptyMessage }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsxRuntime.jsx(react.Text, { flex: 1, children: item.label }), item.durationText && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: item.durationText }) }))] }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsxRuntime.jsx(react.Tag.Root, { size: "sm", children: jsxRuntime.jsx(react.Tag.Label, { children: durationDiff }) })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }) }));
6908
7141
  }
6909
7142
 
6910
7143
  dayjs.extend(utc);
@@ -6927,7 +7160,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
6927
7160
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6928
7161
  backButtonLabel: 'Back',
6929
7162
  forwardButtonLabel: 'Next',
6930
- }, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7163
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
6931
7164
  console.log('[DateTimePicker] Component initialized with props:', {
6932
7165
  value,
6933
7166
  format,
@@ -7373,7 +7606,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7373
7606
  const dateObj = dayjs.tz(selectedDate, timezone);
7374
7607
  return dateObj.isValid() ? dateObj.format('Z') : null;
7375
7608
  }, [selectedDate, timezone]);
7376
- return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsxRuntime.jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7609
+ return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, children: [jsxRuntime.jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7377
7610
  if (date) {
7378
7611
  handleDateChange(date);
7379
7612
  }
@@ -7381,15 +7614,15 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7381
7614
  setSelectedDate('');
7382
7615
  onChange?.(undefined);
7383
7616
  }
7384
- }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsxRuntime.jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled })) : (jsxRuntime.jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsxRuntime.jsx(react.Icon, { as: fa6.FaTrash }) })] }), displayText && (jsxRuntime.jsxs(react.Flex, { gap: 2, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7617
+ }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsxRuntime.jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })) : (jsxRuntime.jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsxRuntime.jsx(react.Icon, { as: fa6.FaTrash }) })] }), displayText && (jsxRuntime.jsxs(react.Flex, { gap: 2, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7385
7618
  }
7386
7619
 
7387
7620
  dayjs.extend(utc);
7388
7621
  dayjs.extend(timezone);
7389
7622
  const DateTimePicker = ({ column, schema, prefix, }) => {
7390
7623
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
7391
- const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
7392
- const formI18n = useFormI18n$1(column, prefix, schema);
7624
+ const { timezone, dateTimePickerLabels, timePickerLabels, insideDialog } = useSchemaContext();
7625
+ const formI18n = useFormI18n(column, prefix, schema);
7393
7626
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
7394
7627
  // with timezone
7395
7628
  dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
@@ -7402,74 +7635,30 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7402
7635
  : '';
7403
7636
  const dateTimePickerLabelsConfig = {
7404
7637
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
7405
- formI18n.translate.t(`common.month_1`, {
7406
- defaultValue: 'January',
7407
- }),
7408
- formI18n.translate.t(`common.month_2`, {
7409
- defaultValue: 'February',
7410
- }),
7411
- formI18n.translate.t(`common.month_3`, {
7412
- defaultValue: 'March',
7413
- }),
7414
- formI18n.translate.t(`common.month_4`, {
7415
- defaultValue: 'April',
7416
- }),
7417
- formI18n.translate.t(`common.month_5`, {
7418
- defaultValue: 'May',
7419
- }),
7420
- formI18n.translate.t(`common.month_6`, {
7421
- defaultValue: 'June',
7422
- }),
7423
- formI18n.translate.t(`common.month_7`, {
7424
- defaultValue: 'July',
7425
- }),
7426
- formI18n.translate.t(`common.month_8`, {
7427
- defaultValue: 'August',
7428
- }),
7429
- formI18n.translate.t(`common.month_9`, {
7430
- defaultValue: 'September',
7431
- }),
7432
- formI18n.translate.t(`common.month_10`, {
7433
- defaultValue: 'October',
7434
- }),
7435
- formI18n.translate.t(`common.month_11`, {
7436
- defaultValue: 'November',
7437
- }),
7438
- formI18n.translate.t(`common.month_12`, {
7439
- defaultValue: 'December',
7440
- }),
7638
+ 'January',
7639
+ 'February',
7640
+ 'March',
7641
+ 'April',
7642
+ 'May',
7643
+ 'June',
7644
+ 'July',
7645
+ 'August',
7646
+ 'September',
7647
+ 'October',
7648
+ 'November',
7649
+ 'December',
7441
7650
  ],
7442
7651
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
7443
- formI18n.translate.t(`common.weekday_1`, {
7444
- defaultValue: 'Sun',
7445
- }),
7446
- formI18n.translate.t(`common.weekday_2`, {
7447
- defaultValue: 'Mon',
7448
- }),
7449
- formI18n.translate.t(`common.weekday_3`, {
7450
- defaultValue: 'Tue',
7451
- }),
7452
- formI18n.translate.t(`common.weekday_4`, {
7453
- defaultValue: 'Wed',
7454
- }),
7455
- formI18n.translate.t(`common.weekday_5`, {
7456
- defaultValue: 'Thu',
7457
- }),
7458
- formI18n.translate.t(`common.weekday_6`, {
7459
- defaultValue: 'Fri',
7460
- }),
7461
- formI18n.translate.t(`common.weekday_7`, {
7462
- defaultValue: 'Sat',
7463
- }),
7652
+ 'Sun',
7653
+ 'Mon',
7654
+ 'Tue',
7655
+ 'Wed',
7656
+ 'Thu',
7657
+ 'Fri',
7658
+ 'Sat',
7464
7659
  ],
7465
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
7466
- formI18n.translate.t(`common.back_button`, {
7467
- defaultValue: 'Back',
7468
- }),
7469
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
7470
- formI18n.translate.t(`common.forward_button`, {
7471
- defaultValue: 'Forward',
7472
- }),
7660
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
7661
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
7473
7662
  };
7474
7663
  const dateTimePickerContent = (jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
7475
7664
  if (!date || date === null || date === undefined) {
@@ -7483,7 +7672,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7483
7672
  else {
7484
7673
  setValue(colLabel, undefined);
7485
7674
  }
7486
- }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
7675
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels }));
7487
7676
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7488
7677
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
7489
7678
  setOpen(true);
@@ -7502,7 +7691,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7502
7691
  }
7503
7692
  if (variant === 'id-picker') {
7504
7693
  idPickerSanityCheck(column, foreign_key);
7505
- return jsxRuntime.jsx(IdPicker, { schema: colSchema, prefix, column });
7694
+ return jsxRuntime.jsx(IdPickerSingle, { schema: colSchema, prefix, column });
7506
7695
  }
7507
7696
  if (format === 'date') {
7508
7697
  return jsxRuntime.jsx(DatePicker, { schema: colSchema, prefix, column });
@@ -7536,7 +7725,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7536
7725
  if (type === 'array') {
7537
7726
  if (variant === 'id-picker') {
7538
7727
  idPickerSanityCheck(column, foreign_key);
7539
- return (jsxRuntime.jsx(IdPicker, { schema: colSchema, prefix, column, isMultiple: true }));
7728
+ return jsxRuntime.jsx(IdPickerMultiple, { schema: colSchema, prefix, column });
7540
7729
  }
7541
7730
  if (variant === 'tag-picker') {
7542
7731
  return jsxRuntime.jsx(TagPicker, { schema: colSchema, prefix, column });
@@ -7588,7 +7777,7 @@ const ArrayViewer = ({ schema, column, prefix }) => {
7588
7777
  const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
7589
7778
  const colLabel = `${prefix}${column}`;
7590
7779
  const isRequired = required?.some((columnId) => columnId === column);
7591
- const formI18n = useFormI18n$1(column, prefix, schema);
7780
+ const formI18n = useFormI18n(column, prefix, schema);
7592
7781
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7593
7782
  const values = watch(colLabel) ?? [];
7594
7783
  return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: '1/span12', children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: values.map((field, index) => (jsxRuntime.jsx(react.Flex, { flexFlow: 'column', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '2', borderRadius: 'md', borderWidth: 'thin', borderColor: {
@@ -7606,7 +7795,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
7606
7795
  const isRequired = required?.some((columnId) => columnId === column);
7607
7796
  const colLabel = `${prefix}${column}`;
7608
7797
  const value = watch(colLabel);
7609
- const formI18n = useFormI18n$1(column, prefix, schema);
7798
+ const formI18n = useFormI18n(column, prefix, schema);
7610
7799
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7611
7800
  gridRow, children: [jsxRuntime.jsx(react.Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
7612
7801
  };
@@ -7630,7 +7819,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7630
7819
  const isRequired = required?.some((columnId) => columnId === column);
7631
7820
  const colLabel = `${prefix}${column}`;
7632
7821
  const selectedDate = watch(colLabel);
7633
- const formI18n = useFormI18n$1(column, prefix, schema);
7822
+ const formI18n = useFormI18n(column, prefix, schema);
7634
7823
  const displayDate = dayjs(selectedDate)
7635
7824
  .tz(timezone)
7636
7825
  .format(displayDateFormat);
@@ -7640,7 +7829,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7640
7829
 
7641
7830
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
7642
7831
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7643
- const formI18n = useFormI18n$1(column, prefix);
7832
+ const formI18n = useFormI18n(column, prefix);
7644
7833
  const { required } = schema;
7645
7834
  const isRequired = required?.some((columnId) => columnId === column);
7646
7835
  const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
@@ -7664,7 +7853,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7664
7853
  const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
7665
7854
  const isRequired = required?.some((columnId) => columnId === column);
7666
7855
  const currentFiles = (watch(column) ?? []);
7667
- const formI18n = useFormI18n$1(column, prefix, schema);
7856
+ const formI18n = useFormI18n(column, prefix, schema);
7668
7857
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', children: jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
7669
7858
  return (jsxRuntime.jsx(react.Card.Root, { variant: 'subtle', children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name })] }) }, file.name));
7670
7859
  }) }) }));
@@ -7672,7 +7861,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7672
7861
 
7673
7862
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7674
7863
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7675
- const { idMap, translate } = useSchemaContext();
7864
+ const { idMap, idPickerLabels, formButtonLabels } = useSchemaContext();
7676
7865
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7677
7866
  const isRequired = required?.some((columnId) => columnId === column);
7678
7867
  const formI18n = useFormI18n(column, prefix, schema);
@@ -7696,12 +7885,12 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7696
7885
  gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
7697
7886
  const item = idMap[id];
7698
7887
  if (item === undefined) {
7699
- return (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
7888
+ return (jsxRuntime.jsx(react.Text, { children: idPickerLabels?.undefined ?? 'Undefined' }, id));
7700
7889
  }
7701
7890
  return (jsxRuntime.jsx(Tag, { closable: true, children: renderDisplay
7702
7891
  ? renderDisplay(item)
7703
7892
  : defaultRenderDisplay(item) }, id));
7704
- }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
7893
+ }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formButtonLabels?.fieldRequired ?? formI18n.required() }))] }));
7705
7894
  };
7706
7895
 
7707
7896
  const NumberViewer = ({ schema, column, prefix, }) => {
@@ -7710,7 +7899,7 @@ const NumberViewer = ({ schema, column, prefix, }) => {
7710
7899
  const isRequired = required?.some((columnId) => columnId === column);
7711
7900
  const colLabel = `${prefix}${column}`;
7712
7901
  const value = watch(colLabel);
7713
- const formI18n = useFormI18n$1(column, prefix, schema);
7902
+ const formI18n = useFormI18n(column, prefix, schema);
7714
7903
  // Format the value for display if formatOptions are provided
7715
7904
  const formatValue = (val) => {
7716
7905
  if (val === undefined || val === null || val === '')
@@ -7736,7 +7925,7 @@ const ObjectViewer = ({ schema, column, prefix }) => {
7736
7925
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
7737
7926
  const colLabel = `${prefix}${column}`;
7738
7927
  const isRequired = required?.some((columnId) => columnId === column);
7739
- const formI18n = useFormI18n$1(column, prefix, schema);
7928
+ const formI18n = useFormI18n(column, prefix, schema);
7740
7929
  const { formState: { errors }, } = reactHookForm.useFormContext();
7741
7930
  if (properties === undefined) {
7742
7931
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -7758,7 +7947,7 @@ const RecordViewer = ({ column, schema, prefix }) => {
7758
7947
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
7759
7948
  const isRequired = required?.some((columnId) => columnId === column);
7760
7949
  const entries = Object.entries(getValues(column) ?? {});
7761
- const formI18n = useFormI18n$1(column, prefix, schema);
7950
+ const formI18n = useFormI18n(column, prefix, schema);
7762
7951
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, children: [entries.length === 0 ? (jsxRuntime.jsx(react.Text, { color: "gray.500", children: "No entries" })) : (jsxRuntime.jsx(react.Grid, { templateColumns: '1fr 1fr', gap: 2, children: entries.map(([key, value]) => {
7763
7952
  return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxRuntime.jsxs(react.Text, { fontWeight: "medium", children: [key, ":"] }), jsxRuntime.jsx(react.Text, { children: String(value ?? '') })] }, key));
7764
7953
  }) })), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
@@ -7770,7 +7959,7 @@ const StringViewer = ({ column, schema, prefix, }) => {
7770
7959
  const isRequired = required?.some((columnId) => columnId === column);
7771
7960
  const colLabel = `${prefix}${column}`;
7772
7961
  const value = watch(colLabel);
7773
- const formI18n = useFormI18n$1(column, prefix, schema);
7962
+ const formI18n = useFormI18n(column, prefix, schema);
7774
7963
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', children: [jsxRuntime.jsx(react.Text, { children: value }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7775
7964
  };
7776
7965
 
@@ -7865,7 +8054,7 @@ const TextAreaViewer = ({ column, schema, prefix, }) => {
7865
8054
  const isRequired = required?.some((columnId) => columnId === column);
7866
8055
  const colLabel = `${prefix}${column}`;
7867
8056
  const value = watch(colLabel);
7868
- const formI18n = useFormI18n$1(column, prefix, schema);
8057
+ const formI18n = useFormI18n(column, prefix, schema);
7869
8058
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsxRuntime.jsx(react.Text, { whiteSpace: "pre-wrap", children: value }), ' ', errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7870
8059
  };
7871
8060
 
@@ -7876,7 +8065,7 @@ const TimeViewer = ({ column, schema, prefix }) => {
7876
8065
  const isRequired = required?.some((columnId) => columnId === column);
7877
8066
  const colLabel = `${prefix}${column}`;
7878
8067
  const selectedDate = watch(colLabel);
7879
- const formI18n = useFormI18n$1(column, prefix, schema);
8068
+ const formI18n = useFormI18n(column, prefix, schema);
7880
8069
  const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
7881
8070
  .tz(timezone)
7882
8071
  .isValid()
@@ -7893,7 +8082,7 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
7893
8082
  const isRequired = required?.some((columnId) => columnId === column);
7894
8083
  const colLabel = `${prefix}${column}`;
7895
8084
  const selectedDate = watch(colLabel);
7896
- const formI18n = useFormI18n$1(column, prefix, schema);
8085
+ const formI18n = useFormI18n(column, prefix, schema);
7897
8086
  const displayDate = dayjs(selectedDate)
7898
8087
  .tz(timezone)
7899
8088
  .format(displayDateFormat);
@@ -7987,7 +8176,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
7987
8176
  };
7988
8177
 
7989
8178
  const SubmitButton = () => {
7990
- const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
8179
+ const { setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
7991
8180
  const methods = reactHookForm.useFormContext();
7992
8181
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7993
8182
  const onValid = (data) => {
@@ -8016,11 +8205,11 @@ const SubmitButton = () => {
8016
8205
  };
8017
8206
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
8018
8207
  methods.handleSubmit(onValid)();
8019
- }, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
8208
+ }, formNoValidate: true, children: formButtonLabels?.submit ?? 'Submit' }));
8020
8209
  };
8021
8210
 
8022
8211
  const FormBody = () => {
8023
- const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8212
+ const { schema, order, ignore, include, isError, isSubmiting, isConfirming, setIsConfirming, validatedData, error, customErrorRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8024
8213
  const { showSubmitButton, showResetButton } = displayConfig;
8025
8214
  const methods = reactHookForm.useFormContext();
8026
8215
  const { properties } = schema;
@@ -8037,21 +8226,6 @@ const FormBody = () => {
8037
8226
  ignore,
8038
8227
  include,
8039
8228
  });
8040
- if (isSuccess) {
8041
- const resetHandler = async () => {
8042
- setIsError(false);
8043
- setIsSubmiting(false);
8044
- setIsSuccess(false);
8045
- setIsConfirming(false);
8046
- setValidatedData(undefined);
8047
- const data = await getUpdatedData();
8048
- methods.reset(data);
8049
- };
8050
- if (customSuccessRenderer) {
8051
- return customSuccessRenderer(resetHandler);
8052
- }
8053
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t('submit_success') }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: 'end', children: jsxRuntime.jsx(react.Button, { onClick: resetHandler, formNoValidate: true, children: formButtonLabels?.submitAgain ?? translate.t('submit_again') }) })] }));
8054
- }
8055
8229
  if (isConfirming) {
8056
8230
  return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
8057
8231
  return (jsxRuntime.jsx(ColumnViewer
@@ -8061,9 +8235,9 @@ const FormBody = () => {
8061
8235
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
8062
8236
  }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: '2', children: [jsxRuntime.jsx(react.Button, { onClick: () => {
8063
8237
  setIsConfirming(false);
8064
- }, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
8238
+ }, variant: 'subtle', children: formButtonLabels?.cancel ?? 'Cancel' }), jsxRuntime.jsx(react.Button, { onClick: () => {
8065
8239
  onFormSubmit(validatedData);
8066
- }, children: formButtonLabels?.confirm ?? translate.t('confirm') })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8240
+ }, children: formButtonLabels?.confirm ?? 'Confirm' })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8067
8241
  }
8068
8242
  return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
8069
8243
  return (jsxRuntime.jsx(ColumnRenderer
@@ -8073,12 +8247,12 @@ const FormBody = () => {
8073
8247
  properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
8074
8248
  }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
8075
8249
  methods.reset();
8076
- }, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8250
+ }, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8077
8251
  };
8078
8252
 
8079
8253
  const FormTitle = () => {
8080
- const { translate } = useSchemaContext();
8081
- return jsxRuntime.jsx(react.Heading, { children: translate.t("title") });
8254
+ const { schema } = useSchemaContext();
8255
+ return jsxRuntime.jsx(react.Heading, { children: schema.title ?? 'Form' });
8082
8256
  };
8083
8257
 
8084
8258
  const DefaultForm = ({ formConfig, }) => {
@@ -8086,7 +8260,9 @@ const DefaultForm = ({ formConfig, }) => {
8086
8260
  return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
8087
8261
  };
8088
8262
 
8089
- const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8263
+ const useForm = ({ preLoadedValues, keyPrefix: _keyPrefix, // Deprecated: kept for backward compatibility
8264
+ namespace: _namespace, // Deprecated: kept for backward compatibility
8265
+ schema, }) => {
8090
8266
  const form = reactHookForm.useForm({
8091
8267
  values: preLoadedValues,
8092
8268
  resolver: schema ? ajvResolver(schema) : undefined,
@@ -8094,12 +8270,16 @@ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8094
8270
  reValidateMode: 'onBlur',
8095
8271
  });
8096
8272
  const [idMap, setIdMap] = React.useState({});
8097
- const translate = reactI18next.useTranslation(namespace || '', { keyPrefix });
8273
+ // Fallback translate object - returns key as-is (no i18n required)
8274
+ const translate = {
8275
+ t: (key) => key,
8276
+ ready: true,
8277
+ };
8098
8278
  return {
8099
8279
  form,
8100
8280
  idMap,
8101
8281
  setIdMap,
8102
- translate,
8282
+ translate, // Components prefer label objects over translate
8103
8283
  };
8104
8284
  };
8105
8285
 
@@ -8427,6 +8607,21 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
8427
8607
  })] }));
8428
8608
  };
8429
8609
 
8610
+ const MobileTableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
8611
+ const { tableLabel, table } = useDataTableContext();
8612
+ const { hasErrorText } = tableLabel;
8613
+ return (jsxRuntime.jsxs(react.Grid, { templateRows: 'auto 1fr auto', width: fitTableWidth ? 'fit-content' : '100%', height: fitTableHeight ? 'fit-content' : '100%', gap: 2, padding: 2, ...gridProps, children: [jsxRuntime.jsxs(react.Stack, { gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, children: [jsxRuntime.jsxs(react.Flex, { gap: 1, alignItems: 'center', children: [showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }), loading && jsxRuntime.jsx(react.Spinner, { size: 'sm' }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: 'red.400' }) }))] }), jsxRuntime.jsxs(react.Flex, { gap: 1, alignItems: 'center', children: [showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Stack, { gap: 2, children: filterTagsOptions.map((option) => {
8614
+ const { column, options } = option;
8615
+ const tableColumn = table.getColumn(column);
8616
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 1, width: '100%', children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { fontSize: 'sm', fontWeight: 'medium', children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
8617
+ if (tags.length === 0) {
8618
+ return tableColumn?.setFilterValue(undefined);
8619
+ }
8620
+ tableColumn?.setFilterValue(tags);
8621
+ } })] }, column));
8622
+ }) })), showFilterTags && (jsxRuntime.jsx(react.Box, { width: '100%', children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Box, { overflow: 'auto', width: '100%', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, borderRadius: 'md', padding: 1, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Stack, { gap: 2, width: '100%', children: [(showPageSizeControl || showPageCountText) && (jsxRuntime.jsxs(react.Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, flexWrap: 'wrap', children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && jsxRuntime.jsx(RowCountText, {})] })), showPagination && (jsxRuntime.jsx(react.Flex, { justifyContent: 'center', width: '100%', children: jsxRuntime.jsx(Pagination, {}) }))] }))] }));
8623
+ };
8624
+
8430
8625
  const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
8431
8626
  'use no memo';
8432
8627
  const { table } = useDataTableContext();
@@ -8486,7 +8681,68 @@ const TableRowSelectorSkeleton = () => {
8486
8681
  bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(react.Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
8487
8682
  };
8488
8683
 
8684
+ const MobileTableDisplay = ({ showSelector = false, isLoading = false, }) => {
8685
+ const { table, rowSelection, setRowSelection } = useDataTableContext();
8686
+ if (isLoading) {
8687
+ return jsxRuntime.jsx(MobileTableSkeleton, { showSelector: showSelector });
8688
+ }
8689
+ return (jsxRuntime.jsx(react.Stack, { gap: 4, padding: 2, children: table.getRowModel().rows.map((row) => {
8690
+ return (jsxRuntime.jsx(react.Card.Root, { width: "100%", children: jsxRuntime.jsxs(react.Card.Body, { padding: 4, children: [showSelector && (jsxRuntime.jsx(react.Flex, { marginBottom: 3, children: jsxRuntime.jsx(Checkbox, { checked: isRowSelected(row.id, rowSelection),
8691
+ disabled: !canRowSelect(row),
8692
+ onCheckedChange: createRowToggleHandler(row, rowSelection, setRowSelection) }) })), jsxRuntime.jsx(react.Stack, { gap: 3, children: row.getVisibleCells().map((cell) => {
8693
+ const displayName = cell.column.columnDef.meta?.displayName ?? cell.column.id;
8694
+ return (jsxRuntime.jsxs(react.Box, { children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "bold", color: { base: 'gray.600', _dark: 'gray.400' }, marginBottom: 1, children: displayName }), jsxRuntime.jsx(react.Box, { color: { base: 'gray.900', _dark: 'gray.100' }, fontSize: "sm", children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) })] }, `mobile-table-cell-${cell.id}`));
8695
+ }) })] }) }, `mobile-table-card-${row.id}`));
8696
+ }) }));
8697
+ };
8698
+ const MobileTableSkeleton = ({ showSelector = false, }) => {
8699
+ const { table } = useDataTableContext();
8700
+ const pageSize = table.getState().pagination.pageSize;
8701
+ const visibleColumns = table.getVisibleLeafColumns();
8702
+ return (jsxRuntime.jsx(react.Stack, { gap: 4, padding: 2, children: Array.from({ length: pageSize }).map((_, rowIndex) => {
8703
+ return (jsxRuntime.jsx(react.Card.Root, { width: "100%", children: jsxRuntime.jsxs(react.Card.Body, { padding: 4, children: [showSelector && (jsxRuntime.jsx(react.Flex, { marginBottom: 3, children: jsxRuntime.jsx(react.Box, { width: "20px", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "md" }) })), jsxRuntime.jsx(react.Stack, { gap: 3, children: visibleColumns.map((column) => {
8704
+ return (jsxRuntime.jsxs(react.Box, { children: [jsxRuntime.jsx(react.Box, { width: "40%", height: "16px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm", marginBottom: 2 }), jsxRuntime.jsx(react.Box, { width: "80%", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm" })] }, `mobile-skeleton-cell-${column.id}`));
8705
+ }) })] }) }, `mobile-skeleton-${rowIndex}`));
8706
+ }) }));
8707
+ };
8708
+
8709
+ /**
8710
+ * Hook to detect if the current window width is mobile (< 768px)
8711
+ * @param breakpoint - The breakpoint in pixels to consider as mobile (default: 768)
8712
+ * @returns boolean indicating if the window is mobile
8713
+ */
8714
+ const useIsMobile = (breakpoint = 768) => {
8715
+ const [isMobile, setIsMobile] = React.useState(() => {
8716
+ if (typeof window === 'undefined')
8717
+ return false;
8718
+ return window.innerWidth < breakpoint;
8719
+ });
8720
+ React.useEffect(() => {
8721
+ if (typeof window === 'undefined')
8722
+ return;
8723
+ const handleResize = () => {
8724
+ setIsMobile(window.innerWidth < breakpoint);
8725
+ };
8726
+ // Set initial value
8727
+ handleResize();
8728
+ // Add event listener
8729
+ window.addEventListener('resize', handleResize);
8730
+ // Cleanup
8731
+ return () => {
8732
+ window.removeEventListener('resize', handleResize);
8733
+ };
8734
+ }, [breakpoint]);
8735
+ return isMobile;
8736
+ };
8737
+
8489
8738
  const DefaultTable = ({ showFooter = false, showHeader = true, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = 'greedy', isLoading = false, }) => {
8739
+ const isMobile = useIsMobile();
8740
+ // Early return for mobile display
8741
+ if (isMobile) {
8742
+ return (jsxRuntime.jsx(MobileTableControls, { ...controlProps, children: jsxRuntime.jsx(MobileTableDisplay, { showSelector: tableHeaderProps.showSelector ??
8743
+ tableBodyProps.showSelector ??
8744
+ false, isLoading: isLoading }) }));
8745
+ }
8490
8746
  const isGreedy = variant === 'greedy';
8491
8747
  const canResize = !isGreedy;
8492
8748
  const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: canResize })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps, canResize: canResize }));
@@ -8587,6 +8843,290 @@ const DataDisplay = ({ variant = '' }) => {
8587
8843
  }) }));
8588
8844
  };
8589
8845
 
8846
+ // Helper function to normalize date
8847
+ function normalizeDate(value) {
8848
+ if (!value)
8849
+ return null;
8850
+ if (value instanceof Date)
8851
+ return value;
8852
+ if (typeof value === 'string' || typeof value === 'number') {
8853
+ const date = dayjs(value).toDate();
8854
+ return isNaN(date.getTime()) ? null : date;
8855
+ }
8856
+ return null;
8857
+ }
8858
+ // Component to conditionally render event title based on available width
8859
+ function ResponsiveEventTitle({ title, placeholder, minWidth, minChars, cellRef, }) {
8860
+ const [truncatedText, setTruncatedText] = React.useState('');
8861
+ const measureRef = React.useRef(null);
8862
+ React.useEffect(() => {
8863
+ const calculateTruncatedText = () => {
8864
+ if (!cellRef.current || !measureRef.current || !title) {
8865
+ setTruncatedText(title || 'Event');
8866
+ return;
8867
+ }
8868
+ const cellWidth = cellRef.current.clientWidth;
8869
+ // Account for padding (approximately 8px on each side)
8870
+ const availableWidth = cellWidth - 16;
8871
+ // If cell is too narrow, calculate how many characters can fit
8872
+ if (availableWidth < minWidth) {
8873
+ // Measure text width using canvas
8874
+ const canvas = document.createElement('canvas');
8875
+ const context = canvas.getContext('2d');
8876
+ if (!context) {
8877
+ setTruncatedText(placeholder);
8878
+ return;
8879
+ }
8880
+ // Get computed font style from the element
8881
+ const computedStyle = window.getComputedStyle(measureRef.current);
8882
+ context.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
8883
+ const ellipsisWidth = context.measureText('...').width;
8884
+ const maxWidth = availableWidth - ellipsisWidth;
8885
+ // Try to show at least minChars characters before ellipsis
8886
+ let truncated = '';
8887
+ let charCount = 0;
8888
+ // Calculate how many characters can fit
8889
+ for (let i = 0; i < Math.min(title.length, 50); i++) {
8890
+ const testText = title.substring(0, i + 1);
8891
+ const textWidth = context.measureText(testText).width;
8892
+ if (textWidth <= maxWidth) {
8893
+ truncated = testText;
8894
+ charCount = i + 1;
8895
+ }
8896
+ else {
8897
+ break;
8898
+ }
8899
+ }
8900
+ // Ensure we show at least minChars characters if possible
8901
+ if (charCount < minChars && title.length >= minChars) {
8902
+ truncated = title.substring(0, minChars);
8903
+ }
8904
+ else if (charCount === 0 && title.length >= 1) {
8905
+ truncated = title.substring(0, 1);
8906
+ }
8907
+ // Only show ellipsis if we have at least minChars characters
8908
+ if (truncated && truncated.length >= minChars) {
8909
+ setTruncatedText(`${truncated}...`);
8910
+ }
8911
+ else {
8912
+ setTruncatedText(placeholder);
8913
+ }
8914
+ }
8915
+ else {
8916
+ // Full width available, show full title
8917
+ setTruncatedText(title);
8918
+ }
8919
+ };
8920
+ calculateTruncatedText();
8921
+ const resizeObserver = new ResizeObserver(calculateTruncatedText);
8922
+ if (cellRef.current) {
8923
+ resizeObserver.observe(cellRef.current);
8924
+ }
8925
+ // Also check on window resize
8926
+ window.addEventListener('resize', calculateTruncatedText);
8927
+ return () => {
8928
+ resizeObserver.disconnect();
8929
+ window.removeEventListener('resize', calculateTruncatedText);
8930
+ };
8931
+ }, [cellRef, minWidth, title, placeholder]);
8932
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { ref: measureRef, style: {
8933
+ visibility: 'hidden',
8934
+ position: 'absolute',
8935
+ whiteSpace: 'nowrap',
8936
+ }, children: title || 'Event' }), truncatedText || title || 'Event'] }));
8937
+ }
8938
+ function CalendarDisplay({ dateColumn, getDate, getEventTitle, getEventColor, renderEvent, firstDayOfWeek = 0, showOutsideDays = true, monthsToDisplay = 1, labels = {
8939
+ monthNamesShort: [
8940
+ 'Jan',
8941
+ 'Feb',
8942
+ 'Mar',
8943
+ 'Apr',
8944
+ 'May',
8945
+ 'Jun',
8946
+ 'Jul',
8947
+ 'Aug',
8948
+ 'Sep',
8949
+ 'Oct',
8950
+ 'Nov',
8951
+ 'Dec',
8952
+ ],
8953
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
8954
+ backButtonLabel: 'Back',
8955
+ forwardButtonLabel: 'Next',
8956
+ }, onDateClick, onEventClick, maxEventsPerDay = 3, colorPalette = 'blue', eventPlaceholder = '...', minEventWidth = 80, minCharsBeforeEllipsis = 2, }) {
8957
+ const { data, table } = useDataTableContext();
8958
+ // Map table data to events
8959
+ const events = React.useMemo(() => {
8960
+ return data
8961
+ .map((row) => {
8962
+ let dateValue;
8963
+ if (getDate) {
8964
+ dateValue = getDate(row);
8965
+ }
8966
+ else {
8967
+ // Try to get date from column
8968
+ const rowData = table
8969
+ .getRowModel()
8970
+ .rows.find((r) => r.original === row);
8971
+ if (rowData) {
8972
+ const cell = rowData.getAllCells().find((c) => {
8973
+ const colId = c.column.id;
8974
+ const accessorKey = c.column.columnDef.accessorKey;
8975
+ return colId === dateColumn || accessorKey === dateColumn;
8976
+ });
8977
+ dateValue = cell?.getValue();
8978
+ }
8979
+ }
8980
+ const date = normalizeDate(dateValue);
8981
+ if (!date)
8982
+ return null;
8983
+ let title;
8984
+ if (getEventTitle) {
8985
+ title = getEventTitle(row);
8986
+ }
8987
+ else {
8988
+ // Use first column's value as title
8989
+ const rowData = table
8990
+ .getRowModel()
8991
+ .rows.find((r) => r.original === row);
8992
+ if (rowData) {
8993
+ const firstCell = rowData.getAllCells()[0];
8994
+ title = String(firstCell?.getValue() ?? '');
8995
+ }
8996
+ }
8997
+ const color = getEventColor?.(row);
8998
+ return {
8999
+ data: row,
9000
+ date,
9001
+ title,
9002
+ color,
9003
+ };
9004
+ })
9005
+ .filter((event) => event !== null);
9006
+ }, [data, table, dateColumn, getDate, getEventTitle, getEventColor]);
9007
+ // Group events by date
9008
+ const eventsByDate = React.useMemo(() => {
9009
+ const map = new Map();
9010
+ events.forEach((event) => {
9011
+ const dateKey = `${event.date.getFullYear()}-${event.date.getMonth()}-${event.date.getDate()}`;
9012
+ if (!map.has(dateKey)) {
9013
+ map.set(dateKey, []);
9014
+ }
9015
+ map.get(dateKey).push(event);
9016
+ });
9017
+ return map;
9018
+ }, [events]);
9019
+ // Get events for a specific date
9020
+ const getEventsForDate = React.useCallback((date) => {
9021
+ const dateKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
9022
+ return eventsByDate.get(dateKey) ?? [];
9023
+ }, [eventsByDate]);
9024
+ const calendarData = useCalendar({
9025
+ firstDayOfWeek,
9026
+ showOutsideDays,
9027
+ monthsToDisplay,
9028
+ });
9029
+ const getDateProps = React.useCallback((props) => {
9030
+ const dateEvents = getEventsForDate(props.dateObj.date);
9031
+ const baseProps = calendarData.getDateProps({ dateObj: props.dateObj });
9032
+ return {
9033
+ ...baseProps,
9034
+ onClick: () => {
9035
+ baseProps.onClick?.();
9036
+ if (onDateClick) {
9037
+ onDateClick(props.dateObj.date, dateEvents);
9038
+ }
9039
+ },
9040
+ };
9041
+ }, [calendarData, getEventsForDate, onDateClick]);
9042
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
9043
+ if (!calendarData.calendars.length) {
9044
+ return null;
9045
+ }
9046
+ return (jsxRuntime.jsxs(react.VStack, { gap: 4, width: "100%", children: [jsxRuntime.jsxs(react.HStack, { gap: 2, justifyContent: "center", children: [jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getBackProps({
9047
+ calendars: calendarData.calendars,
9048
+ offset: 12,
9049
+ }), children: '<<' }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getBackProps({ calendars: calendarData.calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getForwardProps({
9050
+ calendars: calendarData.calendars,
9051
+ }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getForwardProps({
9052
+ calendars: calendarData.calendars,
9053
+ offset: 12,
9054
+ }), children: '>>' })] }), jsxRuntime.jsx(react.Grid, { templateColumns: {
9055
+ base: '1fr',
9056
+ md: monthsToDisplay >= 2 ? 'repeat(2, 1fr)' : '1fr',
9057
+ lg: monthsToDisplay >= 3
9058
+ ? 'repeat(3, 1fr)'
9059
+ : monthsToDisplay === 2
9060
+ ? 'repeat(2, 1fr)'
9061
+ : '1fr',
9062
+ xl: `repeat(${Math.min(monthsToDisplay, 4)}, 1fr)`,
9063
+ }, gap: { base: 4, md: 6 }, width: "100%", justifyContent: "center", children: calendarData.calendars.map((calendar) => (jsxRuntime.jsxs(react.VStack, { gap: 2, alignItems: "stretch", children: [jsxRuntime.jsxs(react.Text, { textAlign: "center", fontSize: { base: 'md', md: 'lg' }, fontWeight: "semibold", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
9064
+ const weekday = (weekdayNum + firstDayOfWeek) % 7;
9065
+ return (jsxRuntime.jsx(react.Text, { textAlign: "center", fontSize: { base: 'xs', md: 'sm' }, fontWeight: "medium", color: { base: 'gray.600', _dark: 'gray.400' }, children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
9066
+ }) }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
9067
+ const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
9068
+ if (!dateObj) {
9069
+ return jsxRuntime.jsx(react.Box, {}, key);
9070
+ }
9071
+ const { date, today, isCurrentMonth } = dateObj;
9072
+ const dateEvents = getEventsForDate(date);
9073
+ const cellRef = React.useRef(null);
9074
+ return (jsxRuntime.jsxs(react.VStack, { ref: cellRef, gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", minHeight: { base: '60px', md: '80px', lg: '100px' }, borderWidth: "1px", borderColor: {
9075
+ base: today ? `${colorPalette}.300` : 'gray.200',
9076
+ _dark: today ? `${colorPalette}.700` : 'gray.700',
9077
+ }, borderRadius: { base: 'sm', md: 'md' }, padding: { base: 0.5, md: 1 }, bgColor: {
9078
+ base: today ? `${colorPalette}.50` : 'white',
9079
+ _dark: today ? `${colorPalette}.950` : 'gray.900',
9080
+ }, opacity: isCurrentMonth ? 1 : 0.5, ...getDateProps({ dateObj }), cursor: onDateClick ? 'pointer' : 'default', _hover: onDateClick
9081
+ ? {
9082
+ bgColor: {
9083
+ base: `${colorPalette}.100`,
9084
+ _dark: `${colorPalette}.900`,
9085
+ },
9086
+ }
9087
+ : {}, children: [jsxRuntime.jsx(react.Text, { fontSize: { base: 'xs', md: 'sm' }, fontWeight: today ? 'bold' : 'normal', color: {
9088
+ base: today ? `${colorPalette}.700` : 'gray.700',
9089
+ _dark: today ? `${colorPalette}.300` : 'gray.300',
9090
+ }, textAlign: "right", paddingRight: { base: 0.5, md: 1 }, children: date.getDate() }), jsxRuntime.jsxs(react.VStack, { gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", flex: 1, overflow: "hidden", children: [dateEvents
9091
+ .slice(0, maxEventsPerDay)
9092
+ .map((event, eventIndex) => {
9093
+ const eventContent = renderEvent ? (renderEvent(event)) : (jsxRuntime.jsx(react.Box, { fontSize: { base: '2xs', md: 'xs' }, paddingX: { base: 0.5, md: 1 }, paddingY: { base: 0.25, md: 0.5 }, borderRadius: { base: 'xs', md: 'sm' }, bgColor: {
9094
+ base: event.color
9095
+ ? `${event.color}.100`
9096
+ : `${colorPalette}.100`,
9097
+ _dark: event.color
9098
+ ? `${event.color}.900`
9099
+ : `${colorPalette}.900`,
9100
+ }, color: {
9101
+ base: event.color
9102
+ ? `${event.color}.800`
9103
+ : `${colorPalette}.800`,
9104
+ _dark: event.color
9105
+ ? `${event.color}.200`
9106
+ : `${colorPalette}.200`,
9107
+ }, onClick: (e) => {
9108
+ e.stopPropagation();
9109
+ if (onEventClick) {
9110
+ onEventClick(event);
9111
+ }
9112
+ }, cursor: onEventClick ? 'pointer' : 'default', _hover: onEventClick
9113
+ ? {
9114
+ opacity: 0.8,
9115
+ }
9116
+ : {}, children: jsxRuntime.jsx(ResponsiveEventTitle, { title: event.title, placeholder: eventPlaceholder, minWidth: minEventWidth, minChars: minCharsBeforeEllipsis, cellRef: cellRef }) }, eventIndex));
9117
+ return (jsxRuntime.jsx(react.Box, { onClick: (e) => e.stopPropagation(), children: eventContent }, eventIndex));
9118
+ }), dateEvents.length > maxEventsPerDay && (jsxRuntime.jsxs(react.Text, { fontSize: "xs", color: {
9119
+ base: `${colorPalette}.600`,
9120
+ _dark: `${colorPalette}.400`,
9121
+ }, paddingX: 1, onClick: (e) => {
9122
+ e.stopPropagation();
9123
+ if (onDateClick) {
9124
+ onDateClick(date, dateEvents);
9125
+ }
9126
+ }, cursor: onDateClick ? 'pointer' : 'default', children: ["+", dateEvents.length - maxEventsPerDay, " more"] }))] })] }, key));
9127
+ })) })] }, `${calendar.month}${calendar.year}`))) })] }));
9128
+ }
9129
+
8590
9130
  // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
8591
9131
  // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
8592
9132
  // end of TS setup!
@@ -8687,7 +9227,7 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
8687
9227
  *
8688
9228
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8689
9229
  */
8690
- 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 = {
9230
+ 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, children, tableLabel = {
8691
9231
  view: 'View',
8692
9232
  edit: 'Edit',
8693
9233
  filterButtonText: 'Filter',
@@ -8698,7 +9238,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8698
9238
  reloadButtonText: 'Reload',
8699
9239
  resetSelection: 'Reset Selection',
8700
9240
  resetSorting: 'Reset Sorting',
8701
- rowCountText: 'Row Count',
9241
+ rowCountText: '',
8702
9242
  hasErrorText: 'Has Error',
8703
9243
  globalFilterPlaceholder: 'Search',
8704
9244
  trueLabel: 'True',
@@ -8755,7 +9295,6 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8755
9295
  globalFilter,
8756
9296
  setGlobalFilter,
8757
9297
  type: 'client',
8758
- translate,
8759
9298
  columns: columns,
8760
9299
  sorting,
8761
9300
  setSorting,
@@ -8787,22 +9326,22 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8787
9326
  *
8788
9327
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8789
9328
  */
8790
- 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 = {
8791
- view: "View",
8792
- edit: "Edit",
8793
- filterButtonText: "Filter",
8794
- filterTitle: "Filter",
8795
- filterReset: "Reset",
8796
- filterClose: "Close",
8797
- reloadTooltip: "Reload",
8798
- reloadButtonText: "Reload",
8799
- resetSelection: "Reset Selection",
8800
- resetSorting: "Reset Sorting",
8801
- rowCountText: "Row Count",
8802
- hasErrorText: "Has Error",
8803
- globalFilterPlaceholder: "Search",
8804
- trueLabel: "True",
8805
- falseLabel: "False",
9329
+ 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, children, tableLabel = {
9330
+ view: 'View',
9331
+ edit: 'Edit',
9332
+ filterButtonText: 'Filter',
9333
+ filterTitle: 'Filter',
9334
+ filterReset: 'Reset',
9335
+ filterClose: 'Close',
9336
+ reloadTooltip: 'Reload',
9337
+ reloadButtonText: 'Reload',
9338
+ resetSelection: 'Reset Selection',
9339
+ resetSorting: 'Reset Sorting',
9340
+ rowCountText: '',
9341
+ hasErrorText: 'Has Error',
9342
+ globalFilterPlaceholder: 'Search',
9343
+ trueLabel: 'True',
9344
+ falseLabel: 'False',
8806
9345
  }, }) {
8807
9346
  const table = reactTable.useReactTable({
8808
9347
  _features: [DensityFeature],
@@ -8812,7 +9351,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8812
9351
  getCoreRowModel: reactTable.getCoreRowModel(),
8813
9352
  manualPagination: true,
8814
9353
  manualSorting: true,
8815
- columnResizeMode: "onChange",
9354
+ columnResizeMode: 'onChange',
8816
9355
  defaultColumn: {
8817
9356
  size: 150, //starting column size
8818
9357
  minSize: 10, //enforced during column resizing
@@ -8855,8 +9394,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8855
9394
  table: table,
8856
9395
  globalFilter,
8857
9396
  setGlobalFilter,
8858
- type: "server",
8859
- translate,
9397
+ type: 'server',
8860
9398
  columns: columns,
8861
9399
  sorting,
8862
9400
  setSorting,
@@ -8874,9 +9412,10 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8874
9412
  setColumnVisibility,
8875
9413
  data: query.data?.data ?? [],
8876
9414
  tableLabel,
8877
- }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
9415
+ }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url: url ?? '', query }, children: children }) }));
8878
9416
  }
8879
9417
 
9418
+ exports.CalendarDisplay = CalendarDisplay;
8880
9419
  exports.CardHeader = CardHeader;
8881
9420
  exports.DataDisplay = DataDisplay;
8882
9421
  exports.DataTable = DataTable;