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

Code before:

    React.useEffect(() => {
      if (format) wave.args[m.name] = value ? formatDateToTimeString(value, '24') : null
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [format])

    // TODO: Remove once CSS vars are fully supported - https://github.com/mui/material-ui/issues/27651
    React.useEffect(() => {
      if (theme) {
        theme.palette.primary.main = fluentPalette.themePrimary
        theme.palette.text.primary = fluentPalette.neutralPrimary
        theme.palette.action.active = fluentPalette.themePrimary
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [fluentPalette.themePrimary, theme])

    return <>
      <React.Suspense fallback={<LazyLoadPlaceholder />}>
        {theme && AdapterDateFns && format
          ? <ThemeProvider theme={theme}>
            <LocalizationProvider dateAdapter={AdapterDateFns}>
              <TimePicker
                value={value}
                label={label}
                open={isDialogOpen}
                onChange={value => onChangeTime(value as Date)}
                onAccept={onSelectTime}
                onClose={() => setIsDialogOpen(false)}
                ampm={hour_format === '12'}
                showToolbar
                ToolbarComponent={({ parsedValue, setOpenView, ampm }) =>
                  // Traps focus inside the popover.
                  // TODO: Check why focus gets back to the textfield after opening the popover from dialog.
                  <Fluent.FocusTrapZone isClickableOutsideFocusTrap>
                    <Toolbar
                      setOpenView={setOpenView}
                      time={parsedValue ? formatDateToTimeString(parsedValue as D, ampm ? '12' : '24') : parsedValue as null}
                      label={label}
                      switchAmPm={switchAmPm}
                    />
                  </Fluent.FocusTrapZone>
                }
                PopperProps={{ ref: popperRef, anchorEl: () => textInputRef.current as VirtualElement, onBlur, ...popoverProps }}
                minTime={min ? parseTimeStringToDate(min) : undefined}
                maxTime={max ? parseTimeStringToDate(max) : undefined}
                minutesStep={allowedMinutesSteps[minutes_step]}
                disabled={disabled}
                onOpen={onOpen}
                renderInput={({ inputProps, error }: TextFieldProps) =>
                  <div ref={textInputRef} data-test={m.name}>
                    <Fluent.TextField

Review comment (suggestion):
Let's use proper types here.

```suggestion
                onChange={onChangeTime}
```

Code after:
      getErrMsg = (hour_format: S, min = '00:00', max = '00:00') =>
        `Wrong input. Please enter the time in range from ${formatDateToTimeString(parseTimeStringToDate(min), hour_format)} 
        to ${formatDateToTimeString(parseTimeStringToDate(max), hour_format)}.`

    React.useEffect(() => {
      if (format) wave.args[m.name] = value ? formatDateToTimeString(value, '24') : null
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [format])

    // TODO: Remove once CSS vars are fully supported - https://github.com/mui/material-ui/issues/27651
    React.useEffect(() => {
      if (theme) {
        theme.palette.primary.main = fluentPalette.themePrimary
        theme.palette.text.primary = fluentPalette.neutralPrimary
        theme.palette.action.active = fluentPalette.themePrimary
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [fluentPalette.themePrimary, theme])

    return <>
      <React.Suspense fallback={<LazyLoadPlaceholder />}>
        {theme && AdapterDateFns && format
          ? <ThemeProvider theme={theme}>
            <LocalizationProvider dateAdapter={AdapterDateFns}>
              <TimePicker
                value={value}
                label={label}
                open={isDialogOpen}
                onChange={onChangeTime}
                onAccept={onSelectTime}
                onClose={() => setIsDialogOpen(false)}
                ampm={hour_format === '12'}
                showToolbar
                ToolbarComponent={({ parsedValue, setOpenView, ampm }) =>
                  // Traps focus inside the popover.
                  // TODO: Check why focus gets back to the textfield after opening the popover from dialog.
                  <Fluent.FocusTrapZone isClickableOutsideFocusTrap>
                    <Toolbar
                      setOpenView={setOpenView}
                      time={parsedValue ? formatDateToTimeString(parsedValue as D, ampm ? '12' : '24') : parsedValue as null}
                      label={label}
                      switchAmPm={switchAmPm}
                    />
                  </Fluent.FocusTrapZone>
                }
                PopperProps={{ ref: popperRef, anchorEl: () => textInputRef.current as VirtualElement, onBlur, ...popoverProps }}
                minTime={min ? parseTimeStringToDate(min) : undefined}
                maxTime={max ? parseTimeStringToDate(max) : undefined}
                minutesStep={allowedMinutesSteps[minutes_step]}
                disabled={disabled}
                onOpen={onOpen}