@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.js CHANGED
@@ -186,22 +186,30 @@ const Radio = React__namespace.forwardRef(function Radio(props, ref) {
186
186
  });
187
187
  const RadioGroup = react.RadioGroup.Root;
188
188
 
189
- const monthNamesFull = [
190
- "January",
191
- "February",
192
- "March",
193
- "April",
194
- "May",
195
- "June",
196
- "July",
197
- "August",
198
- "September",
199
- "October",
200
- "November",
201
- "December",
202
- ];
203
- const weekdayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
189
+ const RangeDatePickerContext = React.createContext({
190
+ labels: {
191
+ monthNamesFull: [
192
+ 'January',
193
+ 'February',
194
+ 'March',
195
+ 'April',
196
+ 'May',
197
+ 'June',
198
+ 'July',
199
+ 'August',
200
+ 'September',
201
+ 'October',
202
+ 'November',
203
+ 'December',
204
+ ],
205
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
206
+ backButtonLabel: 'Back',
207
+ forwardButtonLabel: 'Next',
208
+ },
209
+ });
204
210
  function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, selected = [], firstDayOfWeek = 0, }) {
211
+ const { labels } = React.useContext(RangeDatePickerContext);
212
+ const { monthNamesFull, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
205
213
  const [hoveredDate, setHoveredDate] = React.useState();
206
214
  const onMouseLeave = () => {
207
215
  setHoveredDate(undefined);
@@ -227,16 +235,18 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
227
235
  return false;
228
236
  };
229
237
  if (calendars.length) {
230
- return (jsxRuntime.jsxs(react.Grid, { onMouseLeave: onMouseLeave, children: [jsxRuntime.jsxs(react.Grid, { templateColumns: "repeat(4, auto)", justifyContent: "center", children: [jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({
238
+ return (jsxRuntime.jsxs(react.Grid, { onMouseLeave: onMouseLeave, children: [jsxRuntime.jsxs(react.Grid, { templateColumns: 'repeat(4, auto)', justifyContent: 'center', children: [jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getBackProps({
231
239
  calendars,
232
240
  offset: 12,
233
- }), children: "<<" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getBackProps({ calendars }), children: "Back" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({ calendars }), children: "Next" }), jsxRuntime.jsx(react.Button, { variant: "ghost", ...getForwardProps({
241
+ }), children: '<<' }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getBackProps({ calendars }), children: backButtonLabel }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getForwardProps({ calendars }), children: forwardButtonLabel }), jsxRuntime.jsx(react.Button, { variant: 'ghost', ...getForwardProps({
234
242
  calendars,
235
243
  offset: 12,
236
- }), children: ">>" })] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(2, auto)", justifyContent: "center", gap: 4, children: calendars.map((calendar) => (jsxRuntime.jsxs(react.Grid, { gap: 4, children: [jsxRuntime.jsxs(react.Grid, { justifyContent: "center", children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
244
+ }), children: '>>' })] }), jsxRuntime.jsx(react.Grid, { templateColumns: 'repeat(2, auto)', justifyContent: 'center', gap: 4, children: calendars.map((calendar) => (
245
+ // month and year
246
+ jsxRuntime.jsxs(react.Grid, { gap: 4, alignContent: "start", children: [jsxRuntime.jsxs(react.Grid, { justifyContent: 'center', children: [monthNamesFull[calendar.month], " ", calendar.year] }), jsxRuntime.jsx(react.Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: [0, 1, 2, 3, 4, 5, 6].map((weekdayNum) => {
237
247
  const weekday = (weekdayNum + firstDayOfWeek) % 7;
238
- return (jsxRuntime.jsx(react.Box, { minWidth: "48px", textAlign: "center", children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
239
- }) }), jsxRuntime.jsx(react.Grid, { templateColumns: "repeat(7, auto)", justifyContent: "center", children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
248
+ return (jsxRuntime.jsx(react.Box, { minWidth: '48px', textAlign: 'center', children: weekdayNamesShort[weekday] }, `${calendar.month}${calendar.year}${weekday}`));
249
+ }) }), jsxRuntime.jsx(react.Grid, { templateColumns: 'repeat(7, auto)', justifyContent: 'center', children: calendar.weeks.map((week, windex) => week.map((dateObj, index) => {
240
250
  const key = `${calendar.month}${calendar.year}${windex}${index}`;
241
251
  if (!dateObj) {
242
252
  return jsxRuntime.jsx(react.Box, {}, key);
@@ -245,29 +255,29 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
245
255
  const getStyle = ({ selected, unavailable, today, isInRange, }) => {
246
256
  if (unavailable) {
247
257
  return {
248
- colorPalette: "gray",
249
- variant: "solid",
258
+ colorPalette: 'gray',
259
+ variant: 'solid',
250
260
  };
251
261
  }
252
262
  if (selected) {
253
263
  return {
254
- colorPalette: "blue",
255
- variant: "solid",
264
+ colorPalette: 'blue',
265
+ variant: 'solid',
256
266
  };
257
267
  }
258
268
  if (isInRange) {
259
269
  return {
260
- colorPalette: "blue",
261
- variant: "subtle",
270
+ colorPalette: 'blue',
271
+ variant: 'subtle',
262
272
  };
263
273
  }
264
274
  if (today) {
265
275
  return {
266
- colorPalette: "green",
267
- variant: "solid",
276
+ colorPalette: 'green',
277
+ variant: 'solid',
268
278
  };
269
279
  }
270
- return { variant: "ghost" };
280
+ return { variant: 'ghost' };
271
281
  };
272
282
  return (jsxRuntime.jsx(react.Button, { ...getDateProps({
273
283
  dateObj,
@@ -279,18 +289,34 @@ function Calendar$1({ calendars, getBackProps, getForwardProps, getDateProps, se
279
289
  unavailable: !selectable,
280
290
  today,
281
291
  isInRange: isInRange(date),
282
- }), children: selectable ? date.getDate() : "X" }, key));
292
+ }), children: selectable ? date.getDate() : 'X' }, key));
283
293
  })) })] }, `${calendar.month}${calendar.year}`))) })] }));
284
294
  }
285
295
  return null;
286
296
  }
287
- class RangeDatePicker extends React.Component {
288
- render() {
289
- return (jsxRuntime.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) => (jsxRuntime.jsx(Calendar$1, { ...dayzedData,
290
- firstDayOfWeek: this.props.firstDayOfWeek,
291
- selected: this.props.selected })) }));
292
- }
293
- }
297
+ const RangeDatePicker = ({ labels = {
298
+ monthNamesFull: [
299
+ 'January',
300
+ 'February',
301
+ 'March',
302
+ 'April',
303
+ 'May',
304
+ 'June',
305
+ 'July',
306
+ 'August',
307
+ 'September',
308
+ 'October',
309
+ 'November',
310
+ 'December',
311
+ ],
312
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
313
+ backButtonLabel: 'Back',
314
+ forwardButtonLabel: 'Next',
315
+ }, selected = [], onDateSelected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, ...rest }) => {
316
+ return (jsxRuntime.jsx(RangeDatePickerContext.Provider, { value: { labels }, children: jsxRuntime.jsx(Dayzed, { onDateSelected: onDateSelected, selected: selected, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, date: date, minDate: minDate, maxDate: maxDate, monthsToDisplay: monthsToDisplay, ...rest, render: (dayzedData) => (jsxRuntime.jsx(Calendar$1, { ...dayzedData,
317
+ firstDayOfWeek,
318
+ selected: selected })) }) }));
319
+ };
294
320
 
295
321
  const getRangeDates = ({ selectable, date, selectedDates, }) => {
296
322
  if (!selectable) {
@@ -351,32 +377,38 @@ const RangeFilter = ({ range, setRange, defaultValue, min, max, step, }) => {
351
377
  onValueChange: (val) => setRange(val.value) })] }));
352
378
  };
353
379
 
354
- const Tag = React__namespace.forwardRef(function Tag(props, ref) {
355
- const { startElement, endElement, onClose, closable = !!onClose, children, ...rest } = props;
356
- return (jsxRuntime.jsxs(react.Tag.Root, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.Tag.StartElement, { children: startElement })), jsxRuntime.jsx(react.Tag.Label, { children: children }), endElement && (jsxRuntime.jsx(react.Tag.EndElement, { children: endElement })), closable && (jsxRuntime.jsx(react.Tag.EndElement, { children: jsxRuntime.jsx(react.Tag.CloseTrigger, { onClick: onClose }) }))] }));
380
+ const CheckboxCard = React__namespace.forwardRef(function CheckboxCard(props, ref) {
381
+ const { inputProps, label, description, icon, addon, indicator = jsxRuntime.jsx(react.CheckboxCard.Indicator, {}), indicatorPlacement = "end", ...rest } = props;
382
+ const hasContent = label || description || icon;
383
+ const ContentWrapper = indicator ? react.CheckboxCard.Content : React__namespace.Fragment;
384
+ return (jsxRuntime.jsxs(react.CheckboxCard.Root, { ...rest, children: [jsxRuntime.jsx(react.CheckboxCard.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsxs(react.CheckboxCard.Control, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxRuntime.jsxs(ContentWrapper, { children: [icon, label && (jsxRuntime.jsx(react.CheckboxCard.Label, { children: label })), description && (jsxRuntime.jsx(react.CheckboxCard.Description, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsxRuntime.jsx(react.CheckboxCard.Addon, { children: addon })] }));
357
385
  });
386
+ react.CheckboxCard.Indicator;
358
387
 
359
388
  const TagFilter = ({ availableTags, selectedTags, onTagChange, selectOne = false, }) => {
360
- const toggleTag = (tag) => {
389
+ const handleTagChange = (tag, checked) => {
361
390
  if (selectOne) {
362
- if (selectedTags.includes(tag)) {
363
- onTagChange([]);
391
+ if (checked) {
392
+ onTagChange([tag]);
364
393
  }
365
394
  else {
366
- onTagChange([tag]);
395
+ onTagChange([]);
367
396
  }
368
397
  return;
369
398
  }
370
- if (selectedTags.includes(tag)) {
371
- onTagChange(selectedTags.filter((t) => t !== tag));
399
+ if (checked) {
400
+ onTagChange([...selectedTags, tag]);
372
401
  }
373
402
  else {
374
- onTagChange([...selectedTags, tag]);
403
+ onTagChange(selectedTags.filter((t) => t !== tag));
375
404
  }
376
405
  };
377
- return (jsxRuntime.jsx(react.Flex, { flexFlow: "wrap", p: "0.5rem", gap: "0.5rem", children: availableTags.map((tag) => {
406
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', p: '0.5rem', gap: '0.5rem', children: availableTags.map((tag) => {
378
407
  const { label, value } = tag;
379
- return (jsxRuntime.jsx(Tag, { variant: selectedTags.includes(value) ? "solid" : "outline", cursor: "pointer", closable: selectedTags.includes(value) ? true : undefined, onClick: () => toggleTag(value), children: label ?? value }));
408
+ const isChecked = selectedTags.includes(value);
409
+ return (jsxRuntime.jsx(CheckboxCard, { checked: isChecked, label: label ?? value, size: "sm", variant: isChecked ? 'solid' : 'outline', onCheckedChange: (details) => {
410
+ handleTagChange(value, Boolean(details.checked));
411
+ } }, value));
380
412
  }) }));
381
413
  };
382
414
 
@@ -386,21 +418,21 @@ const Filter = ({ column }) => {
386
418
  const displayName = column.columnDef.meta?.displayName ?? column.id;
387
419
  const filterOptions = column.columnDef.meta?.filterOptions ?? [];
388
420
  if (column.columns.length > 0) {
389
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 1, children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(20rem, 1fr))", gap: 1, children: column.columns.map((column) => {
421
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: 1, children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(react.Grid, { gridTemplateColumns: 'repeat(auto-fit, minmax(20rem, 1fr))', gap: 1, children: column.columns.map((column) => {
390
422
  return jsxRuntime.jsx(Filter, { column: column }, column.id);
391
423
  }) }, column.id)] }));
392
424
  }
393
425
  if (!column.getCanFilter()) {
394
426
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
395
427
  }
396
- if (filterVariant === "select") {
397
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onValueChange: (details) => {
428
+ if (filterVariant === 'select') {
429
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RadioGroup, { value: column.getFilterValue() ? String(column.getFilterValue()) : '', onValueChange: (details) => {
398
430
  column.setFilterValue(details.value);
399
- }, children: jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: "0.5rem", children: [filterOptions.length === 0 && jsxRuntime.jsx(react.Text, { children: "No filter options" }), filterOptions.length > 0 &&
431
+ }, children: jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: '0.5rem', children: [filterOptions.length === 0 && jsxRuntime.jsx(react.Text, { children: "No filter options" }), filterOptions.length > 0 &&
400
432
  filterOptions.map((item) => (jsxRuntime.jsx(Radio, { value: item.value, children: item.label }, item.value)))] }) })] }, column.id));
401
433
  }
402
- if (filterVariant === "tag") {
403
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
434
+ if (filterVariant === 'tag') {
435
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: filterOptions.map((item) => ({
404
436
  label: item.label,
405
437
  value: item.value,
406
438
  })), selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
@@ -410,11 +442,11 @@ const Filter = ({ column }) => {
410
442
  column.setFilterValue(tags);
411
443
  } })] }, column.id));
412
444
  }
413
- if (filterVariant === "boolean") {
445
+ if (filterVariant === 'boolean') {
414
446
  const { trueLabel, falseLabel } = tableLabel;
415
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: [
416
- { label: trueLabel, value: "true" },
417
- { label: falseLabel, value: "false" },
447
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(TagFilter, { availableTags: [
448
+ { label: trueLabel, value: 'true' },
449
+ { label: falseLabel, value: 'false' },
418
450
  ], selectedTags: (column.getFilterValue() ?? []), onTagChange: (tags) => {
419
451
  if (tags.length === 0) {
420
452
  return column.setFilterValue(undefined);
@@ -422,7 +454,7 @@ const Filter = ({ column }) => {
422
454
  column.setFilterValue(tags);
423
455
  } })] }, column.id));
424
456
  }
425
- if (filterVariant === "range") {
457
+ if (filterVariant === 'range') {
426
458
  const filterValue = column.getFilterValue() ?? [
427
459
  undefined,
428
460
  undefined,
@@ -434,14 +466,14 @@ const Filter = ({ column }) => {
434
466
  step: 1,
435
467
  defaultValue: [4, 50],
436
468
  };
437
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RangeFilter, { range: filterValue, setRange: function (value) {
469
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RangeFilter, { range: filterValue, setRange: function (value) {
438
470
  // throw new Error("Function not implemented.");
439
471
  column.setFilterValue(value);
440
472
  }, defaultValue: defaultValue, min: min, max: max, step: step })] }, column.id));
441
473
  }
442
- if (filterVariant === "dateRange") {
474
+ if (filterVariant === 'dateRange') {
443
475
  const filterValue = column.getFilterValue() ?? [];
444
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RangeDatePicker, { selected: filterValue, onDateSelected: ({ selected, selectable, date }) => {
476
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(RangeDatePicker, { selected: filterValue, onDateSelected: ({ selected, selectable, date }) => {
445
477
  const newDates = getRangeDates({
446
478
  selectable,
447
479
  date,
@@ -452,14 +484,14 @@ const Filter = ({ column }) => {
452
484
  });
453
485
  } })] }, column.id));
454
486
  }
455
- if (filterVariant === "custom") {
487
+ if (filterVariant === 'custom') {
456
488
  const renderFilter = column.columnDef.meta?.renderFilter;
457
489
  if (renderFilter === undefined) {
458
- throw new Error("renderFilter is undefined");
490
+ throw new Error('renderFilter is undefined');
459
491
  }
460
492
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderFilter(column) });
461
493
  }
462
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(react.Input, { value: column.getFilterValue() ? String(column.getFilterValue()) : "", onChange: (e) => {
494
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "0.25rem", children: [jsxRuntime.jsx(react.Text, { children: displayName }), jsxRuntime.jsx(react.Input, { value: column.getFilterValue() ? String(column.getFilterValue()) : '', onChange: (e) => {
463
495
  column.setFilterValue(e.target.value);
464
496
  } })] }, column.id));
465
497
  };
@@ -2604,21 +2636,13 @@ function draggable(args) {
2604
2636
 
2605
2637
  /** Arguments given to all monitor feedback functions (eg `canMonitor()`) for a `monitorForElements` */
2606
2638
 
2607
- const CheckboxCard = React__namespace.forwardRef(function CheckboxCard(props, ref) {
2608
- const { inputProps, label, description, icon, addon, indicator = jsxRuntime.jsx(react.CheckboxCard.Indicator, {}), indicatorPlacement = "end", ...rest } = props;
2609
- const hasContent = label || description || icon;
2610
- const ContentWrapper = indicator ? react.CheckboxCard.Content : React__namespace.Fragment;
2611
- return (jsxRuntime.jsxs(react.CheckboxCard.Root, { ...rest, children: [jsxRuntime.jsx(react.CheckboxCard.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsxs(react.CheckboxCard.Control, { children: [indicatorPlacement === "start" && indicator, hasContent && (jsxRuntime.jsxs(ContentWrapper, { children: [icon, label && (jsxRuntime.jsx(react.CheckboxCard.Label, { children: label })), description && (jsxRuntime.jsx(react.CheckboxCard.Description, { children: description })), indicatorPlacement === "inside" && indicator] })), indicatorPlacement === "end" && indicator] }), addon && jsxRuntime.jsx(react.CheckboxCard.Addon, { children: addon })] }));
2612
- });
2613
- react.CheckboxCard.Indicator;
2614
-
2615
2639
  function ColumnCard({ columnId }) {
2616
2640
  const ref = React.useRef(null);
2617
2641
  const [dragging, setDragging] = React.useState(false); // NEW
2618
- const { table, translate } = useDataTableContext();
2619
- const displayName = translate.t(columnId);
2642
+ const { table } = useDataTableContext();
2620
2643
  const column = table.getColumn(columnId);
2621
2644
  invariant(column);
2645
+ const displayName = column.columnDef.meta?.displayName ?? columnId;
2622
2646
  React.useEffect(() => {
2623
2647
  const el = ref.current;
2624
2648
  invariant(el);
@@ -2631,7 +2655,7 @@ function ColumnCard({ columnId }) {
2631
2655
  onDrop: () => setDragging(false), // NEW
2632
2656
  });
2633
2657
  }, [columnId, table]);
2634
- return (jsxRuntime.jsxs(react.Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsxRuntime.jsx(react.Flex, { alignItems: "center", padding: "0", cursor: "grab", children: jsxRuntime.jsx(fa6.FaGripLinesVertical, { color: "colorPalette.400" }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "space-between", alignItems: "center", children: jsxRuntime.jsx(CheckboxCard, { variant: "surface", label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2658
+ return (jsxRuntime.jsxs(react.Grid, { ref: ref, templateColumns: "auto 1fr", gap: "0.5rem", alignItems: "center", style: dragging ? { opacity: 0.4 } : {}, children: [jsxRuntime.jsx(react.Flex, { alignItems: "center", padding: "0", cursor: 'grab', children: jsxRuntime.jsx(fa6.FaGripLinesVertical, { color: "colorPalette.400" }) }), jsxRuntime.jsx(react.Flex, { justifyContent: "space-between", alignItems: "center", children: jsxRuntime.jsx(CheckboxCard, { variant: 'surface', label: displayName, checked: column.getIsVisible(), onChange: column.getToggleVisibilityHandler() }) })] }));
2635
2659
  }
2636
2660
  function CardContainer({ location, children }) {
2637
2661
  const ref = React.useRef(null);
@@ -2653,9 +2677,9 @@ function CardContainer({ location, children }) {
2653
2677
  function getColor(isDraggedOver) {
2654
2678
  if (isDraggedOver) {
2655
2679
  return {
2656
- backgroundColor: "blue.400",
2680
+ backgroundColor: 'blue.400',
2657
2681
  _dark: {
2658
- backgroundColor: "blue.400",
2682
+ backgroundColor: 'blue.400',
2659
2683
  },
2660
2684
  };
2661
2685
  }
@@ -2687,7 +2711,7 @@ const TableViewer = () => {
2687
2711
  const sourceColumn = source.data.column;
2688
2712
  const columnOrder = order.map((id) => {
2689
2713
  if (id == sourceColumn.id) {
2690
- return "<marker>";
2714
+ return '<marker>';
2691
2715
  }
2692
2716
  return id;
2693
2717
  });
@@ -2697,12 +2721,12 @@ const TableViewer = () => {
2697
2721
  ...columnBefore,
2698
2722
  sourceColumn.id,
2699
2723
  ...columnAfter,
2700
- ].filter((id) => id != "<marker>");
2724
+ ].filter((id) => id != '<marker>');
2701
2725
  table.setColumnOrder(newOrder);
2702
2726
  },
2703
2727
  });
2704
2728
  }, [table]);
2705
- return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.25rem", children: order.map((columnId, index) => {
2729
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: '0.25rem', children: order.map((columnId, index) => {
2706
2730
  return (jsxRuntime.jsx(CardContainer, { location: index, children: jsxRuntime.jsx(ColumnCard, { columnId: columnId }) }));
2707
2731
  }) }));
2708
2732
  };
@@ -2793,12 +2817,31 @@ const TableSelector = () => {
2793
2817
 
2794
2818
  const TableFilterTags = () => {
2795
2819
  const { table } = useDataTableContext();
2796
- return (jsxRuntime.jsx(react.Flex, { gap: "0.5rem", flexFlow: "wrap", children: table.getState().columnFilters.map(({ id, value }) => {
2797
- return (jsxRuntime.jsx(Tag, { gap: "0.5rem", closable: true, cursor: "pointer", onClick: () => {
2798
- table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
2799
- return filter.value != value;
2800
- }));
2801
- }, children: `${id}: ${value}` }, `${id}-${value}`));
2820
+ return (jsxRuntime.jsx(react.Flex, { gap: '0.5rem', flexFlow: 'wrap', children: table.getState().columnFilters.map(({ id, value }) => {
2821
+ const column = table.getColumn(id);
2822
+ const displayName = column?.columnDef.meta?.displayName ?? id;
2823
+ // Format the value for display
2824
+ const formatValue = (val) => {
2825
+ if (Array.isArray(val)) {
2826
+ return val.join(', ');
2827
+ }
2828
+ if (val === null || val === undefined) {
2829
+ return '';
2830
+ }
2831
+ return String(val);
2832
+ };
2833
+ const displayValue = formatValue(value);
2834
+ const label = displayValue
2835
+ ? `${displayName}: ${displayValue}`
2836
+ : displayName;
2837
+ return (jsxRuntime.jsx(CheckboxCard, { checked: true, label: label, size: "sm", variant: "outline", colorPalette: "blue", onCheckedChange: (details) => {
2838
+ if (!details.checked) {
2839
+ table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
2840
+ return (filter.id !== id ||
2841
+ JSON.stringify(filter.value) !== JSON.stringify(value));
2842
+ }));
2843
+ }
2844
+ } }, `${id}-${JSON.stringify(value)}`));
2802
2845
  }) }));
2803
2846
  };
2804
2847
 
@@ -3299,6 +3342,11 @@ const TextCell = ({ label, containerProps = {}, textProps = {}, children, }) =>
3299
3342
  return (jsxRuntime.jsx(react.Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }));
3300
3343
  };
3301
3344
 
3345
+ const Tag = React__namespace.forwardRef(function Tag(props, ref) {
3346
+ const { startElement, endElement, onClose, closable = !!onClose, children, ...rest } = props;
3347
+ return (jsxRuntime.jsxs(react.Tag.Root, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.Tag.StartElement, { children: startElement })), jsxRuntime.jsx(react.Tag.Label, { children: children }), endElement && (jsxRuntime.jsx(react.Tag.EndElement, { children: endElement })), closable && (jsxRuntime.jsx(react.Tag.EndElement, { children: jsxRuntime.jsx(react.Tag.CloseTrigger, { onClick: onClose }) }))] }));
3348
+ });
3349
+
3302
3350
  const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
3303
3351
  if (!!row.original === false) {
3304
3352
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
@@ -4037,24 +4085,6 @@ let DatePicker$1 = class DatePicker extends React.Component {
4037
4085
  }
4038
4086
  };
4039
4087
 
4040
- const PopoverContent = React__namespace.forwardRef(function PopoverContent(props, ref) {
4041
- const { portalled = true, portalRef, ...rest } = props;
4042
- return (jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { ref: ref, ...rest }) }) }));
4043
- });
4044
- React__namespace.forwardRef(function PopoverArrow(props, ref) {
4045
- return (jsxRuntime.jsx(react.Popover.Arrow, { ...props, ref: ref, children: jsxRuntime.jsx(react.Popover.ArrowTip, {}) }));
4046
- });
4047
- React__namespace.forwardRef(function PopoverCloseTrigger(props, ref) {
4048
- return (jsxRuntime.jsx(react.Popover.CloseTrigger, { position: "absolute", top: "1", insetEnd: "1", ...props, asChild: true, ref: ref, children: jsxRuntime.jsx(CloseButton, { size: "sm" }) }));
4049
- });
4050
- const PopoverTitle = react.Popover.Title;
4051
- react.Popover.Description;
4052
- react.Popover.Footer;
4053
- react.Popover.Header;
4054
- const PopoverRoot = react.Popover.Root;
4055
- const PopoverBody = react.Popover.Body;
4056
- const PopoverTrigger = react.Popover.Trigger;
4057
-
4058
4088
  /**
4059
4089
  * Custom hook to simplify i18n translation for form fields.
4060
4090
  * Automatically handles colLabel construction and removeIndex logic.
@@ -4123,7 +4153,7 @@ dayjs.extend(utc);
4123
4153
  dayjs.extend(timezone);
4124
4154
  const DatePicker = ({ column, schema, prefix }) => {
4125
4155
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4126
- const { timezone, dateTimePickerLabels } = useSchemaContext();
4156
+ const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
4127
4157
  const formI18n = useFormI18n(column, prefix);
4128
4158
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4129
4159
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4156,90 +4186,92 @@ const DatePicker = ({ column, schema, prefix }) => {
4156
4186
  console.error(e);
4157
4187
  }
4158
4188
  }, [selectedDate, dateFormat, colLabel, setValue]);
4189
+ const datePickerLabels = {
4190
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4191
+ formI18n.translate.t(`common.month_1`, {
4192
+ defaultValue: 'January',
4193
+ }),
4194
+ formI18n.translate.t(`common.month_2`, {
4195
+ defaultValue: 'February',
4196
+ }),
4197
+ formI18n.translate.t(`common.month_3`, {
4198
+ defaultValue: 'March',
4199
+ }),
4200
+ formI18n.translate.t(`common.month_4`, {
4201
+ defaultValue: 'April',
4202
+ }),
4203
+ formI18n.translate.t(`common.month_5`, {
4204
+ defaultValue: 'May',
4205
+ }),
4206
+ formI18n.translate.t(`common.month_6`, {
4207
+ defaultValue: 'June',
4208
+ }),
4209
+ formI18n.translate.t(`common.month_7`, {
4210
+ defaultValue: 'July',
4211
+ }),
4212
+ formI18n.translate.t(`common.month_8`, {
4213
+ defaultValue: 'August',
4214
+ }),
4215
+ formI18n.translate.t(`common.month_9`, {
4216
+ defaultValue: 'September',
4217
+ }),
4218
+ formI18n.translate.t(`common.month_10`, {
4219
+ defaultValue: 'October',
4220
+ }),
4221
+ formI18n.translate.t(`common.month_11`, {
4222
+ defaultValue: 'November',
4223
+ }),
4224
+ formI18n.translate.t(`common.month_12`, {
4225
+ defaultValue: 'December',
4226
+ }),
4227
+ ],
4228
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4229
+ formI18n.translate.t(`common.weekday_1`, {
4230
+ defaultValue: 'Sun',
4231
+ }),
4232
+ formI18n.translate.t(`common.weekday_2`, {
4233
+ defaultValue: 'Mon',
4234
+ }),
4235
+ formI18n.translate.t(`common.weekday_3`, {
4236
+ defaultValue: 'Tue',
4237
+ }),
4238
+ formI18n.translate.t(`common.weekday_4`, {
4239
+ defaultValue: 'Wed',
4240
+ }),
4241
+ formI18n.translate.t(`common.weekday_5`, {
4242
+ defaultValue: 'Thu',
4243
+ }),
4244
+ formI18n.translate.t(`common.weekday_6`, {
4245
+ defaultValue: 'Fri',
4246
+ }),
4247
+ formI18n.translate.t(`common.weekday_7`, {
4248
+ defaultValue: 'Sat',
4249
+ }),
4250
+ ],
4251
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4252
+ formI18n.translate.t(`common.back_button`, {
4253
+ defaultValue: 'Back',
4254
+ }),
4255
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4256
+ formI18n.translate.t(`common.forward_button`, {
4257
+ defaultValue: 'Forward',
4258
+ }),
4259
+ };
4260
+ const datePickerContent = (jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4261
+ setValue(colLabel, dayjs(date).format(dateFormat));
4262
+ setOpen(false);
4263
+ }, labels: datePickerLabels }));
4159
4264
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4160
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4265
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4161
4266
  setOpen(true);
4162
- }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4163
- setValue(colLabel, dayjs(date).format(dateFormat));
4164
- setOpen(false);
4165
- }, labels: {
4166
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4167
- formI18n.translate.t(`common.month_1`, {
4168
- defaultValue: 'January',
4169
- }),
4170
- formI18n.translate.t(`common.month_2`, {
4171
- defaultValue: 'February',
4172
- }),
4173
- formI18n.translate.t(`common.month_3`, {
4174
- defaultValue: 'March',
4175
- }),
4176
- formI18n.translate.t(`common.month_4`, {
4177
- defaultValue: 'April',
4178
- }),
4179
- formI18n.translate.t(`common.month_5`, {
4180
- defaultValue: 'May',
4181
- }),
4182
- formI18n.translate.t(`common.month_6`, {
4183
- defaultValue: 'June',
4184
- }),
4185
- formI18n.translate.t(`common.month_7`, {
4186
- defaultValue: 'July',
4187
- }),
4188
- formI18n.translate.t(`common.month_8`, {
4189
- defaultValue: 'August',
4190
- }),
4191
- formI18n.translate.t(`common.month_9`, {
4192
- defaultValue: 'September',
4193
- }),
4194
- formI18n.translate.t(`common.month_10`, {
4195
- defaultValue: 'October',
4196
- }),
4197
- formI18n.translate.t(`common.month_11`, {
4198
- defaultValue: 'November',
4199
- }),
4200
- formI18n.translate.t(`common.month_12`, {
4201
- defaultValue: 'December',
4202
- }),
4203
- ],
4204
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4205
- formI18n.translate.t(`common.weekday_1`, {
4206
- defaultValue: 'Sun',
4207
- }),
4208
- formI18n.translate.t(`common.weekday_2`, {
4209
- defaultValue: 'Mon',
4210
- }),
4211
- formI18n.translate.t(`common.weekday_3`, {
4212
- defaultValue: 'Tue',
4213
- }),
4214
- formI18n.translate.t(`common.weekday_4`, {
4215
- defaultValue: 'Wed',
4216
- }),
4217
- formI18n.translate.t(`common.weekday_5`, {
4218
- defaultValue: 'Thu',
4219
- }),
4220
- formI18n.translate.t(`common.weekday_6`, {
4221
- defaultValue: 'Fri',
4222
- }),
4223
- formI18n.translate.t(`common.weekday_7`, {
4224
- defaultValue: 'Sat',
4225
- }),
4226
- ],
4227
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4228
- formI18n.translate.t(`common.back_button`, {
4229
- defaultValue: 'Back',
4230
- }),
4231
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4232
- formI18n.translate.t(`common.forward_button`, {
4233
- defaultValue: 'Forward',
4234
- }),
4235
- } })] }) })] }) }));
4267
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: datePickerContent }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: datePickerContent }) }) }) }))] }) }));
4236
4268
  };
4237
4269
 
4238
4270
  dayjs.extend(utc);
4239
4271
  dayjs.extend(timezone);
4240
4272
  const DateRangePicker = ({ column, schema, prefix, }) => {
4241
4273
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4242
- const { timezone, dateTimePickerLabels } = useSchemaContext();
4274
+ const { timezone, insideDialog } = useSchemaContext();
4243
4275
  const formI18n = useFormI18n(column, prefix);
4244
4276
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4245
4277
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4302,9 +4334,9 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4302
4334
  }
4303
4335
  }, [selectedDateRange, dateFormat, colLabel, setValue, timezone]);
4304
4336
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4305
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4337
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4306
4338
  setOpen(true);
4307
- }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), getDisplayText()] }) }), jsxRuntime.jsx(PopoverContent, { minW: '600px', children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selected, selectable, date }) => {
4339
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), getDisplayText()] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selectable, date }) => {
4308
4340
  const newDates = getRangeDates({
4309
4341
  selectable,
4310
4342
  date,
@@ -4318,7 +4350,21 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
4318
4350
  shouldValidate: true,
4319
4351
  shouldDirty: true,
4320
4352
  });
4321
- }, monthsToDisplay: 2 })] }) })] }) }));
4353
+ }, monthsToDisplay: 2, withPopover: false }) }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minW: "50rem", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(RangeDatePicker, { selected: selectedDates, onDateSelected: ({ selectable, date }) => {
4354
+ const newDates = getRangeDates({
4355
+ selectable,
4356
+ date,
4357
+ selectedDates,
4358
+ }) ?? [];
4359
+ // Convert Date[] to string[]
4360
+ const formattedDates = newDates
4361
+ .map((dateObj) => dayjs(dateObj).tz(timezone).format(dateFormat))
4362
+ .filter((dateStr) => dateStr);
4363
+ setValue(colLabel, formattedDates, {
4364
+ shouldValidate: true,
4365
+ shouldDirty: true,
4366
+ });
4367
+ }, monthsToDisplay: 2, withPopover: false }) }) }) }) }))] }) }));
4322
4368
  };
4323
4369
 
4324
4370
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
@@ -5712,134 +5758,310 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
5712
5758
  : undefined, invalid: !!fieldError, children: jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
5713
5759
  };
5714
5760
 
5715
- function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
5716
- am: "am",
5717
- pm: "pm",
5718
- }, onChange = (_newValue) => { }, timezone = "Asia/Hong_Kong", }) {
5761
+ dayjs.extend(utc);
5762
+ dayjs.extend(timezone);
5763
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
5764
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5765
+ meridiemLabel: _meridiemLabel = {
5766
+ am: 'am',
5767
+ pm: 'pm',
5768
+ },
5769
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5770
+ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedDate, }) {
5771
+ // Generate time options (every 15 minutes)
5772
+ const timeOptions = React.useMemo(() => {
5773
+ const options = [];
5774
+ const meridiemOptions = ['am', 'pm'];
5775
+ // Get start time for comparison if provided
5776
+ let startDateTime = null;
5777
+ let shouldFilterByDate = false;
5778
+ if (startTime && selectedDate) {
5779
+ const startDateObj = dayjs(startTime).tz(timezone);
5780
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5781
+ if (startDateObj.isValid() && selectedDateObj.isValid()) {
5782
+ startDateTime = startDateObj;
5783
+ // Only filter if dates are the same
5784
+ shouldFilterByDate =
5785
+ startDateObj.format('YYYY-MM-DD') ===
5786
+ selectedDateObj.format('YYYY-MM-DD');
5787
+ }
5788
+ }
5789
+ for (const mer of meridiemOptions) {
5790
+ for (let h = 1; h <= 12; h++) {
5791
+ for (let m = 0; m < 60; m += 15) {
5792
+ const hour24 = mer === 'am' ? (h === 12 ? 0 : h) : h === 12 ? 12 : h + 12;
5793
+ const timeStr = dayjs()
5794
+ .tz(timezone)
5795
+ .hour(hour24)
5796
+ .minute(m)
5797
+ .format('HH:mmZ');
5798
+ const displayTime = dayjs(`1970-01-01T${timeStr}`, 'HH:mmZ').format('hh:mm a');
5799
+ // Filter out times that would result in negative duration (only when dates are the same)
5800
+ if (startDateTime && selectedDate && shouldFilterByDate) {
5801
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5802
+ const optionDateTime = selectedDateObj
5803
+ .hour(hour24)
5804
+ .minute(m)
5805
+ .second(0)
5806
+ .millisecond(0);
5807
+ if (optionDateTime.isBefore(startDateTime)) {
5808
+ continue; // Skip this option as it would result in negative duration
5809
+ }
5810
+ }
5811
+ // Calculate and append duration if startTime is provided
5812
+ let label = displayTime;
5813
+ if (startDateTime && selectedDate) {
5814
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5815
+ const optionDateTime = selectedDateObj
5816
+ .hour(hour24)
5817
+ .minute(m)
5818
+ .second(0)
5819
+ .millisecond(0);
5820
+ if (optionDateTime.isValid() &&
5821
+ optionDateTime.isAfter(startDateTime)) {
5822
+ const diffMs = optionDateTime.diff(startDateTime);
5823
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
5824
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
5825
+ if (diffHours > 0 || diffMinutes > 0) {
5826
+ const diffText = diffHours > 0
5827
+ ? `${diffHours}h ${diffMinutes}m`
5828
+ : `${diffMinutes}m`;
5829
+ label = `${displayTime} (+${diffText})`;
5830
+ }
5831
+ }
5832
+ }
5833
+ options.push({
5834
+ label,
5835
+ value: `${h}:${m.toString().padStart(2, '0')}:${mer}`,
5836
+ hour: h,
5837
+ minute: m,
5838
+ meridiem: mer,
5839
+ searchText: displayTime, // Use base time without duration for searching
5840
+ });
5841
+ }
5842
+ }
5843
+ }
5844
+ return options;
5845
+ }, [timezone, startTime, selectedDate]);
5846
+ const { contains } = react.useFilter({ sensitivity: 'base' });
5847
+ const { collection, filter } = react.useListCollection({
5848
+ initialItems: timeOptions,
5849
+ itemToString: (item) => item.searchText, // Use searchText (without duration) for filtering
5850
+ itemToValue: (item) => item.value,
5851
+ filter: contains,
5852
+ });
5853
+ // Track input mode vs display mode
5854
+ const [isInputMode, setIsInputMode] = React.useState(false);
5855
+ const [inputValue, setInputValue] = React.useState('');
5856
+ const inputRef = React.useRef(null);
5857
+ // Switch to display mode when value is selected
5858
+ React.useEffect(() => {
5859
+ if (hour !== null && minute !== null && meridiem !== null) {
5860
+ setIsInputMode(false);
5861
+ }
5862
+ }, [hour, minute, meridiem]);
5863
+ // Focus input when switching to input mode
5864
+ React.useEffect(() => {
5865
+ if (isInputMode && inputRef.current) {
5866
+ inputRef.current.focus();
5867
+ }
5868
+ }, [isInputMode]);
5869
+ // Get current value string for combobox
5870
+ const currentValue = React.useMemo(() => {
5871
+ if (hour === null || minute === null || meridiem === null) {
5872
+ return '';
5873
+ }
5874
+ return `${hour}:${minute.toString().padStart(2, '0')}:${meridiem}`;
5875
+ }, [hour, minute, meridiem]);
5876
+ // INPUT MODE: Show raw input text (no duration)
5877
+ const inputModeText = React.useMemo(() => {
5878
+ return inputValue;
5879
+ }, [inputValue]);
5880
+ // DISPLAY MODE: Show selected value with duration
5881
+ const displayModeText = React.useMemo(() => {
5882
+ if (hour === null || minute === null || meridiem === null) {
5883
+ return '';
5884
+ }
5885
+ const hour24 = meridiem === 'am'
5886
+ ? hour === 12
5887
+ ? 0
5888
+ : hour
5889
+ : hour === 12
5890
+ ? 12
5891
+ : hour + 12;
5892
+ const timeStr = dayjs()
5893
+ .tz(timezone)
5894
+ .hour(hour24)
5895
+ .minute(minute)
5896
+ .format('HH:mmZ');
5897
+ const timeDisplay = dayjs(`1970-01-01T${timeStr}`, 'HH:mmZ').format('hh:mm a');
5898
+ // Add duration if startTime is provided
5899
+ if (startTime && selectedDate) {
5900
+ const startDateObj = dayjs(startTime).tz(timezone);
5901
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
5902
+ const currentDateTime = selectedDateObj
5903
+ .hour(hour24)
5904
+ .minute(minute)
5905
+ .second(0)
5906
+ .millisecond(0);
5907
+ if (startDateObj.isValid() && currentDateTime.isValid()) {
5908
+ const diffMs = currentDateTime.diff(startDateObj);
5909
+ if (diffMs >= 0) {
5910
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
5911
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
5912
+ if (diffHours > 0 || diffMinutes > 0) {
5913
+ const diffText = diffHours > 0
5914
+ ? `${diffHours}h ${diffMinutes}m`
5915
+ : `${diffMinutes}m`;
5916
+ return `${timeDisplay} (+${diffText})`;
5917
+ }
5918
+ }
5919
+ }
5920
+ }
5921
+ return timeDisplay;
5922
+ }, [hour, minute, meridiem, timezone, startTime, selectedDate]);
5923
+ // Choose text based on mode
5924
+ const displayText = isInputMode ? inputModeText : displayModeText;
5719
5925
  const handleClear = () => {
5720
5926
  setHour(null);
5721
5927
  setMinute(null);
5722
5928
  setMeridiem(null);
5723
- setInputValue("");
5724
- setShowInput(false);
5929
+ setIsInputMode(false);
5930
+ setInputValue('');
5931
+ filter(''); // Reset filter to show all options
5725
5932
  onChange({ hour: null, minute: null, meridiem: null });
5726
5933
  };
5727
- const getTimeString = (hour, minute, meridiem) => {
5728
- if (hour === null || minute === null || meridiem === null) {
5729
- return "";
5730
- }
5731
- // if the hour is 24, set the hour to 0
5732
- if (hour === 24) {
5733
- return dayjs().tz(timezone).hour(0).minute(minute).format("HH:mmZ");
5734
- }
5735
- // use dayjs to format the time at current timezone
5736
- // if meridiem is pm, add 12 hours
5737
- let newHour = hour;
5738
- if (meridiem === "pm" && hour !== 12) {
5739
- newHour = hour + 12;
5934
+ const handleValueChange = (details) => {
5935
+ if (details.value.length === 0) {
5936
+ handleClear();
5937
+ return;
5740
5938
  }
5741
- // if the hour is 12, set the meridiem to am, and set the hour to 0
5742
- else if (meridiem === "am" && hour === 12) {
5743
- newHour = 0;
5939
+ const selectedValue = details.value[0];
5940
+ const selectedOption = timeOptions.find((opt) => opt.value === selectedValue);
5941
+ if (selectedOption) {
5942
+ setHour(selectedOption.hour);
5943
+ setMinute(selectedOption.minute);
5944
+ setMeridiem(selectedOption.meridiem);
5945
+ setIsInputMode(false); // Switch to display mode
5946
+ setInputValue('');
5947
+ filter(''); // Reset filter after selection
5948
+ onChange({
5949
+ hour: selectedOption.hour,
5950
+ minute: selectedOption.minute,
5951
+ meridiem: selectedOption.meridiem,
5952
+ });
5744
5953
  }
5745
- return dayjs().tz(timezone).hour(newHour).minute(minute).format("HH:mmZ");
5746
5954
  };
5747
- const stringTime = getTimeString(hour, minute, meridiem);
5748
- const [inputValue, setInputValue] = React.useState("");
5749
- const [showInput, setShowInput] = React.useState(false);
5750
- const handleBlur = (text) => {
5751
- // ignore all non-numeric characters
5752
- if (!text) {
5753
- return;
5955
+ // Handle Enter key to select first filtered option
5956
+ const handleKeyDown = (e) => {
5957
+ if (e.key === 'Enter' && collection.items.length > 0) {
5958
+ e.preventDefault();
5959
+ const firstOption = collection.items[0];
5960
+ if (firstOption) {
5961
+ const selectedOption = timeOptions.find((opt) => opt.value === firstOption.value);
5962
+ if (selectedOption) {
5963
+ setHour(selectedOption.hour);
5964
+ setMinute(selectedOption.minute);
5965
+ setMeridiem(selectedOption.meridiem);
5966
+ setIsInputMode(false); // Switch to display mode
5967
+ setInputValue('');
5968
+ filter('');
5969
+ onChange({
5970
+ hour: selectedOption.hour,
5971
+ minute: selectedOption.minute,
5972
+ meridiem: selectedOption.meridiem,
5973
+ });
5974
+ }
5975
+ }
5754
5976
  }
5755
- const value = text.replace(/[^0-9apm]/g, "");
5756
- if (value === "") {
5757
- handleClear();
5977
+ };
5978
+ const handleInputValueChange = (details) => {
5979
+ const inputValue = details.inputValue.trim();
5980
+ setInputValue(inputValue);
5981
+ setIsInputMode(true); // Switch to input mode
5982
+ // Filter the collection based on input
5983
+ filter(inputValue);
5984
+ if (!inputValue) {
5985
+ setIsInputMode(false);
5758
5986
  return;
5759
5987
  }
5760
- // if the value is a valid time, parse it and set the hour, minute, and meridiem
5761
- // if the value is not a valid time, set the stringTime to the value
5762
- // first two characters are the hour
5763
- // next two characters are the minute
5764
- // final two characters are the meridiem
5765
- const hour = parseInt(value.slice(0, 2));
5766
- const minute = parseInt(value.slice(2, 4));
5767
- const meridiem = value.slice(4, 6);
5768
- // validate the hour and minute
5769
- if (isNaN(hour) || isNaN(minute)) {
5770
- setInputValue("");
5988
+ // Try to parse custom input using explicit regex patterns
5989
+ const normalized = inputValue.toLowerCase().replace(/\s+/g, '');
5990
+ // Pattern 1: 12-hour format with meridiem (e.g., "930pm", "1230am", "9:30pm", "12:30am")
5991
+ // Matches: 1-2 digits hour, optional colon, 2 digits minute, am/pm
5992
+ const pattern12HourWithMeridiem = /^(\d{1,2}):?(\d{2})(am|pm)$/;
5993
+ const match12Hour = normalized.match(pattern12HourWithMeridiem);
5994
+ if (match12Hour) {
5995
+ const parsedHour = parseInt(match12Hour[1], 10);
5996
+ const parsedMinute = parseInt(match12Hour[2], 10);
5997
+ const parsedMeridiem = match12Hour[3];
5998
+ // Validate hour (1-12)
5999
+ if (parsedHour < 1 || parsedHour > 12) {
6000
+ return;
6001
+ }
6002
+ // Validate minute (0-59)
6003
+ const validMinute = parsedMinute > 59 ? 0 : parsedMinute;
6004
+ setHour(parsedHour);
6005
+ setMinute(validMinute);
6006
+ setMeridiem(parsedMeridiem);
6007
+ onChange({
6008
+ hour: parsedHour,
6009
+ minute: validMinute,
6010
+ meridiem: parsedMeridiem,
6011
+ });
5771
6012
  return;
5772
6013
  }
5773
- // if the hour is larger than 24, set the hour to 24
5774
- if (hour > 24) {
5775
- setInputValue("");
6014
+ // Pattern 2: 24-hour format (e.g., "2130", "09:30", "21:30")
6015
+ // Matches: 1-2 digits hour, optional colon, 2 digits minute
6016
+ const pattern24Hour = /^(\d{2}):?(\d{2})$/;
6017
+ const match24Hour = normalized.match(pattern24Hour);
6018
+ if (match24Hour) {
6019
+ let parsedHour = parseInt(match24Hour[1], 10);
6020
+ const parsedMinute = parseInt(match24Hour[2], 10);
6021
+ // Validate hour (0-23)
6022
+ if (parsedHour > 23) {
6023
+ return;
6024
+ }
6025
+ // Convert 24-hour to 12-hour format
6026
+ let parsedMeridiem;
6027
+ if (parsedHour === 0) {
6028
+ parsedHour = 12;
6029
+ parsedMeridiem = 'am';
6030
+ }
6031
+ else if (parsedHour === 12) {
6032
+ parsedHour = 12;
6033
+ parsedMeridiem = 'pm';
6034
+ }
6035
+ else if (parsedHour > 12) {
6036
+ parsedHour = parsedHour - 12;
6037
+ parsedMeridiem = 'pm';
6038
+ }
6039
+ else {
6040
+ parsedMeridiem = 'am';
6041
+ }
6042
+ // Validate minute (0-59)
6043
+ const validMinute = parsedMinute > 59 ? 0 : parsedMinute;
6044
+ setHour(parsedHour);
6045
+ setMinute(validMinute);
6046
+ setMeridiem(parsedMeridiem);
6047
+ onChange({
6048
+ hour: parsedHour,
6049
+ minute: validMinute,
6050
+ meridiem: parsedMeridiem,
6051
+ });
5776
6052
  return;
5777
6053
  }
5778
- let newHour = hour;
5779
- let newMinute = minute;
5780
- let newMeridiem = meridiem;
5781
- // if the hour is 24, set the meridiem to am, and set the hour to 0
5782
- if (hour === 24) {
5783
- newMeridiem = "am";
5784
- newHour = 0;
5785
- }
5786
- // if the hour is greater than 12, set the meridiem to pm, and subtract 12 from the hour
5787
- else if (hour > 12) {
5788
- newMeridiem = "pm";
5789
- newHour = hour - 12;
5790
- }
5791
- // if the hour is 12, set the meridiem to pm, and set the hour to 12
5792
- else if (hour === 12) {
5793
- newMeridiem = "pm";
5794
- newHour = 12;
5795
- }
5796
- // if the hour is 0, set the meridiem to am, and set the hour to 12
5797
- else if (hour === 0) {
5798
- newMeridiem = "am";
5799
- newHour = 12;
5800
- }
5801
- else {
5802
- newMeridiem = meridiem ?? "am";
5803
- newHour = hour;
5804
- }
5805
- if (minute > 59) {
5806
- newMinute = 0;
5807
- }
5808
- else {
5809
- newMinute = minute;
5810
- }
5811
- onChange({
5812
- hour: newHour,
5813
- minute: newMinute,
5814
- meridiem: newMeridiem,
5815
- });
5816
- setShowInput(false);
5817
- };
5818
- const handleKeyDown = (e) => {
5819
- if (e.key === "Enter") {
5820
- handleBlur(e.currentTarget.value);
5821
- }
5822
6054
  };
5823
- const inputRef = React.useRef(null);
5824
- return (jsxRuntime.jsxs(react.Grid, { justifyContent: "center", alignItems: "center", templateColumns: "200px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsxRuntime.jsx(react.Input, { onKeyDown: handleKeyDown, onChange: (e) => {
5825
- setInputValue(e.currentTarget.value);
5826
- }, onBlur: (e) => {
5827
- handleBlur(e.currentTarget.value);
5828
- }, onFocus: (e) => {
5829
- e.currentTarget.select();
5830
- }, value: inputValue, display: showInput ? undefined : "none", ref: inputRef }), jsxRuntime.jsxs(react.Button, { onClick: () => {
5831
- setShowInput(true);
5832
- setInputValue(dayjs(`1970-01-01T${getTimeString(hour, minute, meridiem)}`, "hh:mmZ").format("HH:mm"));
5833
- inputRef.current?.focus();
5834
- }, display: showInput ? "none" : "flex", alignItems: "center", justifyContent: "start", variant: "outline", gap: 2, children: [jsxRuntime.jsx(react.Icon, { size: "sm", children: jsxRuntime.jsx(bs.BsClock, {}) }), jsxRuntime.jsx(react.Text, { fontSize: "sm", children: stringTime
5835
- ? dayjs(`1970-01-01T${stringTime}`, "hh:mmZ").format("hh:mm a")
5836
- : "" })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }));
6055
+ return (jsxRuntime.jsxs(react.Grid, { justifyContent: 'center', alignItems: 'center', templateColumns: '200px auto', gap: "2", width: "auto", minWidth: "250px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, width: "100%", children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [isInputMode ? (jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { ref: inputRef, placeholder: "Select time", value: displayText, onKeyDown: handleKeyDown }) })) : (jsxRuntime.jsxs(react.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: [jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(bs.BsClock, {}) }), jsxRuntime.jsx(react.Text, { fontSize: "sm", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: displayText || 'Select time' }), jsxRuntime.jsx(react.Combobox.Trigger, { onClick: (e) => {
6056
+ e.stopPropagation();
6057
+ setIsInputMode(true);
6058
+ } })] })), isInputMode && (jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [jsxRuntime.jsx(react.Combobox.ClearTrigger, {}), jsxRuntime.jsx(react.Combobox.Trigger, {})] }))] }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [item.label, jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }));
5837
6059
  }
5838
6060
 
5839
6061
  dayjs.extend(timezone);
5840
6062
  const TimePicker = ({ column, schema, prefix }) => {
5841
6063
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5842
- const { translate, timezone } = useSchemaContext();
6064
+ const { translate, timezone, insideDialog } = useSchemaContext();
5843
6065
  const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
5844
6066
  const isRequired = required?.some((columnId) => columnId === column);
5845
6067
  const colLabel = `${prefix}${column}`;
@@ -5902,153 +6124,305 @@ const TimePicker = ({ column, schema, prefix }) => {
5902
6124
  ? translate.t(removeIndex(`${colLabel}.field_required`))
5903
6125
  : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5904
6126
  setOpen(true);
5905
- }, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
6127
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsxRuntime.jsx(react.Popover.Body, { overflow: "visible", children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5906
6128
  am: translate.t(`common.am`, { defaultValue: 'AM' }),
5907
6129
  pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
5908
- } }) }) }) })] }) }));
6130
+ } }) }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
6131
+ am: translate.t(`common.am`, { defaultValue: 'AM' }),
6132
+ pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
6133
+ } }) }) }) }) }))] }) }));
5909
6134
  };
5910
6135
 
5911
- function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
5912
- // Refs for focus management
5913
- const hourInputRef = React.useRef(null);
5914
- const minuteInputRef = React.useRef(null);
5915
- const secondInputRef = React.useRef(null);
5916
- // Centralized handler for key events, value changes, and focus management
5917
- const handleKeyDown = (e, field) => {
5918
- const input = e.target;
5919
- const value = input.value;
5920
- // Handle navigation between fields
5921
- if (e.key === "Tab") {
5922
- return;
5923
- }
5924
- if (e.key === ":" && field === "hour") {
5925
- e.preventDefault();
5926
- minuteInputRef.current?.focus();
5927
- return;
5928
- }
5929
- if (e.key === ":" && field === "minute") {
5930
- e.preventDefault();
5931
- secondInputRef.current?.focus();
5932
- return;
5933
- }
5934
- if (e.key === "Backspace" && value === "") {
5935
- e.preventDefault();
5936
- if (field === "minute") {
5937
- hourInputRef.current?.focus();
5938
- }
5939
- else if (field === "second") {
5940
- minuteInputRef.current?.focus();
6136
+ dayjs.extend(utc);
6137
+ dayjs.extend(timezone);
6138
+ function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
6139
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6140
+ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Kong', }) {
6141
+ // Generate time options (every 15 minutes, seconds always 0)
6142
+ const timeOptions = React.useMemo(() => {
6143
+ const options = [];
6144
+ // Get start time for comparison if provided
6145
+ let startDateTime = null;
6146
+ let shouldFilterByDate = false;
6147
+ if (startTime && selectedDate) {
6148
+ const startDateObj = dayjs(startTime).tz(timezone);
6149
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6150
+ if (startDateObj.isValid() && selectedDateObj.isValid()) {
6151
+ startDateTime = startDateObj;
6152
+ // Only filter if dates are the same
6153
+ shouldFilterByDate =
6154
+ startDateObj.format('YYYY-MM-DD') ===
6155
+ selectedDateObj.format('YYYY-MM-DD');
5941
6156
  }
5942
- return;
5943
6157
  }
5944
- // Handle number inputs
5945
- if (field === "hour") {
5946
- if (e.key.match(/^[0-9]$/)) {
5947
- const newValue = value + e.key;
5948
- const numValue = parseInt(newValue, 10);
5949
- if (numValue > 23) {
5950
- const digitValue = parseInt(e.key, 10);
5951
- setHour(digitValue);
5952
- onChange({ hour: digitValue, minute, second });
5953
- return;
6158
+ for (let h = 0; h < 24; h++) {
6159
+ for (let m = 0; m < 60; m += 15) {
6160
+ const timeDisplay = `${h.toString().padStart(2, '0')}:${m
6161
+ .toString()
6162
+ .padStart(2, '0')}:00`;
6163
+ // Filter out times that would result in negative duration (only when dates are the same)
6164
+ if (startDateTime && selectedDate && shouldFilterByDate) {
6165
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6166
+ const optionDateTime = selectedDateObj
6167
+ .hour(h)
6168
+ .minute(m)
6169
+ .second(0)
6170
+ .millisecond(0);
6171
+ if (optionDateTime.isBefore(startDateTime)) {
6172
+ continue; // Skip this option as it would result in negative duration
6173
+ }
5954
6174
  }
5955
- if (numValue >= 0 && numValue <= 23) {
5956
- setHour(numValue);
5957
- onChange({ hour: numValue, minute, second });
5958
- e.preventDefault();
5959
- minuteInputRef.current?.focus();
6175
+ // Calculate and append duration if startTime is provided
6176
+ let label = timeDisplay;
6177
+ if (startDateTime && selectedDate) {
6178
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6179
+ const optionDateTime = selectedDateObj
6180
+ .hour(h)
6181
+ .minute(m)
6182
+ .second(0)
6183
+ .millisecond(0);
6184
+ if (optionDateTime.isValid() &&
6185
+ optionDateTime.isAfter(startDateTime)) {
6186
+ const diffMs = optionDateTime.diff(startDateTime);
6187
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
6188
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
6189
+ const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000);
6190
+ if (diffHours > 0 || diffMinutes > 0 || diffSeconds > 0) {
6191
+ let diffText = '';
6192
+ if (diffHours > 0) {
6193
+ diffText = `${diffHours}h ${diffMinutes}m`;
6194
+ }
6195
+ else if (diffMinutes > 0) {
6196
+ diffText = `${diffMinutes}m ${diffSeconds}s`;
6197
+ }
6198
+ else {
6199
+ diffText = `${diffSeconds}s`;
6200
+ }
6201
+ label = `${timeDisplay} (+${diffText})`;
6202
+ }
6203
+ }
5960
6204
  }
6205
+ options.push({
6206
+ label,
6207
+ value: `${h}:${m}:0`,
6208
+ hour: h,
6209
+ minute: m,
6210
+ second: 0,
6211
+ searchText: timeDisplay, // Use base time without duration for searching
6212
+ });
5961
6213
  }
5962
6214
  }
5963
- else if (field === "minute") {
5964
- if (e.key.match(/^[0-9]$/)) {
5965
- const newValue = value + e.key;
5966
- const numValue = parseInt(newValue, 10);
5967
- if (numValue > 59) {
5968
- const digitValue = parseInt(e.key, 10);
5969
- setMinute(digitValue);
5970
- onChange({ hour, minute: digitValue, second });
5971
- return;
5972
- }
5973
- if (numValue >= 0 && numValue <= 59) {
5974
- setMinute(numValue);
5975
- onChange({ hour, minute: numValue, second });
5976
- e.preventDefault();
5977
- secondInputRef.current?.focus();
5978
- }
5979
- }
6215
+ return options;
6216
+ }, [startTime, selectedDate, timezone]);
6217
+ const { contains } = react.useFilter({ sensitivity: 'base' });
6218
+ const { collection, filter } = react.useListCollection({
6219
+ initialItems: timeOptions,
6220
+ itemToString: (item) => item.searchText, // Use searchText (without duration) for filtering
6221
+ itemToValue: (item) => item.value,
6222
+ filter: contains,
6223
+ });
6224
+ // Get current value string for combobox
6225
+ const currentValue = React.useMemo(() => {
6226
+ if (hour === null || minute === null || second === null) {
6227
+ return '';
5980
6228
  }
5981
- else if (field === "second") {
5982
- if (e.key.match(/^[0-9]$/)) {
5983
- const newValue = value + e.key;
5984
- const numValue = parseInt(newValue, 10);
5985
- if (numValue > 59) {
5986
- const digitValue = parseInt(e.key, 10);
5987
- setSecond(digitValue);
5988
- onChange({ hour, minute, second: digitValue });
5989
- return;
5990
- }
5991
- if (numValue >= 0 && numValue <= 59) {
5992
- setSecond(numValue);
5993
- onChange({ hour, minute, second: numValue });
6229
+ return `${hour}:${minute}:${second}`;
6230
+ }, [hour, minute, second]);
6231
+ // Get display text for combobox
6232
+ const displayText = React.useMemo(() => {
6233
+ if (hour === null || minute === null || second === null) {
6234
+ return '';
6235
+ }
6236
+ const timeDisplay = `${hour.toString().padStart(2, '0')}:${minute
6237
+ .toString()
6238
+ .padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
6239
+ // Show duration difference if startTime is provided
6240
+ if (startTime && selectedDate) {
6241
+ const startDateObj = dayjs(startTime).tz(timezone);
6242
+ const selectedDateObj = dayjs(selectedDate).tz(timezone);
6243
+ const currentDateTime = selectedDateObj
6244
+ .hour(hour)
6245
+ .minute(minute)
6246
+ .second(second ?? 0)
6247
+ .millisecond(0);
6248
+ if (startDateObj.isValid() && currentDateTime.isValid()) {
6249
+ const diffMs = currentDateTime.diff(startDateObj);
6250
+ if (diffMs >= 0) {
6251
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
6252
+ const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
6253
+ const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000);
6254
+ if (diffHours > 0 || diffMinutes > 0 || diffSeconds > 0) {
6255
+ let diffText = '';
6256
+ if (diffHours > 0) {
6257
+ diffText = `${diffHours}h ${diffMinutes}m`;
6258
+ }
6259
+ else if (diffMinutes > 0) {
6260
+ diffText = `${diffMinutes}m ${diffSeconds}s`;
6261
+ }
6262
+ else {
6263
+ diffText = `${diffSeconds}s`;
6264
+ }
6265
+ return `${timeDisplay} (+${diffText})`;
6266
+ }
5994
6267
  }
5995
6268
  }
5996
6269
  }
5997
- };
6270
+ return timeDisplay;
6271
+ }, [hour, minute, second, startTime, selectedDate, timezone]);
5998
6272
  const handleClear = () => {
5999
6273
  setHour(null);
6000
6274
  setMinute(null);
6001
6275
  setSecond(null);
6276
+ filter(''); // Reset filter to show all options
6002
6277
  onChange({ hour: null, minute: null, second: null });
6003
- hourInputRef.current?.focus();
6004
6278
  };
6005
- return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 10px 60px auto", gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsx(react.Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Text, { children: ":" }), jsxRuntime.jsx(react.Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Text, { children: ":" }), jsxRuntime.jsx(react.Input, { ref: secondInputRef, type: "text", value: second === null ? "" : second.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "second"), placeholder: "SS", maxLength: 2, textAlign: "center" }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }) }));
6279
+ const handleValueChange = (details) => {
6280
+ if (details.value.length === 0) {
6281
+ handleClear();
6282
+ return;
6283
+ }
6284
+ const selectedValue = details.value[0];
6285
+ const selectedOption = timeOptions.find((opt) => opt.value === selectedValue);
6286
+ if (selectedOption) {
6287
+ setHour(selectedOption.hour);
6288
+ setMinute(selectedOption.minute);
6289
+ setSecond(selectedOption.second);
6290
+ filter(''); // Reset filter after selection
6291
+ onChange({
6292
+ hour: selectedOption.hour,
6293
+ minute: selectedOption.minute,
6294
+ second: selectedOption.second,
6295
+ });
6296
+ }
6297
+ };
6298
+ const handleInputValueChange = (details) => {
6299
+ const inputValue = details.inputValue.trim();
6300
+ // Filter the collection based on input
6301
+ filter(inputValue);
6302
+ if (!inputValue) {
6303
+ return;
6304
+ }
6305
+ // Parse HH:mm:ss or HH:mm format
6306
+ const timePattern = /^(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/;
6307
+ const match = inputValue.match(timePattern);
6308
+ if (match) {
6309
+ const parsedHour = parseInt(match[1], 10);
6310
+ const parsedMinute = parseInt(match[2], 10);
6311
+ const parsedSecond = match[3] ? parseInt(match[3], 10) : 0;
6312
+ // Validate ranges
6313
+ if (parsedHour >= 0 &&
6314
+ parsedHour <= 23 &&
6315
+ parsedMinute >= 0 &&
6316
+ parsedMinute <= 59 &&
6317
+ parsedSecond >= 0 &&
6318
+ parsedSecond <= 59) {
6319
+ setHour(parsedHour);
6320
+ setMinute(parsedMinute);
6321
+ setSecond(parsedSecond);
6322
+ onChange({
6323
+ hour: parsedHour,
6324
+ minute: parsedMinute,
6325
+ second: parsedSecond,
6326
+ });
6327
+ }
6328
+ }
6329
+ else {
6330
+ // Try to parse formats like "123045" (HHmmss) or "1230" (HHmm)
6331
+ const numbersOnly = inputValue.replace(/[^0-9]/g, '');
6332
+ if (numbersOnly.length >= 4) {
6333
+ const parsedHour = parseInt(numbersOnly.slice(0, 2), 10);
6334
+ const parsedMinute = parseInt(numbersOnly.slice(2, 4), 10);
6335
+ const parsedSecond = numbersOnly.length >= 6 ? parseInt(numbersOnly.slice(4, 6), 10) : 0;
6336
+ // Validate ranges
6337
+ if (parsedHour >= 0 &&
6338
+ parsedHour <= 23 &&
6339
+ parsedMinute >= 0 &&
6340
+ parsedMinute <= 59 &&
6341
+ parsedSecond >= 0 &&
6342
+ parsedSecond <= 59) {
6343
+ setHour(parsedHour);
6344
+ setMinute(parsedMinute);
6345
+ setSecond(parsedSecond);
6346
+ onChange({
6347
+ hour: parsedHour,
6348
+ minute: parsedMinute,
6349
+ second: parsedSecond,
6350
+ });
6351
+ }
6352
+ }
6353
+ }
6354
+ };
6355
+ return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Grid, { justifyContent: 'center', alignItems: 'center', templateColumns: '1fr auto', gap: "2", width: "auto", minWidth: "300px", children: [jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, width: "100%", children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.InputGroup, { startElement: jsxRuntime.jsx(bs.BsClock, {}), children: jsxRuntime.jsx(react.Combobox.Input, { placeholder: "HH:mm:ss", value: displayText }) }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [jsxRuntime.jsx(react.Combobox.ClearTrigger, {}), jsxRuntime.jsx(react.Combobox.Trigger, {})] })] }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Combobox.Positioner, { children: jsxRuntime.jsxs(react.Combobox.Content, { children: [jsxRuntime.jsx(react.Combobox.Empty, { children: "No time found" }), collection.items.map((item) => (jsxRuntime.jsxs(react.Combobox.Item, { item: item, children: [item.label, jsxRuntime.jsx(react.Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(md.MdCancel, {}) }) })] }) }));
6006
6356
  }
6007
6357
 
6008
- function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds = false, labels = {
6358
+ dayjs.extend(utc);
6359
+ dayjs.extend(timezone);
6360
+ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds = false, labels = {
6009
6361
  monthNamesShort: [
6010
- "Jan",
6011
- "Feb",
6012
- "Mar",
6013
- "Apr",
6014
- "May",
6015
- "Jun",
6016
- "Jul",
6017
- "Aug",
6018
- "Sep",
6019
- "Oct",
6020
- "Nov",
6021
- "Dec",
6362
+ 'Jan',
6363
+ 'Feb',
6364
+ 'Mar',
6365
+ 'Apr',
6366
+ 'May',
6367
+ 'Jun',
6368
+ 'Jul',
6369
+ 'Aug',
6370
+ 'Sep',
6371
+ 'Oct',
6372
+ 'Nov',
6373
+ 'Dec',
6022
6374
  ],
6023
- weekdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
6024
- backButtonLabel: "Back",
6025
- forwardButtonLabel: "Next",
6026
- }, timezone = "Asia/Hong_Kong", }) {
6027
- const [selectedDate, setSelectedDate] = React.useState(value || "");
6375
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6376
+ backButtonLabel: 'Back',
6377
+ forwardButtonLabel: 'Next',
6378
+ }, timezone = 'Asia/Hong_Kong', startTime, }) {
6379
+ const [selectedDate, setSelectedDate] = React.useState(value || '');
6028
6380
  // Time state for 12-hour format
6029
6381
  const [hour12, setHour12] = React.useState(value ? dayjs(value).hour() % 12 || 12 : null);
6030
6382
  const [minute, setMinute] = React.useState(value ? dayjs(value).minute() : null);
6031
- const [meridiem, setMeridiem] = React.useState(value ? (dayjs(value).hour() >= 12 ? "pm" : "am") : null);
6383
+ const [meridiem, setMeridiem] = React.useState(value ? (dayjs(value).hour() >= 12 ? 'pm' : 'am') : null);
6032
6384
  // Time state for 24-hour format
6033
6385
  const [hour24, setHour24] = React.useState(value ? dayjs(value).hour() : null);
6034
- const [second, setSecond] = React.useState(value ? dayjs(value).second() : null);
6386
+ const [second, setSecond] = React.useState(showSeconds && value ? dayjs(value).second() : null);
6035
6387
  const handleDateChange = (date) => {
6036
6388
  setSelectedDate(date);
6037
- updateDateTime(dayjs(date).tz(timezone).toISOString());
6389
+ // When showSeconds is false, ignore seconds from the date
6390
+ const dateObj = dayjs(date).tz(timezone);
6391
+ if (!showSeconds && dateObj.isValid()) {
6392
+ const dateWithoutSeconds = dateObj.second(0).millisecond(0).toISOString();
6393
+ updateDateTime(dateWithoutSeconds);
6394
+ }
6395
+ else {
6396
+ updateDateTime(dateObj.toISOString());
6397
+ }
6038
6398
  };
6039
6399
  const handleTimeChange = (timeData) => {
6040
- if (format === "iso-date-time") {
6041
- setHour24(timeData.hour);
6042
- setMinute(timeData.minute);
6043
- if (showSeconds)
6044
- setSecond(timeData.second);
6400
+ if (format === 'iso-date-time') {
6401
+ const data = timeData;
6402
+ setHour24(data.hour);
6403
+ setMinute(data.minute);
6404
+ if (showSeconds) {
6405
+ setSecond(data.second ?? null);
6406
+ }
6407
+ else {
6408
+ // Ignore seconds - always set to null when showSeconds is false
6409
+ setSecond(null);
6410
+ }
6045
6411
  }
6046
6412
  else {
6047
- setHour12(timeData.hour);
6048
- setMinute(timeData.minute);
6049
- setMeridiem(timeData.meridiem);
6413
+ const data = timeData;
6414
+ setHour12(data.hour);
6415
+ setMinute(data.minute);
6416
+ setMeridiem(data.meridiem);
6417
+ }
6418
+ // Use selectedDate if valid, otherwise use today's date as fallback
6419
+ const dateToUse = selectedDate && dayjs(selectedDate).isValid()
6420
+ ? selectedDate
6421
+ : dayjs().tz(timezone).toISOString();
6422
+ const dateObj = dayjs(dateToUse).tz(timezone);
6423
+ if (dateObj.isValid()) {
6424
+ updateDateTime(dateObj.toISOString(), timeData);
6050
6425
  }
6051
- updateDateTime(dayjs(selectedDate).tz(timezone).toISOString(), timeData);
6052
6426
  };
6053
6427
  const updateDateTime = (date, timeData) => {
6054
6428
  if (!date) {
@@ -6056,27 +6430,33 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6056
6430
  return;
6057
6431
  }
6058
6432
  // use dayjs to convert the date to the timezone
6059
- const newDate = dayjs(date).tz(timezone).toDate();
6060
- if (format === "iso-date-time") {
6061
- const h = timeData?.hour ?? hour24;
6062
- const m = timeData?.minute ?? minute;
6063
- const s = showSeconds ? timeData?.second ?? second : 0;
6433
+ const dateObj = dayjs(date).tz(timezone);
6434
+ if (!dateObj.isValid()) {
6435
+ return;
6436
+ }
6437
+ const newDate = dateObj.toDate();
6438
+ if (format === 'iso-date-time') {
6439
+ const data = timeData;
6440
+ const h = data?.hour ?? hour24;
6441
+ const m = data?.minute ?? minute;
6442
+ // Always ignore seconds when showSeconds is false - set to 0
6443
+ const s = showSeconds ? data?.second ?? second ?? 0 : 0;
6064
6444
  if (h !== null)
6065
6445
  newDate.setHours(h);
6066
6446
  if (m !== null)
6067
6447
  newDate.setMinutes(m);
6068
- if (s !== null)
6069
- newDate.setSeconds(s);
6448
+ newDate.setSeconds(s);
6070
6449
  }
6071
6450
  else {
6072
- const h = timeData?.hour ?? hour12;
6073
- const m = timeData?.minute ?? minute;
6074
- const mer = timeData?.meridiem ?? meridiem;
6451
+ const data = timeData;
6452
+ const h = data?.hour ?? hour12;
6453
+ const m = data?.minute ?? minute;
6454
+ const mer = data?.meridiem ?? meridiem;
6075
6455
  if (h !== null && mer !== null) {
6076
6456
  let hour24 = h;
6077
- if (mer === "am" && h === 12)
6457
+ if (mer === 'am' && h === 12)
6078
6458
  hour24 = 0;
6079
- else if (mer === "pm" && h < 12)
6459
+ else if (mer === 'pm' && h < 12)
6080
6460
  hour24 = h + 12;
6081
6461
  newDate.setHours(hour24);
6082
6462
  }
@@ -6087,7 +6467,7 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6087
6467
  onChange?.(dayjs(newDate).tz(timezone).toISOString());
6088
6468
  };
6089
6469
  const handleClear = () => {
6090
- setSelectedDate("");
6470
+ setSelectedDate('');
6091
6471
  setHour12(null);
6092
6472
  setHour24(null);
6093
6473
  setMinute(null);
@@ -6095,21 +6475,26 @@ function DateTimePicker$1({ value, onChange, format = "date-time", showSeconds =
6095
6475
  setMeridiem(null);
6096
6476
  onChange?.(undefined);
6097
6477
  };
6098
- const isISO = format === "iso-date-time";
6099
- return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsxRuntime.jsx(DatePicker$1, { selected: selectedDate
6100
- ? dayjs(selectedDate).tz(timezone).toDate()
6101
- : new Date(), onDateSelected: ({ date }) => handleDateChange(dayjs(date).tz(timezone).toISOString()), monthsToDisplay: 1, labels: labels }), jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsxRuntime.jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: second, setSecond: setSecond, onChange: handleTimeChange })) : (jsxRuntime.jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsxRuntime.jsx(react.Icon, { as: fa6.FaTrash }) })] }), selectedDate && (jsxRuntime.jsxs(react.Flex, { gap: 2, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).format(isISO
6478
+ const isISO = format === 'iso-date-time';
6479
+ // Normalize startTime to ignore milliseconds
6480
+ const normalizedStartTime = startTime
6481
+ ? dayjs(startTime).tz(timezone).millisecond(0).toISOString()
6482
+ : undefined;
6483
+ return (jsxRuntime.jsxs(react.Flex, { direction: "column", gap: 4, p: 4, border: "1px solid", borderColor: "gray.200", borderRadius: "md", children: [jsxRuntime.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 &&
6484
+ dayjs(normalizedStartTime).tz(timezone).isValid()
6485
+ ? dayjs(normalizedStartTime).tz(timezone).startOf('day').toDate()
6486
+ : undefined }), jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsxRuntime.jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone })) : (jsxRuntime.jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone })), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsxRuntime.jsx(react.Icon, { as: fa6.FaTrash }) })] }), selectedDate && (jsxRuntime.jsxs(react.Flex, { gap: 2, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: dayjs(value).format(isISO
6102
6487
  ? showSeconds
6103
- ? "YYYY-MM-DD HH:mm:ss"
6104
- : "YYYY-MM-DD HH:mm"
6105
- : "YYYY-MM-DD hh:mm A ") }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: dayjs(value).tz(timezone).format("Z") }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: "gray.600", _dark: "gray.600" }, children: timezone })] }))] }));
6488
+ ? 'YYYY-MM-DD HH:mm:ss'
6489
+ : 'YYYY-MM-DD HH:mm'
6490
+ : 'YYYY-MM-DD hh:mm A ') }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: dayjs(value).tz(timezone).format('Z') }), jsxRuntime.jsx(react.Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
6106
6491
  }
6107
6492
 
6108
6493
  dayjs.extend(utc);
6109
6494
  dayjs.extend(timezone);
6110
6495
  const DateTimePicker = ({ column, schema, prefix, }) => {
6111
6496
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
6112
- const { timezone, dateTimePickerLabels } = useSchemaContext();
6497
+ const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
6113
6498
  const formI18n = useFormI18n(column, prefix);
6114
6499
  const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
6115
6500
  // with timezone
@@ -6144,82 +6529,84 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
6144
6529
  console.error(e);
6145
6530
  }
6146
6531
  }, [selectedDate, dateFormat, colLabel, setValue]);
6532
+ const dateTimePickerLabelsConfig = {
6533
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
6534
+ formI18n.translate.t(`common.month_1`, {
6535
+ defaultValue: 'January',
6536
+ }),
6537
+ formI18n.translate.t(`common.month_2`, {
6538
+ defaultValue: 'February',
6539
+ }),
6540
+ formI18n.translate.t(`common.month_3`, {
6541
+ defaultValue: 'March',
6542
+ }),
6543
+ formI18n.translate.t(`common.month_4`, {
6544
+ defaultValue: 'April',
6545
+ }),
6546
+ formI18n.translate.t(`common.month_5`, {
6547
+ defaultValue: 'May',
6548
+ }),
6549
+ formI18n.translate.t(`common.month_6`, {
6550
+ defaultValue: 'June',
6551
+ }),
6552
+ formI18n.translate.t(`common.month_7`, {
6553
+ defaultValue: 'July',
6554
+ }),
6555
+ formI18n.translate.t(`common.month_8`, {
6556
+ defaultValue: 'August',
6557
+ }),
6558
+ formI18n.translate.t(`common.month_9`, {
6559
+ defaultValue: 'September',
6560
+ }),
6561
+ formI18n.translate.t(`common.month_10`, {
6562
+ defaultValue: 'October',
6563
+ }),
6564
+ formI18n.translate.t(`common.month_11`, {
6565
+ defaultValue: 'November',
6566
+ }),
6567
+ formI18n.translate.t(`common.month_12`, {
6568
+ defaultValue: 'December',
6569
+ }),
6570
+ ],
6571
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
6572
+ formI18n.translate.t(`common.weekday_1`, {
6573
+ defaultValue: 'Sun',
6574
+ }),
6575
+ formI18n.translate.t(`common.weekday_2`, {
6576
+ defaultValue: 'Mon',
6577
+ }),
6578
+ formI18n.translate.t(`common.weekday_3`, {
6579
+ defaultValue: 'Tue',
6580
+ }),
6581
+ formI18n.translate.t(`common.weekday_4`, {
6582
+ defaultValue: 'Wed',
6583
+ }),
6584
+ formI18n.translate.t(`common.weekday_5`, {
6585
+ defaultValue: 'Thu',
6586
+ }),
6587
+ formI18n.translate.t(`common.weekday_6`, {
6588
+ defaultValue: 'Fri',
6589
+ }),
6590
+ formI18n.translate.t(`common.weekday_7`, {
6591
+ defaultValue: 'Sat',
6592
+ }),
6593
+ ],
6594
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
6595
+ formI18n.translate.t(`common.back_button`, {
6596
+ defaultValue: 'Back',
6597
+ }),
6598
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
6599
+ formI18n.translate.t(`common.forward_button`, {
6600
+ defaultValue: 'Forward',
6601
+ }),
6602
+ };
6603
+ const dateTimePickerContent = (jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
6604
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
6605
+ }, timezone: timezone, labels: dateTimePickerLabelsConfig }));
6147
6606
  return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
6148
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6607
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
6149
6608
  setOpen(true);
6150
- }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsxRuntime.jsx(PopoverContent, { minW: '450px', children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
6151
- setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
6152
- }, timezone: timezone, labels: {
6153
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
6154
- formI18n.translate.t(`common.month_1`, {
6155
- defaultValue: 'January',
6156
- }),
6157
- formI18n.translate.t(`common.month_2`, {
6158
- defaultValue: 'February',
6159
- }),
6160
- formI18n.translate.t(`common.month_3`, {
6161
- defaultValue: 'March',
6162
- }),
6163
- formI18n.translate.t(`common.month_4`, {
6164
- defaultValue: 'April',
6165
- }),
6166
- formI18n.translate.t(`common.month_5`, {
6167
- defaultValue: 'May',
6168
- }),
6169
- formI18n.translate.t(`common.month_6`, {
6170
- defaultValue: 'June',
6171
- }),
6172
- formI18n.translate.t(`common.month_7`, {
6173
- defaultValue: 'July',
6174
- }),
6175
- formI18n.translate.t(`common.month_8`, {
6176
- defaultValue: 'August',
6177
- }),
6178
- formI18n.translate.t(`common.month_9`, {
6179
- defaultValue: 'September',
6180
- }),
6181
- formI18n.translate.t(`common.month_10`, {
6182
- defaultValue: 'October',
6183
- }),
6184
- formI18n.translate.t(`common.month_11`, {
6185
- defaultValue: 'November',
6186
- }),
6187
- formI18n.translate.t(`common.month_12`, {
6188
- defaultValue: 'December',
6189
- }),
6190
- ],
6191
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
6192
- formI18n.translate.t(`common.weekday_1`, {
6193
- defaultValue: 'Sun',
6194
- }),
6195
- formI18n.translate.t(`common.weekday_2`, {
6196
- defaultValue: 'Mon',
6197
- }),
6198
- formI18n.translate.t(`common.weekday_3`, {
6199
- defaultValue: 'Tue',
6200
- }),
6201
- formI18n.translate.t(`common.weekday_4`, {
6202
- defaultValue: 'Wed',
6203
- }),
6204
- formI18n.translate.t(`common.weekday_5`, {
6205
- defaultValue: 'Thu',
6206
- }),
6207
- formI18n.translate.t(`common.weekday_6`, {
6208
- defaultValue: 'Fri',
6209
- }),
6210
- formI18n.translate.t(`common.weekday_7`, {
6211
- defaultValue: 'Sat',
6212
- }),
6213
- ],
6214
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
6215
- formI18n.translate.t(`common.back_button`, {
6216
- defaultValue: 'Back',
6217
- }),
6218
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
6219
- formI18n.translate.t(`common.forward_button`, {
6220
- defaultValue: 'Forward',
6221
- }),
6222
- } })] }) })] }) }));
6609
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: dateTimePickerContent }) }) })) : (jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsxRuntime.jsx(react.Popover.Body, { children: dateTimePickerContent }) }) }) }))] }) }));
6223
6610
  };
6224
6611
 
6225
6612
  const SchemaRenderer = ({ schema, prefix, column, }) => {
@@ -7130,7 +7517,7 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
7130
7517
  };
7131
7518
 
7132
7519
  const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7133
- const { columns, translate, data } = useDataTableContext();
7520
+ const { columns, data } = useDataTableContext();
7134
7521
  const columnsMap = Object.fromEntries(columns.map((def) => {
7135
7522
  const { accessorKey, id } = def;
7136
7523
  if (accessorKey) {
@@ -7144,7 +7531,7 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7144
7531
  if (!!size === false) {
7145
7532
  return 0;
7146
7533
  }
7147
- if (typeof size === "number") {
7534
+ if (typeof size === 'number') {
7148
7535
  return size;
7149
7536
  }
7150
7537
  return 0;
@@ -7153,39 +7540,40 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7153
7540
  const columnWidths = columns
7154
7541
  .map(({ size }) => {
7155
7542
  if (!!size === false) {
7156
- return "1fr";
7543
+ return '1fr';
7157
7544
  }
7158
7545
  return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
7159
7546
  })
7160
- .join(" ");
7161
- console.log({ columnWidths }, "hadfg");
7547
+ .join(' ');
7548
+ console.log({ columnWidths }, 'hadfg');
7162
7549
  const cellProps = {
7163
- flex: "1 0 0%",
7164
- overflow: "auto",
7165
- paddingX: "2",
7166
- py: "1",
7167
- color: { base: "colorPalette.900", _dark: "colorPalette.100" },
7168
- bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
7169
- borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
7170
- borderBottomWidth: "1px",
7550
+ flex: '1 0 0%',
7551
+ overflow: 'auto',
7552
+ paddingX: '2',
7553
+ py: '1',
7554
+ color: { base: 'colorPalette.900', _dark: 'colorPalette.100' },
7555
+ bgColor: { base: 'colorPalette.50', _dark: 'colorPalette.950' },
7556
+ borderBottomColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' },
7557
+ borderBottomWidth: '1px',
7171
7558
  ...{ colorPalette },
7172
7559
  };
7173
7560
  if (data.length <= 0) {
7174
7561
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyComponent });
7175
7562
  }
7176
- return (jsxRuntime.jsxs(react.Grid, { templateColumns: `${columnWidths}`, overflow: "auto", borderWidth: "1px", color: { base: "colorPalette.900", _dark: "colorPalette.100" }, borderColor: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: [jsxRuntime.jsx(react.Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: "colorPalette.200", _dark: "colorPalette.800" }, colorPalette, children: columnHeaders.map((header) => {
7177
- return (jsxRuntime.jsx(react.Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
7563
+ return (jsxRuntime.jsxs(react.Grid, { templateColumns: `${columnWidths}`, overflow: 'auto', borderWidth: '1px', color: { base: 'colorPalette.900', _dark: 'colorPalette.100' }, borderColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: [jsxRuntime.jsx(react.Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: columnHeaders.map((header) => {
7564
+ const columnDef = columnsMap[header];
7565
+ return (jsxRuntime.jsx(react.Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }));
7178
7566
  }) }), data.map((record) => {
7179
7567
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: columnHeaders.map((header) => {
7180
7568
  const { cell } = columnsMap[header];
7181
7569
  const value = record[header];
7182
7570
  if (!!record === false) {
7183
- return (jsxRuntime.jsx(react.Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
7571
+ return (jsxRuntime.jsx(react.Box, { ...cellProps }));
7184
7572
  }
7185
7573
  if (cell) {
7186
7574
  return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }));
7187
7575
  }
7188
- if (typeof value === "object") {
7576
+ if (typeof value === 'object') {
7189
7577
  return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
7190
7578
  }
7191
7579
  return jsxRuntime.jsx(react.Box, { ...cellProps, children: value });
@@ -7292,63 +7680,57 @@ const DefaultTableServer = ({ isLoading: isLoadingOverride, ...props }) => {
7292
7680
  };
7293
7681
 
7294
7682
  const CellRenderer = ({ cell }) => {
7295
- const { translate } = useDataTableContext();
7296
7683
  const getLabel = ({ columnId }) => {
7297
- if (translate !== undefined) {
7298
- return translate.t(`${columnId}`);
7299
- }
7300
- return snakeToLabel(columnId);
7684
+ const column = cell.column;
7685
+ return column.columnDef.meta?.displayName ?? snakeToLabel(columnId);
7301
7686
  };
7302
7687
  const formatValue = (value) => {
7303
- if (typeof value === "object") {
7688
+ if (typeof value === 'object') {
7304
7689
  return JSON.stringify(value);
7305
7690
  }
7306
- if (typeof value === "string") {
7691
+ if (typeof value === 'string') {
7307
7692
  return value;
7308
7693
  }
7309
- if (typeof value === "number" || typeof value === "boolean") {
7694
+ if (typeof value === 'number' || typeof value === 'boolean') {
7310
7695
  return `${value}`;
7311
7696
  }
7312
7697
  if (value === undefined) {
7313
- if (translate !== undefined) {
7314
- return translate.t(`undefined`);
7315
- }
7316
7698
  return `undefined`;
7317
7699
  }
7318
7700
  throw new Error(`value is unknown, ${typeof value}`);
7319
7701
  };
7320
7702
  const showCustomDataDisplay = cell.column.columnDef.meta?.showCustomDisplay ?? false;
7321
7703
  const gridColumn = cell.column.columnDef.meta?.gridColumn ?? [
7322
- "span 12",
7323
- "span 6",
7324
- "span 3",
7704
+ 'span 12',
7705
+ 'span 6',
7706
+ 'span 3',
7325
7707
  ];
7326
7708
  const gridRow = cell.column.columnDef.meta?.gridRow ?? {};
7327
7709
  if (showCustomDataDisplay) {
7328
7710
  return (jsxRuntime.jsx(react.Flex, { gridColumn, gridRow, children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
7329
7711
  }
7330
7712
  const value = cell.getValue();
7331
- if (typeof value === "object") {
7713
+ if (typeof value === 'object') {
7332
7714
  return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(RecordDisplay, { boxProps: {
7333
7715
  borderWidth: 1,
7334
7716
  borderRadius: 4,
7335
- borderColor: "gray.400",
7717
+ borderColor: 'gray.400',
7336
7718
  paddingX: 4,
7337
7719
  paddingY: 2,
7338
7720
  }, object: value })] }, cell.id));
7339
7721
  }
7340
- return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
7722
+ return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: 'colorPalette.400', children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: 'break-word', textOverflow: 'ellipsis', overflow: 'hidden', children: `${formatValue(cell.getValue())}` })] }, cell.id));
7341
7723
  };
7342
- const DataDisplay = ({ variant = "" }) => {
7343
- const { table, translate } = useDataTableContext();
7344
- return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "1", children: table.getRowModel().rows.map((row) => {
7724
+ const DataDisplay = ({ variant = '' }) => {
7725
+ const { table } = useDataTableContext();
7726
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: '1', children: table.getRowModel().rows.map((row) => {
7345
7727
  const rowId = row.id;
7346
- return (jsxRuntime.jsx(react.Card.Root, { children: jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: 4, padding: 4, gridTemplateColumns: "repeat(12, 1fr)", children: table.getAllColumns().map((column) => {
7728
+ return (jsxRuntime.jsx(react.Card.Root, { children: jsxRuntime.jsx(react.Card.Body, { display: 'grid', gap: 4, padding: 4, gridTemplateColumns: 'repeat(12, 1fr)', children: table.getAllColumns().map((column) => {
7347
7729
  const childCell = row.getAllCells().find((cell) => {
7348
7730
  return cell.id === `${rowId}_${column.id}`;
7349
7731
  });
7350
7732
  if (column.columns.length > 0) {
7351
- return (jsxRuntime.jsxs(react.Card.Root, { margin: "1", gridColumn: "span 12", children: [jsxRuntime.jsx(react.Card.Header, { color: "gray.400", children: translate.t(column.id) }), jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: "4", gridTemplateColumns: "repeat(12, 1fr)", children: column.columns.map((column) => {
7733
+ return (jsxRuntime.jsxs(react.Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsxRuntime.jsx(react.Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsxRuntime.jsx(react.Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((column) => {
7352
7734
  if (!column.getIsVisible()) {
7353
7735
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
7354
7736
  }