@bsol-oss/react-datatable5 13.0.1-beta.4 → 13.0.1-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -30,8 +30,8 @@ import addFormats from 'ajv-formats';
30
30
  import dayjs from 'dayjs';
31
31
  import utc from 'dayjs/plugin/utc';
32
32
  import timezone from 'dayjs/plugin/timezone';
33
- import { TiDeleteOutline } from 'react-icons/ti';
34
33
  import customParseFormat from 'dayjs/plugin/customParseFormat';
34
+ import { TiDeleteOutline } from 'react-icons/ti';
35
35
  import { rankItem } from '@tanstack/match-sorter-utils';
36
36
 
37
37
  const DataTableContext = createContext({
@@ -4525,6 +4525,9 @@ const CustomInput = ({ column, schema, prefix }) => {
4525
4525
  }));
4526
4526
  };
4527
4527
 
4528
+ dayjs.extend(utc);
4529
+ dayjs.extend(timezone);
4530
+ dayjs.extend(customParseFormat);
4528
4531
  const Calendar = ({ calendars, getBackProps, getForwardProps, getDateProps, firstDayOfWeek = 0, }) => {
4529
4532
  const { labels } = useContext(DatePickerContext);
4530
4533
  const { monthNamesShort, weekdayNamesShort, backButtonLabel, forwardButtonLabel, } = labels;
@@ -4594,6 +4597,9 @@ const DatePickerContext = createContext({
4594
4597
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4595
4598
  backButtonLabel: 'Back',
4596
4599
  forwardButtonLabel: 'Next',
4600
+ todayLabel: 'Today',
4601
+ yesterdayLabel: 'Yesterday',
4602
+ tomorrowLabel: 'Tomorrow',
4597
4603
  },
4598
4604
  });
4599
4605
  const DatePicker$1 = ({ labels = {
@@ -4614,6 +4620,9 @@ const DatePicker$1 = ({ labels = {
4614
4620
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4615
4621
  backButtonLabel: 'Back',
4616
4622
  forwardButtonLabel: 'Next',
4623
+ todayLabel: 'Today',
4624
+ yesterdayLabel: 'Yesterday',
4625
+ tomorrowLabel: 'Tomorrow',
4617
4626
  }, onDateSelected, selected, firstDayOfWeek, showOutsideDays, date, minDate, maxDate, monthsToDisplay, render, }) => {
4618
4627
  const calendarData = useCalendar({
4619
4628
  onDateSelected,
@@ -4628,9 +4637,164 @@ const DatePicker$1 = ({ labels = {
4628
4637
  return (jsx(DatePickerContext.Provider, { value: { labels }, children: render ? (render(calendarData)) : (jsx(Calendar, { ...calendarData,
4629
4638
  firstDayOfWeek })) }));
4630
4639
  };
4640
+ function DatePickerInput({ value, onChange, placeholder = 'Select a date', dateFormat = 'YYYY-MM-DD', displayFormat = 'YYYY-MM-DD', labels = {
4641
+ monthNamesShort: [
4642
+ 'Jan',
4643
+ 'Feb',
4644
+ 'Mar',
4645
+ 'Apr',
4646
+ 'May',
4647
+ 'Jun',
4648
+ 'Jul',
4649
+ 'Aug',
4650
+ 'Sep',
4651
+ 'Oct',
4652
+ 'Nov',
4653
+ 'Dec',
4654
+ ],
4655
+ weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
4656
+ backButtonLabel: 'Back',
4657
+ forwardButtonLabel: 'Next',
4658
+ todayLabel: 'Today',
4659
+ yesterdayLabel: 'Yesterday',
4660
+ tomorrowLabel: 'Tomorrow',
4661
+ }, timezone = 'Asia/Hong_Kong', minDate, maxDate, firstDayOfWeek, showOutsideDays, monthsToDisplay = 1, insideDialog = false, readOnly = false, showHelperButtons = true, }) {
4662
+ const [open, setOpen] = useState(false);
4663
+ const [inputValue, setInputValue] = useState('');
4664
+ // Update input value when prop value changes
4665
+ useEffect(() => {
4666
+ if (value) {
4667
+ const formatted = typeof value === 'string'
4668
+ ? dayjs(value).tz(timezone).isValid()
4669
+ ? dayjs(value).tz(timezone).format(displayFormat)
4670
+ : ''
4671
+ : dayjs(value).tz(timezone).format(displayFormat);
4672
+ setInputValue(formatted);
4673
+ }
4674
+ else {
4675
+ setInputValue('');
4676
+ }
4677
+ }, [value, displayFormat, timezone]);
4678
+ // Convert value to Date object for DatePicker
4679
+ const selectedDate = value
4680
+ ? typeof value === 'string'
4681
+ ? dayjs(value).tz(timezone).isValid()
4682
+ ? dayjs(value).tz(timezone).toDate()
4683
+ : new Date()
4684
+ : value
4685
+ : new Date();
4686
+ // Shared function to parse and validate input value
4687
+ const parseAndValidateInput = (inputVal) => {
4688
+ // If empty, clear the value
4689
+ if (!inputVal.trim()) {
4690
+ onChange?.(undefined);
4691
+ setInputValue('');
4692
+ return;
4693
+ }
4694
+ // Try parsing with displayFormat first
4695
+ let parsedDate = dayjs(inputVal, displayFormat, true);
4696
+ // If that fails, try common date formats
4697
+ if (!parsedDate.isValid()) {
4698
+ parsedDate = dayjs(inputVal);
4699
+ }
4700
+ // If still invalid, try parsing with dateFormat
4701
+ if (!parsedDate.isValid()) {
4702
+ parsedDate = dayjs(inputVal, dateFormat, true);
4703
+ }
4704
+ // If valid, check constraints and update
4705
+ if (parsedDate.isValid()) {
4706
+ const dateObj = parsedDate.tz(timezone).toDate();
4707
+ // Check min/max constraints
4708
+ if (minDate && dateObj < minDate) {
4709
+ // Invalid: before minDate, reset to prop value
4710
+ resetToPropValue();
4711
+ return;
4712
+ }
4713
+ if (maxDate && dateObj > maxDate) {
4714
+ // Invalid: after maxDate, reset to prop value
4715
+ resetToPropValue();
4716
+ return;
4717
+ }
4718
+ // Valid date - format and update
4719
+ const formattedDate = parsedDate.tz(timezone).format(dateFormat);
4720
+ const formattedDisplay = parsedDate.tz(timezone).format(displayFormat);
4721
+ onChange?.(formattedDate);
4722
+ setInputValue(formattedDisplay);
4723
+ }
4724
+ else {
4725
+ // Invalid date - reset to prop value
4726
+ resetToPropValue();
4727
+ }
4728
+ };
4729
+ // Helper function to reset input to prop value
4730
+ const resetToPropValue = () => {
4731
+ if (value) {
4732
+ const formatted = typeof value === 'string'
4733
+ ? dayjs(value).tz(timezone).isValid()
4734
+ ? dayjs(value).tz(timezone).format(displayFormat)
4735
+ : ''
4736
+ : dayjs(value).tz(timezone).format(displayFormat);
4737
+ setInputValue(formatted);
4738
+ }
4739
+ else {
4740
+ setInputValue('');
4741
+ }
4742
+ };
4743
+ const handleInputChange = (e) => {
4744
+ // Only update the input value, don't parse yet
4745
+ setInputValue(e.target.value);
4746
+ };
4747
+ const handleInputBlur = () => {
4748
+ // Parse and validate when input loses focus
4749
+ parseAndValidateInput(inputValue);
4750
+ };
4751
+ const handleKeyDown = (e) => {
4752
+ // Parse and validate when Enter is pressed
4753
+ if (e.key === 'Enter') {
4754
+ e.preventDefault();
4755
+ parseAndValidateInput(inputValue);
4756
+ }
4757
+ };
4758
+ const handleDateSelected = ({ date }) => {
4759
+ const formattedDate = dayjs(date).tz(timezone).format(dateFormat);
4760
+ onChange?.(formattedDate);
4761
+ setOpen(false);
4762
+ };
4763
+ // Helper function to get dates in the correct timezone
4764
+ const getToday = () => dayjs().tz(timezone).startOf('day').toDate();
4765
+ const getYesterday = () => dayjs().tz(timezone).subtract(1, 'day').startOf('day').toDate();
4766
+ const getTomorrow = () => dayjs().tz(timezone).add(1, 'day').startOf('day').toDate();
4767
+ // Check if a date is within min/max constraints
4768
+ const isDateValid = (date) => {
4769
+ if (minDate) {
4770
+ const minDateStart = dayjs(minDate).tz(timezone).startOf('day').toDate();
4771
+ const dateStart = dayjs(date).tz(timezone).startOf('day').toDate();
4772
+ if (dateStart < minDateStart)
4773
+ return false;
4774
+ }
4775
+ if (maxDate) {
4776
+ const maxDateStart = dayjs(maxDate).tz(timezone).startOf('day').toDate();
4777
+ const dateStart = dayjs(date).tz(timezone).startOf('day').toDate();
4778
+ if (dateStart > maxDateStart)
4779
+ return false;
4780
+ }
4781
+ return true;
4782
+ };
4783
+ const handleHelperButtonClick = (date) => {
4784
+ if (isDateValid(date)) {
4785
+ handleDateSelected({ date });
4786
+ }
4787
+ };
4788
+ const today = getToday();
4789
+ const yesterday = getYesterday();
4790
+ const tomorrow = getTomorrow();
4791
+ const datePickerContent = (jsxs(Grid, { gap: 2, children: [showHelperButtons && (jsxs(Grid, { templateColumns: "repeat(3, 1fr)", gap: 2, children: [jsx(Button$1, { size: "sm", variant: "outline", onClick: () => handleHelperButtonClick(yesterday), disabled: !isDateValid(yesterday), children: labels.yesterdayLabel ?? 'Yesterday' }), jsx(Button$1, { size: "sm", variant: "outline", onClick: () => handleHelperButtonClick(today), disabled: !isDateValid(today), children: labels.todayLabel ?? 'Today' }), jsx(Button$1, { size: "sm", variant: "outline", onClick: () => handleHelperButtonClick(tomorrow), disabled: !isDateValid(tomorrow), children: labels.tomorrowLabel ?? 'Tomorrow' })] })), jsx(DatePicker$1, { selected: selectedDate, onDateSelected: handleDateSelected, labels: labels, minDate: minDate, maxDate: maxDate, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, monthsToDisplay: monthsToDisplay })] }));
4792
+ return (jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(InputGroup, { endElement: jsx(Popover.Trigger, { asChild: true, children: jsx(IconButton, { variant: "ghost", size: "2xs", "aria-label": "Open calendar", onClick: () => setOpen(true), children: jsx(Icon, { children: jsx(MdDateRange, {}) }) }) }), children: jsx(Input, { value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleKeyDown, placeholder: placeholder, readOnly: readOnly }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) }) }))] }));
4793
+ }
4631
4794
 
4632
4795
  dayjs.extend(utc);
4633
4796
  dayjs.extend(timezone);
4797
+ dayjs.extend(customParseFormat);
4634
4798
  const DatePicker = ({ column, schema, prefix }) => {
4635
4799
  const { watch, formState: { errors }, setValue, } = useFormContext();
4636
4800
  const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
@@ -4639,15 +4803,29 @@ const DatePicker = ({ column, schema, prefix }) => {
4639
4803
  const isRequired = required?.some((columnId) => columnId === column);
4640
4804
  const colLabel = formI18n.colLabel;
4641
4805
  const [open, setOpen] = useState(false);
4806
+ const [inputValue, setInputValue] = useState('');
4642
4807
  const selectedDate = watch(colLabel);
4643
- const displayDate = dayjs(selectedDate)
4644
- .tz(timezone)
4645
- .format(displayDateFormat);
4808
+ // Update input value when form value changes
4809
+ useEffect(() => {
4810
+ if (selectedDate) {
4811
+ const parsedDate = dayjs(selectedDate).tz(timezone);
4812
+ if (parsedDate.isValid()) {
4813
+ const formatted = parsedDate.format(displayDateFormat);
4814
+ setInputValue(formatted);
4815
+ }
4816
+ else {
4817
+ setInputValue('');
4818
+ }
4819
+ }
4820
+ else {
4821
+ setInputValue('');
4822
+ }
4823
+ }, [selectedDate, displayDateFormat, timezone]);
4824
+ // Format and validate existing value
4646
4825
  useEffect(() => {
4647
4826
  try {
4648
4827
  if (selectedDate) {
4649
4828
  // Parse the selectedDate as UTC or in a specific timezone to avoid +8 hour shift
4650
- // For example, parse as UTC:
4651
4829
  const parsedDate = dayjs(selectedDate).tz(timezone);
4652
4830
  if (!parsedDate.isValid())
4653
4831
  return;
@@ -4665,7 +4843,7 @@ const DatePicker = ({ column, schema, prefix }) => {
4665
4843
  catch (e) {
4666
4844
  console.error(e);
4667
4845
  }
4668
- }, [selectedDate, dateFormat, colLabel, setValue]);
4846
+ }, [selectedDate, dateFormat, colLabel, setValue, timezone]);
4669
4847
  const datePickerLabels = {
4670
4848
  monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4671
4849
  'January',
@@ -4693,14 +4871,92 @@ const DatePicker = ({ column, schema, prefix }) => {
4693
4871
  backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? 'Back',
4694
4872
  forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? 'Forward',
4695
4873
  };
4696
- const datePickerContent = (jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4697
- setValue(colLabel, dayjs(date).format(dateFormat));
4698
- setOpen(false);
4699
- }, labels: datePickerLabels }));
4874
+ // Convert value to Date object for DatePicker
4875
+ const selectedDateObj = selectedDate
4876
+ ? dayjs(selectedDate).tz(timezone).isValid()
4877
+ ? dayjs(selectedDate).tz(timezone).toDate()
4878
+ : new Date()
4879
+ : new Date();
4880
+ // Shared function to parse and validate input value
4881
+ const parseAndValidateInput = (inputVal) => {
4882
+ // If empty, clear the value
4883
+ if (!inputVal.trim()) {
4884
+ setValue(colLabel, undefined, {
4885
+ shouldValidate: true,
4886
+ shouldDirty: true,
4887
+ });
4888
+ setInputValue('');
4889
+ return;
4890
+ }
4891
+ // Try parsing with displayDateFormat first
4892
+ let parsedDate = dayjs(inputVal, displayDateFormat, true);
4893
+ // If that fails, try common date formats
4894
+ if (!parsedDate.isValid()) {
4895
+ parsedDate = dayjs(inputVal);
4896
+ }
4897
+ // If still invalid, try parsing with dateFormat
4898
+ if (!parsedDate.isValid()) {
4899
+ parsedDate = dayjs(inputVal, dateFormat, true);
4900
+ }
4901
+ // If valid, format and update
4902
+ if (parsedDate.isValid()) {
4903
+ const formattedDate = parsedDate.tz(timezone).format(dateFormat);
4904
+ const formattedDisplay = parsedDate
4905
+ .tz(timezone)
4906
+ .format(displayDateFormat);
4907
+ setValue(colLabel, formattedDate, {
4908
+ shouldValidate: true,
4909
+ shouldDirty: true,
4910
+ });
4911
+ setInputValue(formattedDisplay);
4912
+ }
4913
+ else {
4914
+ // Invalid date - reset to prop value
4915
+ resetToPropValue();
4916
+ }
4917
+ };
4918
+ // Helper function to reset input to prop value
4919
+ const resetToPropValue = () => {
4920
+ if (selectedDate) {
4921
+ const parsedDate = dayjs(selectedDate).tz(timezone);
4922
+ if (parsedDate.isValid()) {
4923
+ const formatted = parsedDate.format(displayDateFormat);
4924
+ setInputValue(formatted);
4925
+ }
4926
+ else {
4927
+ setInputValue('');
4928
+ }
4929
+ }
4930
+ else {
4931
+ setInputValue('');
4932
+ }
4933
+ };
4934
+ const handleInputChange = (e) => {
4935
+ // Only update the input value, don't parse yet
4936
+ setInputValue(e.target.value);
4937
+ };
4938
+ const handleInputBlur = () => {
4939
+ // Parse and validate when input loses focus
4940
+ parseAndValidateInput(inputValue);
4941
+ };
4942
+ const handleKeyDown = (e) => {
4943
+ // Parse and validate when Enter is pressed
4944
+ if (e.key === 'Enter') {
4945
+ e.preventDefault();
4946
+ parseAndValidateInput(inputValue);
4947
+ }
4948
+ };
4949
+ const handleDateSelected = ({ date }) => {
4950
+ const formattedDate = dayjs(date).tz(timezone).format(dateFormat);
4951
+ setValue(colLabel, formattedDate, {
4952
+ shouldValidate: true,
4953
+ shouldDirty: true,
4954
+ });
4955
+ setOpen(false);
4956
+ };
4957
+ const datePickerContent = (jsx(DatePicker$1, { selected: selectedDateObj, onDateSelected: handleDateSelected, labels: datePickerLabels }));
4700
4958
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4701
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4702
- setOpen(true);
4703
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) }) }))] }) }));
4959
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(InputGroup, { endElement: jsx(Popover.Trigger, { asChild: true, children: jsx(IconButton, { variant: "ghost", size: "2xs", "aria-label": "Open calendar", onClick: () => setOpen(true), children: jsx(Icon, { children: jsx(MdDateRange, {}) }) }) }), children: jsx(Input, { value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleKeyDown, placeholder: formI18n.label(), size: "sm" }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) }) }))] }) }));
4704
4960
  };
4705
4961
 
4706
4962
  dayjs.extend(utc);
@@ -6432,14 +6688,74 @@ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
6432
6688
  }
6433
6689
  }
6434
6690
  }
6435
- return options;
6691
+ // Sort options by time (convert to 24-hour for proper chronological sorting)
6692
+ return options.sort((a, b) => {
6693
+ // Convert 12-hour to 24-hour for comparison
6694
+ let hour24A = a.hour;
6695
+ if (a.meridiem === 'am' && a.hour === 12)
6696
+ hour24A = 0;
6697
+ else if (a.meridiem === 'pm' && a.hour < 12)
6698
+ hour24A = a.hour + 12;
6699
+ let hour24B = b.hour;
6700
+ if (b.meridiem === 'am' && b.hour === 12)
6701
+ hour24B = 0;
6702
+ else if (b.meridiem === 'pm' && b.hour < 12)
6703
+ hour24B = b.hour + 12;
6704
+ // Compare by hour first, then minute
6705
+ if (hour24A !== hour24B) {
6706
+ return hour24A - hour24B;
6707
+ }
6708
+ return a.minute - b.minute;
6709
+ });
6436
6710
  }, [startTime, selectedDate, timezone]);
6437
- const { contains } = useFilter({ sensitivity: 'base' });
6711
+ // itemToString returns only the clean display text (no metadata)
6712
+ const itemToString = useMemo(() => {
6713
+ return (item) => {
6714
+ return item.searchText; // Clean display text only
6715
+ };
6716
+ }, []);
6717
+ // Custom filter function that filters by time and supports 24-hour format input
6718
+ const customTimeFilter = useMemo(() => {
6719
+ return (itemText, filterText) => {
6720
+ if (!filterText) {
6721
+ return true; // Show all items when no filter
6722
+ }
6723
+ const lowerItemText = itemText.toLowerCase();
6724
+ const lowerFilterText = filterText.toLowerCase();
6725
+ // First, try matching against the display text (12-hour format)
6726
+ if (lowerItemText.includes(lowerFilterText)) {
6727
+ return true;
6728
+ }
6729
+ // Find the corresponding item to check 24-hour format matches
6730
+ const item = timeOptions.find((opt) => opt.searchText.toLowerCase() === lowerItemText);
6731
+ if (!item) {
6732
+ return false;
6733
+ }
6734
+ // Convert item to 24-hour format for matching
6735
+ let hour24 = item.hour;
6736
+ if (item.meridiem === 'am' && item.hour === 12)
6737
+ hour24 = 0;
6738
+ else if (item.meridiem === 'pm' && item.hour < 12)
6739
+ hour24 = item.hour + 12;
6740
+ const hour24Str = hour24.toString().padStart(2, '0');
6741
+ const minuteStr = item.minute.toString().padStart(2, '0');
6742
+ // Check if filterText matches 24-hour format variations
6743
+ const formats = [
6744
+ `${hour24Str}:${minuteStr}`, // "13:30"
6745
+ `${hour24Str}${minuteStr}`, // "1330"
6746
+ hour24Str, // "13"
6747
+ `${hour24}:${minuteStr}`, // "13:30" (without padding)
6748
+ hour24.toString(), // "13" (without padding)
6749
+ ];
6750
+ return formats.some((format) => format.toLowerCase().includes(lowerFilterText) ||
6751
+ lowerFilterText.includes(format.toLowerCase()));
6752
+ };
6753
+ }, [timeOptions]);
6438
6754
  const { collection, filter } = useListCollection({
6439
6755
  initialItems: timeOptions,
6440
- itemToString: (item) => item.searchText, // Use searchText (without duration) for filtering
6756
+ itemToString: itemToString,
6441
6757
  itemToValue: (item) => item.value,
6442
- filter: contains,
6758
+ filter: customTimeFilter,
6443
6759
  });
6444
6760
  // Get current value string for combobox
6445
6761
  const currentValue = useMemo(() => {
@@ -6529,6 +6845,47 @@ const TimePicker$1 = ({ hour, setHour, minute, setMinute, meridiem, setMeridiem,
6529
6845
  if (!trimmedValue) {
6530
6846
  return;
6531
6847
  }
6848
+ // Parse 24-hour format first (e.g., "13:30", "14:00", "1330", "1400", "9:05", "905")
6849
+ const timePattern24Hour = /^(\d{1,2}):?(\d{2})$/;
6850
+ const match24Hour = trimmedValue.match(timePattern24Hour);
6851
+ if (match24Hour) {
6852
+ const parsedHour24 = parseInt(match24Hour[1], 10);
6853
+ const parsedMinute = parseInt(match24Hour[2], 10);
6854
+ // Validate 24-hour format ranges
6855
+ if (parsedHour24 >= 0 &&
6856
+ parsedHour24 <= 23 &&
6857
+ parsedMinute >= 0 &&
6858
+ parsedMinute <= 59) {
6859
+ // Convert 24-hour to 12-hour format
6860
+ let hour12;
6861
+ let meridiem;
6862
+ if (parsedHour24 === 0) {
6863
+ hour12 = 12;
6864
+ meridiem = 'am';
6865
+ }
6866
+ else if (parsedHour24 === 12) {
6867
+ hour12 = 12;
6868
+ meridiem = 'pm';
6869
+ }
6870
+ else if (parsedHour24 > 12) {
6871
+ hour12 = parsedHour24 - 12;
6872
+ meridiem = 'pm';
6873
+ }
6874
+ else {
6875
+ hour12 = parsedHour24;
6876
+ meridiem = 'am';
6877
+ }
6878
+ setHour(hour12);
6879
+ setMinute(parsedMinute);
6880
+ setMeridiem(meridiem);
6881
+ onChange({
6882
+ hour: hour12,
6883
+ minute: parsedMinute,
6884
+ meridiem: meridiem,
6885
+ });
6886
+ return;
6887
+ }
6888
+ }
6532
6889
  // Parse formats like "1:30 PM", "1:30PM", "1:30 pm", "1:30pm"
6533
6890
  const timePattern12Hour = /^(\d{1,2}):(\d{1,2})\s*(am|pm|AM|PM)$/i;
6534
6891
  const match12Hour = trimmedValue.match(timePattern12Hour);
@@ -6694,133 +7051,6 @@ const TimePicker = ({ column, schema, prefix }) => {
6694
7051
  }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, labels: timePickerLabels }) }) }) }) }))] }) }));
6695
7052
  };
6696
7053
 
6697
- dayjs.extend(utc);
6698
- dayjs.extend(timezone);
6699
- dayjs.extend(customParseFormat);
6700
- function DatePickerInput({ value, onChange, placeholder = 'Select a date', dateFormat = 'YYYY-MM-DD', displayFormat = 'YYYY-MM-DD', labels = {
6701
- monthNamesShort: [
6702
- 'Jan',
6703
- 'Feb',
6704
- 'Mar',
6705
- 'Apr',
6706
- 'May',
6707
- 'Jun',
6708
- 'Jul',
6709
- 'Aug',
6710
- 'Sep',
6711
- 'Oct',
6712
- 'Nov',
6713
- 'Dec',
6714
- ],
6715
- weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
6716
- backButtonLabel: 'Back',
6717
- forwardButtonLabel: 'Next',
6718
- }, timezone = 'Asia/Hong_Kong', minDate, maxDate, firstDayOfWeek, showOutsideDays, monthsToDisplay = 1, insideDialog = false, readOnly = false, }) {
6719
- const [open, setOpen] = useState(false);
6720
- const [inputValue, setInputValue] = useState('');
6721
- // Update input value when prop value changes
6722
- useEffect(() => {
6723
- if (value) {
6724
- const formatted = typeof value === 'string'
6725
- ? dayjs(value).tz(timezone).isValid()
6726
- ? dayjs(value).tz(timezone).format(displayFormat)
6727
- : ''
6728
- : dayjs(value).tz(timezone).format(displayFormat);
6729
- setInputValue(formatted);
6730
- }
6731
- else {
6732
- setInputValue('');
6733
- }
6734
- }, [value, displayFormat, timezone]);
6735
- // Convert value to Date object for DatePicker
6736
- const selectedDate = value
6737
- ? typeof value === 'string'
6738
- ? dayjs(value).tz(timezone).isValid()
6739
- ? dayjs(value).tz(timezone).toDate()
6740
- : new Date()
6741
- : value
6742
- : new Date();
6743
- // Shared function to parse and validate input value
6744
- const parseAndValidateInput = (inputVal) => {
6745
- // If empty, clear the value
6746
- if (!inputVal.trim()) {
6747
- onChange?.(undefined);
6748
- setInputValue('');
6749
- return;
6750
- }
6751
- // Try parsing with displayFormat first
6752
- let parsedDate = dayjs(inputVal, displayFormat, true);
6753
- // If that fails, try common date formats
6754
- if (!parsedDate.isValid()) {
6755
- parsedDate = dayjs(inputVal);
6756
- }
6757
- // If still invalid, try parsing with dateFormat
6758
- if (!parsedDate.isValid()) {
6759
- parsedDate = dayjs(inputVal, dateFormat, true);
6760
- }
6761
- // If valid, check constraints and update
6762
- if (parsedDate.isValid()) {
6763
- const dateObj = parsedDate.tz(timezone).toDate();
6764
- // Check min/max constraints
6765
- if (minDate && dateObj < minDate) {
6766
- // Invalid: before minDate, reset to prop value
6767
- resetToPropValue();
6768
- return;
6769
- }
6770
- if (maxDate && dateObj > maxDate) {
6771
- // Invalid: after maxDate, reset to prop value
6772
- resetToPropValue();
6773
- return;
6774
- }
6775
- // Valid date - format and update
6776
- const formattedDate = parsedDate.tz(timezone).format(dateFormat);
6777
- const formattedDisplay = parsedDate.tz(timezone).format(displayFormat);
6778
- onChange?.(formattedDate);
6779
- setInputValue(formattedDisplay);
6780
- }
6781
- else {
6782
- // Invalid date - reset to prop value
6783
- resetToPropValue();
6784
- }
6785
- };
6786
- // Helper function to reset input to prop value
6787
- const resetToPropValue = () => {
6788
- if (value) {
6789
- const formatted = typeof value === 'string'
6790
- ? dayjs(value).tz(timezone).isValid()
6791
- ? dayjs(value).tz(timezone).format(displayFormat)
6792
- : ''
6793
- : dayjs(value).tz(timezone).format(displayFormat);
6794
- setInputValue(formatted);
6795
- }
6796
- else {
6797
- setInputValue('');
6798
- }
6799
- };
6800
- const handleInputChange = (e) => {
6801
- // Only update the input value, don't parse yet
6802
- setInputValue(e.target.value);
6803
- };
6804
- const handleInputBlur = () => {
6805
- // Parse and validate when input loses focus
6806
- parseAndValidateInput(inputValue);
6807
- };
6808
- const handleKeyDown = (e) => {
6809
- // Parse and validate when Enter is pressed
6810
- if (e.key === 'Enter') {
6811
- e.preventDefault();
6812
- parseAndValidateInput(inputValue);
6813
- }
6814
- };
6815
- const handleDateSelected = ({ date }) => {
6816
- const formattedDate = dayjs(date).tz(timezone).format(dateFormat);
6817
- onChange?.(formattedDate);
6818
- setOpen(false);
6819
- };
6820
- const datePickerContent = (jsx(DatePicker$1, { selected: selectedDate, onDateSelected: handleDateSelected, labels: labels, minDate: minDate, maxDate: maxDate, firstDayOfWeek: firstDayOfWeek, showOutsideDays: showOutsideDays, monthsToDisplay: monthsToDisplay }));
6821
- return (jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(InputGroup, { endElement: jsx(Popover.Trigger, { asChild: true, children: jsx(IconButton, { variant: "ghost", size: "2xs", "aria-label": "Open calendar", onClick: () => setOpen(true), children: jsx(Icon, { children: jsx(MdDateRange, {}) }) }) }), children: jsx(Input, { value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleKeyDown, placeholder: placeholder, readOnly: readOnly }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minH: "25rem", children: jsx(Popover.Body, { children: datePickerContent }) }) }) }))] }));
6822
- }
6823
-
6824
7054
  dayjs.extend(utc);
6825
7055
  dayjs.extend(timezone);
6826
7056
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond,
@@ -7064,7 +7294,20 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
7064
7294
  });
7065
7295
  }
7066
7296
  };
7297
+ const [inputValue, setInputValue] = useState('');
7298
+ // Sync inputValue with currentValue when time changes externally
7299
+ useEffect(() => {
7300
+ if (hour !== null && minute !== null && second !== null) {
7301
+ const formattedValue = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
7302
+ setInputValue(formattedValue);
7303
+ }
7304
+ else {
7305
+ setInputValue('');
7306
+ }
7307
+ }, [hour, minute, second]);
7067
7308
  const handleInputValueChange = (details) => {
7309
+ // Update local input value state
7310
+ setInputValue(details.inputValue);
7068
7311
  // Filter the collection based on input, but don't parse yet
7069
7312
  filter(details.inputValue);
7070
7313
  };
@@ -7074,24 +7317,26 @@ onChange = (_newValue) => { }, startTime, selectedDate, timezone = 'Asia/Hong_Ko
7074
7317
  };
7075
7318
  const handleBlur = (e) => {
7076
7319
  // Parse and commit the input value when losing focus
7077
- const inputValue = e.target.value;
7078
- if (inputValue) {
7079
- parseAndCommitInput(inputValue);
7320
+ const inputVal = e.target.value;
7321
+ setInputValue(inputVal);
7322
+ if (inputVal) {
7323
+ parseAndCommitInput(inputVal);
7080
7324
  }
7081
7325
  };
7082
7326
  const handleKeyDown = (e) => {
7083
7327
  // Commit input on Enter key
7084
7328
  if (e.key === 'Enter') {
7085
7329
  e.preventDefault();
7086
- const inputValue = e.currentTarget.value;
7087
- if (inputValue) {
7088
- parseAndCommitInput(inputValue);
7330
+ const inputVal = e.currentTarget.value;
7331
+ setInputValue(inputVal);
7332
+ if (inputVal) {
7333
+ parseAndCommitInput(inputVal);
7089
7334
  }
7090
7335
  // Blur the input
7091
7336
  e.currentTarget?.blur();
7092
7337
  }
7093
7338
  };
7094
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { placeholder: labels.placeholder, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels.emptyMessage }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
7339
+ return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Flex, { alignItems: "center", gap: "2", width: "auto", minWidth: "300px", children: [jsxs(Combobox.Root, { collection: collection, value: currentValue ? [currentValue] : [], onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, allowCustomValue: true, selectionBehavior: "replace", openOnClick: true, flex: 1, children: [jsxs(Combobox.Control, { children: [jsx(InputGroup$1, { startElement: jsx(BsClock, {}), children: jsx(Combobox.Input, { value: inputValue, placeholder: labels.placeholder, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }) }), jsx(Combobox.IndicatorGroup, { children: jsx(Combobox.Trigger, {}) })] }), jsx(Portal, { disabled: !portalled, children: jsx(Combobox.Positioner, { children: jsxs(Combobox.Content, { children: [jsx(Combobox.Empty, { children: labels.emptyMessage }), collection.items.map((item) => (jsxs(Combobox.Item, { item: item, children: [jsxs(Flex, { alignItems: "center", gap: 2, width: "100%", children: [jsx(Text, { flex: 1, children: item.label }), item.durationText && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: item.durationText }) }))] }), jsx(Combobox.ItemIndicator, {})] }, item.value)))] }) }) })] }), durationDiff && (jsx(Tag$1.Root, { size: "sm", children: jsx(Tag$1.Label, { children: durationDiff }) })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(Icon, { children: jsx(MdCancel, {}) }) })] }) }));
7095
7340
  }
7096
7341
 
7097
7342
  dayjs.extend(utc);
@@ -7114,7 +7359,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7114
7359
  weekdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
7115
7360
  backButtonLabel: 'Back',
7116
7361
  forwardButtonLabel: 'Next',
7117
- }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, }) {
7362
+ }, timePickerLabels, timezone = 'Asia/Hong_Kong', startTime, minDate, maxDate, portalled = false, defaultDate, defaultTime, }) {
7118
7363
  console.log('[DateTimePicker] Component initialized with props:', {
7119
7364
  value,
7120
7365
  format,
@@ -7189,13 +7434,77 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7189
7434
  value,
7190
7435
  initialTime,
7191
7436
  });
7437
+ // Normalize startTime to ignore milliseconds (needed for effectiveDefaultDate calculation)
7438
+ const normalizedStartTime = startTime
7439
+ ? dayjs(startTime).tz(timezone).millisecond(0).toISOString()
7440
+ : undefined;
7441
+ // Calculate effective defaultDate: use prop if provided, otherwise use startTime date, otherwise use today
7442
+ const effectiveDefaultDate = useMemo(() => {
7443
+ if (defaultDate) {
7444
+ return defaultDate;
7445
+ }
7446
+ if (normalizedStartTime &&
7447
+ dayjs(normalizedStartTime).tz(timezone).isValid()) {
7448
+ return dayjs(normalizedStartTime).tz(timezone).format('YYYY-MM-DD');
7449
+ }
7450
+ return dayjs().tz(timezone).format('YYYY-MM-DD');
7451
+ }, [defaultDate, normalizedStartTime, timezone]);
7452
+ // Initialize time with default values if no value is provided
7453
+ const getInitialTimeValues = () => {
7454
+ if (value && initialTime.hour12 !== null) {
7455
+ return initialTime;
7456
+ }
7457
+ // If no value or no time in value, use defaultTime or 00:00
7458
+ if (defaultTime) {
7459
+ if (format === 'iso-date-time') {
7460
+ const defaultTime24 = defaultTime;
7461
+ return {
7462
+ hour12: null,
7463
+ minute: defaultTime24.minute ?? 0,
7464
+ meridiem: null,
7465
+ hour24: defaultTime24.hour ?? 0,
7466
+ second: showSeconds ? defaultTime24.second ?? 0 : null,
7467
+ };
7468
+ }
7469
+ else {
7470
+ const defaultTime12 = defaultTime;
7471
+ return {
7472
+ hour12: defaultTime12.hour ?? 12,
7473
+ minute: defaultTime12.minute ?? 0,
7474
+ meridiem: defaultTime12.meridiem ?? 'am',
7475
+ hour24: null,
7476
+ second: null,
7477
+ };
7478
+ }
7479
+ }
7480
+ // Default to 00:00
7481
+ if (format === 'iso-date-time') {
7482
+ return {
7483
+ hour12: null,
7484
+ minute: 0,
7485
+ meridiem: null,
7486
+ hour24: 0,
7487
+ second: showSeconds ? 0 : null,
7488
+ };
7489
+ }
7490
+ else {
7491
+ return {
7492
+ hour12: 12,
7493
+ minute: 0,
7494
+ meridiem: 'am',
7495
+ hour24: null,
7496
+ second: null,
7497
+ };
7498
+ }
7499
+ };
7500
+ const initialTimeValues = getInitialTimeValues();
7192
7501
  // Time state for 12-hour format
7193
- const [hour12, setHour12] = useState(initialTime.hour12);
7194
- const [minute, setMinute] = useState(initialTime.minute);
7195
- const [meridiem, setMeridiem] = useState(initialTime.meridiem);
7502
+ const [hour12, setHour12] = useState(initialTimeValues.hour12);
7503
+ const [minute, setMinute] = useState(initialTimeValues.minute);
7504
+ const [meridiem, setMeridiem] = useState(initialTimeValues.meridiem);
7196
7505
  // Time state for 24-hour format
7197
- const [hour24, setHour24] = useState(initialTime.hour24);
7198
- const [second, setSecond] = useState(initialTime.second);
7506
+ const [hour24, setHour24] = useState(initialTimeValues.hour24);
7507
+ const [second, setSecond] = useState(initialTimeValues.second);
7199
7508
  // Sync selectedDate and time states when value prop changes
7200
7509
  useEffect(() => {
7201
7510
  console.log('[DateTimePicker] useEffect triggered - value changed:', {
@@ -7203,27 +7512,47 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7203
7512
  timezone,
7204
7513
  format,
7205
7514
  });
7206
- // If value is null, undefined, or invalid, clear all fields
7515
+ // If value is null, undefined, or invalid, clear date but keep default time values
7207
7516
  if (!value || value === null || value === undefined) {
7208
- console.log('[DateTimePicker] Value is null/undefined, clearing all fields');
7517
+ console.log('[DateTimePicker] Value is null/undefined, clearing date but keeping default time');
7209
7518
  setSelectedDate('');
7210
- setHour12(null);
7211
- setMinute(null);
7212
- setMeridiem(null);
7213
- setHour24(null);
7214
- setSecond(null);
7519
+ // Keep default time values instead of clearing them
7520
+ if (format === 'iso-date-time') {
7521
+ setHour24(defaultTime ? defaultTime.hour ?? 0 : 0);
7522
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7523
+ setSecond(showSeconds
7524
+ ? defaultTime
7525
+ ? defaultTime.second ?? 0
7526
+ : 0
7527
+ : null);
7528
+ }
7529
+ else {
7530
+ setHour12(defaultTime ? defaultTime.hour ?? 12 : 12);
7531
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7532
+ setMeridiem(defaultTime ? defaultTime.meridiem ?? 'am' : 'am');
7533
+ }
7215
7534
  return;
7216
7535
  }
7217
7536
  // Check if value is valid
7218
7537
  const dateObj = dayjs(value).tz(timezone);
7219
7538
  if (!dateObj.isValid()) {
7220
- console.log('[DateTimePicker] Invalid value, clearing all fields');
7539
+ console.log('[DateTimePicker] Invalid value, clearing date but keeping default time');
7221
7540
  setSelectedDate('');
7222
- setHour12(null);
7223
- setMinute(null);
7224
- setMeridiem(null);
7225
- setHour24(null);
7226
- setSecond(null);
7541
+ // Keep default time values instead of clearing them
7542
+ if (format === 'iso-date-time') {
7543
+ setHour24(defaultTime ? defaultTime.hour ?? 0 : 0);
7544
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7545
+ setSecond(showSeconds
7546
+ ? defaultTime
7547
+ ? defaultTime.second ?? 0
7548
+ : 0
7549
+ : null);
7550
+ }
7551
+ else {
7552
+ setHour12(defaultTime ? defaultTime.hour ?? 12 : 12);
7553
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7554
+ setMeridiem(defaultTime ? defaultTime.meridiem ?? 'am' : 'am');
7555
+ }
7227
7556
  return;
7228
7557
  }
7229
7558
  const dateString = getDateString(value);
@@ -7279,16 +7608,76 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7279
7608
  onChange?.(undefined);
7280
7609
  return;
7281
7610
  }
7611
+ // Check if time values are null - if so, use defaultTime or set to 00:00
7612
+ const hasTimeValues = format === 'iso-date-time'
7613
+ ? hour24 !== null || minute !== null
7614
+ : hour12 !== null || minute !== null || meridiem !== null;
7615
+ let timeDataToUse = undefined;
7616
+ if (!hasTimeValues) {
7617
+ // Use defaultTime if provided, otherwise default to 00:00
7618
+ if (defaultTime) {
7619
+ console.log('[DateTimePicker] No time values set, using defaultTime');
7620
+ if (format === 'iso-date-time') {
7621
+ const defaultTime24 = defaultTime;
7622
+ setHour24(defaultTime24.hour ?? 0);
7623
+ setMinute(defaultTime24.minute ?? 0);
7624
+ if (showSeconds) {
7625
+ setSecond(defaultTime24.second ?? 0);
7626
+ }
7627
+ timeDataToUse = {
7628
+ hour: defaultTime24.hour ?? 0,
7629
+ minute: defaultTime24.minute ?? 0,
7630
+ second: showSeconds ? defaultTime24.second ?? 0 : undefined,
7631
+ };
7632
+ }
7633
+ else {
7634
+ const defaultTime12 = defaultTime;
7635
+ setHour12(defaultTime12.hour ?? 12);
7636
+ setMinute(defaultTime12.minute ?? 0);
7637
+ setMeridiem(defaultTime12.meridiem ?? 'am');
7638
+ timeDataToUse = {
7639
+ hour: defaultTime12.hour ?? 12,
7640
+ minute: defaultTime12.minute ?? 0,
7641
+ meridiem: defaultTime12.meridiem ?? 'am',
7642
+ };
7643
+ }
7644
+ }
7645
+ else {
7646
+ console.log('[DateTimePicker] No time values set, defaulting to 00:00');
7647
+ if (format === 'iso-date-time') {
7648
+ setHour24(0);
7649
+ setMinute(0);
7650
+ if (showSeconds) {
7651
+ setSecond(0);
7652
+ }
7653
+ timeDataToUse = {
7654
+ hour: 0,
7655
+ minute: 0,
7656
+ second: showSeconds ? 0 : undefined,
7657
+ };
7658
+ }
7659
+ else {
7660
+ setHour12(12);
7661
+ setMinute(0);
7662
+ setMeridiem('am');
7663
+ timeDataToUse = {
7664
+ hour: 12,
7665
+ minute: 0,
7666
+ meridiem: 'am',
7667
+ };
7668
+ }
7669
+ }
7670
+ }
7282
7671
  // When showSeconds is false, ignore seconds from the date
7283
7672
  if (!showSeconds) {
7284
7673
  const dateWithoutSeconds = dateObj.second(0).millisecond(0).toISOString();
7285
7674
  console.log('[DateTimePicker] Updating date without seconds:', dateWithoutSeconds);
7286
- updateDateTime(dateWithoutSeconds);
7675
+ updateDateTime(dateWithoutSeconds, timeDataToUse);
7287
7676
  }
7288
7677
  else {
7289
7678
  const dateWithSeconds = dateObj.toISOString();
7290
7679
  console.log('[DateTimePicker] Updating date with seconds:', dateWithSeconds);
7291
- updateDateTime(dateWithSeconds);
7680
+ updateDateTime(dateWithSeconds, timeDataToUse);
7292
7681
  }
7293
7682
  };
7294
7683
  const handleTimeChange = (timeData) => {
@@ -7318,17 +7707,36 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7318
7707
  setMinute(data.minute);
7319
7708
  setMeridiem(data.meridiem);
7320
7709
  }
7321
- // Use selectedDate if valid, otherwise clear all fields
7710
+ // Use selectedDate if valid, otherwise use effectiveDefaultDate or clear all fields
7322
7711
  if (!selectedDate || !dayjs(selectedDate).isValid()) {
7323
- console.log('[DateTimePicker] No valid selectedDate, clearing all fields');
7324
- setSelectedDate('');
7325
- setHour12(null);
7326
- setMinute(null);
7327
- setMeridiem(null);
7328
- setHour24(null);
7329
- setSecond(null);
7330
- onChange?.(undefined);
7331
- return;
7712
+ // If effectiveDefaultDate is available, use it instead of clearing
7713
+ if (effectiveDefaultDate && dayjs(effectiveDefaultDate).isValid()) {
7714
+ console.log('[DateTimePicker] No valid selectedDate, using effectiveDefaultDate:', effectiveDefaultDate);
7715
+ setSelectedDate(effectiveDefaultDate);
7716
+ const dateObj = dayjs(effectiveDefaultDate).tz(timezone);
7717
+ if (dateObj.isValid()) {
7718
+ updateDateTime(dateObj.toISOString(), timeData);
7719
+ }
7720
+ else {
7721
+ console.warn('[DateTimePicker] Invalid effectiveDefaultDate, clearing fields');
7722
+ setSelectedDate('');
7723
+ setHour12(null);
7724
+ setMinute(null);
7725
+ setMeridiem(null);
7726
+ setHour24(null);
7727
+ setSecond(null);
7728
+ onChange?.(undefined);
7729
+ }
7730
+ return;
7731
+ }
7732
+ else {
7733
+ console.log('[DateTimePicker] No valid selectedDate and no effectiveDefaultDate, keeping time values but no date');
7734
+ // Keep the time values that were just set, but don't set a date
7735
+ // This should rarely happen as effectiveDefaultDate always defaults to today
7736
+ setSelectedDate('');
7737
+ onChange?.(undefined);
7738
+ return;
7739
+ }
7332
7740
  }
7333
7741
  const dateObj = dayjs(selectedDate).tz(timezone);
7334
7742
  if (dateObj.isValid()) {
@@ -7471,18 +7879,24 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7471
7879
  };
7472
7880
  const handleClear = () => {
7473
7881
  setSelectedDate('');
7474
- setHour12(null);
7475
- setHour24(null);
7476
- setMinute(null);
7477
- setSecond(null);
7478
- setMeridiem(null);
7882
+ // Reset to default time values instead of clearing them
7883
+ if (format === 'iso-date-time') {
7884
+ setHour24(defaultTime ? defaultTime.hour ?? 0 : 0);
7885
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7886
+ setSecond(showSeconds
7887
+ ? defaultTime
7888
+ ? defaultTime.second ?? 0
7889
+ : 0
7890
+ : null);
7891
+ }
7892
+ else {
7893
+ setHour12(defaultTime ? defaultTime.hour ?? 12 : 12);
7894
+ setMinute(defaultTime ? defaultTime.minute ?? 0 : 0);
7895
+ setMeridiem(defaultTime ? defaultTime.meridiem ?? 'am' : 'am');
7896
+ }
7479
7897
  onChange?.(undefined);
7480
7898
  };
7481
7899
  const isISO = format === 'iso-date-time';
7482
- // Normalize startTime to ignore milliseconds
7483
- const normalizedStartTime = startTime
7484
- ? dayjs(startTime).tz(timezone).millisecond(0).toISOString()
7485
- : undefined;
7486
7900
  // Determine minDate: prioritize explicit minDate prop, then fall back to startTime
7487
7901
  const effectiveMinDate = minDate
7488
7902
  ? minDate
@@ -7560,7 +7974,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7560
7974
  const dateObj = dayjs.tz(selectedDate, timezone);
7561
7975
  return dateObj.isValid() ? dateObj.format('Z') : null;
7562
7976
  }, [selectedDate, timezone]);
7563
- return (jsxs(Flex, { direction: "column", gap: 4, children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7977
+ return (jsxs(Flex, { direction: "column", gap: 2, children: [jsx(DatePickerInput, { value: selectedDate || undefined, onChange: (date) => {
7564
7978
  if (date) {
7565
7979
  handleDateChange(date);
7566
7980
  }
@@ -7568,7 +7982,7 @@ function DateTimePicker$1({ value, onChange, format = 'date-time', showSeconds =
7568
7982
  setSelectedDate('');
7569
7983
  onChange?.(undefined);
7570
7984
  }
7571
- }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: true }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 4, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7985
+ }, placeholder: "Select a date", dateFormat: "YYYY-MM-DD", displayFormat: "YYYY-MM-DD", labels: labels, timezone: timezone, minDate: effectiveMinDate, maxDate: maxDate, monthsToDisplay: 1, readOnly: false }), jsxs(Grid, { templateColumns: "1fr auto", alignItems: "center", gap: 2, children: [isISO ? (jsx(IsoTimePicker, { hour: hour24, setHour: setHour24, minute: minute, setMinute: setMinute, second: showSeconds ? second : null, setSecond: showSeconds ? setSecond : () => { }, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })) : (jsx(TimePicker$1, { hour: hour12, setHour: setHour12, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, startTime: normalizedStartTime, selectedDate: selectedDate, timezone: timezone, portalled: portalled, labels: timePickerLabels })), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "outline", colorScheme: "red", children: jsx(Icon, { as: FaTrash }) })] }), displayText && (jsxs(Flex, { gap: 2, children: [jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: displayText }), timezoneOffset && (jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezoneOffset })), jsx(Text, { fontSize: "sm", color: { base: 'gray.600', _dark: 'gray.600' }, children: timezone })] }))] }));
7572
7986
  }
7573
7987
 
7574
7988
  dayjs.extend(utc);
@@ -7630,7 +8044,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
7630
8044
  return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
7631
8045
  gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, autoFocus: false, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
7632
8046
  setOpen(true);
7633
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), displayDate || ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "450px", minH: "25rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) }) }))] }) }));
8047
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), displayDate || ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "350px", minH: "10rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) })) : (jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { width: "fit-content", minW: "350px", minH: "10rem", children: jsx(Popover.Body, { children: dateTimePickerContent }) }) }) }))] }) }));
7634
8048
  };
7635
8049
 
7636
8050
  const SchemaRenderer = ({ schema, prefix, column, }) => {