@@ -25,6 +25,7 @@ import { useUserPreferences } from '@/useUserPreferences';
2525
2626import { Icon } from '../Icon' ;
2727
28+ import { TimePickerMode } from './types' ;
2829import { useTimePickerForm } from './useTimePickerForm' ;
2930import {
3031 dateParser ,
@@ -34,7 +35,10 @@ import {
3435 RELATIVE_TIME_OPTIONS ,
3536} from './utils' ;
3637
37- const modeAtom = atomWithStorage ( 'hdx-time-picker-mode' , 'Time range' ) ;
38+ const modeAtom = atomWithStorage < TimePickerMode > (
39+ 'hdx-time-picker-mode' ,
40+ TimePickerMode . Range ,
41+ ) ;
3842
3943const DATE_INPUT_PLACEHOLDER = 'YYY-MM-DD HH:mm:ss' ;
4044const DATE_INPUT_FORMAT = 'YYYY-MM-DD HH:mm:ss' ;
@@ -101,15 +105,25 @@ export const TimePicker = ({
101105 } , [ value ] ) ;
102106
103107 React . useEffect ( ( ) => {
104- if ( dateRange [ 0 ] && dateRange [ 1 ] ) {
105- form . setValues ( {
106- startDate : dateRange [ 0 ] ,
107- endDate : dateRange [ 1 ] ,
108- } ) ;
108+ // Only update form values from external dateRange when popover is closed
109+ // This prevents overwriting user inputs while they're editing
110+ if ( ! opened && dateRange [ 0 ] && dateRange [ 1 ] ) {
111+ if ( mode === TimePickerMode . Range ) {
112+ form . setValues ( {
113+ startDate : dateRange [ 0 ] ,
114+ endDate : dateRange [ 1 ] ,
115+ } ) ;
116+ } else if ( mode === TimePickerMode . Around ) {
117+ // For "Around a time" mode, set the startDate to the midpoint of the range
118+ const midpoint = new Date (
119+ ( dateRange [ 0 ] . getTime ( ) + dateRange [ 1 ] . getTime ( ) ) / 2 ,
120+ ) ;
121+ form . setFieldValue ( 'startDate' , midpoint ) ;
122+ }
109123 }
110- // only run when dateRange changes
124+ // only run when dateRange changes or opened state changes
111125 // eslint-disable-next-line react-hooks/exhaustive-deps
112- } , [ dateRange ] ) ;
126+ } , [ dateRange , opened , mode ] ) ;
113127
114128 const handleSearch = React . useCallback (
115129 ( value : string | [ Date | null , Date | null ] ) => {
@@ -141,11 +155,11 @@ export const TimePicker = ({
141155 return ;
142156 }
143157 const { startDate, endDate } = form . values ;
144- if ( mode === 'Time range' ) {
158+ if ( mode === TimePickerMode . Range ) {
145159 handleSearch ( [ startDate , endDate ] ) ;
146160 close ( ) ;
147161 }
148- if ( mode === ' Around a time' ) {
162+ if ( mode === TimePickerMode . Around ) {
149163 const duration = DURATIONS [ form . values . duration ] ;
150164 const from = startDate && sub ( startDate , duration ) ;
151165 const to = startDate && add ( startDate , duration ) ;
@@ -281,11 +295,49 @@ export const TimePicker = ({
281295 < SegmentedControl
282296 size = "xs"
283297 mb = "xs"
284- data = { [ 'Time range' , ' Around a time' ] }
298+ data = { [ TimePickerMode . Range , TimePickerMode . Around ] }
285299 value = { mode }
286- onChange = { setMode }
300+ onChange = { newMode => {
301+ const value = newMode as TimePickerMode ;
302+ setMode ( value ) ;
303+ // When switching to "Around a time", calculate the center point and appropriate duration
304+ if (
305+ value === TimePickerMode . Around &&
306+ form . values . startDate &&
307+ form . values . endDate
308+ ) {
309+ const midpoint = new Date (
310+ ( form . values . startDate . getTime ( ) +
311+ form . values . endDate . getTime ( ) ) /
312+ 2 ,
313+ ) ;
314+ const halfRangeMs =
315+ ( form . values . endDate . getTime ( ) -
316+ form . values . startDate . getTime ( ) ) /
317+ 2 ;
318+
319+ // Find the closest duration option
320+ const halfRangeMinutes = halfRangeMs / ( 1000 * 60 ) ;
321+ let closestDuration = '15m' ; // default
322+
323+ if ( halfRangeMinutes <= 0.5 ) closestDuration = '30s' ;
324+ else if ( halfRangeMinutes <= 1 ) closestDuration = '1m' ;
325+ else if ( halfRangeMinutes <= 5 ) closestDuration = '5m' ;
326+ else if ( halfRangeMinutes <= 15 ) closestDuration = '15m' ;
327+ else if ( halfRangeMinutes <= 30 ) closestDuration = '30m' ;
328+ else if ( halfRangeMinutes <= 60 ) closestDuration = '1h' ;
329+ else if ( halfRangeMinutes <= 180 ) closestDuration = '3h' ;
330+ else if ( halfRangeMinutes <= 360 ) closestDuration = '6h' ;
331+ else closestDuration = '12h' ;
332+
333+ form . setValues ( {
334+ startDate : midpoint ,
335+ duration : closestDuration ,
336+ } ) ;
337+ }
338+ } }
287339 />
288- { mode === 'Time range' ? (
340+ { mode === TimePickerMode . Range ? (
289341 < >
290342 < H > Start time</ H >
291343 < DateInputCmp
0 commit comments