@bsol-oss/react-datatable5 12.0.0-beta.89 → 12.0.0-beta.90

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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Image, Alert, Field as Field$1, Popover, useFilter, useListCollection, Combobox, Tabs, Skeleton, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, CheckboxCard as CheckboxCard$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, Tooltip as Tooltip$1, Group, InputElement, Icon, EmptyState as EmptyState$2, VStack, List, Table as Table$1, Checkbox as Checkbox$1, Card, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Tag as Tag$1, Image, Alert, Field as Field$1, Popover, useFilter, useListCollection, Combobox, Tabs, Skeleton, NumberInput, Show, RadioCard, CheckboxGroup, InputGroup as InputGroup$1, Center, Heading } from '@chakra-ui/react';
3
3
  import { AiOutlineColumnWidth } from 'react-icons/ai';
4
4
  import * as React from 'react';
5
5
  import React__default, { createContext, useContext, useState, useEffect, useRef, useMemo, forwardRef } from 'react';
@@ -166,22 +166,30 @@ const Radio = React.forwardRef(function Radio(props, ref) {
166
166
  });
167
167
  const RadioGroup = RadioGroup$1.Root;
168
168
 
169
- const monthNamesFull = [
170
- "January",
171
- "February",
172
- "March",
173
- "April",
174
- "May",
175
- "June",
176
- "July",
177
- "August",
178
- "September",
179
- "October",
180
- "November",
181
- "December",
182
- ];
183
- const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
169
+ const RangeDatePickerContext = createContext({
170
+ labels: {
171
+ monthNamesFull: [
172
+ 'January',
173
+ 'February',
174
+ 'March',
175
+ 'April',
176
+ 'May',
177
+ 'June',
178
+ 'July',
179
+ 'August',
180
+ 'September',
181
+ 'October',
182
+ 'November',
183
+ 'December',
184
+ ],
185
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
186
+ backButtonLabel: 'Back',
187
+ forwardButtonLabel: 'Next',
188
+ },
189
+ });
184
190
  function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, selected = [], firstDayOfWeek = 0, }) {
191
+ const { labels } = useContext(RangeDatePickerContext);
192
+ const { monthNamesFull, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
185
193
  const [hoveredDate, setHoveredDate] = useState();
186
194
  const onMouseLeave = () => {
187
195
  setHoveredDate(undefined);
@@ -207,16 +215,18 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
207
215
  return false;
208
216
  };
209
217
  if (calendars.length) {
210
- return (jsxs(Grid, { onMouseLeave: onMouseLeave, children: [jsxs(Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsx(Button$1, { variant: "ghost", ...getBackProps({
218
+ return (jsxs(Grid, { onMouseLeave: onMouseLeave, children: [jsxs(Grid, { templateColumns: 'repeat(4, auto)', justifyContent: 'center', children: [jsx(Button$1, { variant: 'ghost', ...getBackProps({
211
219
  calendars,
212
220
  offset: 12,
213
- }), children: "<<" }), jsx(Button$1, { variant: "ghost", ...getBackProps({ calendars }), children: "Back" }), jsx(Button$1, { variant: "ghost", ...getForwardProps({ calendars }), children: "Next" }), jsx(Button$1, { variant: "ghost", ...getForwardProps({
221
+ }), children: '<<' }), jsx(Button$1, { variant: 'ghost', ...getBackProps({ calendars }), children: backButtonLabel }), jsx(Button$1, { variant: 'ghost', ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsx(Button$1, { variant: 'ghost', ...getForwardProps({
214
222
  calendars,
215
223
  offset: 12,
216
- }), children: ">>" })] }), jsx(Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", gap: 4, children: calendars.map((calendar) => (jsxs(Grid, { gap: 4, children: [jsxs(Grid, { justifyContent: "center", children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsx(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
224
+ }), children: '>>' })] }), jsx(Grid, { templateColumns: 'repeat(2, auto)', justifyContent: 'center', gap: 4, children: calendars.map((calendar) => (
225
+ // month and year
226
+ jsxs(Grid, { gap: 4, alignContent: "start", children: [jsxs(Grid, { justifyContent: 'center', children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsx(Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
217
227
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
218
- return (jsx(Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
219
- }) }), jsx(Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
228
+ return (jsx(Box, { minWidth: '48px', textAlign: 'center', children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
229
+ }) }), jsx(Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
220
230
  const key = `${calendar.month}${calendar.year}${windex}${index}`;
221
231
  if (!dateObj) {
222
232
  return jsx(Box, {}, key);
@@ -225,29 +235,29 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
225
235
  const getStyle = ({ selected, unavailable, today, isInRange, }) => {
226
236
  if (unavailable) {
227
237
  return {
228
- colorPalette: "gray",
229
- variant: "solid",
238
+ colorPalette: 'gray',
239
+ variant: 'solid',
230
240
  };
231
241
  }
232
242
  if (selected) {
233
243
  return {
234
- colorPalette: "blue",
235
- variant: "solid",
244
+ colorPalette: 'blue',
245
+ variant: 'solid',
236
246
  };
237
247
  }
238
248
  if (isInRange) {
239
249
  return {
240
- colorPalette: "blue",
241
- variant: "subtle",
250
+ colorPalette: 'blue',
251
+ variant: 'subtle',
242
252
  };
243
253
  }
244
254
  if (today) {
245
255
  return {
246
- colorPalette: "green",
247
- variant: "solid",
256
+ colorPalette: 'green',
257
+ variant: 'solid',
248
258
  };
249
259
  }
250
- return { variant: "ghost" };
260
+ return { variant: 'ghost' };
251
261
  };
252
262
  return (jsx(Button$1, { ...getDateProps({
253
263
  dateObj,
@@ -259,18 +269,34 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
259
269
  unavailable: !selectable,
260
270
  today,
261
271
  isInRange: isInRange(date),
262
- }), children: selectable ? date.getDate() : "X" }, key));
272
+ }), children: selectable ? date.getDate() : 'X' }, key));
263
273
  })) })] }, `${calendar.month}${calendar.year}`))) })] }));
264
274
  }
265
275
  return null;
266
276
  }
267
- class RangeDatePicker extends React__default.Component {
268
- render() {
269
- return (jsx(Dayzed, { onDateSelected: this.props.onDateSelected, selected: this.props.selected, firstDayOfWeek: this.props.firstDayOfWeek, showOutsideDays: this.props.showOutsideDays, date: this.props.date, minDate: this.props.minDate, maxDate: this.props.maxDate, monthsToDisplay: this.props.monthsToDisplay, render: (dayzedData) => (jsx(Calendar$1, { ...dayzedData,
270
- firstDayOfWeek: this.props.firstDayOfWeek,
271
- selected: this.props.selected })) }));
272
- }
273
- }
277
+ const RangeDatePicker = ({ labels = {
278
+ monthNamesFull: [
279
+ 'January',
280
+ 'February',
281
+ 'March',
282
+ 'April',
283
+ 'May',
284
+ 'June',
285
+ 'July',
286
+ 'August',
287
+ 'September',
288
+ 'October',
289
+ 'November',
290
+ 'December',
291
+ ],
292
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
293
+ backButtonLabel: 'Back',
294
+ forwardButtonLabel: 'Next',
295
+ }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, ...rest }) => {
296
+ return (jsx(RangeDatePickerContext.Provider, { value: { labels }, children: jsx(Dayzed, { onDateSelected: onDateSelected, selected: selected, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, date: date, minDate: minDate, maxDate: maxDate, monthsToDisplay: monthsToDisplay, ...rest, render: (dayzedData) => (jsx(Calendar$1, { ...dayzedData,
297
+ firstDayOfWeek,
298
+ selected: selected })) }) }));
299
+ };
274
300
 
275
301
  const getRangeDates = ({ selectable, date, selectedDates, }) => {
276
302
  if (!selectable) {
@@ -331,32 +357,38 @@ const RangeFilter = ({ range, setRange, defaultValue, min, max, step, }) => {
331
357
  onValueChange: (val) => setRange(val.value) })] }));
332
358
  };
333
359
 
334
- const Tag = React.forwardRef(function Tag(props, ref) {
335
- const { startElement, endElement, onClose, closable = !!onClose, children, ...rest } = props;
336
- return (jsxs(Tag$1.Root, { ref: ref, ...rest, children: [startElement && (jsx(Tag$1.StartElement, { children: startElement })), jsx(Tag$1.Label, { children: children }), endElement && (jsx(Tag$1.EndElement, { children: endElement })), closable && (jsx(Tag$1.EndElement, { children: jsx(Tag$1.CloseTrigger, { onClick: onClose }) }))] }));
360
+ const CheckboxCard = React.forwardRef(function CheckboxCard(props, ref) {
361
+ const { inputProps, label, description, icon, addon, indicator = jsx(CheckboxCard$1.Indicator, {}), indicatorPlacement = "end", ...rest } = props;
362
+ const hasContent = label || description || icon;
363
+ const ContentWrapper = indicator ? CheckboxCard$1.Content : React.Fragment;
364
+ return (jsxs(CheckboxCard$1.Root, { ...rest, children: [jsx(CheckboxCard$1.HiddenInput, { ref: ref, ...inputProps }), jsxs(CheckboxCard$1.Control, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxs(ContentWrapper, { children: [icon, label && (jsx(CheckboxCard$1.Label, { children: label })), description && (jsx(CheckboxCard$1.Description, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsx(CheckboxCard$1.Addon, { children: addon })] }));
337
365
  });
366
+ CheckboxCard$1.Indicator;
338
367
 
339
368
  const TagFilter = ({ availableTags, selectedTags, onTagChange, selectOne = false, }) => {
340
- const toggleTag = (tag) => {
369
+ const handleTagChange = (tag, checked) => {
341
370
  if (selectOne) {
342
- if (selectedTags.includes(tag)) {
343
- onTagChange([]);
371
+ if (checked) {
372
+ onTagChange([tag]);
344
373
  }
345
374
  else {
346
- onTagChange([tag]);
375
+ onTagChange([]);
347
376
  }
348
377
  return;
349
378
  }
350
- if (selectedTags.includes(tag)) {
351
- onTagChange(selectedTags.filter((t) => t !== tag));
379
+ if (checked) {
380
+ onTagChange([...selectedTags, tag]);
352
381
  }
353
382
  else {
354
- onTagChange([...selectedTags, tag]);
383
+ onTagChange(selectedTags.filter((t) => t !== tag));
355
384
  }
356
385
  };
357
- return (jsx(Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => {
386
+ return (jsx(Flex, { flexFlow: 'wrap', p: '0.5rem', gap: '0.5rem', children: availableTags.map((tag) => {
358
387
  const { label, value } = tag;
359
- return (jsx(Tag, { variant: selectedTags.includes(value) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(value) ? true : undefined, onClick: () => toggleTag(value), children: label ?? value }));
388
+ const isChecked = selectedTags.includes(value);
389
+ return (jsx(CheckboxCard, { checked: isChecked, label: label ?? value, size: "sm", variant: isChecked ? 'solid' : 'outline', onCheckedChange: (details) => {
390
+ handleTagChange(value, Boolean(details.checked));
391
+ } }, value));
360
392
  }) }));
361
393
  };
362
394
 
@@ -366,21 +398,21 @@ const Filter = ({ column }) => {
366
398
  const displayName = column.columnDef.meta?.displayName ?? column.id;
367
399
  const filterOptions = column.columnDef.meta?.filterOptions ?? [];
368
400
  if (column.columns.length > 0) {
369
- return (jsxs(Flex, { flexFlow: "column", gap: 1, children: [jsx(Text, { children: displayName }), jsx(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(20rem, 1fr))", gap: 1, children: column.columns.map((column) => {
401
+ return (jsxs(Flex, { flexFlow: 'column', gap: 1, children: [jsx(Text, { children: displayName }), jsx(Grid, { gridTemplateColumns: 'repeat(auto-fit, minmax(20rem, 1fr))', gap: 1, children: column.columns.map((column) => {
370
402
  return jsx(Filter, { column: column }, column.id);
371
403
  }) }, column.id)] }));
372
404
  }
373
405
  if (!column.getCanFilter()) {
374
406
  return jsx(Fragment, {});
375
407
  }
376
- if (filterVariant === "select") {
377
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onValueChange: (details) => {
408
+ if (filterVariant === 'select') {
409
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : '', onValueChange: (details) => {
378
410
  column.setFilterValue(details.value);
379
- }, children: jsxs(Flex, { flexFlow: "wrap", gap: "0.5rem", children: [filterOptions.length === 0 && jsx(Text, { children: "No filter options" }), filterOptions.length > 0 &&
411
+ }, children: jsxs(Flex, { flexFlow: 'wrap', gap: '0.5rem', children: [filterOptions.length === 0 && jsx(Text, { children: "No filter options" }), filterOptions.length > 0 &&
380
412
  filterOptions.map((item) => (jsx(Radio, { value: item.value, children: item.label }, item.value)))] }) })] }, column.id));
381
413
  }
382
- if (filterVariant === "tag") {
383
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
414
+ if (filterVariant === 'tag') {
415
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
384
416
  label: item.label,
385
417
  value: item.value,
386
418
  })), selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
@@ -390,11 +422,11 @@ const Filter = ({ column }) => {
390
422
  column.setFilterValue(tags);
391
423
  } })] }, column.id));
392
424
  }
393
- if (filterVariant === "boolean") {
425
+ if (filterVariant === 'boolean') {
394
426
  const { trueLabel, falseLabel } = tableLabel;
395
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: [
396
- { label: trueLabel, value: "true" },
397
- { label: falseLabel, value: "false" },
427
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(TagFilter, { availableTags: [
428
+ { label: trueLabel, value: 'true' },
429
+ { label: falseLabel, value: 'false' },
398
430
  ], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
399
431
  if (tags.length === 0) {
400
432
  return column.setFilterValue(undefined);
@@ -402,7 +434,7 @@ const Filter = ({ column }) => {
402
434
  column.setFilterValue(tags);
403
435
  } })] }, column.id));
404
436
  }
405
- if (filterVariant === "range") {
437
+ if (filterVariant === 'range') {
406
438
  const filterValue = column.getFilterValue() ?? [
407
439
  undefined,
408
440
  undefined,
@@ -414,14 +446,14 @@ const Filter = ({ column }) => {
414
446
  step: 1,
415
447
  defaultValue: [4, 50],
416
448
  };
417
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RangeFilter, { range: filterValue, setRange: function (value) {
449
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RangeFilter, { range: filterValue, setRange: function (value) {
418
450
  // throw new Error("Function not implemented.");
419
451
  column.setFilterValue(value);
420
452
  }, defaultValue: defaultValue, min: min, max: max, step: step })] }, column.id));
421
453
  }
422
- if (filterVariant === "dateRange") {
454
+ if (filterVariant === 'dateRange') {
423
455
  const filterValue = column.getFilterValue() ?? [];
424
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RangeDatePicker, { selected: filterValue, onDateSelected: ({ selected, selectable, date }) => {
456
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(RangeDatePicker, { selected: filterValue, onDateSelected: ({ selected, selectable, date }) => {
425
457
  const newDates = getRangeDates({
426
458
  selectable,
427
459
  date,
@@ -432,14 +464,14 @@ const Filter = ({ column }) => {
432
464
  });
433
465
  } })] }, column.id));
434
466
  }
435
- if (filterVariant === "custom") {
467
+ if (filterVariant === 'custom') {
436
468
  const renderFilter = column.columnDef.meta?.renderFilter;
437
469
  if (renderFilter === undefined) {
438
- throw new Error("renderFilter is undefined");
470
+ throw new Error('renderFilter is undefined');
439
471
  }
440
472
  return jsx(Fragment, { children: renderFilter(column) });
441
473
  }
442
- return (jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(Input, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onChange: (e) => {
474
+ return (jsxs(Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsx(Text, { children: displayName }), jsx(Input, { value: column.getFilterValue() ? String(column.getFilterValue()) : '', onChange: (e) => {
443
475
  column.setFilterValue(e.target.value);
444
476
  } })] }, column.id));
445
477
  };
@@ -2584,21 +2616,13 @@ function draggable(args) {
2584
2616
 
2585
2617
  /** Arguments given to all monitor feedback functions (eg `canMonitor()`) for a `monitorForElements` */
2586
2618
 
2587
- const CheckboxCard = React.forwardRef(function CheckboxCard(props, ref) {
2588
- const { inputProps, label, description, icon, addon, indicator = jsx(CheckboxCard$1.Indicator, {}), indicatorPlacement = "end", ...rest } = props;
2589
- const hasContent = label || description || icon;
2590
- const ContentWrapper = indicator ? CheckboxCard$1.Content : React.Fragment;
2591
- return (jsxs(CheckboxCard$1.Root, { ...rest, children: [jsx(CheckboxCard$1.HiddenInput, { ref: ref, ...inputProps }), jsxs(CheckboxCard$1.Control, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxs(ContentWrapper, { children: [icon, label && (jsx(CheckboxCard$1.Label, { children: label })), description && (jsx(CheckboxCard$1.Description, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsx(CheckboxCard$1.Addon, { children: addon })] }));
2592
- });
2593
- CheckboxCard$1.Indicator;
2594
-
2595
2619
  function ColumnCard({ columnId }) {
2596
2620
  const ref = useRef(null);
2597
2621
  const [dragging, setDragging] = useState(false); // NEW
2598
- const { table, translate } = useDataTableContext();
2599
- const displayName = translate.t(columnId);
2622
+ const { table } = useDataTableContext();
2600
2623
  const column = table.getColumn(columnId);
2601
2624
  invariant(column);
2625
+ const displayName = column.columnDef.meta?.displayName ?? columnId;
2602
2626
  useEffect(() => {
2603
2627
  const el = ref.current;
2604
2628
  invariant(el);
@@ -2611,7 +2635,7 @@ function ColumnCard({ columnId }) {
2611
2635
  onDrop: () => setDragging(false), // NEW
2612
2636
  });
2613
2637
  }, [columnId, table]);
2614
- return (jsxs(Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsx(Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsx(FaGripLinesVertical, { color: "colorPalette.400" }) }), jsx(Flex, { justifyContent: "space-between", alignItems: "center", children: jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2638
+ return (jsxs(Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsx(Flex, { alignItems: "center", padding: "0", cursor: 'grab', children: jsx(FaGripLinesVertical, { color: "colorPalette.400" }) }), jsx(Flex, { justifyContent: "space-between", alignItems: "center", children: jsx(CheckboxCard, { variant: 'surface', label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2615
2639
  }
2616
2640
  function CardContainer({ location, children }) {
2617
2641
  const ref = useRef(null);
@@ -2633,9 +2657,9 @@ function CardContainer({ location, children }) {
2633
2657
  function getColor(isDraggedOver) {
2634
2658
  if (isDraggedOver) {
2635
2659
  return {
2636
- backgroundColor: "blue.400",
2660
+ backgroundColor: 'blue.400',
2637
2661
  _dark: {
2638
- backgroundColor: "blue.400",
2662
+ backgroundColor: 'blue.400',
2639
2663
  },
2640
2664
  };
2641
2665
  }
@@ -2667,7 +2691,7 @@ const TableViewer = () => {
2667
2691
  const sourceColumn = source.data.column;
2668
2692
  const columnOrder = order.map((id) => {
2669
2693
  if (id == sourceColumn.id) {
2670
- return "<marker>";
2694
+ return '<marker>';
2671
2695
  }
2672
2696
  return id;
2673
2697
  });
@@ -2677,12 +2701,12 @@ const TableViewer = () => {
2677
2701
  ...columnBefore,
2678
2702
  sourceColumn.id,
2679
2703
  ...columnAfter,
2680
- ].filter((id) => id != "<marker>");
2704
+ ].filter((id) => id != '<marker>');
2681
2705
  table.setColumnOrder(newOrder);
2682
2706
  },
2683
2707
  });
2684
2708
  }, [table]);
2685
- return (jsx(Flex, { flexFlow: "column", gap: "0.25rem", children: order.map((columnId, index) => {
2709
+ return (jsx(Flex, { flexFlow: 'column', gap: '0.25rem', children: order.map((columnId, index) => {
2686
2710
  return (jsx(CardContainer, { location: index, children: jsx(ColumnCard, { columnId: columnId }) }));
2687
2711
  }) }));
2688
2712
  };
@@ -2773,12 +2797,31 @@ const TableSelector = () => {
2773
2797
 
2774
2798
  const TableFilterTags = () => {
2775
2799
  const { table } = useDataTableContext();
2776
- return (jsx(Flex, { gap: "0.5rem", flexFlow: "wrap", children: table.getState().columnFilters.map(({ id, value }) => {
2777
- return (jsx(Tag, { gap: "0.5rem", closable: true, cursor: "pointer", onClick: () => {
2778
- table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
2779
- return filter.value != value;
2780
- }));
2781
- }, children: `${id}: ${value}` }, `${id}-${value}`));
2800
+ return (jsx(Flex, { gap: '0.5rem', flexFlow: 'wrap', children: table.getState().columnFilters.map(({ id, value }) => {
2801
+ const column = table.getColumn(id);
2802
+ const displayName = column?.columnDef.meta?.displayName ?? id;
2803
+ // Format the value for display
2804
+ const formatValue = (val) => {
2805
+ if (Array.isArray(val)) {
2806
+ return val.join(', ');
2807
+ }
2808
+ if (val === null || val === undefined) {
2809
+ return '';
2810
+ }
2811
+ return String(val);
2812
+ };
2813
+ const displayValue = formatValue(value);
2814
+ const label = displayValue
2815
+ ? `${displayName}: ${displayValue}`
2816
+ : displayName;
2817
+ return (jsx(CheckboxCard, { checked: true, label: label, size: "sm", variant: "outline", colorPalette: "blue", onCheckedChange: (details) => {
2818
+ if (!details.checked) {
2819
+ table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
2820
+ return (filter.id !== id ||
2821
+ JSON.stringify(filter.value) !== JSON.stringify(value));
2822
+ }));
2823
+ }
2824
+ } }, `${id}-${JSON.stringify(value)}`));
2782
2825
  }) }));
2783
2826
  };
2784
2827
 
@@ -3279,6 +3322,11 @@ const TextCell = ({ label, containerProps = {}, textProps = {}, children, }) =>
3279
3322
  return (jsx(Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsx(Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }));
3280
3323
  };
3281
3324
 
3325
+ const Tag = React.forwardRef(function Tag(props, ref) {
3326
+ const { startElement, endElement, onClose, closable = !!onClose, children, ...rest } = props;
3327
+ return (jsxs(Tag$1.Root, { ref: ref, ...rest, children: [startElement && (jsx(Tag$1.StartElement, { children: startElement })), jsx(Tag$1.Label, { children: children }), endElement && (jsx(Tag$1.EndElement, { children: endElement })), closable && (jsx(Tag$1.EndElement, { children: jsx(Tag$1.CloseTrigger, { onClick: onClose }) }))] }));
3328
+ });
3329
+
3282
3330
  const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
3283
3331
  if (!!row.original === false) {
3284
3332
  return jsx(Fragment, {});
@@ -4017,24 +4065,6 @@ let DatePicker$1 = class DatePicker extends React__default.Component {
4017
4065
  }
4018
4066
  };
4019
4067
 
4020
- const PopoverContent = React.forwardRef(function PopoverContent(props, ref) {
4021
- const { portalled = true, portalRef, ...rest } = props;
4022
- return (jsx(Portal, { disabled: !portalled, container: portalRef, children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { ref: ref, ...rest }) }) }));
4023
- });
4024
- React.forwardRef(function PopoverArrow(props, ref) {
4025
- return (jsx(Popover.Arrow, { ...props, ref: ref, children: jsx(Popover.ArrowTip, {}) }));
4026
- });
4027
- React.forwardRef(function PopoverCloseTrigger(props, ref) {
4028
- return (jsx(Popover.CloseTrigger, { position: "absolute", top: "1", insetEnd: "1", ...props, asChild: true, ref: ref, children: jsx(CloseButton, { size: "sm" }) }));
4029
- });
4030
- const PopoverTitle = Popover.Title;
4031
- Popover.Description;
4032
- Popover.Footer;
4033
- Popover.Header;
4034
- const PopoverRoot = Popover.Root;
4035
- const PopoverBody = Popover.Body;
4036
- const PopoverTrigger = Popover.Trigger;
4037
-
4038
4068
  /**
4039
4069
  * Custom hook to simplify i18n translation for form fields.
4040
4070
  * Automatically handles colLabel construction and removeIndex logic.
@@ -4103,7 +4133,7 @@ dayjs.extend(utc);
4103
4133
  dayjs.extend(timezone);
4104
4134
  const DatePicker = ({ column, schema, prefix }) => {
4105
4135
  const { watch, formState: { errors }, setValue, } = useFormContext();
4106
- const { timezone, dateTimePickerLabels } = useSchemaContext();
4136
+ const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
4107
4137
  const formI18n = useFormI18n(column, prefix);
4108
4138
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4109
4139
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4136,90 +4166,92 @@ const DatePicker = ({ column, schema, prefix }) => {
4136
4166
  console.error(e);
4137
4167
  }
4138
4168
  }, [selectedDate, dateFormat, colLabel, setValue]);
4169
+ const datePickerLabels = {
4170
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4171
+ formI18n.translate.t(`common.month_1`, {
4172
+ defaultValue: 'January',
4173
+ }),
4174
+ formI18n.translate.t(`common.month_2`, {
4175
+ defaultValue: 'February',
4176
+ }),
4177
+ formI18n.translate.t(`common.month_3`, {
4178
+ defaultValue: 'March',
4179
+ }),
4180
+ formI18n.translate.t(`common.month_4`, {
4181
+ defaultValue: 'April',
4182
+ }),
4183
+ formI18n.translate.t(`common.month_5`, {
4184
+ defaultValue: 'May',
4185
+ }),
4186
+ formI18n.translate.t(`common.month_6`, {
4187
+ defaultValue: 'June',
4188
+ }),
4189
+ formI18n.translate.t(`common.month_7`, {
4190
+ defaultValue: 'July',
4191
+ }),
4192
+ formI18n.translate.t(`common.month_8`, {
4193
+ defaultValue: 'August',
4194
+ }),
4195
+ formI18n.translate.t(`common.month_9`, {
4196
+ defaultValue: 'September',
4197
+ }),
4198
+ formI18n.translate.t(`common.month_10`, {
4199
+ defaultValue: 'October',
4200
+ }),
4201
+ formI18n.translate.t(`common.month_11`, {
4202
+ defaultValue: 'November',
4203
+ }),
4204
+ formI18n.translate.t(`common.month_12`, {
4205
+ defaultValue: 'December',
4206
+ }),
4207
+ ],
4208
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4209
+ formI18n.translate.t(`common.weekday_1`, {
4210
+ defaultValue: 'Sun',
4211
+ }),
4212
+ formI18n.translate.t(`common.weekday_2`, {
4213
+ defaultValue: 'Mon',
4214
+ }),
4215
+ formI18n.translate.t(`common.weekday_3`, {
4216
+ defaultValue: 'Tue',
4217
+ }),
4218
+ formI18n.translate.t(`common.weekday_4`, {
4219
+ defaultValue: 'Wed',
4220
+ }),
4221
+ formI18n.translate.t(`common.weekday_5`, {
4222
+ defaultValue: 'Thu',
4223
+ }),
4224
+ formI18n.translate.t(`common.weekday_6`, {
4225
+ defaultValue: 'Fri',
4226
+ }),
4227
+ formI18n.translate.t(`common.weekday_7`, {
4228
+ defaultValue: 'Sat',
4229
+ }),
4230
+ ],
4231
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4232
+ formI18n.translate.t(`common.back_button`, {
4233
+ defaultValue: 'Back',
4234
+ }),
4235
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4236
+ formI18n.translate.t(`common.forward_button`, {
4237
+ defaultValue: 'Forward',
4238
+ }),
4239
+ };
4240
+ const datePickerContent = (jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4241
+ setValue(colLabel, dayjs(date).format(dateFormat));
4242
+ setOpen(false);
4243
+ }, labels: datePickerLabels }));
4139
4244
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4140
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4245
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4141
4246
  setOpen(true);
4142
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4143
- setValue(colLabel, dayjs(date).format(dateFormat));
4144
- setOpen(false);
4145
- }, labels: {
4146
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4147
- formI18n.translate.t(`common.month_1`, {
4148
- defaultValue: 'January',
4149
- }),
4150
- formI18n.translate.t(`common.month_2`, {
4151
- defaultValue: 'February',
4152
- }),
4153
- formI18n.translate.t(`common.month_3`, {
4154
- defaultValue: 'March',
4155
- }),
4156
- formI18n.translate.t(`common.month_4`, {
4157
- defaultValue: 'April',
4158
- }),
4159
- formI18n.translate.t(`common.month_5`, {
4160
- defaultValue: 'May',
4161
- }),
4162
- formI18n.translate.t(`common.month_6`, {
4163
- defaultValue: 'June',
4164
- }),
4165
- formI18n.translate.t(`common.month_7`, {
4166
- defaultValue: 'July',
4167
- }),
4168
- formI18n.translate.t(`common.month_8`, {
4169
- defaultValue: 'August',
4170
- }),
4171
- formI18n.translate.t(`common.month_9`, {
4172
- defaultValue: 'September',
4173
- }),
4174
- formI18n.translate.t(`common.month_10`, {
4175
- defaultValue: 'October',
4176
- }),
4177
- formI18n.translate.t(`common.month_11`, {
4178
- defaultValue: 'November',
4179
- }),
4180
- formI18n.translate.t(`common.month_12`, {
4181
- defaultValue: 'December',
4182
- }),
4183
- ],
4184
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4185
- formI18n.translate.t(`common.weekday_1`, {
4186
- defaultValue: 'Sun',
4187
- }),
4188
- formI18n.translate.t(`common.weekday_2`, {
4189
- defaultValue: 'Mon',
4190
- }),
4191
- formI18n.translate.t(`common.weekday_3`, {
4192
- defaultValue: 'Tue',
4193
- }),
4194
- formI18n.translate.t(`common.weekday_4`, {
4195
- defaultValue: 'Wed',
4196
- }),
4197
- formI18n.translate.t(`common.weekday_5`, {
4198
- defaultValue: 'Thu',
4199
- }),
4200
- formI18n.translate.t(`common.weekday_6`, {
4201
- defaultValue: 'Fri',
4202
- }),
4203
- formI18n.translate.t(`common.weekday_7`, {
4204
- defaultValue: 'Sat',
4205
- }),
4206
- ],
4207
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4208
- formI18n.translate.t(`common.back_button`, {
4209
- defaultValue: 'Back',
4210
- }),
4211
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4212
- formI18n.translate.t(`common.forward_button`, {
4213
- defaultValue: 'Forward',
4214
- }),
4215
- } })] }) })] }) }));
4247
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) }) }))] }) }));
4216
4248
  };
4217
4249
 
4218
4250
  dayjs.extend(utc);
4219
4251
  dayjs.extend(timezone);
4220
4252
  const DateRangePicker = ({ column, schema, prefix, }) => {
4221
4253
  const { watch, formState: { errors }, setValue, } = useFormContext();
4222
- const { timezone, dateTimePickerLabels } = useSchemaContext();
4254
+ const { timezone, insideDialog } = useSchemaContext();
4223
4255
  const formI18n = useFormI18n(column, prefix);
4224
4256
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4225
4257
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4282,9 +4314,9 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4282
4314
  }
4283
4315
  }, [selectedDateRange, dateFormat, colLabel, setValue, timezone]);
4284
4316
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4285
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4317
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4286
4318
  setOpen(true);
4287
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), getDisplayText()] }) }), jsx(PopoverContent, { minW: '600px', children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selected, selectable, date }) => {
4319
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), getDisplayText()] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsx(Popover.Body, { children: jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selectable, date }) => {
4288
4320
  const newDates = getRangeDates({
4289
4321
  selectable,
4290
4322
  date,
@@ -4298,7 +4330,21 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4298
4330
  shouldValidate: true,
4299
4331
  shouldDirty: true,
4300
4332
  });
4301
- }, monthsToDisplay: 2 })] }) })] }) }));
4333
+ }, monthsToDisplay: 2, withPopover: false }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsx(Popover.Body, { children: jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selectable, date }) => {
4334
+ const newDates = getRangeDates({
4335
+ selectable,
4336
+ date,
4337
+ selectedDates,
4338
+ }) ?? [];
4339
+ // Convert Date[] to string[]
4340
+ const formattedDates = newDates
4341
+ .map((dateObj) => dayjs(dateObj).tz(timezone).format(dateFormat))
4342
+ .filter((dateStr) => dateStr);
4343
+ setValue(colLabel, formattedDates, {
4344
+ shouldValidate: true,
4345
+ shouldDirty: true,
4346
+ });
4347
+ }, monthsToDisplay: 2, withPopover: false }) }) }) }) }))] }) }));
4302
4348
  };
4303
4349
 
4304
4350
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
@@ -5692,134 +5738,310 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
5692
5738
  : undefined, invalid: !!fieldError, children: jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
5693
5739
  };
5694
5740
 
5695
- function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
5696
- am: "am",
5697
- pm: "pm",
5698
- }, onChange = (_newValue) => { }, timezone = "Asia/Hong_Kong", }) {
5741
+ dayjs.extend(utc);
5742
+ dayjs.extend(timezone);
5743
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
5744
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5745
+ meridiemLabel: _meridiemLabel = {
5746
+ am: 'am',
5747
+ pm: 'pm',
5748
+ },
5749
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5750
+ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedDate, }) {
5751
+ // Generate time options (every 15 minutes)
5752
+ const timeOptions = useMemo(() => {
5753
+ const options = [];
5754
+ const meridiemOptions = ['am', 'pm'];
5755
+ // Get start time for comparison if provided
5756
+ let startDateTime = null;
5757
+ let shouldFilterByDate = false;
5758
+ if (startTime && selectedDate) {
5759
+ const startDateObj = dayjs(startTime).tz(timezone);
5760
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5761
+ if (startDateObj.isValid() && selectedDateObj.isValid()) {
5762
+ startDateTime = startDateObj;
5763
+ // Only filter if dates are the same
5764
+ shouldFilterByDate =
5765
+ startDateObj.format('YYYY-MM-DD') ===
5766
+ selectedDateObj.format('YYYY-MM-DD');
5767
+ }
5768
+ }
5769
+ for (const mer of meridiemOptions) {
5770
+ for (let h = 1; h <= 12; h++) {
5771
+ for (let m = 0; m < 60; m += 15) {
5772
+ const hour24 = mer === 'am' ? (h === 12 ? 0 : h) : h === 12 ? 12 : h + 12;
5773
+ const timeStr = dayjs()
5774
+ .tz(timezone)
5775
+ .hour(hour24)
5776
+ .minute(m)
5777
+ .format('HH:mmZ');
5778
+ const displayTime = dayjs(`1970-01-01T${timeStr}`, 'HH:mmZ').format('hh:mm a');
5779
+ // Filter out times that would result in negative duration (only when dates are the same)
5780
+ if (startDateTime && selectedDate && shouldFilterByDate) {
5781
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5782
+ const optionDateTime = selectedDateObj
5783
+ .hour(hour24)
5784
+ .minute(m)
5785
+ .second(0)
5786
+ .millisecond(0);
5787
+ if (optionDateTime.isBefore(startDateTime)) {
5788
+ continue; // Skip this option as it would result in negative duration
5789
+ }
5790
+ }
5791
+ // Calculate and append duration if startTime is provided
5792
+ let label = displayTime;
5793
+ if (startDateTime && selectedDate) {
5794
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5795
+ const optionDateTime = selectedDateObj
5796
+ .hour(hour24)
5797
+ .minute(m)
5798
+ .second(0)
5799
+ .millisecond(0);
5800
+ if (optionDateTime.isValid() &&
5801
+ optionDateTime.isAfter(startDateTime)) {
5802
+ const diffMs = optionDateTime.diff(startDateTime);
5803
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
5804
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
5805
+ if (diffHours > 0 || diffMinutes > 0) {
5806
+ const diffText = diffHours > 0
5807
+ ? `${diffHours}h ${diffMinutes}m`
5808
+ : `${diffMinutes}m`;
5809
+ label = `${displayTime} (+${diffText})`;
5810
+ }
5811
+ }
5812
+ }
5813
+ options.push({
5814
+ label,
5815
+ value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
5816
+ hour: h,
5817
+ minute: m,
5818
+ meridiem: mer,
5819
+ searchText: displayTime, // Use base time without duration for searching
5820
+ });
5821
+ }
5822
+ }
5823
+ }
5824
+ return options;
5825
+ }, [timezone, startTime, selectedDate]);
5826
+ const { contains } = useFilter({ sensitivity: 'base' });
5827
+ const { collection, filter } = useListCollection({
5828
+ initialItems: timeOptions,
5829
+ itemToString: (item) => item.searchText, // Use searchText (without duration) for filtering
5830
+ itemToValue: (item) => item.value,
5831
+ filter: contains,
5832
+ });
5833
+ // Track input mode vs display mode
5834
+ const [isInputMode, setIsInputMode] = useState(false);
5835
+ const [inputValue, setInputValue] = useState('');
5836
+ const inputRef = useRef(null);
5837
+ // Switch to display mode when value is selected
5838
+ useEffect(() => {
5839
+ if (hour !== null && minute !== null && meridiem !== null) {
5840
+ setIsInputMode(false);
5841
+ }
5842
+ }, [hour, minute, meridiem]);
5843
+ // Focus input when switching to input mode
5844
+ useEffect(() => {
5845
+ if (isInputMode && inputRef.current) {
5846
+ inputRef.current.focus();
5847
+ }
5848
+ }, [isInputMode]);
5849
+ // Get current value string for combobox
5850
+ const currentValue = useMemo(() => {
5851
+ if (hour === null || minute === null || meridiem === null) {
5852
+ return '';
5853
+ }
5854
+ return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
5855
+ }, [hour, minute, meridiem]);
5856
+ // INPUT MODE: Show raw input text (no duration)
5857
+ const inputModeText = useMemo(() => {
5858
+ return inputValue;
5859
+ }, [inputValue]);
5860
+ // DISPLAY MODE: Show selected value with duration
5861
+ const displayModeText = useMemo(() => {
5862
+ if (hour === null || minute === null || meridiem === null) {
5863
+ return '';
5864
+ }
5865
+ const hour24 = meridiem === 'am'
5866
+ ? hour === 12
5867
+ ? 0
5868
+ : hour
5869
+ : hour === 12
5870
+ ? 12
5871
+ : hour + 12;
5872
+ const timeStr = dayjs()
5873
+ .tz(timezone)
5874
+ .hour(hour24)
5875
+ .minute(minute)
5876
+ .format('HH:mmZ');
5877
+ const timeDisplay = dayjs(`1970-01-01T${timeStr}`, 'HH:mmZ').format('hh:mm a');
5878
+ // Add duration if startTime is provided
5879
+ if (startTime && selectedDate) {
5880
+ const startDateObj = dayjs(startTime).tz(timezone);
5881
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5882
+ const currentDateTime = selectedDateObj
5883
+ .hour(hour24)
5884
+ .minute(minute)
5885
+ .second(0)
5886
+ .millisecond(0);
5887
+ if (startDateObj.isValid() && currentDateTime.isValid()) {
5888
+ const diffMs = currentDateTime.diff(startDateObj);
5889
+ if (diffMs >= 0) {
5890
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
5891
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
5892
+ if (diffHours > 0 || diffMinutes > 0) {
5893
+ const diffText = diffHours > 0
5894
+ ? `${diffHours}h ${diffMinutes}m`
5895
+ : `${diffMinutes}m`;
5896
+ return `${timeDisplay} (+${diffText})`;
5897
+ }
5898
+ }
5899
+ }
5900
+ }
5901
+ return timeDisplay;
5902
+ }, [hour, minute, meridiem, timezone, startTime, selectedDate]);
5903
+ // Choose text based on mode
5904
+ const displayText = isInputMode ? inputModeText : displayModeText;
5699
5905
  const handleClear = () => {
5700
5906
  setHour(null);
5701
5907
  setMinute(null);
5702
5908
  setMeridiem(null);
5703
- setInputValue("");
5704
- setShowInput(false);
5909
+ setIsInputMode(false);
5910
+ setInputValue('');
5911
+ filter(''); // Reset filter to show all options
5705
5912
  onChange({ hour: null, minute: null, meridiem: null });
5706
5913
  };
5707
- const getTimeString = (hour, minute, meridiem) => {
5708
- if (hour === null || minute === null || meridiem === null) {
5709
- return "";
5710
- }
5711
- // if the hour is 24, set the hour to 0
5712
- if (hour === 24) {
5713
- return dayjs().tz(timezone).hour(0).minute(minute).format("HH:mmZ");
5714
- }
5715
- // use dayjs to format the time at current timezone
5716
- // if meridiem is pm, add 12 hours
5717
- let newHour = hour;
5718
- if (meridiem === "pm" && hour !== 12) {
5719
- newHour = hour + 12;
5914
+ const handleValueChange = (details) => {
5915
+ if (details.value.length === 0) {
5916
+ handleClear();
5917
+ return;
5720
5918
  }
5721
- // if the hour is 12, set the meridiem to am, and set the hour to 0
5722
- else if (meridiem === "am" && hour === 12) {
5723
- newHour = 0;
5919
+ const selectedValue = details.value[0];
5920
+ const selectedOption = timeOptions.find((opt) => opt.value === selectedValue);
5921
+ if (selectedOption) {
5922
+ setHour(selectedOption.hour);
5923
+ setMinute(selectedOption.minute);
5924
+ setMeridiem(selectedOption.meridiem);
5925
+ setIsInputMode(false); // Switch to display mode
5926
+ setInputValue('');
5927
+ filter(''); // Reset filter after selection
5928
+ onChange({
5929
+ hour: selectedOption.hour,
5930
+ minute: selectedOption.minute,
5931
+ meridiem: selectedOption.meridiem,
5932
+ });
5724
5933
  }
5725
- return dayjs().tz(timezone).hour(newHour).minute(minute).format("HH:mmZ");
5726
5934
  };
5727
- const stringTime = getTimeString(hour, minute, meridiem);
5728
- const [inputValue, setInputValue] = useState("");
5729
- const [showInput, setShowInput] = useState(false);
5730
- const handleBlur = (text) => {
5731
- // ignore all non-numeric characters
5732
- if (!text) {
5733
- return;
5935
+ // Handle Enter key to select first filtered option
5936
+ const handleKeyDown = (e) => {
5937
+ if (e.key === 'Enter' && collection.items.length > 0) {
5938
+ e.preventDefault();
5939
+ const firstOption = collection.items[0];
5940
+ if (firstOption) {
5941
+ const selectedOption = timeOptions.find((opt) => opt.value === firstOption.value);
5942
+ if (selectedOption) {
5943
+ setHour(selectedOption.hour);
5944
+ setMinute(selectedOption.minute);
5945
+ setMeridiem(selectedOption.meridiem);
5946
+ setIsInputMode(false); // Switch to display mode
5947
+ setInputValue('');
5948
+ filter('');
5949
+ onChange({
5950
+ hour: selectedOption.hour,
5951
+ minute: selectedOption.minute,
5952
+ meridiem: selectedOption.meridiem,
5953
+ });
5954
+ }
5955
+ }
5734
5956
  }
5735
- const value = text.replace(/[^0-9apm]/g, "");
5736
- if (value === "") {
5737
- handleClear();
5957
+ };
5958
+ const handleInputValueChange = (details) => {
5959
+ const inputValue = details.inputValue.trim();
5960
+ setInputValue(inputValue);
5961
+ setIsInputMode(true); // Switch to input mode
5962
+ // Filter the collection based on input
5963
+ filter(inputValue);
5964
+ if (!inputValue) {
5965
+ setIsInputMode(false);
5738
5966
  return;
5739
5967
  }
5740
- // if the value is a valid time, parse it and set the hour, minute, and meridiem
5741
- // if the value is not a valid time, set the stringTime to the value
5742
- // first two characters are the hour
5743
- // next two characters are the minute
5744
- // final two characters are the meridiem
5745
- const hour = parseInt(value.slice(0, 2));
5746
- const minute = parseInt(value.slice(2, 4));
5747
- const meridiem = value.slice(4, 6);
5748
- // validate the hour and minute
5749
- if (isNaN(hour) || isNaN(minute)) {
5750
- setInputValue("");
5968
+ // Try to parse custom input using explicit regex patterns
5969
+ const normalized = inputValue.toLowerCase().replace(/\s+/g, '');
5970
+ // Pattern 1: 12-hour format with meridiem (e.g., "930pm", "1230am", "9:30pm", "12:30am")
5971
+ // Matches: 1-2 digits hour, optional colon, 2 digits minute, am/pm
5972
+ const pattern12HourWithMeridiem = /^(\d{1,2}):?(\d{2})(am|pm)$/;
5973
+ const match12Hour = normalized.match(pattern12HourWithMeridiem);
5974
+ if (match12Hour) {
5975
+ const parsedHour = parseInt(match12Hour[1], 10);
5976
+ const parsedMinute = parseInt(match12Hour[2], 10);
5977
+ const parsedMeridiem = match12Hour[3];
5978
+ // Validate hour (1-12)
5979
+ if (parsedHour < 1 || parsedHour > 12) {
5980
+ return;
5981
+ }
5982
+ // Validate minute (0-59)
5983
+ const validMinute = parsedMinute > 59 ? 0 : parsedMinute;
5984
+ setHour(parsedHour);
5985
+ setMinute(validMinute);
5986
+ setMeridiem(parsedMeridiem);
5987
+ onChange({
5988
+ hour: parsedHour,
5989
+ minute: validMinute,
5990
+ meridiem: parsedMeridiem,
5991
+ });
5751
5992
  return;
5752
5993
  }
5753
- // if the hour is larger than 24, set the hour to 24
5754
- if (hour > 24) {
5755
- setInputValue("");
5994
+ // Pattern 2: 24-hour format (e.g., "2130", "09:30", "21:30")
5995
+ // Matches: 1-2 digits hour, optional colon, 2 digits minute
5996
+ const pattern24Hour = /^(\d{2}):?(\d{2})$/;
5997
+ const match24Hour = normalized.match(pattern24Hour);
5998
+ if (match24Hour) {
5999
+ let parsedHour = parseInt(match24Hour[1], 10);
6000
+ const parsedMinute = parseInt(match24Hour[2], 10);
6001
+ // Validate hour (0-23)
6002
+ if (parsedHour > 23) {
6003
+ return;
6004
+ }
6005
+ // Convert 24-hour to 12-hour format
6006
+ let parsedMeridiem;
6007
+ if (parsedHour === 0) {
6008
+ parsedHour = 12;
6009
+ parsedMeridiem = 'am';
6010
+ }
6011
+ else if (parsedHour === 12) {
6012
+ parsedHour = 12;
6013
+ parsedMeridiem = 'pm';
6014
+ }
6015
+ else if (parsedHour > 12) {
6016
+ parsedHour = parsedHour - 12;
6017
+ parsedMeridiem = 'pm';
6018
+ }
6019
+ else {
6020
+ parsedMeridiem = 'am';
6021
+ }
6022
+ // Validate minute (0-59)
6023
+ const validMinute = parsedMinute > 59 ? 0 : parsedMinute;
6024
+ setHour(parsedHour);
6025
+ setMinute(validMinute);
6026
+ setMeridiem(parsedMeridiem);
6027
+ onChange({
6028
+ hour: parsedHour,
6029
+ minute: validMinute,
6030
+ meridiem: parsedMeridiem,
6031
+ });
5756
6032
  return;
5757
6033
  }
5758
- let newHour = hour;
5759
- let newMinute = minute;
5760
- let newMeridiem = meridiem;
5761
- // if the hour is 24, set the meridiem to am, and set the hour to 0
5762
- if (hour === 24) {
5763
- newMeridiem = "am";
5764
- newHour = 0;
5765
- }
5766
- // if the hour is greater than 12, set the meridiem to pm, and subtract 12 from the hour
5767
- else if (hour > 12) {
5768
- newMeridiem = "pm";
5769
- newHour = hour - 12;
5770
- }
5771
- // if the hour is 12, set the meridiem to pm, and set the hour to 12
5772
- else if (hour === 12) {
5773
- newMeridiem = "pm";
5774
- newHour = 12;
5775
- }
5776
- // if the hour is 0, set the meridiem to am, and set the hour to 12
5777
- else if (hour === 0) {
5778
- newMeridiem = "am";
5779
- newHour = 12;
5780
- }
5781
- else {
5782
- newMeridiem = meridiem ?? "am";
5783
- newHour = hour;
5784
- }
5785
- if (minute > 59) {
5786
- newMinute = 0;
5787
- }
5788
- else {
5789
- newMinute = minute;
5790
- }
5791
- onChange({
5792
- hour: newHour,
5793
- minute: newMinute,
5794
- meridiem: newMeridiem,
5795
- });
5796
- setShowInput(false);
5797
- };
5798
- const handleKeyDown = (e) => {
5799
- if (e.key === "Enter") {
5800
- handleBlur(e.currentTarget.value);
5801
- }
5802
6034
  };
5803
- const inputRef = useRef(null);
5804
- return (jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "200px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsx(Input, { onKeyDown: handleKeyDown, onChange: (e) => {
5805
- setInputValue(e.currentTarget.value);
5806
- }, onBlur: (e) => {
5807
- handleBlur(e.currentTarget.value);
5808
- }, onFocus: (e) => {
5809
- e.currentTarget.select();
5810
- }, value: inputValue, display: showInput ? undefined : "none", ref: inputRef }), jsxs(Button$1, { onClick: () => {
5811
- setShowInput(true);
5812
- setInputValue(dayjs(`1970-01-01T${getTimeString(hour, minute, meridiem)}`, "hh:mmZ").format("HH:mm"));
5813
- inputRef.current?.focus();
5814
- }, display: showInput ? "none" : "flex", alignItems: "center", justifyContent: "start", variant: "outline", gap: 2, children: [jsx(Icon, { size: "sm", children: jsx(BsClock, {}) }), jsx(Text, { fontSize: "sm", children: stringTime
5815
- ? dayjs(`1970-01-01T${stringTime}`, "hh:mmZ").format("hh:mm a")
5816
- : "" })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }));
6035
+ return (jsxs(Grid, { justifyContent: 'center', alignItems: 'center', templateColumns: '200px auto', gap: "2", width: "auto", minWidth: "250px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, width: "100%", children: [jsxs(Combobox.Control, { children: [isInputMode ? (jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { ref: inputRef, placeholder: "Select time", value: displayText, onKeyDown: handleKeyDown }) })) : (jsxs(Grid, { templateColumns: "auto 1fr auto", alignItems: "center", gap: 2, width: "100%", minHeight: "40px", px: 3, border: "1px solid", borderColor: "gray.200", borderRadius: "md", cursor: "pointer", onClick: () => setIsInputMode(true), children: [jsx(Icon, { children: jsx(BsClock, {}) }), jsx(Text, { fontSize: "sm", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: displayText || 'Select time' }), jsx(Combobox.Trigger, { onClick: (e) => {
6036
+ e.stopPropagation();
6037
+ setIsInputMode(true);
6038
+ } })] })), isInputMode && (jsxs(Combobox.IndicatorGroup, { children: [jsx(Combobox.ClearTrigger, {}), jsx(Combobox.Trigger, {})] }))] }), jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [item.label, jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }));
5817
6039
  }
5818
6040
 
5819
6041
  dayjs.extend(timezone);
5820
6042
  const TimePicker = ({ column, schema, prefix }) => {
5821
6043
  const { watch, formState: { errors }, setValue, } = useFormContext();
5822
- const { translate, timezone } = useSchemaContext();
6044
+ const { translate, timezone, insideDialog } = useSchemaContext();
5823
6045
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
5824
6046
  const isRequired = required?.some((columnId) => columnId === column);
5825
6047
  const colLabel = `${prefix}${column}`;
@@ -5882,153 +6104,305 @@ const TimePicker = ({ column, schema, prefix }) => {
5882
6104
  ? translate.t(removeIndex(`${colLabel}.field_required`))
5883
6105
  : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5884
6106
  setOpen(true);
5885
- }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
6107
+ }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5886
6108
  am: translate.t(`common.am`, { defaultValue: 'AM' }),
5887
6109
  pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
5888
- } }) }) }) })] }) }));
6110
+ } }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
6111
+ am: translate.t(`common.am`, { defaultValue: 'AM' }),
6112
+ pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
6113
+ } }) }) }) }) }))] }) }));
5889
6114
  };
5890
6115
 
5891
- function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
5892
- // Refs for focus management
5893
- const hourInputRef = useRef(null);
5894
- const minuteInputRef = useRef(null);
5895
- const secondInputRef = useRef(null);
5896
- // Centralized handler for key events, value changes, and focus management
5897
- const handleKeyDown = (e, field) => {
5898
- const input = e.target;
5899
- const value = input.value;
5900
- // Handle navigation between fields
5901
- if (e.key === "Tab") {
5902
- return;
5903
- }
5904
- if (e.key === ":" && field === "hour") {
5905
- e.preventDefault();
5906
- minuteInputRef.current?.focus();
5907
- return;
5908
- }
5909
- if (e.key === ":" && field === "minute") {
5910
- e.preventDefault();
5911
- secondInputRef.current?.focus();
5912
- return;
5913
- }
5914
- if (e.key === "Backspace" && value === "") {
5915
- e.preventDefault();
5916
- if (field === "minute") {
5917
- hourInputRef.current?.focus();
5918
- }
5919
- else if (field === "second") {
5920
- minuteInputRef.current?.focus();
6116
+ dayjs.extend(utc);
6117
+ dayjs.extend(timezone);
6118
+ function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6119
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6120
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', }) {
6121
+ // Generate time options (every 15 minutes, seconds always 0)
6122
+ const timeOptions = useMemo(() => {
6123
+ const options = [];
6124
+ // Get start time for comparison if provided
6125
+ let startDateTime = null;
6126
+ let shouldFilterByDate = false;
6127
+ if (startTime && selectedDate) {
6128
+ const startDateObj = dayjs(startTime).tz(timezone);
6129
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6130
+ if (startDateObj.isValid() && selectedDateObj.isValid()) {
6131
+ startDateTime = startDateObj;
6132
+ // Only filter if dates are the same
6133
+ shouldFilterByDate =
6134
+ startDateObj.format('YYYY-MM-DD') ===
6135
+ selectedDateObj.format('YYYY-MM-DD');
5921
6136
  }
5922
- return;
5923
6137
  }
5924
- // Handle number inputs
5925
- if (field === "hour") {
5926
- if (e.key.match(/^[0-9]$/)) {
5927
- const newValue = value + e.key;
5928
- const numValue = parseInt(newValue, 10);
5929
- if (numValue > 23) {
5930
- const digitValue = parseInt(e.key, 10);
5931
- setHour(digitValue);
5932
- onChange({ hour: digitValue, minute, second });
5933
- return;
6138
+ for (let h = 0; h < 24; h++) {
6139
+ for (let m = 0; m < 60; m += 15) {
6140
+ const timeDisplay = `${h.toString().padStart(2, '0')}:${m
6141
+ .toString()
6142
+ .padStart(2, '0')}:00`;
6143
+ // Filter out times that would result in negative duration (only when dates are the same)
6144
+ if (startDateTime && selectedDate && shouldFilterByDate) {
6145
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6146
+ const optionDateTime = selectedDateObj
6147
+ .hour(h)
6148
+ .minute(m)
6149
+ .second(0)
6150
+ .millisecond(0);
6151
+ if (optionDateTime.isBefore(startDateTime)) {
6152
+ continue; // Skip this option as it would result in negative duration
6153
+ }
5934
6154
  }
5935
- if (numValue >= 0 && numValue <= 23) {
5936
- setHour(numValue);
5937
- onChange({ hour: numValue, minute, second });
5938
- e.preventDefault();
5939
- minuteInputRef.current?.focus();
6155
+ // Calculate and append duration if startTime is provided
6156
+ let label = timeDisplay;
6157
+ if (startDateTime && selectedDate) {
6158
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6159
+ const optionDateTime = selectedDateObj
6160
+ .hour(h)
6161
+ .minute(m)
6162
+ .second(0)
6163
+ .millisecond(0);
6164
+ if (optionDateTime.isValid() &&
6165
+ optionDateTime.isAfter(startDateTime)) {
6166
+ const diffMs = optionDateTime.diff(startDateTime);
6167
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
6168
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
6169
+ const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000);
6170
+ if (diffHours > 0 || diffMinutes > 0 || diffSeconds > 0) {
6171
+ let diffText = '';
6172
+ if (diffHours > 0) {
6173
+ diffText = `${diffHours}h ${diffMinutes}m`;
6174
+ }
6175
+ else if (diffMinutes > 0) {
6176
+ diffText = `${diffMinutes}m ${diffSeconds}s`;
6177
+ }
6178
+ else {
6179
+ diffText = `${diffSeconds}s`;
6180
+ }
6181
+ label = `${timeDisplay} (+${diffText})`;
6182
+ }
6183
+ }
5940
6184
  }
6185
+ options.push({
6186
+ label,
6187
+ value: `${h}:${m}:0`,
6188
+ hour: h,
6189
+ minute: m,
6190
+ second: 0,
6191
+ searchText: timeDisplay, // Use base time without duration for searching
6192
+ });
5941
6193
  }
5942
6194
  }
5943
- else if (field === "minute") {
5944
- if (e.key.match(/^[0-9]$/)) {
5945
- const newValue = value + e.key;
5946
- const numValue = parseInt(newValue, 10);
5947
- if (numValue > 59) {
5948
- const digitValue = parseInt(e.key, 10);
5949
- setMinute(digitValue);
5950
- onChange({ hour, minute: digitValue, second });
5951
- return;
5952
- }
5953
- if (numValue >= 0 && numValue <= 59) {
5954
- setMinute(numValue);
5955
- onChange({ hour, minute: numValue, second });
5956
- e.preventDefault();
5957
- secondInputRef.current?.focus();
5958
- }
5959
- }
6195
+ return options;
6196
+ }, [startTime, selectedDate, timezone]);
6197
+ const { contains } = useFilter({ sensitivity: 'base' });
6198
+ const { collection, filter } = useListCollection({
6199
+ initialItems: timeOptions,
6200
+ itemToString: (item) => item.searchText, // Use searchText (without duration) for filtering
6201
+ itemToValue: (item) => item.value,
6202
+ filter: contains,
6203
+ });
6204
+ // Get current value string for combobox
6205
+ const currentValue = useMemo(() => {
6206
+ if (hour === null || minute === null || second === null) {
6207
+ return '';
5960
6208
  }
5961
- else if (field === "second") {
5962
- if (e.key.match(/^[0-9]$/)) {
5963
- const newValue = value + e.key;
5964
- const numValue = parseInt(newValue, 10);
5965
- if (numValue > 59) {
5966
- const digitValue = parseInt(e.key, 10);
5967
- setSecond(digitValue);
5968
- onChange({ hour, minute, second: digitValue });
5969
- return;
5970
- }
5971
- if (numValue >= 0 && numValue <= 59) {
5972
- setSecond(numValue);
5973
- onChange({ hour, minute, second: numValue });
6209
+ return `${hour}:${minute}:${second}`;
6210
+ }, [hour, minute, second]);
6211
+ // Get display text for combobox
6212
+ const displayText = useMemo(() => {
6213
+ if (hour === null || minute === null || second === null) {
6214
+ return '';
6215
+ }
6216
+ const timeDisplay = `${hour.toString().padStart(2, '0')}:${minute
6217
+ .toString()
6218
+ .padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
6219
+ // Show duration difference if startTime is provided
6220
+ if (startTime && selectedDate) {
6221
+ const startDateObj = dayjs(startTime).tz(timezone);
6222
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6223
+ const currentDateTime = selectedDateObj
6224
+ .hour(hour)
6225
+ .minute(minute)
6226
+ .second(second ?? 0)
6227
+ .millisecond(0);
6228
+ if (startDateObj.isValid() && currentDateTime.isValid()) {
6229
+ const diffMs = currentDateTime.diff(startDateObj);
6230
+ if (diffMs >= 0) {
6231
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
6232
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
6233
+ const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000);
6234
+ if (diffHours > 0 || diffMinutes > 0 || diffSeconds > 0) {
6235
+ let diffText = '';
6236
+ if (diffHours > 0) {
6237
+ diffText = `${diffHours}h ${diffMinutes}m`;
6238
+ }
6239
+ else if (diffMinutes > 0) {
6240
+ diffText = `${diffMinutes}m ${diffSeconds}s`;
6241
+ }
6242
+ else {
6243
+ diffText = `${diffSeconds}s`;
6244
+ }
6245
+ return `${timeDisplay} (+${diffText})`;
6246
+ }
5974
6247
  }
5975
6248
  }
5976
6249
  }
5977
- };
6250
+ return timeDisplay;
6251
+ }, [hour, minute, second, startTime, selectedDate, timezone]);
5978
6252
  const handleClear = () => {
5979
6253
  setHour(null);
5980
6254
  setMinute(null);
5981
6255
  setSecond(null);
6256
+ filter(''); // Reset filter to show all options
5982
6257
  onChange({ hour: null, minute: null, second: null });
5983
- hourInputRef.current?.focus();
5984
6258
  };
5985
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 10px 60px auto", gap: "2", width: "auto", minWidth: "300px", children: [jsx(Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: secondInputRef, type: "text", value: second === null ? "" : second.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "second"), placeholder: "SS", maxLength: 2, textAlign: "center" }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }) }));
6259
+ const handleValueChange = (details) => {
6260
+ if (details.value.length === 0) {
6261
+ handleClear();
6262
+ return;
6263
+ }
6264
+ const selectedValue = details.value[0];
6265
+ const selectedOption = timeOptions.find((opt) => opt.value === selectedValue);
6266
+ if (selectedOption) {
6267
+ setHour(selectedOption.hour);
6268
+ setMinute(selectedOption.minute);
6269
+ setSecond(selectedOption.second);
6270
+ filter(''); // Reset filter after selection
6271
+ onChange({
6272
+ hour: selectedOption.hour,
6273
+ minute: selectedOption.minute,
6274
+ second: selectedOption.second,
6275
+ });
6276
+ }
6277
+ };
6278
+ const handleInputValueChange = (details) => {
6279
+ const inputValue = details.inputValue.trim();
6280
+ // Filter the collection based on input
6281
+ filter(inputValue);
6282
+ if (!inputValue) {
6283
+ return;
6284
+ }
6285
+ // Parse HH:mm:ss or HH:mm format
6286
+ const timePattern = /^(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/;
6287
+ const match = inputValue.match(timePattern);
6288
+ if (match) {
6289
+ const parsedHour = parseInt(match[1], 10);
6290
+ const parsedMinute = parseInt(match[2], 10);
6291
+ const parsedSecond = match[3] ? parseInt(match[3], 10) : 0;
6292
+ // Validate ranges
6293
+ if (parsedHour >= 0 &&
6294
+ parsedHour <= 23 &&
6295
+ parsedMinute >= 0 &&
6296
+ parsedMinute <= 59 &&
6297
+ parsedSecond >= 0 &&
6298
+ parsedSecond <= 59) {
6299
+ setHour(parsedHour);
6300
+ setMinute(parsedMinute);
6301
+ setSecond(parsedSecond);
6302
+ onChange({
6303
+ hour: parsedHour,
6304
+ minute: parsedMinute,
6305
+ second: parsedSecond,
6306
+ });
6307
+ }
6308
+ }
6309
+ else {
6310
+ // Try to parse formats like "123045" (HHmmss) or "1230" (HHmm)
6311
+ const numbersOnly = inputValue.replace(/[^0-9]/g, '');
6312
+ if (numbersOnly.length >= 4) {
6313
+ const parsedHour = parseInt(numbersOnly.slice(0, 2), 10);
6314
+ const parsedMinute = parseInt(numbersOnly.slice(2, 4), 10);
6315
+ const parsedSecond = numbersOnly.length >= 6 ? parseInt(numbersOnly.slice(4, 6), 10) : 0;
6316
+ // Validate ranges
6317
+ if (parsedHour >= 0 &&
6318
+ parsedHour <= 23 &&
6319
+ parsedMinute >= 0 &&
6320
+ parsedMinute <= 59 &&
6321
+ parsedSecond >= 0 &&
6322
+ parsedSecond <= 59) {
6323
+ setHour(parsedHour);
6324
+ setMinute(parsedMinute);
6325
+ setSecond(parsedSecond);
6326
+ onChange({
6327
+ hour: parsedHour,
6328
+ minute: parsedMinute,
6329
+ second: parsedSecond,
6330
+ });
6331
+ }
6332
+ }
6333
+ }
6334
+ };
6335
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Grid, { justifyContent: 'center', alignItems: 'center', templateColumns: '1fr auto', gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, width: "100%", children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: "HH:mm:ss", value: displayText }) }), jsxs(Combobox.IndicatorGroup, { children: [jsx(Combobox.ClearTrigger, {}), jsx(Combobox.Trigger, {})] })] }), jsx(Portal, { children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [item.label, jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
5986
6336
  }
5987
6337
 
5988
- function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds = false, labels = {
6338
+ dayjs.extend(utc);
6339
+ dayjs.extend(timezone);
6340
+ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds = false, labels = {
5989
6341
  monthNamesShort: [
5990
- "Jan",
5991
- "Feb",
5992
- "Mar",
5993
- "Apr",
5994
- "May",
5995
- "Jun",
5996
- "Jul",
5997
- "Aug",
5998
- "Sep",
5999
- "Oct",
6000
- "Nov",
6001
- "Dec",
6342
+ 'Jan',
6343
+ 'Feb',
6344
+ 'Mar',
6345
+ 'Apr',
6346
+ 'May',
6347
+ 'Jun',
6348
+ 'Jul',
6349
+ 'Aug',
6350
+ 'Sep',
6351
+ 'Oct',
6352
+ 'Nov',
6353
+ 'Dec',
6002
6354
  ],
6003
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
6004
- backButtonLabel: "Back",
6005
- forwardButtonLabel: "Next",
6006
- }, timezone = "Asia/Hong_Kong", }) {
6007
- const [selectedDate, setSelectedDate] = useState(value || "");
6355
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6356
+ backButtonLabel: 'Back',
6357
+ forwardButtonLabel: 'Next',
6358
+ }, timezone = 'Asia/Hong_Kong', startTime, }) {
6359
+ const [selectedDate, setSelectedDate] = useState(value || '');
6008
6360
  // Time state for 12-hour format
6009
6361
  const [hour12, setHour12] = useState(value ? dayjs(value).hour() % 12 || 12 : null);
6010
6362
  const [minute, setMinute] = useState(value ? dayjs(value).minute() : null);
6011
- const [meridiem, setMeridiem] = useState(value ? (dayjs(value).hour() >= 12 ? "pm" : "am") : null);
6363
+ const [meridiem, setMeridiem] = useState(value ? (dayjs(value).hour() >= 12 ? 'pm' : 'am') : null);
6012
6364
  // Time state for 24-hour format
6013
6365
  const [hour24, setHour24] = useState(value ? dayjs(value).hour() : null);
6014
- const [second, setSecond] = useState(value ? dayjs(value).second() : null);
6366
+ const [second, setSecond] = useState(showSeconds && value ? dayjs(value).second() : null);
6015
6367
  const handleDateChange = (date) => {
6016
6368
  setSelectedDate(date);
6017
- updateDateTime(dayjs(date).tz(timezone).toISOString());
6369
+ // When showSeconds is false, ignore seconds from the date
6370
+ const dateObj = dayjs(date).tz(timezone);
6371
+ if (!showSeconds && dateObj.isValid()) {
6372
+ const dateWithoutSeconds = dateObj.second(0).millisecond(0).toISOString();
6373
+ updateDateTime(dateWithoutSeconds);
6374
+ }
6375
+ else {
6376
+ updateDateTime(dateObj.toISOString());
6377
+ }
6018
6378
  };
6019
6379
  const handleTimeChange = (timeData) => {
6020
- if (format === "iso-date-time") {
6021
- setHour24(timeData.hour);
6022
- setMinute(timeData.minute);
6023
- if (showSeconds)
6024
- setSecond(timeData.second);
6380
+ if (format === 'iso-date-time') {
6381
+ const data = timeData;
6382
+ setHour24(data.hour);
6383
+ setMinute(data.minute);
6384
+ if (showSeconds) {
6385
+ setSecond(data.second ?? null);
6386
+ }
6387
+ else {
6388
+ // Ignore seconds - always set to null when showSeconds is false
6389
+ setSecond(null);
6390
+ }
6025
6391
  }
6026
6392
  else {
6027
- setHour12(timeData.hour);
6028
- setMinute(timeData.minute);
6029
- setMeridiem(timeData.meridiem);
6393
+ const data = timeData;
6394
+ setHour12(data.hour);
6395
+ setMinute(data.minute);
6396
+ setMeridiem(data.meridiem);
6397
+ }
6398
+ // Use selectedDate if valid, otherwise use today's date as fallback
6399
+ const dateToUse = selectedDate && dayjs(selectedDate).isValid()
6400
+ ? selectedDate
6401
+ : dayjs().tz(timezone).toISOString();
6402
+ const dateObj = dayjs(dateToUse).tz(timezone);
6403
+ if (dateObj.isValid()) {
6404
+ updateDateTime(dateObj.toISOString(), timeData);
6030
6405
  }
6031
- updateDateTime(dayjs(selectedDate).tz(timezone).toISOString(), timeData);
6032
6406
  };
6033
6407
  const updateDateTime = (date, timeData) => {
6034
6408
  if (!date) {
@@ -6036,27 +6410,33 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6036
6410
  return;
6037
6411
  }
6038
6412
  // use dayjs to convert the date to the timezone
6039
- const newDate = dayjs(date).tz(timezone).toDate();
6040
- if (format === "iso-date-time") {
6041
- const h = timeData?.hour ?? hour24;
6042
- const m = timeData?.minute ?? minute;
6043
- const s = showSeconds ? timeData?.second ?? second : 0;
6413
+ const dateObj = dayjs(date).tz(timezone);
6414
+ if (!dateObj.isValid()) {
6415
+ return;
6416
+ }
6417
+ const newDate = dateObj.toDate();
6418
+ if (format === 'iso-date-time') {
6419
+ const data = timeData;
6420
+ const h = data?.hour ?? hour24;
6421
+ const m = data?.minute ?? minute;
6422
+ // Always ignore seconds when showSeconds is false - set to 0
6423
+ const s = showSeconds ? data?.second ?? second ?? 0 : 0;
6044
6424
  if (h !== null)
6045
6425
  newDate.setHours(h);
6046
6426
  if (m !== null)
6047
6427
  newDate.setMinutes(m);
6048
- if (s !== null)
6049
- newDate.setSeconds(s);
6428
+ newDate.setSeconds(s);
6050
6429
  }
6051
6430
  else {
6052
- const h = timeData?.hour ?? hour12;
6053
- const m = timeData?.minute ?? minute;
6054
- const mer = timeData?.meridiem ?? meridiem;
6431
+ const data = timeData;
6432
+ const h = data?.hour ?? hour12;
6433
+ const m = data?.minute ?? minute;
6434
+ const mer = data?.meridiem ?? meridiem;
6055
6435
  if (h !== null && mer !== null) {
6056
6436
  let hour24 = h;
6057
- if (mer === "am" && h === 12)
6437
+ if (mer === 'am' && h === 12)
6058
6438
  hour24 = 0;
6059
- else if (mer === "pm" && h < 12)
6439
+ else if (mer === 'pm' && h < 12)
6060
6440
  hour24 = h + 12;
6061
6441
  newDate.setHours(hour24);
6062
6442
  }
@@ -6067,7 +6447,7 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6067
6447
  onChange?.(dayjs(newDate).tz(timezone).toISOString());
6068
6448
  };
6069
6449
  const handleClear = () => {
6070
- setSelectedDate("");
6450
+ setSelectedDate('');
6071
6451
  setHour12(null);
6072
6452
  setHour24(null);
6073
6453
  setMinute(null);
@@ -6075,21 +6455,26 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6075
6455
  setMeridiem(null);
6076
6456
  onChange?.(undefined);
6077
6457
  };
6078
- const isISO = format === "iso-date-time";
6079
- return (jsxs(Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsx(DatePicker$1, { selected: selectedDate
6080
- ? dayjs(selectedDate).tz(timezone).toDate()
6081
- : new Date(), onDateSelected: ({ date }) => handleDateChange(dayjs(date).tz(timezone).toISOString()), monthsToDisplay: 1, labels: labels }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: second, setSecond: setSecond, onChange: handleTimeChange })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), selectedDate && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).format(isISO
6458
+ const isISO = format === 'iso-date-time';
6459
+ // Normalize startTime to ignore milliseconds
6460
+ const normalizedStartTime = startTime
6461
+ ? dayjs(startTime).tz(timezone).millisecond(0).toISOString()
6462
+ : undefined;
6463
+ return (jsxs(Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsx(DatePicker$1, { selected: selectedDate ? dayjs(selectedDate).tz(timezone).toDate() : new Date(), onDateSelected: ({ date }) => handleDateChange(dayjs(date).tz(timezone).toISOString()), monthsToDisplay: 1, labels: labels, minDate: normalizedStartTime &&
6464
+ dayjs(normalizedStartTime).tz(timezone).isValid()
6465
+ ? dayjs(normalizedStartTime).tz(timezone).startOf('day').toDate()
6466
+ : undefined }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), selectedDate && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: dayjs(value).format(isISO
6082
6467
  ? showSeconds
6083
- ? "YYYY-MM-DD HH:mm:ss"
6084
- : "YYYY-MM-DD HH:mm"
6085
- : "YYYY-MM-DD hh:mm A ") }), jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).tz(timezone).format("Z") }), jsx(Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: timezone })] }))] }));
6468
+ ? 'YYYY-MM-DD HH:mm:ss'
6469
+ : 'YYYY-MM-DD HH:mm'
6470
+ : 'YYYY-MM-DD hh:mm A ') }), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: dayjs(value).tz(timezone).format('Z') }), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
6086
6471
  }
6087
6472
 
6088
6473
  dayjs.extend(utc);
6089
6474
  dayjs.extend(timezone);
6090
6475
  const DateTimePicker = ({ column, schema, prefix, }) => {
6091
6476
  const { watch, formState: { errors }, setValue, } = useFormContext();
6092
- const { timezone, dateTimePickerLabels } = useSchemaContext();
6477
+ const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
6093
6478
  const formI18n = useFormI18n(column, prefix);
6094
6479
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
6095
6480
  // with timezone
@@ -6124,82 +6509,84 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
6124
6509
  console.error(e);
6125
6510
  }
6126
6511
  }, [selectedDate, dateFormat, colLabel, setValue]);
6512
+ const dateTimePickerLabelsConfig = {
6513
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
6514
+ formI18n.translate.t(`common.month_1`, {
6515
+ defaultValue: 'January',
6516
+ }),
6517
+ formI18n.translate.t(`common.month_2`, {
6518
+ defaultValue: 'February',
6519
+ }),
6520
+ formI18n.translate.t(`common.month_3`, {
6521
+ defaultValue: 'March',
6522
+ }),
6523
+ formI18n.translate.t(`common.month_4`, {
6524
+ defaultValue: 'April',
6525
+ }),
6526
+ formI18n.translate.t(`common.month_5`, {
6527
+ defaultValue: 'May',
6528
+ }),
6529
+ formI18n.translate.t(`common.month_6`, {
6530
+ defaultValue: 'June',
6531
+ }),
6532
+ formI18n.translate.t(`common.month_7`, {
6533
+ defaultValue: 'July',
6534
+ }),
6535
+ formI18n.translate.t(`common.month_8`, {
6536
+ defaultValue: 'August',
6537
+ }),
6538
+ formI18n.translate.t(`common.month_9`, {
6539
+ defaultValue: 'September',
6540
+ }),
6541
+ formI18n.translate.t(`common.month_10`, {
6542
+ defaultValue: 'October',
6543
+ }),
6544
+ formI18n.translate.t(`common.month_11`, {
6545
+ defaultValue: 'November',
6546
+ }),
6547
+ formI18n.translate.t(`common.month_12`, {
6548
+ defaultValue: 'December',
6549
+ }),
6550
+ ],
6551
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
6552
+ formI18n.translate.t(`common.weekday_1`, {
6553
+ defaultValue: 'Sun',
6554
+ }),
6555
+ formI18n.translate.t(`common.weekday_2`, {
6556
+ defaultValue: 'Mon',
6557
+ }),
6558
+ formI18n.translate.t(`common.weekday_3`, {
6559
+ defaultValue: 'Tue',
6560
+ }),
6561
+ formI18n.translate.t(`common.weekday_4`, {
6562
+ defaultValue: 'Wed',
6563
+ }),
6564
+ formI18n.translate.t(`common.weekday_5`, {
6565
+ defaultValue: 'Thu',
6566
+ }),
6567
+ formI18n.translate.t(`common.weekday_6`, {
6568
+ defaultValue: 'Fri',
6569
+ }),
6570
+ formI18n.translate.t(`common.weekday_7`, {
6571
+ defaultValue: 'Sat',
6572
+ }),
6573
+ ],
6574
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
6575
+ formI18n.translate.t(`common.back_button`, {
6576
+ defaultValue: 'Back',
6577
+ }),
6578
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
6579
+ formI18n.translate.t(`common.forward_button`, {
6580
+ defaultValue: 'Forward',
6581
+ }),
6582
+ };
6583
+ const dateTimePickerContent = (jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
6584
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
6585
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
6127
6586
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6128
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6587
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6129
6588
  setOpen(true);
6130
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsx(PopoverContent, { minW: '450px', children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
6131
- setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
6132
- }, timezone: timezone, labels: {
6133
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
6134
- formI18n.translate.t(`common.month_1`, {
6135
- defaultValue: 'January',
6136
- }),
6137
- formI18n.translate.t(`common.month_2`, {
6138
- defaultValue: 'February',
6139
- }),
6140
- formI18n.translate.t(`common.month_3`, {
6141
- defaultValue: 'March',
6142
- }),
6143
- formI18n.translate.t(`common.month_4`, {
6144
- defaultValue: 'April',
6145
- }),
6146
- formI18n.translate.t(`common.month_5`, {
6147
- defaultValue: 'May',
6148
- }),
6149
- formI18n.translate.t(`common.month_6`, {
6150
- defaultValue: 'June',
6151
- }),
6152
- formI18n.translate.t(`common.month_7`, {
6153
- defaultValue: 'July',
6154
- }),
6155
- formI18n.translate.t(`common.month_8`, {
6156
- defaultValue: 'August',
6157
- }),
6158
- formI18n.translate.t(`common.month_9`, {
6159
- defaultValue: 'September',
6160
- }),
6161
- formI18n.translate.t(`common.month_10`, {
6162
- defaultValue: 'October',
6163
- }),
6164
- formI18n.translate.t(`common.month_11`, {
6165
- defaultValue: 'November',
6166
- }),
6167
- formI18n.translate.t(`common.month_12`, {
6168
- defaultValue: 'December',
6169
- }),
6170
- ],
6171
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
6172
- formI18n.translate.t(`common.weekday_1`, {
6173
- defaultValue: 'Sun',
6174
- }),
6175
- formI18n.translate.t(`common.weekday_2`, {
6176
- defaultValue: 'Mon',
6177
- }),
6178
- formI18n.translate.t(`common.weekday_3`, {
6179
- defaultValue: 'Tue',
6180
- }),
6181
- formI18n.translate.t(`common.weekday_4`, {
6182
- defaultValue: 'Wed',
6183
- }),
6184
- formI18n.translate.t(`common.weekday_5`, {
6185
- defaultValue: 'Thu',
6186
- }),
6187
- formI18n.translate.t(`common.weekday_6`, {
6188
- defaultValue: 'Fri',
6189
- }),
6190
- formI18n.translate.t(`common.weekday_7`, {
6191
- defaultValue: 'Sat',
6192
- }),
6193
- ],
6194
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
6195
- formI18n.translate.t(`common.back_button`, {
6196
- defaultValue: 'Back',
6197
- }),
6198
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
6199
- formI18n.translate.t(`common.forward_button`, {
6200
- defaultValue: 'Forward',
6201
- }),
6202
- } })] }) })] }) }));
6589
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) }) }))] }) }));
6203
6590
  };
6204
6591
 
6205
6592
  const SchemaRenderer = ({ schema, prefix, column, }) => {
@@ -7110,7 +7497,7 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
7110
7497
  };
7111
7498
 
7112
7499
  const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7113
- const { columns, translate, data } = useDataTableContext();
7500
+ const { columns, data } = useDataTableContext();
7114
7501
  const columnsMap = Object.fromEntries(columns.map((def) => {
7115
7502
  const { accessorKey, id } = def;
7116
7503
  if (accessorKey) {
@@ -7124,7 +7511,7 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7124
7511
  if (!!size === false) {
7125
7512
  return 0;
7126
7513
  }
7127
- if (typeof size === "number") {
7514
+ if (typeof size === 'number') {
7128
7515
  return size;
7129
7516
  }
7130
7517
  return 0;
@@ -7133,39 +7520,40 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7133
7520
  const columnWidths = columns
7134
7521
  .map(({ size }) => {
7135
7522
  if (!!size === false) {
7136
- return "1fr";
7523
+ return '1fr';
7137
7524
  }
7138
7525
  return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
7139
7526
  })
7140
- .join(" ");
7141
- console.log({ columnWidths }, "hadfg");
7527
+ .join(' ');
7528
+ console.log({ columnWidths }, 'hadfg');
7142
7529
  const cellProps = {
7143
- flex: "1 0 0%",
7144
- overflow: "auto",
7145
- paddingX: "2",
7146
- py: "1",
7147
- color: { base: "colorPalette.900", _dark: "colorPalette.100" },
7148
- bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
7149
- borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
7150
- borderBottomWidth: "1px",
7530
+ flex: '1 0 0%',
7531
+ overflow: 'auto',
7532
+ paddingX: '2',
7533
+ py: '1',
7534
+ color: { base: 'colorPalette.900', _dark: 'colorPalette.100' },
7535
+ bgColor: { base: 'colorPalette.50', _dark: 'colorPalette.950' },
7536
+ borderBottomColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' },
7537
+ borderBottomWidth: '1px',
7151
7538
  ...{ colorPalette },
7152
7539
  };
7153
7540
  if (data.length <= 0) {
7154
7541
  return jsx(Fragment, { children: emptyComponent });
7155
7542
  }
7156
- return (jsxs(Grid, { templateColumns: `${columnWidths}`, overflow: "auto", borderWidth: "1px", color: { base: "colorPalette.900", _dark: "colorPalette.100" }, borderColor: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: [jsx(Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: columnHeaders.map((header) => {
7157
- return (jsx(Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
7543
+ return (jsxs(Grid, { templateColumns: `${columnWidths}`, overflow: 'auto', borderWidth: '1px', color: { base: 'colorPalette.900', _dark: 'colorPalette.100' }, borderColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: [jsx(Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: columnHeaders.map((header) => {
7544
+ const columnDef = columnsMap[header];
7545
+ return (jsx(Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }));
7158
7546
  }) }), data.map((record) => {
7159
7547
  return (jsx(Fragment, { children: columnHeaders.map((header) => {
7160
7548
  const { cell } = columnsMap[header];
7161
7549
  const value = record[header];
7162
7550
  if (!!record === false) {
7163
- return (jsx(Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
7551
+ return (jsx(Box, { ...cellProps }));
7164
7552
  }
7165
7553
  if (cell) {
7166
7554
  return (jsx(Box, { ...cellProps, children: cell({ row: { original: record } }) }));
7167
7555
  }
7168
- if (typeof value === "object") {
7556
+ if (typeof value === 'object') {
7169
7557
  return (jsx(Box, { ...cellProps, children: jsx(RecordDisplay, { object: value }) }));
7170
7558
  }
7171
7559
  return jsx(Box, { ...cellProps, children: value });
@@ -7272,63 +7660,57 @@ const DefaultTableServer = ({ isLoading: isLoadingOverride, ...props }) => {
7272
7660
  };
7273
7661
 
7274
7662
  const CellRenderer = ({ cell }) => {
7275
- const { translate } = useDataTableContext();
7276
7663
  const getLabel = ({ columnId }) => {
7277
- if (translate !== undefined) {
7278
- return translate.t(`${columnId}`);
7279
- }
7280
- return snakeToLabel(columnId);
7664
+ const column = cell.column;
7665
+ return column.columnDef.meta?.displayName ?? snakeToLabel(columnId);
7281
7666
  };
7282
7667
  const formatValue = (value) => {
7283
- if (typeof value === "object") {
7668
+ if (typeof value === 'object') {
7284
7669
  return JSON.stringify(value);
7285
7670
  }
7286
- if (typeof value === "string") {
7671
+ if (typeof value === 'string') {
7287
7672
  return value;
7288
7673
  }
7289
- if (typeof value === "number" || typeof value === "boolean") {
7674
+ if (typeof value === 'number' || typeof value === 'boolean') {
7290
7675
  return `${value}`;
7291
7676
  }
7292
7677
  if (value === undefined) {
7293
- if (translate !== undefined) {
7294
- return translate.t(`undefined`);
7295
- }
7296
7678
  return `undefined`;
7297
7679
  }
7298
7680
  throw new Error(`value is unknown, ${typeof value}`);
7299
7681
  };
7300
7682
  const showCustomDataDisplay = cell.column.columnDef.meta?.showCustomDisplay ?? false;
7301
7683
  const gridColumn = cell.column.columnDef.meta?.gridColumn ?? [
7302
- "span 12",
7303
- "span 6",
7304
- "span 3",
7684
+ 'span 12',
7685
+ 'span 6',
7686
+ 'span 3',
7305
7687
  ];
7306
7688
  const gridRow = cell.column.columnDef.meta?.gridRow ?? {};
7307
7689
  if (showCustomDataDisplay) {
7308
7690
  return (jsx(Flex, { gridColumn, gridRow, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
7309
7691
  }
7310
7692
  const value = cell.getValue();
7311
- if (typeof value === "object") {
7693
+ if (typeof value === 'object') {
7312
7694
  return (jsxs(Box, { gridColumn, gridRow, children: [jsx(Box, { children: getLabel({ columnId: cell.column.id }) }), jsx(RecordDisplay, { boxProps: {
7313
7695
  borderWidth: 1,
7314
7696
  borderRadius: 4,
7315
- borderColor: "gray.400",
7697
+ borderColor: 'gray.400',
7316
7698
  paddingX: 4,
7317
7699
  paddingY: 2,
7318
7700
  }, object: value })] }, cell.id));
7319
7701
  }
7320
- return (jsxs(Box, { gridColumn, gridRow, children: [jsx(Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsx(Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
7702
+ return (jsxs(Box, { gridColumn, gridRow, children: [jsx(Box, { color: 'colorPalette.400', children: getLabel({ columnId: cell.column.id }) }), jsx(Box, { wordBreak: 'break-word', textOverflow: 'ellipsis', overflow: 'hidden', children: `${formatValue(cell.getValue())}` })] }, cell.id));
7321
7703
  };
7322
- const DataDisplay = ({ variant = "" }) => {
7323
- const { table, translate } = useDataTableContext();
7324
- return (jsx(Flex, { flexFlow: "column", gap: "1", children: table.getRowModel().rows.map((row) => {
7704
+ const DataDisplay = ({ variant = '' }) => {
7705
+ const { table } = useDataTableContext();
7706
+ return (jsx(Flex, { flexFlow: 'column', gap: '1', children: table.getRowModel().rows.map((row) => {
7325
7707
  const rowId = row.id;
7326
- return (jsx(Card.Root, { children: jsx(Card.Body, { display: "grid", gap: 4, padding: 4, gridTemplateColumns: "repeat(12, 1fr)", children: table.getAllColumns().map((column) => {
7708
+ return (jsx(Card.Root, { children: jsx(Card.Body, { display: 'grid', gap: 4, padding: 4, gridTemplateColumns: 'repeat(12, 1fr)', children: table.getAllColumns().map((column) => {
7327
7709
  const childCell = row.getAllCells().find((cell) => {
7328
7710
  return cell.id === `${rowId}_${column.id}`;
7329
7711
  });
7330
7712
  if (column.columns.length > 0) {
7331
- return (jsxs(Card.Root, { margin: "1", gridColumn: "span 12", children: [jsx(Card.Header, { color: "gray.400", children: translate.t(column.id) }), jsx(Card.Body, { display: "grid", gap: "4", gridTemplateColumns: "repeat(12, 1fr)", children: column.columns.map((column) => {
7713
+ return (jsxs(Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsx(Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsx(Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((column) => {
7332
7714
  if (!column.getIsVisible()) {
7333
7715
  return jsx(Fragment, {});
7334
7716
  }