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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts +166 -41
  3. package/dist/index.js +1151 -612
  4. package/dist/index.mjs +1153 -615
  5. package/dist/types/components/DataTable/DataTable.d.ts +1 -3
  6. package/dist/types/components/DataTable/DataTableServer.d.ts +7 -9
  7. package/dist/types/components/DataTable/context/DataTableContext.d.ts +4 -6
  8. package/dist/types/components/DataTable/controls/MobileTableControls.d.ts +29 -0
  9. package/dist/types/components/DataTable/controls/TableControls.d.ts +2 -2
  10. package/dist/types/components/DataTable/display/CalendarDisplay.d.ts +84 -0
  11. package/dist/types/components/DataTable/display/DataDisplay.d.ts +0 -2
  12. package/dist/types/components/DataTable/display/MobileTableDisplay.d.ts +5 -0
  13. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +1 -3
  14. package/dist/types/components/DataTable/hooks/useIsMobile.d.ts +6 -0
  15. package/dist/types/components/DataTable/useDataTable.d.ts +3 -6
  16. package/dist/types/components/DataTable/useDataTableServer.d.ts +4 -4
  17. package/dist/types/components/DataTable/utils/getColumns.d.ts +3 -5
  18. package/dist/types/components/DatePicker/DatePicker.d.ts +7 -8
  19. package/dist/types/components/DatePicker/DateTimePicker.d.ts +3 -1
  20. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +5 -1
  21. package/dist/types/components/DatePicker/RangeDatePicker.d.ts +4 -4
  22. package/dist/types/components/DatePicker/useCalendar.d.ts +48 -0
  23. package/dist/types/components/Form/SchemaFormContext.d.ts +5 -3
  24. package/dist/types/components/Form/components/core/FormBody.d.ts +1 -2
  25. package/dist/types/components/Form/components/core/FormRoot.d.ts +6 -4
  26. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -2
  27. package/dist/types/components/Form/components/fields/IdPicker.d.ts +8 -0
  28. package/dist/types/components/Form/components/fields/IdPickerMultiple.d.ts +7 -0
  29. package/dist/types/components/Form/components/fields/IdPickerSingle.d.ts +7 -0
  30. package/dist/types/components/Form/components/fields/useIdPickerData.d.ts +46 -0
  31. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +9 -0
  32. package/dist/types/components/Form/useForm.d.ts +7 -2
  33. package/dist/types/components/Form/utils/useFormI18n.d.ts +14 -12
  34. package/dist/types/components/TimePicker/TimePicker.d.ts +4 -6
  35. package/dist/types/components/ui/provider.d.ts +1 -1
  36. package/dist/types/index.d.ts +1 -0
  37. package/package.json +1 -3
package/dist/index.mjs CHANGED
@@ -1,14 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, CheckboxCard as CheckboxCard$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Clipboard, Badge, Link, Tag as Tag$1, Image, Alert, Field as Field$1, Popover, useFilter, useListCollection, Combobox, Tabs, Skeleton, NumberInput, Show, RadioCard, CheckboxGroup, InputGroup as InputGroup$1, Center, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, CheckboxCard as CheckboxCard$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Clipboard, Badge, Link, Tag as Tag$1, Image, Alert, Field as Field$1, Popover, useFilter, useListCollection, Combobox, Tabs, Skeleton, NumberInput, Show, RadioCard, CheckboxGroup, InputGroup as InputGroup$1, Center, Heading, Stack } from '@chakra-ui/react';
3
3
  import { AiOutlineColumnWidth } from 'react-icons/ai';
4
4
  import * as React from 'react';
5
- import React__default, { createContext, useContext, useState, useEffect, useRef, useMemo, forwardRef, useCallback } from 'react';
5
+ import { createContext, useContext, useState, useMemo, useCallback, useEffect, useRef, forwardRef } from 'react';
6
6
  import { LuX, LuCheck, LuChevronRight, LuCopy, LuExternalLink, LuSearch, LuImage, LuFile } from 'react-icons/lu';
7
7
  import { MdOutlineSort, MdFilterAlt, MdSearch, MdOutlineChecklist, MdClear, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdDateRange } from 'react-icons/md';
8
8
  import { FaUpDown, FaGripLinesVertical, FaTrash } from 'react-icons/fa6';
9
9
  import { BiDownArrow, BiUpArrow, BiError } from 'react-icons/bi';
10
10
  import { CgClose, CgTrash } from 'react-icons/cg';
11
- import Dayzed from '@bsol-oss/dayzed-react19';
12
11
  import { HiMiniEllipsisHorizontal, HiChevronLeft, HiChevronRight } from 'react-icons/hi2';
13
12
  import { IoMdEye, IoMdCheckbox, IoMdClock } from 'react-icons/io';
14
13
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
@@ -24,7 +23,6 @@ import { BsExclamationCircleFill, BsClock } from 'react-icons/bs';
24
23
  import { HiColorSwatch } from 'react-icons/hi';
25
24
  import { flexRender, createColumnHelper, makeStateUpdater, functionalUpdate, useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel } from '@tanstack/react-table';
26
25
  import { GrAscend, GrDescend } from 'react-icons/gr';
27
- import { useTranslation } from 'react-i18next';
28
26
  import axios from 'axios';
29
27
  import { FormProvider, useFormContext, useForm as useForm$1 } from 'react-hook-form';
30
28
  import Ajv from 'ajv';
@@ -38,36 +36,35 @@ import { rankItem } from '@tanstack/match-sorter-utils';
38
36
 
39
37
  const DataTableContext = createContext({
40
38
  table: {},
41
- globalFilter: "",
39
+ globalFilter: '',
42
40
  setGlobalFilter: () => { },
43
- type: "client",
44
- translate: {},
41
+ type: 'client',
45
42
  data: [],
46
43
  columns: [],
47
44
  columnOrder: [],
48
45
  columnFilters: [],
49
- density: "sm",
46
+ density: 'sm',
50
47
  sorting: [],
51
48
  setPagination: function () {
52
- throw new Error("Function not implemented.");
49
+ throw new Error('Function not implemented.');
53
50
  },
54
51
  setSorting: function () {
55
- throw new Error("Function not implemented.");
52
+ throw new Error('Function not implemented.');
56
53
  },
57
54
  setColumnFilters: function () {
58
- throw new Error("Function not implemented.");
55
+ throw new Error('Function not implemented.');
59
56
  },
60
57
  setRowSelection: function () {
61
- throw new Error("Function not implemented.");
58
+ throw new Error('Function not implemented.');
62
59
  },
63
60
  setColumnOrder: function () {
64
- throw new Error("Function not implemented.");
61
+ throw new Error('Function not implemented.');
65
62
  },
66
63
  setDensity: function () {
67
- throw new Error("Function not implemented.");
64
+ throw new Error('Function not implemented.');
68
65
  },
69
66
  setColumnVisibility: function () {
70
- throw new Error("Function not implemented.");
67
+ throw new Error('Function not implemented.');
71
68
  },
72
69
  pagination: {
73
70
  pageIndex: 0,
@@ -76,21 +73,21 @@ const DataTableContext = createContext({
76
73
  rowSelection: {},
77
74
  columnVisibility: {},
78
75
  tableLabel: {
79
- view: "View",
80
- edit: "Edit",
81
- filterButtonText: "Filter",
82
- filterTitle: "Filter",
83
- filterReset: "Reset",
84
- filterClose: "Close",
85
- reloadTooltip: "Reload",
86
- reloadButtonText: "Reload",
87
- resetSelection: "Reset Selection",
88
- resetSorting: "Reset Sorting",
89
- rowCountText: "Row Count",
90
- hasErrorText: "Has Error",
91
- globalFilterPlaceholder: "Search",
92
- trueLabel: "True",
93
- falseLabel: "False",
76
+ view: 'View',
77
+ edit: 'Edit',
78
+ filterButtonText: 'Filter',
79
+ filterTitle: 'Filter',
80
+ filterReset: 'Reset',
81
+ filterClose: 'Close',
82
+ reloadTooltip: 'Reload',
83
+ reloadButtonText: 'Reload',
84
+ resetSelection: 'Reset Selection',
85
+ resetSorting: 'Reset Sorting',
86
+ rowCountText: '',
87
+ hasErrorText: 'Has Error',
88
+ globalFilterPlaceholder: 'Search',
89
+ trueLabel: 'True',
90
+ falseLabel: 'False',
94
91
  },
95
92
  });
96
93
 
@@ -167,6 +164,166 @@ const Radio = React.forwardRef(function Radio(props, ref) {
167
164
  });
168
165
  const RadioGroup = RadioGroup$1.Root;
169
166
 
167
+ // Helper function to check if two dates are the same day
168
+ function isSameDay(date1, date2) {
169
+ return (date1.getFullYear() === date2.getFullYear() &&
170
+ date1.getMonth() === date2.getMonth() &&
171
+ date1.getDate() === date2.getDate());
172
+ }
173
+ // Helper function to check if a date is today
174
+ function isToday(date) {
175
+ const today = new Date();
176
+ return isSameDay(date, today);
177
+ }
178
+ // Helper function to check if a date is selected
179
+ function isSelected(date, selected) {
180
+ if (!selected)
181
+ return false;
182
+ if (Array.isArray(selected)) {
183
+ return selected.some((d) => isSameDay(d, date));
184
+ }
185
+ return isSameDay(selected, date);
186
+ }
187
+ // Helper function to check if a date is selectable
188
+ function isSelectable(date, minDate, maxDate) {
189
+ if (minDate) {
190
+ // Normalize to start of day for comparison
191
+ const minDateStart = new Date(minDate);
192
+ minDateStart.setHours(0, 0, 0, 0);
193
+ const dateStart = new Date(date);
194
+ dateStart.setHours(0, 0, 0, 0);
195
+ if (dateStart < minDateStart)
196
+ return false;
197
+ }
198
+ if (maxDate) {
199
+ // Normalize to start of day for comparison
200
+ const maxDateStart = new Date(maxDate);
201
+ maxDateStart.setHours(0, 0, 0, 0);
202
+ const dateStart = new Date(date);
203
+ dateStart.setHours(0, 0, 0, 0);
204
+ if (dateStart > maxDateStart)
205
+ return false;
206
+ }
207
+ return true;
208
+ }
209
+ // Generate calendar weeks for a given month
210
+ function generateCalendarWeeks(year, month, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate) {
211
+ const weeks = [];
212
+ const firstDay = new Date(year, month, 1);
213
+ const lastDay = new Date(year, month + 1, 0);
214
+ // Get the first day of the week for the first day of the month
215
+ let firstDayWeekday = firstDay.getDay();
216
+ // Adjust for firstDayOfWeek
217
+ firstDayWeekday = (firstDayWeekday - firstDayOfWeek + 7) % 7;
218
+ // Start from the first day of the week that contains the first day of the month
219
+ const startDate = new Date(firstDay);
220
+ startDate.setDate(startDate.getDate() - firstDayWeekday);
221
+ let currentDate = new Date(startDate);
222
+ const endDate = new Date(lastDay);
223
+ // Find the last day of the week that contains the last day of the month
224
+ let lastDayWeekday = lastDay.getDay();
225
+ lastDayWeekday = (lastDayWeekday - firstDayOfWeek + 7) % 7;
226
+ endDate.setDate(endDate.getDate() + (6 - lastDayWeekday));
227
+ while (currentDate <= endDate) {
228
+ const week = [];
229
+ for (let i = 0; i < 7; i++) {
230
+ const date = new Date(currentDate);
231
+ const isCurrentMonth = date.getMonth() === month;
232
+ if (!showOutsideDays && !isCurrentMonth) {
233
+ week.push(null);
234
+ }
235
+ else {
236
+ const calendarDate = {
237
+ date,
238
+ selected: isSelected(date, selected),
239
+ selectable: isSelectable(date, minDate, maxDate) &&
240
+ (showOutsideDays || isCurrentMonth),
241
+ today: isToday(date),
242
+ isCurrentMonth,
243
+ };
244
+ week.push(calendarDate);
245
+ }
246
+ currentDate.setDate(currentDate.getDate() + 1);
247
+ }
248
+ weeks.push(week);
249
+ }
250
+ return weeks;
251
+ }
252
+ // Generate calendars for the given months
253
+ function generateCalendars(startDate, monthsToDisplay, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate) {
254
+ const calendars = [];
255
+ const currentDate = new Date(startDate);
256
+ for (let i = 0; i < monthsToDisplay; i++) {
257
+ const year = currentDate.getFullYear();
258
+ const month = currentDate.getMonth();
259
+ const weeks = generateCalendarWeeks(year, month, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate);
260
+ calendars.push({
261
+ month,
262
+ year,
263
+ weeks,
264
+ });
265
+ // Move to next month
266
+ currentDate.setMonth(month + 1);
267
+ }
268
+ return calendars;
269
+ }
270
+ function useCalendar({ selected, firstDayOfWeek = 0, showOutsideDays = true, date, minDate, maxDate, monthsToDisplay = 1, onDateSelected, }) {
271
+ const [currentDate, setCurrentDate] = useState(() => {
272
+ return date ? new Date(date) : new Date();
273
+ });
274
+ const calendars = useMemo(() => {
275
+ return generateCalendars(currentDate, monthsToDisplay, firstDayOfWeek, showOutsideDays, selected, minDate, maxDate);
276
+ }, [
277
+ currentDate,
278
+ monthsToDisplay,
279
+ firstDayOfWeek,
280
+ showOutsideDays,
281
+ selected,
282
+ minDate,
283
+ maxDate,
284
+ ]);
285
+ const navigate = useCallback((offset) => {
286
+ setCurrentDate((prev) => {
287
+ const newDate = new Date(prev);
288
+ newDate.setMonth(prev.getMonth() + offset);
289
+ return newDate;
290
+ });
291
+ }, []);
292
+ const getBackProps = useCallback((props) => {
293
+ return {
294
+ onClick: () => {
295
+ navigate(-(props?.offset || 1));
296
+ },
297
+ };
298
+ }, [navigate]);
299
+ const getForwardProps = useCallback((props) => {
300
+ return {
301
+ onClick: () => {
302
+ navigate(props?.offset || 1);
303
+ },
304
+ };
305
+ }, [navigate]);
306
+ const getDateProps = useCallback((props) => {
307
+ return {
308
+ onClick: () => {
309
+ if (props.dateObj.selectable && onDateSelected) {
310
+ onDateSelected({
311
+ date: props.dateObj.date,
312
+ selected: selected || props.dateObj.date,
313
+ });
314
+ }
315
+ },
316
+ onMouseEnter: props.onMouseEnter,
317
+ };
318
+ }, [onDateSelected, selected]);
319
+ return {
320
+ calendars,
321
+ getBackProps,
322
+ getForwardProps,
323
+ getDateProps,
324
+ };
325
+ }
326
+
170
327
  const RangeDatePickerContext = createContext({
171
328
  labels: {
172
329
  monthNamesFull: [
@@ -232,7 +389,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
232
389
  if (!dateObj) {
233
390
  return jsx(Box, {}, key);
234
391
  }
235
- const { date, selected, selectable, today } = dateObj;
392
+ const { date, selected, selectable, today, isCurrentMonth, } = dateObj;
236
393
  const getStyle = ({ selected, unavailable, today, isInRange, }) => {
237
394
  if (unavailable) {
238
395
  return {
@@ -270,7 +427,7 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
270
427
  unavailable: !selectable,
271
428
  today,
272
429
  isInRange: isInRange(date),
273
- }), children: selectable ? date.getDate() : 'X' }, key));
430
+ }), opacity: isCurrentMonth ? 1 : 0.4, children: selectable ? date.getDate() : 'X' }, key));
274
431
  })) })] }, `${calendar.month}${calendar.year}`))) })] }));
275
432
  }
276
433
  return null;
@@ -293,10 +450,57 @@ const RangeDatePicker = ({ labels = {
293
450
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
294
451
  backButtonLabel: 'Back',
295
452
  forwardButtonLabel: 'Next',
296
- }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, ...rest }) => {
297
- return (jsx(RangeDatePickerContext.Provider, { value: { labels }, children: jsx(Dayzed, { onDateSelected: onDateSelected, selected: selected, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, date: date, minDate: minDate, maxDate: maxDate, monthsToDisplay: monthsToDisplay, ...rest, render: (dayzedData) => (jsx(Calendar$1, { ...dayzedData,
298
- firstDayOfWeek,
299
- selected: selected })) }) }));
453
+ }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, render, }) => {
454
+ const handleDateSelected = (obj) => {
455
+ if (onDateSelected) {
456
+ const dateObj = obj.date;
457
+ const currentSelected = Array.isArray(obj.selected)
458
+ ? obj.selected
459
+ : [obj.selected];
460
+ // Range selection logic: if one date selected, add second; if two selected, replace with new date
461
+ let newSelected;
462
+ if (currentSelected.length === 0) {
463
+ newSelected = [dateObj];
464
+ }
465
+ else if (currentSelected.length === 1) {
466
+ const firstDate = currentSelected[0];
467
+ if (dateObj < firstDate) {
468
+ newSelected = [dateObj, firstDate];
469
+ }
470
+ else {
471
+ newSelected = [firstDate, dateObj];
472
+ }
473
+ }
474
+ else {
475
+ newSelected = [dateObj];
476
+ }
477
+ // Check if date is selectable
478
+ const selectable = !minDate || dateObj >= minDate;
479
+ if (maxDate) {
480
+ const isSelectable = dateObj <= maxDate;
481
+ if (!isSelectable)
482
+ return;
483
+ }
484
+ onDateSelected({
485
+ selected: newSelected,
486
+ selectable,
487
+ date: dateObj,
488
+ });
489
+ }
490
+ };
491
+ const calendarData = useCalendar({
492
+ onDateSelected: handleDateSelected,
493
+ selected,
494
+ firstDayOfWeek,
495
+ showOutsideDays,
496
+ date,
497
+ minDate,
498
+ maxDate,
499
+ monthsToDisplay,
500
+ });
501
+ return (jsx(RangeDatePickerContext.Provider, { value: { labels }, children: render ? (render(calendarData)) : (jsx(Calendar$1, { ...calendarData,
502
+ firstDayOfWeek,
503
+ selected: selected })) }));
300
504
  };
301
505
 
302
506
  const getRangeDates = ({ selectable, date, selectedDates, }) => {
@@ -532,7 +736,7 @@ const MenuTrigger = Menu.Trigger;
532
736
 
533
737
  const PageSizeControl = ({ pageSizes = [10, 20, 30, 40, 50], }) => {
534
738
  const { table } = useDataTableContext();
535
- return (jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", gap: "0.5rem", children: [table.getState().pagination.pageSize, " ", jsx(BiDownArrow, {})] }) }), jsx(MenuContent, { children: pageSizes.map((pageSize) => (jsx(MenuItem, { value: `chakra-table-pageSize-${pageSize}`, onClick: () => {
739
+ return (jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsx(Button$1, { variant: 'ghost', gap: '0.5rem', children: table.getState().pagination.pageSize }) }), jsx(MenuContent, { children: pageSizes.map((pageSize) => (jsx(MenuItem, { value: `chakra-table-pageSize-${pageSize}`, onClick: () => {
536
740
  table.setPageSize(Number(pageSize));
537
741
  }, children: pageSize }, `chakra-table-pageSize-${pageSize}`))) })] }));
538
742
  };
@@ -560,81 +764,149 @@ const PaginationRoot = React.forwardRef(function PaginationRoot(props, ref) {
560
764
  }
561
765
  const container = containerRef.current;
562
766
  let rafId = null;
563
- const calculateSiblingCount = () => {
564
- if (!container)
565
- return;
566
- const width = container.offsetWidth;
567
- if (width === 0)
568
- return;
569
- // Estimate button width based on size
570
- // These are approximate widths including padding for different button sizes
767
+ let timeoutId = null;
768
+ const measureButtonWidth = () => {
769
+ // Try to measure actual rendered buttons for accuracy
770
+ // Look for page number buttons (they contain numeric text)
771
+ const allButtons = container.querySelectorAll('button');
772
+ const pageButtons = [];
773
+ allButtons.forEach((button) => {
774
+ const text = button.textContent?.trim();
775
+ // Page buttons contain numbers, prev/next buttons contain icons
776
+ if (text && /^\d+$/.test(text)) {
777
+ pageButtons.push(button);
778
+ }
779
+ });
780
+ if (pageButtons.length > 0) {
781
+ // Measure multiple buttons and take the average for accuracy
782
+ let totalWidth = 0;
783
+ let count = 0;
784
+ pageButtons.forEach((button) => {
785
+ const width = button.offsetWidth;
786
+ if (width > 0) {
787
+ totalWidth += width;
788
+ count++;
789
+ }
790
+ });
791
+ if (count > 0) {
792
+ return Math.ceil(totalWidth / count);
793
+ }
794
+ }
795
+ // Fallback to estimated widths based on size
571
796
  const buttonWidthMap = {
572
797
  xs: 28,
573
798
  sm: 36,
574
799
  md: 40,
575
800
  lg: 44,
576
801
  };
577
- let buttonWidth = buttonWidthMap[size] || 36;
578
- // Try to measure actual button if available (for more accuracy)
579
- const buttons = container.querySelectorAll('button');
580
- if (buttons.length > 0) {
581
- const firstButton = buttons[0];
582
- if (firstButton.offsetWidth > 0) {
583
- // Use measured width, but account for text content variation
584
- const measuredWidth = firstButton.offsetWidth;
585
- // Page number buttons might be slightly wider due to text, use measured width
586
- buttonWidth = Math.max(buttonWidth, measuredWidth);
802
+ return buttonWidthMap[size] || 36;
803
+ };
804
+ const measurePrevNextWidth = () => {
805
+ const allButtons = container.querySelectorAll('button');
806
+ let prevWidth = 0;
807
+ let nextWidth = 0;
808
+ allButtons.forEach((button) => {
809
+ const html = button.innerHTML;
810
+ // Check if it's a prev/next button by looking for chevron icons or SVG
811
+ if (html.includes('chevron') ||
812
+ html.includes('Chevron') ||
813
+ button.querySelector('svg')) {
814
+ const width = button.offsetWidth;
815
+ if (width > 0) {
816
+ // First icon button is likely prev, last is next
817
+ if (prevWidth === 0) {
818
+ prevWidth = width;
819
+ }
820
+ else {
821
+ nextWidth = width;
822
+ }
823
+ }
587
824
  }
825
+ });
826
+ if (prevWidth > 0 && nextWidth > 0) {
827
+ return prevWidth + nextWidth;
588
828
  }
589
- // Account for prev/next buttons and gaps
590
- // HStack gap is typically 8px in Chakra UI
591
- const gap = 8;
592
- const prevNextWidth = buttonWidth * 2 + gap;
593
- const availableWidth = Math.max(0, width - prevNextWidth);
829
+ // Fallback: use page button width estimate
830
+ return measureButtonWidth() * 2;
831
+ };
832
+ const calculateSiblingCount = () => {
833
+ if (!container)
834
+ return;
835
+ const width = container.offsetWidth;
836
+ if (width === 0)
837
+ return;
838
+ // Measure actual button widths
839
+ const pageButtonWidth = measureButtonWidth();
840
+ const prevNextWidth = measurePrevNextWidth();
841
+ // Get computed gap from container (HStack gap)
842
+ const containerStyles = window.getComputedStyle(container);
843
+ const gap = parseFloat(containerStyles.gap) || 8;
844
+ // Account for gaps: prev button + gap + page buttons + gap + next button
845
+ // We need at least 2 gaps (before and after page buttons)
846
+ const availableWidth = Math.max(0, width - prevNextWidth - gap * 2);
594
847
  // Each page button takes buttonWidth + gap
595
- const buttonWithGap = buttonWidth + gap;
596
- const maxButtons = Math.floor(availableWidth / buttonWithGap);
597
- // Calculate sibling count
598
- // Minimum structure: [prev] [1] [current] [last] [next] = 5 buttons
599
- // With siblings: [prev] [1] [...] [current-N] ... [current] ... [current+N] [...] [last] [next]
600
- // We need: prev(1) + first(1) + ellipsis(1) + siblings*2 + current(1) + ellipsis(1) + last(1) + next(1)
601
- // Minimum: 5 buttons (prev, first, current, last, next)
602
- // With siblings: 5 + siblings*2 + ellipsis*2 (if needed)
603
- const minRequired = 5;
604
- const extraButtons = Math.max(0, maxButtons - minRequired);
605
- // Calculate sibling count
606
- // If we have enough space for ellipsis (2 buttons), account for that
848
+ const buttonWithGap = pageButtonWidth + gap;
849
+ const maxPageButtons = Math.floor(availableWidth / buttonWithGap);
850
+ // Calculate sibling count based on pagination structure
851
+ // Structure: [prev] [first] [ellipsis?] [siblings] [current] [siblings] [ellipsis?] [last] [next]
852
+ // Minimum: prev(1) + first(1) + current(1) + last(1) + next(1) = 5 buttons
853
+ // With siblings and ellipsis: 5 + siblings*2 + ellipsis*2
854
+ const minRequired = 5; // prev, first, current, last, next
855
+ const extraButtons = Math.max(0, maxPageButtons - minRequired);
607
856
  let calculated = minSiblingCount;
608
857
  if (extraButtons >= 4) {
609
- // Space for ellipsis (2) + siblings
858
+ // Enough space for ellipsis (2 buttons) + siblings on both sides
859
+ // Structure: [prev] [1] [...] [siblings] [current] [siblings] [...] [last] [next]
860
+ // Extra buttons = ellipsis(2) + siblings*2
610
861
  calculated = Math.floor((extraButtons - 2) / 2);
611
862
  }
612
863
  else if (extraButtons >= 2) {
613
864
  // Space for some siblings but not ellipsis
865
+ // Structure: [prev] [1] [siblings] [current] [siblings] [last] [next]
614
866
  calculated = Math.floor(extraButtons / 2);
615
867
  }
616
868
  // Apply max limit if provided
617
869
  if (maxSiblingCount !== undefined) {
618
870
  calculated = Math.min(calculated, maxSiblingCount);
619
871
  }
620
- setCalculatedSiblingCount(Math.max(minSiblingCount, calculated));
872
+ const finalSiblingCount = Math.max(minSiblingCount, calculated);
873
+ // Only update if value changed to avoid unnecessary re-renders
874
+ setCalculatedSiblingCount((prev) => {
875
+ if (prev !== finalSiblingCount) {
876
+ return finalSiblingCount;
877
+ }
878
+ return prev;
879
+ });
621
880
  };
622
- const resizeObserver = new ResizeObserver(() => {
623
- // Use requestAnimationFrame to debounce and ensure DOM is updated
881
+ const scheduleCalculation = () => {
882
+ // Cancel any pending calculations
624
883
  if (rafId !== null) {
625
884
  cancelAnimationFrame(rafId);
626
885
  }
627
- rafId = requestAnimationFrame(calculateSiblingCount);
628
- });
886
+ if (timeoutId !== null) {
887
+ clearTimeout(timeoutId);
888
+ }
889
+ // Use requestAnimationFrame for smooth updates
890
+ rafId = requestAnimationFrame(() => {
891
+ // Small delay to ensure DOM is fully rendered
892
+ timeoutId = setTimeout(calculateSiblingCount, 50);
893
+ });
894
+ };
895
+ const resizeObserver = new ResizeObserver(scheduleCalculation);
629
896
  resizeObserver.observe(container);
630
- // Initial calculation after a short delay to ensure buttons are rendered
631
- const timeoutId = setTimeout(calculateSiblingCount, 100);
897
+ // Initial calculation - try multiple times to ensure buttons are rendered
898
+ scheduleCalculation();
899
+ // Also try after a longer delay as fallback
900
+ const fallbackTimeout = setTimeout(calculateSiblingCount, 200);
632
901
  return () => {
633
902
  resizeObserver.disconnect();
634
903
  if (rafId !== null) {
635
904
  cancelAnimationFrame(rafId);
636
905
  }
637
- clearTimeout(timeoutId);
906
+ if (timeoutId !== null) {
907
+ clearTimeout(timeoutId);
908
+ }
909
+ clearTimeout(fallbackTimeout);
638
910
  };
639
911
  }, [size, siblingCount, minSiblingCount, maxSiblingCount]);
640
912
  const mergedRef = React.useCallback((node) => {
@@ -814,12 +1086,19 @@ const ResetSelectionButton = () => {
814
1086
  const RowCountText = () => {
815
1087
  const { table, type } = useDataTableContext();
816
1088
  const getCount = () => {
817
- if (type === "client") {
1089
+ if (type === 'client') {
818
1090
  return table.getFilteredRowModel().flatRows.length ?? 0;
819
1091
  }
820
1092
  return table.getRowCount();
821
1093
  };
822
- return jsx(Text, { children: getCount() });
1094
+ const totalCount = getCount();
1095
+ const { pageIndex, pageSize } = table.getState().pagination;
1096
+ if (totalCount === 0) {
1097
+ return jsx(Text, { children: "0 of 0" });
1098
+ }
1099
+ const start = pageIndex * pageSize + 1;
1100
+ const end = Math.min((pageIndex + 1) * pageSize, totalCount);
1101
+ return jsx(Text, { children: `${start}-${end} / ${totalCount}` });
823
1102
  };
824
1103
 
825
1104
  // pulling this into a separate file so adapter(s) that don't
@@ -2928,17 +3207,17 @@ const TableFilterTags = () => {
2928
3207
 
2929
3208
  const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsx(Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsx(Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
2930
3209
  const { tableLabel, table } = useDataTableContext();
2931
- const { rowCountText, hasErrorText } = tableLabel;
2932
- return (jsxs(Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxs(Flex, { flexFlow: "column", gap: 2, children: [jsxs(Flex, { justifyContent: "space-between", children: [jsx(Box, { children: showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }) }), jsxs(Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsx(Spinner, { size: "sm" }), hasError && (jsx(Tooltip, { content: hasErrorText, children: jsx(Icon, { as: BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsx(Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
3210
+ const { hasErrorText } = tableLabel;
3211
+ return (jsxs(Grid, { templateRows: 'auto 1fr', width: fitTableWidth ? 'fit-content' : '100%', height: fitTableHeight ? 'fit-content' : '100%', gap: '0.5rem', p: 1, ...gridProps, children: [jsxs(Flex, { flexFlow: 'column', gap: 2, children: [jsxs(Flex, { justifyContent: 'space-between', children: [jsx(Box, { children: showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }) }), jsxs(Flex, { gap: '0.5rem', alignItems: 'center', justifySelf: 'end', children: [loading && jsx(Spinner, { size: 'sm' }), hasError && (jsx(Tooltip, { content: hasErrorText, children: jsx(Icon, { as: BsExclamationCircleFill, color: 'red.400' }) })), showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsx(Flex, { flexFlow: 'column', gap: '0.5rem', children: filterTagsOptions.map((option) => {
2933
3212
  const { column, options } = option;
2934
3213
  const tableColumn = table.getColumn(column);
2935
- return (jsxs(Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsx(Text, { children: tableColumn?.columnDef.meta?.displayName })), jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
3214
+ return (jsxs(Flex, { alignItems: 'center', flexFlow: 'wrap', gap: '0.5rem', children: [tableColumn?.columnDef.meta?.displayName && (jsx(Text, { children: tableColumn?.columnDef.meta?.displayName })), jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
2936
3215
  if (tags.length === 0) {
2937
3216
  return tableColumn?.setFilterValue(undefined);
2938
3217
  }
2939
3218
  tableColumn?.setFilterValue(tags);
2940
3219
  } })] }, column));
2941
- }) })), showFilterTags && (jsx(Flex, { children: jsx(TableFilterTags, {}) }))] }), jsx(Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxs(Flex, { justifyContent: "space-between", children: [jsxs(Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && (jsxs(Flex, { children: [jsx(Text, { paddingRight: "0.5rem", children: rowCountText }), jsx(RowCountText, {})] }))] }), jsx(Box, { justifySelf: "end", children: showPagination && jsx(Pagination, {}) })] }))] }));
3220
+ }) })), showFilterTags && (jsx(Flex, { children: jsx(TableFilterTags, {}) }))] }), jsx(Grid, { children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxs(Flex, { justifyContent: 'space-between', children: [jsxs(Flex, { gap: '1rem', alignItems: 'center', children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && jsx(RowCountText, {})] }), jsx(Box, { justifySelf: 'end', children: showPagination && jsx(Pagination, {}) })] }))] }));
2942
3221
  };
2943
3222
 
2944
3223
  const EmptyState$1 = React.forwardRef(function EmptyState(props, ref) {
@@ -3100,7 +3379,7 @@ const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showL
3100
3379
  if (!showLoading && table.getRowModel().rows.length <= 0) {
3101
3380
  return emptyComponent;
3102
3381
  }
3103
- return (jsx(Box, { ref: containerRef, width: "100%", overflow: "auto", children: jsx(Table$1.Root, { stickyHeader: true, variant: 'outline', width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...props, children: children }) }));
3382
+ return (jsx(Box, { ref: containerRef, width: "100%", overflow: "auto", children: jsx(Table$1.Root, { stickyHeader: true, width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', ...props, children: children }) }));
3104
3383
  };
3105
3384
 
3106
3385
  const Checkbox = React.forwardRef(function Checkbox(props, ref) {
@@ -3146,11 +3425,7 @@ const TableBody = ({ showSelector = false, canResize = true, }) => {
3146
3425
  // styling resize and pinning start
3147
3426
  flex: `${canResize ? '0' : '1'} 0 ${cell.column.getSize()}px`,
3148
3427
  // this is to avoid the cell from being too wide
3149
- minWidth: `0`, color: {
3150
- base: 'colorPalette.900',
3151
- _dark: 'colorPalette.100',
3152
- },
3153
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...getTdProps(cell), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3428
+ minWidth: `0`, ...getTdProps(cell), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3154
3429
  })] }, `chakra-table-row-${row.id}`));
3155
3430
  }) }));
3156
3431
  };
@@ -3160,11 +3435,7 @@ const TableRowSelector = ({ row }) => {
3160
3435
  const isSelected = isRowSelected(row.id, rowSelection);
3161
3436
  const canSelect = canRowSelect(row);
3162
3437
  const toggleHandler = createRowToggleHandler(row, rowSelection, setRowSelection);
3163
- return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
3164
- base: 'colorPalette.900',
3165
- _dark: 'colorPalette.100',
3166
- },
3167
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: isSelected,
3438
+ return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', justifyItems: 'center', alignItems: 'center', children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: isSelected,
3168
3439
  disabled: !canSelect,
3169
3440
  onCheckedChange: toggleHandler }) }));
3170
3441
  };
@@ -3281,18 +3552,6 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3281
3552
  const columnMeta = header.column.columnDef.meta;
3282
3553
  return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3283
3554
  };
3284
- const getThProps = (header) => {
3285
- const thProps = header.column.getIsPinned()
3286
- ? {
3287
- left: showSelector
3288
- ? `${header.getStart('left') + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3289
- : `${header.getStart('left')}px`,
3290
- position: 'sticky',
3291
- zIndex: 100 + 1,
3292
- }
3293
- : {};
3294
- return thProps;
3295
- };
3296
3555
  const stickyProps = {
3297
3556
  position: 'sticky',
3298
3557
  top: 0,
@@ -3344,11 +3603,7 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3344
3603
  [header.id]: finalWidth,
3345
3604
  }));
3346
3605
  };
3347
- return (jsx(Table$1.Header, { ...(isSticky ? stickyProps : {}), bgColor: 'transparent', ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxs(Table$1.Row, { display: 'flex', bgColor: 'transparent', ...tableRowProps, children: [showSelector && (jsx(Table$1.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
3348
- base: 'colorPalette.900',
3349
- _dark: 'colorPalette.100',
3350
- },
3351
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
3606
+ return (jsx(Table$1.Header, { ...(isSticky ? stickyProps : {}), ...tableHeaderProps, children: table.getHeaderGroups().map((headerGroup) => (jsxs(Table$1.Row, { display: 'flex', ...tableRowProps, children: [showSelector && (jsx(Table$1.ColumnHeader, { padding: `${table.getDensityValue()}px`, display: 'grid', justifyItems: 'center', alignItems: 'center', children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
3352
3607
  // indeterminate: areSomeRowsSelected(table, rowSelection),
3353
3608
  onChange: createToggleAllRowsHandler(table, rowSelection, setRowSelection) }) })), headerGroup.headers.map((header) => {
3354
3609
  const resizeProps = {
@@ -3358,30 +3613,11 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3358
3613
  };
3359
3614
  return (jsxs(Table$1.ColumnHeader, { padding: 0, columnSpan: `${header.colSpan}`,
3360
3615
  // styling resize and pinning start
3361
- flex: `${canResize ? '0' : '1'} 0 ${header.column.getSize()}px`, display: 'grid', gridTemplateColumns: '1fr auto', zIndex: 1500 + header.index, color: {
3362
- base: 'colorPalette.800',
3363
- _dark: 'colorPalette.200',
3364
- },
3365
- bg: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, ...getThProps(header), children: [jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsx(Flex, { padding: `${table.getDensityValue()}px`, alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', overflow: 'auto', color: {
3366
- base: 'colorPalette.800',
3367
- _dark: 'colorPalette.200',
3368
- _hover: {
3369
- base: 'colorPalette.700',
3370
- _dark: 'colorPalette.300',
3371
- },
3372
- },
3373
- bg: {
3374
- base: 'colorPalette.100',
3375
- _dark: 'colorPalette.900',
3376
- _hover: {
3377
- base: 'colorPalette.200',
3378
- _dark: 'colorPalette.800',
3379
- },
3380
- }, children: jsxs(Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
3616
+ flex: `${canResize ? '0' : '1'} 0 ${header.column.getSize()}px`, display: 'grid', gridTemplateColumns: '1fr auto', zIndex: 1500 + header.index, children: [jsxs(MenuRoot, { children: [jsx(MenuTrigger, { asChild: true, children: jsx(Flex, { padding: `${table.getDensityValue()}px`, alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', overflow: 'auto', children: jsxs(Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
3381
3617
  ? null
3382
3618
  : flexRender(header.column.columnDef.header, header.getContext()), jsx(Box, { children: header.column.getCanSort() && (jsxs(Fragment, { children: [header.column.getIsSorted() === false && jsx(Fragment, {}), header.column.getIsSorted() === 'asc' && (jsx(BiUpArrow, {})), header.column.getIsSorted() === 'desc' && (jsx(BiDownArrow, {}))] })) }), jsx(Box, { children: header.column.getIsFiltered() && jsx(MdFilterListAlt, {}) })] }) }) }), jsxs(MenuContent, { children: [!header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "pin-column", children: jsxs(Button, { variant: 'ghost', onClick: () => {
3383
3619
  header.column.pin('left');
3384
- }, children: [jsx(MdPushPin, {}), getHeaderText(header, 'pinColumn')] }) })), header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxs(Button, { variant: 'ghost', onClick: () => {
3620
+ }, p: 1, children: [jsx(MdPushPin, {}), getHeaderText(header, 'pinColumn')] }) })), header.column.getIsPinned() && (jsx(MenuItem, { asChild: true, value: "cancel-pin", children: jsxs(Button, { variant: 'ghost', onClick: () => {
3385
3621
  header.column.pin(false);
3386
3622
  }, children: [jsx(MdCancel, {}), getHeaderText(header, 'cancelPin')] }) })), header.column.getCanSort() && (jsxs(Fragment, { children: [jsx(MenuItem, { asChild: true, value: "sort-ascend", children: jsxs(Button, { variant: 'ghost', onClick: () => {
3387
3623
  table.setSorting((state) => {
@@ -3581,7 +3817,7 @@ const ErrorAlert = ({ showMessage = true }) => {
3581
3817
  const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: defaultPagination = {
3582
3818
  pageIndex: 0, //initial page index
3583
3819
  pageSize: 10, //default page size
3584
- }, rowSelection: defaultRowSelection = {}, columnFilters: defaultColumnFilters = [], columnOrder: defaultColumnOrder = [], columnVisibility: defaultColumnVisibility = {}, globalFilter: defaultGlobalFilter = "", density: defaultDensity = "sm", } = {
3820
+ }, rowSelection: defaultRowSelection = {}, columnFilters: defaultColumnFilters = [], columnOrder: defaultColumnOrder = [], columnVisibility: defaultColumnVisibility = {}, globalFilter: defaultGlobalFilter = '', density: defaultDensity = 'sm', } = {
3585
3821
  sorting: [],
3586
3822
  pagination: {
3587
3823
  pageIndex: 0, //initial page index
@@ -3591,9 +3827,9 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3591
3827
  columnFilters: [],
3592
3828
  columnOrder: [],
3593
3829
  columnVisibility: {},
3594
- globalFilter: "",
3595
- density: "sm",
3596
- }, keyPrefix = "", } = {
3830
+ globalFilter: '',
3831
+ density: 'sm',
3832
+ }, } = {
3597
3833
  default: {
3598
3834
  sorting: [],
3599
3835
  pagination: {
@@ -3604,8 +3840,8 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3604
3840
  columnFilters: [],
3605
3841
  columnOrder: [],
3606
3842
  columnVisibility: {},
3607
- globalFilter: "",
3608
- density: "sm",
3843
+ globalFilter: '',
3844
+ density: 'sm',
3609
3845
  },
3610
3846
  }) => {
3611
3847
  const [sorting, setSorting] = useState(defaultSorting);
@@ -3616,7 +3852,6 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3616
3852
  const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter);
3617
3853
  const [density, setDensity] = useState(defaultDensity);
3618
3854
  const [columnVisibility, setColumnVisibility] = useState(defaultColumnVisibility);
3619
- const translate = useTranslation("", { keyPrefix });
3620
3855
  return {
3621
3856
  sorting,
3622
3857
  setSorting,
@@ -3634,12 +3869,11 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3634
3869
  setDensity,
3635
3870
  columnVisibility,
3636
3871
  setColumnVisibility,
3637
- translate,
3638
3872
  };
3639
3873
  };
3640
3874
 
3641
3875
  const useDataTableServer = (props) => {
3642
- const { url, default: defaultProps, keyPrefix, placeholderData, queryFn: customQueryFn, } = props;
3876
+ const { url, default: defaultProps, placeholderData, queryFn: customQueryFn, } = props;
3643
3877
  const { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, } = defaultProps || {};
3644
3878
  const [sorting, setSorting] = useState(defaultSorting || []);
3645
3879
  const [columnFilters, setColumnFilters] = useState(defaultColumnFilters || []); // can set initial column filter state here
@@ -3649,8 +3883,8 @@ const useDataTableServer = (props) => {
3649
3883
  });
3650
3884
  const [rowSelection, setRowSelection] = useState(defaultRowSelection || {});
3651
3885
  const [columnOrder, setColumnOrder] = useState(defaultColumnOrder || []);
3652
- const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter || "");
3653
- const [density, setDensity] = useState(defaultDensity || "sm");
3886
+ const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter || '');
3887
+ const [density, setDensity] = useState(defaultDensity || 'sm');
3654
3888
  const [columnVisibility, setColumnVisibility] = useState(defaultColumnVisibility || {});
3655
3889
  const { pageSize, pageIndex } = pagination;
3656
3890
  const params = {
@@ -3662,7 +3896,7 @@ const useDataTableServer = (props) => {
3662
3896
  };
3663
3897
  const defaultQueryFn = async () => {
3664
3898
  if (!url) {
3665
- throw new Error("url is required");
3899
+ throw new Error('url is required');
3666
3900
  }
3667
3901
  const response = await axios.get(url, {
3668
3902
  params,
@@ -3676,7 +3910,6 @@ const useDataTableServer = (props) => {
3676
3910
  : defaultQueryFn,
3677
3911
  placeholderData,
3678
3912
  });
3679
- const translate = useTranslation("", { keyPrefix });
3680
3913
  return {
3681
3914
  sorting,
3682
3915
  setSorting,
@@ -3695,7 +3928,6 @@ const useDataTableServer = (props) => {
3695
3928
  columnVisibility,
3696
3929
  setColumnVisibility,
3697
3930
  query,
3698
- translate,
3699
3931
  };
3700
3932
  };
3701
3933
 
@@ -3714,11 +3946,8 @@ const snakeToLabel = (str) => {
3714
3946
  .join(" "); // Join with space
3715
3947
  };
3716
3948
 
3717
- const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3949
+ const RecordDisplay = ({ object, boxProps, prefix = '', }) => {
3718
3950
  const getColumn = ({ field }) => {
3719
- if (translate !== undefined) {
3720
- return translate.t(`${prefix}${field}`);
3721
- }
3722
3951
  return snakeToLabel(field);
3723
3952
  };
3724
3953
  if (object === null) {
@@ -3726,7 +3955,7 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3726
3955
  }
3727
3956
  return (jsx(Grid, { rowGap: 1, padding: 1, overflow: 'auto', ...boxProps, children: Object.entries(object).map(([field, value], index) => {
3728
3957
  const uniqueKey = `${prefix}${field}-${index}`;
3729
- return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsx(Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsx(Text, { children: JSON.stringify(value) }))] }, uniqueKey));
3958
+ return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsx(Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.` })) : (jsx(Text, { children: JSON.stringify(value) }))] }, uniqueKey));
3730
3959
  }) }));
3731
3960
  };
3732
3961
 
@@ -3740,15 +3969,12 @@ const widthSanityCheck = (widthList, ignoreList, properties) => {
3740
3969
  throw new Error(`The width list is too long given from the number of remaining properties after ignore some.`);
3741
3970
  }
3742
3971
  };
3743
- const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, translate, }) => {
3972
+ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, }) => {
3744
3973
  const { properties } = schema;
3745
- idListSanityCheck("ignore", ignore, properties);
3974
+ idListSanityCheck('ignore', ignore, properties);
3746
3975
  widthSanityCheck(width, ignore, properties);
3747
- idListSanityCheck("meta", Object.keys(meta), properties);
3976
+ idListSanityCheck('meta', Object.keys(meta), properties);
3748
3977
  const getColumn = ({ column }) => {
3749
- if (translate !== undefined) {
3750
- return translate.t(`${column}`);
3751
- }
3752
3978
  return snakeToLabel(column);
3753
3979
  };
3754
3980
  const keys = Object.keys(properties);
@@ -3757,15 +3983,15 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3757
3983
  return !ignore.some((shouldIgnoreKey) => key === shouldIgnoreKey);
3758
3984
  });
3759
3985
  const columnHelper = createColumnHelper();
3760
- // @ts-expect-error find type for unknown
3761
3986
  const columns = [
3762
3987
  ...ignored.map((column, index) => {
3988
+ // @ts-expect-error column accessor type issue with generic TData
3763
3989
  return columnHelper.accessor(column, {
3764
3990
  cell: (props) => {
3765
3991
  // @ts-expect-error find type for unknown
3766
3992
  const value = props.row.original[column];
3767
- if (typeof value === "object") {
3768
- return (jsx(Grid, { overflow: "auto", children: jsx(RecordDisplay, { object: value, translate }) }));
3993
+ if (typeof value === 'object') {
3994
+ return (jsx(Grid, { overflow: 'auto', children: jsx(RecordDisplay, { object: value }) }));
3769
3995
  }
3770
3996
  return jsx(TextCell, { children: value });
3771
3997
  },
@@ -3797,6 +4023,11 @@ const SchemaFormContext = createContext({
3797
4023
  include: [],
3798
4024
  onSubmit: async () => { },
3799
4025
  rowNumber: 0,
4026
+ /** Default translate fallback - returns key as-is */
4027
+ translate: {
4028
+ t: (key) => key,
4029
+ ready: true,
4030
+ },
3800
4031
  requestOptions: {},
3801
4032
  timezone: 'Asia/Hong_Kong',
3802
4033
  displayConfig: {
@@ -4029,7 +4260,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4029
4260
  showSubmitButton: true,
4030
4261
  showResetButton: true,
4031
4262
  showTitle: true,
4032
- }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, insideDialog = false, }) => {
4263
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog = false, }) => {
4033
4264
  const [isSuccess, setIsSuccess] = useState(false);
4034
4265
  const [isError, setIsError] = useState(false);
4035
4266
  const [isSubmiting, setIsSubmiting] = useState(false);
@@ -4120,6 +4351,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4120
4351
  enumPickerLabels,
4121
4352
  filePickerLabels,
4122
4353
  formButtonLabels,
4354
+ timePickerLabels,
4123
4355
  ajvResolver: ajvResolver(schema),
4124
4356
  insideDialog,
4125
4357
  }, children: jsx(FormProvider, { ...form, children: children }) }));
@@ -4130,31 +4362,33 @@ function removeIndex(str) {
4130
4362
  }
4131
4363
 
4132
4364
  /**
4133
- * Custom hook to simplify i18n translation for form fields.
4365
+ * Custom hook for form field labels and fallback text.
4134
4366
  * Automatically handles colLabel construction and removeIndex logic.
4367
+ * Uses schema.title when available, otherwise falls back to translate function.
4135
4368
  *
4136
4369
  * @param column - The column name
4137
4370
  * @param prefix - The prefix for the field (usually empty string or parent path)
4138
- * @returns Object with translation helper functions
4371
+ * @param schema - Optional schema object with title property
4372
+ * @returns Object with label helper functions
4139
4373
  *
4140
4374
  * @example
4141
4375
  * ```tsx
4142
- * const formI18n = useFormI18n(column, prefix);
4376
+ * const formI18n = useFormI18n(column, prefix, schema);
4143
4377
  *
4144
- * // Get field label
4378
+ * // Get field label (prefers schema.title)
4145
4379
  * <Field label={formI18n.label()} />
4146
4380
  *
4147
- * // Get error message
4381
+ * // Get required error message
4148
4382
  * <Text>{formI18n.required()}</Text>
4149
4383
  *
4150
- * // Get custom translation key
4384
+ * // Get custom text
4151
4385
  * <Text>{formI18n.t('add_more')}</Text>
4152
4386
  *
4153
4387
  * // Access the raw colLabel
4154
4388
  * const colLabel = formI18n.colLabel;
4155
4389
  * ```
4156
4390
  */
4157
- const useFormI18n$1 = (column, prefix = '', schema) => {
4391
+ const useFormI18n = (column, prefix = '', schema) => {
4158
4392
  const { translate } = useSchemaContext();
4159
4393
  const colLabel = `${prefix}${column}`;
4160
4394
  return {
@@ -4163,7 +4397,7 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4163
4397
  */
4164
4398
  colLabel,
4165
4399
  /**
4166
- * Get the field label from schema title prop, or fall back to translation
4400
+ * Get the field label from schema title prop, or fall back to translate function
4167
4401
  * Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
4168
4402
  */
4169
4403
  label: (options) => {
@@ -4173,18 +4407,18 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4173
4407
  return translate.t(removeIndex(`${colLabel}.field_label`), options);
4174
4408
  },
4175
4409
  /**
4176
- * Get the required error message translation
4410
+ * Get the required error message
4177
4411
  * Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
4178
4412
  */
4179
4413
  required: (options) => {
4180
4414
  return translate.t(removeIndex(`${colLabel}.field_required`), options);
4181
4415
  },
4182
4416
  /**
4183
- * Get a translation for any custom key relative to the field
4417
+ * Get text for any custom key relative to the field
4184
4418
  * Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
4185
4419
  *
4186
- * @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
4187
- * @param options - Optional translation options (e.g., defaultValue, interpolation variables)
4420
+ * @param key - The key suffix (e.g., 'add_more', 'total', etc.)
4421
+ * @param options - Optional options (e.g., defaultValue, interpolation variables)
4188
4422
  */
4189
4423
  t: (key, options) => {
4190
4424
  return translate.t(removeIndex(`${colLabel}.${key}`), options);
@@ -4202,8 +4436,9 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4202
4436
  const { type } = items;
4203
4437
  const colLabel = `${prefix}${column}`;
4204
4438
  const isRequired = required?.some((columnId) => columnId === column);
4205
- const formI18n = useFormI18n$1(column, prefix, schema);
4439
+ const formI18n = useFormI18n(column, prefix, schema);
4206
4440
  const { formState: { errors }, setValue, watch, } = useFormContext();
4441
+ const { formButtonLabels } = useSchemaContext();
4207
4442
  const fields = (watch(colLabel) ?? []);
4208
4443
  return (jsxs(Flex, { gridRow, gridColumn, flexFlow: 'column', gap: 2, children: [jsxs(Box, { as: "label", children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: 'column', gap: 2, children: fields.map((field, index) => (jsxs(Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4209
4444
  base: 'colorPalette.200',
@@ -4229,7 +4464,7 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4229
4464
  return;
4230
4465
  }
4231
4466
  setValue(colLabel, [...fields, {}]);
4232
- }, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
4467
+ }, children: formButtonLabels?.add ?? 'Add' }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
4233
4468
  };
4234
4469
 
4235
4470
  const Field = React.forwardRef(function Field(props, ref) {
@@ -4243,7 +4478,7 @@ const BooleanPicker = ({ schema, column, prefix }) => {
4243
4478
  const isRequired = required?.some((columnId) => columnId === column);
4244
4479
  const colLabel = `${prefix}${column}`;
4245
4480
  const value = watch(colLabel);
4246
- const formI18n = useFormI18n$1(column, prefix, schema);
4481
+ const formI18n = useFormI18n(column, prefix, schema);
4247
4482
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4248
4483
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
4249
4484
  setValue(colLabel, !value);
@@ -4264,50 +4499,50 @@ const CustomInput = ({ column, schema, prefix }) => {
4264
4499
 
4265
4500
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
4266
4501
  const { labels } = useContext(DatePickerContext);
4267
- const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel } = labels;
4502
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
4268
4503
  if (calendars.length) {
4269
- return (jsxs(Grid, { children: [jsxs(Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...getBackProps({
4504
+ return (jsxs(Grid, { children: [jsxs(Grid, { templateColumns: 'repeat(4, auto)', justifyContent: 'center', children: [jsx(Button$1, { variant: 'ghost', ...getBackProps({
4270
4505
  calendars,
4271
4506
  offset: 12,
4272
- }), children: "<<" }), jsx(Button$1, { variant: "ghost", ...getBackProps({ calendars }), children: backButtonLabel }), jsx(Button$1, { variant: "ghost", ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsx(Button$1, { variant: "ghost", ...getForwardProps({
4507
+ }), children: '<<' }), jsx(Button$1, { variant: 'ghost', ...getBackProps({ calendars }), children: backButtonLabel }), jsx(Button$1, { variant: 'ghost', ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsx(Button$1, { variant: 'ghost', ...getForwardProps({
4273
4508
  calendars,
4274
4509
  offset: 12,
4275
- }), children: ">>" })] }), jsx(Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", children: calendars.map((calendar) => (jsxs(Grid, { gap: 4, children: [jsxs(Grid, { justifyContent: "center", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxs(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
4510
+ }), children: '>>' })] }), jsx(Grid, { templateColumns: 'repeat(2, auto)', justifyContent: 'center', children: calendars.map((calendar) => (jsxs(Grid, { gap: 4, children: [jsxs(Grid, { justifyContent: 'center', children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsxs(Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: [[0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
4276
4511
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
4277
- return (jsx(Text, { textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
4512
+ return (jsx(Text, { textAlign: 'center', children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
4278
4513
  }), calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
4279
4514
  const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
4280
4515
  if (!dateObj) {
4281
4516
  return jsx(Grid, {}, key);
4282
4517
  }
4283
- const { date, selected, selectable, today } = dateObj;
4518
+ const { date, selected, selectable, today, isCurrentMonth, } = dateObj;
4284
4519
  const getDateColor = ({ today, selected, selectable, }) => {
4285
4520
  if (!selectable) {
4286
- return "gray";
4521
+ return 'gray';
4287
4522
  }
4288
4523
  if (selected) {
4289
- return "blue";
4524
+ return 'blue';
4290
4525
  }
4291
4526
  if (today) {
4292
- return "green";
4527
+ return 'green';
4293
4528
  }
4294
- return "";
4529
+ return '';
4295
4530
  };
4296
4531
  const getVariant = ({ today, selected, selectable, }) => {
4297
4532
  if (!selectable) {
4298
- return "surface";
4533
+ return 'surface';
4299
4534
  }
4300
4535
  if (selected) {
4301
- return "solid";
4536
+ return 'solid';
4302
4537
  }
4303
4538
  if (today) {
4304
- return "surface";
4539
+ return 'surface';
4305
4540
  }
4306
- return "ghost";
4541
+ return 'ghost';
4307
4542
  };
4308
4543
  const color = getDateColor({ today, selected, selectable });
4309
4544
  const variant = getVariant({ today, selected, selectable });
4310
- return (jsx(Button$1, { variant: variant, colorPalette: color, ...getDateProps({ dateObj }), children: selectable ? date.getDate() : "X" }, key));
4545
+ return (jsx(Button$1, { variant: variant, colorPalette: color, opacity: isCurrentMonth ? 1 : 0.4, ...getDateProps({ dateObj }), children: selectable ? date.getDate() : 'X' }, key));
4311
4546
  }))] })] }, `${calendar.month}${calendar.year}`))) })] }));
4312
4547
  }
4313
4548
  return null;
@@ -4315,50 +4550,55 @@ const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firs
4315
4550
  const DatePickerContext = createContext({
4316
4551
  labels: {
4317
4552
  monthNamesShort: [
4318
- "Jan",
4319
- "Feb",
4320
- "Mar",
4321
- "Apr",
4322
- "May",
4323
- "Jun",
4324
- "Jul",
4325
- "Aug",
4326
- "Sep",
4327
- "Oct",
4328
- "Nov",
4329
- "Dec",
4553
+ 'Jan',
4554
+ 'Feb',
4555
+ 'Mar',
4556
+ 'Apr',
4557
+ 'May',
4558
+ 'Jun',
4559
+ 'Jul',
4560
+ 'Aug',
4561
+ 'Sep',
4562
+ 'Oct',
4563
+ 'Nov',
4564
+ 'Dec',
4330
4565
  ],
4331
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4332
- backButtonLabel: "Back",
4333
- forwardButtonLabel: "Next",
4566
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4567
+ backButtonLabel: 'Back',
4568
+ forwardButtonLabel: 'Next',
4334
4569
  },
4335
4570
  });
4336
- let DatePicker$1 = class DatePicker extends React__default.Component {
4337
- render() {
4338
- const { labels = {
4339
- monthNamesShort: [
4340
- "Jan",
4341
- "Feb",
4342
- "Mar",
4343
- "Apr",
4344
- "May",
4345
- "Jun",
4346
- "Jul",
4347
- "Aug",
4348
- "Sep",
4349
- "Oct",
4350
- "Nov",
4351
- "Dec",
4352
- ],
4353
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4354
- backButtonLabel: "Back",
4355
- forwardButtonLabel: "Next",
4356
- }, } = this.props;
4357
- return (jsx(DatePickerContext.Provider, { value: { labels }, children: jsx(Dayzed, { onDateSelected: this.props.onDateSelected, selected: this.props.selected, firstDayOfWeek: this.props.firstDayOfWeek, showOutsideDays: this.props.showOutsideDays, date: this.props.date, minDate: this.props.minDate, maxDate: this.props.maxDate, monthsToDisplay: this.props.monthsToDisplay, render:
4358
- // @ts-expect-error - Dayzed types need to be fixed
4359
- (dayzedData) => (jsx(Calendar, { ...dayzedData,
4360
- firstDayOfWeek: this.props.firstDayOfWeek })) }) }));
4361
- }
4571
+ const DatePicker$1 = ({ labels = {
4572
+ monthNamesShort: [
4573
+ 'Jan',
4574
+ 'Feb',
4575
+ 'Mar',
4576
+ 'Apr',
4577
+ 'May',
4578
+ 'Jun',
4579
+ 'Jul',
4580
+ 'Aug',
4581
+ 'Sep',
4582
+ 'Oct',
4583
+ 'Nov',
4584
+ 'Dec',
4585
+ ],
4586
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4587
+ backButtonLabel: 'Back',
4588
+ forwardButtonLabel: 'Next',
4589
+ }, onDateSelected, selected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, render, }) => {
4590
+ const calendarData = useCalendar({
4591
+ onDateSelected,
4592
+ selected,
4593
+ firstDayOfWeek,
4594
+ showOutsideDays,
4595
+ date,
4596
+ minDate,
4597
+ maxDate,
4598
+ monthsToDisplay,
4599
+ });
4600
+ return (jsx(DatePickerContext.Provider, { value: { labels }, children: render ? (render(calendarData)) : (jsx(Calendar, { ...calendarData,
4601
+ firstDayOfWeek })) }));
4362
4602
  };
4363
4603
 
4364
4604
  dayjs.extend(utc);
@@ -4366,7 +4606,7 @@ dayjs.extend(timezone);
4366
4606
  const DatePicker = ({ column, schema, prefix }) => {
4367
4607
  const { watch, formState: { errors }, setValue, } = useFormContext();
4368
4608
  const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
4369
- const formI18n = useFormI18n$1(column, prefix, schema);
4609
+ const formI18n = useFormI18n(column, prefix, schema);
4370
4610
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4371
4611
  const isRequired = required?.some((columnId) => columnId === column);
4372
4612
  const colLabel = formI18n.colLabel;
@@ -4400,74 +4640,30 @@ const DatePicker = ({ column, schema, prefix }) => {
4400
4640
  }, [selectedDate, dateFormat, colLabel, setValue]);
4401
4641
  const datePickerLabels = {
4402
4642
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4403
- formI18n.translate.t(`common.month_1`, {
4404
- defaultValue: 'January',
4405
- }),
4406
- formI18n.translate.t(`common.month_2`, {
4407
- defaultValue: 'February',
4408
- }),
4409
- formI18n.translate.t(`common.month_3`, {
4410
- defaultValue: 'March',
4411
- }),
4412
- formI18n.translate.t(`common.month_4`, {
4413
- defaultValue: 'April',
4414
- }),
4415
- formI18n.translate.t(`common.month_5`, {
4416
- defaultValue: 'May',
4417
- }),
4418
- formI18n.translate.t(`common.month_6`, {
4419
- defaultValue: 'June',
4420
- }),
4421
- formI18n.translate.t(`common.month_7`, {
4422
- defaultValue: 'July',
4423
- }),
4424
- formI18n.translate.t(`common.month_8`, {
4425
- defaultValue: 'August',
4426
- }),
4427
- formI18n.translate.t(`common.month_9`, {
4428
- defaultValue: 'September',
4429
- }),
4430
- formI18n.translate.t(`common.month_10`, {
4431
- defaultValue: 'October',
4432
- }),
4433
- formI18n.translate.t(`common.month_11`, {
4434
- defaultValue: 'November',
4435
- }),
4436
- formI18n.translate.t(`common.month_12`, {
4437
- defaultValue: 'December',
4438
- }),
4643
+ 'January',
4644
+ 'February',
4645
+ 'March',
4646
+ 'April',
4647
+ 'May',
4648
+ 'June',
4649
+ 'July',
4650
+ 'August',
4651
+ 'September',
4652
+ 'October',
4653
+ 'November',
4654
+ 'December',
4439
4655
  ],
4440
4656
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4441
- formI18n.translate.t(`common.weekday_1`, {
4442
- defaultValue: 'Sun',
4443
- }),
4444
- formI18n.translate.t(`common.weekday_2`, {
4445
- defaultValue: 'Mon',
4446
- }),
4447
- formI18n.translate.t(`common.weekday_3`, {
4448
- defaultValue: 'Tue',
4449
- }),
4450
- formI18n.translate.t(`common.weekday_4`, {
4451
- defaultValue: 'Wed',
4452
- }),
4453
- formI18n.translate.t(`common.weekday_5`, {
4454
- defaultValue: 'Thu',
4455
- }),
4456
- formI18n.translate.t(`common.weekday_6`, {
4457
- defaultValue: 'Fri',
4458
- }),
4459
- formI18n.translate.t(`common.weekday_7`, {
4460
- defaultValue: 'Sat',
4461
- }),
4657
+ 'Sun',
4658
+ 'Mon',
4659
+ 'Tue',
4660
+ 'Wed',
4661
+ 'Thu',
4662
+ 'Fri',
4663
+ 'Sat',
4462
4664
  ],
4463
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4464
- formI18n.translate.t(`common.back_button`, {
4465
- defaultValue: 'Back',
4466
- }),
4467
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4468
- formI18n.translate.t(`common.forward_button`, {
4469
- defaultValue: 'Forward',
4470
- }),
4665
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
4666
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
4471
4667
  };
4472
4668
  const datePickerContent = (jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4473
4669
  setValue(colLabel, dayjs(date).format(dateFormat));
@@ -4484,7 +4680,7 @@ dayjs.extend(timezone);
4484
4680
  const DateRangePicker = ({ column, schema, prefix, }) => {
4485
4681
  const { watch, formState: { errors }, setValue, } = useFormContext();
4486
4682
  const { timezone, insideDialog } = useSchemaContext();
4487
- const formI18n = useFormI18n$1(column, prefix);
4683
+ const formI18n = useFormI18n(column, prefix);
4488
4684
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4489
4685
  const isRequired = required?.some((columnId) => columnId === column);
4490
4686
  const colLabel = formI18n.colLabel;
@@ -4582,7 +4778,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4582
4778
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
4583
4779
  const { watch, formState: { errors }, setValue, } = useFormContext();
4584
4780
  const { enumPickerLabels, insideDialog } = useSchemaContext();
4585
- const formI18n = useFormI18n$1(column, prefix, schema);
4781
+ const formI18n = useFormI18n(column, prefix, schema);
4586
4782
  const { required, variant } = schema;
4587
4783
  const isRequired = required?.some((columnId) => columnId === column);
4588
4784
  const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
@@ -5129,7 +5325,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
5129
5325
  }) })) }))] }));
5130
5326
  };
5131
5327
 
5132
- function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
5328
+ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, colLabel, }) {
5133
5329
  const [selectedFile, setSelectedFile] = useState(undefined);
5134
5330
  const [activeTab, setActiveTab] = useState('browse');
5135
5331
  const [uploadingFiles, setUploadingFiles] = useState(new Set());
@@ -5198,15 +5394,8 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5198
5394
  const showTabs = enableUpload && !!onUploadFile && !!onFetchFiles;
5199
5395
  if (!onFetchFiles && !onUploadFile)
5200
5396
  return null;
5201
- return (jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsx(DialogCloseTrigger, {})] }), jsx(DialogBody, { children: showTabs ? (jsxs(Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxs(Tabs.List, { children: [jsx(Tabs.Trigger, { value: "browse", children: labels?.browseTab ??
5202
- translate(removeIndex(`${colLabel}.browse_tab`)) ??
5203
- 'Browse Library' }), jsx(Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
5204
- translate(removeIndex(`${colLabel}.upload_tab`)) ??
5205
- 'Upload Files' })] }), jsx(Tabs.Content, { value: "browse", children: onFetchFiles && (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsx(Tabs.Content, { value: "upload", children: jsxs(VStack, { align: "stretch", gap: 4, children: [jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
5206
- translate(removeIndex(`${colLabel}.fileDropzone`)) ??
5207
- 'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsx(Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsx(Box, { py: 2, children: jsxs(HStack, { gap: 2, children: [jsx(Spinner, { size: "sm", colorPalette: "blue" }), jsxs(Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ??
5208
- translate(removeIndex(`${colLabel}.uploading`)) ??
5209
- 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsx(VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsx(Box, { bg: {
5397
+ return (jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsx(DialogCloseTrigger, {})] }), jsx(DialogBody, { children: showTabs ? (jsxs(Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxs(Tabs.List, { children: [jsx(Tabs.Trigger, { value: "browse", children: labels?.browseTab ?? 'Browse Library' }), jsx(Tabs.Trigger, { value: "upload", children: labels?.uploadTab ?? 'Upload Files' })] }), jsx(Tabs.Content, { value: "browse", children: onFetchFiles && (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsx(Tabs.Content, { value: "upload", children: jsxs(VStack, { align: "stretch", gap: 4, children: [jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
5398
+ 'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsx(Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsx(Box, { py: 2, children: jsxs(HStack, { gap: 2, children: [jsx(Spinner, { size: "sm", colorPalette: "blue" }), jsxs(Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ?? 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsx(VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsx(Box, { bg: {
5210
5399
  base: 'colorPalette.50',
5211
5400
  _dark: 'colorPalette.900/20',
5212
5401
  }, border: "1px solid", borderColor: {
@@ -5215,18 +5404,12 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5215
5404
  }, colorPalette: "red", borderRadius: "md", p: 3, children: jsxs(Text, { fontSize: "sm", color: {
5216
5405
  base: 'colorPalette.600',
5217
5406
  _dark: 'colorPalette.300',
5218
- }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
5219
- translate(removeIndex(`${colLabel}.upload_failed`)) ??
5220
- 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), jsx(DialogFooter, { children: jsxs(HStack, { gap: 3, justify: "end", children: [jsx(Button$1, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
5221
- translate(removeIndex(`${colLabel}.cancel`)) ??
5222
- 'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ??
5223
- translate(removeIndex(`${colLabel}.select`)) ??
5224
- 'Select' })] }) })] }) }));
5407
+ }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ?? 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), jsx(DialogFooter, { children: jsxs(HStack, { gap: 3, justify: "end", children: [jsx(Button$1, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ?? 'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ?? 'Select' })] }) })] }) }));
5225
5408
  }
5226
5409
  const FilePicker = ({ column, schema, prefix }) => {
5227
5410
  const { setValue, formState: { errors }, watch, } = useFormContext();
5228
5411
  const { filePickerLabels } = useSchemaContext();
5229
- const formI18n = useFormI18n$1(column, prefix);
5412
+ const formI18n = useFormI18n(column, prefix);
5230
5413
  const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
5231
5414
  const isRequired = required?.some((columnId) => columnId === column);
5232
5415
  const isSingleSelect = type === 'string';
@@ -5302,7 +5485,7 @@ const FilePicker = ({ column, schema, prefix }) => {
5302
5485
  const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5303
5486
  const { setValue, formState: { errors }, watch, } = useFormContext();
5304
5487
  const { filePickerLabels } = useSchemaContext();
5305
- const formI18n = useFormI18n$1(column, prefix);
5488
+ const formI18n = useFormI18n(column, prefix);
5306
5489
  const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
5307
5490
  const isRequired = required?.some((columnId) => columnId === column);
5308
5491
  const isSingleSelect = type === 'string';
@@ -5398,8 +5581,8 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5398
5581
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsx(VStack, { align: "stretch", gap: 2, children: jsx(Button$1, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
5399
5582
  formI18n.t('browse_library') ??
5400
5583
  'Browse from Library' }) }), jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
5401
- formI18n.t('dialog_title') ??
5402
- 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel }), jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
5584
+ filePickerLabels?.dialogTitle ??
5585
+ 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, colLabel: colLabel }), jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
5403
5586
  const file = fileMap.get(fileId);
5404
5587
  const isImage = file
5405
5588
  ? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
@@ -5448,17 +5631,16 @@ const defaultRenderDisplay = (item) => {
5448
5631
  return JSON.stringify(item);
5449
5632
  };
5450
5633
 
5451
- const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5634
+ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5452
5635
  const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
5453
5636
  const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5454
- const formI18n = useFormI18n$1(column, prefix, schema);
5455
- const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
5456
- const isRequired = required?.some((columnId) => columnId === column);
5637
+ const { renderDisplay, foreign_key } = schema;
5457
5638
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5458
5639
  const [searchText, setSearchText] = useState('');
5459
5640
  const [debouncedSearchText, setDebouncedSearchText] = useState('');
5460
5641
  const [limit] = useState(50); // Increased limit for combobox
5461
- const colLabel = formI18n.colLabel;
5642
+ // Get colLabel from schema context (we'll compute it here)
5643
+ const colLabel = `${prefix}${column}`;
5462
5644
  const watchedValue = watch(colLabel);
5463
5645
  const watchId = !isMultiple ? watchedValue : undefined;
5464
5646
  const watchIds = isMultiple
@@ -5657,20 +5839,6 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5657
5839
  itemToValue: (item) => item.value,
5658
5840
  filter: contains,
5659
5841
  });
5660
- // Handle input value change (search)
5661
- const handleInputValueChange = (details) => {
5662
- setSearchText(details.inputValue);
5663
- // Filter will be applied after data is fetched
5664
- };
5665
- // Handle value change
5666
- const handleValueChange = (details) => {
5667
- if (isMultiple) {
5668
- setValue(colLabel, details.value);
5669
- }
5670
- else {
5671
- setValue(colLabel, details.value[0] || '');
5672
- }
5673
- };
5674
5842
  // Track previous comboboxItems to avoid unnecessary updates
5675
5843
  const prevComboboxItemsRef = useRef('');
5676
5844
  const prevSearchTextRef = useRef('');
@@ -5700,8 +5868,106 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5700
5868
  // comboboxItems and searchText are the only dependencies we care about
5701
5869
  // eslint-disable-next-line react-hooks/exhaustive-deps
5702
5870
  }, [comboboxItems, searchText]);
5871
+ return {
5872
+ colLabel,
5873
+ currentValue,
5874
+ searchText,
5875
+ setSearchText,
5876
+ debouncedSearchText,
5877
+ isLoading,
5878
+ isFetching,
5879
+ isPending,
5880
+ isError,
5881
+ isSearching,
5882
+ isLoadingInitialValues,
5883
+ isFetchingInitialValues,
5884
+ missingIds,
5885
+ comboboxItems,
5886
+ collection,
5887
+ filter,
5888
+ set,
5889
+ idMap,
5890
+ idPickerLabels,
5891
+ insideDialog: insideDialog ?? false,
5892
+ renderDisplay,
5893
+ column_ref,
5894
+ errors,
5895
+ setValue,
5896
+ };
5897
+ };
5898
+
5899
+ const IdPickerSingle = ({ column, schema, prefix, }) => {
5900
+ const formI18n = useFormI18n(column, prefix, schema);
5901
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5902
+ const isRequired = required?.some((columnId) => columnId === column);
5903
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5904
+ column,
5905
+ schema,
5906
+ prefix,
5907
+ isMultiple: false,
5908
+ });
5909
+ const handleInputValueChange = (details) => {
5910
+ setSearchText(details.inputValue);
5911
+ };
5912
+ const handleValueChange = (details) => {
5913
+ setValue(colLabel, details.value[0] || '');
5914
+ };
5915
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5703
5916
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5704
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
5917
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsx(Flex, { mb: 2, children: (() => {
5918
+ const id = currentValue[0];
5919
+ const item = idMap[id];
5920
+ // Show loading skeleton while fetching initial values
5921
+ if (item === undefined &&
5922
+ (isLoadingInitialValues || isFetchingInitialValues) &&
5923
+ missingIds.includes(id)) {
5924
+ return jsx(Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
5925
+ }
5926
+ // Only show "not found" if we're not loading and item is still missing
5927
+ if (item === undefined) {
5928
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
5929
+ }
5930
+ return jsx(Text, { fontSize: "sm", children: renderDisplayFunction(item) });
5931
+ })() })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: false, closeOnSelect: true, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5932
+ ? { strategy: 'fixed', hideWhenDetached: true }
5933
+ : undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
5934
+ setValue(colLabel, '');
5935
+ } })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5936
+ // Show skeleton items to prevent UI shift
5937
+ jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5938
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5939
+ : idPickerLabels?.initialResults ??
5940
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5941
+ ? renderDisplayFunction(item.raw)
5942
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5943
+ // Show skeleton items to prevent UI shift
5944
+ jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5945
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5946
+ : idPickerLabels?.initialResults ??
5947
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5948
+ ? renderDisplayFunction(item.raw)
5949
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5950
+ };
5951
+
5952
+ const IdPickerMultiple = ({ column, schema, prefix, }) => {
5953
+ const formI18n = useFormI18n(column, prefix, schema);
5954
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5955
+ const isRequired = required?.some((columnId) => columnId === column);
5956
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5957
+ column,
5958
+ schema,
5959
+ prefix,
5960
+ isMultiple: true,
5961
+ });
5962
+ const handleInputValueChange = (details) => {
5963
+ setSearchText(details.inputValue);
5964
+ };
5965
+ const handleValueChange = (details) => {
5966
+ setValue(colLabel, details.value);
5967
+ };
5968
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5969
+ return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5970
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
5705
5971
  const item = idMap[id];
5706
5972
  // Show loading skeleton while fetching initial values
5707
5973
  if (item === undefined &&
@@ -5711,34 +5977,28 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5711
5977
  }
5712
5978
  // Only show "not found" if we're not loading and item is still missing
5713
5979
  if (item === undefined) {
5714
- return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
5980
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }, id));
5715
5981
  }
5716
5982
  return (jsx(Tag, { closable: true, onClick: () => {
5717
5983
  const newValue = currentValue.filter((itemId) => itemId !== id);
5718
5984
  setValue(colLabel, newValue);
5719
- }, children: renderDisplay
5720
- ? renderDisplay(item)
5721
- : defaultRenderDisplay(item) }, id));
5722
- }) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5985
+ }, children: renderDisplayFunction(item) }, id));
5986
+ }) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: true, closeOnSelect: false, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5723
5987
  ? { strategy: 'fixed', hideWhenDetached: true }
5724
- : undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
5725
- setValue(colLabel, '');
5726
- } })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
5988
+ : undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5727
5989
  // Show skeleton items to prevent UI shift
5728
5990
  jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5729
- ? idPickerLabels?.emptySearchResult ??
5730
- formI18n.t('empty_search_result')
5991
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5731
5992
  : idPickerLabels?.initialResults ??
5732
- formI18n.t('initial_results') })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplay === true
5733
- ? renderDisplay(item.raw)
5734
- : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
5993
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5994
+ ? renderDisplayFunction(item.raw)
5995
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5735
5996
  // Show skeleton items to prevent UI shift
5736
5997
  jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5737
- ? idPickerLabels?.emptySearchResult ??
5738
- formI18n.t('empty_search_result')
5998
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5739
5999
  : idPickerLabels?.initialResults ??
5740
- formI18n.t('initial_results') })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplay === true
5741
- ? renderDisplay(item.raw)
6000
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
6001
+ ? renderDisplayFunction(item.raw)
5742
6002
  : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5743
6003
  };
5744
6004
 
@@ -5812,7 +6072,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
5812
6072
  const colLabel = `${prefix}${column}`;
5813
6073
  const value = watch(`${colLabel}`);
5814
6074
  const fieldError = getFieldError(errors, colLabel);
5815
- const formI18n = useFormI18n$1(column, prefix, schema);
6075
+ const formI18n = useFormI18n(column, prefix, schema);
5816
6076
  return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
5817
6077
  ? fieldError.includes('required')
5818
6078
  ? formI18n.required()
@@ -5830,7 +6090,7 @@ const ObjectInput = ({ schema, column, prefix }) => {
5830
6090
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
5831
6091
  const colLabel = `${prefix}${column}`;
5832
6092
  const isRequired = required?.some((columnId) => columnId === column);
5833
- const formI18n = useFormI18n$1(column, prefix, schema);
6093
+ const formI18n = useFormI18n(column, prefix, schema);
5834
6094
  const { formState: { errors }, } = useFormContext();
5835
6095
  if (properties === undefined) {
5836
6096
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -5850,14 +6110,14 @@ const ObjectInput = ({ schema, column, prefix }) => {
5850
6110
 
5851
6111
  const RecordInput = ({ column, schema, prefix }) => {
5852
6112
  const { formState: { errors }, setValue, getValues, } = useFormContext();
5853
- const { translate } = useSchemaContext();
6113
+ const { formButtonLabels } = useSchemaContext();
5854
6114
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5855
6115
  const isRequired = required?.some((columnId) => columnId === column);
5856
6116
  const entries = Object.entries(getValues(column) ?? {});
5857
6117
  const [showNewEntries, setShowNewEntries] = useState(false);
5858
6118
  const [newKey, setNewKey] = useState();
5859
6119
  const [newValue, setNewValue] = useState();
5860
- const formI18n = useFormI18n$1(column, prefix, schema);
6120
+ const formI18n = useFormI18n(column, prefix, schema);
5861
6121
  return (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]) => {
5862
6122
  return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
5863
6123
  const filtered = entries.filter(([target]) => {
@@ -5894,11 +6154,11 @@ const RecordInput = ({ column, schema, prefix }) => {
5894
6154
  setShowNewEntries(false);
5895
6155
  setNewKey(undefined);
5896
6156
  setNewValue(undefined);
5897
- }, children: translate.t(`${column}.save`) })] })] }) }), jsx(Button, { onClick: () => {
6157
+ }, children: formButtonLabels?.save ?? 'Save' })] })] }) }), jsx(Button, { onClick: () => {
5898
6158
  setShowNewEntries(true);
5899
6159
  setNewKey(undefined);
5900
6160
  setNewValue(undefined);
5901
- }, children: translate.t(`${column}.addNew`) })] }));
6161
+ }, children: formButtonLabels?.addNew ?? 'Add New' })] }));
5902
6162
  };
5903
6163
 
5904
6164
  const StringInputField = ({ column, schema, prefix, }) => {
@@ -5907,7 +6167,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
5907
6167
  const isRequired = required?.some((columnId) => columnId === column);
5908
6168
  const colLabel = `${prefix}${column}`;
5909
6169
  const fieldError = getFieldError(errors, colLabel);
5910
- const formI18n = useFormI18n$1(column, prefix, schema);
6170
+ const formI18n = useFormI18n(column, prefix, schema);
5911
6171
  return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
5912
6172
  };
5913
6173
 
@@ -6099,7 +6359,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6099
6359
  const form = useFormContext();
6100
6360
  const { setValue, watch } = form;
6101
6361
  const fieldError = getFieldError(errors, colLabel);
6102
- const formI18n = useFormI18n$1(column, prefix, schema);
6362
+ const formI18n = useFormI18n(column, prefix, schema);
6103
6363
  const watchValue = watch(colLabel);
6104
6364
  return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
6105
6365
  ? fieldError.includes('required')
@@ -6110,18 +6370,13 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6110
6370
 
6111
6371
  dayjs.extend(utc);
6112
6372
  dayjs.extend(timezone);
6113
- function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
6114
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6115
- meridiemLabel: _meridiemLabel = {
6116
- am: 'am',
6117
- pm: 'pm',
6118
- },
6119
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6120
- onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedDate, portalled = true, }) {
6121
- // Generate time options (every 15 minutes)
6373
+ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem, onChange = () => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6374
+ placeholder: 'hh:mm AM/PM',
6375
+ emptyMessage: 'No time found',
6376
+ }, }) => {
6377
+ // Generate time options (every 15 minutes in 12-hour format)
6122
6378
  const timeOptions = useMemo(() => {
6123
6379
  const options = [];
6124
- const meridiemOptions = ['am', 'pm'];
6125
6380
  // Get start time for comparison if provided
6126
6381
  let startDateTime = null;
6127
6382
  let shouldFilterByDate = false;
@@ -6136,14 +6391,16 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6136
6391
  selectedDateObj.format('YYYY-MM-DD');
6137
6392
  }
6138
6393
  }
6139
- for (const mer of meridiemOptions) {
6140
- for (let h = 1; h <= 12; h++) {
6141
- for (let m = 0; m < 60; m += 15) {
6142
- const hour24 = mer === 'am' ? (h === 12 ? 0 : h) : h === 12 ? 12 : h + 12;
6143
- // Format time directly without using dayjs with dummy dates
6144
- const formattedHour = h.toString().padStart(2, '0');
6145
- const formattedMinute = m.toString().padStart(2, '0');
6146
- const displayTime = `${formattedHour}:${formattedMinute} ${mer}`;
6394
+ // Generate 12-hour format options (1-12 for hours, AM/PM)
6395
+ for (let h = 1; h <= 12; h++) {
6396
+ for (let m = 0; m < 60; m += 15) {
6397
+ for (const mer of ['am', 'pm']) {
6398
+ // Convert 12-hour to 24-hour for comparison
6399
+ let hour24 = h;
6400
+ if (mer === 'am' && h === 12)
6401
+ hour24 = 0;
6402
+ else if (mer === 'pm' && h < 12)
6403
+ hour24 = h + 12;
6147
6404
  // Filter out times that would result in negative duration (only when dates are the same)
6148
6405
  if (startDateTime && selectedDate && shouldFilterByDate) {
6149
6406
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
@@ -6186,20 +6443,23 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6186
6443
  }
6187
6444
  }
6188
6445
  }
6446
+ const hourDisplay = h.toString();
6447
+ const minuteDisplay = m.toString().padStart(2, '0');
6448
+ const timeDisplay = `${hourDisplay}:${minuteDisplay} ${mer.toUpperCase()}`;
6189
6449
  options.push({
6190
- label: displayTime,
6191
- value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
6450
+ label: timeDisplay,
6451
+ value: `${h}:${m}:${mer}`,
6192
6452
  hour: h,
6193
6453
  minute: m,
6194
6454
  meridiem: mer,
6195
- searchText: displayTime, // Use base time without duration for searching
6455
+ searchText: timeDisplay, // Use base time without duration for searching
6196
6456
  durationText,
6197
6457
  });
6198
6458
  }
6199
6459
  }
6200
6460
  }
6201
6461
  return options;
6202
- }, [timezone, startTime, selectedDate]);
6462
+ }, [startTime, selectedDate, timezone]);
6203
6463
  const { contains } = useFilter({ sensitivity: 'base' });
6204
6464
  const { collection, filter } = useListCollection({
6205
6465
  initialItems: timeOptions,
@@ -6212,7 +6472,7 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6212
6472
  if (hour === null || minute === null || meridiem === null) {
6213
6473
  return '';
6214
6474
  }
6215
- return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
6475
+ return `${hour}:${minute}:${meridiem}`;
6216
6476
  }, [hour, minute, meridiem]);
6217
6477
  // Calculate duration difference
6218
6478
  const durationDiff = useMemo(() => {
@@ -6223,15 +6483,14 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6223
6483
  meridiem === null) {
6224
6484
  return null;
6225
6485
  }
6226
- const hour24 = meridiem === 'am'
6227
- ? hour === 12
6228
- ? 0
6229
- : hour
6230
- : hour === 12
6231
- ? 12
6232
- : hour + 12;
6233
6486
  const startDateObj = dayjs(startTime).tz(timezone);
6234
6487
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
6488
+ // Convert 12-hour to 24-hour format
6489
+ let hour24 = hour;
6490
+ if (meridiem === 'am' && hour === 12)
6491
+ hour24 = 0;
6492
+ else if (meridiem === 'pm' && hour < 12)
6493
+ hour24 = hour + 12;
6235
6494
  const currentDateTime = selectedDateObj
6236
6495
  .hour(hour24)
6237
6496
  .minute(minute)
@@ -6296,83 +6555,54 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6296
6555
  if (!trimmedValue) {
6297
6556
  return;
6298
6557
  }
6299
- // Try to parse custom input using explicit regex patterns
6300
- const normalized = trimmedValue.toLowerCase().replace(/\s+/g, '');
6301
- // Pattern 1: 12-hour format with meridiem (e.g., "930pm", "1230am", "9:30pm", "12:30am")
6302
- // Matches: 1-2 digits hour, optional colon, 2 digits minute, am/pm
6303
- const pattern12HourWithMeridiem = /^(\d{1,2}):?(\d{2})(am|pm)$/;
6304
- const match12Hour = normalized.match(pattern12HourWithMeridiem);
6558
+ // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6559
+ const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6560
+ const match12Hour = trimmedValue.match(timePattern12Hour);
6305
6561
  if (match12Hour) {
6306
6562
  const parsedHour = parseInt(match12Hour[1], 10);
6307
6563
  const parsedMinute = parseInt(match12Hour[2], 10);
6308
- const parsedMeridiem = match12Hour[3];
6309
- // Validate hour (1-12)
6310
- if (parsedHour < 1 || parsedHour > 12) {
6311
- // Parse failed, select first result
6312
- selectFirstResult();
6313
- return;
6314
- }
6315
- // Validate minute (0-59)
6316
- if (parsedMinute < 0 || parsedMinute > 59) {
6317
- // Parse failed, select first result
6318
- selectFirstResult();
6564
+ const parsedMeridiem = match12Hour[3].toLowerCase();
6565
+ // Validate ranges
6566
+ if (parsedHour >= 1 &&
6567
+ parsedHour <= 12 &&
6568
+ parsedMinute >= 0 &&
6569
+ parsedMinute <= 59) {
6570
+ setHour(parsedHour);
6571
+ setMinute(parsedMinute);
6572
+ setMeridiem(parsedMeridiem);
6573
+ onChange({
6574
+ hour: parsedHour,
6575
+ minute: parsedMinute,
6576
+ meridiem: parsedMeridiem,
6577
+ });
6319
6578
  return;
6320
6579
  }
6321
- setHour(parsedHour);
6322
- setMinute(parsedMinute);
6323
- setMeridiem(parsedMeridiem);
6324
- onChange({
6325
- hour: parsedHour,
6326
- minute: parsedMinute,
6327
- meridiem: parsedMeridiem,
6328
- });
6329
- return;
6330
6580
  }
6331
- // Pattern 2: 24-hour format (e.g., "2130", "09:30", "21:30")
6332
- // Matches: 1-2 digits hour, optional colon, 2 digits minute
6333
- const pattern24Hour = /^(\d{1,2}):?(\d{2})$/;
6334
- const match24Hour = normalized.match(pattern24Hour);
6335
- if (match24Hour) {
6336
- let parsedHour = parseInt(match24Hour[1], 10);
6337
- const parsedMinute = parseInt(match24Hour[2], 10);
6338
- // Validate hour (0-23)
6339
- if (parsedHour < 0 || parsedHour > 23) {
6340
- // Parse failed, select first result
6341
- selectFirstResult();
6342
- return;
6343
- }
6344
- // Validate minute (0-59)
6345
- if (parsedMinute < 0 || parsedMinute > 59) {
6346
- // Parse failed, select first result
6347
- selectFirstResult();
6348
- return;
6349
- }
6350
- // Convert 24-hour to 12-hour format
6351
- let parsedMeridiem;
6352
- if (parsedHour === 0) {
6353
- parsedHour = 12;
6354
- parsedMeridiem = 'am';
6355
- }
6356
- else if (parsedHour === 12) {
6357
- parsedHour = 12;
6358
- parsedMeridiem = 'pm';
6359
- }
6360
- else if (parsedHour > 12) {
6361
- parsedHour = parsedHour - 12;
6362
- parsedMeridiem = 'pm';
6363
- }
6364
- else {
6365
- parsedMeridiem = 'am';
6581
+ // Try to parse formats like "130pm" or "130 pm" (without colon)
6582
+ const timePatternNoColon = /^(\d{1,4})\s*(am|pm|AM|PM)$/i;
6583
+ const matchNoColon = trimmedValue.match(timePatternNoColon);
6584
+ if (matchNoColon) {
6585
+ const numbersOnly = matchNoColon[1];
6586
+ const parsedMeridiem = matchNoColon[2].toLowerCase();
6587
+ if (numbersOnly.length >= 3) {
6588
+ const parsedHour = parseInt(numbersOnly.slice(0, -2), 10);
6589
+ const parsedMinute = parseInt(numbersOnly.slice(-2), 10);
6590
+ // Validate ranges
6591
+ if (parsedHour >= 1 &&
6592
+ parsedHour <= 12 &&
6593
+ parsedMinute >= 0 &&
6594
+ parsedMinute <= 59) {
6595
+ setHour(parsedHour);
6596
+ setMinute(parsedMinute);
6597
+ setMeridiem(parsedMeridiem);
6598
+ onChange({
6599
+ hour: parsedHour,
6600
+ minute: parsedMinute,
6601
+ meridiem: parsedMeridiem,
6602
+ });
6603
+ return;
6604
+ }
6366
6605
  }
6367
- setHour(parsedHour);
6368
- setMinute(parsedMinute);
6369
- setMeridiem(parsedMeridiem);
6370
- onChange({
6371
- hour: parsedHour,
6372
- minute: parsedMinute,
6373
- meridiem: parsedMeridiem,
6374
- });
6375
- return;
6376
6606
  }
6377
6607
  // Parse failed, select first result
6378
6608
  selectFirstResult();
@@ -6419,17 +6649,17 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6419
6649
  e.currentTarget?.blur();
6420
6650
  }
6421
6651
  };
6422
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: "hh:mm a", onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", colorPalette: "blue", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
6423
- }
6652
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: labels?.placeholder ?? 'hh:mm AM/PM', onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels?.emptyMessage ?? 'No time found' }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
6653
+ };
6424
6654
 
6425
6655
  dayjs.extend(timezone);
6426
6656
  const TimePicker = ({ column, schema, prefix }) => {
6427
6657
  const { watch, formState: { errors }, setValue, } = useFormContext();
6428
- const { timezone, insideDialog } = useSchemaContext();
6658
+ const { timezone, insideDialog, timePickerLabels } = useSchemaContext();
6429
6659
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
6430
6660
  const isRequired = required?.some((columnId) => columnId === column);
6431
6661
  const colLabel = `${prefix}${column}`;
6432
- const formI18n = useFormI18n$1(column, prefix, schema);
6662
+ const formI18n = useFormI18n(column, prefix, schema);
6433
6663
  const [open, setOpen] = useState(false);
6434
6664
  const value = watch(colLabel);
6435
6665
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
@@ -6487,7 +6717,7 @@ const TimePicker = ({ column, schema, prefix }) => {
6487
6717
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6488
6718
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6489
6719
  setOpen(true);
6490
- }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange }) }) }) }) }))] }) }));
6720
+ }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) }) }))] }) }));
6491
6721
  };
6492
6722
 
6493
6723
  dayjs.extend(utc);
@@ -6621,7 +6851,10 @@ dayjs.extend(utc);
6621
6851
  dayjs.extend(timezone);
6622
6852
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6623
6853
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6624
- onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, }) {
6854
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6855
+ placeholder: 'HH:mm:ss',
6856
+ emptyMessage: 'No time found',
6857
+ }, }) {
6625
6858
  // Generate time options (every 15 minutes, seconds always 0)
6626
6859
  const timeOptions = useMemo(() => {
6627
6860
  const options = [];
@@ -6884,7 +7117,7 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
6884
7117
  e.currentTarget?.blur();
6885
7118
  }
6886
7119
  };
6887
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: "HH:mm:ss", onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
7120
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: labels.placeholder, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels.emptyMessage }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
6888
7121
  }
6889
7122
 
6890
7123
  dayjs.extend(utc);
@@ -6907,7 +7140,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
6907
7140
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6908
7141
  backButtonLabel: 'Back',
6909
7142
  forwardButtonLabel: 'Next',
6910
- }, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7143
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
6911
7144
  console.log('[DateTimePicker] Component initialized with props:', {
6912
7145
  value,
6913
7146
  format,
@@ -7353,7 +7586,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7353
7586
  const dateObj = dayjs.tz(selectedDate, timezone);
7354
7587
  return dateObj.isValid() ? dateObj.format('Z') : null;
7355
7588
  }, [selectedDate, timezone]);
7356
- return (jsxs(Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7589
+ return (jsxs(Flex, { direction: "column", gap: 4, children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7357
7590
  if (date) {
7358
7591
  handleDateChange(date);
7359
7592
  }
@@ -7361,15 +7594,15 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7361
7594
  setSelectedDate('');
7362
7595
  onChange?.(undefined);
7363
7596
  }
7364
- }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (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 })) : (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 })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7597
+ }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (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 })) : (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 })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7365
7598
  }
7366
7599
 
7367
7600
  dayjs.extend(utc);
7368
7601
  dayjs.extend(timezone);
7369
7602
  const DateTimePicker = ({ column, schema, prefix, }) => {
7370
7603
  const { watch, formState: { errors }, setValue, } = useFormContext();
7371
- const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
7372
- const formI18n = useFormI18n$1(column, prefix, schema);
7604
+ const { timezone, dateTimePickerLabels, timePickerLabels, insideDialog } = useSchemaContext();
7605
+ const formI18n = useFormI18n(column, prefix, schema);
7373
7606
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
7374
7607
  // with timezone
7375
7608
  dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
@@ -7382,74 +7615,30 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7382
7615
  : '';
7383
7616
  const dateTimePickerLabelsConfig = {
7384
7617
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
7385
- formI18n.translate.t(`common.month_1`, {
7386
- defaultValue: 'January',
7387
- }),
7388
- formI18n.translate.t(`common.month_2`, {
7389
- defaultValue: 'February',
7390
- }),
7391
- formI18n.translate.t(`common.month_3`, {
7392
- defaultValue: 'March',
7393
- }),
7394
- formI18n.translate.t(`common.month_4`, {
7395
- defaultValue: 'April',
7396
- }),
7397
- formI18n.translate.t(`common.month_5`, {
7398
- defaultValue: 'May',
7399
- }),
7400
- formI18n.translate.t(`common.month_6`, {
7401
- defaultValue: 'June',
7402
- }),
7403
- formI18n.translate.t(`common.month_7`, {
7404
- defaultValue: 'July',
7405
- }),
7406
- formI18n.translate.t(`common.month_8`, {
7407
- defaultValue: 'August',
7408
- }),
7409
- formI18n.translate.t(`common.month_9`, {
7410
- defaultValue: 'September',
7411
- }),
7412
- formI18n.translate.t(`common.month_10`, {
7413
- defaultValue: 'October',
7414
- }),
7415
- formI18n.translate.t(`common.month_11`, {
7416
- defaultValue: 'November',
7417
- }),
7418
- formI18n.translate.t(`common.month_12`, {
7419
- defaultValue: 'December',
7420
- }),
7618
+ 'January',
7619
+ 'February',
7620
+ 'March',
7621
+ 'April',
7622
+ 'May',
7623
+ 'June',
7624
+ 'July',
7625
+ 'August',
7626
+ 'September',
7627
+ 'October',
7628
+ 'November',
7629
+ 'December',
7421
7630
  ],
7422
7631
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
7423
- formI18n.translate.t(`common.weekday_1`, {
7424
- defaultValue: 'Sun',
7425
- }),
7426
- formI18n.translate.t(`common.weekday_2`, {
7427
- defaultValue: 'Mon',
7428
- }),
7429
- formI18n.translate.t(`common.weekday_3`, {
7430
- defaultValue: 'Tue',
7431
- }),
7432
- formI18n.translate.t(`common.weekday_4`, {
7433
- defaultValue: 'Wed',
7434
- }),
7435
- formI18n.translate.t(`common.weekday_5`, {
7436
- defaultValue: 'Thu',
7437
- }),
7438
- formI18n.translate.t(`common.weekday_6`, {
7439
- defaultValue: 'Fri',
7440
- }),
7441
- formI18n.translate.t(`common.weekday_7`, {
7442
- defaultValue: 'Sat',
7443
- }),
7632
+ 'Sun',
7633
+ 'Mon',
7634
+ 'Tue',
7635
+ 'Wed',
7636
+ 'Thu',
7637
+ 'Fri',
7638
+ 'Sat',
7444
7639
  ],
7445
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
7446
- formI18n.translate.t(`common.back_button`, {
7447
- defaultValue: 'Back',
7448
- }),
7449
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
7450
- formI18n.translate.t(`common.forward_button`, {
7451
- defaultValue: 'Forward',
7452
- }),
7640
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
7641
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
7453
7642
  };
7454
7643
  const dateTimePickerContent = (jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
7455
7644
  if (!date || date === null || date === undefined) {
@@ -7463,7 +7652,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7463
7652
  else {
7464
7653
  setValue(colLabel, undefined);
7465
7654
  }
7466
- }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
7655
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels }));
7467
7656
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7468
7657
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
7469
7658
  setOpen(true);
@@ -7482,7 +7671,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7482
7671
  }
7483
7672
  if (variant === 'id-picker') {
7484
7673
  idPickerSanityCheck(column, foreign_key);
7485
- return jsx(IdPicker, { schema: colSchema, prefix, column });
7674
+ return jsx(IdPickerSingle, { schema: colSchema, prefix, column });
7486
7675
  }
7487
7676
  if (format === 'date') {
7488
7677
  return jsx(DatePicker, { schema: colSchema, prefix, column });
@@ -7516,7 +7705,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7516
7705
  if (type === 'array') {
7517
7706
  if (variant === 'id-picker') {
7518
7707
  idPickerSanityCheck(column, foreign_key);
7519
- return (jsx(IdPicker, { schema: colSchema, prefix, column, isMultiple: true }));
7708
+ return jsx(IdPickerMultiple, { schema: colSchema, prefix, column });
7520
7709
  }
7521
7710
  if (variant === 'tag-picker') {
7522
7711
  return jsx(TagPicker, { schema: colSchema, prefix, column });
@@ -7568,7 +7757,7 @@ const ArrayViewer = ({ schema, column, prefix }) => {
7568
7757
  const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
7569
7758
  const colLabel = `${prefix}${column}`;
7570
7759
  const isRequired = required?.some((columnId) => columnId === column);
7571
- const formI18n = useFormI18n$1(column, prefix, schema);
7760
+ const formI18n = useFormI18n(column, prefix, schema);
7572
7761
  const { watch, formState: { errors }, } = useFormContext();
7573
7762
  const values = watch(colLabel) ?? [];
7574
7763
  return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: '1/span12', children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: 'column', gap: 1, children: values.map((field, index) => (jsx(Flex, { flexFlow: 'column', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '2', borderRadius: 'md', borderWidth: 'thin', borderColor: {
@@ -7586,7 +7775,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
7586
7775
  const isRequired = required?.some((columnId) => columnId === column);
7587
7776
  const colLabel = `${prefix}${column}`;
7588
7777
  const value = watch(colLabel);
7589
- const formI18n = useFormI18n$1(column, prefix, schema);
7778
+ const formI18n = useFormI18n(column, prefix, schema);
7590
7779
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7591
7780
  gridRow, children: [jsx(Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
7592
7781
  };
@@ -7610,7 +7799,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7610
7799
  const isRequired = required?.some((columnId) => columnId === column);
7611
7800
  const colLabel = `${prefix}${column}`;
7612
7801
  const selectedDate = watch(colLabel);
7613
- const formI18n = useFormI18n$1(column, prefix, schema);
7802
+ const formI18n = useFormI18n(column, prefix, schema);
7614
7803
  const displayDate = dayjs(selectedDate)
7615
7804
  .tz(timezone)
7616
7805
  .format(displayDateFormat);
@@ -7620,7 +7809,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7620
7809
 
7621
7810
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
7622
7811
  const { watch, formState: { errors }, } = useFormContext();
7623
- const formI18n = useFormI18n$1(column, prefix);
7812
+ const formI18n = useFormI18n(column, prefix);
7624
7813
  const { required } = schema;
7625
7814
  const isRequired = required?.some((columnId) => columnId === column);
7626
7815
  const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
@@ -7644,7 +7833,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7644
7833
  const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
7645
7834
  const isRequired = required?.some((columnId) => columnId === column);
7646
7835
  const currentFiles = (watch(column) ?? []);
7647
- const formI18n = useFormI18n$1(column, prefix, schema);
7836
+ const formI18n = useFormI18n(column, prefix, schema);
7648
7837
  return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', children: jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
7649
7838
  return (jsx(Card.Root, { variant: 'subtle', children: jsxs(Card.Body, { gap: "2", display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name })] }) }, file.name));
7650
7839
  }) }) }));
@@ -7652,7 +7841,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7652
7841
 
7653
7842
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7654
7843
  const { watch, formState: { errors }, } = useFormContext();
7655
- const { idMap, translate } = useSchemaContext();
7844
+ const { idMap, idPickerLabels, formButtonLabels } = useSchemaContext();
7656
7845
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7657
7846
  const isRequired = required?.some((columnId) => columnId === column);
7658
7847
  const formI18n = useFormI18n(column, prefix, schema);
@@ -7676,12 +7865,12 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7676
7865
  gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
7677
7866
  const item = idMap[id];
7678
7867
  if (item === undefined) {
7679
- return (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
7868
+ return (jsx(Text, { children: idPickerLabels?.undefined ?? 'Undefined' }, id));
7680
7869
  }
7681
7870
  return (jsx(Tag, { closable: true, children: renderDisplay
7682
7871
  ? renderDisplay(item)
7683
7872
  : defaultRenderDisplay(item) }, id));
7684
- }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
7873
+ }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: formButtonLabels?.fieldRequired ?? formI18n.required() }))] }));
7685
7874
  };
7686
7875
 
7687
7876
  const NumberViewer = ({ schema, column, prefix, }) => {
@@ -7690,7 +7879,7 @@ const NumberViewer = ({ schema, column, prefix, }) => {
7690
7879
  const isRequired = required?.some((columnId) => columnId === column);
7691
7880
  const colLabel = `${prefix}${column}`;
7692
7881
  const value = watch(colLabel);
7693
- const formI18n = useFormI18n$1(column, prefix, schema);
7882
+ const formI18n = useFormI18n(column, prefix, schema);
7694
7883
  // Format the value for display if formatOptions are provided
7695
7884
  const formatValue = (val) => {
7696
7885
  if (val === undefined || val === null || val === '')
@@ -7716,7 +7905,7 @@ const ObjectViewer = ({ schema, column, prefix }) => {
7716
7905
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
7717
7906
  const colLabel = `${prefix}${column}`;
7718
7907
  const isRequired = required?.some((columnId) => columnId === column);
7719
- const formI18n = useFormI18n$1(column, prefix, schema);
7908
+ const formI18n = useFormI18n(column, prefix, schema);
7720
7909
  const { formState: { errors }, } = useFormContext();
7721
7910
  if (properties === undefined) {
7722
7911
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -7738,7 +7927,7 @@ const RecordViewer = ({ column, schema, prefix }) => {
7738
7927
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
7739
7928
  const isRequired = required?.some((columnId) => columnId === column);
7740
7929
  const entries = Object.entries(getValues(column) ?? {});
7741
- const formI18n = useFormI18n$1(column, prefix, schema);
7930
+ const formI18n = useFormI18n(column, prefix, schema);
7742
7931
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, children: [entries.length === 0 ? (jsx(Text, { color: "gray.500", children: "No entries" })) : (jsx(Grid, { templateColumns: '1fr 1fr', gap: 2, children: entries.map(([key, value]) => {
7743
7932
  return (jsxs(Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxs(Text, { fontWeight: "medium", children: [key, ":"] }), jsx(Text, { children: String(value ?? '') })] }, key));
7744
7933
  }) })), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
@@ -7750,7 +7939,7 @@ const StringViewer = ({ column, schema, prefix, }) => {
7750
7939
  const isRequired = required?.some((columnId) => columnId === column);
7751
7940
  const colLabel = `${prefix}${column}`;
7752
7941
  const value = watch(colLabel);
7753
- const formI18n = useFormI18n$1(column, prefix, schema);
7942
+ const formI18n = useFormI18n(column, prefix, schema);
7754
7943
  return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7755
7944
  };
7756
7945
 
@@ -7845,7 +8034,7 @@ const TextAreaViewer = ({ column, schema, prefix, }) => {
7845
8034
  const isRequired = required?.some((columnId) => columnId === column);
7846
8035
  const colLabel = `${prefix}${column}`;
7847
8036
  const value = watch(colLabel);
7848
- const formI18n = useFormI18n$1(column, prefix, schema);
8037
+ const formI18n = useFormI18n(column, prefix, schema);
7849
8038
  return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), ' ', errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7850
8039
  };
7851
8040
 
@@ -7856,7 +8045,7 @@ const TimeViewer = ({ column, schema, prefix }) => {
7856
8045
  const isRequired = required?.some((columnId) => columnId === column);
7857
8046
  const colLabel = `${prefix}${column}`;
7858
8047
  const selectedDate = watch(colLabel);
7859
- const formI18n = useFormI18n$1(column, prefix, schema);
8048
+ const formI18n = useFormI18n(column, prefix, schema);
7860
8049
  const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
7861
8050
  .tz(timezone)
7862
8051
  .isValid()
@@ -7873,7 +8062,7 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
7873
8062
  const isRequired = required?.some((columnId) => columnId === column);
7874
8063
  const colLabel = `${prefix}${column}`;
7875
8064
  const selectedDate = watch(colLabel);
7876
- const formI18n = useFormI18n$1(column, prefix, schema);
8065
+ const formI18n = useFormI18n(column, prefix, schema);
7877
8066
  const displayDate = dayjs(selectedDate)
7878
8067
  .tz(timezone)
7879
8068
  .format(displayDateFormat);
@@ -7967,7 +8156,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
7967
8156
  };
7968
8157
 
7969
8158
  const SubmitButton = () => {
7970
- const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
8159
+ const { setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
7971
8160
  const methods = useFormContext();
7972
8161
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7973
8162
  const onValid = (data) => {
@@ -7996,11 +8185,11 @@ const SubmitButton = () => {
7996
8185
  };
7997
8186
  return (jsx(Button$1, { onClick: () => {
7998
8187
  methods.handleSubmit(onValid)();
7999
- }, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
8188
+ }, formNoValidate: true, children: formButtonLabels?.submit ?? 'Submit' }));
8000
8189
  };
8001
8190
 
8002
8191
  const FormBody = () => {
8003
- const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8192
+ const { schema, order, ignore, include, isError, isSubmiting, isConfirming, setIsConfirming, validatedData, error, customErrorRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8004
8193
  const { showSubmitButton, showResetButton } = displayConfig;
8005
8194
  const methods = useFormContext();
8006
8195
  const { properties } = schema;
@@ -8017,21 +8206,6 @@ const FormBody = () => {
8017
8206
  ignore,
8018
8207
  include,
8019
8208
  });
8020
- if (isSuccess) {
8021
- const resetHandler = async () => {
8022
- setIsError(false);
8023
- setIsSubmiting(false);
8024
- setIsSuccess(false);
8025
- setIsConfirming(false);
8026
- setValidatedData(undefined);
8027
- const data = await getUpdatedData();
8028
- methods.reset(data);
8029
- };
8030
- if (customSuccessRenderer) {
8031
- return customSuccessRenderer(resetHandler);
8032
- }
8033
- return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Title, { children: translate.t('submit_success') }) })] }), jsx(Flex, { justifyContent: 'end', children: jsx(Button$1, { onClick: resetHandler, formNoValidate: true, children: formButtonLabels?.submitAgain ?? translate.t('submit_again') }) })] }));
8034
- }
8035
8209
  if (isConfirming) {
8036
8210
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
8037
8211
  return (jsx(ColumnViewer
@@ -8041,9 +8215,9 @@ const FormBody = () => {
8041
8215
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
8042
8216
  }) }), jsxs(Flex, { justifyContent: 'end', gap: '2', children: [jsx(Button$1, { onClick: () => {
8043
8217
  setIsConfirming(false);
8044
- }, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsx(Button$1, { onClick: () => {
8218
+ }, variant: 'subtle', children: formButtonLabels?.cancel ?? 'Cancel' }), jsx(Button$1, { onClick: () => {
8045
8219
  onFormSubmit(validatedData);
8046
- }, children: formButtonLabels?.confirm ?? translate.t('confirm') })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8220
+ }, children: formButtonLabels?.confirm ?? 'Confirm' })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8047
8221
  }
8048
8222
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
8049
8223
  return (jsx(ColumnRenderer
@@ -8053,12 +8227,12 @@ const FormBody = () => {
8053
8227
  properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
8054
8228
  }) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
8055
8229
  methods.reset();
8056
- }, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8230
+ }, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8057
8231
  };
8058
8232
 
8059
8233
  const FormTitle = () => {
8060
- const { translate } = useSchemaContext();
8061
- return jsx(Heading, { children: translate.t("title") });
8234
+ const { schema } = useSchemaContext();
8235
+ return jsx(Heading, { children: schema.title ?? 'Form' });
8062
8236
  };
8063
8237
 
8064
8238
  const DefaultForm = ({ formConfig, }) => {
@@ -8066,7 +8240,9 @@ const DefaultForm = ({ formConfig, }) => {
8066
8240
  return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
8067
8241
  };
8068
8242
 
8069
- const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8243
+ const useForm = ({ preLoadedValues, keyPrefix: _keyPrefix, // Deprecated: kept for backward compatibility
8244
+ namespace: _namespace, // Deprecated: kept for backward compatibility
8245
+ schema, }) => {
8070
8246
  const form = useForm$1({
8071
8247
  values: preLoadedValues,
8072
8248
  resolver: schema ? ajvResolver(schema) : undefined,
@@ -8074,12 +8250,16 @@ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8074
8250
  reValidateMode: 'onBlur',
8075
8251
  });
8076
8252
  const [idMap, setIdMap] = useState({});
8077
- const translate = useTranslation(namespace || '', { keyPrefix });
8253
+ // Fallback translate object - returns key as-is (no i18n required)
8254
+ const translate = {
8255
+ t: (key) => key,
8256
+ ready: true,
8257
+ };
8078
8258
  return {
8079
8259
  form,
8080
8260
  idMap,
8081
8261
  setIdMap,
8082
- translate,
8262
+ translate, // Components prefer label objects over translate
8083
8263
  };
8084
8264
  };
8085
8265
 
@@ -8407,6 +8587,21 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
8407
8587
  })] }));
8408
8588
  };
8409
8589
 
8590
+ const MobileTableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsx(Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsx(Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
8591
+ const { tableLabel, table } = useDataTableContext();
8592
+ const { hasErrorText } = tableLabel;
8593
+ return (jsxs(Grid, { templateRows: 'auto 1fr auto', width: fitTableWidth ? 'fit-content' : '100%', height: fitTableHeight ? 'fit-content' : '100%', gap: 2, padding: 2, ...gridProps, children: [jsxs(Stack, { gap: 2, children: [jsxs(Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, children: [jsxs(Flex, { gap: 1, alignItems: 'center', children: [showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }), loading && jsx(Spinner, { size: 'sm' }), hasError && (jsx(Tooltip, { content: hasErrorText, children: jsx(Icon, { as: BsExclamationCircleFill, color: 'red.400' }) }))] }), jsxs(Flex, { gap: 1, alignItems: 'center', children: [showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsx(Stack, { gap: 2, children: filterTagsOptions.map((option) => {
8594
+ const { column, options } = option;
8595
+ const tableColumn = table.getColumn(column);
8596
+ return (jsxs(Flex, { flexFlow: 'column', gap: 1, width: '100%', children: [tableColumn?.columnDef.meta?.displayName && (jsx(Text, { fontSize: 'sm', fontWeight: 'medium', children: tableColumn?.columnDef.meta?.displayName })), jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
8597
+ if (tags.length === 0) {
8598
+ return tableColumn?.setFilterValue(undefined);
8599
+ }
8600
+ tableColumn?.setFilterValue(tags);
8601
+ } })] }, column));
8602
+ }) })), showFilterTags && (jsx(Box, { width: '100%', children: jsx(TableFilterTags, {}) }))] }), jsx(Box, { overflow: 'auto', width: '100%', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, borderRadius: 'md', padding: 1, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxs(Stack, { gap: 2, width: '100%', children: [(showPageSizeControl || showPageCountText) && (jsxs(Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, flexWrap: 'wrap', children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && jsx(RowCountText, {})] })), showPagination && (jsx(Flex, { justifyContent: 'center', width: '100%', children: jsx(Pagination, {}) }))] }))] }));
8603
+ };
8604
+
8410
8605
  const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
8411
8606
  'use no memo';
8412
8607
  const { table } = useDataTableContext();
@@ -8466,7 +8661,68 @@ const TableRowSelectorSkeleton = () => {
8466
8661
  bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsx(Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
8467
8662
  };
8468
8663
 
8664
+ const MobileTableDisplay = ({ showSelector = false, isLoading = false, }) => {
8665
+ const { table, rowSelection, setRowSelection } = useDataTableContext();
8666
+ if (isLoading) {
8667
+ return jsx(MobileTableSkeleton, { showSelector: showSelector });
8668
+ }
8669
+ return (jsx(Stack, { gap: 4, padding: 2, children: table.getRowModel().rows.map((row) => {
8670
+ return (jsx(Card.Root, { width: "100%", children: jsxs(Card.Body, { padding: 4, children: [showSelector && (jsx(Flex, { marginBottom: 3, children: jsx(Checkbox, { checked: isRowSelected(row.id, rowSelection),
8671
+ disabled: !canRowSelect(row),
8672
+ onCheckedChange: createRowToggleHandler(row, rowSelection, setRowSelection) }) })), jsx(Stack, { gap: 3, children: row.getVisibleCells().map((cell) => {
8673
+ const displayName = cell.column.columnDef.meta?.displayName ?? cell.column.id;
8674
+ return (jsxs(Box, { children: [jsx(Text, { fontSize: "sm", fontWeight: "bold", color: { base: 'gray.600', _dark: 'gray.400' }, marginBottom: 1, children: displayName }), jsx(Box, { color: { base: 'gray.900', _dark: 'gray.100' }, fontSize: "sm", children: flexRender(cell.column.columnDef.cell, cell.getContext()) })] }, `mobile-table-cell-${cell.id}`));
8675
+ }) })] }) }, `mobile-table-card-${row.id}`));
8676
+ }) }));
8677
+ };
8678
+ const MobileTableSkeleton = ({ showSelector = false, }) => {
8679
+ const { table } = useDataTableContext();
8680
+ const pageSize = table.getState().pagination.pageSize;
8681
+ const visibleColumns = table.getVisibleLeafColumns();
8682
+ return (jsx(Stack, { gap: 4, padding: 2, children: Array.from({ length: pageSize }).map((_, rowIndex) => {
8683
+ return (jsx(Card.Root, { width: "100%", children: jsxs(Card.Body, { padding: 4, children: [showSelector && (jsx(Flex, { marginBottom: 3, children: jsx(Box, { width: "20px", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "md" }) })), jsx(Stack, { gap: 3, children: visibleColumns.map((column) => {
8684
+ return (jsxs(Box, { children: [jsx(Box, { width: "40%", height: "16px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm", marginBottom: 2 }), jsx(Box, { width: "80%", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm" })] }, `mobile-skeleton-cell-${column.id}`));
8685
+ }) })] }) }, `mobile-skeleton-${rowIndex}`));
8686
+ }) }));
8687
+ };
8688
+
8689
+ /**
8690
+ * Hook to detect if the current window width is mobile (< 768px)
8691
+ * @param breakpoint - The breakpoint in pixels to consider as mobile (default: 768)
8692
+ * @returns boolean indicating if the window is mobile
8693
+ */
8694
+ const useIsMobile = (breakpoint = 768) => {
8695
+ const [isMobile, setIsMobile] = useState(() => {
8696
+ if (typeof window === 'undefined')
8697
+ return false;
8698
+ return window.innerWidth < breakpoint;
8699
+ });
8700
+ useEffect(() => {
8701
+ if (typeof window === 'undefined')
8702
+ return;
8703
+ const handleResize = () => {
8704
+ setIsMobile(window.innerWidth < breakpoint);
8705
+ };
8706
+ // Set initial value
8707
+ handleResize();
8708
+ // Add event listener
8709
+ window.addEventListener('resize', handleResize);
8710
+ // Cleanup
8711
+ return () => {
8712
+ window.removeEventListener('resize', handleResize);
8713
+ };
8714
+ }, [breakpoint]);
8715
+ return isMobile;
8716
+ };
8717
+
8469
8718
  const DefaultTable = ({ showFooter = false, showHeader = true, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = 'greedy', isLoading = false, }) => {
8719
+ const isMobile = useIsMobile();
8720
+ // Early return for mobile display
8721
+ if (isMobile) {
8722
+ return (jsx(MobileTableControls, { ...controlProps, children: jsx(MobileTableDisplay, { showSelector: tableHeaderProps.showSelector ??
8723
+ tableBodyProps.showSelector ??
8724
+ false, isLoading: isLoading }) }));
8725
+ }
8470
8726
  const isGreedy = variant === 'greedy';
8471
8727
  const canResize = !isGreedy;
8472
8728
  const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: canResize })) : (jsx(TableBody, { ...tableBodyProps, canResize: canResize }));
@@ -8567,6 +8823,290 @@ const DataDisplay = ({ variant = '' }) => {
8567
8823
  }) }));
8568
8824
  };
8569
8825
 
8826
+ // Helper function to normalize date
8827
+ function normalizeDate(value) {
8828
+ if (!value)
8829
+ return null;
8830
+ if (value instanceof Date)
8831
+ return value;
8832
+ if (typeof value === 'string' || typeof value === 'number') {
8833
+ const date = dayjs(value).toDate();
8834
+ return isNaN(date.getTime()) ? null : date;
8835
+ }
8836
+ return null;
8837
+ }
8838
+ // Component to conditionally render event title based on available width
8839
+ function ResponsiveEventTitle({ title, placeholder, minWidth, minChars, cellRef, }) {
8840
+ const [truncatedText, setTruncatedText] = useState('');
8841
+ const measureRef = useRef(null);
8842
+ useEffect(() => {
8843
+ const calculateTruncatedText = () => {
8844
+ if (!cellRef.current || !measureRef.current || !title) {
8845
+ setTruncatedText(title || 'Event');
8846
+ return;
8847
+ }
8848
+ const cellWidth = cellRef.current.clientWidth;
8849
+ // Account for padding (approximately 8px on each side)
8850
+ const availableWidth = cellWidth - 16;
8851
+ // If cell is too narrow, calculate how many characters can fit
8852
+ if (availableWidth < minWidth) {
8853
+ // Measure text width using canvas
8854
+ const canvas = document.createElement('canvas');
8855
+ const context = canvas.getContext('2d');
8856
+ if (!context) {
8857
+ setTruncatedText(placeholder);
8858
+ return;
8859
+ }
8860
+ // Get computed font style from the element
8861
+ const computedStyle = window.getComputedStyle(measureRef.current);
8862
+ context.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
8863
+ const ellipsisWidth = context.measureText('...').width;
8864
+ const maxWidth = availableWidth - ellipsisWidth;
8865
+ // Try to show at least minChars characters before ellipsis
8866
+ let truncated = '';
8867
+ let charCount = 0;
8868
+ // Calculate how many characters can fit
8869
+ for (let i = 0; i < Math.min(title.length, 50); i++) {
8870
+ const testText = title.substring(0, i + 1);
8871
+ const textWidth = context.measureText(testText).width;
8872
+ if (textWidth <= maxWidth) {
8873
+ truncated = testText;
8874
+ charCount = i + 1;
8875
+ }
8876
+ else {
8877
+ break;
8878
+ }
8879
+ }
8880
+ // Ensure we show at least minChars characters if possible
8881
+ if (charCount < minChars && title.length >= minChars) {
8882
+ truncated = title.substring(0, minChars);
8883
+ }
8884
+ else if (charCount === 0 && title.length >= 1) {
8885
+ truncated = title.substring(0, 1);
8886
+ }
8887
+ // Only show ellipsis if we have at least minChars characters
8888
+ if (truncated && truncated.length >= minChars) {
8889
+ setTruncatedText(`${truncated}...`);
8890
+ }
8891
+ else {
8892
+ setTruncatedText(placeholder);
8893
+ }
8894
+ }
8895
+ else {
8896
+ // Full width available, show full title
8897
+ setTruncatedText(title);
8898
+ }
8899
+ };
8900
+ calculateTruncatedText();
8901
+ const resizeObserver = new ResizeObserver(calculateTruncatedText);
8902
+ if (cellRef.current) {
8903
+ resizeObserver.observe(cellRef.current);
8904
+ }
8905
+ // Also check on window resize
8906
+ window.addEventListener('resize', calculateTruncatedText);
8907
+ return () => {
8908
+ resizeObserver.disconnect();
8909
+ window.removeEventListener('resize', calculateTruncatedText);
8910
+ };
8911
+ }, [cellRef, minWidth, title, placeholder]);
8912
+ return (jsxs(Fragment, { children: [jsx("span", { ref: measureRef, style: {
8913
+ visibility: 'hidden',
8914
+ position: 'absolute',
8915
+ whiteSpace: 'nowrap',
8916
+ }, children: title || 'Event' }), truncatedText || title || 'Event'] }));
8917
+ }
8918
+ function CalendarDisplay({ dateColumn, getDate, getEventTitle, getEventColor, renderEvent, firstDayOfWeek = 0, showOutsideDays = true, monthsToDisplay = 1, labels = {
8919
+ monthNamesShort: [
8920
+ 'Jan',
8921
+ 'Feb',
8922
+ 'Mar',
8923
+ 'Apr',
8924
+ 'May',
8925
+ 'Jun',
8926
+ 'Jul',
8927
+ 'Aug',
8928
+ 'Sep',
8929
+ 'Oct',
8930
+ 'Nov',
8931
+ 'Dec',
8932
+ ],
8933
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
8934
+ backButtonLabel: 'Back',
8935
+ forwardButtonLabel: 'Next',
8936
+ }, onDateClick, onEventClick, maxEventsPerDay = 3, colorPalette = 'blue', eventPlaceholder = '...', minEventWidth = 80, minCharsBeforeEllipsis = 2, }) {
8937
+ const { data, table } = useDataTableContext();
8938
+ // Map table data to events
8939
+ const events = useMemo(() => {
8940
+ return data
8941
+ .map((row) => {
8942
+ let dateValue;
8943
+ if (getDate) {
8944
+ dateValue = getDate(row);
8945
+ }
8946
+ else {
8947
+ // Try to get date from column
8948
+ const rowData = table
8949
+ .getRowModel()
8950
+ .rows.find((r) => r.original === row);
8951
+ if (rowData) {
8952
+ const cell = rowData.getAllCells().find((c) => {
8953
+ const colId = c.column.id;
8954
+ const accessorKey = c.column.columnDef.accessorKey;
8955
+ return colId === dateColumn || accessorKey === dateColumn;
8956
+ });
8957
+ dateValue = cell?.getValue();
8958
+ }
8959
+ }
8960
+ const date = normalizeDate(dateValue);
8961
+ if (!date)
8962
+ return null;
8963
+ let title;
8964
+ if (getEventTitle) {
8965
+ title = getEventTitle(row);
8966
+ }
8967
+ else {
8968
+ // Use first column's value as title
8969
+ const rowData = table
8970
+ .getRowModel()
8971
+ .rows.find((r) => r.original === row);
8972
+ if (rowData) {
8973
+ const firstCell = rowData.getAllCells()[0];
8974
+ title = String(firstCell?.getValue() ?? '');
8975
+ }
8976
+ }
8977
+ const color = getEventColor?.(row);
8978
+ return {
8979
+ data: row,
8980
+ date,
8981
+ title,
8982
+ color,
8983
+ };
8984
+ })
8985
+ .filter((event) => event !== null);
8986
+ }, [data, table, dateColumn, getDate, getEventTitle, getEventColor]);
8987
+ // Group events by date
8988
+ const eventsByDate = useMemo(() => {
8989
+ const map = new Map();
8990
+ events.forEach((event) => {
8991
+ const dateKey = `${event.date.getFullYear()}-${event.date.getMonth()}-${event.date.getDate()}`;
8992
+ if (!map.has(dateKey)) {
8993
+ map.set(dateKey, []);
8994
+ }
8995
+ map.get(dateKey).push(event);
8996
+ });
8997
+ return map;
8998
+ }, [events]);
8999
+ // Get events for a specific date
9000
+ const getEventsForDate = useCallback((date) => {
9001
+ const dateKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
9002
+ return eventsByDate.get(dateKey) ?? [];
9003
+ }, [eventsByDate]);
9004
+ const calendarData = useCalendar({
9005
+ firstDayOfWeek,
9006
+ showOutsideDays,
9007
+ monthsToDisplay,
9008
+ });
9009
+ const getDateProps = useCallback((props) => {
9010
+ const dateEvents = getEventsForDate(props.dateObj.date);
9011
+ const baseProps = calendarData.getDateProps({ dateObj: props.dateObj });
9012
+ return {
9013
+ ...baseProps,
9014
+ onClick: () => {
9015
+ baseProps.onClick?.();
9016
+ if (onDateClick) {
9017
+ onDateClick(props.dateObj.date, dateEvents);
9018
+ }
9019
+ },
9020
+ };
9021
+ }, [calendarData, getEventsForDate, onDateClick]);
9022
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
9023
+ if (!calendarData.calendars.length) {
9024
+ return null;
9025
+ }
9026
+ return (jsxs(VStack, { gap: 4, width: "100%", children: [jsxs(HStack, { gap: 2, justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({
9027
+ calendars: calendarData.calendars,
9028
+ offset: 12,
9029
+ }), children: '<<' }), jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({ calendars: calendarData.calendars }), children: backButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9030
+ calendars: calendarData.calendars,
9031
+ }), children: forwardButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9032
+ calendars: calendarData.calendars,
9033
+ offset: 12,
9034
+ }), children: '>>' })] }), jsx(Grid, { templateColumns: {
9035
+ base: '1fr',
9036
+ md: monthsToDisplay >= 2 ? 'repeat(2, 1fr)' : '1fr',
9037
+ lg: monthsToDisplay >= 3
9038
+ ? 'repeat(3, 1fr)'
9039
+ : monthsToDisplay === 2
9040
+ ? 'repeat(2, 1fr)'
9041
+ : '1fr',
9042
+ xl: `repeat(${Math.min(monthsToDisplay, 4)}, 1fr)`,
9043
+ }, gap: { base: 4, md: 6 }, width: "100%", justifyContent: "center", children: calendarData.calendars.map((calendar) => (jsxs(VStack, { gap: 2, alignItems: "stretch", children: [jsxs(Text, { textAlign: "center", fontSize: { base: 'md', md: 'lg' }, fontWeight: "semibold", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
9044
+ const weekday = (weekdayNum + firstDayOfWeek) % 7;
9045
+ return (jsx(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}`));
9046
+ }) }), jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
9047
+ const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
9048
+ if (!dateObj) {
9049
+ return jsx(Box, {}, key);
9050
+ }
9051
+ const { date, today, isCurrentMonth } = dateObj;
9052
+ const dateEvents = getEventsForDate(date);
9053
+ const cellRef = useRef(null);
9054
+ return (jsxs(VStack, { ref: cellRef, gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", minHeight: { base: '60px', md: '80px', lg: '100px' }, borderWidth: "1px", borderColor: {
9055
+ base: today ? `${colorPalette}.300` : 'gray.200',
9056
+ _dark: today ? `${colorPalette}.700` : 'gray.700',
9057
+ }, borderRadius: { base: 'sm', md: 'md' }, padding: { base: 0.5, md: 1 }, bgColor: {
9058
+ base: today ? `${colorPalette}.50` : 'white',
9059
+ _dark: today ? `${colorPalette}.950` : 'gray.900',
9060
+ }, opacity: isCurrentMonth ? 1 : 0.5, ...getDateProps({ dateObj }), cursor: onDateClick ? 'pointer' : 'default', _hover: onDateClick
9061
+ ? {
9062
+ bgColor: {
9063
+ base: `${colorPalette}.100`,
9064
+ _dark: `${colorPalette}.900`,
9065
+ },
9066
+ }
9067
+ : {}, children: [jsx(Text, { fontSize: { base: 'xs', md: 'sm' }, fontWeight: today ? 'bold' : 'normal', color: {
9068
+ base: today ? `${colorPalette}.700` : 'gray.700',
9069
+ _dark: today ? `${colorPalette}.300` : 'gray.300',
9070
+ }, textAlign: "right", paddingRight: { base: 0.5, md: 1 }, children: date.getDate() }), jsxs(VStack, { gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", flex: 1, overflow: "hidden", children: [dateEvents
9071
+ .slice(0, maxEventsPerDay)
9072
+ .map((event, eventIndex) => {
9073
+ const eventContent = renderEvent ? (renderEvent(event)) : (jsx(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: {
9074
+ base: event.color
9075
+ ? `${event.color}.100`
9076
+ : `${colorPalette}.100`,
9077
+ _dark: event.color
9078
+ ? `${event.color}.900`
9079
+ : `${colorPalette}.900`,
9080
+ }, color: {
9081
+ base: event.color
9082
+ ? `${event.color}.800`
9083
+ : `${colorPalette}.800`,
9084
+ _dark: event.color
9085
+ ? `${event.color}.200`
9086
+ : `${colorPalette}.200`,
9087
+ }, onClick: (e) => {
9088
+ e.stopPropagation();
9089
+ if (onEventClick) {
9090
+ onEventClick(event);
9091
+ }
9092
+ }, cursor: onEventClick ? 'pointer' : 'default', _hover: onEventClick
9093
+ ? {
9094
+ opacity: 0.8,
9095
+ }
9096
+ : {}, children: jsx(ResponsiveEventTitle, { title: event.title, placeholder: eventPlaceholder, minWidth: minEventWidth, minChars: minCharsBeforeEllipsis, cellRef: cellRef }) }, eventIndex));
9097
+ return (jsx(Box, { onClick: (e) => e.stopPropagation(), children: eventContent }, eventIndex));
9098
+ }), dateEvents.length > maxEventsPerDay && (jsxs(Text, { fontSize: "xs", color: {
9099
+ base: `${colorPalette}.600`,
9100
+ _dark: `${colorPalette}.400`,
9101
+ }, paddingX: 1, onClick: (e) => {
9102
+ e.stopPropagation();
9103
+ if (onDateClick) {
9104
+ onDateClick(date, dateEvents);
9105
+ }
9106
+ }, cursor: onDateClick ? 'pointer' : 'default', children: ["+", dateEvents.length - maxEventsPerDay, " more"] }))] })] }, key));
9107
+ })) })] }, `${calendar.month}${calendar.year}`))) })] }));
9108
+ }
9109
+
8570
9110
  // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
8571
9111
  // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
8572
9112
  // end of TS setup!
@@ -8667,7 +9207,7 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
8667
9207
  *
8668
9208
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8669
9209
  */
8670
- 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 = {
9210
+ 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 = {
8671
9211
  view: 'View',
8672
9212
  edit: 'Edit',
8673
9213
  filterButtonText: 'Filter',
@@ -8678,7 +9218,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8678
9218
  reloadButtonText: 'Reload',
8679
9219
  resetSelection: 'Reset Selection',
8680
9220
  resetSorting: 'Reset Sorting',
8681
- rowCountText: 'Row Count',
9221
+ rowCountText: '',
8682
9222
  hasErrorText: 'Has Error',
8683
9223
  globalFilterPlaceholder: 'Search',
8684
9224
  trueLabel: 'True',
@@ -8735,7 +9275,6 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8735
9275
  globalFilter,
8736
9276
  setGlobalFilter,
8737
9277
  type: 'client',
8738
- translate,
8739
9278
  columns: columns,
8740
9279
  sorting,
8741
9280
  setSorting,
@@ -8767,22 +9306,22 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8767
9306
  *
8768
9307
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8769
9308
  */
8770
- 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 = {
8771
- view: "View",
8772
- edit: "Edit",
8773
- filterButtonText: "Filter",
8774
- filterTitle: "Filter",
8775
- filterReset: "Reset",
8776
- filterClose: "Close",
8777
- reloadTooltip: "Reload",
8778
- reloadButtonText: "Reload",
8779
- resetSelection: "Reset Selection",
8780
- resetSorting: "Reset Sorting",
8781
- rowCountText: "Row Count",
8782
- hasErrorText: "Has Error",
8783
- globalFilterPlaceholder: "Search",
8784
- trueLabel: "True",
8785
- falseLabel: "False",
9309
+ 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 = {
9310
+ view: 'View',
9311
+ edit: 'Edit',
9312
+ filterButtonText: 'Filter',
9313
+ filterTitle: 'Filter',
9314
+ filterReset: 'Reset',
9315
+ filterClose: 'Close',
9316
+ reloadTooltip: 'Reload',
9317
+ reloadButtonText: 'Reload',
9318
+ resetSelection: 'Reset Selection',
9319
+ resetSorting: 'Reset Sorting',
9320
+ rowCountText: '',
9321
+ hasErrorText: 'Has Error',
9322
+ globalFilterPlaceholder: 'Search',
9323
+ trueLabel: 'True',
9324
+ falseLabel: 'False',
8786
9325
  }, }) {
8787
9326
  const table = useReactTable({
8788
9327
  _features: [DensityFeature],
@@ -8792,7 +9331,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8792
9331
  getCoreRowModel: getCoreRowModel(),
8793
9332
  manualPagination: true,
8794
9333
  manualSorting: true,
8795
- columnResizeMode: "onChange",
9334
+ columnResizeMode: 'onChange',
8796
9335
  defaultColumn: {
8797
9336
  size: 150, //starting column size
8798
9337
  minSize: 10, //enforced during column resizing
@@ -8835,8 +9374,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8835
9374
  table: table,
8836
9375
  globalFilter,
8837
9376
  setGlobalFilter,
8838
- type: "server",
8839
- translate,
9377
+ type: 'server',
8840
9378
  columns: columns,
8841
9379
  sorting,
8842
9380
  setSorting,
@@ -8854,7 +9392,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8854
9392
  setColumnVisibility,
8855
9393
  data: query.data?.data ?? [],
8856
9394
  tableLabel,
8857
- }, children: jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
9395
+ }, children: jsx(DataTableServerContext.Provider, { value: { url: url ?? '', query }, children: children }) }));
8858
9396
  }
8859
9397
 
8860
- export { CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
9398
+ export { CalendarDisplay, CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };