diff --git a/packages/datetime/src/components/Calendar/Calendar.tsx b/packages/datetime/src/components/Calendar/Calendar.tsx index 0eb2ba08..97e6bc85 100644 --- a/packages/datetime/src/components/Calendar/Calendar.tsx +++ b/packages/datetime/src/components/Calendar/Calendar.tsx @@ -16,7 +16,7 @@ import { type IStyledOverloadCss, type IStyledPolymorphic, } from '@devoinc/genesys-ui'; -import type { IParseResult } from '../../declarations'; +import type { IParseResult, TDateRange } from '../../declarations'; import { toTimestamp } from '../../helpers'; import { parseAllDates } from '../../parsers'; import { CalendarWeekDay, Cell, type CellProps } from './components'; @@ -48,7 +48,7 @@ export interface CalendarProps * One of `number` or `Date`. */ hoverDay?: Date | number; /** Selected range. */ - value?: (number | Date)[]; + value?: TDateRange; /** Days of the week to show in the calendar. The first day of the week is Monday. */ weekDays?: [string, string, string, string, string, string, string]; weekStart?: number; diff --git a/packages/datetime/src/components/Calendar/behaviors/rangeBehavior.ts b/packages/datetime/src/components/Calendar/behaviors/rangeBehavior.ts index 08193645..52ea84a0 100644 --- a/packages/datetime/src/components/Calendar/behaviors/rangeBehavior.ts +++ b/packages/datetime/src/components/Calendar/behaviors/rangeBehavior.ts @@ -1,6 +1,8 @@ import { compareDesc } from 'date-fns'; -export const rangeBehavior = (range: (number | Date)[], dt: number | Date) => +import type { TDate, TDateRange } from '../../../declarations'; + +export const rangeBehavior = (range: TDateRange, dt: TDate) => range.length === 1 ? compareDesc(dt, range[0]) < 0 ? [range[0], dt] diff --git a/packages/datetime/src/components/Calendar/day.ts b/packages/datetime/src/components/Calendar/day.ts index 6775e5ec..32ceb6f9 100644 --- a/packages/datetime/src/components/Calendar/day.ts +++ b/packages/datetime/src/components/Calendar/day.ts @@ -1,6 +1,6 @@ import { set, getDate, getTime, format } from 'date-fns'; -import type { TParseDate } from '../../declarations'; +import type { TDateRange, TParseDate } from '../../declarations'; import type { TCalendarI18n, TConditionFunction, @@ -181,7 +181,7 @@ export const getClassNameFromProperties = (dayProps: TDayProperties) => [ ...(dayProps.isRightHover ? ['rightmost'] : []), ]; -export const getFrom = (value: (number | Date)[]) => { +export const getFrom = (value: TDateRange) => { if (value[0] && getTime(value[0]) > 0) { return getTime( set(value[0], { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }), @@ -190,7 +190,7 @@ export const getFrom = (value: (number | Date)[]) => { return 0; }; -export const getTo = (value: (number | Date)[]) => { +export const getTo = (value: TDateRange) => { if (value[1] && getTime(value[1]) > 0) { return getTime( set(value[1], { diff --git a/packages/datetime/src/components/DateTimeRange/DateTimeRange.mdx b/packages/datetime/src/components/DateTimeRange/DateTimeRange.mdx index eb0a7707..b12f037e 100644 --- a/packages/datetime/src/components/DateTimeRange/DateTimeRange.mdx +++ b/packages/datetime/src/components/DateTimeRange/DateTimeRange.mdx @@ -51,10 +51,6 @@ The hook `useTimeRangePreserve` return a callback that is aware of changes in the range from calendars or from time pickers and is modifying the final range result to give it to the state management of the upper layer. -## With presets - - - ## Related components - [DateTime](?path=/docs/components-datetime-datetime--docs) diff --git a/packages/datetime/src/components/DateTimeRange/DateTimeRange.stories.tsx b/packages/datetime/src/components/DateTimeRange/DateTimeRange.stories.tsx index 49a82c83..c77d4c3a 100644 --- a/packages/datetime/src/components/DateTimeRange/DateTimeRange.stories.tsx +++ b/packages/datetime/src/components/DateTimeRange/DateTimeRange.stories.tsx @@ -4,6 +4,7 @@ import { Meta, StoryObj } from '@storybook/react'; import { DateTimeRange } from './DateTimeRange'; import { useTimeRangePreserve } from './hooks'; import { defaultPresets } from '../Presets'; +import type { TDateRange } from '../../declarations'; const meta: Meta = { title: 'Components/Datetime/DateTimeRange', @@ -16,7 +17,7 @@ type Story = StoryObj; export const Playground: Story = { render: () => ((args) => { - const [value, setValue] = React.useState<(number | Date)[]>([]); + const [value, setValue] = React.useState([]); const [monthDate, setMonthDate] = React.useState( new Date(), ); @@ -30,6 +31,7 @@ export const Playground: Story = { onChangeMonthDate={(dt) => { setMonthDate(dt); }} + presets={defaultPresets} /> ); })(), @@ -58,29 +60,3 @@ export const PreservingTime: Story = { ); })(), }; - -export const WithPresets: Story = { - tags: ['isHidden'], - render: () => { - return ((args) => { - const [value, setValue] = React.useState<(number | Date)[]>([]); - const [monthDate, setMonthDate] = React.useState( - new Date(), - ); - const { onChangeRange } = useTimeRangePreserve(setValue); - - return ( - { - setMonthDate(dt); - }} - presets={defaultPresets} - /> - ); - })(); - }, -}; diff --git a/packages/datetime/src/components/DateTimeRange/DateTimeRange.tsx b/packages/datetime/src/components/DateTimeRange/DateTimeRange.tsx index fce59fb8..0227f01a 100644 --- a/packages/datetime/src/components/DateTimeRange/DateTimeRange.tsx +++ b/packages/datetime/src/components/DateTimeRange/DateTimeRange.tsx @@ -25,9 +25,10 @@ import { } from './constants'; import { defaultDateTimeRangeI18n } from './i18n'; import { useMergeI18n } from '../../hooks'; +import type { TDateRange } from '../../declarations'; export interface DateTimeRangeProps - extends Pick, + extends Pick, Pick, Pick, Required>, @@ -38,16 +39,13 @@ export interface DateTimeRangeProps /** Show the time input HTML element. */ hasTime?: boolean; /** Function called when clicking a cell or editing a time input HTML. */ - onChange?: (value: (number | Date)[], source: TDateTimeRangeSource) => void; + onChange?: (value: TDateRange, source: TDateTimeRangeSource) => void; /** Placeholder for the presets list */ presetsPlaceholder?: PresetsProps['placeholder']; /** Function called when the displayed month is changed (the left one). One * of `number` or `Date`. */ onChangeMonthDate?: (monthDate: number | Date) => void; - /** Function called when clicking an option from preset date list. */ - onChangePreset?: (preset: string) => void; - /** Selected preset */ - preset?: string; + value?: TDateRange; } export const DateTimeRange: React.FC = ({ @@ -65,8 +63,6 @@ export const DateTimeRange: React.FC = ({ weekDays, presetsPlaceholder, presets, - preset, - onChangePreset = () => null, style, }) => { const i18n = useMergeI18n( @@ -89,6 +85,11 @@ export const DateTimeRange: React.FC = ({ setHoverDay(null); }, []); + const canCalendarRender = React.useMemo( + () => value.length > 0 && value.every((x) => typeof x !== 'string'), + [value], + ); + return ( @@ -108,7 +109,7 @@ export const DateTimeRange: React.FC = ({ onClick={(dt) => { onChange( rangeBehavior( - value, + value as (number | Date)[], set(dt, { hours: 0, minutes: 0, @@ -119,9 +120,9 @@ export const DateTimeRange: React.FC = ({ DATE_TIME_RANGE_SOURCE_CAL_LEFT, ); }} - value={value} - hasLeftHoverEffect={value.length === 1} - hasRightHoverEffect={value.length === 1} + value={canCalendarRender ? (value as (number | Date)[]) : []} + hasLeftHoverEffect={canCalendarRender ? value.length === 1 : false} + hasRightHoverEffect={canCalendarRender ? value.length === 1 : false} parseDate={parseDate} weekDays={weekDays} hoverDay={hoverDay} @@ -150,8 +151,8 @@ export const DateTimeRange: React.FC = ({ ); }} size="sm" - value={value.length >= 2 ? value[0] : null} - disabled={value.length < 2} + value={canCalendarRender && value.length >= 2 ? value[0] : ''} + disabled={!canCalendarRender || value.length < 2} /> )} @@ -184,9 +185,9 @@ export const DateTimeRange: React.FC = ({ DATE_TIME_RANGE_SOURCE_CAL_RIGHT, ); }} - value={value} - hasLeftHoverEffect={value.length === 1} - hasRightHoverEffect={value.length === 1} + value={canCalendarRender ? value : []} + hasLeftHoverEffect={canCalendarRender ? value.length === 1 : false} + hasRightHoverEffect={canCalendarRender ? value.length === 1 : false} parseDate={parseDate} weekDays={weekDays} hoverDay={hoverDay} @@ -215,8 +216,8 @@ export const DateTimeRange: React.FC = ({ ); }} size="sm" - value={value.length >= 2 ? value[1] : null} - disabled={value.length < 2} + value={canCalendarRender && value.length >= 2 ? value[1] : ''} + disabled={!canCalendarRender || value.length < 2} /> )} @@ -224,13 +225,13 @@ export const DateTimeRange: React.FC = ({ {presets && ( { - onChangePreset(newPreset); + onChange={(newValue) => { + onChange(newValue, 'presets'); }} /> diff --git a/packages/datetime/src/components/DateTimeRange/declarations.ts b/packages/datetime/src/components/DateTimeRange/declarations.ts index 224a60a6..68552708 100644 --- a/packages/datetime/src/components/DateTimeRange/declarations.ts +++ b/packages/datetime/src/components/DateTimeRange/declarations.ts @@ -1,10 +1,11 @@ -import { TMonthSelectorI18n } from "../MonthSelector"; +import { TMonthSelectorI18n } from '../MonthSelector'; export type TDateTimeRangeSource = | 'cal-left' | 'cal-right' | 'time-left' - | 'time-right'; + | 'time-right' + | 'presets'; export type TDateTimeRangeI18n = TMonthSelectorI18n & { /** The from month text */ diff --git a/packages/datetime/src/components/DateTimeRangeFloatingPicker/DateTimeRangeFloatingPicker.tsx b/packages/datetime/src/components/DateTimeRangeFloatingPicker/DateTimeRangeFloatingPicker.tsx index 3f98db72..a58e8499 100644 --- a/packages/datetime/src/components/DateTimeRangeFloatingPicker/DateTimeRangeFloatingPicker.tsx +++ b/packages/datetime/src/components/DateTimeRangeFloatingPicker/DateTimeRangeFloatingPicker.tsx @@ -13,7 +13,7 @@ import { import { parseStrDate } from '../../parsers'; import { formatDate as formatDateHelper } from '../../helpers'; -import type { IParseResult, ITime } from '../../declarations'; +import type { IParseResult, ITime, TDateRange } from '../../declarations'; import { DateTimeRange, type DateTimeRangeProps } from '../DateTimeRange'; import { DateTimeRangeInput, @@ -32,12 +32,7 @@ export interface DateTimeRangeFloatingPickerProps >, Pick< DateTimeRangeProps, - | 'monthDate' - | 'preset' - | 'presets' - | 'presetsPlaceholder' - | 'onChangePreset' - | 'weekDays' + 'monthDate' | 'presets' | 'presetsPlaceholder' | 'weekDays' >, Pick< DateTimeRangeInputProps, @@ -55,7 +50,7 @@ export interface DateTimeRangeFloatingPickerProps /** Internacionalization object */ i18n?: TDateTimeRangeFloatingPickerI18n; /** Initial value for the input. */ - value: (string | number | Date)[]; + value: TDateRange; /** Enable or disable the Apply button. */ disableApplyButton: boolean; /** Function called when Cancel button is clicked. */ @@ -84,13 +79,10 @@ export const DateTimeRangeFloatingPicker: React.FC< placement, size = 'md', value, - preset, presets = defaultPresets, presetsPlaceholder, - onChangePreset = () => null, autoApply = false, onRealTimeClick, - }) => { const i18n = useMergeI18n( userI18n, @@ -179,13 +171,7 @@ export const DateTimeRangeFloatingPicker: React.FC< i18n={i18n} id={id ? `${id}-datetime-range` : null} onChange={setTmpValue} - onChangePreset={onChangePreset} - value={ - typeof tmpValue[0] === 'string' - ? null - : (tmpValue as (number | Date)[]) - } - preset={preset} + value={tmpValue} presets={presets} presetsPlaceholder={presetsPlaceholder} monthDate={monthDate} diff --git a/packages/datetime/src/components/Presets/eq.ts b/packages/datetime/src/components/Presets/eq.ts index dfb8e516..287dc14e 100644 --- a/packages/datetime/src/components/Presets/eq.ts +++ b/packages/datetime/src/components/Presets/eq.ts @@ -1,7 +1,7 @@ import type { TDateRange } from '../../declarations'; export const arePresetValuesEqual = (a: TDateRange, b: TDateRange) => - a.length === b.length + a?.length === b?.length ? a.every((item, index) => typeof item === typeof b[index] ? typeof item === 'number' || typeof item === 'string' diff --git a/packages/datetime/src/components/Time/Time.tsx b/packages/datetime/src/components/Time/Time.tsx index 180dbddd..cdcd1615 100644 --- a/packages/datetime/src/components/Time/Time.tsx +++ b/packages/datetime/src/components/Time/Time.tsx @@ -10,7 +10,7 @@ import { type IStyledPolymorphic, } from '@devoinc/genesys-ui'; -import type { ITime } from '../../declarations'; +import type { ITime, TDate } from '../../declarations'; import { getFormatTimeStr, formatDate } from '../../helpers'; import { TTimeI18n } from './declarations'; import { defaultTimeI18n } from './i18n'; @@ -26,7 +26,7 @@ export interface TimeProps /** The size of the Time, specially the input. */ size?: TFieldSize; /** Initial value. One of `number` or `Date`. */ - value?: Date | number; + value?: TDate; /** Diable the time field */ disabled?: boolean; /** Internacionalization object */ @@ -41,7 +41,7 @@ export const Time: React.FC = ({ onChange, size = 'md', style, - value, + value = '', disabled = false, i18n: userI18n = defaultTimeI18n, minDate, diff --git a/packages/datetime/src/declarations.ts b/packages/datetime/src/declarations.ts index 9d7d4da0..5e21a098 100644 --- a/packages/datetime/src/declarations.ts +++ b/packages/datetime/src/declarations.ts @@ -19,4 +19,5 @@ export interface IParseResult { export type TParseDate = (dt: number | Date) => IParseResult; -export type TDateRange = (number | string | Date)[]; +export type TDate = number | string | Date; +export type TDateRange = TDate[]; diff --git a/packages/datetime/src/helpers/formatter.ts b/packages/datetime/src/helpers/formatter.ts index 4aec0f5b..2a3592f8 100644 --- a/packages/datetime/src/helpers/formatter.ts +++ b/packages/datetime/src/helpers/formatter.ts @@ -15,6 +15,6 @@ export const getFormatDateStr = () => 'yyyy-MM-dd'; * Formats a date string based on the provided parameters */ export const formatDate = ( - dt: Date | number, + dt: string | number | Date, format: string = 'yyyy-MM-dd HH:mm:ss', -): string => formatFNS(dt, format); +): string => (typeof dt === 'string' ? dt : formatFNS(dt, format));