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

Code before:
            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),
      formatDateToTimeString = (date: D, hour_format: S) => format ? format(date, hour_format === '12' ? 'hh:mm aa' : 'HH:mm') : '',
      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(() => {
      const
        time = m.value ? parseTimeStringToDate(m.value) : null,
        minTime = min ? parseTimeStringToDate(min) : null,
        maxTime = max ? parseTimeStringToDate(max) : null,
        newTime = time && minTime && time < minTime ? minTime : time && maxTime && time > maxTime ? maxTime : time
      if (format) wave.args[m.name] = newTime ? formatDateToTimeString(newTime, '24') : null
      setValue(newTime)
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [format, m.name, m.value, max, min])

    // 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}

Review comment (suggestion):
It would be better to precompute the parsedMin/Max just once instead of doing so in render, outOfBounds, here and getErrorMessage.

Code after:
            disabled: cssVar('$neutralTertiaryAlt'),
          },
          action: {
            active: fluentPalette.themePrimary,
            disabled: cssVar('$neutralLight'),
            hover: cssVar('$neutralLight'),
            hoverOpacity: 0.04
          }
        },
      },
      { format, AdapterDateFns, theme } = useTime(themeObj),
      formatDateToTimeString = React.useCallback((date: D, hour_format: S) => format ? format(date, hour_format === '12' ? 'hh:mm aa' : 'HH:mm') : '', [format])

    React.useEffect(() => {
      const time = m.value ? parseTimeStringToDate(m.value) : null
      const newTime = time && isBelowMin(time, minTime) ? minTime : time && isOverMax(time, maxTime) ? maxTime : time
      if (format) wave.args[m.name] = newTime ? formatDateToTimeString(newTime, '24') : null
      setValue(newTime)
    }, [format, formatDateToTimeString, m.name, m.value, maxTime, minTime])

    // 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={