Repository: h2oai/wave
File: ui/src/time_picker.tsx (TypeScript)

Code before:
    </div>,
  Toolbar = ({ setOpenView, time, label, switchAmPm, amPmDisabled }: ToolbarProps) =>
    <div className={css.toolbar}>
      {label && <Fluent.Label className={css.toolbarLabel}>{label}</Fluent.Label>}
      <Fluent.Text className={css.toolbarText}>
        <Fluent.Text className={css.toolbarTime} onClick={() => setOpenView('hours')}>{time?.substring(0, 2) || '--'}</Fluent.Text>:
        <Fluent.Text className={css.toolbarTime} onClick={() => setOpenView('minutes')}>{time?.substring(3, 5) || '--'}</Fluent.Text>{' '}
        <Fluent.Text className={clas(css.toolbarTime, amPmDisabled ? css.toolbarTextDisabled : css.toolbarTimeActive)} onClick={amPmDisabled ? undefined : switchAmPm}>{time?.substring(6, 8) || ''}</Fluent.Text>
      </Fluent.Text>
    </div>


export const
  XTimePicker = ({ model: m }: { model: TimePicker }) => {
    const
      { hour_format = '12', label, disabled, min, max, placeholder, required, minutes_step = 1 } = m,
      [value, setValue] = React.useState(m.value ? parseTimeStringToDate(m.value) : null),
      [isDialogOpen, setIsDialogOpen] = React.useState(false),
      textInputRef = React.useRef<HTMLDivElement | null>(null),
      popperRef = React.useRef<HTMLDivElement | null>(null),
      minTime = React.useMemo(() => parseTimeStringToDate(min || '00:00'), [min]),
      maxTime = React.useMemo(() => parseTimeStringToDate(max || '24:00'), [max]),
      switchAmPm = () => {
        setValue((prevValue) => {
          if (prevValue && canSwitchAmPm(prevValue, minTime, maxTime)) {
            const date = new Date(prevValue!)
            date.setTime(date.getTime() + 12 * 60 * 60 * 1000)
            const newValue = formatDateToTimeString(date, '24')
            m.value = newValue
            wave.args[m.name] = newValue
            return date
          }
          return prevValue
        })
      },
      onChangeTime = (time: unknown) => {
        const date = time instanceof Date && new Date(normalize(formatDateToTimeString(time, '24')))
        if (date && !isOutOfBounds(date, minTime, maxTime)) {
          const newValue = formatDateToTimeString(time, '24')
          m.value = newValue
          wave.args[m.name] = newValue
          setValue(time)
        }
      },
      onSelectTime = () => { if (m.trigger) wave.push() },
      // HACK: https://stackoverflow.com/questions/70106353/material-ui-date-time-picker-safari-browser-issue
      onOpen = () => setTimeout(() => (document.activeElement as HTMLElement)?.blur()),
      onBlur = (ev: React.FocusEvent) => {
        // Close the popover if the side panel or dialog opens.
        // TODO: Investigate why MUI dismiss on outer click handling doesn't work in this case.
        if (!ev.relatedTarget || !Fluent.elementContains(popperRef.current, ev.relatedTarget as HTMLElement)) setIsDialogOpen(false)

Review comment (suggestion):
Already checked in `if`. Also, why do we need `new Date` here if prevValue is already a Date?

```suggestion
            const date = new Date(prevValue)
```

Code after:
export const
  XTimePicker = ({ model: m }: { model: TimePicker }) => {
    const
      { hour_format = '12', label, disabled, min, max, placeholder, required, minutes_step = 1 } = m,
      [value, setValue] = React.useState(m.value ? parseTimeStringToDate(m.value) : null),
      [isDialogOpen, setIsDialogOpen] = React.useState(false),
      textInputRef = React.useRef<HTMLDivElement | null>(null),
      popperRef = React.useRef<HTMLDivElement | null>(null),
      minTime = React.useMemo(() => parseTimeStringToDate(min || '00:00'), [min]),
      maxTime = React.useMemo(() => parseTimeStringToDate(max || '24:00'), [max]),
      onChangeTime = (time: unknown) => {
        if (!(time instanceof Date)) return
        const newValue = formatDateToTimeString(time, '24')
        const date = new Date(normalize(newValue))
        if (isOutOfBounds(date, minTime, maxTime)) return
        m.value = newValue
        wave.args[m.name] = newValue
        setValue(time)
      },
      onSelectTime = () => { if (m.trigger) wave.push() },
      // HACK: https://stackoverflow.com/questions/70106353/material-ui-date-time-picker-safari-browser-issue
      onOpen = () => setTimeout(() => (document.activeElement as HTMLElement)?.blur()),
      onBlur = (ev: React.FocusEvent) => {
        // Close the popover if the side panel or dialog opens.
        // TODO: Investigate why MUI dismiss on outer click handling doesn't work in this case.
        if (!ev.relatedTarget || !Fluent.elementContains(popperRef.current, ev.relatedTarget as HTMLElement)) setIsDialogOpen(false)
      },
      { palette: fluentPalette } = Fluent.useTheme(),
      themeObj = {
        palette: {
          background: {
            paper: cssVar('$card'),
          },
          primary: {
            main: fluentPalette.themePrimary,
            contrastText: cssVar('$neutralLight')
          },
          text: {
            primary: fluentPalette.neutralPrimary,
            secondary: cssVar('$neutralSecondary'),
            disabled: cssVar('$neutralTertiaryAlt'),
          },
          action: {
            active: fluentPalette.themePrimary,
            disabled: cssVar('$neutralLight'),
            hover: cssVar('$neutralLight'),
            hoverOpacity: 0.04
          }
        },
      },
      { format, AdapterDateFns, theme } = useTime(themeObj),