From cff07c9fb65551059754d702f7bda8f141e6d4e3 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Thu, 16 Jan 2025 15:58:02 +0000 Subject: [PATCH] Chore: Replace `rc-time-picker` with `rc-picker` (#99022) * replace rc-time-picker with rc-picker * remove unnecessary stack * remove TimePickerInput * make props stricter * fix type assertions * remove outdated comment * fix types * fix clear icon * fix styling * fix z-index and 6 tests * fix remaining unit tests * betterer results * styling tweaks * don't show/hide scrollbars on hover --- .betterer.results | 4 - .yarnrc.yml | 4 - package.json | 1 - packages/grafana-ui/package.json | 2 +- .../DateTimePicker/DateTimePicker.test.tsx | 26 +-- .../DateTimePickers/TimeOfDayPicker.story.tsx | 2 +- .../DateTimePickers/TimeOfDayPicker.tsx | 193 ++++++++++++------ .../src/themes/GlobalStyles/GlobalStyles.tsx | 2 - .../src/themes/GlobalStyles/rcTimePicker.ts | 43 ---- .../grafana/components/TimePickerInput.tsx | 185 ----------------- .../grafana/components/TimeRegionEditor.tsx | 27 +-- yarn.lock | 174 ++++++---------- 12 files changed, 225 insertions(+), 438 deletions(-) delete mode 100644 packages/grafana-ui/src/themes/GlobalStyles/rcTimePicker.ts delete mode 100644 public/app/plugins/datasource/grafana/components/TimePickerInput.tsx diff --git a/.betterer.results b/.betterer.results index 40e87849b9b..7f8289827a0 100644 --- a/.betterer.results +++ b/.betterer.results @@ -7323,10 +7323,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"] ], - "public/app/plugins/datasource/grafana/components/TimePickerInput.tsx:5381": [ - [0, 0, 0, "\'@grafana/ui/src/components/Forms/commonStyles\' import is restricted from being used by a pattern. Import from the public export instead.", "0"], - [0, 0, 0, "\'@grafana/ui/src/themes/mixins\' import is restricted from being used by a pattern. Import from the public export instead.", "1"] - ], "public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx:5381": [ [0, 0, 0, "\'@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOffset\' import is restricted from being used by a pattern. Import from the public export instead.", "0"], [0, 0, 0, "\'@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneTitle\' import is restricted from being used by a pattern. Import from the public export instead.", "1"] diff --git a/.yarnrc.yml b/.yarnrc.yml index f71bc901067..a5a0620502d 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -13,10 +13,6 @@ packageExtensions: doctrine@3.0.0: dependencies: assert: 2.0.0 - rc-time-picker@3.7.3: - peerDependencies: - react: 17.0.1 - react-dom: 17.0.1 rc-trigger@2.6.5: peerDependencies: react: 17.0.1 diff --git a/package.json b/package.json index e6bbe7d9342..a904ada7489 100644 --- a/package.json +++ b/package.json @@ -359,7 +359,6 @@ "pluralize": "^8.0.0", "prismjs": "1.29.0", "rc-slider": "11.1.8", - "rc-time-picker": "3.7.3", "rc-tree": "5.13.0", "re-resizable": "6.10.3", "react": "18.2.0", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 67fcee3c097..1e8f79787fd 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -85,8 +85,8 @@ "prismjs": "1.29.0", "rc-cascader": "3.33.0", "rc-drawer": "7.2.0", + "rc-picker": "4.9.2", "rc-slider": "11.1.8", - "rc-time-picker": "^3.7.3", "rc-tooltip": "6.4.0", "react-calendar": "^5.1.0", "react-colorful": "5.6.1", diff --git a/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.test.tsx b/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.test.tsx index 0d83fc4a53d..ca99959c7d0 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.test.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { dateTime, dateTimeAsMoment, dateTimeForTimeZone, getTimeZone, setTimeZoneResolver } from '@grafana/data'; @@ -86,23 +86,16 @@ describe('Date time picker', () => { // open the time of day overlay await userEvent.click(screen.getAllByRole('textbox')[1]); + const hourList = screen.getAllByRole('list')[0]; // change the hour - await userEvent.click( - screen.getAllByRole('button', { - name: '00', - })[0] - ); + await userEvent.click(within(hourList).getByText('00')); // Check the active day is the 5th expect(screen.getByRole('button', { name: 'May 5, 2021' })).toHaveClass('react-calendar__tile--active'); // change the hour - await userEvent.click( - screen.getAllByRole('button', { - name: '23', - })[0] - ); + await userEvent.click(within(hourList).getByText('23')); // Check the active day is the 5th expect(screen.getByRole('button', { name: 'May 5, 2021' })).toHaveClass('react-calendar__tile--active'); @@ -123,7 +116,6 @@ describe('Date time picker', () => { await userEvent.click(screen.getByRole('button', { name: 'May 15, 2021' })); const timeInput = screen.getAllByRole('textbox')[1]; - expect(timeInput).toHaveClass('rc-time-picker-input'); expect(timeInput).not.toHaveDisplayValue('00:00:00'); } ); @@ -216,9 +208,7 @@ describe('Date time picker', () => { await userEvent.click(screen.getAllByRole('textbox')[1]); // check the hour element is visible - const hourElement = screen.getAllByRole('button', { - name: '00', - })[0]; + const hourElement = screen.getAllByText('00')[0]; expect(hourElement).toBeVisible(); // select the hour value and check it's still visible @@ -227,11 +217,7 @@ describe('Date time picker', () => { // click outside the overlay and check the hour element is no longer visible await userEvent.click(document.body); - expect( - screen.queryByRole('button', { - name: '00', - }) - ).not.toBeInTheDocument(); + expect(screen.queryByText('00')).not.toBeInTheDocument(); } ); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.story.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.story.tsx index bde38d03457..b75516367cc 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.story.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.story.tsx @@ -24,7 +24,7 @@ export const Basic: StoryFn = (args) => { return ( { + onChange={(newValue?) => { action('on selected')(newValue); updateArgs({ value: newValue }); }} diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.tsx index 23e6e2d2870..4fbd2031927 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.tsx @@ -1,5 +1,8 @@ import { css, cx } from '@emotion/css'; -import RcTimePicker from 'rc-time-picker'; +import { Moment } from 'moment'; +import RcPicker, { PickerProps } from 'rc-picker'; +import generateConfig from 'rc-picker/lib/generate/moment'; +import locale from 'rc-picker/lib/locale/en_US'; import { dateTime, DateTime, dateTimeAsMoment, GrafanaTheme2, isDateTimeInput } from '@grafana/data'; @@ -8,62 +11,102 @@ import { getFocusStyles } from '../../themes/mixins'; import { inputSizes } from '../Forms/commonStyles'; import { FormInputSize } from '../Forms/types'; import { Icon } from '../Icon/Icon'; +import 'rc-picker/assets/index.css'; -import 'rc-time-picker/assets/index.css'; - -export interface Props { - onChange: (value: DateTime) => void; +interface BaseProps { + onChange: (value: DateTime) => void | ((value?: DateTime) => void); value?: DateTime; showHour?: boolean; showSeconds?: boolean; - minuteStep?: number; + minuteStep?: PickerProps['minuteStep']; size?: FormInputSize; disabled?: boolean; disabledHours?: () => number[]; disabledMinutes?: () => number[]; disabledSeconds?: () => number[]; + placeholder?: string; + allowEmpty?: boolean; } +interface AllowEmptyProps extends BaseProps { + allowEmpty: true; + onChange: (value?: DateTime) => void; +} + +interface NoAllowEmptyProps extends BaseProps { + allowEmpty?: false; + onChange: (value: DateTime) => void; +} + +export type Props = AllowEmptyProps | NoAllowEmptyProps; + export const POPUP_CLASS_NAME = 'time-of-day-picker-panel'; export const TimeOfDayPicker = ({ minuteStep = 1, showHour = true, showSeconds = false, - onChange, value, size = 'auto', disabled, disabledHours, disabledMinutes, disabledSeconds, + placeholder, + // note: we can't destructure allowEmpty/onChange here + // in order to discriminate the types properly later in the onChange handler + ...restProps }: Props) => { const styles = useStyles2(getStyles); + const allowClear = restProps.allowEmpty ?? false; return ( - + generateConfig={generateConfig} + locale={locale} + allowClear={ + allowClear && { + clearIcon: , + } + } className={cx(inputSizes()[size], styles.input)} - popupClassName={cx(styles.picker, POPUP_CLASS_NAME)} - defaultValue={dateTimeAsMoment()} + classNames={{ + popup: cx(styles.picker, POPUP_CLASS_NAME), + }} + defaultValue={restProps.allowEmpty ? undefined : dateTimeAsMoment()} + disabled={disabled} + disabledTime={() => ({ + disabledHours, + disabledMinutes, + disabledSeconds, + })} + format={generateFormat(showHour, showSeconds)} + minuteStep={minuteStep} onChange={(value) => { if (isDateTimeInput(value)) { - return onChange(dateTime(value)); + if (restProps.allowEmpty) { + return restProps.onChange(value ? dateTime(value) : undefined); + } else { + return restProps.onChange(dateTime(value)); + } } }} - allowEmpty={false} - showSecond={showSeconds} - value={dateTimeAsMoment(value)} - showHour={showHour} - minuteStep={minuteStep} - inputIcon={} - disabled={disabled} - disabledHours={disabledHours} - disabledMinutes={disabledMinutes} - disabledSeconds={disabledSeconds} + picker="time" + placeholder={placeholder} + showNow={false} + needConfirm={false} + suffixIcon={} + value={value ? dateTimeAsMoment(value) : value} /> ); }; +function generateFormat(showHour = true, showSeconds = false) { + const maybeHour = showHour ? 'HH:' : ''; + const maybeSecond = showSeconds ? ':ss' : ''; + return maybeHour + 'mm' + maybeSecond; +} + interface CaretProps { wrapperStyle?: string; } @@ -78,31 +121,44 @@ const Caret = ({ wrapperStyle = '' }: CaretProps) => { const getStyles = (theme: GrafanaTheme2) => { const bgColor = theme.components.input.background; - const menuShadowColor = theme.v1.palette.black; - const optionBgHover = theme.colors.background.secondary; + const optionBgHover = theme.colors.action.hover; const borderRadius = theme.shape.radius.default; const borderColor = theme.components.input.borderColor; + return { caretWrapper: css({ - position: 'absolute', - right: '8px', + position: 'relative', top: '50%', transform: 'translateY(-50%)', display: 'inline-block', - textAlign: 'right', color: theme.colors.text.secondary, }), + clearIcon: css({ + color: theme.colors.text.secondary, + + '&:hover': { + color: theme.colors.text.maxContrast, + }, + }), picker: css({ - '.rc-time-picker-panel-select': { - fontSize: '14px', + '&.rc-picker-dropdown': { + boxShadow: 'none', + zIndex: theme.zIndex.portal, + }, + '.rc-picker-time-panel-column': { + fontSize: theme.typography.htmlFontSize, backgroundColor: bgColor, color: theme.colors.text.secondary, - borderColor, + padding: 'unset', + overflowY: 'auto', + scrollbarWidth: 'thin', + width: theme.spacing(8), li: { - outlineWidth: '2px', - '&.rc-time-picker-panel-select-option-selected': { + paddingRight: theme.spacing(2), + width: 'auto', + '&.rc-picker-time-panel-cell-selected': { backgroundColor: 'inherit', - border: `1px solid ${theme.v1.palette.orange}`, + border: `1px solid ${theme.colors.action.selectedBorder}`, borderRadius, color: theme.colors.text.primary, }, @@ -112,44 +168,37 @@ const getStyles = (theme: GrafanaTheme2) => { color: theme.colors.text.primary, }, - '&.rc-time-picker-panel-select-option-disabled': { + '&.rc-picker-time-panel-cell-disabled': { color: theme.colors.action.disabledText, }, }, + + '.rc-picker-time-panel-cell-inner': { + color: 'inherit', + }, + + '&:not(:last-of-type)': { + borderRight: `1px solid ${borderColor}`, + }, }, - '.rc-time-picker-panel-inner': { - boxShadow: `0px 4px 4px ${menuShadowColor}`, + '.rc-picker-panel': { + boxShadow: theme.shadows.z3, backgroundColor: bgColor, borderColor, borderRadius, - marginTop: '3px', - - '.rc-time-picker-panel-input-wrap': { - marginRight: '2px', - - '&, .rc-time-picker-panel-input': { - backgroundColor: bgColor, - paddingTop: '2px', - }, - }, - - '.rc-time-picker-panel-combobox': { - display: 'flex', - }, + overflow: 'hidden', }, }), input: css({ - '.rc-time-picker-input': { - backgroundColor: bgColor, - borderRadius, - borderColor, - color: theme.colors.text.primary, - height: theme.spacing(4), + '&.rc-picker-focused': { + border: 'none', - '&:focus': getFocusStyles(theme), + '.rc-picker-input': getFocusStyles(theme), + }, - '&:disabled': { + '&.rc-picker-disabled': { + '.rc-picker-input': { backgroundColor: theme.colors.action.disabledBackground, color: theme.colors.action.disabledText, border: `1px solid ${theme.colors.action.disabledBackground}`, @@ -158,6 +207,36 @@ const getStyles = (theme: GrafanaTheme2) => { }, }, }, + + '.rc-picker-input': { + backgroundColor: bgColor, + borderRadius, + borderColor, + borderStyle: 'solid', + borderWidth: '1px', + color: theme.colors.text.primary, + height: theme.spacing(4), + padding: theme.spacing(0, 1), + + input: { + color: 'unset', + backgroundColor: 'unset', + '&:focus': { + outline: 'none', + }, + + '&::placeholder': { + color: theme.colors.text.disabled, + }, + }, + }, + + '.rc-picker-clear': { + alignItems: 'center', + display: 'flex', + insetInlineEnd: 'unset', + position: 'relative', + }, }), }; }; diff --git a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx index 0aacc8db438..12e094433d2 100644 --- a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx +++ b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx @@ -19,7 +19,6 @@ import { getLegacySelectStyles } from './legacySelect'; import { getMarkdownStyles } from './markdownStyles'; import { getPageStyles } from './page'; import { getQueryEditorStyles } from './queryEditor'; -import { getRcTimePickerStyles } from './rcTimePicker'; import { getSkeletonStyles } from './skeletonStyles'; import { getSlateStyles } from './slate'; import { getUplotStyles } from './uPlot'; @@ -48,7 +47,6 @@ export function GlobalStyles() { getMarkdownStyles(theme), getPageStyles(theme), getQueryEditorStyles(theme), - getRcTimePickerStyles(theme), getSkeletonStyles(theme), getSlateStyles(theme), getUplotStyles(theme), diff --git a/packages/grafana-ui/src/themes/GlobalStyles/rcTimePicker.ts b/packages/grafana-ui/src/themes/GlobalStyles/rcTimePicker.ts deleted file mode 100644 index 36df58946b6..00000000000 --- a/packages/grafana-ui/src/themes/GlobalStyles/rcTimePicker.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { css } from '@emotion/react'; - -import { GrafanaTheme2 } from '@grafana/data'; - -export function getRcTimePickerStyles(theme: GrafanaTheme2) { - return css({ - '.rc-time-picker-input,.rc-time-picker-panel-input-wrap,.rc-time-picker-panel-inner': { - backgroundColor: theme.components.input.background, - color: theme.colors.text.secondary, - borderColor: theme.components.input.borderColor, - fontSize: theme.typography.body.fontSize, - }, - - '.rc-time-picker-input': { - padding: theme.spacing(0, 1), - height: theme.spacing(4), - }, - - '.rc-time-picker-panel': { - width: '176px', - }, - - '.rc-time-picker-panel-select': { - width: '50%', - - '&:only-child': { - width: '100%', - }, - - '.rc-time-picker-panel-select-option-selected': { - backgroundColor: theme.colors.background.secondary, - }, - - 'li:hover': { - backgroundColor: theme.colors.background.secondary, - }, - }, - - '.rc-time-picker-panel-narrow': { - maxWidth: 'none', - }, - }); -} diff --git a/public/app/plugins/datasource/grafana/components/TimePickerInput.tsx b/public/app/plugins/datasource/grafana/components/TimePickerInput.tsx deleted file mode 100644 index 7526c5f0a9a..00000000000 --- a/public/app/plugins/datasource/grafana/components/TimePickerInput.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import { css, cx } from '@emotion/css'; -import { Moment } from 'moment'; -import TimePicker from 'rc-time-picker'; - -import { GrafanaTheme2 } from '@grafana/data'; -import { FormInputSize, Icon, useStyles2 } from '@grafana/ui'; -import { inputSizes } from '@grafana/ui/src/components/Forms/commonStyles'; -import { getFocusStyles } from '@grafana/ui/src/themes/mixins'; - -export interface Props { - onChange: (value: Moment) => void; - value?: Moment; - defaultValue?: Moment; - showHour?: boolean; - showSeconds?: boolean; - minuteStep?: number; - size?: FormInputSize; - disabled?: boolean; - disabledHours?: () => number[]; - disabledMinutes?: () => number[]; - disabledSeconds?: () => number[]; - placeholder?: string; - format?: string; - allowEmpty?: boolean; - width?: number; -} - -export const POPUP_CLASS_NAME = 'time-of-day-picker-panel'; - -// @TODO fix TimeOfDayPicker and switch? -export const TimePickerInput = ({ - minuteStep = 1, - showHour = true, - showSeconds = false, - onChange, - value, - size = 'auto', - disabled, - disabledHours, - disabledMinutes, - disabledSeconds, - placeholder, - format = 'HH:mm', - defaultValue = undefined, - allowEmpty = false, - width, -}: Props) => { - const styles = useStyles2(getStyles); - - const getWidth = () => { - if (width) { - return css({ - width: `${width}px`, - }); - } - - return inputSizes()[size]; - }; - - return ( - onChange(v)} - showHour={showHour} - showSecond={showSeconds} - format={format} - allowEmpty={allowEmpty} - className={cx(getWidth(), styles.input)} - popupClassName={cx(styles.picker, POPUP_CLASS_NAME)} - minuteStep={minuteStep} - inputIcon={} - disabled={disabled} - disabledHours={disabledHours} - disabledMinutes={disabledMinutes} - disabledSeconds={disabledSeconds} - placeholder={placeholder} - /> - ); -}; - -interface CaretProps { - wrapperStyle?: string; -} - -const Caret = ({ wrapperStyle = '' }: CaretProps) => { - return ( -
- -
- ); -}; - -const getStyles = (theme: GrafanaTheme2) => { - const bgColor = theme.components.input.background; - const menuShadowColor = theme.v1.palette.black; - const optionBgHover = theme.colors.background.secondary; - const borderRadius = theme.shape.radius.default; - const borderColor = theme.components.input.borderColor; - - return { - caretWrapper: css({ - position: 'absolute', - right: '8px', - top: '50%', - transform: 'translateY(-50%)', - display: 'inline-block', - textAlign: 'right', - color: theme.colors.text.secondary, - }), - picker: css({ - '.rc-time-picker-panel-select': { - fontSize: '14px', - backgroundColor: bgColor, - borderColor: borderColor, - li: { - outlineWidth: '2px', - '&.rc-time-picker-panel-select-option-selected': { - backgroundColor: 'inherit', - border: `1px solid ${theme.v1.palette.orange}`, - borderRadius: borderRadius, - }, - - '&:hover': { - background: optionBgHover, - }, - - '&.rc-time-picker-panel-select-option-disabled': { - color: theme.colors.action.disabledText, - }, - }, - }, - - '.rc-time-picker-panel-inner': { - boxShadow: `0px 4px 4px ${menuShadowColor}`, - backgroundColor: bgColor, - borderColor: borderColor, - borderRadius: borderRadius, - marginTop: '3px', - - '.rc-time-picker-panel-input-wrap': { - marginRight: '2px', - - '&, .rc-time-picker-panel-input': { - backgroundColor: bgColor, - paddingTop: '2px', - }, - }, - - '.rc-time-picker-panel-combobox': { - display: 'flex', - }, - }, - }), - input: css({ - '.rc-time-picker-input': { - backgroundColor: bgColor, - borderRadius: borderRadius, - borderColor: borderColor, - height: theme.spacing(4), - - '&:focus': getFocusStyles(theme), - - '&:disabled': { - backgroundColor: theme.colors.action.disabledBackground, - color: theme.colors.action.disabledText, - border: `1px solid ${theme.colors.action.disabledBackground}`, - '&:focus': { - boxShadow: 'none', - }, - }, - }, - - '.rc-time-picker-clear': { - position: 'absolute', - right: '20px', - top: '50%', - cursor: 'pointer', - overflow: 'hidden', - transform: 'translateY(-50%)', - color: theme.colors.text.secondary, - }, - }), - }; -}; diff --git a/public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx b/public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx index 6fdec781340..9ba25879675 100644 --- a/public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx +++ b/public/app/plugins/datasource/grafana/components/TimeRegionEditor.tsx @@ -2,15 +2,13 @@ import { css } from '@emotion/css'; import moment, { Moment } from 'moment/moment'; import { useState } from 'react'; -import { getTimeZoneInfo, GrafanaTheme2, SelectableValue } from '@grafana/data'; -import { Button, Field, FieldSet, Select, Stack, TimeZonePicker, useStyles2 } from '@grafana/ui'; +import { dateTimeAsMoment, getTimeZoneInfo, GrafanaTheme2, isDateTime, SelectableValue } from '@grafana/data'; +import { Button, Field, FieldSet, Select, Stack, TimeOfDayPicker, TimeZonePicker, useStyles2 } from '@grafana/ui'; import { TimeZoneOffset } from '@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOffset'; import { TimeZoneTitle } from '@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneTitle'; import { TimeRegionConfig } from 'app/core/utils/timeRegions'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; -import { TimePickerInput } from './TimePickerInput'; - interface Props { value: TimeRegionConfig; onChange: (value?: TimeRegionConfig) => void; @@ -74,7 +72,7 @@ export const TimeRegionEditor = ({ value, onChange }: Props) => { return timezone; }; - const onTimeChange = (v: Moment, field: string) => { + const onTimeChange = (v: Moment | undefined, field: string) => { const time = v ? v.format('HH:mm') : undefined; if (field === 'from') { onChange({ ...value, from: time }); @@ -122,6 +120,9 @@ export const TimeRegionEditor = ({ value, onChange }: Props) => { ); }; + const from = getTime(value.from); + const to = getTime(value.to); + return (
@@ -134,12 +135,12 @@ export const TimeRegionEditor = ({ value, onChange }: Props) => { onChange={(v) => onFromDayOfWeekChange(v)} width={20} /> - onTimeChange(v, 'from')} + onTimeChange(v ? dateTimeAsMoment(v) : v, 'from')} allowEmpty={true} placeholder="HH:mm" - width={100} + size="sm" /> @@ -155,12 +156,12 @@ export const TimeRegionEditor = ({ value, onChange }: Props) => { width={20} /> )} - onTimeChange(v, 'to')} + onTimeChange(v ? dateTimeAsMoment(v) : v, 'to')} allowEmpty={true} placeholder="HH:mm" - width={100} + size="sm" /> diff --git a/yarn.lock b/yarn.lock index d5581c46a4f..f44165df0ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1438,7 +1438,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:7.26.0, @babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.0, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.1, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:7.26.0, @babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.0, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.1, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": version: 7.26.0 resolution: "@babel/runtime@npm:7.26.0" dependencies: @@ -3895,8 +3895,8 @@ __metadata: process: "npm:^0.11.10" rc-cascader: "npm:3.33.0" rc-drawer: "npm:7.2.0" + rc-picker: "npm:4.9.2" rc-slider: "npm:11.1.8" - rc-time-picker: "npm:^3.7.3" rc-tooltip: "npm:6.4.0" react: "npm:18.2.0" react-calendar: "npm:^5.1.0" @@ -11522,16 +11522,6 @@ __metadata: languageName: node linkType: hard -"babel-runtime@npm:6.x, babel-runtime@npm:^6.26.0": - version: 6.26.0 - resolution: "babel-runtime@npm:6.26.0" - dependencies: - core-js: "npm:^2.4.0" - regenerator-runtime: "npm:^0.11.0" - checksum: 10/2cdf0f083b9598a43cdb11cbf1e7060584079a9a2230f06aec997ba81e887ef17fdcb5ad813a484ee099e06d2de0cea832bdd3011c06325acb284284c754ee8f - languageName: node - linkType: hard - "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -12819,22 +12809,6 @@ __metadata: languageName: node linkType: hard -"component-classes@npm:^1.2.5": - version: 1.2.6 - resolution: "component-classes@npm:1.2.6" - dependencies: - component-indexof: "npm:0.0.3" - checksum: 10/aa70f282b85a19d7a190dabb2c72c9b8a2a5565fc42d72ca0661e8ce47e55e53da29f468467771d7e0bf4ba8c9723e5a21954fc38b942d9d873ee56be856adfc - languageName: node - linkType: hard - -"component-indexof@npm:0.0.3": - version: 0.0.3 - resolution: "component-indexof@npm:0.0.3" - checksum: 10/34a720e96fc0be1043a4517845b1b7483989736c559089eca285f7ac9ef049eacc8ab12fc31f924dfa2d4ecea0714611a695d087ce11caf30502b5a80646e9e9 - languageName: node - linkType: hard - "compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -13126,7 +13100,7 @@ __metadata: languageName: node linkType: hard -"core-js@npm:^2.4.0, core-js@npm:^2.6.5": +"core-js@npm:^2.6.5": version: 2.6.12 resolution: "core-js@npm:2.6.12" checksum: 10/7c624eb00a59c74c769d5d80f751f3bf1fc6201205b6562f27286ad5e00bbca1483f2f7eb0c2854b86f526ef5c7dc958b45f2ff536f8a31b8e9cb1a13a96efca @@ -13298,16 +13272,6 @@ __metadata: languageName: node linkType: hard -"css-animation@npm:^1.3.2": - version: 1.6.1 - resolution: "css-animation@npm:1.6.1" - dependencies: - babel-runtime: "npm:6.x" - component-classes: "npm:^1.2.5" - checksum: 10/5aea8fd333300c6b15f523ac741dd2ed367489485c7a9a43647f7779fef9e5f338c405e3ad9ed8db338503b4aefea86108112a01bf78651b623f8bd2e146e0e0 - languageName: node - linkType: hard - "css-box-model@npm:^1.2.1": version: 1.2.1 resolution: "css-box-model@npm:1.2.1" @@ -17642,7 +17606,6 @@ __metadata: prismjs: "npm:1.29.0" pseudoizer: "npm:^0.1.0" rc-slider: "npm:11.1.8" - rc-time-picker: "npm:3.7.3" rc-tree: "npm:5.13.0" re-resizable: "npm:6.10.3" react: "npm:18.2.0" @@ -22053,7 +22016,7 @@ __metadata: languageName: node linkType: hard -"moment@npm:2.30.1, moment@npm:2.x, moment@npm:^2.20.1, moment@npm:^2.29.4, moment@npm:^2.30.1": +"moment@npm:2.30.1, moment@npm:^2.20.1, moment@npm:^2.29.4, moment@npm:^2.30.1": version: 2.30.1 resolution: "moment@npm:2.30.1" checksum: 10/ae42d876d4ec831ef66110bdc302c0657c664991e45cf2afffc4b0f6cd6d251dde11375c982a5c0564ccc0fa593fc564576ddceb8c8845e87c15f58aa6baca69 @@ -24710,7 +24673,7 @@ __metadata: languageName: node linkType: hard -"raf@npm:^3.1.0, raf@npm:^3.4.0, raf@npm:^3.4.1": +"raf@npm:^3.1.0, raf@npm:^3.4.1": version: 3.4.1 resolution: "raf@npm:3.4.1" dependencies: @@ -24792,18 +24755,6 @@ __metadata: languageName: node linkType: hard -"rc-align@npm:^2.4.0": - version: 2.4.5 - resolution: "rc-align@npm:2.4.5" - dependencies: - babel-runtime: "npm:^6.26.0" - dom-align: "npm:^1.7.0" - prop-types: "npm:^15.5.8" - rc-util: "npm:^4.0.4" - checksum: 10/6a82f7b47dda397b90c7b6d41e5500b9e3e427891d15a54f95708abf31a8aba19d882bd9e5ab42f4979b455aa2236b96cf6403152507bcd1fd7663be08a0ceb5 - languageName: node - linkType: hard - "rc-align@npm:^4.0.0": version: 4.0.15 resolution: "rc-align@npm:4.0.15" @@ -24820,21 +24771,6 @@ __metadata: languageName: node linkType: hard -"rc-animate@npm:2.x": - version: 2.11.1 - resolution: "rc-animate@npm:2.11.1" - dependencies: - babel-runtime: "npm:6.x" - classnames: "npm:^2.2.6" - css-animation: "npm:^1.3.2" - prop-types: "npm:15.x" - raf: "npm:^3.4.0" - rc-util: "npm:^4.15.3" - react-lifecycles-compat: "npm:^3.0.4" - checksum: 10/afb54ad896c9d50af212ae7a56a216b47b38238a4e8e187437fe965c2cf100f1ca82668ed90d38dcd3b0e3ced53f54383e417af09c6dc09f6db0f78cba2aa9e4 - languageName: node - linkType: hard - "rc-cascader@npm:1.0.1": version: 1.0.1 resolution: "rc-cascader@npm:1.0.1" @@ -24926,6 +24862,51 @@ __metadata: languageName: node linkType: hard +"rc-overflow@npm:^1.3.2": + version: 1.4.1 + resolution: "rc-overflow@npm:1.4.1" + dependencies: + "@babel/runtime": "npm:^7.11.1" + classnames: "npm:^2.2.1" + rc-resize-observer: "npm:^1.0.0" + rc-util: "npm:^5.37.0" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/c5f1daf4ed74ff4d76d593237233a28260d48170deaa87e48b552c0a60ed9cffd23be78bf04472b98da91c2a17f8182589aff7a865c2d66a04731bab6455d216 + languageName: node + linkType: hard + +"rc-picker@npm:4.9.2": + version: 4.9.2 + resolution: "rc-picker@npm:4.9.2" + dependencies: + "@babel/runtime": "npm:^7.24.7" + "@rc-component/trigger": "npm:^2.0.0" + classnames: "npm:^2.2.1" + rc-overflow: "npm:^1.3.2" + rc-resize-observer: "npm:^1.4.0" + rc-util: "npm:^5.43.0" + peerDependencies: + date-fns: ">= 2.x" + dayjs: ">= 1.x" + luxon: ">= 3.x" + moment: ">= 2.x" + react: ">=16.9.0" + react-dom: ">=16.9.0" + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + checksum: 10/5bf0abec3b0fc778a8b0d64023d395f22692b910ead0e63b1f9b941ee510769c814525733bf9084d504567aa449fa50c4dafb18ae95b8e1a291c857e535aeb28 + languageName: node + linkType: hard + "rc-resize-observer@npm:^1.0.0, rc-resize-observer@npm:^1.3.1": version: 1.3.1 resolution: "rc-resize-observer@npm:1.3.1" @@ -24941,6 +24922,21 @@ __metadata: languageName: node linkType: hard +"rc-resize-observer@npm:^1.4.0": + version: 1.4.3 + resolution: "rc-resize-observer@npm:1.4.3" + dependencies: + "@babel/runtime": "npm:^7.20.7" + classnames: "npm:^2.2.1" + rc-util: "npm:^5.44.1" + resize-observer-polyfill: "npm:^1.5.1" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/aff63c93e811440617d0d2c628a8c1b5e2516e5a26e2d8fc99560fd822d06b9de56cd826fb64b094fc3dc8e926e60e2e38bf594134b17a5024c61cd5a406e4cd + languageName: node + linkType: hard + "rc-select@npm:~14.16.2": version: 14.16.3 resolution: "rc-select@npm:14.16.3" @@ -24973,20 +24969,6 @@ __metadata: languageName: node linkType: hard -"rc-time-picker@npm:3.7.3, rc-time-picker@npm:^3.7.3": - version: 3.7.3 - resolution: "rc-time-picker@npm:3.7.3" - dependencies: - classnames: "npm:2.x" - moment: "npm:2.x" - prop-types: "npm:^15.5.8" - raf: "npm:^3.4.1" - rc-trigger: "npm:^2.2.0" - react-lifecycles-compat: "npm:^3.0.4" - checksum: 10/236ba0dd1b1cee4dd398d2542c251a7e0da21b31d3390a23c45cc7f2ea266cfddd1f0b7f681fe205f2d92edaa72771cb087505790b5124eb0ca31668feb74da5 - languageName: node - linkType: hard - "rc-tooltip@npm:6.4.0": version: 6.4.0 resolution: "rc-tooltip@npm:6.4.0" @@ -25018,21 +25000,6 @@ __metadata: languageName: node linkType: hard -"rc-trigger@npm:^2.2.0": - version: 2.6.5 - resolution: "rc-trigger@npm:2.6.5" - dependencies: - babel-runtime: "npm:6.x" - classnames: "npm:^2.2.6" - prop-types: "npm:15.x" - rc-align: "npm:^2.4.0" - rc-animate: "npm:2.x" - rc-util: "npm:^4.4.0" - react-lifecycles-compat: "npm:^3.0.4" - checksum: 10/a3ed5f0c453a37ab00fce302e9f40daa64870eb001576a3409a94550802af1e01cbd7b050b3adf7225af03e82e2070d095477957fcd07209ee32602a2f3fba31 - languageName: node - linkType: hard - "rc-trigger@npm:^4.0.0": version: 4.4.3 resolution: "rc-trigger@npm:4.4.3" @@ -25047,7 +25014,7 @@ __metadata: languageName: node linkType: hard -"rc-util@npm:^4.0.4, rc-util@npm:^4.15.3, rc-util@npm:^4.4.0": +"rc-util@npm:^4.0.4": version: 4.21.1 resolution: "rc-util@npm:4.21.1" dependencies: @@ -25060,7 +25027,7 @@ __metadata: languageName: node linkType: hard -"rc-util@npm:^5.0.1, rc-util@npm:^5.0.6, rc-util@npm:^5.15.0, rc-util@npm:^5.16.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.26.0, rc-util@npm:^5.27.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1, rc-util@npm:^5.43.0, rc-util@npm:^5.44.3": +"rc-util@npm:^5.0.1, rc-util@npm:^5.0.6, rc-util@npm:^5.15.0, rc-util@npm:^5.16.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.26.0, rc-util@npm:^5.27.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1, rc-util@npm:^5.43.0, rc-util@npm:^5.44.1, rc-util@npm:^5.44.3": version: 5.44.3 resolution: "rc-util@npm:5.44.3" dependencies: @@ -26248,13 +26215,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.11.0": - version: 0.11.1 - resolution: "regenerator-runtime@npm:0.11.1" - checksum: 10/64e62d78594c227e7d5269811bca9e4aa6451332adaae8c79a30cab0fa98733b1ad90bdb9d038095c340c6fad3b414a49a8d9e0b6b424ab7ff8f94f35704f8a2 - languageName: node - linkType: hard - "regenerator-runtime@npm:^0.13.4, regenerator-runtime@npm:^0.13.7": version: 0.13.11 resolution: "regenerator-runtime@npm:0.13.11"