@bsol-oss/react-datatable5 12.0.0-beta.65 → 12.0.0-beta.67

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
@@ -3718,6 +3718,7 @@ const validateData = (data, schema) => {
3718
3718
  const validate = ajv.compile(schema);
3719
3719
  const validationResult = validate(data);
3720
3720
  const errors = validate.errors;
3721
+ console.log(errors, data);
3721
3722
  return {
3722
3723
  isValid: validationResult,
3723
3724
  validate,
@@ -5031,92 +5032,125 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
5031
5032
  function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
5032
5033
  am: "am",
5033
5034
  pm: "pm",
5034
- }, onChange = (_newValue) => { }, }) {
5035
- // Refs for focus management
5036
- const hourInputRef = React.useRef(null);
5037
- const minuteInputRef = React.useRef(null);
5038
- React.useRef(null);
5039
- // Centralized handler for key events, value changes, and focus management
5040
- const handleKeyDown = (e, field) => {
5041
- const input = e.target;
5042
- const value = input.value;
5043
- // Handle navigation between fields
5044
- if (e.key === "Tab") {
5045
- // Tab is handled by the browser, no need to override
5035
+ }, onChange = (_newValue) => { }, timezone = "Asia/Hong_Kong", }) {
5036
+ const handleClear = () => {
5037
+ setHour(null);
5038
+ setMinute(null);
5039
+ setMeridiem(null);
5040
+ setInputValue("");
5041
+ setShowInput(false);
5042
+ onChange({ hour: null, minute: null, meridiem: null });
5043
+ };
5044
+ const getTimeString = (hour, minute, meridiem) => {
5045
+ if (hour === null || minute === null || meridiem === null) {
5046
+ return "";
5047
+ }
5048
+ // if the hour is 24, set the hour to 0
5049
+ if (hour === 24) {
5050
+ return dayjs().tz(timezone).hour(0).minute(minute).format("HH:mmZ");
5051
+ }
5052
+ // use dayjs to format the time at current timezone
5053
+ // if meridiem is pm, add 12 hours
5054
+ let newHour = hour;
5055
+ if (meridiem === "pm" && hour !== 12) {
5056
+ newHour = hour + 12;
5057
+ }
5058
+ // if the hour is 12, set the meridiem to am, and set the hour to 0
5059
+ else if (meridiem === "am" && hour === 12) {
5060
+ newHour = 0;
5061
+ }
5062
+ return dayjs().tz(timezone).hour(newHour).minute(minute).format("HH:mmZ");
5063
+ };
5064
+ const stringTime = getTimeString(hour, minute, meridiem);
5065
+ const [inputValue, setInputValue] = React.useState("");
5066
+ const [showInput, setShowInput] = React.useState(false);
5067
+ const handleBlur = (text) => {
5068
+ // ignore all non-numeric characters
5069
+ if (!text) {
5046
5070
  return;
5047
5071
  }
5048
- if (e.key === ":" && field === "hour") {
5049
- e.preventDefault();
5050
- minuteInputRef.current?.focus();
5072
+ const value = text.replace(/[^0-9apm]/g, "");
5073
+ if (value === "") {
5074
+ handleClear();
5051
5075
  return;
5052
5076
  }
5053
- if (e.key === "Backspace" && value === "") {
5054
- e.preventDefault();
5055
- if (field === "minute") {
5056
- hourInputRef.current?.focus();
5057
- }
5058
- else if (field === "meridiem") {
5059
- minuteInputRef.current?.focus();
5060
- }
5077
+ // if the value is a valid time, parse it and set the hour, minute, and meridiem
5078
+ // if the value is not a valid time, set the stringTime to the value
5079
+ // first two characters are the hour
5080
+ // next two characters are the minute
5081
+ // final two characters are the meridiem
5082
+ const hour = parseInt(value.slice(0, 2));
5083
+ const minute = parseInt(value.slice(2, 4));
5084
+ const meridiem = value.slice(4, 6);
5085
+ // validate the hour and minute
5086
+ if (isNaN(hour) || isNaN(minute)) {
5087
+ setInputValue("");
5061
5088
  return;
5062
5089
  }
5063
- // Handle number inputs
5064
- if (field === "hour") {
5065
- if (e.key.match(/^[0-9]$/)) {
5066
- const newValue = value + e.key;
5067
- const numValue = parseInt(newValue, 10);
5068
- console.log("newValue", newValue, numValue);
5069
- if (numValue > 12) {
5070
- const digitValue = parseInt(e.key, 10);
5071
- setHour(digitValue);
5072
- onChange({ hour: digitValue, minute, meridiem });
5073
- return;
5074
- }
5075
- // Auto-advance to minutes if we have a valid hour (1-12)
5076
- if (numValue >= 1 && numValue <= 12) {
5077
- // Set the hour value
5078
- setHour(numValue);
5079
- onChange({ hour: numValue, minute, meridiem });
5080
- // Move to minute input
5081
- e.preventDefault();
5082
- minuteInputRef.current?.focus();
5083
- }
5084
- }
5090
+ // if the hour is larger than 24, set the hour to 24
5091
+ if (hour > 24) {
5092
+ setInputValue("");
5093
+ return;
5085
5094
  }
5086
- else if (field === "minute") {
5087
- if (e.key.match(/^[0-9]$/)) {
5088
- const newValue = value + e.key;
5089
- const numValue = parseInt(newValue, 10);
5090
- console.log("newValue minute", newValue, numValue, numValue > 60, numValue >= 0 && numValue <= 59, e.key);
5091
- if (numValue > 60) {
5092
- const digitValue = parseInt(e.key, 10);
5093
- setMinute(digitValue);
5094
- onChange({ hour, minute: digitValue, meridiem });
5095
- return;
5096
- }
5097
- // Auto-advance to meridiem if we have a valid minute (0-59)
5098
- if (numValue >= 0 && numValue <= 59) {
5099
- // Set the minute value
5100
- setMinute(numValue);
5101
- onChange({ hour, minute: numValue, meridiem });
5102
- }
5103
- }
5095
+ let newHour = hour;
5096
+ let newMinute = minute;
5097
+ let newMeridiem = meridiem;
5098
+ // if the hour is 24, set the meridiem to am, and set the hour to 0
5099
+ if (hour === 24) {
5100
+ newMeridiem = "am";
5101
+ newHour = 0;
5104
5102
  }
5103
+ // if the hour is greater than 12, set the meridiem to pm, and subtract 12 from the hour
5104
+ else if (hour > 12) {
5105
+ newMeridiem = "pm";
5106
+ newHour = hour - 12;
5107
+ }
5108
+ // if the hour is 12, set the meridiem to pm, and set the hour to 12
5109
+ else if (hour === 12) {
5110
+ newMeridiem = "pm";
5111
+ newHour = 12;
5112
+ }
5113
+ // if the hour is 0, set the meridiem to am, and set the hour to 12
5114
+ else if (hour === 0) {
5115
+ newMeridiem = "am";
5116
+ newHour = 12;
5117
+ }
5118
+ else {
5119
+ newMeridiem = meridiem ?? "am";
5120
+ newHour = hour;
5121
+ }
5122
+ if (minute > 59) {
5123
+ newMinute = 0;
5124
+ }
5125
+ else {
5126
+ newMinute = minute;
5127
+ }
5128
+ onChange({
5129
+ hour: newHour,
5130
+ minute: newMinute,
5131
+ meridiem: newMeridiem,
5132
+ });
5133
+ setShowInput(false);
5105
5134
  };
5106
- // Handle meridiem button click
5107
- const handleMeridiemClick = (newMeridiem) => {
5108
- setMeridiem(newMeridiem);
5109
- onChange({ hour, minute, meridiem: newMeridiem });
5110
- };
5111
- const handleClear = () => {
5112
- setHour(null);
5113
- setMinute(null);
5114
- setMeridiem(null);
5115
- onChange({ hour: null, minute: null, meridiem: null });
5116
- // Focus the hour field after clearing
5117
- hourInputRef.current?.focus();
5135
+ const handleKeyDown = (e) => {
5136
+ if (e.key === "Enter") {
5137
+ handleBlur(e.currentTarget.value);
5138
+ }
5118
5139
  };
5119
- return (jsxRuntime.jsx(react.Flex, { direction: "column", gap: 3, children: jsxRuntime.jsxs(react.Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 90px auto", gap: "2", width: "auto", minWidth: "250px", 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.jsxs(react.Flex, { gap: "1", children: [jsxRuntime.jsx(react.Button, { size: "sm", colorScheme: meridiem === "am" ? "blue" : "gray", variant: meridiem === "am" ? "solid" : "outline", onClick: () => handleMeridiemClick("am"), width: "40px", children: meridiemLabel.am }), jsxRuntime.jsx(react.Button, { size: "sm", colorScheme: meridiem === "pm" ? "blue" : "gray", variant: meridiem === "pm" ? "solid" : "outline", onClick: () => handleMeridiemClick("pm"), width: "40px", children: meridiemLabel.pm })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }) }));
5140
+ const inputRef = React.useRef(null);
5141
+ 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) => {
5142
+ setInputValue(e.currentTarget.value);
5143
+ }, onBlur: (e) => {
5144
+ handleBlur(e.currentTarget.value);
5145
+ }, onFocus: (e) => {
5146
+ e.currentTarget.select();
5147
+ }, value: inputValue, display: showInput ? undefined : "none", ref: inputRef }), jsxRuntime.jsxs(react.Button, { onClick: () => {
5148
+ setShowInput(true);
5149
+ setInputValue(dayjs(`1970-01-01T${getTimeString(hour, minute, meridiem)}`, "hh:mmZ").format("HH:mm"));
5150
+ inputRef.current?.focus();
5151
+ }, 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
5152
+ ? dayjs(`1970-01-01T${stringTime}`, "hh:mmZ").format("hh:mm a")
5153
+ : "" })] }), jsxRuntime.jsx(react.Button, { onClick: handleClear, size: "sm", variant: "ghost", children: jsxRuntime.jsx(md.MdCancel, {}) })] }));
5120
5154
  }
5121
5155
 
5122
5156
  dayjs.extend(timezone);
@@ -5131,13 +5165,14 @@ const TimePicker = ({ column, schema, prefix }) => {
5131
5165
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
5132
5166
  ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
5133
5167
  : "";
5134
- // Parse the initial time parts from the ISO time string (HH:mm:ss)
5135
- const parseTime = (isoTime) => {
5136
- if (!isoTime)
5168
+ // Parse the initial time parts from the time string (HH:mm:ssZ)
5169
+ const parseTime = (time) => {
5170
+ if (!time)
5137
5171
  return { hour: 12, minute: 0, meridiem: "am" };
5138
- const parsed = dayjs(`1970-01-01T${isoTime}`).tz(timezone);
5139
- if (!parsed.isValid())
5172
+ const parsed = dayjs(`1970-01-01T${time}`).tz(timezone);
5173
+ if (!parsed.isValid()) {
5140
5174
  return { hour: 12, minute: 0, meridiem: "am" };
5175
+ }
5141
5176
  let hour = parsed.hour();
5142
5177
  const minute = parsed.minute();
5143
5178
  const meridiem = hour >= 12 ? "pm" : "am";
@@ -5157,35 +5192,30 @@ const TimePicker = ({ column, schema, prefix }) => {
5157
5192
  setMinute(minute);
5158
5193
  setMeridiem(meridiem);
5159
5194
  }, [value]);
5160
- // Convert hour, minute, meridiem to 24-hour ISO time string
5161
- const toIsoTime = (hour, minute, meridiem) => {
5195
+ const getTimeString = (hour, minute, meridiem) => {
5162
5196
  if (hour === null || minute === null || meridiem === null)
5163
5197
  return null;
5164
- let h = hour;
5165
- if (meridiem === "am" && hour === 12)
5166
- h = 0;
5167
- else if (meridiem === "pm" && hour < 12)
5168
- h = hour + 12;
5169
- return dayjs(`1970-01-01T${h.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:00`)
5170
- .tz(timezone)
5171
- .format(timeFormat);
5198
+ let newHour = hour;
5199
+ if (meridiem === "pm" && hour !== 12) {
5200
+ newHour = hour + 12;
5201
+ }
5202
+ return dayjs().tz(timezone).hour(newHour).minute(minute).format(timeFormat);
5172
5203
  };
5173
5204
  // Handle changes to time parts
5174
5205
  const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
5175
5206
  setHour(newHour);
5176
5207
  setMinute(newMinute);
5177
5208
  setMeridiem(newMeridiem);
5178
- const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
5179
- setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
5209
+ const timeString = getTimeString(newHour, newMinute, newMeridiem);
5210
+ setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
5180
5211
  };
5181
- const containerRef = React.useRef(null);
5182
5212
  return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5183
5213
  gridRow, 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: () => {
5184
5214
  setOpen(true);
5185
- }, justifyContent: "start", children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { ref: containerRef, 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: {
5186
- am: translate.t(`common.am`, { defaultValue: "AM" }),
5187
- pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5188
- } }) }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5215
+ }, 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: {
5216
+ am: translate.t(`common.am`, { defaultValue: "AM" }),
5217
+ pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5218
+ } }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5189
5219
  };
5190
5220
 
5191
5221
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
package/dist/index.mjs CHANGED
@@ -20,7 +20,7 @@ import invariant from 'tiny-invariant';
20
20
  import { HiColorSwatch, HiOutlineInformationCircle } from 'react-icons/hi';
21
21
  import { flexRender, makeStateUpdater, functionalUpdate, useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel, createColumnHelper } from '@tanstack/react-table';
22
22
  import { rankItem } from '@tanstack/match-sorter-utils';
23
- import { BsExclamationCircleFill } from 'react-icons/bs';
23
+ import { BsExclamationCircleFill, BsClock } from 'react-icons/bs';
24
24
  import { useDebounce } from '@uidotdev/usehooks';
25
25
  import { useQueryClient, useQuery } from '@tanstack/react-query';
26
26
  import { IoReload } from 'react-icons/io5';
@@ -3698,6 +3698,7 @@ const validateData = (data, schema) => {
3698
3698
  const validate = ajv.compile(schema);
3699
3699
  const validationResult = validate(data);
3700
3700
  const errors = validate.errors;
3701
+ console.log(errors, data);
3701
3702
  return {
3702
3703
  isValid: validationResult,
3703
3704
  validate,
@@ -5011,92 +5012,125 @@ const TextAreaInput = ({ column, schema, prefix, }) => {
5011
5012
  function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
5012
5013
  am: "am",
5013
5014
  pm: "pm",
5014
- }, onChange = (_newValue) => { }, }) {
5015
- // Refs for focus management
5016
- const hourInputRef = useRef(null);
5017
- const minuteInputRef = useRef(null);
5018
- useRef(null);
5019
- // Centralized handler for key events, value changes, and focus management
5020
- const handleKeyDown = (e, field) => {
5021
- const input = e.target;
5022
- const value = input.value;
5023
- // Handle navigation between fields
5024
- if (e.key === "Tab") {
5025
- // Tab is handled by the browser, no need to override
5015
+ }, onChange = (_newValue) => { }, timezone = "Asia/Hong_Kong", }) {
5016
+ const handleClear = () => {
5017
+ setHour(null);
5018
+ setMinute(null);
5019
+ setMeridiem(null);
5020
+ setInputValue("");
5021
+ setShowInput(false);
5022
+ onChange({ hour: null, minute: null, meridiem: null });
5023
+ };
5024
+ const getTimeString = (hour, minute, meridiem) => {
5025
+ if (hour === null || minute === null || meridiem === null) {
5026
+ return "";
5027
+ }
5028
+ // if the hour is 24, set the hour to 0
5029
+ if (hour === 24) {
5030
+ return dayjs().tz(timezone).hour(0).minute(minute).format("HH:mmZ");
5031
+ }
5032
+ // use dayjs to format the time at current timezone
5033
+ // if meridiem is pm, add 12 hours
5034
+ let newHour = hour;
5035
+ if (meridiem === "pm" && hour !== 12) {
5036
+ newHour = hour + 12;
5037
+ }
5038
+ // if the hour is 12, set the meridiem to am, and set the hour to 0
5039
+ else if (meridiem === "am" && hour === 12) {
5040
+ newHour = 0;
5041
+ }
5042
+ return dayjs().tz(timezone).hour(newHour).minute(minute).format("HH:mmZ");
5043
+ };
5044
+ const stringTime = getTimeString(hour, minute, meridiem);
5045
+ const [inputValue, setInputValue] = useState("");
5046
+ const [showInput, setShowInput] = useState(false);
5047
+ const handleBlur = (text) => {
5048
+ // ignore all non-numeric characters
5049
+ if (!text) {
5026
5050
  return;
5027
5051
  }
5028
- if (e.key === ":" && field === "hour") {
5029
- e.preventDefault();
5030
- minuteInputRef.current?.focus();
5052
+ const value = text.replace(/[^0-9apm]/g, "");
5053
+ if (value === "") {
5054
+ handleClear();
5031
5055
  return;
5032
5056
  }
5033
- if (e.key === "Backspace" && value === "") {
5034
- e.preventDefault();
5035
- if (field === "minute") {
5036
- hourInputRef.current?.focus();
5037
- }
5038
- else if (field === "meridiem") {
5039
- minuteInputRef.current?.focus();
5040
- }
5057
+ // if the value is a valid time, parse it and set the hour, minute, and meridiem
5058
+ // if the value is not a valid time, set the stringTime to the value
5059
+ // first two characters are the hour
5060
+ // next two characters are the minute
5061
+ // final two characters are the meridiem
5062
+ const hour = parseInt(value.slice(0, 2));
5063
+ const minute = parseInt(value.slice(2, 4));
5064
+ const meridiem = value.slice(4, 6);
5065
+ // validate the hour and minute
5066
+ if (isNaN(hour) || isNaN(minute)) {
5067
+ setInputValue("");
5041
5068
  return;
5042
5069
  }
5043
- // Handle number inputs
5044
- if (field === "hour") {
5045
- if (e.key.match(/^[0-9]$/)) {
5046
- const newValue = value + e.key;
5047
- const numValue = parseInt(newValue, 10);
5048
- console.log("newValue", newValue, numValue);
5049
- if (numValue > 12) {
5050
- const digitValue = parseInt(e.key, 10);
5051
- setHour(digitValue);
5052
- onChange({ hour: digitValue, minute, meridiem });
5053
- return;
5054
- }
5055
- // Auto-advance to minutes if we have a valid hour (1-12)
5056
- if (numValue >= 1 && numValue <= 12) {
5057
- // Set the hour value
5058
- setHour(numValue);
5059
- onChange({ hour: numValue, minute, meridiem });
5060
- // Move to minute input
5061
- e.preventDefault();
5062
- minuteInputRef.current?.focus();
5063
- }
5064
- }
5070
+ // if the hour is larger than 24, set the hour to 24
5071
+ if (hour > 24) {
5072
+ setInputValue("");
5073
+ return;
5065
5074
  }
5066
- else if (field === "minute") {
5067
- if (e.key.match(/^[0-9]$/)) {
5068
- const newValue = value + e.key;
5069
- const numValue = parseInt(newValue, 10);
5070
- console.log("newValue minute", newValue, numValue, numValue > 60, numValue >= 0 && numValue <= 59, e.key);
5071
- if (numValue > 60) {
5072
- const digitValue = parseInt(e.key, 10);
5073
- setMinute(digitValue);
5074
- onChange({ hour, minute: digitValue, meridiem });
5075
- return;
5076
- }
5077
- // Auto-advance to meridiem if we have a valid minute (0-59)
5078
- if (numValue >= 0 && numValue <= 59) {
5079
- // Set the minute value
5080
- setMinute(numValue);
5081
- onChange({ hour, minute: numValue, meridiem });
5082
- }
5083
- }
5075
+ let newHour = hour;
5076
+ let newMinute = minute;
5077
+ let newMeridiem = meridiem;
5078
+ // if the hour is 24, set the meridiem to am, and set the hour to 0
5079
+ if (hour === 24) {
5080
+ newMeridiem = "am";
5081
+ newHour = 0;
5084
5082
  }
5083
+ // if the hour is greater than 12, set the meridiem to pm, and subtract 12 from the hour
5084
+ else if (hour > 12) {
5085
+ newMeridiem = "pm";
5086
+ newHour = hour - 12;
5087
+ }
5088
+ // if the hour is 12, set the meridiem to pm, and set the hour to 12
5089
+ else if (hour === 12) {
5090
+ newMeridiem = "pm";
5091
+ newHour = 12;
5092
+ }
5093
+ // if the hour is 0, set the meridiem to am, and set the hour to 12
5094
+ else if (hour === 0) {
5095
+ newMeridiem = "am";
5096
+ newHour = 12;
5097
+ }
5098
+ else {
5099
+ newMeridiem = meridiem ?? "am";
5100
+ newHour = hour;
5101
+ }
5102
+ if (minute > 59) {
5103
+ newMinute = 0;
5104
+ }
5105
+ else {
5106
+ newMinute = minute;
5107
+ }
5108
+ onChange({
5109
+ hour: newHour,
5110
+ minute: newMinute,
5111
+ meridiem: newMeridiem,
5112
+ });
5113
+ setShowInput(false);
5085
5114
  };
5086
- // Handle meridiem button click
5087
- const handleMeridiemClick = (newMeridiem) => {
5088
- setMeridiem(newMeridiem);
5089
- onChange({ hour, minute, meridiem: newMeridiem });
5090
- };
5091
- const handleClear = () => {
5092
- setHour(null);
5093
- setMinute(null);
5094
- setMeridiem(null);
5095
- onChange({ hour: null, minute: null, meridiem: null });
5096
- // Focus the hour field after clearing
5097
- hourInputRef.current?.focus();
5115
+ const handleKeyDown = (e) => {
5116
+ if (e.key === "Enter") {
5117
+ handleBlur(e.currentTarget.value);
5118
+ }
5098
5119
  };
5099
- return (jsx(Flex, { direction: "column", gap: 3, children: jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "60px 10px 60px 90px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsx(Input, { ref: hourInputRef, type: "text", value: hour === null ? "" : hour.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "hour"), placeholder: "HH", maxLength: 2, textAlign: "center" }), jsx(Text, { children: ":" }), jsx(Input, { ref: minuteInputRef, type: "text", value: minute === null ? "" : minute.toString().padStart(2, "0"), onKeyDown: (e) => handleKeyDown(e, "minute"), placeholder: "MM", maxLength: 2, textAlign: "center" }), jsxs(Flex, { gap: "1", children: [jsx(Button$1, { size: "sm", colorScheme: meridiem === "am" ? "blue" : "gray", variant: meridiem === "am" ? "solid" : "outline", onClick: () => handleMeridiemClick("am"), width: "40px", children: meridiemLabel.am }), jsx(Button$1, { size: "sm", colorScheme: meridiem === "pm" ? "blue" : "gray", variant: meridiem === "pm" ? "solid" : "outline", onClick: () => handleMeridiemClick("pm"), width: "40px", children: meridiemLabel.pm })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }) }));
5120
+ const inputRef = useRef(null);
5121
+ return (jsxs(Grid, { justifyContent: "center", alignItems: "center", templateColumns: "200px auto", gap: "2", width: "auto", minWidth: "250px", children: [jsx(Input, { onKeyDown: handleKeyDown, onChange: (e) => {
5122
+ setInputValue(e.currentTarget.value);
5123
+ }, onBlur: (e) => {
5124
+ handleBlur(e.currentTarget.value);
5125
+ }, onFocus: (e) => {
5126
+ e.currentTarget.select();
5127
+ }, value: inputValue, display: showInput ? undefined : "none", ref: inputRef }), jsxs(Button$1, { onClick: () => {
5128
+ setShowInput(true);
5129
+ setInputValue(dayjs(`1970-01-01T${getTimeString(hour, minute, meridiem)}`, "hh:mmZ").format("HH:mm"));
5130
+ inputRef.current?.focus();
5131
+ }, display: showInput ? "none" : "flex", alignItems: "center", justifyContent: "start", variant: "outline", gap: 2, children: [jsx(Icon, { size: "sm", children: jsx(BsClock, {}) }), jsx(Text, { fontSize: "sm", children: stringTime
5132
+ ? dayjs(`1970-01-01T${stringTime}`, "hh:mmZ").format("hh:mm a")
5133
+ : "" })] }), jsx(Button$1, { onClick: handleClear, size: "sm", variant: "ghost", children: jsx(MdCancel, {}) })] }));
5100
5134
  }
5101
5135
 
5102
5136
  dayjs.extend(timezone);
@@ -5111,13 +5145,14 @@ const TimePicker = ({ column, schema, prefix }) => {
5111
5145
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
5112
5146
  ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
5113
5147
  : "";
5114
- // Parse the initial time parts from the ISO time string (HH:mm:ss)
5115
- const parseTime = (isoTime) => {
5116
- if (!isoTime)
5148
+ // Parse the initial time parts from the time string (HH:mm:ssZ)
5149
+ const parseTime = (time) => {
5150
+ if (!time)
5117
5151
  return { hour: 12, minute: 0, meridiem: "am" };
5118
- const parsed = dayjs(`1970-01-01T${isoTime}`).tz(timezone);
5119
- if (!parsed.isValid())
5152
+ const parsed = dayjs(`1970-01-01T${time}`).tz(timezone);
5153
+ if (!parsed.isValid()) {
5120
5154
  return { hour: 12, minute: 0, meridiem: "am" };
5155
+ }
5121
5156
  let hour = parsed.hour();
5122
5157
  const minute = parsed.minute();
5123
5158
  const meridiem = hour >= 12 ? "pm" : "am";
@@ -5137,35 +5172,30 @@ const TimePicker = ({ column, schema, prefix }) => {
5137
5172
  setMinute(minute);
5138
5173
  setMeridiem(meridiem);
5139
5174
  }, [value]);
5140
- // Convert hour, minute, meridiem to 24-hour ISO time string
5141
- const toIsoTime = (hour, minute, meridiem) => {
5175
+ const getTimeString = (hour, minute, meridiem) => {
5142
5176
  if (hour === null || minute === null || meridiem === null)
5143
5177
  return null;
5144
- let h = hour;
5145
- if (meridiem === "am" && hour === 12)
5146
- h = 0;
5147
- else if (meridiem === "pm" && hour < 12)
5148
- h = hour + 12;
5149
- return dayjs(`1970-01-01T${h.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:00`)
5150
- .tz(timezone)
5151
- .format(timeFormat);
5178
+ let newHour = hour;
5179
+ if (meridiem === "pm" && hour !== 12) {
5180
+ newHour = hour + 12;
5181
+ }
5182
+ return dayjs().tz(timezone).hour(newHour).minute(minute).format(timeFormat);
5152
5183
  };
5153
5184
  // Handle changes to time parts
5154
5185
  const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
5155
5186
  setHour(newHour);
5156
5187
  setMinute(newMinute);
5157
5188
  setMeridiem(newMeridiem);
5158
- const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
5159
- setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
5189
+ const timeString = getTimeString(newHour, newMinute, newMeridiem);
5190
+ setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
5160
5191
  };
5161
- const containerRef = useRef(null);
5162
5192
  return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5163
5193
  gridRow, 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: () => {
5164
5194
  setOpen(true);
5165
- }, justifyContent: "start", children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { ref: containerRef, children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5166
- am: translate.t(`common.am`, { defaultValue: "AM" }),
5167
- pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5168
- } }) }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5195
+ }, justifyContent: "start", children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5196
+ am: translate.t(`common.am`, { defaultValue: "AM" }),
5197
+ pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5198
+ } }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5169
5199
  };
5170
5200
 
5171
5201
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
@@ -15,6 +15,7 @@ interface TimePickerProps {
15
15
  am: string;
16
16
  pm: string;
17
17
  };
18
+ timezone?: string;
18
19
  }
19
- export declare function TimePicker({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel, onChange, }: TimePickerProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function TimePicker({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel, onChange, timezone, }: TimePickerProps): import("react/jsx-runtime").JSX.Element;
20
21
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "12.0.0-beta.65",
3
+ "version": "12.0.0-beta.67",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",