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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts +166 -41
  3. package/dist/index.js +1220 -652
  4. package/dist/index.mjs +1222 -655
  5. package/dist/types/components/DataTable/DataTable.d.ts +1 -3
  6. package/dist/types/components/DataTable/DataTableServer.d.ts +7 -9
  7. package/dist/types/components/DataTable/context/DataTableContext.d.ts +4 -6
  8. package/dist/types/components/DataTable/controls/MobileTableControls.d.ts +29 -0
  9. package/dist/types/components/DataTable/controls/TableControls.d.ts +2 -2
  10. package/dist/types/components/DataTable/display/CalendarDisplay.d.ts +84 -0
  11. package/dist/types/components/DataTable/display/DataDisplay.d.ts +0 -2
  12. package/dist/types/components/DataTable/display/MobileTableDisplay.d.ts +5 -0
  13. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +1 -3
  14. package/dist/types/components/DataTable/hooks/useIsMobile.d.ts +6 -0
  15. package/dist/types/components/DataTable/useDataTable.d.ts +3 -6
  16. package/dist/types/components/DataTable/useDataTableServer.d.ts +4 -4
  17. package/dist/types/components/DataTable/utils/getColumns.d.ts +3 -5
  18. package/dist/types/components/DatePicker/DatePicker.d.ts +7 -8
  19. package/dist/types/components/DatePicker/DateTimePicker.d.ts +3 -1
  20. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +5 -1
  21. package/dist/types/components/DatePicker/RangeDatePicker.d.ts +4 -4
  22. package/dist/types/components/DatePicker/useCalendar.d.ts +48 -0
  23. package/dist/types/components/Form/SchemaFormContext.d.ts +5 -3
  24. package/dist/types/components/Form/components/core/FormBody.d.ts +1 -2
  25. package/dist/types/components/Form/components/core/FormRoot.d.ts +6 -4
  26. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -2
  27. package/dist/types/components/Form/components/fields/IdPicker.d.ts +8 -0
  28. package/dist/types/components/Form/components/fields/IdPickerMultiple.d.ts +7 -0
  29. package/dist/types/components/Form/components/fields/IdPickerSingle.d.ts +7 -0
  30. package/dist/types/components/Form/components/fields/useIdPickerData.d.ts +68 -0
  31. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +9 -0
  32. package/dist/types/components/Form/useForm.d.ts +7 -2
  33. package/dist/types/components/Form/utils/useFormI18n.d.ts +14 -12
  34. package/dist/types/components/TimePicker/TimePicker.d.ts +4 -6
  35. package/dist/types/components/ui/provider.d.ts +1 -1
  36. package/dist/types/index.d.ts +1 -0
  37. package/package.json +1 -3
package/dist/index.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,79 @@ const defaultRenderDisplay = (item) => {
5448
5631
  return JSON.stringify(item);
5449
5632
  };
5450
5633
 
5451
- const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5634
+ /**
5635
+ * Load initial values for IdPicker fields into idMap
5636
+ * Uses customQueryFn if available, otherwise falls back to getTableData
5637
+ *
5638
+ * @param params - Configuration for loading initial values
5639
+ * @returns Promise with fetched data and idMap
5640
+ */
5641
+ const loadInitialValues = async ({ ids, foreign_key, serverUrl, setIdMap, }) => {
5642
+ if (!ids || ids.length === 0) {
5643
+ return { data: { data: [], count: 0 }, idMap: {} };
5644
+ }
5645
+ const { table, column: column_ref, customQueryFn } = foreign_key;
5646
+ // Filter out IDs that are already in idMap (optional optimization)
5647
+ // For now, we'll fetch all requested IDs to ensure consistency
5648
+ if (customQueryFn) {
5649
+ const { data, idMap: returnedIdMap } = await customQueryFn({
5650
+ searching: '',
5651
+ limit: ids.length,
5652
+ offset: 0,
5653
+ where: [
5654
+ {
5655
+ id: column_ref,
5656
+ value: ids.length === 1 ? ids[0] : ids, // CustomQueryFn accepts string | string[]
5657
+ },
5658
+ ],
5659
+ });
5660
+ // Update idMap with returned values
5661
+ if (returnedIdMap && Object.keys(returnedIdMap).length > 0) {
5662
+ setIdMap((state) => {
5663
+ return { ...state, ...returnedIdMap };
5664
+ });
5665
+ }
5666
+ return { data, idMap: returnedIdMap || {} };
5667
+ }
5668
+ // Fallback to default getTableData
5669
+ const data = await getTableData({
5670
+ serverUrl,
5671
+ searching: '',
5672
+ in_table: table,
5673
+ limit: ids.length,
5674
+ offset: 0,
5675
+ where: [
5676
+ {
5677
+ id: column_ref,
5678
+ value: ids, // Always pass as array
5679
+ },
5680
+ ],
5681
+ });
5682
+ // Build idMap from fetched data
5683
+ const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5684
+ return [
5685
+ item[column_ref],
5686
+ {
5687
+ ...item,
5688
+ },
5689
+ ];
5690
+ }));
5691
+ // Update idMap state
5692
+ setIdMap((state) => {
5693
+ return { ...state, ...newMap };
5694
+ });
5695
+ return { data: data, idMap: newMap };
5696
+ };
5697
+ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5452
5698
  const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
5453
5699
  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);
5700
+ const { renderDisplay, foreign_key } = schema;
5457
5701
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5458
5702
  const [searchText, setSearchText] = useState('');
5459
5703
  const [debouncedSearchText, setDebouncedSearchText] = useState('');
5460
5704
  const [limit] = useState(50); // Increased limit for combobox
5461
- const colLabel = formI18n.colLabel;
5705
+ // Get colLabel from schema context (we'll compute it here)
5706
+ const colLabel = `${prefix}${column}`;
5462
5707
  const watchedValue = watch(colLabel);
5463
5708
  const watchId = !isMultiple ? watchedValue : undefined;
5464
5709
  const watchIds = isMultiple
@@ -5505,48 +5750,14 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5505
5750
  if (missingIds.length === 0) {
5506
5751
  return { data: [], count: 0 };
5507
5752
  }
5508
- if (customQueryFn) {
5509
- const { data, idMap } = await customQueryFn({
5510
- searching: '',
5511
- limit: missingIds.length,
5512
- offset: 0,
5513
- where: [
5514
- {
5515
- id: column_ref,
5516
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5517
- },
5518
- ],
5519
- });
5520
- setIdMap((state) => {
5521
- return { ...state, ...idMap };
5522
- });
5523
- return data;
5524
- }
5525
- const data = await getTableData({
5753
+ // Use the reusable loadInitialValues function
5754
+ const result = await loadInitialValues({
5755
+ ids: missingIds,
5756
+ foreign_key: foreign_key,
5526
5757
  serverUrl,
5527
- searching: '',
5528
- in_table: table,
5529
- limit: missingIds.length,
5530
- offset: 0,
5531
- where: [
5532
- {
5533
- id: column_ref,
5534
- value: missingIds.length === 1 ? missingIds[0] : missingIds,
5535
- },
5536
- ],
5537
- });
5538
- const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
5539
- return [
5540
- item[column_ref],
5541
- {
5542
- ...item,
5543
- },
5544
- ];
5545
- }));
5546
- setIdMap((state) => {
5547
- return { ...state, ...newMap };
5758
+ setIdMap,
5548
5759
  });
5549
- return data;
5760
+ return result.data;
5550
5761
  },
5551
5762
  enabled: missingIds.length > 0, // Only fetch if there are missing IDs
5552
5763
  staleTime: 300000,
@@ -5657,20 +5868,6 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5657
5868
  itemToValue: (item) => item.value,
5658
5869
  filter: contains,
5659
5870
  });
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
5871
  // Track previous comboboxItems to avoid unnecessary updates
5675
5872
  const prevComboboxItemsRef = useRef('');
5676
5873
  const prevSearchTextRef = useRef('');
@@ -5700,8 +5897,106 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5700
5897
  // comboboxItems and searchText are the only dependencies we care about
5701
5898
  // eslint-disable-next-line react-hooks/exhaustive-deps
5702
5899
  }, [comboboxItems, searchText]);
5900
+ return {
5901
+ colLabel,
5902
+ currentValue,
5903
+ searchText,
5904
+ setSearchText,
5905
+ debouncedSearchText,
5906
+ isLoading,
5907
+ isFetching,
5908
+ isPending,
5909
+ isError,
5910
+ isSearching,
5911
+ isLoadingInitialValues,
5912
+ isFetchingInitialValues,
5913
+ missingIds,
5914
+ comboboxItems,
5915
+ collection,
5916
+ filter,
5917
+ set,
5918
+ idMap,
5919
+ idPickerLabels,
5920
+ insideDialog: insideDialog ?? false,
5921
+ renderDisplay,
5922
+ column_ref,
5923
+ errors,
5924
+ setValue,
5925
+ };
5926
+ };
5927
+
5928
+ const IdPickerSingle = ({ column, schema, prefix, }) => {
5929
+ const formI18n = useFormI18n(column, prefix, schema);
5930
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5931
+ const isRequired = required?.some((columnId) => columnId === column);
5932
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5933
+ column,
5934
+ schema,
5935
+ prefix,
5936
+ isMultiple: false,
5937
+ });
5938
+ const handleInputValueChange = (details) => {
5939
+ setSearchText(details.inputValue);
5940
+ };
5941
+ const handleValueChange = (details) => {
5942
+ setValue(colLabel, details.value[0] || '');
5943
+ };
5944
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5703
5945
  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) => {
5946
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsx(Flex, { mb: 2, children: (() => {
5947
+ const id = currentValue[0];
5948
+ const item = idMap[id];
5949
+ // Show loading skeleton while fetching initial values
5950
+ if (item === undefined &&
5951
+ (isLoadingInitialValues || isFetchingInitialValues) &&
5952
+ missingIds.includes(id)) {
5953
+ return jsx(Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
5954
+ }
5955
+ // Only show "not found" if we're not loading and item is still missing
5956
+ if (item === undefined) {
5957
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
5958
+ }
5959
+ return jsx(Text, { fontSize: "sm", children: renderDisplayFunction(item) });
5960
+ })() })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: false, closeOnSelect: true, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5961
+ ? { strategy: 'fixed', hideWhenDetached: true }
5962
+ : 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: () => {
5963
+ setValue(colLabel, '');
5964
+ } })), 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 ? (
5965
+ // Show skeleton items to prevent UI shift
5966
+ 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
5967
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5968
+ : idPickerLabels?.initialResults ??
5969
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5970
+ ? renderDisplayFunction(item.raw)
5971
+ : 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 ? (
5972
+ // Show skeleton items to prevent UI shift
5973
+ 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
5974
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5975
+ : idPickerLabels?.initialResults ??
5976
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5977
+ ? renderDisplayFunction(item.raw)
5978
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5979
+ };
5980
+
5981
+ const IdPickerMultiple = ({ column, schema, prefix, }) => {
5982
+ const formI18n = useFormI18n(column, prefix, schema);
5983
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5984
+ const isRequired = required?.some((columnId) => columnId === column);
5985
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5986
+ column,
5987
+ schema,
5988
+ prefix,
5989
+ isMultiple: true,
5990
+ });
5991
+ const handleInputValueChange = (details) => {
5992
+ setSearchText(details.inputValue);
5993
+ };
5994
+ const handleValueChange = (details) => {
5995
+ setValue(colLabel, details.value);
5996
+ };
5997
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5998
+ return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5999
+ 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
6000
  const item = idMap[id];
5706
6001
  // Show loading skeleton while fetching initial values
5707
6002
  if (item === undefined &&
@@ -5711,34 +6006,28 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5711
6006
  }
5712
6007
  // Only show "not found" if we're not loading and item is still missing
5713
6008
  if (item === undefined) {
5714
- return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
6009
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }, id));
5715
6010
  }
5716
6011
  return (jsx(Tag, { closable: true, onClick: () => {
5717
6012
  const newValue = currentValue.filter((itemId) => itemId !== id);
5718
6013
  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
6014
+ }, children: renderDisplayFunction(item) }, id));
6015
+ }) })), 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
6016
  ? { 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 ? (
6017
+ : 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
6018
  // Show skeleton items to prevent UI shift
5728
6019
  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')
6020
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5731
6021
  : 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 ? (
6022
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
6023
+ ? renderDisplayFunction(item.raw)
6024
+ : 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
6025
  // Show skeleton items to prevent UI shift
5736
6026
  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')
6027
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5739
6028
  : 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)
6029
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
6030
+ ? renderDisplayFunction(item.raw)
5742
6031
  : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5743
6032
  };
5744
6033
 
@@ -5812,7 +6101,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
5812
6101
  const colLabel = `${prefix}${column}`;
5813
6102
  const value = watch(`${colLabel}`);
5814
6103
  const fieldError = getFieldError(errors, colLabel);
5815
- const formI18n = useFormI18n$1(column, prefix, schema);
6104
+ const formI18n = useFormI18n(column, prefix, schema);
5816
6105
  return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
5817
6106
  ? fieldError.includes('required')
5818
6107
  ? formI18n.required()
@@ -5830,7 +6119,7 @@ const ObjectInput = ({ schema, column, prefix }) => {
5830
6119
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
5831
6120
  const colLabel = `${prefix}${column}`;
5832
6121
  const isRequired = required?.some((columnId) => columnId === column);
5833
- const formI18n = useFormI18n$1(column, prefix, schema);
6122
+ const formI18n = useFormI18n(column, prefix, schema);
5834
6123
  const { formState: { errors }, } = useFormContext();
5835
6124
  if (properties === undefined) {
5836
6125
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -5850,14 +6139,14 @@ const ObjectInput = ({ schema, column, prefix }) => {
5850
6139
 
5851
6140
  const RecordInput = ({ column, schema, prefix }) => {
5852
6141
  const { formState: { errors }, setValue, getValues, } = useFormContext();
5853
- const { translate } = useSchemaContext();
6142
+ const { formButtonLabels } = useSchemaContext();
5854
6143
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5855
6144
  const isRequired = required?.some((columnId) => columnId === column);
5856
6145
  const entries = Object.entries(getValues(column) ?? {});
5857
6146
  const [showNewEntries, setShowNewEntries] = useState(false);
5858
6147
  const [newKey, setNewKey] = useState();
5859
6148
  const [newValue, setNewValue] = useState();
5860
- const formI18n = useFormI18n$1(column, prefix, schema);
6149
+ const formI18n = useFormI18n(column, prefix, schema);
5861
6150
  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
6151
  return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
5863
6152
  const filtered = entries.filter(([target]) => {
@@ -5894,11 +6183,11 @@ const RecordInput = ({ column, schema, prefix }) => {
5894
6183
  setShowNewEntries(false);
5895
6184
  setNewKey(undefined);
5896
6185
  setNewValue(undefined);
5897
- }, children: translate.t(`${column}.save`) })] })] }) }), jsx(Button, { onClick: () => {
6186
+ }, children: formButtonLabels?.save ?? 'Save' })] })] }) }), jsx(Button, { onClick: () => {
5898
6187
  setShowNewEntries(true);
5899
6188
  setNewKey(undefined);
5900
6189
  setNewValue(undefined);
5901
- }, children: translate.t(`${column}.addNew`) })] }));
6190
+ }, children: formButtonLabels?.addNew ?? 'Add New' })] }));
5902
6191
  };
5903
6192
 
5904
6193
  const StringInputField = ({ column, schema, prefix, }) => {
@@ -5907,7 +6196,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
5907
6196
  const isRequired = required?.some((columnId) => columnId === column);
5908
6197
  const colLabel = `${prefix}${column}`;
5909
6198
  const fieldError = getFieldError(errors, colLabel);
5910
- const formI18n = useFormI18n$1(column, prefix, schema);
6199
+ const formI18n = useFormI18n(column, prefix, schema);
5911
6200
  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
6201
  };
5913
6202
 
@@ -6099,7 +6388,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6099
6388
  const form = useFormContext();
6100
6389
  const { setValue, watch } = form;
6101
6390
  const fieldError = getFieldError(errors, colLabel);
6102
- const formI18n = useFormI18n$1(column, prefix, schema);
6391
+ const formI18n = useFormI18n(column, prefix, schema);
6103
6392
  const watchValue = watch(colLabel);
6104
6393
  return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
6105
6394
  ? fieldError.includes('required')
@@ -6110,18 +6399,13 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6110
6399
 
6111
6400
  dayjs.extend(utc);
6112
6401
  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)
6402
+ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem, onChange = () => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6403
+ placeholder: 'hh:mm AM/PM',
6404
+ emptyMessage: 'No time found',
6405
+ }, }) => {
6406
+ // Generate time options (every 15 minutes in 12-hour format)
6122
6407
  const timeOptions = useMemo(() => {
6123
6408
  const options = [];
6124
- const meridiemOptions = ['am', 'pm'];
6125
6409
  // Get start time for comparison if provided
6126
6410
  let startDateTime = null;
6127
6411
  let shouldFilterByDate = false;
@@ -6136,14 +6420,16 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6136
6420
  selectedDateObj.format('YYYY-MM-DD');
6137
6421
  }
6138
6422
  }
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}`;
6423
+ // Generate 12-hour format options (1-12 for hours, AM/PM)
6424
+ for (let h = 1; h <= 12; h++) {
6425
+ for (let m = 0; m < 60; m += 15) {
6426
+ for (const mer of ['am', 'pm']) {
6427
+ // Convert 12-hour to 24-hour for comparison
6428
+ let hour24 = h;
6429
+ if (mer === 'am' && h === 12)
6430
+ hour24 = 0;
6431
+ else if (mer === 'pm' && h < 12)
6432
+ hour24 = h + 12;
6147
6433
  // Filter out times that would result in negative duration (only when dates are the same)
6148
6434
  if (startDateTime && selectedDate && shouldFilterByDate) {
6149
6435
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
@@ -6186,20 +6472,23 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6186
6472
  }
6187
6473
  }
6188
6474
  }
6475
+ const hourDisplay = h.toString();
6476
+ const minuteDisplay = m.toString().padStart(2, '0');
6477
+ const timeDisplay = `${hourDisplay}:${minuteDisplay} ${mer.toUpperCase()}`;
6189
6478
  options.push({
6190
- label: displayTime,
6191
- value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
6479
+ label: timeDisplay,
6480
+ value: `${h}:${m}:${mer}`,
6192
6481
  hour: h,
6193
6482
  minute: m,
6194
6483
  meridiem: mer,
6195
- searchText: displayTime, // Use base time without duration for searching
6484
+ searchText: timeDisplay, // Use base time without duration for searching
6196
6485
  durationText,
6197
6486
  });
6198
6487
  }
6199
6488
  }
6200
6489
  }
6201
6490
  return options;
6202
- }, [timezone, startTime, selectedDate]);
6491
+ }, [startTime, selectedDate, timezone]);
6203
6492
  const { contains } = useFilter({ sensitivity: 'base' });
6204
6493
  const { collection, filter } = useListCollection({
6205
6494
  initialItems: timeOptions,
@@ -6212,7 +6501,7 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6212
6501
  if (hour === null || minute === null || meridiem === null) {
6213
6502
  return '';
6214
6503
  }
6215
- return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
6504
+ return `${hour}:${minute}:${meridiem}`;
6216
6505
  }, [hour, minute, meridiem]);
6217
6506
  // Calculate duration difference
6218
6507
  const durationDiff = useMemo(() => {
@@ -6223,15 +6512,14 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6223
6512
  meridiem === null) {
6224
6513
  return null;
6225
6514
  }
6226
- const hour24 = meridiem === 'am'
6227
- ? hour === 12
6228
- ? 0
6229
- : hour
6230
- : hour === 12
6231
- ? 12
6232
- : hour + 12;
6233
6515
  const startDateObj = dayjs(startTime).tz(timezone);
6234
6516
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
6517
+ // Convert 12-hour to 24-hour format
6518
+ let hour24 = hour;
6519
+ if (meridiem === 'am' && hour === 12)
6520
+ hour24 = 0;
6521
+ else if (meridiem === 'pm' && hour < 12)
6522
+ hour24 = hour + 12;
6235
6523
  const currentDateTime = selectedDateObj
6236
6524
  .hour(hour24)
6237
6525
  .minute(minute)
@@ -6296,83 +6584,54 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6296
6584
  if (!trimmedValue) {
6297
6585
  return;
6298
6586
  }
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);
6587
+ // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6588
+ const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6589
+ const match12Hour = trimmedValue.match(timePattern12Hour);
6305
6590
  if (match12Hour) {
6306
6591
  const parsedHour = parseInt(match12Hour[1], 10);
6307
6592
  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();
6593
+ const parsedMeridiem = match12Hour[3].toLowerCase();
6594
+ // Validate ranges
6595
+ if (parsedHour >= 1 &&
6596
+ parsedHour <= 12 &&
6597
+ parsedMinute >= 0 &&
6598
+ parsedMinute <= 59) {
6599
+ setHour(parsedHour);
6600
+ setMinute(parsedMinute);
6601
+ setMeridiem(parsedMeridiem);
6602
+ onChange({
6603
+ hour: parsedHour,
6604
+ minute: parsedMinute,
6605
+ meridiem: parsedMeridiem,
6606
+ });
6319
6607
  return;
6320
6608
  }
6321
- setHour(parsedHour);
6322
- setMinute(parsedMinute);
6323
- setMeridiem(parsedMeridiem);
6324
- onChange({
6325
- hour: parsedHour,
6326
- minute: parsedMinute,
6327
- meridiem: parsedMeridiem,
6328
- });
6329
- return;
6330
6609
  }
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';
6610
+ // Try to parse formats like "130pm" or "130 pm" (without colon)
6611
+ const timePatternNoColon = /^(\d{1,4})\s*(am|pm|AM|PM)$/i;
6612
+ const matchNoColon = trimmedValue.match(timePatternNoColon);
6613
+ if (matchNoColon) {
6614
+ const numbersOnly = matchNoColon[1];
6615
+ const parsedMeridiem = matchNoColon[2].toLowerCase();
6616
+ if (numbersOnly.length >= 3) {
6617
+ const parsedHour = parseInt(numbersOnly.slice(0, -2), 10);
6618
+ const parsedMinute = parseInt(numbersOnly.slice(-2), 10);
6619
+ // Validate ranges
6620
+ if (parsedHour >= 1 &&
6621
+ parsedHour <= 12 &&
6622
+ parsedMinute >= 0 &&
6623
+ parsedMinute <= 59) {
6624
+ setHour(parsedHour);
6625
+ setMinute(parsedMinute);
6626
+ setMeridiem(parsedMeridiem);
6627
+ onChange({
6628
+ hour: parsedHour,
6629
+ minute: parsedMinute,
6630
+ meridiem: parsedMeridiem,
6631
+ });
6632
+ return;
6633
+ }
6366
6634
  }
6367
- setHour(parsedHour);
6368
- setMinute(parsedMinute);
6369
- setMeridiem(parsedMeridiem);
6370
- onChange({
6371
- hour: parsedHour,
6372
- minute: parsedMinute,
6373
- meridiem: parsedMeridiem,
6374
- });
6375
- return;
6376
6635
  }
6377
6636
  // Parse failed, select first result
6378
6637
  selectFirstResult();
@@ -6419,17 +6678,17 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6419
6678
  e.currentTarget?.blur();
6420
6679
  }
6421
6680
  };
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
- }
6681
+ 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, {}) }) })] }) }));
6682
+ };
6424
6683
 
6425
6684
  dayjs.extend(timezone);
6426
6685
  const TimePicker = ({ column, schema, prefix }) => {
6427
6686
  const { watch, formState: { errors }, setValue, } = useFormContext();
6428
- const { timezone, insideDialog } = useSchemaContext();
6687
+ const { timezone, insideDialog, timePickerLabels } = useSchemaContext();
6429
6688
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
6430
6689
  const isRequired = required?.some((columnId) => columnId === column);
6431
6690
  const colLabel = `${prefix}${column}`;
6432
- const formI18n = useFormI18n$1(column, prefix, schema);
6691
+ const formI18n = useFormI18n(column, prefix, schema);
6433
6692
  const [open, setOpen] = useState(false);
6434
6693
  const value = watch(colLabel);
6435
6694
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
@@ -6487,7 +6746,7 @@ const TimePicker = ({ column, schema, prefix }) => {
6487
6746
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6488
6747
  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
6748
  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 }) }) }) }) }))] }) }));
6749
+ }, 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
6750
  };
6492
6751
 
6493
6752
  dayjs.extend(utc);
@@ -6621,7 +6880,10 @@ dayjs.extend(utc);
6621
6880
  dayjs.extend(timezone);
6622
6881
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6623
6882
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6624
- onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, }) {
6883
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6884
+ placeholder: 'HH:mm:ss',
6885
+ emptyMessage: 'No time found',
6886
+ }, }) {
6625
6887
  // Generate time options (every 15 minutes, seconds always 0)
6626
6888
  const timeOptions = useMemo(() => {
6627
6889
  const options = [];
@@ -6884,7 +7146,7 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
6884
7146
  e.currentTarget?.blur();
6885
7147
  }
6886
7148
  };
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, {}) }) })] }) }));
7149
+ 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
7150
  }
6889
7151
 
6890
7152
  dayjs.extend(utc);
@@ -6907,7 +7169,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
6907
7169
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6908
7170
  backButtonLabel: 'Back',
6909
7171
  forwardButtonLabel: 'Next',
6910
- }, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7172
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
6911
7173
  console.log('[DateTimePicker] Component initialized with props:', {
6912
7174
  value,
6913
7175
  format,
@@ -7353,7 +7615,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7353
7615
  const dateObj = dayjs.tz(selectedDate, timezone);
7354
7616
  return dateObj.isValid() ? dateObj.format('Z') : null;
7355
7617
  }, [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) => {
7618
+ return (jsxs(Flex, { direction: "column", gap: 4, children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7357
7619
  if (date) {
7358
7620
  handleDateChange(date);
7359
7621
  }
@@ -7361,15 +7623,15 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7361
7623
  setSelectedDate('');
7362
7624
  onChange?.(undefined);
7363
7625
  }
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 })] }))] }));
7626
+ }, 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
7627
  }
7366
7628
 
7367
7629
  dayjs.extend(utc);
7368
7630
  dayjs.extend(timezone);
7369
7631
  const DateTimePicker = ({ column, schema, prefix, }) => {
7370
7632
  const { watch, formState: { errors }, setValue, } = useFormContext();
7371
- const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
7372
- const formI18n = useFormI18n$1(column, prefix, schema);
7633
+ const { timezone, dateTimePickerLabels, timePickerLabels, insideDialog } = useSchemaContext();
7634
+ const formI18n = useFormI18n(column, prefix, schema);
7373
7635
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
7374
7636
  // with timezone
7375
7637
  dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
@@ -7382,74 +7644,30 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7382
7644
  : '';
7383
7645
  const dateTimePickerLabelsConfig = {
7384
7646
  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
- }),
7647
+ 'January',
7648
+ 'February',
7649
+ 'March',
7650
+ 'April',
7651
+ 'May',
7652
+ 'June',
7653
+ 'July',
7654
+ 'August',
7655
+ 'September',
7656
+ 'October',
7657
+ 'November',
7658
+ 'December',
7421
7659
  ],
7422
7660
  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
- }),
7661
+ 'Sun',
7662
+ 'Mon',
7663
+ 'Tue',
7664
+ 'Wed',
7665
+ 'Thu',
7666
+ 'Fri',
7667
+ 'Sat',
7444
7668
  ],
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
- }),
7669
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
7670
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
7453
7671
  };
7454
7672
  const dateTimePickerContent = (jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
7455
7673
  if (!date || date === null || date === undefined) {
@@ -7463,7 +7681,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7463
7681
  else {
7464
7682
  setValue(colLabel, undefined);
7465
7683
  }
7466
- }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
7684
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels }));
7467
7685
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7468
7686
  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
7687
  setOpen(true);
@@ -7482,7 +7700,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7482
7700
  }
7483
7701
  if (variant === 'id-picker') {
7484
7702
  idPickerSanityCheck(column, foreign_key);
7485
- return jsx(IdPicker, { schema: colSchema, prefix, column });
7703
+ return jsx(IdPickerSingle, { schema: colSchema, prefix, column });
7486
7704
  }
7487
7705
  if (format === 'date') {
7488
7706
  return jsx(DatePicker, { schema: colSchema, prefix, column });
@@ -7516,7 +7734,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7516
7734
  if (type === 'array') {
7517
7735
  if (variant === 'id-picker') {
7518
7736
  idPickerSanityCheck(column, foreign_key);
7519
- return (jsx(IdPicker, { schema: colSchema, prefix, column, isMultiple: true }));
7737
+ return jsx(IdPickerMultiple, { schema: colSchema, prefix, column });
7520
7738
  }
7521
7739
  if (variant === 'tag-picker') {
7522
7740
  return jsx(TagPicker, { schema: colSchema, prefix, column });
@@ -7568,7 +7786,7 @@ const ArrayViewer = ({ schema, column, prefix }) => {
7568
7786
  const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
7569
7787
  const colLabel = `${prefix}${column}`;
7570
7788
  const isRequired = required?.some((columnId) => columnId === column);
7571
- const formI18n = useFormI18n$1(column, prefix, schema);
7789
+ const formI18n = useFormI18n(column, prefix, schema);
7572
7790
  const { watch, formState: { errors }, } = useFormContext();
7573
7791
  const values = watch(colLabel) ?? [];
7574
7792
  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 +7804,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
7586
7804
  const isRequired = required?.some((columnId) => columnId === column);
7587
7805
  const colLabel = `${prefix}${column}`;
7588
7806
  const value = watch(colLabel);
7589
- const formI18n = useFormI18n$1(column, prefix, schema);
7807
+ const formI18n = useFormI18n(column, prefix, schema);
7590
7808
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7591
7809
  gridRow, children: [jsx(Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
7592
7810
  };
@@ -7610,7 +7828,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7610
7828
  const isRequired = required?.some((columnId) => columnId === column);
7611
7829
  const colLabel = `${prefix}${column}`;
7612
7830
  const selectedDate = watch(colLabel);
7613
- const formI18n = useFormI18n$1(column, prefix, schema);
7831
+ const formI18n = useFormI18n(column, prefix, schema);
7614
7832
  const displayDate = dayjs(selectedDate)
7615
7833
  .tz(timezone)
7616
7834
  .format(displayDateFormat);
@@ -7620,7 +7838,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7620
7838
 
7621
7839
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
7622
7840
  const { watch, formState: { errors }, } = useFormContext();
7623
- const formI18n = useFormI18n$1(column, prefix);
7841
+ const formI18n = useFormI18n(column, prefix);
7624
7842
  const { required } = schema;
7625
7843
  const isRequired = required?.some((columnId) => columnId === column);
7626
7844
  const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
@@ -7644,7 +7862,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7644
7862
  const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
7645
7863
  const isRequired = required?.some((columnId) => columnId === column);
7646
7864
  const currentFiles = (watch(column) ?? []);
7647
- const formI18n = useFormI18n$1(column, prefix, schema);
7865
+ const formI18n = useFormI18n(column, prefix, schema);
7648
7866
  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
7867
  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
7868
  }) }) }));
@@ -7652,7 +7870,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7652
7870
 
7653
7871
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7654
7872
  const { watch, formState: { errors }, } = useFormContext();
7655
- const { idMap, translate } = useSchemaContext();
7873
+ const { idMap, idPickerLabels, formButtonLabels } = useSchemaContext();
7656
7874
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7657
7875
  const isRequired = required?.some((columnId) => columnId === column);
7658
7876
  const formI18n = useFormI18n(column, prefix, schema);
@@ -7676,12 +7894,12 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7676
7894
  gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
7677
7895
  const item = idMap[id];
7678
7896
  if (item === undefined) {
7679
- return (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
7897
+ return (jsx(Text, { children: idPickerLabels?.undefined ?? 'Undefined' }, id));
7680
7898
  }
7681
7899
  return (jsx(Tag, { closable: true, children: renderDisplay
7682
7900
  ? renderDisplay(item)
7683
7901
  : defaultRenderDisplay(item) }, id));
7684
- }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
7902
+ }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: formButtonLabels?.fieldRequired ?? formI18n.required() }))] }));
7685
7903
  };
7686
7904
 
7687
7905
  const NumberViewer = ({ schema, column, prefix, }) => {
@@ -7690,7 +7908,7 @@ const NumberViewer = ({ schema, column, prefix, }) => {
7690
7908
  const isRequired = required?.some((columnId) => columnId === column);
7691
7909
  const colLabel = `${prefix}${column}`;
7692
7910
  const value = watch(colLabel);
7693
- const formI18n = useFormI18n$1(column, prefix, schema);
7911
+ const formI18n = useFormI18n(column, prefix, schema);
7694
7912
  // Format the value for display if formatOptions are provided
7695
7913
  const formatValue = (val) => {
7696
7914
  if (val === undefined || val === null || val === '')
@@ -7716,7 +7934,7 @@ const ObjectViewer = ({ schema, column, prefix }) => {
7716
7934
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
7717
7935
  const colLabel = `${prefix}${column}`;
7718
7936
  const isRequired = required?.some((columnId) => columnId === column);
7719
- const formI18n = useFormI18n$1(column, prefix, schema);
7937
+ const formI18n = useFormI18n(column, prefix, schema);
7720
7938
  const { formState: { errors }, } = useFormContext();
7721
7939
  if (properties === undefined) {
7722
7940
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -7738,7 +7956,7 @@ const RecordViewer = ({ column, schema, prefix }) => {
7738
7956
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
7739
7957
  const isRequired = required?.some((columnId) => columnId === column);
7740
7958
  const entries = Object.entries(getValues(column) ?? {});
7741
- const formI18n = useFormI18n$1(column, prefix, schema);
7959
+ const formI18n = useFormI18n(column, prefix, schema);
7742
7960
  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
7961
  return (jsxs(Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxs(Text, { fontWeight: "medium", children: [key, ":"] }), jsx(Text, { children: String(value ?? '') })] }, key));
7744
7962
  }) })), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
@@ -7750,7 +7968,7 @@ const StringViewer = ({ column, schema, prefix, }) => {
7750
7968
  const isRequired = required?.some((columnId) => columnId === column);
7751
7969
  const colLabel = `${prefix}${column}`;
7752
7970
  const value = watch(colLabel);
7753
- const formI18n = useFormI18n$1(column, prefix, schema);
7971
+ const formI18n = useFormI18n(column, prefix, schema);
7754
7972
  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
7973
  };
7756
7974
 
@@ -7845,7 +8063,7 @@ const TextAreaViewer = ({ column, schema, prefix, }) => {
7845
8063
  const isRequired = required?.some((columnId) => columnId === column);
7846
8064
  const colLabel = `${prefix}${column}`;
7847
8065
  const value = watch(colLabel);
7848
- const formI18n = useFormI18n$1(column, prefix, schema);
8066
+ const formI18n = useFormI18n(column, prefix, schema);
7849
8067
  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
8068
  };
7851
8069
 
@@ -7856,7 +8074,7 @@ const TimeViewer = ({ column, schema, prefix }) => {
7856
8074
  const isRequired = required?.some((columnId) => columnId === column);
7857
8075
  const colLabel = `${prefix}${column}`;
7858
8076
  const selectedDate = watch(colLabel);
7859
- const formI18n = useFormI18n$1(column, prefix, schema);
8077
+ const formI18n = useFormI18n(column, prefix, schema);
7860
8078
  const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
7861
8079
  .tz(timezone)
7862
8080
  .isValid()
@@ -7873,7 +8091,7 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
7873
8091
  const isRequired = required?.some((columnId) => columnId === column);
7874
8092
  const colLabel = `${prefix}${column}`;
7875
8093
  const selectedDate = watch(colLabel);
7876
- const formI18n = useFormI18n$1(column, prefix, schema);
8094
+ const formI18n = useFormI18n(column, prefix, schema);
7877
8095
  const displayDate = dayjs(selectedDate)
7878
8096
  .tz(timezone)
7879
8097
  .format(displayDateFormat);
@@ -7967,7 +8185,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
7967
8185
  };
7968
8186
 
7969
8187
  const SubmitButton = () => {
7970
- const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
8188
+ const { setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
7971
8189
  const methods = useFormContext();
7972
8190
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7973
8191
  const onValid = (data) => {
@@ -7996,11 +8214,11 @@ const SubmitButton = () => {
7996
8214
  };
7997
8215
  return (jsx(Button$1, { onClick: () => {
7998
8216
  methods.handleSubmit(onValid)();
7999
- }, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
8217
+ }, formNoValidate: true, children: formButtonLabels?.submit ?? 'Submit' }));
8000
8218
  };
8001
8219
 
8002
8220
  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();
8221
+ const { schema, order, ignore, include, isError, isSubmiting, isConfirming, setIsConfirming, validatedData, error, customErrorRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8004
8222
  const { showSubmitButton, showResetButton } = displayConfig;
8005
8223
  const methods = useFormContext();
8006
8224
  const { properties } = schema;
@@ -8017,21 +8235,6 @@ const FormBody = () => {
8017
8235
  ignore,
8018
8236
  include,
8019
8237
  });
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
8238
  if (isConfirming) {
8036
8239
  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
8240
  return (jsx(ColumnViewer
@@ -8041,9 +8244,9 @@ const FormBody = () => {
8041
8244
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
8042
8245
  }) }), jsxs(Flex, { justifyContent: 'end', gap: '2', children: [jsx(Button$1, { onClick: () => {
8043
8246
  setIsConfirming(false);
8044
- }, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsx(Button$1, { onClick: () => {
8247
+ }, variant: 'subtle', children: formButtonLabels?.cancel ?? 'Cancel' }), jsx(Button$1, { onClick: () => {
8045
8248
  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)] }));
8249
+ }, 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
8250
  }
8048
8251
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
8049
8252
  return (jsx(ColumnRenderer
@@ -8053,12 +8256,12 @@ const FormBody = () => {
8053
8256
  properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
8054
8257
  }) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
8055
8258
  methods.reset();
8056
- }, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8259
+ }, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8057
8260
  };
8058
8261
 
8059
8262
  const FormTitle = () => {
8060
- const { translate } = useSchemaContext();
8061
- return jsx(Heading, { children: translate.t("title") });
8263
+ const { schema } = useSchemaContext();
8264
+ return jsx(Heading, { children: schema.title ?? 'Form' });
8062
8265
  };
8063
8266
 
8064
8267
  const DefaultForm = ({ formConfig, }) => {
@@ -8066,7 +8269,9 @@ const DefaultForm = ({ formConfig, }) => {
8066
8269
  return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
8067
8270
  };
8068
8271
 
8069
- const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8272
+ const useForm = ({ preLoadedValues, keyPrefix: _keyPrefix, // Deprecated: kept for backward compatibility
8273
+ namespace: _namespace, // Deprecated: kept for backward compatibility
8274
+ schema, }) => {
8070
8275
  const form = useForm$1({
8071
8276
  values: preLoadedValues,
8072
8277
  resolver: schema ? ajvResolver(schema) : undefined,
@@ -8074,12 +8279,16 @@ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8074
8279
  reValidateMode: 'onBlur',
8075
8280
  });
8076
8281
  const [idMap, setIdMap] = useState({});
8077
- const translate = useTranslation(namespace || '', { keyPrefix });
8282
+ // Fallback translate object - returns key as-is (no i18n required)
8283
+ const translate = {
8284
+ t: (key) => key,
8285
+ ready: true,
8286
+ };
8078
8287
  return {
8079
8288
  form,
8080
8289
  idMap,
8081
8290
  setIdMap,
8082
- translate,
8291
+ translate, // Components prefer label objects over translate
8083
8292
  };
8084
8293
  };
8085
8294
 
@@ -8407,6 +8616,21 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
8407
8616
  })] }));
8408
8617
  };
8409
8618
 
8619
+ 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 = {}, }) => {
8620
+ const { tableLabel, table } = useDataTableContext();
8621
+ const { hasErrorText } = tableLabel;
8622
+ 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) => {
8623
+ const { column, options } = option;
8624
+ const tableColumn = table.getColumn(column);
8625
+ 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) => {
8626
+ if (tags.length === 0) {
8627
+ return tableColumn?.setFilterValue(undefined);
8628
+ }
8629
+ tableColumn?.setFilterValue(tags);
8630
+ } })] }, column));
8631
+ }) })), 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, {}) }))] }))] }));
8632
+ };
8633
+
8410
8634
  const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
8411
8635
  'use no memo';
8412
8636
  const { table } = useDataTableContext();
@@ -8466,7 +8690,68 @@ const TableRowSelectorSkeleton = () => {
8466
8690
  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
8691
  };
8468
8692
 
8693
+ const MobileTableDisplay = ({ showSelector = false, isLoading = false, }) => {
8694
+ const { table, rowSelection, setRowSelection } = useDataTableContext();
8695
+ if (isLoading) {
8696
+ return jsx(MobileTableSkeleton, { showSelector: showSelector });
8697
+ }
8698
+ return (jsx(Stack, { gap: 4, padding: 2, children: table.getRowModel().rows.map((row) => {
8699
+ 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),
8700
+ disabled: !canRowSelect(row),
8701
+ onCheckedChange: createRowToggleHandler(row, rowSelection, setRowSelection) }) })), jsx(Stack, { gap: 3, children: row.getVisibleCells().map((cell) => {
8702
+ const displayName = cell.column.columnDef.meta?.displayName ?? cell.column.id;
8703
+ 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}`));
8704
+ }) })] }) }, `mobile-table-card-${row.id}`));
8705
+ }) }));
8706
+ };
8707
+ const MobileTableSkeleton = ({ showSelector = false, }) => {
8708
+ const { table } = useDataTableContext();
8709
+ const pageSize = table.getState().pagination.pageSize;
8710
+ const visibleColumns = table.getVisibleLeafColumns();
8711
+ return (jsx(Stack, { gap: 4, padding: 2, children: Array.from({ length: pageSize }).map((_, rowIndex) => {
8712
+ 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) => {
8713
+ 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}`));
8714
+ }) })] }) }, `mobile-skeleton-${rowIndex}`));
8715
+ }) }));
8716
+ };
8717
+
8718
+ /**
8719
+ * Hook to detect if the current window width is mobile (< 768px)
8720
+ * @param breakpoint - The breakpoint in pixels to consider as mobile (default: 768)
8721
+ * @returns boolean indicating if the window is mobile
8722
+ */
8723
+ const useIsMobile = (breakpoint = 768) => {
8724
+ const [isMobile, setIsMobile] = useState(() => {
8725
+ if (typeof window === 'undefined')
8726
+ return false;
8727
+ return window.innerWidth < breakpoint;
8728
+ });
8729
+ useEffect(() => {
8730
+ if (typeof window === 'undefined')
8731
+ return;
8732
+ const handleResize = () => {
8733
+ setIsMobile(window.innerWidth < breakpoint);
8734
+ };
8735
+ // Set initial value
8736
+ handleResize();
8737
+ // Add event listener
8738
+ window.addEventListener('resize', handleResize);
8739
+ // Cleanup
8740
+ return () => {
8741
+ window.removeEventListener('resize', handleResize);
8742
+ };
8743
+ }, [breakpoint]);
8744
+ return isMobile;
8745
+ };
8746
+
8469
8747
  const DefaultTable = ({ showFooter = false, showHeader = true, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = 'greedy', isLoading = false, }) => {
8748
+ const isMobile = useIsMobile();
8749
+ // Early return for mobile display
8750
+ if (isMobile) {
8751
+ return (jsx(MobileTableControls, { ...controlProps, children: jsx(MobileTableDisplay, { showSelector: tableHeaderProps.showSelector ??
8752
+ tableBodyProps.showSelector ??
8753
+ false, isLoading: isLoading }) }));
8754
+ }
8470
8755
  const isGreedy = variant === 'greedy';
8471
8756
  const canResize = !isGreedy;
8472
8757
  const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: canResize })) : (jsx(TableBody, { ...tableBodyProps, canResize: canResize }));
@@ -8567,6 +8852,290 @@ const DataDisplay = ({ variant = '' }) => {
8567
8852
  }) }));
8568
8853
  };
8569
8854
 
8855
+ // Helper function to normalize date
8856
+ function normalizeDate(value) {
8857
+ if (!value)
8858
+ return null;
8859
+ if (value instanceof Date)
8860
+ return value;
8861
+ if (typeof value === 'string' || typeof value === 'number') {
8862
+ const date = dayjs(value).toDate();
8863
+ return isNaN(date.getTime()) ? null : date;
8864
+ }
8865
+ return null;
8866
+ }
8867
+ // Component to conditionally render event title based on available width
8868
+ function ResponsiveEventTitle({ title, placeholder, minWidth, minChars, cellRef, }) {
8869
+ const [truncatedText, setTruncatedText] = useState('');
8870
+ const measureRef = useRef(null);
8871
+ useEffect(() => {
8872
+ const calculateTruncatedText = () => {
8873
+ if (!cellRef.current || !measureRef.current || !title) {
8874
+ setTruncatedText(title || 'Event');
8875
+ return;
8876
+ }
8877
+ const cellWidth = cellRef.current.clientWidth;
8878
+ // Account for padding (approximately 8px on each side)
8879
+ const availableWidth = cellWidth - 16;
8880
+ // If cell is too narrow, calculate how many characters can fit
8881
+ if (availableWidth < minWidth) {
8882
+ // Measure text width using canvas
8883
+ const canvas = document.createElement('canvas');
8884
+ const context = canvas.getContext('2d');
8885
+ if (!context) {
8886
+ setTruncatedText(placeholder);
8887
+ return;
8888
+ }
8889
+ // Get computed font style from the element
8890
+ const computedStyle = window.getComputedStyle(measureRef.current);
8891
+ context.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
8892
+ const ellipsisWidth = context.measureText('...').width;
8893
+ const maxWidth = availableWidth - ellipsisWidth;
8894
+ // Try to show at least minChars characters before ellipsis
8895
+ let truncated = '';
8896
+ let charCount = 0;
8897
+ // Calculate how many characters can fit
8898
+ for (let i = 0; i < Math.min(title.length, 50); i++) {
8899
+ const testText = title.substring(0, i + 1);
8900
+ const textWidth = context.measureText(testText).width;
8901
+ if (textWidth <= maxWidth) {
8902
+ truncated = testText;
8903
+ charCount = i + 1;
8904
+ }
8905
+ else {
8906
+ break;
8907
+ }
8908
+ }
8909
+ // Ensure we show at least minChars characters if possible
8910
+ if (charCount < minChars && title.length >= minChars) {
8911
+ truncated = title.substring(0, minChars);
8912
+ }
8913
+ else if (charCount === 0 && title.length >= 1) {
8914
+ truncated = title.substring(0, 1);
8915
+ }
8916
+ // Only show ellipsis if we have at least minChars characters
8917
+ if (truncated && truncated.length >= minChars) {
8918
+ setTruncatedText(`${truncated}...`);
8919
+ }
8920
+ else {
8921
+ setTruncatedText(placeholder);
8922
+ }
8923
+ }
8924
+ else {
8925
+ // Full width available, show full title
8926
+ setTruncatedText(title);
8927
+ }
8928
+ };
8929
+ calculateTruncatedText();
8930
+ const resizeObserver = new ResizeObserver(calculateTruncatedText);
8931
+ if (cellRef.current) {
8932
+ resizeObserver.observe(cellRef.current);
8933
+ }
8934
+ // Also check on window resize
8935
+ window.addEventListener('resize', calculateTruncatedText);
8936
+ return () => {
8937
+ resizeObserver.disconnect();
8938
+ window.removeEventListener('resize', calculateTruncatedText);
8939
+ };
8940
+ }, [cellRef, minWidth, title, placeholder]);
8941
+ return (jsxs(Fragment, { children: [jsx("span", { ref: measureRef, style: {
8942
+ visibility: 'hidden',
8943
+ position: 'absolute',
8944
+ whiteSpace: 'nowrap',
8945
+ }, children: title || 'Event' }), truncatedText || title || 'Event'] }));
8946
+ }
8947
+ function CalendarDisplay({ dateColumn, getDate, getEventTitle, getEventColor, renderEvent, firstDayOfWeek = 0, showOutsideDays = true, monthsToDisplay = 1, labels = {
8948
+ monthNamesShort: [
8949
+ 'Jan',
8950
+ 'Feb',
8951
+ 'Mar',
8952
+ 'Apr',
8953
+ 'May',
8954
+ 'Jun',
8955
+ 'Jul',
8956
+ 'Aug',
8957
+ 'Sep',
8958
+ 'Oct',
8959
+ 'Nov',
8960
+ 'Dec',
8961
+ ],
8962
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
8963
+ backButtonLabel: 'Back',
8964
+ forwardButtonLabel: 'Next',
8965
+ }, onDateClick, onEventClick, maxEventsPerDay = 3, colorPalette = 'blue', eventPlaceholder = '...', minEventWidth = 80, minCharsBeforeEllipsis = 2, }) {
8966
+ const { data, table } = useDataTableContext();
8967
+ // Map table data to events
8968
+ const events = useMemo(() => {
8969
+ return data
8970
+ .map((row) => {
8971
+ let dateValue;
8972
+ if (getDate) {
8973
+ dateValue = getDate(row);
8974
+ }
8975
+ else {
8976
+ // Try to get date from column
8977
+ const rowData = table
8978
+ .getRowModel()
8979
+ .rows.find((r) => r.original === row);
8980
+ if (rowData) {
8981
+ const cell = rowData.getAllCells().find((c) => {
8982
+ const colId = c.column.id;
8983
+ const accessorKey = c.column.columnDef.accessorKey;
8984
+ return colId === dateColumn || accessorKey === dateColumn;
8985
+ });
8986
+ dateValue = cell?.getValue();
8987
+ }
8988
+ }
8989
+ const date = normalizeDate(dateValue);
8990
+ if (!date)
8991
+ return null;
8992
+ let title;
8993
+ if (getEventTitle) {
8994
+ title = getEventTitle(row);
8995
+ }
8996
+ else {
8997
+ // Use first column's value as title
8998
+ const rowData = table
8999
+ .getRowModel()
9000
+ .rows.find((r) => r.original === row);
9001
+ if (rowData) {
9002
+ const firstCell = rowData.getAllCells()[0];
9003
+ title = String(firstCell?.getValue() ?? '');
9004
+ }
9005
+ }
9006
+ const color = getEventColor?.(row);
9007
+ return {
9008
+ data: row,
9009
+ date,
9010
+ title,
9011
+ color,
9012
+ };
9013
+ })
9014
+ .filter((event) => event !== null);
9015
+ }, [data, table, dateColumn, getDate, getEventTitle, getEventColor]);
9016
+ // Group events by date
9017
+ const eventsByDate = useMemo(() => {
9018
+ const map = new Map();
9019
+ events.forEach((event) => {
9020
+ const dateKey = `${event.date.getFullYear()}-${event.date.getMonth()}-${event.date.getDate()}`;
9021
+ if (!map.has(dateKey)) {
9022
+ map.set(dateKey, []);
9023
+ }
9024
+ map.get(dateKey).push(event);
9025
+ });
9026
+ return map;
9027
+ }, [events]);
9028
+ // Get events for a specific date
9029
+ const getEventsForDate = useCallback((date) => {
9030
+ const dateKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
9031
+ return eventsByDate.get(dateKey) ?? [];
9032
+ }, [eventsByDate]);
9033
+ const calendarData = useCalendar({
9034
+ firstDayOfWeek,
9035
+ showOutsideDays,
9036
+ monthsToDisplay,
9037
+ });
9038
+ const getDateProps = useCallback((props) => {
9039
+ const dateEvents = getEventsForDate(props.dateObj.date);
9040
+ const baseProps = calendarData.getDateProps({ dateObj: props.dateObj });
9041
+ return {
9042
+ ...baseProps,
9043
+ onClick: () => {
9044
+ baseProps.onClick?.();
9045
+ if (onDateClick) {
9046
+ onDateClick(props.dateObj.date, dateEvents);
9047
+ }
9048
+ },
9049
+ };
9050
+ }, [calendarData, getEventsForDate, onDateClick]);
9051
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
9052
+ if (!calendarData.calendars.length) {
9053
+ return null;
9054
+ }
9055
+ return (jsxs(VStack, { gap: 4, width: "100%", children: [jsxs(HStack, { gap: 2, justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({
9056
+ calendars: calendarData.calendars,
9057
+ offset: 12,
9058
+ }), children: '<<' }), jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({ calendars: calendarData.calendars }), children: backButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9059
+ calendars: calendarData.calendars,
9060
+ }), children: forwardButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9061
+ calendars: calendarData.calendars,
9062
+ offset: 12,
9063
+ }), children: '>>' })] }), jsx(Grid, { templateColumns: {
9064
+ base: '1fr',
9065
+ md: monthsToDisplay >= 2 ? 'repeat(2, 1fr)' : '1fr',
9066
+ lg: monthsToDisplay >= 3
9067
+ ? 'repeat(3, 1fr)'
9068
+ : monthsToDisplay === 2
9069
+ ? 'repeat(2, 1fr)'
9070
+ : '1fr',
9071
+ xl: `repeat(${Math.min(monthsToDisplay, 4)}, 1fr)`,
9072
+ }, 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) => {
9073
+ const weekday = (weekdayNum + firstDayOfWeek) % 7;
9074
+ 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}`));
9075
+ }) }), jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
9076
+ const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
9077
+ if (!dateObj) {
9078
+ return jsx(Box, {}, key);
9079
+ }
9080
+ const { date, today, isCurrentMonth } = dateObj;
9081
+ const dateEvents = getEventsForDate(date);
9082
+ const cellRef = useRef(null);
9083
+ return (jsxs(VStack, { ref: cellRef, gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", minHeight: { base: '60px', md: '80px', lg: '100px' }, borderWidth: "1px", borderColor: {
9084
+ base: today ? `${colorPalette}.300` : 'gray.200',
9085
+ _dark: today ? `${colorPalette}.700` : 'gray.700',
9086
+ }, borderRadius: { base: 'sm', md: 'md' }, padding: { base: 0.5, md: 1 }, bgColor: {
9087
+ base: today ? `${colorPalette}.50` : 'white',
9088
+ _dark: today ? `${colorPalette}.950` : 'gray.900',
9089
+ }, opacity: isCurrentMonth ? 1 : 0.5, ...getDateProps({ dateObj }), cursor: onDateClick ? 'pointer' : 'default', _hover: onDateClick
9090
+ ? {
9091
+ bgColor: {
9092
+ base: `${colorPalette}.100`,
9093
+ _dark: `${colorPalette}.900`,
9094
+ },
9095
+ }
9096
+ : {}, children: [jsx(Text, { fontSize: { base: 'xs', md: 'sm' }, fontWeight: today ? 'bold' : 'normal', color: {
9097
+ base: today ? `${colorPalette}.700` : 'gray.700',
9098
+ _dark: today ? `${colorPalette}.300` : 'gray.300',
9099
+ }, 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
9100
+ .slice(0, maxEventsPerDay)
9101
+ .map((event, eventIndex) => {
9102
+ 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: {
9103
+ base: event.color
9104
+ ? `${event.color}.100`
9105
+ : `${colorPalette}.100`,
9106
+ _dark: event.color
9107
+ ? `${event.color}.900`
9108
+ : `${colorPalette}.900`,
9109
+ }, color: {
9110
+ base: event.color
9111
+ ? `${event.color}.800`
9112
+ : `${colorPalette}.800`,
9113
+ _dark: event.color
9114
+ ? `${event.color}.200`
9115
+ : `${colorPalette}.200`,
9116
+ }, onClick: (e) => {
9117
+ e.stopPropagation();
9118
+ if (onEventClick) {
9119
+ onEventClick(event);
9120
+ }
9121
+ }, cursor: onEventClick ? 'pointer' : 'default', _hover: onEventClick
9122
+ ? {
9123
+ opacity: 0.8,
9124
+ }
9125
+ : {}, children: jsx(ResponsiveEventTitle, { title: event.title, placeholder: eventPlaceholder, minWidth: minEventWidth, minChars: minCharsBeforeEllipsis, cellRef: cellRef }) }, eventIndex));
9126
+ return (jsx(Box, { onClick: (e) => e.stopPropagation(), children: eventContent }, eventIndex));
9127
+ }), dateEvents.length > maxEventsPerDay && (jsxs(Text, { fontSize: "xs", color: {
9128
+ base: `${colorPalette}.600`,
9129
+ _dark: `${colorPalette}.400`,
9130
+ }, paddingX: 1, onClick: (e) => {
9131
+ e.stopPropagation();
9132
+ if (onDateClick) {
9133
+ onDateClick(date, dateEvents);
9134
+ }
9135
+ }, cursor: onDateClick ? 'pointer' : 'default', children: ["+", dateEvents.length - maxEventsPerDay, " more"] }))] })] }, key));
9136
+ })) })] }, `${calendar.month}${calendar.year}`))) })] }));
9137
+ }
9138
+
8570
9139
  // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
8571
9140
  // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
8572
9141
  // end of TS setup!
@@ -8667,7 +9236,7 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
8667
9236
  *
8668
9237
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8669
9238
  */
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 = {
9239
+ 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
9240
  view: 'View',
8672
9241
  edit: 'Edit',
8673
9242
  filterButtonText: 'Filter',
@@ -8678,7 +9247,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8678
9247
  reloadButtonText: 'Reload',
8679
9248
  resetSelection: 'Reset Selection',
8680
9249
  resetSorting: 'Reset Sorting',
8681
- rowCountText: 'Row Count',
9250
+ rowCountText: '',
8682
9251
  hasErrorText: 'Has Error',
8683
9252
  globalFilterPlaceholder: 'Search',
8684
9253
  trueLabel: 'True',
@@ -8735,7 +9304,6 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8735
9304
  globalFilter,
8736
9305
  setGlobalFilter,
8737
9306
  type: 'client',
8738
- translate,
8739
9307
  columns: columns,
8740
9308
  sorting,
8741
9309
  setSorting,
@@ -8767,22 +9335,22 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8767
9335
  *
8768
9336
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8769
9337
  */
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",
9338
+ 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 = {
9339
+ view: 'View',
9340
+ edit: 'Edit',
9341
+ filterButtonText: 'Filter',
9342
+ filterTitle: 'Filter',
9343
+ filterReset: 'Reset',
9344
+ filterClose: 'Close',
9345
+ reloadTooltip: 'Reload',
9346
+ reloadButtonText: 'Reload',
9347
+ resetSelection: 'Reset Selection',
9348
+ resetSorting: 'Reset Sorting',
9349
+ rowCountText: '',
9350
+ hasErrorText: 'Has Error',
9351
+ globalFilterPlaceholder: 'Search',
9352
+ trueLabel: 'True',
9353
+ falseLabel: 'False',
8786
9354
  }, }) {
8787
9355
  const table = useReactTable({
8788
9356
  _features: [DensityFeature],
@@ -8792,7 +9360,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8792
9360
  getCoreRowModel: getCoreRowModel(),
8793
9361
  manualPagination: true,
8794
9362
  manualSorting: true,
8795
- columnResizeMode: "onChange",
9363
+ columnResizeMode: 'onChange',
8796
9364
  defaultColumn: {
8797
9365
  size: 150, //starting column size
8798
9366
  minSize: 10, //enforced during column resizing
@@ -8835,8 +9403,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8835
9403
  table: table,
8836
9404
  globalFilter,
8837
9405
  setGlobalFilter,
8838
- type: "server",
8839
- translate,
9406
+ type: 'server',
8840
9407
  columns: columns,
8841
9408
  sorting,
8842
9409
  setSorting,
@@ -8854,7 +9421,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8854
9421
  setColumnVisibility,
8855
9422
  data: query.data?.data ?? [],
8856
9423
  tableLabel,
8857
- }, children: jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
9424
+ }, children: jsx(DataTableServerContext.Provider, { value: { url: url ?? '', query }, children: children }) }));
8858
9425
  }
8859
9426
 
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 };
9427
+ 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 };