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