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

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 +1220 -652
  4. package/dist/index.mjs +1222 -655
  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 +68 -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,79 @@ const defaultRenderDisplay = (item) => {
5468
5651
  return JSON.stringify(item);
5469
5652
  };
5470
5653
 
5471
- const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5654
+ /**
5655
+ * Load initial values for IdPicker fields into idMap
5656
+ * Uses customQueryFn if available, otherwise falls back to getTableData
5657
+ *
5658
+ * @param params - Configuration for loading initial values
5659
+ * @returns Promise with fetched data and idMap
5660
+ */
5661
+ const loadInitialValues = async ({ ids, foreign_key, serverUrl, setIdMap, }) => {
5662
+ if (!ids || ids.length === 0) {
5663
+ return { data: { data: [], count: 0 }, idMap: {} };
5664
+ }
5665
+ const { table, column: column_ref, customQueryFn } = foreign_key;
5666
+ // Filter out IDs that are already in idMap (optional optimization)
5667
+ // For now, we'll fetch all requested IDs to ensure consistency
5668
+ if (customQueryFn) {
5669
+ const { data, idMap: returnedIdMap } = await customQueryFn({
5670
+ searching: '',
5671
+ limit: ids.length,
5672
+ offset: 0,
5673
+ where: [
5674
+ {
5675
+ id: column_ref,
5676
+ value: ids.length === 1 ? ids[0] : ids, // CustomQueryFn accepts string | string[]
5677
+ },
5678
+ ],
5679
+ });
5680
+ // Update idMap with returned values
5681
+ if (returnedIdMap && Object.keys(returnedIdMap).length > 0) {
5682
+ setIdMap((state) => {
5683
+ return { ...state, ...returnedIdMap };
5684
+ });
5685
+ }
5686
+ return { data, idMap: returnedIdMap || {} };
5687
+ }
5688
+ // Fallback to default getTableData
5689
+ const data = await getTableData({
5690
+ serverUrl,
5691
+ searching: '',
5692
+ in_table: table,
5693
+ limit: ids.length,
5694
+ offset: 0,
5695
+ where: [
5696
+ {
5697
+ id: column_ref,
5698
+ value: ids, // Always pass as array
5699
+ },
5700
+ ],
5701
+ });
5702
+ // Build idMap from fetched data
5703
+ const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5704
+ return [
5705
+ item[column_ref],
5706
+ {
5707
+ ...item,
5708
+ },
5709
+ ];
5710
+ }));
5711
+ // Update idMap state
5712
+ setIdMap((state) => {
5713
+ return { ...state, ...newMap };
5714
+ });
5715
+ return { data: data, idMap: newMap };
5716
+ };
5717
+ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5472
5718
  const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5473
5719
  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);
5720
+ const { renderDisplay, foreign_key } = schema;
5477
5721
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5478
5722
  const [searchText, setSearchText] = React.useState('');
5479
5723
  const [debouncedSearchText, setDebouncedSearchText] = React.useState('');
5480
5724
  const [limit] = React.useState(50); // Increased limit for combobox
5481
- const colLabel = formI18n.colLabel;
5725
+ // Get colLabel from schema context (we'll compute it here)
5726
+ const colLabel = `${prefix}${column}`;
5482
5727
  const watchedValue = watch(colLabel);
5483
5728
  const watchId = !isMultiple ? watchedValue : undefined;
5484
5729
  const watchIds = isMultiple
@@ -5525,48 +5770,14 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5525
5770
  if (missingIds.length === 0) {
5526
5771
  return { data: [], count: 0 };
5527
5772
  }
5528
- if (customQueryFn) {
5529
- const { data, idMap } = await customQueryFn({
5530
- searching: '',
5531
- limit: missingIds.length,
5532
- offset: 0,
5533
- where: [
5534
- {
5535
- id: column_ref,
5536
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5537
- },
5538
- ],
5539
- });
5540
- setIdMap((state) => {
5541
- return { ...state, ...idMap };
5542
- });
5543
- return data;
5544
- }
5545
- const data = await getTableData({
5773
+ // Use the reusable loadInitialValues function
5774
+ const result = await loadInitialValues({
5775
+ ids: missingIds,
5776
+ foreign_key: foreign_key,
5546
5777
  serverUrl,
5547
- searching: '',
5548
- in_table: table,
5549
- limit: missingIds.length,
5550
- offset: 0,
5551
- where: [
5552
- {
5553
- id: column_ref,
5554
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5555
- },
5556
- ],
5557
- });
5558
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5559
- return [
5560
- item[column_ref],
5561
- {
5562
- ...item,
5563
- },
5564
- ];
5565
- }));
5566
- setIdMap((state) => {
5567
- return { ...state, ...newMap };
5778
+ setIdMap,
5568
5779
  });
5569
- return data;
5780
+ return result.data;
5570
5781
  },
5571
5782
  enabled: missingIds.length > 0, // Only fetch if there are missing IDs
5572
5783
  staleTime: 300000,
@@ -5677,20 +5888,6 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5677
5888
  itemToValue: (item) => item.value,
5678
5889
  filter: contains,
5679
5890
  });
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
5891
  // Track previous comboboxItems to avoid unnecessary updates
5695
5892
  const prevComboboxItemsRef = React.useRef('');
5696
5893
  const prevSearchTextRef = React.useRef('');
@@ -5720,8 +5917,106 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5720
5917
  // comboboxItems and searchText are the only dependencies we care about
5721
5918
  // eslint-disable-next-line react-hooks/exhaustive-deps
5722
5919
  }, [comboboxItems, searchText]);
5920
+ return {
5921
+ colLabel,
5922
+ currentValue,
5923
+ searchText,
5924
+ setSearchText,
5925
+ debouncedSearchText,
5926
+ isLoading,
5927
+ isFetching,
5928
+ isPending,
5929
+ isError,
5930
+ isSearching,
5931
+ isLoadingInitialValues,
5932
+ isFetchingInitialValues,
5933
+ missingIds,
5934
+ comboboxItems,
5935
+ collection,
5936
+ filter,
5937
+ set,
5938
+ idMap,
5939
+ idPickerLabels,
5940
+ insideDialog: insideDialog ?? false,
5941
+ renderDisplay,
5942
+ column_ref,
5943
+ errors,
5944
+ setValue,
5945
+ };
5946
+ };
5947
+
5948
+ const IdPickerSingle = ({ column, schema, prefix, }) => {
5949
+ const formI18n = useFormI18n(column, prefix, schema);
5950
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5951
+ const isRequired = required?.some((columnId) => columnId === column);
5952
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5953
+ column,
5954
+ schema,
5955
+ prefix,
5956
+ isMultiple: false,
5957
+ });
5958
+ const handleInputValueChange = (details) => {
5959
+ setSearchText(details.inputValue);
5960
+ };
5961
+ const handleValueChange = (details) => {
5962
+ setValue(colLabel, details.value[0] || '');
5963
+ };
5964
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5723
5965
  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) => {
5966
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { mb: 2, children: (() => {
5967
+ const id = currentValue[0];
5968
+ const item = idMap[id];
5969
+ // Show loading skeleton while fetching initial values
5970
+ if (item === undefined &&
5971
+ (isLoadingInitialValues || isFetchingInitialValues) &&
5972
+ missingIds.includes(id)) {
5973
+ return jsxRuntime.jsx(react.Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
5974
+ }
5975
+ // Only show "not found" if we're not loading and item is still missing
5976
+ if (item === undefined) {
5977
+ return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
5978
+ }
5979
+ return jsxRuntime.jsx(react.Text, { fontSize: "sm", children: renderDisplayFunction(item) });
5980
+ })() })), 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
5981
+ ? { strategy: 'fixed', hideWhenDetached: true }
5982
+ : 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: () => {
5983
+ setValue(colLabel, '');
5984
+ } })), 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 ? (
5985
+ // Show skeleton items to prevent UI shift
5986
+ 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
5987
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5988
+ : idPickerLabels?.initialResults ??
5989
+ '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
5990
+ ? renderDisplayFunction(item.raw)
5991
+ : 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 ? (
5992
+ // Show skeleton items to prevent UI shift
5993
+ 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
5994
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5995
+ : idPickerLabels?.initialResults ??
5996
+ '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
5997
+ ? renderDisplayFunction(item.raw)
5998
+ : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5999
+ };
6000
+
6001
+ const IdPickerMultiple = ({ column, schema, prefix, }) => {
6002
+ const formI18n = useFormI18n(column, prefix, schema);
6003
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
6004
+ const isRequired = required?.some((columnId) => columnId === column);
6005
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
6006
+ column,
6007
+ schema,
6008
+ prefix,
6009
+ isMultiple: true,
6010
+ });
6011
+ const handleInputValueChange = (details) => {
6012
+ setSearchText(details.inputValue);
6013
+ };
6014
+ const handleValueChange = (details) => {
6015
+ setValue(colLabel, details.value);
6016
+ };
6017
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
6018
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6019
+ 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
6020
  const item = idMap[id];
5726
6021
  // Show loading skeleton while fetching initial values
5727
6022
  if (item === undefined &&
@@ -5731,34 +6026,28 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5731
6026
  }
5732
6027
  // Only show "not found" if we're not loading and item is still missing
5733
6028
  if (item === undefined) {
5734
- return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
6029
+ return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }, id));
5735
6030
  }
5736
6031
  return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
5737
6032
  const newValue = currentValue.filter((itemId) => itemId !== id);
5738
6033
  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
6034
+ }, children: renderDisplayFunction(item) }, id));
6035
+ }) })), 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
6036
  ? { 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 ? (
6037
+ : 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
6038
  // Show skeleton items to prevent UI shift
5748
6039
  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')
6040
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5751
6041
  : 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 ? (
6042
+ '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
6043
+ ? renderDisplayFunction(item.raw)
6044
+ : 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
6045
  // Show skeleton items to prevent UI shift
5756
6046
  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')
6047
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5759
6048
  : 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)
6049
+ '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
6050
+ ? renderDisplayFunction(item.raw)
5762
6051
  : item.label }), jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5763
6052
  };
5764
6053
 
@@ -5832,7 +6121,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
5832
6121
  const colLabel = `${prefix}${column}`;
5833
6122
  const value = watch(`${colLabel}`);
5834
6123
  const fieldError = getFieldError(errors, colLabel);
5835
- const formI18n = useFormI18n$1(column, prefix, schema);
6124
+ const formI18n = useFormI18n(column, prefix, schema);
5836
6125
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
5837
6126
  ? fieldError.includes('required')
5838
6127
  ? formI18n.required()
@@ -5850,7 +6139,7 @@ const ObjectInput = ({ schema, column, prefix }) => {
5850
6139
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
5851
6140
  const colLabel = `${prefix}${column}`;
5852
6141
  const isRequired = required?.some((columnId) => columnId === column);
5853
- const formI18n = useFormI18n$1(column, prefix, schema);
6142
+ const formI18n = useFormI18n(column, prefix, schema);
5854
6143
  const { formState: { errors }, } = reactHookForm.useFormContext();
5855
6144
  if (properties === undefined) {
5856
6145
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -5870,14 +6159,14 @@ const ObjectInput = ({ schema, column, prefix }) => {
5870
6159
 
5871
6160
  const RecordInput = ({ column, schema, prefix }) => {
5872
6161
  const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
5873
- const { translate } = useSchemaContext();
6162
+ const { formButtonLabels } = useSchemaContext();
5874
6163
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5875
6164
  const isRequired = required?.some((columnId) => columnId === column);
5876
6165
  const entries = Object.entries(getValues(column) ?? {});
5877
6166
  const [showNewEntries, setShowNewEntries] = React.useState(false);
5878
6167
  const [newKey, setNewKey] = React.useState();
5879
6168
  const [newValue, setNewValue] = React.useState();
5880
- const formI18n = useFormI18n$1(column, prefix, schema);
6169
+ const formI18n = useFormI18n(column, prefix, schema);
5881
6170
  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
6171
  return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
5883
6172
  const filtered = entries.filter(([target]) => {
@@ -5914,11 +6203,11 @@ const RecordInput = ({ column, schema, prefix }) => {
5914
6203
  setShowNewEntries(false);
5915
6204
  setNewKey(undefined);
5916
6205
  setNewValue(undefined);
5917
- }, children: translate.t(`${column}.save`) })] })] }) }), jsxRuntime.jsx(Button, { onClick: () => {
6206
+ }, children: formButtonLabels?.save ?? 'Save' })] })] }) }), jsxRuntime.jsx(Button, { onClick: () => {
5918
6207
  setShowNewEntries(true);
5919
6208
  setNewKey(undefined);
5920
6209
  setNewValue(undefined);
5921
- }, children: translate.t(`${column}.addNew`) })] }));
6210
+ }, children: formButtonLabels?.addNew ?? 'Add New' })] }));
5922
6211
  };
5923
6212
 
5924
6213
  const StringInputField = ({ column, schema, prefix, }) => {
@@ -5927,7 +6216,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
5927
6216
  const isRequired = required?.some((columnId) => columnId === column);
5928
6217
  const colLabel = `${prefix}${column}`;
5929
6218
  const fieldError = getFieldError(errors, colLabel);
5930
- const formI18n = useFormI18n$1(column, prefix, schema);
6219
+ const formI18n = useFormI18n(column, prefix, schema);
5931
6220
  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
6221
  };
5933
6222
 
@@ -6119,7 +6408,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6119
6408
  const form = reactHookForm.useFormContext();
6120
6409
  const { setValue, watch } = form;
6121
6410
  const fieldError = getFieldError(errors, colLabel);
6122
- const formI18n = useFormI18n$1(column, prefix, schema);
6411
+ const formI18n = useFormI18n(column, prefix, schema);
6123
6412
  const watchValue = watch(colLabel);
6124
6413
  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
6414
  ? fieldError.includes('required')
@@ -6130,18 +6419,13 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6130
6419
 
6131
6420
  dayjs.extend(utc);
6132
6421
  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)
6422
+ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem, onChange = () => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6423
+ placeholder: 'hh:mm AM/PM',
6424
+ emptyMessage: 'No time found',
6425
+ }, }) => {
6426
+ // Generate time options (every 15 minutes in 12-hour format)
6142
6427
  const timeOptions = React.useMemo(() => {
6143
6428
  const options = [];
6144
- const meridiemOptions = ['am', 'pm'];
6145
6429
  // Get start time for comparison if provided
6146
6430
  let startDateTime = null;
6147
6431
  let shouldFilterByDate = false;
@@ -6156,14 +6440,16 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6156
6440
  selectedDateObj.format('YYYY-MM-DD');
6157
6441
  }
6158
6442
  }
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}`;
6443
+ // Generate 12-hour format options (1-12 for hours, AM/PM)
6444
+ for (let h = 1; h <= 12; h++) {
6445
+ for (let m = 0; m < 60; m += 15) {
6446
+ for (const mer of ['am', 'pm']) {
6447
+ // Convert 12-hour to 24-hour for comparison
6448
+ let hour24 = h;
6449
+ if (mer === 'am' && h === 12)
6450
+ hour24 = 0;
6451
+ else if (mer === 'pm' && h < 12)
6452
+ hour24 = h + 12;
6167
6453
  // Filter out times that would result in negative duration (only when dates are the same)
6168
6454
  if (startDateTime && selectedDate && shouldFilterByDate) {
6169
6455
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
@@ -6206,20 +6492,23 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6206
6492
  }
6207
6493
  }
6208
6494
  }
6495
+ const hourDisplay = h.toString();
6496
+ const minuteDisplay = m.toString().padStart(2, '0');
6497
+ const timeDisplay = `${hourDisplay}:${minuteDisplay} ${mer.toUpperCase()}`;
6209
6498
  options.push({
6210
- label: displayTime,
6211
- value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
6499
+ label: timeDisplay,
6500
+ value: `${h}:${m}:${mer}`,
6212
6501
  hour: h,
6213
6502
  minute: m,
6214
6503
  meridiem: mer,
6215
- searchText: displayTime, // Use base time without duration for searching
6504
+ searchText: timeDisplay, // Use base time without duration for searching
6216
6505
  durationText,
6217
6506
  });
6218
6507
  }
6219
6508
  }
6220
6509
  }
6221
6510
  return options;
6222
- }, [timezone, startTime, selectedDate]);
6511
+ }, [startTime, selectedDate, timezone]);
6223
6512
  const { contains } = react.useFilter({ sensitivity: 'base' });
6224
6513
  const { collection, filter } = react.useListCollection({
6225
6514
  initialItems: timeOptions,
@@ -6232,7 +6521,7 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6232
6521
  if (hour === null || minute === null || meridiem === null) {
6233
6522
  return '';
6234
6523
  }
6235
- return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
6524
+ return `${hour}:${minute}:${meridiem}`;
6236
6525
  }, [hour, minute, meridiem]);
6237
6526
  // Calculate duration difference
6238
6527
  const durationDiff = React.useMemo(() => {
@@ -6243,15 +6532,14 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6243
6532
  meridiem === null) {
6244
6533
  return null;
6245
6534
  }
6246
- const hour24 = meridiem === 'am'
6247
- ? hour === 12
6248
- ? 0
6249
- : hour
6250
- : hour === 12
6251
- ? 12
6252
- : hour + 12;
6253
6535
  const startDateObj = dayjs(startTime).tz(timezone);
6254
6536
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
6537
+ // Convert 12-hour to 24-hour format
6538
+ let hour24 = hour;
6539
+ if (meridiem === 'am' && hour === 12)
6540
+ hour24 = 0;
6541
+ else if (meridiem === 'pm' && hour < 12)
6542
+ hour24 = hour + 12;
6255
6543
  const currentDateTime = selectedDateObj
6256
6544
  .hour(hour24)
6257
6545
  .minute(minute)
@@ -6316,83 +6604,54 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6316
6604
  if (!trimmedValue) {
6317
6605
  return;
6318
6606
  }
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);
6607
+ // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6608
+ const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6609
+ const match12Hour = trimmedValue.match(timePattern12Hour);
6325
6610
  if (match12Hour) {
6326
6611
  const parsedHour = parseInt(match12Hour[1], 10);
6327
6612
  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();
6613
+ const parsedMeridiem = match12Hour[3].toLowerCase();
6614
+ // Validate ranges
6615
+ if (parsedHour >= 1 &&
6616
+ parsedHour <= 12 &&
6617
+ parsedMinute >= 0 &&
6618
+ parsedMinute <= 59) {
6619
+ setHour(parsedHour);
6620
+ setMinute(parsedMinute);
6621
+ setMeridiem(parsedMeridiem);
6622
+ onChange({
6623
+ hour: parsedHour,
6624
+ minute: parsedMinute,
6625
+ meridiem: parsedMeridiem,
6626
+ });
6339
6627
  return;
6340
6628
  }
6341
- setHour(parsedHour);
6342
- setMinute(parsedMinute);
6343
- setMeridiem(parsedMeridiem);
6344
- onChange({
6345
- hour: parsedHour,
6346
- minute: parsedMinute,
6347
- meridiem: parsedMeridiem,
6348
- });
6349
- return;
6350
6629
  }
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';
6630
+ // Try to parse formats like "130pm" or "130 pm" (without colon)
6631
+ const timePatternNoColon = /^(\d{1,4})\s*(am|pm|AM|PM)$/i;
6632
+ const matchNoColon = trimmedValue.match(timePatternNoColon);
6633
+ if (matchNoColon) {
6634
+ const numbersOnly = matchNoColon[1];
6635
+ const parsedMeridiem = matchNoColon[2].toLowerCase();
6636
+ if (numbersOnly.length >= 3) {
6637
+ const parsedHour = parseInt(numbersOnly.slice(0, -2), 10);
6638
+ const parsedMinute = parseInt(numbersOnly.slice(-2), 10);
6639
+ // Validate ranges
6640
+ if (parsedHour >= 1 &&
6641
+ parsedHour <= 12 &&
6642
+ parsedMinute >= 0 &&
6643
+ parsedMinute <= 59) {
6644
+ setHour(parsedHour);
6645
+ setMinute(parsedMinute);
6646
+ setMeridiem(parsedMeridiem);
6647
+ onChange({
6648
+ hour: parsedHour,
6649
+ minute: parsedMinute,
6650
+ meridiem: parsedMeridiem,
6651
+ });
6652
+ return;
6653
+ }
6386
6654
  }
6387
- setHour(parsedHour);
6388
- setMinute(parsedMinute);
6389
- setMeridiem(parsedMeridiem);
6390
- onChange({
6391
- hour: parsedHour,
6392
- minute: parsedMinute,
6393
- meridiem: parsedMeridiem,
6394
- });
6395
- return;
6396
6655
  }
6397
6656
  // Parse failed, select first result
6398
6657
  selectFirstResult();
@@ -6439,17 +6698,17 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6439
6698
  e.currentTarget?.blur();
6440
6699
  }
6441
6700
  };
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
- }
6701
+ 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, {}) }) })] }) }));
6702
+ };
6444
6703
 
6445
6704
  dayjs.extend(timezone);
6446
6705
  const TimePicker = ({ column, schema, prefix }) => {
6447
6706
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
6448
- const { timezone, insideDialog } = useSchemaContext();
6707
+ const { timezone, insideDialog, timePickerLabels } = useSchemaContext();
6449
6708
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
6450
6709
  const isRequired = required?.some((columnId) => columnId === column);
6451
6710
  const colLabel = `${prefix}${column}`;
6452
- const formI18n = useFormI18n$1(column, prefix, schema);
6711
+ const formI18n = useFormI18n(column, prefix, schema);
6453
6712
  const [open, setOpen] = React.useState(false);
6454
6713
  const value = watch(colLabel);
6455
6714
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
@@ -6507,7 +6766,7 @@ const TimePicker = ({ column, schema, prefix }) => {
6507
6766
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6508
6767
  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
6768
  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 }) }) }) }) }))] }) }));
6769
+ }, 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
6770
  };
6512
6771
 
6513
6772
  dayjs.extend(utc);
@@ -6641,7 +6900,10 @@ dayjs.extend(utc);
6641
6900
  dayjs.extend(timezone);
6642
6901
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6643
6902
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6644
- onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, }) {
6903
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6904
+ placeholder: 'HH:mm:ss',
6905
+ emptyMessage: 'No time found',
6906
+ }, }) {
6645
6907
  // Generate time options (every 15 minutes, seconds always 0)
6646
6908
  const timeOptions = React.useMemo(() => {
6647
6909
  const options = [];
@@ -6904,7 +7166,7 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
6904
7166
  e.currentTarget?.blur();
6905
7167
  }
6906
7168
  };
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, {}) }) })] }) }));
7169
+ 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
7170
  }
6909
7171
 
6910
7172
  dayjs.extend(utc);
@@ -6927,7 +7189,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
6927
7189
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6928
7190
  backButtonLabel: 'Back',
6929
7191
  forwardButtonLabel: 'Next',
6930
- }, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7192
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
6931
7193
  console.log('[DateTimePicker] Component initialized with props:', {
6932
7194
  value,
6933
7195
  format,
@@ -7373,7 +7635,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7373
7635
  const dateObj = dayjs.tz(selectedDate, timezone);
7374
7636
  return dateObj.isValid() ? dateObj.format('Z') : null;
7375
7637
  }, [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) => {
7638
+ return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, children: [jsxRuntime.jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7377
7639
  if (date) {
7378
7640
  handleDateChange(date);
7379
7641
  }
@@ -7381,15 +7643,15 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7381
7643
  setSelectedDate('');
7382
7644
  onChange?.(undefined);
7383
7645
  }
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 })] }))] }));
7646
+ }, 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
7647
  }
7386
7648
 
7387
7649
  dayjs.extend(utc);
7388
7650
  dayjs.extend(timezone);
7389
7651
  const DateTimePicker = ({ column, schema, prefix, }) => {
7390
7652
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
7391
- const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
7392
- const formI18n = useFormI18n$1(column, prefix, schema);
7653
+ const { timezone, dateTimePickerLabels, timePickerLabels, insideDialog } = useSchemaContext();
7654
+ const formI18n = useFormI18n(column, prefix, schema);
7393
7655
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
7394
7656
  // with timezone
7395
7657
  dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
@@ -7402,74 +7664,30 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7402
7664
  : '';
7403
7665
  const dateTimePickerLabelsConfig = {
7404
7666
  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
- }),
7667
+ 'January',
7668
+ 'February',
7669
+ 'March',
7670
+ 'April',
7671
+ 'May',
7672
+ 'June',
7673
+ 'July',
7674
+ 'August',
7675
+ 'September',
7676
+ 'October',
7677
+ 'November',
7678
+ 'December',
7441
7679
  ],
7442
7680
  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
- }),
7681
+ 'Sun',
7682
+ 'Mon',
7683
+ 'Tue',
7684
+ 'Wed',
7685
+ 'Thu',
7686
+ 'Fri',
7687
+ 'Sat',
7464
7688
  ],
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
- }),
7689
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
7690
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
7473
7691
  };
7474
7692
  const dateTimePickerContent = (jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
7475
7693
  if (!date || date === null || date === undefined) {
@@ -7483,7 +7701,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7483
7701
  else {
7484
7702
  setValue(colLabel, undefined);
7485
7703
  }
7486
- }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
7704
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels }));
7487
7705
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7488
7706
  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
7707
  setOpen(true);
@@ -7502,7 +7720,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7502
7720
  }
7503
7721
  if (variant === 'id-picker') {
7504
7722
  idPickerSanityCheck(column, foreign_key);
7505
- return jsxRuntime.jsx(IdPicker, { schema: colSchema, prefix, column });
7723
+ return jsxRuntime.jsx(IdPickerSingle, { schema: colSchema, prefix, column });
7506
7724
  }
7507
7725
  if (format === 'date') {
7508
7726
  return jsxRuntime.jsx(DatePicker, { schema: colSchema, prefix, column });
@@ -7536,7 +7754,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7536
7754
  if (type === 'array') {
7537
7755
  if (variant === 'id-picker') {
7538
7756
  idPickerSanityCheck(column, foreign_key);
7539
- return (jsxRuntime.jsx(IdPicker, { schema: colSchema, prefix, column, isMultiple: true }));
7757
+ return jsxRuntime.jsx(IdPickerMultiple, { schema: colSchema, prefix, column });
7540
7758
  }
7541
7759
  if (variant === 'tag-picker') {
7542
7760
  return jsxRuntime.jsx(TagPicker, { schema: colSchema, prefix, column });
@@ -7588,7 +7806,7 @@ const ArrayViewer = ({ schema, column, prefix }) => {
7588
7806
  const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
7589
7807
  const colLabel = `${prefix}${column}`;
7590
7808
  const isRequired = required?.some((columnId) => columnId === column);
7591
- const formI18n = useFormI18n$1(column, prefix, schema);
7809
+ const formI18n = useFormI18n(column, prefix, schema);
7592
7810
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7593
7811
  const values = watch(colLabel) ?? [];
7594
7812
  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 +7824,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
7606
7824
  const isRequired = required?.some((columnId) => columnId === column);
7607
7825
  const colLabel = `${prefix}${column}`;
7608
7826
  const value = watch(colLabel);
7609
- const formI18n = useFormI18n$1(column, prefix, schema);
7827
+ const formI18n = useFormI18n(column, prefix, schema);
7610
7828
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7611
7829
  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
7830
  };
@@ -7630,7 +7848,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7630
7848
  const isRequired = required?.some((columnId) => columnId === column);
7631
7849
  const colLabel = `${prefix}${column}`;
7632
7850
  const selectedDate = watch(colLabel);
7633
- const formI18n = useFormI18n$1(column, prefix, schema);
7851
+ const formI18n = useFormI18n(column, prefix, schema);
7634
7852
  const displayDate = dayjs(selectedDate)
7635
7853
  .tz(timezone)
7636
7854
  .format(displayDateFormat);
@@ -7640,7 +7858,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7640
7858
 
7641
7859
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
7642
7860
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7643
- const formI18n = useFormI18n$1(column, prefix);
7861
+ const formI18n = useFormI18n(column, prefix);
7644
7862
  const { required } = schema;
7645
7863
  const isRequired = required?.some((columnId) => columnId === column);
7646
7864
  const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
@@ -7664,7 +7882,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7664
7882
  const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
7665
7883
  const isRequired = required?.some((columnId) => columnId === column);
7666
7884
  const currentFiles = (watch(column) ?? []);
7667
- const formI18n = useFormI18n$1(column, prefix, schema);
7885
+ const formI18n = useFormI18n(column, prefix, schema);
7668
7886
  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
7887
  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
7888
  }) }) }));
@@ -7672,7 +7890,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7672
7890
 
7673
7891
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7674
7892
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
7675
- const { idMap, translate } = useSchemaContext();
7893
+ const { idMap, idPickerLabels, formButtonLabels } = useSchemaContext();
7676
7894
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7677
7895
  const isRequired = required?.some((columnId) => columnId === column);
7678
7896
  const formI18n = useFormI18n(column, prefix, schema);
@@ -7696,12 +7914,12 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7696
7914
  gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
7697
7915
  const item = idMap[id];
7698
7916
  if (item === undefined) {
7699
- return (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
7917
+ return (jsxRuntime.jsx(react.Text, { children: idPickerLabels?.undefined ?? 'Undefined' }, id));
7700
7918
  }
7701
7919
  return (jsxRuntime.jsx(Tag, { closable: true, children: renderDisplay
7702
7920
  ? renderDisplay(item)
7703
7921
  : 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`)) }))] }));
7922
+ }) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formButtonLabels?.fieldRequired ?? formI18n.required() }))] }));
7705
7923
  };
7706
7924
 
7707
7925
  const NumberViewer = ({ schema, column, prefix, }) => {
@@ -7710,7 +7928,7 @@ const NumberViewer = ({ schema, column, prefix, }) => {
7710
7928
  const isRequired = required?.some((columnId) => columnId === column);
7711
7929
  const colLabel = `${prefix}${column}`;
7712
7930
  const value = watch(colLabel);
7713
- const formI18n = useFormI18n$1(column, prefix, schema);
7931
+ const formI18n = useFormI18n(column, prefix, schema);
7714
7932
  // Format the value for display if formatOptions are provided
7715
7933
  const formatValue = (val) => {
7716
7934
  if (val === undefined || val === null || val === '')
@@ -7736,7 +7954,7 @@ const ObjectViewer = ({ schema, column, prefix }) => {
7736
7954
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
7737
7955
  const colLabel = `${prefix}${column}`;
7738
7956
  const isRequired = required?.some((columnId) => columnId === column);
7739
- const formI18n = useFormI18n$1(column, prefix, schema);
7957
+ const formI18n = useFormI18n(column, prefix, schema);
7740
7958
  const { formState: { errors }, } = reactHookForm.useFormContext();
7741
7959
  if (properties === undefined) {
7742
7960
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -7758,7 +7976,7 @@ const RecordViewer = ({ column, schema, prefix }) => {
7758
7976
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
7759
7977
  const isRequired = required?.some((columnId) => columnId === column);
7760
7978
  const entries = Object.entries(getValues(column) ?? {});
7761
- const formI18n = useFormI18n$1(column, prefix, schema);
7979
+ const formI18n = useFormI18n(column, prefix, schema);
7762
7980
  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
7981
  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
7982
  }) })), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
@@ -7770,7 +7988,7 @@ const StringViewer = ({ column, schema, prefix, }) => {
7770
7988
  const isRequired = required?.some((columnId) => columnId === column);
7771
7989
  const colLabel = `${prefix}${column}`;
7772
7990
  const value = watch(colLabel);
7773
- const formI18n = useFormI18n$1(column, prefix, schema);
7991
+ const formI18n = useFormI18n(column, prefix, schema);
7774
7992
  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
7993
  };
7776
7994
 
@@ -7865,7 +8083,7 @@ const TextAreaViewer = ({ column, schema, prefix, }) => {
7865
8083
  const isRequired = required?.some((columnId) => columnId === column);
7866
8084
  const colLabel = `${prefix}${column}`;
7867
8085
  const value = watch(colLabel);
7868
- const formI18n = useFormI18n$1(column, prefix, schema);
8086
+ const formI18n = useFormI18n(column, prefix, schema);
7869
8087
  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
8088
  };
7871
8089
 
@@ -7876,7 +8094,7 @@ const TimeViewer = ({ column, schema, prefix }) => {
7876
8094
  const isRequired = required?.some((columnId) => columnId === column);
7877
8095
  const colLabel = `${prefix}${column}`;
7878
8096
  const selectedDate = watch(colLabel);
7879
- const formI18n = useFormI18n$1(column, prefix, schema);
8097
+ const formI18n = useFormI18n(column, prefix, schema);
7880
8098
  const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
7881
8099
  .tz(timezone)
7882
8100
  .isValid()
@@ -7893,7 +8111,7 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
7893
8111
  const isRequired = required?.some((columnId) => columnId === column);
7894
8112
  const colLabel = `${prefix}${column}`;
7895
8113
  const selectedDate = watch(colLabel);
7896
- const formI18n = useFormI18n$1(column, prefix, schema);
8114
+ const formI18n = useFormI18n(column, prefix, schema);
7897
8115
  const displayDate = dayjs(selectedDate)
7898
8116
  .tz(timezone)
7899
8117
  .format(displayDateFormat);
@@ -7987,7 +8205,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
7987
8205
  };
7988
8206
 
7989
8207
  const SubmitButton = () => {
7990
- const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
8208
+ const { setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
7991
8209
  const methods = reactHookForm.useFormContext();
7992
8210
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7993
8211
  const onValid = (data) => {
@@ -8016,11 +8234,11 @@ const SubmitButton = () => {
8016
8234
  };
8017
8235
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
8018
8236
  methods.handleSubmit(onValid)();
8019
- }, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
8237
+ }, formNoValidate: true, children: formButtonLabels?.submit ?? 'Submit' }));
8020
8238
  };
8021
8239
 
8022
8240
  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();
8241
+ const { schema, order, ignore, include, isError, isSubmiting, isConfirming, setIsConfirming, validatedData, error, customErrorRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8024
8242
  const { showSubmitButton, showResetButton } = displayConfig;
8025
8243
  const methods = reactHookForm.useFormContext();
8026
8244
  const { properties } = schema;
@@ -8037,21 +8255,6 @@ const FormBody = () => {
8037
8255
  ignore,
8038
8256
  include,
8039
8257
  });
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
8258
  if (isConfirming) {
8056
8259
  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
8260
  return (jsxRuntime.jsx(ColumnViewer
@@ -8061,9 +8264,9 @@ const FormBody = () => {
8061
8264
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
8062
8265
  }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: '2', children: [jsxRuntime.jsx(react.Button, { onClick: () => {
8063
8266
  setIsConfirming(false);
8064
- }, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
8267
+ }, variant: 'subtle', children: formButtonLabels?.cancel ?? 'Cancel' }), jsxRuntime.jsx(react.Button, { onClick: () => {
8065
8268
  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)] }));
8269
+ }, 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
8270
  }
8068
8271
  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
8272
  return (jsxRuntime.jsx(ColumnRenderer
@@ -8073,12 +8276,12 @@ const FormBody = () => {
8073
8276
  properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
8074
8277
  }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
8075
8278
  methods.reset();
8076
- }, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8279
+ }, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8077
8280
  };
8078
8281
 
8079
8282
  const FormTitle = () => {
8080
- const { translate } = useSchemaContext();
8081
- return jsxRuntime.jsx(react.Heading, { children: translate.t("title") });
8283
+ const { schema } = useSchemaContext();
8284
+ return jsxRuntime.jsx(react.Heading, { children: schema.title ?? 'Form' });
8082
8285
  };
8083
8286
 
8084
8287
  const DefaultForm = ({ formConfig, }) => {
@@ -8086,7 +8289,9 @@ const DefaultForm = ({ formConfig, }) => {
8086
8289
  return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
8087
8290
  };
8088
8291
 
8089
- const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8292
+ const useForm = ({ preLoadedValues, keyPrefix: _keyPrefix, // Deprecated: kept for backward compatibility
8293
+ namespace: _namespace, // Deprecated: kept for backward compatibility
8294
+ schema, }) => {
8090
8295
  const form = reactHookForm.useForm({
8091
8296
  values: preLoadedValues,
8092
8297
  resolver: schema ? ajvResolver(schema) : undefined,
@@ -8094,12 +8299,16 @@ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8094
8299
  reValidateMode: 'onBlur',
8095
8300
  });
8096
8301
  const [idMap, setIdMap] = React.useState({});
8097
- const translate = reactI18next.useTranslation(namespace || '', { keyPrefix });
8302
+ // Fallback translate object - returns key as-is (no i18n required)
8303
+ const translate = {
8304
+ t: (key) => key,
8305
+ ready: true,
8306
+ };
8098
8307
  return {
8099
8308
  form,
8100
8309
  idMap,
8101
8310
  setIdMap,
8102
- translate,
8311
+ translate, // Components prefer label objects over translate
8103
8312
  };
8104
8313
  };
8105
8314
 
@@ -8427,6 +8636,21 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
8427
8636
  })] }));
8428
8637
  };
8429
8638
 
8639
+ 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 = {}, }) => {
8640
+ const { tableLabel, table } = useDataTableContext();
8641
+ const { hasErrorText } = tableLabel;
8642
+ 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) => {
8643
+ const { column, options } = option;
8644
+ const tableColumn = table.getColumn(column);
8645
+ 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) => {
8646
+ if (tags.length === 0) {
8647
+ return tableColumn?.setFilterValue(undefined);
8648
+ }
8649
+ tableColumn?.setFilterValue(tags);
8650
+ } })] }, column));
8651
+ }) })), 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, {}) }))] }))] }));
8652
+ };
8653
+
8430
8654
  const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
8431
8655
  'use no memo';
8432
8656
  const { table } = useDataTableContext();
@@ -8486,7 +8710,68 @@ const TableRowSelectorSkeleton = () => {
8486
8710
  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
8711
  };
8488
8712
 
8713
+ const MobileTableDisplay = ({ showSelector = false, isLoading = false, }) => {
8714
+ const { table, rowSelection, setRowSelection } = useDataTableContext();
8715
+ if (isLoading) {
8716
+ return jsxRuntime.jsx(MobileTableSkeleton, { showSelector: showSelector });
8717
+ }
8718
+ return (jsxRuntime.jsx(react.Stack, { gap: 4, padding: 2, children: table.getRowModel().rows.map((row) => {
8719
+ 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),
8720
+ disabled: !canRowSelect(row),
8721
+ onCheckedChange: createRowToggleHandler(row, rowSelection, setRowSelection) }) })), jsxRuntime.jsx(react.Stack, { gap: 3, children: row.getVisibleCells().map((cell) => {
8722
+ const displayName = cell.column.columnDef.meta?.displayName ?? cell.column.id;
8723
+ 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}`));
8724
+ }) })] }) }, `mobile-table-card-${row.id}`));
8725
+ }) }));
8726
+ };
8727
+ const MobileTableSkeleton = ({ showSelector = false, }) => {
8728
+ const { table } = useDataTableContext();
8729
+ const pageSize = table.getState().pagination.pageSize;
8730
+ const visibleColumns = table.getVisibleLeafColumns();
8731
+ return (jsxRuntime.jsx(react.Stack, { gap: 4, padding: 2, children: Array.from({ length: pageSize }).map((_, rowIndex) => {
8732
+ 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) => {
8733
+ 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}`));
8734
+ }) })] }) }, `mobile-skeleton-${rowIndex}`));
8735
+ }) }));
8736
+ };
8737
+
8738
+ /**
8739
+ * Hook to detect if the current window width is mobile (< 768px)
8740
+ * @param breakpoint - The breakpoint in pixels to consider as mobile (default: 768)
8741
+ * @returns boolean indicating if the window is mobile
8742
+ */
8743
+ const useIsMobile = (breakpoint = 768) => {
8744
+ const [isMobile, setIsMobile] = React.useState(() => {
8745
+ if (typeof window === 'undefined')
8746
+ return false;
8747
+ return window.innerWidth < breakpoint;
8748
+ });
8749
+ React.useEffect(() => {
8750
+ if (typeof window === 'undefined')
8751
+ return;
8752
+ const handleResize = () => {
8753
+ setIsMobile(window.innerWidth < breakpoint);
8754
+ };
8755
+ // Set initial value
8756
+ handleResize();
8757
+ // Add event listener
8758
+ window.addEventListener('resize', handleResize);
8759
+ // Cleanup
8760
+ return () => {
8761
+ window.removeEventListener('resize', handleResize);
8762
+ };
8763
+ }, [breakpoint]);
8764
+ return isMobile;
8765
+ };
8766
+
8489
8767
  const DefaultTable = ({ showFooter = false, showHeader = true, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = 'greedy', isLoading = false, }) => {
8768
+ const isMobile = useIsMobile();
8769
+ // Early return for mobile display
8770
+ if (isMobile) {
8771
+ return (jsxRuntime.jsx(MobileTableControls, { ...controlProps, children: jsxRuntime.jsx(MobileTableDisplay, { showSelector: tableHeaderProps.showSelector ??
8772
+ tableBodyProps.showSelector ??
8773
+ false, isLoading: isLoading }) }));
8774
+ }
8490
8775
  const isGreedy = variant === 'greedy';
8491
8776
  const canResize = !isGreedy;
8492
8777
  const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: canResize })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps, canResize: canResize }));
@@ -8587,6 +8872,290 @@ const DataDisplay = ({ variant = '' }) => {
8587
8872
  }) }));
8588
8873
  };
8589
8874
 
8875
+ // Helper function to normalize date
8876
+ function normalizeDate(value) {
8877
+ if (!value)
8878
+ return null;
8879
+ if (value instanceof Date)
8880
+ return value;
8881
+ if (typeof value === 'string' || typeof value === 'number') {
8882
+ const date = dayjs(value).toDate();
8883
+ return isNaN(date.getTime()) ? null : date;
8884
+ }
8885
+ return null;
8886
+ }
8887
+ // Component to conditionally render event title based on available width
8888
+ function ResponsiveEventTitle({ title, placeholder, minWidth, minChars, cellRef, }) {
8889
+ const [truncatedText, setTruncatedText] = React.useState('');
8890
+ const measureRef = React.useRef(null);
8891
+ React.useEffect(() => {
8892
+ const calculateTruncatedText = () => {
8893
+ if (!cellRef.current || !measureRef.current || !title) {
8894
+ setTruncatedText(title || 'Event');
8895
+ return;
8896
+ }
8897
+ const cellWidth = cellRef.current.clientWidth;
8898
+ // Account for padding (approximately 8px on each side)
8899
+ const availableWidth = cellWidth - 16;
8900
+ // If cell is too narrow, calculate how many characters can fit
8901
+ if (availableWidth < minWidth) {
8902
+ // Measure text width using canvas
8903
+ const canvas = document.createElement('canvas');
8904
+ const context = canvas.getContext('2d');
8905
+ if (!context) {
8906
+ setTruncatedText(placeholder);
8907
+ return;
8908
+ }
8909
+ // Get computed font style from the element
8910
+ const computedStyle = window.getComputedStyle(measureRef.current);
8911
+ context.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
8912
+ const ellipsisWidth = context.measureText('...').width;
8913
+ const maxWidth = availableWidth - ellipsisWidth;
8914
+ // Try to show at least minChars characters before ellipsis
8915
+ let truncated = '';
8916
+ let charCount = 0;
8917
+ // Calculate how many characters can fit
8918
+ for (let i = 0; i < Math.min(title.length, 50); i++) {
8919
+ const testText = title.substring(0, i + 1);
8920
+ const textWidth = context.measureText(testText).width;
8921
+ if (textWidth <= maxWidth) {
8922
+ truncated = testText;
8923
+ charCount = i + 1;
8924
+ }
8925
+ else {
8926
+ break;
8927
+ }
8928
+ }
8929
+ // Ensure we show at least minChars characters if possible
8930
+ if (charCount < minChars && title.length >= minChars) {
8931
+ truncated = title.substring(0, minChars);
8932
+ }
8933
+ else if (charCount === 0 && title.length >= 1) {
8934
+ truncated = title.substring(0, 1);
8935
+ }
8936
+ // Only show ellipsis if we have at least minChars characters
8937
+ if (truncated && truncated.length >= minChars) {
8938
+ setTruncatedText(`${truncated}...`);
8939
+ }
8940
+ else {
8941
+ setTruncatedText(placeholder);
8942
+ }
8943
+ }
8944
+ else {
8945
+ // Full width available, show full title
8946
+ setTruncatedText(title);
8947
+ }
8948
+ };
8949
+ calculateTruncatedText();
8950
+ const resizeObserver = new ResizeObserver(calculateTruncatedText);
8951
+ if (cellRef.current) {
8952
+ resizeObserver.observe(cellRef.current);
8953
+ }
8954
+ // Also check on window resize
8955
+ window.addEventListener('resize', calculateTruncatedText);
8956
+ return () => {
8957
+ resizeObserver.disconnect();
8958
+ window.removeEventListener('resize', calculateTruncatedText);
8959
+ };
8960
+ }, [cellRef, minWidth, title, placeholder]);
8961
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { ref: measureRef, style: {
8962
+ visibility: 'hidden',
8963
+ position: 'absolute',
8964
+ whiteSpace: 'nowrap',
8965
+ }, children: title || 'Event' }), truncatedText || title || 'Event'] }));
8966
+ }
8967
+ function CalendarDisplay({ dateColumn, getDate, getEventTitle, getEventColor, renderEvent, firstDayOfWeek = 0, showOutsideDays = true, monthsToDisplay = 1, labels = {
8968
+ monthNamesShort: [
8969
+ 'Jan',
8970
+ 'Feb',
8971
+ 'Mar',
8972
+ 'Apr',
8973
+ 'May',
8974
+ 'Jun',
8975
+ 'Jul',
8976
+ 'Aug',
8977
+ 'Sep',
8978
+ 'Oct',
8979
+ 'Nov',
8980
+ 'Dec',
8981
+ ],
8982
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
8983
+ backButtonLabel: 'Back',
8984
+ forwardButtonLabel: 'Next',
8985
+ }, onDateClick, onEventClick, maxEventsPerDay = 3, colorPalette = 'blue', eventPlaceholder = '...', minEventWidth = 80, minCharsBeforeEllipsis = 2, }) {
8986
+ const { data, table } = useDataTableContext();
8987
+ // Map table data to events
8988
+ const events = React.useMemo(() => {
8989
+ return data
8990
+ .map((row) => {
8991
+ let dateValue;
8992
+ if (getDate) {
8993
+ dateValue = getDate(row);
8994
+ }
8995
+ else {
8996
+ // Try to get date from column
8997
+ const rowData = table
8998
+ .getRowModel()
8999
+ .rows.find((r) => r.original === row);
9000
+ if (rowData) {
9001
+ const cell = rowData.getAllCells().find((c) => {
9002
+ const colId = c.column.id;
9003
+ const accessorKey = c.column.columnDef.accessorKey;
9004
+ return colId === dateColumn || accessorKey === dateColumn;
9005
+ });
9006
+ dateValue = cell?.getValue();
9007
+ }
9008
+ }
9009
+ const date = normalizeDate(dateValue);
9010
+ if (!date)
9011
+ return null;
9012
+ let title;
9013
+ if (getEventTitle) {
9014
+ title = getEventTitle(row);
9015
+ }
9016
+ else {
9017
+ // Use first column's value as title
9018
+ const rowData = table
9019
+ .getRowModel()
9020
+ .rows.find((r) => r.original === row);
9021
+ if (rowData) {
9022
+ const firstCell = rowData.getAllCells()[0];
9023
+ title = String(firstCell?.getValue() ?? '');
9024
+ }
9025
+ }
9026
+ const color = getEventColor?.(row);
9027
+ return {
9028
+ data: row,
9029
+ date,
9030
+ title,
9031
+ color,
9032
+ };
9033
+ })
9034
+ .filter((event) => event !== null);
9035
+ }, [data, table, dateColumn, getDate, getEventTitle, getEventColor]);
9036
+ // Group events by date
9037
+ const eventsByDate = React.useMemo(() => {
9038
+ const map = new Map();
9039
+ events.forEach((event) => {
9040
+ const dateKey = `${event.date.getFullYear()}-${event.date.getMonth()}-${event.date.getDate()}`;
9041
+ if (!map.has(dateKey)) {
9042
+ map.set(dateKey, []);
9043
+ }
9044
+ map.get(dateKey).push(event);
9045
+ });
9046
+ return map;
9047
+ }, [events]);
9048
+ // Get events for a specific date
9049
+ const getEventsForDate = React.useCallback((date) => {
9050
+ const dateKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
9051
+ return eventsByDate.get(dateKey) ?? [];
9052
+ }, [eventsByDate]);
9053
+ const calendarData = useCalendar({
9054
+ firstDayOfWeek,
9055
+ showOutsideDays,
9056
+ monthsToDisplay,
9057
+ });
9058
+ const getDateProps = React.useCallback((props) => {
9059
+ const dateEvents = getEventsForDate(props.dateObj.date);
9060
+ const baseProps = calendarData.getDateProps({ dateObj: props.dateObj });
9061
+ return {
9062
+ ...baseProps,
9063
+ onClick: () => {
9064
+ baseProps.onClick?.();
9065
+ if (onDateClick) {
9066
+ onDateClick(props.dateObj.date, dateEvents);
9067
+ }
9068
+ },
9069
+ };
9070
+ }, [calendarData, getEventsForDate, onDateClick]);
9071
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
9072
+ if (!calendarData.calendars.length) {
9073
+ return null;
9074
+ }
9075
+ 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({
9076
+ calendars: calendarData.calendars,
9077
+ offset: 12,
9078
+ }), children: '<<' }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getBackProps({ calendars: calendarData.calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getForwardProps({
9079
+ calendars: calendarData.calendars,
9080
+ }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...calendarData.getForwardProps({
9081
+ calendars: calendarData.calendars,
9082
+ offset: 12,
9083
+ }), children: '>>' })] }), jsxRuntime.jsx(react.Grid, { templateColumns: {
9084
+ base: '1fr',
9085
+ md: monthsToDisplay >= 2 ? 'repeat(2, 1fr)' : '1fr',
9086
+ lg: monthsToDisplay >= 3
9087
+ ? 'repeat(3, 1fr)'
9088
+ : monthsToDisplay === 2
9089
+ ? 'repeat(2, 1fr)'
9090
+ : '1fr',
9091
+ xl: `repeat(${Math.min(monthsToDisplay, 4)}, 1fr)`,
9092
+ }, 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) => {
9093
+ const weekday = (weekdayNum + firstDayOfWeek) % 7;
9094
+ 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}`));
9095
+ }) }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
9096
+ const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
9097
+ if (!dateObj) {
9098
+ return jsxRuntime.jsx(react.Box, {}, key);
9099
+ }
9100
+ const { date, today, isCurrentMonth } = dateObj;
9101
+ const dateEvents = getEventsForDate(date);
9102
+ const cellRef = React.useRef(null);
9103
+ 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: {
9104
+ base: today ? `${colorPalette}.300` : 'gray.200',
9105
+ _dark: today ? `${colorPalette}.700` : 'gray.700',
9106
+ }, borderRadius: { base: 'sm', md: 'md' }, padding: { base: 0.5, md: 1 }, bgColor: {
9107
+ base: today ? `${colorPalette}.50` : 'white',
9108
+ _dark: today ? `${colorPalette}.950` : 'gray.900',
9109
+ }, opacity: isCurrentMonth ? 1 : 0.5, ...getDateProps({ dateObj }), cursor: onDateClick ? 'pointer' : 'default', _hover: onDateClick
9110
+ ? {
9111
+ bgColor: {
9112
+ base: `${colorPalette}.100`,
9113
+ _dark: `${colorPalette}.900`,
9114
+ },
9115
+ }
9116
+ : {}, children: [jsxRuntime.jsx(react.Text, { fontSize: { base: 'xs', md: 'sm' }, fontWeight: today ? 'bold' : 'normal', color: {
9117
+ base: today ? `${colorPalette}.700` : 'gray.700',
9118
+ _dark: today ? `${colorPalette}.300` : 'gray.300',
9119
+ }, 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
9120
+ .slice(0, maxEventsPerDay)
9121
+ .map((event, eventIndex) => {
9122
+ 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: {
9123
+ base: event.color
9124
+ ? `${event.color}.100`
9125
+ : `${colorPalette}.100`,
9126
+ _dark: event.color
9127
+ ? `${event.color}.900`
9128
+ : `${colorPalette}.900`,
9129
+ }, color: {
9130
+ base: event.color
9131
+ ? `${event.color}.800`
9132
+ : `${colorPalette}.800`,
9133
+ _dark: event.color
9134
+ ? `${event.color}.200`
9135
+ : `${colorPalette}.200`,
9136
+ }, onClick: (e) => {
9137
+ e.stopPropagation();
9138
+ if (onEventClick) {
9139
+ onEventClick(event);
9140
+ }
9141
+ }, cursor: onEventClick ? 'pointer' : 'default', _hover: onEventClick
9142
+ ? {
9143
+ opacity: 0.8,
9144
+ }
9145
+ : {}, children: jsxRuntime.jsx(ResponsiveEventTitle, { title: event.title, placeholder: eventPlaceholder, minWidth: minEventWidth, minChars: minCharsBeforeEllipsis, cellRef: cellRef }) }, eventIndex));
9146
+ return (jsxRuntime.jsx(react.Box, { onClick: (e) => e.stopPropagation(), children: eventContent }, eventIndex));
9147
+ }), dateEvents.length > maxEventsPerDay && (jsxRuntime.jsxs(react.Text, { fontSize: "xs", color: {
9148
+ base: `${colorPalette}.600`,
9149
+ _dark: `${colorPalette}.400`,
9150
+ }, paddingX: 1, onClick: (e) => {
9151
+ e.stopPropagation();
9152
+ if (onDateClick) {
9153
+ onDateClick(date, dateEvents);
9154
+ }
9155
+ }, cursor: onDateClick ? 'pointer' : 'default', children: ["+", dateEvents.length - maxEventsPerDay, " more"] }))] })] }, key));
9156
+ })) })] }, `${calendar.month}${calendar.year}`))) })] }));
9157
+ }
9158
+
8590
9159
  // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
8591
9160
  // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
8592
9161
  // end of TS setup!
@@ -8687,7 +9256,7 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
8687
9256
  *
8688
9257
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8689
9258
  */
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 = {
9259
+ 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
9260
  view: 'View',
8692
9261
  edit: 'Edit',
8693
9262
  filterButtonText: 'Filter',
@@ -8698,7 +9267,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8698
9267
  reloadButtonText: 'Reload',
8699
9268
  resetSelection: 'Reset Selection',
8700
9269
  resetSorting: 'Reset Sorting',
8701
- rowCountText: 'Row Count',
9270
+ rowCountText: '',
8702
9271
  hasErrorText: 'Has Error',
8703
9272
  globalFilterPlaceholder: 'Search',
8704
9273
  trueLabel: 'True',
@@ -8755,7 +9324,6 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8755
9324
  globalFilter,
8756
9325
  setGlobalFilter,
8757
9326
  type: 'client',
8758
- translate,
8759
9327
  columns: columns,
8760
9328
  sorting,
8761
9329
  setSorting,
@@ -8787,22 +9355,22 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8787
9355
  *
8788
9356
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8789
9357
  */
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",
9358
+ 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 = {
9359
+ view: 'View',
9360
+ edit: 'Edit',
9361
+ filterButtonText: 'Filter',
9362
+ filterTitle: 'Filter',
9363
+ filterReset: 'Reset',
9364
+ filterClose: 'Close',
9365
+ reloadTooltip: 'Reload',
9366
+ reloadButtonText: 'Reload',
9367
+ resetSelection: 'Reset Selection',
9368
+ resetSorting: 'Reset Sorting',
9369
+ rowCountText: '',
9370
+ hasErrorText: 'Has Error',
9371
+ globalFilterPlaceholder: 'Search',
9372
+ trueLabel: 'True',
9373
+ falseLabel: 'False',
8806
9374
  }, }) {
8807
9375
  const table = reactTable.useReactTable({
8808
9376
  _features: [DensityFeature],
@@ -8812,7 +9380,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8812
9380
  getCoreRowModel: reactTable.getCoreRowModel(),
8813
9381
  manualPagination: true,
8814
9382
  manualSorting: true,
8815
- columnResizeMode: "onChange",
9383
+ columnResizeMode: 'onChange',
8816
9384
  defaultColumn: {
8817
9385
  size: 150, //starting column size
8818
9386
  minSize: 10, //enforced during column resizing
@@ -8855,8 +9423,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8855
9423
  table: table,
8856
9424
  globalFilter,
8857
9425
  setGlobalFilter,
8858
- type: "server",
8859
- translate,
9426
+ type: 'server',
8860
9427
  columns: columns,
8861
9428
  sorting,
8862
9429
  setSorting,
@@ -8874,9 +9441,10 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8874
9441
  setColumnVisibility,
8875
9442
  data: query.data?.data ?? [],
8876
9443
  tableLabel,
8877
- }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
9444
+ }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url: url ?? '', query }, children: children }) }));
8878
9445
  }
8879
9446
 
9447
+ exports.CalendarDisplay = CalendarDisplay;
8880
9448
  exports.CardHeader = CardHeader;
8881
9449
  exports.DataDisplay = DataDisplay;
8882
9450
  exports.DataTable = DataTable;