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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts +170 -43
  3. package/dist/index.js +1166 -637
  4. package/dist/index.mjs +1168 -640
  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/DefaultTable.d.ts +2 -1
  8. package/dist/types/components/DataTable/context/DataTableContext.d.ts +4 -6
  9. package/dist/types/components/DataTable/controls/MobileTableControls.d.ts +29 -0
  10. package/dist/types/components/DataTable/controls/TableControls.d.ts +2 -2
  11. package/dist/types/components/DataTable/display/CalendarDisplay.d.ts +84 -0
  12. package/dist/types/components/DataTable/display/DataDisplay.d.ts +0 -2
  13. package/dist/types/components/DataTable/display/MobileTableDisplay.d.ts +5 -0
  14. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +1 -3
  15. package/dist/types/components/DataTable/display/TextCell.d.ts +2 -1
  16. package/dist/types/components/DataTable/hooks/useIsMobile.d.ts +6 -0
  17. package/dist/types/components/DataTable/useDataTable.d.ts +3 -6
  18. package/dist/types/components/DataTable/useDataTableServer.d.ts +4 -4
  19. package/dist/types/components/DataTable/utils/getColumns.d.ts +3 -5
  20. package/dist/types/components/DatePicker/DatePicker.d.ts +7 -8
  21. package/dist/types/components/DatePicker/DateTimePicker.d.ts +3 -1
  22. package/dist/types/components/DatePicker/IsoTimePicker.d.ts +5 -1
  23. package/dist/types/components/DatePicker/RangeDatePicker.d.ts +4 -4
  24. package/dist/types/components/DatePicker/useCalendar.d.ts +48 -0
  25. package/dist/types/components/Form/SchemaFormContext.d.ts +5 -3
  26. package/dist/types/components/Form/components/core/FormBody.d.ts +1 -2
  27. package/dist/types/components/Form/components/core/FormRoot.d.ts +6 -4
  28. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -2
  29. package/dist/types/components/Form/components/fields/IdPicker.d.ts +8 -0
  30. package/dist/types/components/Form/components/fields/IdPickerMultiple.d.ts +7 -0
  31. package/dist/types/components/Form/components/fields/IdPickerSingle.d.ts +7 -0
  32. package/dist/types/components/Form/components/fields/useIdPickerData.d.ts +46 -0
  33. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +9 -0
  34. package/dist/types/components/Form/useForm.d.ts +7 -2
  35. package/dist/types/components/Form/utils/useFormI18n.d.ts +14 -12
  36. package/dist/types/components/TimePicker/TimePicker.d.ts +4 -6
  37. package/dist/types/components/ui/provider.d.ts +1 -1
  38. package/dist/types/index.d.ts +1 -0
  39. 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) => {
@@ -3494,14 +3730,14 @@ const highlightText = (text, searchTerm) => {
3494
3730
  }
3495
3731
  return parts.length > 0 ? jsx(Fragment, { children: parts }) : textStr;
3496
3732
  };
3497
- const RenderValue = ({ text, href, onClick, isCopyable, isBadge, badgeColor, colorPalette, globalFilter, }) => {
3733
+ const RenderValue = ({ text, href, onClick, isCopyable, isBadge, badgeColor, colorPalette, globalFilter, alignEnd = false, }) => {
3498
3734
  const highlightedText = useMemo(() => highlightText(text ?? '', globalFilter), [text, globalFilter]);
3499
3735
  if (isBadge) {
3500
3736
  return (jsx(Badge, { colorPalette: colorPalette || badgeColor, children: highlightedText }));
3501
3737
  }
3502
3738
  // onClick takes precedence over href
3503
3739
  if (onClick) {
3504
- return (jsx(Box, { as: "button", onClick: onClick, cursor: "pointer", textAlign: "left", _hover: {
3740
+ return (jsx(Box, { as: "button", onClick: onClick, cursor: "pointer", textAlign: alignEnd ? 'right' : 'left', _hover: {
3505
3741
  textDecoration: 'underline',
3506
3742
  color: {
3507
3743
  base: 'blue.500',
@@ -3519,7 +3755,7 @@ const RenderValue = ({ text, href, onClick, isCopyable, isBadge, badgeColor, col
3519
3755
  }
3520
3756
  return jsx(Fragment, { children: highlightedText });
3521
3757
  };
3522
- const TextCell = ({ text, href, onClick, isCopyable, isBadge, badgeColor, colorPalette,
3758
+ const TextCell = ({ text, href, onClick, isCopyable, isBadge, badgeColor, colorPalette, alignEnd = false,
3523
3759
  // Legacy props
3524
3760
  label, containerProps = {}, textProps = {}, children, }) => {
3525
3761
  // Get globalFilter from context
@@ -3533,23 +3769,25 @@ label, containerProps = {}, textProps = {}, children, }) => {
3533
3769
  const highlightedDisplayText = typeof displayText === 'string' || typeof displayText === 'number'
3534
3770
  ? highlightText(displayText, globalFilter)
3535
3771
  : displayText;
3772
+ const flexJustifyContent = alignEnd ? 'flex-end' : undefined;
3773
+ const textAlign = alignEnd ? 'right' : undefined;
3536
3774
  if (label) {
3537
- return (jsx(Flex, { alignItems: 'center', height: '100%', ...containerProps, children: jsx(Tooltip, { content: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', children: label }), children: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', wordBreak: 'break-all', ...textProps, children: highlightedDisplayText }) }) }));
3775
+ return (jsx(Flex, { alignItems: 'center', justifyContent: flexJustifyContent, height: '100%', ...containerProps, children: jsx(Tooltip, { content: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', children: label }), children: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', wordBreak: 'break-all', textAlign: textAlign, ...textProps, children: highlightedDisplayText }) }) }));
3538
3776
  }
3539
- return (jsx(Flex, { alignItems: 'center', height: '100%', ...containerProps, children: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', wordBreak: 'break-all', ...textProps, children: highlightedDisplayText }) }));
3777
+ return (jsx(Flex, { alignItems: 'center', justifyContent: flexJustifyContent, height: '100%', ...containerProps, children: jsx(Text, { as: "span", overflow: "hidden", textOverflow: 'ellipsis', wordBreak: 'break-all', textAlign: textAlign, ...textProps, children: highlightedDisplayText }) }));
3540
3778
  }
3541
3779
  // New API: use text prop
3542
3780
  const displayValue = text ?? children;
3543
3781
  if (Array.isArray(displayValue)) {
3544
- return (jsx(Flex, { gap: 2, flexWrap: "wrap", children: displayValue.map((item, index) => {
3782
+ return (jsx(Flex, { gap: 2, flexWrap: "wrap", justifyContent: alignEnd ? 'flex-end' : undefined, children: displayValue.map((item, index) => {
3545
3783
  const highlightedItem = highlightText(item, globalFilter);
3546
3784
  return (jsx(Badge, { colorPalette: colorPalette || badgeColor, children: highlightedItem }, index));
3547
3785
  }) }));
3548
3786
  }
3549
3787
  if (!!displayValue === false) {
3550
- return (jsx(Text, { textOverflow: "ellipsis", whiteSpace: "nowrap", overflow: "hidden", wordBreak: "break-all", display: "flex", alignItems: "center", height: "100%", children: "-" }));
3788
+ return (jsx(Text, { textOverflow: "ellipsis", whiteSpace: "nowrap", overflow: "hidden", wordBreak: "break-all", display: "flex", alignItems: "center", justifyContent: alignEnd ? 'flex-end' : undefined, height: "100%", textAlign: alignEnd ? 'right' : undefined, children: "-" }));
3551
3789
  }
3552
- return (jsx(Box, { textOverflow: "ellipsis", whiteSpace: "nowrap", wordBreak: "break-all", overflow: "auto", display: "flex", alignItems: "center", height: "100%", children: jsx(RenderValue, { text: displayValue, href: href, onClick: onClick, isCopyable: isCopyable, isBadge: isBadge, badgeColor: badgeColor, colorPalette: colorPalette, globalFilter: globalFilter }) }));
3790
+ return (jsx(Box, { textOverflow: "ellipsis", whiteSpace: "nowrap", wordBreak: "break-all", overflow: "auto", display: "flex", alignItems: "center", justifyContent: alignEnd ? 'flex-end' : undefined, height: "100%", textAlign: alignEnd ? 'right' : undefined, children: jsx(RenderValue, { text: displayValue, href: href, onClick: onClick, isCopyable: isCopyable, isBadge: isBadge, badgeColor: badgeColor, colorPalette: colorPalette, globalFilter: globalFilter, alignEnd: alignEnd }) }));
3553
3791
  };
3554
3792
 
3555
3793
  const Tag = React.forwardRef(function Tag(props, ref) {
@@ -3579,7 +3817,7 @@ const ErrorAlert = ({ showMessage = true }) => {
3579
3817
  const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: defaultPagination = {
3580
3818
  pageIndex: 0, //initial page index
3581
3819
  pageSize: 10, //default page size
3582
- }, 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', } = {
3583
3821
  sorting: [],
3584
3822
  pagination: {
3585
3823
  pageIndex: 0, //initial page index
@@ -3589,9 +3827,9 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3589
3827
  columnFilters: [],
3590
3828
  columnOrder: [],
3591
3829
  columnVisibility: {},
3592
- globalFilter: "",
3593
- density: "sm",
3594
- }, keyPrefix = "", } = {
3830
+ globalFilter: '',
3831
+ density: 'sm',
3832
+ }, } = {
3595
3833
  default: {
3596
3834
  sorting: [],
3597
3835
  pagination: {
@@ -3602,8 +3840,8 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3602
3840
  columnFilters: [],
3603
3841
  columnOrder: [],
3604
3842
  columnVisibility: {},
3605
- globalFilter: "",
3606
- density: "sm",
3843
+ globalFilter: '',
3844
+ density: 'sm',
3607
3845
  },
3608
3846
  }) => {
3609
3847
  const [sorting, setSorting] = useState(defaultSorting);
@@ -3614,7 +3852,6 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3614
3852
  const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter);
3615
3853
  const [density, setDensity] = useState(defaultDensity);
3616
3854
  const [columnVisibility, setColumnVisibility] = useState(defaultColumnVisibility);
3617
- const translate = useTranslation("", { keyPrefix });
3618
3855
  return {
3619
3856
  sorting,
3620
3857
  setSorting,
@@ -3632,12 +3869,11 @@ const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: def
3632
3869
  setDensity,
3633
3870
  columnVisibility,
3634
3871
  setColumnVisibility,
3635
- translate,
3636
3872
  };
3637
3873
  };
3638
3874
 
3639
3875
  const useDataTableServer = (props) => {
3640
- const { url, default: defaultProps, keyPrefix, placeholderData, queryFn: customQueryFn, } = props;
3876
+ const { url, default: defaultProps, placeholderData, queryFn: customQueryFn, } = props;
3641
3877
  const { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, } = defaultProps || {};
3642
3878
  const [sorting, setSorting] = useState(defaultSorting || []);
3643
3879
  const [columnFilters, setColumnFilters] = useState(defaultColumnFilters || []); // can set initial column filter state here
@@ -3647,8 +3883,8 @@ const useDataTableServer = (props) => {
3647
3883
  });
3648
3884
  const [rowSelection, setRowSelection] = useState(defaultRowSelection || {});
3649
3885
  const [columnOrder, setColumnOrder] = useState(defaultColumnOrder || []);
3650
- const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter || "");
3651
- const [density, setDensity] = useState(defaultDensity || "sm");
3886
+ const [globalFilter, setGlobalFilter] = useState(defaultGlobalFilter || '');
3887
+ const [density, setDensity] = useState(defaultDensity || 'sm');
3652
3888
  const [columnVisibility, setColumnVisibility] = useState(defaultColumnVisibility || {});
3653
3889
  const { pageSize, pageIndex } = pagination;
3654
3890
  const params = {
@@ -3660,7 +3896,7 @@ const useDataTableServer = (props) => {
3660
3896
  };
3661
3897
  const defaultQueryFn = async () => {
3662
3898
  if (!url) {
3663
- throw new Error("url is required");
3899
+ throw new Error('url is required');
3664
3900
  }
3665
3901
  const response = await axios.get(url, {
3666
3902
  params,
@@ -3674,7 +3910,6 @@ const useDataTableServer = (props) => {
3674
3910
  : defaultQueryFn,
3675
3911
  placeholderData,
3676
3912
  });
3677
- const translate = useTranslation("", { keyPrefix });
3678
3913
  return {
3679
3914
  sorting,
3680
3915
  setSorting,
@@ -3693,7 +3928,6 @@ const useDataTableServer = (props) => {
3693
3928
  columnVisibility,
3694
3929
  setColumnVisibility,
3695
3930
  query,
3696
- translate,
3697
3931
  };
3698
3932
  };
3699
3933
 
@@ -3712,11 +3946,8 @@ const snakeToLabel = (str) => {
3712
3946
  .join(" "); // Join with space
3713
3947
  };
3714
3948
 
3715
- const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3949
+ const RecordDisplay = ({ object, boxProps, prefix = '', }) => {
3716
3950
  const getColumn = ({ field }) => {
3717
- if (translate !== undefined) {
3718
- return translate.t(`${prefix}${field}`);
3719
- }
3720
3951
  return snakeToLabel(field);
3721
3952
  };
3722
3953
  if (object === null) {
@@ -3724,7 +3955,7 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
3724
3955
  }
3725
3956
  return (jsx(Grid, { rowGap: 1, padding: 1, overflow: 'auto', ...boxProps, children: Object.entries(object).map(([field, value], index) => {
3726
3957
  const uniqueKey = `${prefix}${field}-${index}`;
3727
- 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));
3728
3959
  }) }));
3729
3960
  };
3730
3961
 
@@ -3738,15 +3969,12 @@ const widthSanityCheck = (widthList, ignoreList, properties) => {
3738
3969
  throw new Error(`The width list is too long given from the number of remaining properties after ignore some.`);
3739
3970
  }
3740
3971
  };
3741
- const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, translate, }) => {
3972
+ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {}, defaultWidth = 400, }) => {
3742
3973
  const { properties } = schema;
3743
- idListSanityCheck("ignore", ignore, properties);
3974
+ idListSanityCheck('ignore', ignore, properties);
3744
3975
  widthSanityCheck(width, ignore, properties);
3745
- idListSanityCheck("meta", Object.keys(meta), properties);
3976
+ idListSanityCheck('meta', Object.keys(meta), properties);
3746
3977
  const getColumn = ({ column }) => {
3747
- if (translate !== undefined) {
3748
- return translate.t(`${column}`);
3749
- }
3750
3978
  return snakeToLabel(column);
3751
3979
  };
3752
3980
  const keys = Object.keys(properties);
@@ -3755,15 +3983,15 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3755
3983
  return !ignore.some((shouldIgnoreKey) => key === shouldIgnoreKey);
3756
3984
  });
3757
3985
  const columnHelper = createColumnHelper();
3758
- // @ts-expect-error find type for unknown
3759
3986
  const columns = [
3760
3987
  ...ignored.map((column, index) => {
3988
+ // @ts-expect-error column accessor type issue with generic TData
3761
3989
  return columnHelper.accessor(column, {
3762
3990
  cell: (props) => {
3763
3991
  // @ts-expect-error find type for unknown
3764
3992
  const value = props.row.original[column];
3765
- if (typeof value === "object") {
3766
- 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 }) }));
3767
3995
  }
3768
3996
  return jsx(TextCell, { children: value });
3769
3997
  },
@@ -3795,6 +4023,11 @@ const SchemaFormContext = createContext({
3795
4023
  include: [],
3796
4024
  onSubmit: async () => { },
3797
4025
  rowNumber: 0,
4026
+ /** Default translate fallback - returns key as-is */
4027
+ translate: {
4028
+ t: (key) => key,
4029
+ ready: true,
4030
+ },
3798
4031
  requestOptions: {},
3799
4032
  timezone: 'Asia/Hong_Kong',
3800
4033
  displayConfig: {
@@ -4027,7 +4260,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4027
4260
  showSubmitButton: true,
4028
4261
  showResetButton: true,
4029
4262
  showTitle: true,
4030
- }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, insideDialog = false, }) => {
4263
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog = false, }) => {
4031
4264
  const [isSuccess, setIsSuccess] = useState(false);
4032
4265
  const [isError, setIsError] = useState(false);
4033
4266
  const [isSubmiting, setIsSubmiting] = useState(false);
@@ -4118,6 +4351,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
4118
4351
  enumPickerLabels,
4119
4352
  filePickerLabels,
4120
4353
  formButtonLabels,
4354
+ timePickerLabels,
4121
4355
  ajvResolver: ajvResolver(schema),
4122
4356
  insideDialog,
4123
4357
  }, children: jsx(FormProvider, { ...form, children: children }) }));
@@ -4128,31 +4362,33 @@ function removeIndex(str) {
4128
4362
  }
4129
4363
 
4130
4364
  /**
4131
- * Custom hook to simplify i18n translation for form fields.
4365
+ * Custom hook for form field labels and fallback text.
4132
4366
  * Automatically handles colLabel construction and removeIndex logic.
4367
+ * Uses schema.title when available, otherwise falls back to translate function.
4133
4368
  *
4134
4369
  * @param column - The column name
4135
4370
  * @param prefix - The prefix for the field (usually empty string or parent path)
4136
- * @returns Object with translation helper functions
4371
+ * @param schema - Optional schema object with title property
4372
+ * @returns Object with label helper functions
4137
4373
  *
4138
4374
  * @example
4139
4375
  * ```tsx
4140
- * const formI18n = useFormI18n(column, prefix);
4376
+ * const formI18n = useFormI18n(column, prefix, schema);
4141
4377
  *
4142
- * // Get field label
4378
+ * // Get field label (prefers schema.title)
4143
4379
  * <Field label={formI18n.label()} />
4144
4380
  *
4145
- * // Get error message
4381
+ * // Get required error message
4146
4382
  * <Text>{formI18n.required()}</Text>
4147
4383
  *
4148
- * // Get custom translation key
4384
+ * // Get custom text
4149
4385
  * <Text>{formI18n.t('add_more')}</Text>
4150
4386
  *
4151
4387
  * // Access the raw colLabel
4152
4388
  * const colLabel = formI18n.colLabel;
4153
4389
  * ```
4154
4390
  */
4155
- const useFormI18n$1 = (column, prefix = '', schema) => {
4391
+ const useFormI18n = (column, prefix = '', schema) => {
4156
4392
  const { translate } = useSchemaContext();
4157
4393
  const colLabel = `${prefix}${column}`;
4158
4394
  return {
@@ -4161,7 +4397,7 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4161
4397
  */
4162
4398
  colLabel,
4163
4399
  /**
4164
- * 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
4165
4401
  * Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
4166
4402
  */
4167
4403
  label: (options) => {
@@ -4171,18 +4407,18 @@ const useFormI18n$1 = (column, prefix = '', schema) => {
4171
4407
  return translate.t(removeIndex(`${colLabel}.field_label`), options);
4172
4408
  },
4173
4409
  /**
4174
- * Get the required error message translation
4410
+ * Get the required error message
4175
4411
  * Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
4176
4412
  */
4177
4413
  required: (options) => {
4178
4414
  return translate.t(removeIndex(`${colLabel}.field_required`), options);
4179
4415
  },
4180
4416
  /**
4181
- * Get a translation for any custom key relative to the field
4417
+ * Get text for any custom key relative to the field
4182
4418
  * Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
4183
4419
  *
4184
- * @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
4185
- * @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)
4186
4422
  */
4187
4423
  t: (key, options) => {
4188
4424
  return translate.t(removeIndex(`${colLabel}.${key}`), options);
@@ -4200,8 +4436,9 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4200
4436
  const { type } = items;
4201
4437
  const colLabel = `${prefix}${column}`;
4202
4438
  const isRequired = required?.some((columnId) => columnId === column);
4203
- const formI18n = useFormI18n$1(column, prefix, schema);
4439
+ const formI18n = useFormI18n(column, prefix, schema);
4204
4440
  const { formState: { errors }, setValue, watch, } = useFormContext();
4441
+ const { formButtonLabels } = useSchemaContext();
4205
4442
  const fields = (watch(colLabel) ?? []);
4206
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: {
4207
4444
  base: 'colorPalette.200',
@@ -4227,7 +4464,7 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
4227
4464
  return;
4228
4465
  }
4229
4466
  setValue(colLabel, [...fields, {}]);
4230
- }, 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() }))] }));
4231
4468
  };
4232
4469
 
4233
4470
  const Field = React.forwardRef(function Field(props, ref) {
@@ -4241,7 +4478,7 @@ const BooleanPicker = ({ schema, column, prefix }) => {
4241
4478
  const isRequired = required?.some((columnId) => columnId === column);
4242
4479
  const colLabel = `${prefix}${column}`;
4243
4480
  const value = watch(colLabel);
4244
- const formI18n = useFormI18n$1(column, prefix, schema);
4481
+ const formI18n = useFormI18n(column, prefix, schema);
4245
4482
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4246
4483
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
4247
4484
  setValue(colLabel, !value);
@@ -4262,50 +4499,50 @@ const CustomInput = ({ column, schema, prefix }) => {
4262
4499
 
4263
4500
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
4264
4501
  const { labels } = useContext(DatePickerContext);
4265
- const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel } = labels;
4502
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
4266
4503
  if (calendars.length) {
4267
- 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({
4268
4505
  calendars,
4269
4506
  offset: 12,
4270
- }), 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({
4271
4508
  calendars,
4272
4509
  offset: 12,
4273
- }), 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) => {
4274
4511
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
4275
- 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}`));
4276
4513
  }), calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
4277
4514
  const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
4278
4515
  if (!dateObj) {
4279
4516
  return jsx(Grid, {}, key);
4280
4517
  }
4281
- const { date, selected, selectable, today } = dateObj;
4518
+ const { date, selected, selectable, today, isCurrentMonth, } = dateObj;
4282
4519
  const getDateColor = ({ today, selected, selectable, }) => {
4283
4520
  if (!selectable) {
4284
- return "gray";
4521
+ return 'gray';
4285
4522
  }
4286
4523
  if (selected) {
4287
- return "blue";
4524
+ return 'blue';
4288
4525
  }
4289
4526
  if (today) {
4290
- return "green";
4527
+ return 'green';
4291
4528
  }
4292
- return "";
4529
+ return '';
4293
4530
  };
4294
4531
  const getVariant = ({ today, selected, selectable, }) => {
4295
4532
  if (!selectable) {
4296
- return "surface";
4533
+ return 'surface';
4297
4534
  }
4298
4535
  if (selected) {
4299
- return "solid";
4536
+ return 'solid';
4300
4537
  }
4301
4538
  if (today) {
4302
- return "surface";
4539
+ return 'surface';
4303
4540
  }
4304
- return "ghost";
4541
+ return 'ghost';
4305
4542
  };
4306
4543
  const color = getDateColor({ today, selected, selectable });
4307
4544
  const variant = getVariant({ today, selected, selectable });
4308
- 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));
4309
4546
  }))] })] }, `${calendar.month}${calendar.year}`))) })] }));
4310
4547
  }
4311
4548
  return null;
@@ -4313,50 +4550,55 @@ const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firs
4313
4550
  const DatePickerContext = createContext({
4314
4551
  labels: {
4315
4552
  monthNamesShort: [
4316
- "Jan",
4317
- "Feb",
4318
- "Mar",
4319
- "Apr",
4320
- "May",
4321
- "Jun",
4322
- "Jul",
4323
- "Aug",
4324
- "Sep",
4325
- "Oct",
4326
- "Nov",
4327
- "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',
4328
4565
  ],
4329
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4330
- backButtonLabel: "Back",
4331
- forwardButtonLabel: "Next",
4566
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4567
+ backButtonLabel: 'Back',
4568
+ forwardButtonLabel: 'Next',
4332
4569
  },
4333
4570
  });
4334
- let DatePicker$1 = class DatePicker extends React__default.Component {
4335
- render() {
4336
- const { labels = {
4337
- monthNamesShort: [
4338
- "Jan",
4339
- "Feb",
4340
- "Mar",
4341
- "Apr",
4342
- "May",
4343
- "Jun",
4344
- "Jul",
4345
- "Aug",
4346
- "Sep",
4347
- "Oct",
4348
- "Nov",
4349
- "Dec",
4350
- ],
4351
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
4352
- backButtonLabel: "Back",
4353
- forwardButtonLabel: "Next",
4354
- }, } = this.props;
4355
- 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:
4356
- // @ts-expect-error - Dayzed types need to be fixed
4357
- (dayzedData) => (jsx(Calendar, { ...dayzedData,
4358
- firstDayOfWeek: this.props.firstDayOfWeek })) }) }));
4359
- }
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 })) }));
4360
4602
  };
4361
4603
 
4362
4604
  dayjs.extend(utc);
@@ -4364,7 +4606,7 @@ dayjs.extend(timezone);
4364
4606
  const DatePicker = ({ column, schema, prefix }) => {
4365
4607
  const { watch, formState: { errors }, setValue, } = useFormContext();
4366
4608
  const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
4367
- const formI18n = useFormI18n$1(column, prefix, schema);
4609
+ const formI18n = useFormI18n(column, prefix, schema);
4368
4610
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4369
4611
  const isRequired = required?.some((columnId) => columnId === column);
4370
4612
  const colLabel = formI18n.colLabel;
@@ -4398,74 +4640,30 @@ const DatePicker = ({ column, schema, prefix }) => {
4398
4640
  }, [selectedDate, dateFormat, colLabel, setValue]);
4399
4641
  const datePickerLabels = {
4400
4642
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4401
- formI18n.translate.t(`common.month_1`, {
4402
- defaultValue: 'January',
4403
- }),
4404
- formI18n.translate.t(`common.month_2`, {
4405
- defaultValue: 'February',
4406
- }),
4407
- formI18n.translate.t(`common.month_3`, {
4408
- defaultValue: 'March',
4409
- }),
4410
- formI18n.translate.t(`common.month_4`, {
4411
- defaultValue: 'April',
4412
- }),
4413
- formI18n.translate.t(`common.month_5`, {
4414
- defaultValue: 'May',
4415
- }),
4416
- formI18n.translate.t(`common.month_6`, {
4417
- defaultValue: 'June',
4418
- }),
4419
- formI18n.translate.t(`common.month_7`, {
4420
- defaultValue: 'July',
4421
- }),
4422
- formI18n.translate.t(`common.month_8`, {
4423
- defaultValue: 'August',
4424
- }),
4425
- formI18n.translate.t(`common.month_9`, {
4426
- defaultValue: 'September',
4427
- }),
4428
- formI18n.translate.t(`common.month_10`, {
4429
- defaultValue: 'October',
4430
- }),
4431
- formI18n.translate.t(`common.month_11`, {
4432
- defaultValue: 'November',
4433
- }),
4434
- formI18n.translate.t(`common.month_12`, {
4435
- defaultValue: 'December',
4436
- }),
4643
+ 'January',
4644
+ 'February',
4645
+ 'March',
4646
+ 'April',
4647
+ 'May',
4648
+ 'June',
4649
+ 'July',
4650
+ 'August',
4651
+ 'September',
4652
+ 'October',
4653
+ 'November',
4654
+ 'December',
4437
4655
  ],
4438
4656
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4439
- formI18n.translate.t(`common.weekday_1`, {
4440
- defaultValue: 'Sun',
4441
- }),
4442
- formI18n.translate.t(`common.weekday_2`, {
4443
- defaultValue: 'Mon',
4444
- }),
4445
- formI18n.translate.t(`common.weekday_3`, {
4446
- defaultValue: 'Tue',
4447
- }),
4448
- formI18n.translate.t(`common.weekday_4`, {
4449
- defaultValue: 'Wed',
4450
- }),
4451
- formI18n.translate.t(`common.weekday_5`, {
4452
- defaultValue: 'Thu',
4453
- }),
4454
- formI18n.translate.t(`common.weekday_6`, {
4455
- defaultValue: 'Fri',
4456
- }),
4457
- formI18n.translate.t(`common.weekday_7`, {
4458
- defaultValue: 'Sat',
4459
- }),
4657
+ 'Sun',
4658
+ 'Mon',
4659
+ 'Tue',
4660
+ 'Wed',
4661
+ 'Thu',
4662
+ 'Fri',
4663
+ 'Sat',
4460
4664
  ],
4461
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4462
- formI18n.translate.t(`common.back_button`, {
4463
- defaultValue: 'Back',
4464
- }),
4465
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4466
- formI18n.translate.t(`common.forward_button`, {
4467
- defaultValue: 'Forward',
4468
- }),
4665
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
4666
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
4469
4667
  };
4470
4668
  const datePickerContent = (jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4471
4669
  setValue(colLabel, dayjs(date).format(dateFormat));
@@ -4482,7 +4680,7 @@ dayjs.extend(timezone);
4482
4680
  const DateRangePicker = ({ column, schema, prefix, }) => {
4483
4681
  const { watch, formState: { errors }, setValue, } = useFormContext();
4484
4682
  const { timezone, insideDialog } = useSchemaContext();
4485
- const formI18n = useFormI18n$1(column, prefix);
4683
+ const formI18n = useFormI18n(column, prefix);
4486
4684
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4487
4685
  const isRequired = required?.some((columnId) => columnId === column);
4488
4686
  const colLabel = formI18n.colLabel;
@@ -4580,7 +4778,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4580
4778
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
4581
4779
  const { watch, formState: { errors }, setValue, } = useFormContext();
4582
4780
  const { enumPickerLabels, insideDialog } = useSchemaContext();
4583
- const formI18n = useFormI18n$1(column, prefix, schema);
4781
+ const formI18n = useFormI18n(column, prefix, schema);
4584
4782
  const { required, variant } = schema;
4585
4783
  const isRequired = required?.some((columnId) => columnId === column);
4586
4784
  const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
@@ -5127,7 +5325,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
5127
5325
  }) })) }))] }));
5128
5326
  };
5129
5327
 
5130
- 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, }) {
5131
5329
  const [selectedFile, setSelectedFile] = useState(undefined);
5132
5330
  const [activeTab, setActiveTab] = useState('browse');
5133
5331
  const [uploadingFiles, setUploadingFiles] = useState(new Set());
@@ -5196,15 +5394,8 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5196
5394
  const showTabs = enableUpload && !!onUploadFile && !!onFetchFiles;
5197
5395
  if (!onFetchFiles && !onUploadFile)
5198
5396
  return null;
5199
- 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 ??
5200
- translate(removeIndex(`${colLabel}.browse_tab`)) ??
5201
- 'Browse Library' }), jsx(Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
5202
- translate(removeIndex(`${colLabel}.upload_tab`)) ??
5203
- '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 ??
5204
- translate(removeIndex(`${colLabel}.fileDropzone`)) ??
5205
- '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 ??
5206
- translate(removeIndex(`${colLabel}.uploading`)) ??
5207
- '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: {
5208
5399
  base: 'colorPalette.50',
5209
5400
  _dark: 'colorPalette.900/20',
5210
5401
  }, border: "1px solid", borderColor: {
@@ -5213,18 +5404,12 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
5213
5404
  }, colorPalette: "red", borderRadius: "md", p: 3, children: jsxs(Text, { fontSize: "sm", color: {
5214
5405
  base: 'colorPalette.600',
5215
5406
  _dark: 'colorPalette.300',
5216
- }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
5217
- translate(removeIndex(`${colLabel}.upload_failed`)) ??
5218
- '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 ??
5219
- translate(removeIndex(`${colLabel}.cancel`)) ??
5220
- 'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ??
5221
- translate(removeIndex(`${colLabel}.select`)) ??
5222
- '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' })] }) })] }) }));
5223
5408
  }
5224
5409
  const FilePicker = ({ column, schema, prefix }) => {
5225
5410
  const { setValue, formState: { errors }, watch, } = useFormContext();
5226
5411
  const { filePickerLabels } = useSchemaContext();
5227
- const formI18n = useFormI18n$1(column, prefix);
5412
+ const formI18n = useFormI18n(column, prefix);
5228
5413
  const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
5229
5414
  const isRequired = required?.some((columnId) => columnId === column);
5230
5415
  const isSingleSelect = type === 'string';
@@ -5300,7 +5485,7 @@ const FilePicker = ({ column, schema, prefix }) => {
5300
5485
  const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5301
5486
  const { setValue, formState: { errors }, watch, } = useFormContext();
5302
5487
  const { filePickerLabels } = useSchemaContext();
5303
- const formI18n = useFormI18n$1(column, prefix);
5488
+ const formI18n = useFormI18n(column, prefix);
5304
5489
  const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
5305
5490
  const isRequired = required?.some((columnId) => columnId === column);
5306
5491
  const isSingleSelect = type === 'string';
@@ -5396,8 +5581,8 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
5396
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 ??
5397
5582
  formI18n.t('browse_library') ??
5398
5583
  'Browse from Library' }) }), jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
5399
- formI18n.t('dialog_title') ??
5400
- '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) => {
5401
5586
  const file = fileMap.get(fileId);
5402
5587
  const isImage = file
5403
5588
  ? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
@@ -5446,17 +5631,16 @@ const defaultRenderDisplay = (item) => {
5446
5631
  return JSON.stringify(item);
5447
5632
  };
5448
5633
 
5449
- const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5634
+ const useIdPickerData = ({ column, schema, prefix, isMultiple, }) => {
5450
5635
  const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
5451
5636
  const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
5452
- const formI18n = useFormI18n$1(column, prefix, schema);
5453
- const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
5454
- const isRequired = required?.some((columnId) => columnId === column);
5637
+ const { renderDisplay, foreign_key } = schema;
5455
5638
  const { table, column: column_ref, customQueryFn, } = foreign_key;
5456
5639
  const [searchText, setSearchText] = useState('');
5457
5640
  const [debouncedSearchText, setDebouncedSearchText] = useState('');
5458
5641
  const [limit] = useState(50); // Increased limit for combobox
5459
- const colLabel = formI18n.colLabel;
5642
+ // Get colLabel from schema context (we'll compute it here)
5643
+ const colLabel = `${prefix}${column}`;
5460
5644
  const watchedValue = watch(colLabel);
5461
5645
  const watchId = !isMultiple ? watchedValue : undefined;
5462
5646
  const watchIds = isMultiple
@@ -5655,20 +5839,6 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5655
5839
  itemToValue: (item) => item.value,
5656
5840
  filter: contains,
5657
5841
  });
5658
- // Handle input value change (search)
5659
- const handleInputValueChange = (details) => {
5660
- setSearchText(details.inputValue);
5661
- // Filter will be applied after data is fetched
5662
- };
5663
- // Handle value change
5664
- const handleValueChange = (details) => {
5665
- if (isMultiple) {
5666
- setValue(colLabel, details.value);
5667
- }
5668
- else {
5669
- setValue(colLabel, details.value[0] || '');
5670
- }
5671
- };
5672
5842
  // Track previous comboboxItems to avoid unnecessary updates
5673
5843
  const prevComboboxItemsRef = useRef('');
5674
5844
  const prevSearchTextRef = useRef('');
@@ -5698,8 +5868,106 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5698
5868
  // comboboxItems and searchText are the only dependencies we care about
5699
5869
  // eslint-disable-next-line react-hooks/exhaustive-deps
5700
5870
  }, [comboboxItems, searchText]);
5871
+ return {
5872
+ colLabel,
5873
+ currentValue,
5874
+ searchText,
5875
+ setSearchText,
5876
+ debouncedSearchText,
5877
+ isLoading,
5878
+ isFetching,
5879
+ isPending,
5880
+ isError,
5881
+ isSearching,
5882
+ isLoadingInitialValues,
5883
+ isFetchingInitialValues,
5884
+ missingIds,
5885
+ comboboxItems,
5886
+ collection,
5887
+ filter,
5888
+ set,
5889
+ idMap,
5890
+ idPickerLabels,
5891
+ insideDialog: insideDialog ?? false,
5892
+ renderDisplay,
5893
+ column_ref,
5894
+ errors,
5895
+ setValue,
5896
+ };
5897
+ };
5898
+
5899
+ const IdPickerSingle = ({ column, schema, prefix, }) => {
5900
+ const formI18n = useFormI18n(column, prefix, schema);
5901
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5902
+ const isRequired = required?.some((columnId) => columnId === column);
5903
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5904
+ column,
5905
+ schema,
5906
+ prefix,
5907
+ isMultiple: false,
5908
+ });
5909
+ const handleInputValueChange = (details) => {
5910
+ setSearchText(details.inputValue);
5911
+ };
5912
+ const handleValueChange = (details) => {
5913
+ setValue(colLabel, details.value[0] || '');
5914
+ };
5915
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5916
+ return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5917
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsx(Flex, { mb: 2, children: (() => {
5918
+ const id = currentValue[0];
5919
+ const item = idMap[id];
5920
+ // Show loading skeleton while fetching initial values
5921
+ if (item === undefined &&
5922
+ (isLoadingInitialValues || isFetchingInitialValues) &&
5923
+ missingIds.includes(id)) {
5924
+ return jsx(Skeleton, { height: "24px", width: "100px", borderRadius: "md" });
5925
+ }
5926
+ // Only show "not found" if we're not loading and item is still missing
5927
+ if (item === undefined) {
5928
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }));
5929
+ }
5930
+ return jsx(Text, { fontSize: "sm", children: renderDisplayFunction(item) });
5931
+ })() })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: false, closeOnSelect: true, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5932
+ ? { strategy: 'fixed', hideWhenDetached: true }
5933
+ : undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
5934
+ setValue(colLabel, '');
5935
+ } })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5936
+ // Show skeleton items to prevent UI shift
5937
+ jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5938
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5939
+ : idPickerLabels?.initialResults ??
5940
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5941
+ ? renderDisplayFunction(item.raw)
5942
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5943
+ // Show skeleton items to prevent UI shift
5944
+ jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5945
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5946
+ : idPickerLabels?.initialResults ??
5947
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5948
+ ? renderDisplayFunction(item.raw)
5949
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5950
+ };
5951
+
5952
+ const IdPickerMultiple = ({ column, schema, prefix, }) => {
5953
+ const formI18n = useFormI18n(column, prefix, schema);
5954
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, } = schema;
5955
+ const isRequired = required?.some((columnId) => columnId === column);
5956
+ const { colLabel, currentValue, searchText, setSearchText, isLoading, isFetching, isPending, isError, isSearching, isLoadingInitialValues, isFetchingInitialValues, missingIds, collection, idMap, idPickerLabels, insideDialog, renderDisplay: renderDisplayFn, errors, setValue, } = useIdPickerData({
5957
+ column,
5958
+ schema,
5959
+ prefix,
5960
+ isMultiple: true,
5961
+ });
5962
+ const handleInputValueChange = (details) => {
5963
+ setSearchText(details.inputValue);
5964
+ };
5965
+ const handleValueChange = (details) => {
5966
+ setValue(colLabel, details.value);
5967
+ };
5968
+ const renderDisplayFunction = renderDisplayFn || renderDisplay || defaultRenderDisplay;
5701
5969
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5702
- 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) => {
5970
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
5703
5971
  const item = idMap[id];
5704
5972
  // Show loading skeleton while fetching initial values
5705
5973
  if (item === undefined &&
@@ -5709,34 +5977,28 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5709
5977
  }
5710
5978
  // Only show "not found" if we're not loading and item is still missing
5711
5979
  if (item === undefined) {
5712
- return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
5980
+ return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? 'Undefined' }, id));
5713
5981
  }
5714
5982
  return (jsx(Tag, { closable: true, onClick: () => {
5715
5983
  const newValue = currentValue.filter((itemId) => itemId !== id);
5716
5984
  setValue(colLabel, newValue);
5717
- }, children: renderDisplay
5718
- ? renderDisplay(item)
5719
- : defaultRenderDisplay(item) }, id));
5720
- }) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5985
+ }, children: renderDisplayFunction(item) }, id));
5986
+ }) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: true, closeOnSelect: false, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
5721
5987
  ? { strategy: 'fixed', hideWhenDetached: true }
5722
- : 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: () => {
5723
- setValue(colLabel, '');
5724
- } })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
5988
+ : undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? 'Type to search' }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), jsx(Combobox.Trigger, {})] })] }), insideDialog ? (jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5725
5989
  // Show skeleton items to prevent UI shift
5726
5990
  jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5727
- ? idPickerLabels?.emptySearchResult ??
5728
- formI18n.t('empty_search_result')
5991
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5729
5992
  : idPickerLabels?.initialResults ??
5730
- formI18n.t('initial_results') })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplay === true
5731
- ? renderDisplay(item.raw)
5732
- : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: formI18n.t('loading_failed') })) : isFetching || isLoading || isPending || isSearching ? (
5993
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
5994
+ ? renderDisplayFunction(item.raw)
5995
+ : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) })) : (jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsx(Combobox.Content, { children: isError ? (jsx(Text, { p: 2, color: "fg.error", fontSize: "sm", children: idPickerLabels?.emptySearchResult ?? 'Loading failed' })) : isFetching || isLoading || isPending || isSearching ? (
5733
5996
  // Show skeleton items to prevent UI shift
5734
5997
  jsx(Fragment, { children: Array.from({ length: 5 }).map((_, index) => (jsx(Flex, { p: 2, align: "center", gap: 2, children: jsx(Skeleton, { height: "20px", flex: "1" }) }, `skeleton-${index}`))) })) : collection.items.length === 0 ? (jsx(Combobox.Empty, { children: searchText
5735
- ? idPickerLabels?.emptySearchResult ??
5736
- formI18n.t('empty_search_result')
5998
+ ? idPickerLabels?.emptySearchResult ?? 'No results found'
5737
5999
  : idPickerLabels?.initialResults ??
5738
- formI18n.t('initial_results') })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplay === true
5739
- ? renderDisplay(item.raw)
6000
+ 'Start typing to search' })) : (jsx(Fragment, { children: collection.items.map((item, index) => (jsxs(Combobox.Item, { item: item, children: [jsx(Combobox.ItemText, { children: !!renderDisplayFunction === true
6001
+ ? renderDisplayFunction(item.raw)
5740
6002
  : item.label }), jsx(Combobox.ItemIndicator, {})] }, item.value ?? `item-${index}`))) })) }) }) }))] })] }));
5741
6003
  };
5742
6004
 
@@ -5810,7 +6072,7 @@ const NumberInputField = ({ schema, column, prefix, }) => {
5810
6072
  const colLabel = `${prefix}${column}`;
5811
6073
  const value = watch(`${colLabel}`);
5812
6074
  const fieldError = getFieldError(errors, colLabel);
5813
- const formI18n = useFormI18n$1(column, prefix, schema);
6075
+ const formI18n = useFormI18n(column, prefix, schema);
5814
6076
  return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
5815
6077
  ? fieldError.includes('required')
5816
6078
  ? formI18n.required()
@@ -5828,7 +6090,7 @@ const ObjectInput = ({ schema, column, prefix }) => {
5828
6090
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
5829
6091
  const colLabel = `${prefix}${column}`;
5830
6092
  const isRequired = required?.some((columnId) => columnId === column);
5831
- const formI18n = useFormI18n$1(column, prefix, schema);
6093
+ const formI18n = useFormI18n(column, prefix, schema);
5832
6094
  const { formState: { errors }, } = useFormContext();
5833
6095
  if (properties === undefined) {
5834
6096
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -5848,14 +6110,14 @@ const ObjectInput = ({ schema, column, prefix }) => {
5848
6110
 
5849
6111
  const RecordInput = ({ column, schema, prefix }) => {
5850
6112
  const { formState: { errors }, setValue, getValues, } = useFormContext();
5851
- const { translate } = useSchemaContext();
6113
+ const { formButtonLabels } = useSchemaContext();
5852
6114
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5853
6115
  const isRequired = required?.some((columnId) => columnId === column);
5854
6116
  const entries = Object.entries(getValues(column) ?? {});
5855
6117
  const [showNewEntries, setShowNewEntries] = useState(false);
5856
6118
  const [newKey, setNewKey] = useState();
5857
6119
  const [newValue, setNewValue] = useState();
5858
- const formI18n = useFormI18n$1(column, prefix, schema);
6120
+ const formI18n = useFormI18n(column, prefix, schema);
5859
6121
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`] ? formI18n.required() : undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
5860
6122
  return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
5861
6123
  const filtered = entries.filter(([target]) => {
@@ -5892,11 +6154,11 @@ const RecordInput = ({ column, schema, prefix }) => {
5892
6154
  setShowNewEntries(false);
5893
6155
  setNewKey(undefined);
5894
6156
  setNewValue(undefined);
5895
- }, children: translate.t(`${column}.save`) })] })] }) }), jsx(Button, { onClick: () => {
6157
+ }, children: formButtonLabels?.save ?? 'Save' })] })] }) }), jsx(Button, { onClick: () => {
5896
6158
  setShowNewEntries(true);
5897
6159
  setNewKey(undefined);
5898
6160
  setNewValue(undefined);
5899
- }, children: translate.t(`${column}.addNew`) })] }));
6161
+ }, children: formButtonLabels?.addNew ?? 'Add New' })] }));
5900
6162
  };
5901
6163
 
5902
6164
  const StringInputField = ({ column, schema, prefix, }) => {
@@ -5905,7 +6167,7 @@ const StringInputField = ({ column, schema, prefix, }) => {
5905
6167
  const isRequired = required?.some((columnId) => columnId === column);
5906
6168
  const colLabel = `${prefix}${column}`;
5907
6169
  const fieldError = getFieldError(errors, colLabel);
5908
- const formI18n = useFormI18n$1(column, prefix, schema);
6170
+ const formI18n = useFormI18n(column, prefix, schema);
5909
6171
  return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
5910
6172
  };
5911
6173
 
@@ -6097,7 +6359,7 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6097
6359
  const form = useFormContext();
6098
6360
  const { setValue, watch } = form;
6099
6361
  const fieldError = getFieldError(errors, colLabel);
6100
- const formI18n = useFormI18n$1(column, prefix, schema);
6362
+ const formI18n = useFormI18n(column, prefix, schema);
6101
6363
  const watchValue = watch(colLabel);
6102
6364
  return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
6103
6365
  ? fieldError.includes('required')
@@ -6108,18 +6370,13 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
6108
6370
 
6109
6371
  dayjs.extend(utc);
6110
6372
  dayjs.extend(timezone);
6111
- function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
6112
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6113
- meridiemLabel: _meridiemLabel = {
6114
- am: 'am',
6115
- pm: 'pm',
6116
- },
6117
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6118
- onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedDate, portalled = true, }) {
6119
- // Generate time options (every 15 minutes)
6373
+ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem, onChange = () => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6374
+ placeholder: 'hh:mm AM/PM',
6375
+ emptyMessage: 'No time found',
6376
+ }, }) => {
6377
+ // Generate time options (every 15 minutes in 12-hour format)
6120
6378
  const timeOptions = useMemo(() => {
6121
6379
  const options = [];
6122
- const meridiemOptions = ['am', 'pm'];
6123
6380
  // Get start time for comparison if provided
6124
6381
  let startDateTime = null;
6125
6382
  let shouldFilterByDate = false;
@@ -6134,14 +6391,16 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6134
6391
  selectedDateObj.format('YYYY-MM-DD');
6135
6392
  }
6136
6393
  }
6137
- for (const mer of meridiemOptions) {
6138
- for (let h = 1; h <= 12; h++) {
6139
- for (let m = 0; m < 60; m += 15) {
6140
- const hour24 = mer === 'am' ? (h === 12 ? 0 : h) : h === 12 ? 12 : h + 12;
6141
- // Format time directly without using dayjs with dummy dates
6142
- const formattedHour = h.toString().padStart(2, '0');
6143
- const formattedMinute = m.toString().padStart(2, '0');
6144
- const displayTime = `${formattedHour}:${formattedMinute} ${mer}`;
6394
+ // Generate 12-hour format options (1-12 for hours, AM/PM)
6395
+ for (let h = 1; h <= 12; h++) {
6396
+ for (let m = 0; m < 60; m += 15) {
6397
+ for (const mer of ['am', 'pm']) {
6398
+ // Convert 12-hour to 24-hour for comparison
6399
+ let hour24 = h;
6400
+ if (mer === 'am' && h === 12)
6401
+ hour24 = 0;
6402
+ else if (mer === 'pm' && h < 12)
6403
+ hour24 = h + 12;
6145
6404
  // Filter out times that would result in negative duration (only when dates are the same)
6146
6405
  if (startDateTime && selectedDate && shouldFilterByDate) {
6147
6406
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
@@ -6184,20 +6443,23 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6184
6443
  }
6185
6444
  }
6186
6445
  }
6446
+ const hourDisplay = h.toString();
6447
+ const minuteDisplay = m.toString().padStart(2, '0');
6448
+ const timeDisplay = `${hourDisplay}:${minuteDisplay} ${mer.toUpperCase()}`;
6187
6449
  options.push({
6188
- label: displayTime,
6189
- value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
6450
+ label: timeDisplay,
6451
+ value: `${h}:${m}:${mer}`,
6190
6452
  hour: h,
6191
6453
  minute: m,
6192
6454
  meridiem: mer,
6193
- searchText: displayTime, // Use base time without duration for searching
6455
+ searchText: timeDisplay, // Use base time without duration for searching
6194
6456
  durationText,
6195
6457
  });
6196
6458
  }
6197
6459
  }
6198
6460
  }
6199
6461
  return options;
6200
- }, [timezone, startTime, selectedDate]);
6462
+ }, [startTime, selectedDate, timezone]);
6201
6463
  const { contains } = useFilter({ sensitivity: 'base' });
6202
6464
  const { collection, filter } = useListCollection({
6203
6465
  initialItems: timeOptions,
@@ -6210,7 +6472,7 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6210
6472
  if (hour === null || minute === null || meridiem === null) {
6211
6473
  return '';
6212
6474
  }
6213
- return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
6475
+ return `${hour}:${minute}:${meridiem}`;
6214
6476
  }, [hour, minute, meridiem]);
6215
6477
  // Calculate duration difference
6216
6478
  const durationDiff = useMemo(() => {
@@ -6221,15 +6483,14 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6221
6483
  meridiem === null) {
6222
6484
  return null;
6223
6485
  }
6224
- const hour24 = meridiem === 'am'
6225
- ? hour === 12
6226
- ? 0
6227
- : hour
6228
- : hour === 12
6229
- ? 12
6230
- : hour + 12;
6231
6486
  const startDateObj = dayjs(startTime).tz(timezone);
6232
6487
  const selectedDateObj = dayjs(selectedDate).tz(timezone);
6488
+ // Convert 12-hour to 24-hour format
6489
+ let hour24 = hour;
6490
+ if (meridiem === 'am' && hour === 12)
6491
+ hour24 = 0;
6492
+ else if (meridiem === 'pm' && hour < 12)
6493
+ hour24 = hour + 12;
6233
6494
  const currentDateTime = selectedDateObj
6234
6495
  .hour(hour24)
6235
6496
  .minute(minute)
@@ -6294,83 +6555,54 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6294
6555
  if (!trimmedValue) {
6295
6556
  return;
6296
6557
  }
6297
- // Try to parse custom input using explicit regex patterns
6298
- const normalized = trimmedValue.toLowerCase().replace(/\s+/g, '');
6299
- // Pattern 1: 12-hour format with meridiem (e.g., "930pm", "1230am", "9:30pm", "12:30am")
6300
- // Matches: 1-2 digits hour, optional colon, 2 digits minute, am/pm
6301
- const pattern12HourWithMeridiem = /^(\d{1,2}):?(\d{2})(am|pm)$/;
6302
- const match12Hour = normalized.match(pattern12HourWithMeridiem);
6558
+ // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6559
+ const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6560
+ const match12Hour = trimmedValue.match(timePattern12Hour);
6303
6561
  if (match12Hour) {
6304
6562
  const parsedHour = parseInt(match12Hour[1], 10);
6305
6563
  const parsedMinute = parseInt(match12Hour[2], 10);
6306
- const parsedMeridiem = match12Hour[3];
6307
- // Validate hour (1-12)
6308
- if (parsedHour < 1 || parsedHour > 12) {
6309
- // Parse failed, select first result
6310
- selectFirstResult();
6311
- return;
6312
- }
6313
- // Validate minute (0-59)
6314
- if (parsedMinute < 0 || parsedMinute > 59) {
6315
- // Parse failed, select first result
6316
- selectFirstResult();
6564
+ const parsedMeridiem = match12Hour[3].toLowerCase();
6565
+ // Validate ranges
6566
+ if (parsedHour >= 1 &&
6567
+ parsedHour <= 12 &&
6568
+ parsedMinute >= 0 &&
6569
+ parsedMinute <= 59) {
6570
+ setHour(parsedHour);
6571
+ setMinute(parsedMinute);
6572
+ setMeridiem(parsedMeridiem);
6573
+ onChange({
6574
+ hour: parsedHour,
6575
+ minute: parsedMinute,
6576
+ meridiem: parsedMeridiem,
6577
+ });
6317
6578
  return;
6318
6579
  }
6319
- setHour(parsedHour);
6320
- setMinute(parsedMinute);
6321
- setMeridiem(parsedMeridiem);
6322
- onChange({
6323
- hour: parsedHour,
6324
- minute: parsedMinute,
6325
- meridiem: parsedMeridiem,
6326
- });
6327
- return;
6328
6580
  }
6329
- // Pattern 2: 24-hour format (e.g., "2130", "09:30", "21:30")
6330
- // Matches: 1-2 digits hour, optional colon, 2 digits minute
6331
- const pattern24Hour = /^(\d{1,2}):?(\d{2})$/;
6332
- const match24Hour = normalized.match(pattern24Hour);
6333
- if (match24Hour) {
6334
- let parsedHour = parseInt(match24Hour[1], 10);
6335
- const parsedMinute = parseInt(match24Hour[2], 10);
6336
- // Validate hour (0-23)
6337
- if (parsedHour < 0 || parsedHour > 23) {
6338
- // Parse failed, select first result
6339
- selectFirstResult();
6340
- return;
6341
- }
6342
- // Validate minute (0-59)
6343
- if (parsedMinute < 0 || parsedMinute > 59) {
6344
- // Parse failed, select first result
6345
- selectFirstResult();
6346
- return;
6347
- }
6348
- // Convert 24-hour to 12-hour format
6349
- let parsedMeridiem;
6350
- if (parsedHour === 0) {
6351
- parsedHour = 12;
6352
- parsedMeridiem = 'am';
6353
- }
6354
- else if (parsedHour === 12) {
6355
- parsedHour = 12;
6356
- parsedMeridiem = 'pm';
6357
- }
6358
- else if (parsedHour > 12) {
6359
- parsedHour = parsedHour - 12;
6360
- parsedMeridiem = 'pm';
6361
- }
6362
- else {
6363
- parsedMeridiem = 'am';
6581
+ // Try to parse formats like "130pm" or "130 pm" (without colon)
6582
+ const timePatternNoColon = /^(\d{1,4})\s*(am|pm|AM|PM)$/i;
6583
+ const matchNoColon = trimmedValue.match(timePatternNoColon);
6584
+ if (matchNoColon) {
6585
+ const numbersOnly = matchNoColon[1];
6586
+ const parsedMeridiem = matchNoColon[2].toLowerCase();
6587
+ if (numbersOnly.length >= 3) {
6588
+ const parsedHour = parseInt(numbersOnly.slice(0, -2), 10);
6589
+ const parsedMinute = parseInt(numbersOnly.slice(-2), 10);
6590
+ // Validate ranges
6591
+ if (parsedHour >= 1 &&
6592
+ parsedHour <= 12 &&
6593
+ parsedMinute >= 0 &&
6594
+ parsedMinute <= 59) {
6595
+ setHour(parsedHour);
6596
+ setMinute(parsedMinute);
6597
+ setMeridiem(parsedMeridiem);
6598
+ onChange({
6599
+ hour: parsedHour,
6600
+ minute: parsedMinute,
6601
+ meridiem: parsedMeridiem,
6602
+ });
6603
+ return;
6604
+ }
6364
6605
  }
6365
- setHour(parsedHour);
6366
- setMinute(parsedMinute);
6367
- setMeridiem(parsedMeridiem);
6368
- onChange({
6369
- hour: parsedHour,
6370
- minute: parsedMinute,
6371
- meridiem: parsedMeridiem,
6372
- });
6373
- return;
6374
6606
  }
6375
6607
  // Parse failed, select first result
6376
6608
  selectFirstResult();
@@ -6417,17 +6649,17 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
6417
6649
  e.currentTarget?.blur();
6418
6650
  }
6419
6651
  };
6420
- 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, {}) }) })] }) }));
6421
- }
6652
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: labels?.placeholder ?? 'hh:mm AM/PM', onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels?.emptyMessage ?? 'No time found' }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
6653
+ };
6422
6654
 
6423
6655
  dayjs.extend(timezone);
6424
6656
  const TimePicker = ({ column, schema, prefix }) => {
6425
6657
  const { watch, formState: { errors }, setValue, } = useFormContext();
6426
- const { timezone, insideDialog } = useSchemaContext();
6658
+ const { timezone, insideDialog, timePickerLabels } = useSchemaContext();
6427
6659
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
6428
6660
  const isRequired = required?.some((columnId) => columnId === column);
6429
6661
  const colLabel = `${prefix}${column}`;
6430
- const formI18n = useFormI18n$1(column, prefix, schema);
6662
+ const formI18n = useFormI18n(column, prefix, schema);
6431
6663
  const [open, setOpen] = useState(false);
6432
6664
  const value = watch(colLabel);
6433
6665
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
@@ -6485,13 +6717,7 @@ const TimePicker = ({ column, schema, prefix }) => {
6485
6717
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6486
6718
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6487
6719
  setOpen(true);
6488
- }, 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, meridiemLabel: {
6489
- am: translate.t(`common.am`, { defaultValue: 'AM' }),
6490
- pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
6491
- } }) }) }) })) : (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, meridiemLabel: {
6492
- am: translate.t(`common.am`, { defaultValue: 'AM' }),
6493
- pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
6494
- } }) }) }) }) }))] }) }));
6720
+ }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) }) }))] }) }));
6495
6721
  };
6496
6722
 
6497
6723
  dayjs.extend(utc);
@@ -6625,7 +6851,10 @@ dayjs.extend(utc);
6625
6851
  dayjs.extend(timezone);
6626
6852
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6627
6853
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6628
- onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, }) {
6854
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', portalled = true, labels = {
6855
+ placeholder: 'HH:mm:ss',
6856
+ emptyMessage: 'No time found',
6857
+ }, }) {
6629
6858
  // Generate time options (every 15 minutes, seconds always 0)
6630
6859
  const timeOptions = useMemo(() => {
6631
6860
  const options = [];
@@ -6888,7 +7117,7 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
6888
7117
  e.currentTarget?.blur();
6889
7118
  }
6890
7119
  };
6891
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: "HH:mm:ss", onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
7120
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: labels.placeholder, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels.emptyMessage }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
6892
7121
  }
6893
7122
 
6894
7123
  dayjs.extend(utc);
@@ -6911,7 +7140,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
6911
7140
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6912
7141
  backButtonLabel: 'Back',
6913
7142
  forwardButtonLabel: 'Next',
6914
- }, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7143
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
6915
7144
  console.log('[DateTimePicker] Component initialized with props:', {
6916
7145
  value,
6917
7146
  format,
@@ -7357,7 +7586,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7357
7586
  const dateObj = dayjs.tz(selectedDate, timezone);
7358
7587
  return dateObj.isValid() ? dateObj.format('Z') : null;
7359
7588
  }, [selectedDate, timezone]);
7360
- return (jsxs(Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7589
+ return (jsxs(Flex, { direction: "column", gap: 4, children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7361
7590
  if (date) {
7362
7591
  handleDateChange(date);
7363
7592
  }
@@ -7365,15 +7594,15 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7365
7594
  setSelectedDate('');
7366
7595
  onChange?.(undefined);
7367
7596
  }
7368
- }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7597
+ }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7369
7598
  }
7370
7599
 
7371
7600
  dayjs.extend(utc);
7372
7601
  dayjs.extend(timezone);
7373
7602
  const DateTimePicker = ({ column, schema, prefix, }) => {
7374
7603
  const { watch, formState: { errors }, setValue, } = useFormContext();
7375
- const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
7376
- const formI18n = useFormI18n$1(column, prefix, schema);
7604
+ const { timezone, dateTimePickerLabels, timePickerLabels, insideDialog } = useSchemaContext();
7605
+ const formI18n = useFormI18n(column, prefix, schema);
7377
7606
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
7378
7607
  // with timezone
7379
7608
  dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
@@ -7386,74 +7615,30 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7386
7615
  : '';
7387
7616
  const dateTimePickerLabelsConfig = {
7388
7617
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
7389
- formI18n.translate.t(`common.month_1`, {
7390
- defaultValue: 'January',
7391
- }),
7392
- formI18n.translate.t(`common.month_2`, {
7393
- defaultValue: 'February',
7394
- }),
7395
- formI18n.translate.t(`common.month_3`, {
7396
- defaultValue: 'March',
7397
- }),
7398
- formI18n.translate.t(`common.month_4`, {
7399
- defaultValue: 'April',
7400
- }),
7401
- formI18n.translate.t(`common.month_5`, {
7402
- defaultValue: 'May',
7403
- }),
7404
- formI18n.translate.t(`common.month_6`, {
7405
- defaultValue: 'June',
7406
- }),
7407
- formI18n.translate.t(`common.month_7`, {
7408
- defaultValue: 'July',
7409
- }),
7410
- formI18n.translate.t(`common.month_8`, {
7411
- defaultValue: 'August',
7412
- }),
7413
- formI18n.translate.t(`common.month_9`, {
7414
- defaultValue: 'September',
7415
- }),
7416
- formI18n.translate.t(`common.month_10`, {
7417
- defaultValue: 'October',
7418
- }),
7419
- formI18n.translate.t(`common.month_11`, {
7420
- defaultValue: 'November',
7421
- }),
7422
- formI18n.translate.t(`common.month_12`, {
7423
- defaultValue: 'December',
7424
- }),
7618
+ 'January',
7619
+ 'February',
7620
+ 'March',
7621
+ 'April',
7622
+ 'May',
7623
+ 'June',
7624
+ 'July',
7625
+ 'August',
7626
+ 'September',
7627
+ 'October',
7628
+ 'November',
7629
+ 'December',
7425
7630
  ],
7426
7631
  weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
7427
- formI18n.translate.t(`common.weekday_1`, {
7428
- defaultValue: 'Sun',
7429
- }),
7430
- formI18n.translate.t(`common.weekday_2`, {
7431
- defaultValue: 'Mon',
7432
- }),
7433
- formI18n.translate.t(`common.weekday_3`, {
7434
- defaultValue: 'Tue',
7435
- }),
7436
- formI18n.translate.t(`common.weekday_4`, {
7437
- defaultValue: 'Wed',
7438
- }),
7439
- formI18n.translate.t(`common.weekday_5`, {
7440
- defaultValue: 'Thu',
7441
- }),
7442
- formI18n.translate.t(`common.weekday_6`, {
7443
- defaultValue: 'Fri',
7444
- }),
7445
- formI18n.translate.t(`common.weekday_7`, {
7446
- defaultValue: 'Sat',
7447
- }),
7632
+ 'Sun',
7633
+ 'Mon',
7634
+ 'Tue',
7635
+ 'Wed',
7636
+ 'Thu',
7637
+ 'Fri',
7638
+ 'Sat',
7448
7639
  ],
7449
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
7450
- formI18n.translate.t(`common.back_button`, {
7451
- defaultValue: 'Back',
7452
- }),
7453
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
7454
- formI18n.translate.t(`common.forward_button`, {
7455
- defaultValue: 'Forward',
7456
- }),
7640
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
7641
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
7457
7642
  };
7458
7643
  const dateTimePickerContent = (jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
7459
7644
  if (!date || date === null || date === undefined) {
@@ -7467,7 +7652,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7467
7652
  else {
7468
7653
  setValue(colLabel, undefined);
7469
7654
  }
7470
- }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
7655
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig, timePickerLabels: timePickerLabels }));
7471
7656
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7472
7657
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
7473
7658
  setOpen(true);
@@ -7486,7 +7671,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7486
7671
  }
7487
7672
  if (variant === 'id-picker') {
7488
7673
  idPickerSanityCheck(column, foreign_key);
7489
- return jsx(IdPicker, { schema: colSchema, prefix, column });
7674
+ return jsx(IdPickerSingle, { schema: colSchema, prefix, column });
7490
7675
  }
7491
7676
  if (format === 'date') {
7492
7677
  return jsx(DatePicker, { schema: colSchema, prefix, column });
@@ -7520,7 +7705,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
7520
7705
  if (type === 'array') {
7521
7706
  if (variant === 'id-picker') {
7522
7707
  idPickerSanityCheck(column, foreign_key);
7523
- return (jsx(IdPicker, { schema: colSchema, prefix, column, isMultiple: true }));
7708
+ return jsx(IdPickerMultiple, { schema: colSchema, prefix, column });
7524
7709
  }
7525
7710
  if (variant === 'tag-picker') {
7526
7711
  return jsx(TagPicker, { schema: colSchema, prefix, column });
@@ -7572,7 +7757,7 @@ const ArrayViewer = ({ schema, column, prefix }) => {
7572
7757
  const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
7573
7758
  const colLabel = `${prefix}${column}`;
7574
7759
  const isRequired = required?.some((columnId) => columnId === column);
7575
- const formI18n = useFormI18n$1(column, prefix, schema);
7760
+ const formI18n = useFormI18n(column, prefix, schema);
7576
7761
  const { watch, formState: { errors }, } = useFormContext();
7577
7762
  const values = watch(colLabel) ?? [];
7578
7763
  return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: '1/span12', children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: 'column', gap: 1, children: values.map((field, index) => (jsx(Flex, { flexFlow: 'column', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '2', borderRadius: 'md', borderWidth: 'thin', borderColor: {
@@ -7590,7 +7775,7 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
7590
7775
  const isRequired = required?.some((columnId) => columnId === column);
7591
7776
  const colLabel = `${prefix}${column}`;
7592
7777
  const value = watch(colLabel);
7593
- const formI18n = useFormI18n$1(column, prefix, schema);
7778
+ const formI18n = useFormI18n(column, prefix, schema);
7594
7779
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7595
7780
  gridRow, children: [jsx(Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
7596
7781
  };
@@ -7614,7 +7799,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7614
7799
  const isRequired = required?.some((columnId) => columnId === column);
7615
7800
  const colLabel = `${prefix}${column}`;
7616
7801
  const selectedDate = watch(colLabel);
7617
- const formI18n = useFormI18n$1(column, prefix, schema);
7802
+ const formI18n = useFormI18n(column, prefix, schema);
7618
7803
  const displayDate = dayjs(selectedDate)
7619
7804
  .tz(timezone)
7620
7805
  .format(displayDateFormat);
@@ -7624,7 +7809,7 @@ const DateViewer = ({ column, schema, prefix }) => {
7624
7809
 
7625
7810
  const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
7626
7811
  const { watch, formState: { errors }, } = useFormContext();
7627
- const formI18n = useFormI18n$1(column, prefix);
7812
+ const formI18n = useFormI18n(column, prefix);
7628
7813
  const { required } = schema;
7629
7814
  const isRequired = required?.some((columnId) => columnId === column);
7630
7815
  const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
@@ -7648,7 +7833,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7648
7833
  const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
7649
7834
  const isRequired = required?.some((columnId) => columnId === column);
7650
7835
  const currentFiles = (watch(column) ?? []);
7651
- const formI18n = useFormI18n$1(column, prefix, schema);
7836
+ const formI18n = useFormI18n(column, prefix, schema);
7652
7837
  return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', children: jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
7653
7838
  return (jsx(Card.Root, { variant: 'subtle', children: jsxs(Card.Body, { gap: "2", display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name })] }) }, file.name));
7654
7839
  }) }) }));
@@ -7656,7 +7841,7 @@ const FileViewer = ({ column, schema, prefix }) => {
7656
7841
 
7657
7842
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7658
7843
  const { watch, formState: { errors }, } = useFormContext();
7659
- const { idMap, translate } = useSchemaContext();
7844
+ const { idMap, idPickerLabels, formButtonLabels } = useSchemaContext();
7660
7845
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7661
7846
  const isRequired = required?.some((columnId) => columnId === column);
7662
7847
  const formI18n = useFormI18n(column, prefix, schema);
@@ -7680,12 +7865,12 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
7680
7865
  gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
7681
7866
  const item = idMap[id];
7682
7867
  if (item === undefined) {
7683
- return (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
7868
+ return (jsx(Text, { children: idPickerLabels?.undefined ?? 'Undefined' }, id));
7684
7869
  }
7685
7870
  return (jsx(Tag, { closable: true, children: renderDisplay
7686
7871
  ? renderDisplay(item)
7687
7872
  : defaultRenderDisplay(item) }, id));
7688
- }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
7873
+ }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: formButtonLabels?.fieldRequired ?? formI18n.required() }))] }));
7689
7874
  };
7690
7875
 
7691
7876
  const NumberViewer = ({ schema, column, prefix, }) => {
@@ -7694,7 +7879,7 @@ const NumberViewer = ({ schema, column, prefix, }) => {
7694
7879
  const isRequired = required?.some((columnId) => columnId === column);
7695
7880
  const colLabel = `${prefix}${column}`;
7696
7881
  const value = watch(colLabel);
7697
- const formI18n = useFormI18n$1(column, prefix, schema);
7882
+ const formI18n = useFormI18n(column, prefix, schema);
7698
7883
  // Format the value for display if formatOptions are provided
7699
7884
  const formatValue = (val) => {
7700
7885
  if (val === undefined || val === null || val === '')
@@ -7720,7 +7905,7 @@ const ObjectViewer = ({ schema, column, prefix }) => {
7720
7905
  const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
7721
7906
  const colLabel = `${prefix}${column}`;
7722
7907
  const isRequired = required?.some((columnId) => columnId === column);
7723
- const formI18n = useFormI18n$1(column, prefix, schema);
7908
+ const formI18n = useFormI18n(column, prefix, schema);
7724
7909
  const { formState: { errors }, } = useFormContext();
7725
7910
  if (properties === undefined) {
7726
7911
  throw new Error(`properties is undefined when using ObjectInput`);
@@ -7742,7 +7927,7 @@ const RecordViewer = ({ column, schema, prefix }) => {
7742
7927
  const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
7743
7928
  const isRequired = required?.some((columnId) => columnId === column);
7744
7929
  const entries = Object.entries(getValues(column) ?? {});
7745
- const formI18n = useFormI18n$1(column, prefix, schema);
7930
+ const formI18n = useFormI18n(column, prefix, schema);
7746
7931
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, children: [entries.length === 0 ? (jsx(Text, { color: "gray.500", children: "No entries" })) : (jsx(Grid, { templateColumns: '1fr 1fr', gap: 2, children: entries.map(([key, value]) => {
7747
7932
  return (jsxs(Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxs(Text, { fontWeight: "medium", children: [key, ":"] }), jsx(Text, { children: String(value ?? '') })] }, key));
7748
7933
  }) })), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
@@ -7754,7 +7939,7 @@ const StringViewer = ({ column, schema, prefix, }) => {
7754
7939
  const isRequired = required?.some((columnId) => columnId === column);
7755
7940
  const colLabel = `${prefix}${column}`;
7756
7941
  const value = watch(colLabel);
7757
- const formI18n = useFormI18n$1(column, prefix, schema);
7942
+ const formI18n = useFormI18n(column, prefix, schema);
7758
7943
  return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7759
7944
  };
7760
7945
 
@@ -7849,7 +8034,7 @@ const TextAreaViewer = ({ column, schema, prefix, }) => {
7849
8034
  const isRequired = required?.some((columnId) => columnId === column);
7850
8035
  const colLabel = `${prefix}${column}`;
7851
8036
  const value = watch(colLabel);
7852
- const formI18n = useFormI18n$1(column, prefix, schema);
8037
+ const formI18n = useFormI18n(column, prefix, schema);
7853
8038
  return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), ' ', errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
7854
8039
  };
7855
8040
 
@@ -7860,7 +8045,7 @@ const TimeViewer = ({ column, schema, prefix }) => {
7860
8045
  const isRequired = required?.some((columnId) => columnId === column);
7861
8046
  const colLabel = `${prefix}${column}`;
7862
8047
  const selectedDate = watch(colLabel);
7863
- const formI18n = useFormI18n$1(column, prefix, schema);
8048
+ const formI18n = useFormI18n(column, prefix, schema);
7864
8049
  const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
7865
8050
  .tz(timezone)
7866
8051
  .isValid()
@@ -7877,7 +8062,7 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
7877
8062
  const isRequired = required?.some((columnId) => columnId === column);
7878
8063
  const colLabel = `${prefix}${column}`;
7879
8064
  const selectedDate = watch(colLabel);
7880
- const formI18n = useFormI18n$1(column, prefix, schema);
8065
+ const formI18n = useFormI18n(column, prefix, schema);
7881
8066
  const displayDate = dayjs(selectedDate)
7882
8067
  .tz(timezone)
7883
8068
  .format(displayDateFormat);
@@ -7971,7 +8156,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
7971
8156
  };
7972
8157
 
7973
8158
  const SubmitButton = () => {
7974
- const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
8159
+ const { setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
7975
8160
  const methods = useFormContext();
7976
8161
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7977
8162
  const onValid = (data) => {
@@ -8000,11 +8185,11 @@ const SubmitButton = () => {
8000
8185
  };
8001
8186
  return (jsx(Button$1, { onClick: () => {
8002
8187
  methods.handleSubmit(onValid)();
8003
- }, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
8188
+ }, formNoValidate: true, children: formButtonLabels?.submit ?? 'Submit' }));
8004
8189
  };
8005
8190
 
8006
8191
  const FormBody = () => {
8007
- const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8192
+ const { schema, order, ignore, include, isError, isSubmiting, isConfirming, setIsConfirming, validatedData, error, customErrorRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
8008
8193
  const { showSubmitButton, showResetButton } = displayConfig;
8009
8194
  const methods = useFormContext();
8010
8195
  const { properties } = schema;
@@ -8021,21 +8206,6 @@ const FormBody = () => {
8021
8206
  ignore,
8022
8207
  include,
8023
8208
  });
8024
- if (isSuccess) {
8025
- const resetHandler = async () => {
8026
- setIsError(false);
8027
- setIsSubmiting(false);
8028
- setIsSuccess(false);
8029
- setIsConfirming(false);
8030
- setValidatedData(undefined);
8031
- const data = await getUpdatedData();
8032
- methods.reset(data);
8033
- };
8034
- if (customSuccessRenderer) {
8035
- return customSuccessRenderer(resetHandler);
8036
- }
8037
- 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') }) })] }));
8038
- }
8039
8209
  if (isConfirming) {
8040
8210
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
8041
8211
  return (jsx(ColumnViewer
@@ -8045,9 +8215,9 @@ const FormBody = () => {
8045
8215
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
8046
8216
  }) }), jsxs(Flex, { justifyContent: 'end', gap: '2', children: [jsx(Button$1, { onClick: () => {
8047
8217
  setIsConfirming(false);
8048
- }, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsx(Button$1, { onClick: () => {
8218
+ }, variant: 'subtle', children: formButtonLabels?.cancel ?? 'Cancel' }), jsx(Button$1, { onClick: () => {
8049
8219
  onFormSubmit(validatedData);
8050
- }, children: formButtonLabels?.confirm ?? translate.t('confirm') })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8220
+ }, children: formButtonLabels?.confirm ?? 'Confirm' })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
8051
8221
  }
8052
8222
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
8053
8223
  return (jsx(ColumnRenderer
@@ -8057,12 +8227,12 @@ const FormBody = () => {
8057
8227
  properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
8058
8228
  }) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
8059
8229
  methods.reset();
8060
- }, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8230
+ }, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
8061
8231
  };
8062
8232
 
8063
8233
  const FormTitle = () => {
8064
- const { translate } = useSchemaContext();
8065
- return jsx(Heading, { children: translate.t("title") });
8234
+ const { schema } = useSchemaContext();
8235
+ return jsx(Heading, { children: schema.title ?? 'Form' });
8066
8236
  };
8067
8237
 
8068
8238
  const DefaultForm = ({ formConfig, }) => {
@@ -8070,7 +8240,9 @@ const DefaultForm = ({ formConfig, }) => {
8070
8240
  return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
8071
8241
  };
8072
8242
 
8073
- const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8243
+ const useForm = ({ preLoadedValues, keyPrefix: _keyPrefix, // Deprecated: kept for backward compatibility
8244
+ namespace: _namespace, // Deprecated: kept for backward compatibility
8245
+ schema, }) => {
8074
8246
  const form = useForm$1({
8075
8247
  values: preLoadedValues,
8076
8248
  resolver: schema ? ajvResolver(schema) : undefined,
@@ -8078,12 +8250,16 @@ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
8078
8250
  reValidateMode: 'onBlur',
8079
8251
  });
8080
8252
  const [idMap, setIdMap] = useState({});
8081
- const translate = useTranslation(namespace || '', { keyPrefix });
8253
+ // Fallback translate object - returns key as-is (no i18n required)
8254
+ const translate = {
8255
+ t: (key) => key,
8256
+ ready: true,
8257
+ };
8082
8258
  return {
8083
8259
  form,
8084
8260
  idMap,
8085
8261
  setIdMap,
8086
- translate,
8262
+ translate, // Components prefer label objects over translate
8087
8263
  };
8088
8264
  };
8089
8265
 
@@ -8411,6 +8587,21 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
8411
8587
  })] }));
8412
8588
  };
8413
8589
 
8590
+ const MobileTableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsx(Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsx(Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
8591
+ const { tableLabel, table } = useDataTableContext();
8592
+ const { hasErrorText } = tableLabel;
8593
+ return (jsxs(Grid, { templateRows: 'auto 1fr auto', width: fitTableWidth ? 'fit-content' : '100%', height: fitTableHeight ? 'fit-content' : '100%', gap: 2, padding: 2, ...gridProps, children: [jsxs(Stack, { gap: 2, children: [jsxs(Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, children: [jsxs(Flex, { gap: 1, alignItems: 'center', children: [showView && jsx(ViewDialog, { icon: jsx(MdOutlineViewColumn, {}) }), loading && jsx(Spinner, { size: 'sm' }), hasError && (jsx(Tooltip, { content: hasErrorText, children: jsx(Icon, { as: BsExclamationCircleFill, color: 'red.400' }) }))] }), jsxs(Flex, { gap: 1, alignItems: 'center', children: [showGlobalFilter && jsx(GlobalFilter, {}), showFilter && jsx(FilterDialog, {}), showReload && jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsx(Stack, { gap: 2, children: filterTagsOptions.map((option) => {
8594
+ const { column, options } = option;
8595
+ const tableColumn = table.getColumn(column);
8596
+ return (jsxs(Flex, { flexFlow: 'column', gap: 1, width: '100%', children: [tableColumn?.columnDef.meta?.displayName && (jsx(Text, { fontSize: 'sm', fontWeight: 'medium', children: tableColumn?.columnDef.meta?.displayName })), jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
8597
+ if (tags.length === 0) {
8598
+ return tableColumn?.setFilterValue(undefined);
8599
+ }
8600
+ tableColumn?.setFilterValue(tags);
8601
+ } })] }, column));
8602
+ }) })), showFilterTags && (jsx(Box, { width: '100%', children: jsx(TableFilterTags, {}) }))] }), jsx(Box, { overflow: 'auto', width: '100%', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, borderRadius: 'md', padding: 1, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxs(Stack, { gap: 2, width: '100%', children: [(showPageSizeControl || showPageCountText) && (jsxs(Flex, { justifyContent: 'space-between', alignItems: 'center', gap: 2, flexWrap: 'wrap', children: [showPageSizeControl && jsx(PageSizeControl, {}), showPageCountText && jsx(RowCountText, {})] })), showPagination && (jsx(Flex, { justifyContent: 'center', width: '100%', children: jsx(Pagination, {}) }))] }))] }));
8603
+ };
8604
+
8414
8605
  const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
8415
8606
  'use no memo';
8416
8607
  const { table } = useDataTableContext();
@@ -8470,22 +8661,77 @@ const TableRowSelectorSkeleton = () => {
8470
8661
  bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsx(Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
8471
8662
  };
8472
8663
 
8473
- const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = '', isLoading = false, }) => {
8474
- if (variant === 'greedy') {
8475
- const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: false })) : (jsx(TableBody, { ...tableBodyProps, canResize: false, ...tableBodyProps }));
8476
- return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { canResize: false,
8477
- showLoading: isLoading,
8478
- showSelector: tableHeaderProps.showSelector ??
8664
+ const MobileTableDisplay = ({ showSelector = false, isLoading = false, }) => {
8665
+ const { table, rowSelection, setRowSelection } = useDataTableContext();
8666
+ if (isLoading) {
8667
+ return jsx(MobileTableSkeleton, { showSelector: showSelector });
8668
+ }
8669
+ return (jsx(Stack, { gap: 4, padding: 2, children: table.getRowModel().rows.map((row) => {
8670
+ return (jsx(Card.Root, { width: "100%", children: jsxs(Card.Body, { padding: 4, children: [showSelector && (jsx(Flex, { marginBottom: 3, children: jsx(Checkbox, { checked: isRowSelected(row.id, rowSelection),
8671
+ disabled: !canRowSelect(row),
8672
+ onCheckedChange: createRowToggleHandler(row, rowSelection, setRowSelection) }) })), jsx(Stack, { gap: 3, children: row.getVisibleCells().map((cell) => {
8673
+ const displayName = cell.column.columnDef.meta?.displayName ?? cell.column.id;
8674
+ return (jsxs(Box, { children: [jsx(Text, { fontSize: "sm", fontWeight: "bold", color: { base: 'gray.600', _dark: 'gray.400' }, marginBottom: 1, children: displayName }), jsx(Box, { color: { base: 'gray.900', _dark: 'gray.100' }, fontSize: "sm", children: flexRender(cell.column.columnDef.cell, cell.getContext()) })] }, `mobile-table-cell-${cell.id}`));
8675
+ }) })] }) }, `mobile-table-card-${row.id}`));
8676
+ }) }));
8677
+ };
8678
+ const MobileTableSkeleton = ({ showSelector = false, }) => {
8679
+ const { table } = useDataTableContext();
8680
+ const pageSize = table.getState().pagination.pageSize;
8681
+ const visibleColumns = table.getVisibleLeafColumns();
8682
+ return (jsx(Stack, { gap: 4, padding: 2, children: Array.from({ length: pageSize }).map((_, rowIndex) => {
8683
+ return (jsx(Card.Root, { width: "100%", children: jsxs(Card.Body, { padding: 4, children: [showSelector && (jsx(Flex, { marginBottom: 3, children: jsx(Box, { width: "20px", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "md" }) })), jsx(Stack, { gap: 3, children: visibleColumns.map((column) => {
8684
+ return (jsxs(Box, { children: [jsx(Box, { width: "40%", height: "16px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm", marginBottom: 2 }), jsx(Box, { width: "80%", height: "20px", bg: { base: 'gray.200', _dark: 'gray.700' }, borderRadius: "sm" })] }, `mobile-skeleton-cell-${column.id}`));
8685
+ }) })] }) }, `mobile-skeleton-${rowIndex}`));
8686
+ }) }));
8687
+ };
8688
+
8689
+ /**
8690
+ * Hook to detect if the current window width is mobile (< 768px)
8691
+ * @param breakpoint - The breakpoint in pixels to consider as mobile (default: 768)
8692
+ * @returns boolean indicating if the window is mobile
8693
+ */
8694
+ const useIsMobile = (breakpoint = 768) => {
8695
+ const [isMobile, setIsMobile] = useState(() => {
8696
+ if (typeof window === 'undefined')
8697
+ return false;
8698
+ return window.innerWidth < breakpoint;
8699
+ });
8700
+ useEffect(() => {
8701
+ if (typeof window === 'undefined')
8702
+ return;
8703
+ const handleResize = () => {
8704
+ setIsMobile(window.innerWidth < breakpoint);
8705
+ };
8706
+ // Set initial value
8707
+ handleResize();
8708
+ // Add event listener
8709
+ window.addEventListener('resize', handleResize);
8710
+ // Cleanup
8711
+ return () => {
8712
+ window.removeEventListener('resize', handleResize);
8713
+ };
8714
+ }, [breakpoint]);
8715
+ return isMobile;
8716
+ };
8717
+
8718
+ const DefaultTable = ({ showFooter = false, showHeader = true, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = 'greedy', isLoading = false, }) => {
8719
+ const isMobile = useIsMobile();
8720
+ // Early return for mobile display
8721
+ if (isMobile) {
8722
+ return (jsx(MobileTableControls, { ...controlProps, children: jsx(MobileTableDisplay, { showSelector: tableHeaderProps.showSelector ??
8479
8723
  tableBodyProps.showSelector ??
8480
- false,
8481
- ...tableProps, children: [jsx(TableHeader, { canResize: false, ...tableHeaderProps }), bodyComponent, showFooter && (jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
8724
+ false, isLoading: isLoading }) }));
8482
8725
  }
8483
- const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: tableBodyProps.canResize })) : (jsx(TableBody, { ...tableBodyProps }));
8484
- return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { showLoading: isLoading,
8726
+ const isGreedy = variant === 'greedy';
8727
+ const canResize = !isGreedy;
8728
+ const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: canResize })) : (jsx(TableBody, { ...tableBodyProps, canResize: canResize }));
8729
+ return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { canResize,
8730
+ showLoading: isLoading,
8485
8731
  showSelector: tableHeaderProps.showSelector ??
8486
8732
  tableBodyProps.showSelector ??
8487
8733
  false,
8488
- ...tableProps, children: [jsx(TableHeader, { ...tableHeaderProps }), bodyComponent, showFooter && jsx(TableFooter, { ...tableFooterProps })] }) }));
8734
+ ...tableProps, children: [showHeader && jsx(TableHeader, { canResize, ...tableHeaderProps }), bodyComponent, showFooter && jsx(TableFooter, { canResize, ...tableFooterProps })] }) }));
8489
8735
  };
8490
8736
 
8491
8737
  /**
@@ -8577,6 +8823,290 @@ const DataDisplay = ({ variant = '' }) => {
8577
8823
  }) }));
8578
8824
  };
8579
8825
 
8826
+ // Helper function to normalize date
8827
+ function normalizeDate(value) {
8828
+ if (!value)
8829
+ return null;
8830
+ if (value instanceof Date)
8831
+ return value;
8832
+ if (typeof value === 'string' || typeof value === 'number') {
8833
+ const date = dayjs(value).toDate();
8834
+ return isNaN(date.getTime()) ? null : date;
8835
+ }
8836
+ return null;
8837
+ }
8838
+ // Component to conditionally render event title based on available width
8839
+ function ResponsiveEventTitle({ title, placeholder, minWidth, minChars, cellRef, }) {
8840
+ const [truncatedText, setTruncatedText] = useState('');
8841
+ const measureRef = useRef(null);
8842
+ useEffect(() => {
8843
+ const calculateTruncatedText = () => {
8844
+ if (!cellRef.current || !measureRef.current || !title) {
8845
+ setTruncatedText(title || 'Event');
8846
+ return;
8847
+ }
8848
+ const cellWidth = cellRef.current.clientWidth;
8849
+ // Account for padding (approximately 8px on each side)
8850
+ const availableWidth = cellWidth - 16;
8851
+ // If cell is too narrow, calculate how many characters can fit
8852
+ if (availableWidth < minWidth) {
8853
+ // Measure text width using canvas
8854
+ const canvas = document.createElement('canvas');
8855
+ const context = canvas.getContext('2d');
8856
+ if (!context) {
8857
+ setTruncatedText(placeholder);
8858
+ return;
8859
+ }
8860
+ // Get computed font style from the element
8861
+ const computedStyle = window.getComputedStyle(measureRef.current);
8862
+ context.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
8863
+ const ellipsisWidth = context.measureText('...').width;
8864
+ const maxWidth = availableWidth - ellipsisWidth;
8865
+ // Try to show at least minChars characters before ellipsis
8866
+ let truncated = '';
8867
+ let charCount = 0;
8868
+ // Calculate how many characters can fit
8869
+ for (let i = 0; i < Math.min(title.length, 50); i++) {
8870
+ const testText = title.substring(0, i + 1);
8871
+ const textWidth = context.measureText(testText).width;
8872
+ if (textWidth <= maxWidth) {
8873
+ truncated = testText;
8874
+ charCount = i + 1;
8875
+ }
8876
+ else {
8877
+ break;
8878
+ }
8879
+ }
8880
+ // Ensure we show at least minChars characters if possible
8881
+ if (charCount < minChars && title.length >= minChars) {
8882
+ truncated = title.substring(0, minChars);
8883
+ }
8884
+ else if (charCount === 0 && title.length >= 1) {
8885
+ truncated = title.substring(0, 1);
8886
+ }
8887
+ // Only show ellipsis if we have at least minChars characters
8888
+ if (truncated && truncated.length >= minChars) {
8889
+ setTruncatedText(`${truncated}...`);
8890
+ }
8891
+ else {
8892
+ setTruncatedText(placeholder);
8893
+ }
8894
+ }
8895
+ else {
8896
+ // Full width available, show full title
8897
+ setTruncatedText(title);
8898
+ }
8899
+ };
8900
+ calculateTruncatedText();
8901
+ const resizeObserver = new ResizeObserver(calculateTruncatedText);
8902
+ if (cellRef.current) {
8903
+ resizeObserver.observe(cellRef.current);
8904
+ }
8905
+ // Also check on window resize
8906
+ window.addEventListener('resize', calculateTruncatedText);
8907
+ return () => {
8908
+ resizeObserver.disconnect();
8909
+ window.removeEventListener('resize', calculateTruncatedText);
8910
+ };
8911
+ }, [cellRef, minWidth, title, placeholder]);
8912
+ return (jsxs(Fragment, { children: [jsx("span", { ref: measureRef, style: {
8913
+ visibility: 'hidden',
8914
+ position: 'absolute',
8915
+ whiteSpace: 'nowrap',
8916
+ }, children: title || 'Event' }), truncatedText || title || 'Event'] }));
8917
+ }
8918
+ function CalendarDisplay({ dateColumn, getDate, getEventTitle, getEventColor, renderEvent, firstDayOfWeek = 0, showOutsideDays = true, monthsToDisplay = 1, labels = {
8919
+ monthNamesShort: [
8920
+ 'Jan',
8921
+ 'Feb',
8922
+ 'Mar',
8923
+ 'Apr',
8924
+ 'May',
8925
+ 'Jun',
8926
+ 'Jul',
8927
+ 'Aug',
8928
+ 'Sep',
8929
+ 'Oct',
8930
+ 'Nov',
8931
+ 'Dec',
8932
+ ],
8933
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
8934
+ backButtonLabel: 'Back',
8935
+ forwardButtonLabel: 'Next',
8936
+ }, onDateClick, onEventClick, maxEventsPerDay = 3, colorPalette = 'blue', eventPlaceholder = '...', minEventWidth = 80, minCharsBeforeEllipsis = 2, }) {
8937
+ const { data, table } = useDataTableContext();
8938
+ // Map table data to events
8939
+ const events = useMemo(() => {
8940
+ return data
8941
+ .map((row) => {
8942
+ let dateValue;
8943
+ if (getDate) {
8944
+ dateValue = getDate(row);
8945
+ }
8946
+ else {
8947
+ // Try to get date from column
8948
+ const rowData = table
8949
+ .getRowModel()
8950
+ .rows.find((r) => r.original === row);
8951
+ if (rowData) {
8952
+ const cell = rowData.getAllCells().find((c) => {
8953
+ const colId = c.column.id;
8954
+ const accessorKey = c.column.columnDef.accessorKey;
8955
+ return colId === dateColumn || accessorKey === dateColumn;
8956
+ });
8957
+ dateValue = cell?.getValue();
8958
+ }
8959
+ }
8960
+ const date = normalizeDate(dateValue);
8961
+ if (!date)
8962
+ return null;
8963
+ let title;
8964
+ if (getEventTitle) {
8965
+ title = getEventTitle(row);
8966
+ }
8967
+ else {
8968
+ // Use first column's value as title
8969
+ const rowData = table
8970
+ .getRowModel()
8971
+ .rows.find((r) => r.original === row);
8972
+ if (rowData) {
8973
+ const firstCell = rowData.getAllCells()[0];
8974
+ title = String(firstCell?.getValue() ?? '');
8975
+ }
8976
+ }
8977
+ const color = getEventColor?.(row);
8978
+ return {
8979
+ data: row,
8980
+ date,
8981
+ title,
8982
+ color,
8983
+ };
8984
+ })
8985
+ .filter((event) => event !== null);
8986
+ }, [data, table, dateColumn, getDate, getEventTitle, getEventColor]);
8987
+ // Group events by date
8988
+ const eventsByDate = useMemo(() => {
8989
+ const map = new Map();
8990
+ events.forEach((event) => {
8991
+ const dateKey = `${event.date.getFullYear()}-${event.date.getMonth()}-${event.date.getDate()}`;
8992
+ if (!map.has(dateKey)) {
8993
+ map.set(dateKey, []);
8994
+ }
8995
+ map.get(dateKey).push(event);
8996
+ });
8997
+ return map;
8998
+ }, [events]);
8999
+ // Get events for a specific date
9000
+ const getEventsForDate = useCallback((date) => {
9001
+ const dateKey = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
9002
+ return eventsByDate.get(dateKey) ?? [];
9003
+ }, [eventsByDate]);
9004
+ const calendarData = useCalendar({
9005
+ firstDayOfWeek,
9006
+ showOutsideDays,
9007
+ monthsToDisplay,
9008
+ });
9009
+ const getDateProps = useCallback((props) => {
9010
+ const dateEvents = getEventsForDate(props.dateObj.date);
9011
+ const baseProps = calendarData.getDateProps({ dateObj: props.dateObj });
9012
+ return {
9013
+ ...baseProps,
9014
+ onClick: () => {
9015
+ baseProps.onClick?.();
9016
+ if (onDateClick) {
9017
+ onDateClick(props.dateObj.date, dateEvents);
9018
+ }
9019
+ },
9020
+ };
9021
+ }, [calendarData, getEventsForDate, onDateClick]);
9022
+ const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
9023
+ if (!calendarData.calendars.length) {
9024
+ return null;
9025
+ }
9026
+ return (jsxs(VStack, { gap: 4, width: "100%", children: [jsxs(HStack, { gap: 2, justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({
9027
+ calendars: calendarData.calendars,
9028
+ offset: 12,
9029
+ }), children: '<<' }), jsx(Button$1, { variant: "ghost", ...calendarData.getBackProps({ calendars: calendarData.calendars }), children: backButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9030
+ calendars: calendarData.calendars,
9031
+ }), children: forwardButtonLabel }), jsx(Button$1, { variant: "ghost", ...calendarData.getForwardProps({
9032
+ calendars: calendarData.calendars,
9033
+ offset: 12,
9034
+ }), children: '>>' })] }), jsx(Grid, { templateColumns: {
9035
+ base: '1fr',
9036
+ md: monthsToDisplay >= 2 ? 'repeat(2, 1fr)' : '1fr',
9037
+ lg: monthsToDisplay >= 3
9038
+ ? 'repeat(3, 1fr)'
9039
+ : monthsToDisplay === 2
9040
+ ? 'repeat(2, 1fr)'
9041
+ : '1fr',
9042
+ xl: `repeat(${Math.min(monthsToDisplay, 4)}, 1fr)`,
9043
+ }, gap: { base: 4, md: 6 }, width: "100%", justifyContent: "center", children: calendarData.calendars.map((calendar) => (jsxs(VStack, { gap: 2, alignItems: "stretch", children: [jsxs(Text, { textAlign: "center", fontSize: { base: 'md', md: 'lg' }, fontWeight: "semibold", children: [monthNamesShort[calendar.month], " ", calendar.year] }), jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
9044
+ const weekday = (weekdayNum + firstDayOfWeek) % 7;
9045
+ return (jsx(Text, { textAlign: "center", fontSize: { base: 'xs', md: 'sm' }, fontWeight: "medium", color: { base: 'gray.600', _dark: 'gray.400' }, children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
9046
+ }) }), jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: { base: 0.5, md: 1 }, children: calendar.weeks.map((week, weekIndex) => week.map((dateObj, index) => {
9047
+ const key = `${calendar.month}${calendar.year}${weekIndex}${index}`;
9048
+ if (!dateObj) {
9049
+ return jsx(Box, {}, key);
9050
+ }
9051
+ const { date, today, isCurrentMonth } = dateObj;
9052
+ const dateEvents = getEventsForDate(date);
9053
+ const cellRef = useRef(null);
9054
+ return (jsxs(VStack, { ref: cellRef, gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", minHeight: { base: '60px', md: '80px', lg: '100px' }, borderWidth: "1px", borderColor: {
9055
+ base: today ? `${colorPalette}.300` : 'gray.200',
9056
+ _dark: today ? `${colorPalette}.700` : 'gray.700',
9057
+ }, borderRadius: { base: 'sm', md: 'md' }, padding: { base: 0.5, md: 1 }, bgColor: {
9058
+ base: today ? `${colorPalette}.50` : 'white',
9059
+ _dark: today ? `${colorPalette}.950` : 'gray.900',
9060
+ }, opacity: isCurrentMonth ? 1 : 0.5, ...getDateProps({ dateObj }), cursor: onDateClick ? 'pointer' : 'default', _hover: onDateClick
9061
+ ? {
9062
+ bgColor: {
9063
+ base: `${colorPalette}.100`,
9064
+ _dark: `${colorPalette}.900`,
9065
+ },
9066
+ }
9067
+ : {}, children: [jsx(Text, { fontSize: { base: 'xs', md: 'sm' }, fontWeight: today ? 'bold' : 'normal', color: {
9068
+ base: today ? `${colorPalette}.700` : 'gray.700',
9069
+ _dark: today ? `${colorPalette}.300` : 'gray.300',
9070
+ }, textAlign: "right", paddingRight: { base: 0.5, md: 1 }, children: date.getDate() }), jsxs(VStack, { gap: { base: 0.25, md: 0.5 }, alignItems: "stretch", flex: 1, overflow: "hidden", children: [dateEvents
9071
+ .slice(0, maxEventsPerDay)
9072
+ .map((event, eventIndex) => {
9073
+ const eventContent = renderEvent ? (renderEvent(event)) : (jsx(Box, { fontSize: { base: '2xs', md: 'xs' }, paddingX: { base: 0.5, md: 1 }, paddingY: { base: 0.25, md: 0.5 }, borderRadius: { base: 'xs', md: 'sm' }, bgColor: {
9074
+ base: event.color
9075
+ ? `${event.color}.100`
9076
+ : `${colorPalette}.100`,
9077
+ _dark: event.color
9078
+ ? `${event.color}.900`
9079
+ : `${colorPalette}.900`,
9080
+ }, color: {
9081
+ base: event.color
9082
+ ? `${event.color}.800`
9083
+ : `${colorPalette}.800`,
9084
+ _dark: event.color
9085
+ ? `${event.color}.200`
9086
+ : `${colorPalette}.200`,
9087
+ }, onClick: (e) => {
9088
+ e.stopPropagation();
9089
+ if (onEventClick) {
9090
+ onEventClick(event);
9091
+ }
9092
+ }, cursor: onEventClick ? 'pointer' : 'default', _hover: onEventClick
9093
+ ? {
9094
+ opacity: 0.8,
9095
+ }
9096
+ : {}, children: jsx(ResponsiveEventTitle, { title: event.title, placeholder: eventPlaceholder, minWidth: minEventWidth, minChars: minCharsBeforeEllipsis, cellRef: cellRef }) }, eventIndex));
9097
+ return (jsx(Box, { onClick: (e) => e.stopPropagation(), children: eventContent }, eventIndex));
9098
+ }), dateEvents.length > maxEventsPerDay && (jsxs(Text, { fontSize: "xs", color: {
9099
+ base: `${colorPalette}.600`,
9100
+ _dark: `${colorPalette}.400`,
9101
+ }, paddingX: 1, onClick: (e) => {
9102
+ e.stopPropagation();
9103
+ if (onDateClick) {
9104
+ onDateClick(date, dateEvents);
9105
+ }
9106
+ }, cursor: onDateClick ? 'pointer' : 'default', children: ["+", dateEvents.length - maxEventsPerDay, " more"] }))] })] }, key));
9107
+ })) })] }, `${calendar.month}${calendar.year}`))) })] }));
9108
+ }
9109
+
8580
9110
  // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
8581
9111
  // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
8582
9112
  // end of TS setup!
@@ -8677,7 +9207,7 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
8677
9207
  *
8678
9208
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8679
9209
  */
8680
- function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, translate, children, tableLabel = {
9210
+ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, children, tableLabel = {
8681
9211
  view: 'View',
8682
9212
  edit: 'Edit',
8683
9213
  filterButtonText: 'Filter',
@@ -8688,7 +9218,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8688
9218
  reloadButtonText: 'Reload',
8689
9219
  resetSelection: 'Reset Selection',
8690
9220
  resetSorting: 'Reset Sorting',
8691
- rowCountText: 'Row Count',
9221
+ rowCountText: '',
8692
9222
  hasErrorText: 'Has Error',
8693
9223
  globalFilterPlaceholder: 'Search',
8694
9224
  trueLabel: 'True',
@@ -8745,7 +9275,6 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8745
9275
  globalFilter,
8746
9276
  setGlobalFilter,
8747
9277
  type: 'client',
8748
- translate,
8749
9278
  columns: columns,
8750
9279
  sorting,
8751
9280
  setSorting,
@@ -8777,22 +9306,22 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
8777
9306
  *
8778
9307
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
8779
9308
  */
8780
- 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 = {
8781
- view: "View",
8782
- edit: "Edit",
8783
- filterButtonText: "Filter",
8784
- filterTitle: "Filter",
8785
- filterReset: "Reset",
8786
- filterClose: "Close",
8787
- reloadTooltip: "Reload",
8788
- reloadButtonText: "Reload",
8789
- resetSelection: "Reset Selection",
8790
- resetSorting: "Reset Sorting",
8791
- rowCountText: "Row Count",
8792
- hasErrorText: "Has Error",
8793
- globalFilterPlaceholder: "Search",
8794
- trueLabel: "True",
8795
- falseLabel: "False",
9309
+ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, children, tableLabel = {
9310
+ view: 'View',
9311
+ edit: 'Edit',
9312
+ filterButtonText: 'Filter',
9313
+ filterTitle: 'Filter',
9314
+ filterReset: 'Reset',
9315
+ filterClose: 'Close',
9316
+ reloadTooltip: 'Reload',
9317
+ reloadButtonText: 'Reload',
9318
+ resetSelection: 'Reset Selection',
9319
+ resetSorting: 'Reset Sorting',
9320
+ rowCountText: '',
9321
+ hasErrorText: 'Has Error',
9322
+ globalFilterPlaceholder: 'Search',
9323
+ trueLabel: 'True',
9324
+ falseLabel: 'False',
8796
9325
  }, }) {
8797
9326
  const table = useReactTable({
8798
9327
  _features: [DensityFeature],
@@ -8802,7 +9331,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8802
9331
  getCoreRowModel: getCoreRowModel(),
8803
9332
  manualPagination: true,
8804
9333
  manualSorting: true,
8805
- columnResizeMode: "onChange",
9334
+ columnResizeMode: 'onChange',
8806
9335
  defaultColumn: {
8807
9336
  size: 150, //starting column size
8808
9337
  minSize: 10, //enforced during column resizing
@@ -8845,8 +9374,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8845
9374
  table: table,
8846
9375
  globalFilter,
8847
9376
  setGlobalFilter,
8848
- type: "server",
8849
- translate,
9377
+ type: 'server',
8850
9378
  columns: columns,
8851
9379
  sorting,
8852
9380
  setSorting,
@@ -8864,7 +9392,7 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
8864
9392
  setColumnVisibility,
8865
9393
  data: query.data?.data ?? [],
8866
9394
  tableLabel,
8867
- }, children: jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
9395
+ }, children: jsx(DataTableServerContext.Provider, { value: { url: url ?? '', query }, children: children }) }));
8868
9396
  }
8869
9397
 
8870
- export { CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
9398
+ export { CalendarDisplay, CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };