Skip to content

Commit

Permalink
feat(react/date-pickers)!: replace Calendar with DateCalendar
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `Calendar` component has been deprecated. Use `DateCalendar` component instead.
  • Loading branch information
cheton committed Dec 21, 2024
1 parent a6597a2 commit ae03b20
Show file tree
Hide file tree
Showing 24 changed files with 137 additions and 82 deletions.
2 changes: 1 addition & 1 deletion packages/react-docs/config/sidebar-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const routes = [

{ title: 'DATE PICKERS', heading: true },
{ title: 'Overview', path: 'components/date-pickers' },
{ title: 'Calendar', path: 'components/date-pickers/calendar' },
{ title: 'DateCalendar', path: 'components/date-pickers/date-calendar' },
{ title: 'DatePicker', path: 'components/date-pickers/date-picker' },

{ title: 'FEEDBACK', heading: true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Calendar
# DateCalendar

## Import

```js
import {
Calendar,
DateCalendar,
} from '@tonic-ui/react';
```

Expand All @@ -14,16 +14,16 @@ import {

## Props

### Calendar
### DateCalendar

| Name | Type | Default | Description |
| :--- | :--- | :------ | :---------- |
| date | Date | | The selected date. |
| defaultDate | Date | | The default selected date. |
| defaultValue | Date | | The default selected date. |
| firstDayOfWeek | number | 0 | The first day of the week.<br/>0 = Sunday<br/>1 = Monday<br/>2 = Tuesday<br/>3 = Wednesday<br/>4 = Thursday<br/>5 = Friday<br/>6 = Saturday |
| formatDate | function | | A callback called to return the formatted date string in the given format.<br/><br/><b>Signature</b><br/>`function(date, format, options) => void`<br/>_date_: The original date.<br/>_format_: The string of [format tokens](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table).<br/>_options_: An object with options. |
| minDate | Date | | The minimum date that can be selected. |
| maxDate | Date | | The maximum date that can be selected. |
| onChange | function | | A callback called when the value (the selected date) changes.<br/><br/><b>Signature:</b><br/>`function(value) => void`<br/>_value_: The selected date. |
| onError | function | | An error-first callback called when the date validation returns an error (or the date is valid after error).<br/><br/><b>Signature</b><br/>`function(error, value) => void`<br/>_error_: The error message. It will be `undefined` if the date is valid after error.<br/>_value_: The selected date. |
| shouldDisableDate | function | | Disable specific date.<br/><br/><b>Signature:</b><br/>`function(date) => boolean`<br/>_date_: The date to check.<br/>_returns (boolean)_: Return `true` if the date will be disabled. |
| value | Date | | The selected date. |
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
Box,
Button,
ButtonGroup,
Calendar,
Code,
DateCalendar,
Divider,
Flex,
Input,
Expand Down Expand Up @@ -90,8 +90,8 @@ const App = () => {
)}
</Flex>
</FormGroup>
<Calendar
date={date}
<DateCalendar
value={date}
firstDayOfWeek={firstDayOfWeek}
formatDate={(date, format) => {
const options = {
Expand All @@ -102,11 +102,9 @@ const App = () => {
maxDate={maxDate ? new Date(maxDate) : undefined}
minDate={minDate ? new Date(minDate) : undefined}
onChange={(nextDate) => {
console.log('onChange:', nextDate);
setDate(nextDate);
}}
onError={(error, value) => {
console.log('onError:', error);
setError(error);
}}
shouldDisableDate={(date) => {
Expand Down Expand Up @@ -139,8 +137,8 @@ const App = () => {
</MenuButton>
<MenuList
onClick={(event) => {
const value = event.target.getAttribute('value');
setLocale(value);
const localeValue = event.target.getAttribute('value');
setLocale(localeValue);
}}
maxHeight={240}
minWidth={100}
Expand Down Expand Up @@ -170,13 +168,13 @@ const App = () => {
{`// format\nimport format from 'date-fns/format';\n\n// locale\nimport enLocale from 'date-fns/locale/en-US'; // English (United States)\nimport deLocale from 'date-fns/locale/de'; // Deutsch\nimport esLocale from 'date-fns/locale/es'; // Español\nimport frLocale from 'date-fns/locale/fr'; // Français\nimport itLocale from 'date-fns/locale/it'; // Italiano\nimport jaLocale from 'date-fns/locale/ja'; // 日本語\nimport koLocale from 'date-fns/locale/ko'; // 한국어\nimport zhCNLocale from 'date-fns/locale/zh-CN'; // 简体中文\nimport zhTWLocale from 'date-fns/locale/zh-TW'; // 繁體中文`}
</PreformattedText>
<PreformattedText>
{`// Calendar component\nformatDate={(date, format, options) => {\n return format(date, format, { locale: enLocale });\n}}`}
{`// DateCalendar component\nformatDate={(date, format, options) => {\n return format(date, format, { locale: enLocale });\n}}`}
</PreformattedText>
</Flex>
<Divider my="4x" />
<Box mb="4x">
<Text fontSize="lg" lineHeight="lg">
Calendar props
DateCalendar props
</Text>
</Box>
<FormGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const disableWeekends = (date) => {
const App = () => {
const [maxDate, setMaxDate] = useState('');
const [minDate, setMinDate] = useState('');
const [closeOnSelect, toggleCloseOnSelect] = useToggle(false);
const [closeOnSelect, toggleCloseOnSelect] = useToggle(true);
const [dateOption, changeDateOptionBy] = useSelection('none');
const [firstDayOfWeek, changeFirstDayOfWeekBy] = useSelection(0);
const [inputFormat, changeInputFormatBy] = useSelection(inputFormats[0]);
Expand Down Expand Up @@ -139,15 +139,12 @@ const App = () => {
maxDate={maxDate ? new Date(maxDate) : undefined}
minDate={minDate ? new Date(minDate) : undefined}
onChange={(nextValue) => {
console.log('onChange:', nextValue);
setValue(nextValue);
}}
onError={(error, value) => {
console.log('onError:', error, value);
setError(error);
}}
shouldDisableDate={(date) => {
console.log('shouldDisableDate:', date, shouldDisableDateOption);
if (shouldDisableDateOption === 'weekdays') {
return disableWeekdays(date);
}
Expand All @@ -159,7 +156,6 @@ const App = () => {
value={value}
inputFormat={inputFormat}
renderInput={({ error: inputError, inputProps }) => {
console.log('renderInput:', inputError, inputProps);
return (
<Box>
<DateInput
Expand Down Expand Up @@ -195,8 +191,8 @@ const App = () => {
</MenuButton>
<MenuList
onClick={(event) => {
const value = event.target.getAttribute('value');
setLocale(value);
const localeValue = event.target.getAttribute('value');
setLocale(localeValue);
}}
maxHeight={240}
minWidth={100}
Expand Down
3 changes: 2 additions & 1 deletion packages/react/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ test('should match expected exports', () => {
const expectedExports = [
// deprecated
'AccordionCollapse',
'Calendar',
'ToastProvider',
'useToast',

Expand Down Expand Up @@ -61,7 +62,7 @@ test('should match expected exports', () => {
'CSSBaseline',

// date-pickers
'Calendar',
'DateCalendar',
'DatePicker',

// default-props
Expand Down
10 changes: 0 additions & 10 deletions packages/react/src/date-pickers/Calendar/context.js

This file was deleted.

3 changes: 0 additions & 3 deletions packages/react/src/date-pickers/Calendar/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { useConst, usePrevious } from '@tonic-ui/react-hooks';
import {
useConst,
useOnceWhen,
usePrevious,
} from '@tonic-ui/react-hooks';
import {
getActiveElement,
getAllFocusable,
isNullOrUndefined,
warnDeprecatedProps,
} from '@tonic-ui/utils';
import differenceInCalendarDays from 'date-fns/differenceInCalendarDays';
import addMonths from 'date-fns/addMonths';
Expand All @@ -21,10 +26,10 @@ import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'rea
import { Box } from '../../box';
import { useDefaultProps } from '../../default-props';
import { validateDate } from '../validation';
import { CalendarProvider } from './context';
import { DateCalendarProvider } from './context';
import MonthDate from './MonthDate';
import YearMonthPicker from './YearMonthPicker';
import { useCalendarStyle } from './styles';
import { useDateCalendarStyle } from './styles';

const getMemoizedState = memoize(state => ({ ...state }));

Expand All @@ -46,22 +51,50 @@ const mapValueToEndOfDay = (value) => {
return (isDate(date) && isValid(date)) ? endOfDay(date) : null;
};

const Calendar = forwardRef((inProps, ref) => {
const {
const DateCalendar = forwardRef((inProps, ref) => {

Check warning on line 54 in packages/react/src/date-pickers/DateCalendar/DateCalendar.js

View workflow job for this annotation

GitHub Actions / build

Arrow function has too many lines (262). Maximum allowed is 200
let {
date: dateProp, // deprecated
defaultDate: defaultDateProp, // deprecated

children, // eslint-disable-line no-unused-vars
date: dateProp,
defaultDate: defaultDateProp,
defaultValue: defaultValueProp,
firstDayOfWeek = 0, // 0 = Sunday, 1 = Monday, ...
formatDate: formatDateProp,
maxDate: maxDateProp,
minDate: minDateProp,
onChange: onChangeProp,
onError: onErrorProp,
shouldDisableDate,
value: valueProp,
...rest
} = useDefaultProps({ props: inProps, name: 'Calendar' });
} = useDefaultProps({ props: inProps, name: 'DateCalendar' });

{ // deprecation warning
const prefix = `${DateCalendar.displayName}:`;

useOnceWhen(() => {
warnDeprecatedProps('date', {

Check warning on line 76 in packages/react/src/date-pickers/DateCalendar/DateCalendar.js

View check run for this annotation

Codecov / codecov/patch

packages/react/src/date-pickers/DateCalendar/DateCalendar.js#L76

Added line #L76 was not covered by tests
prefix,
alternative: 'value',
willRemove: true,
});
}, (dateProp !== undefined));

useOnceWhen(() => {
warnDeprecatedProps('defaultDate', {

Check warning on line 84 in packages/react/src/date-pickers/DateCalendar/DateCalendar.js

View check run for this annotation

Codecov / codecov/patch

packages/react/src/date-pickers/DateCalendar/DateCalendar.js#L84

Added line #L84 was not covered by tests
prefix,
alternative: 'defaultValue',
willRemove: true,
});
}, (defaultDateProp !== undefined));

// TODO: remove `date` and `defaultDate` props in next major version
valueProp = valueProp ?? dateProp;
defaultValueProp = defaultValueProp ?? defaultDateProp;
}

const initialDate = useConst(() => {
const value = dateProp ?? defaultDateProp;
const value = valueProp ?? defaultValueProp;
return mapValueToDate(value);
});
const initialActiveDate = useConst(() => {
Expand Down Expand Up @@ -117,12 +150,12 @@ const Calendar = forwardRef((inProps, ref) => {
}, [date, onErrorProp, previousValidationError, validationError]);

useEffect(() => {
const isControlled = (dateProp !== undefined);
const isControlled = (valueProp !== undefined);
if (isControlled) {
const nextDate = dateProp;
const nextDate = valueProp;
setDate(nextDate);
}
}, [dateProp]);
}, [valueProp]);

useEffect(() => {
const isDateChanged = !!date && (date !== previousDate);
Expand Down Expand Up @@ -155,13 +188,13 @@ const Calendar = forwardRef((inProps, ref) => {
}, [activeDate]); // Re-run effect when activeDate changes

const onChange = useCallback((nextDate) => {
const isControlled = (dateProp !== undefined);
const isControlled = (valueProp !== undefined);
if (!isControlled) {
setDate(nextDate);
}

onChangeProp?.(nextDate);
}, [dateProp, onChangeProp]);
}, [valueProp, onChangeProp]);

const calendarMonthDateEventHandler = {};

Expand Down Expand Up @@ -428,10 +461,10 @@ const Calendar = forwardRef((inProps, ref) => {
});

const tabIndex = -1;
const styleProps = useCalendarStyle({ tabIndex });
const styleProps = useDateCalendarStyle({ tabIndex });

return (
<CalendarProvider value={context}>
<DateCalendarProvider value={context}>
<Box
ref={ref}
tabIndex={tabIndex}
Expand All @@ -444,10 +477,10 @@ const Calendar = forwardRef((inProps, ref) => {
{...calendarMonthDateEventHandler}
/>
</Box>
</CalendarProvider>
</DateCalendarProvider>
);
});

Calendar.displayName = 'Calendar';
DateCalendar.displayName = 'DateCalendar';

export default Calendar;
export default DateCalendar;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import isSameMonth from 'date-fns/isSameMonth';
import React, { forwardRef } from 'react';
import { Box } from '../../../box';
import { useDayStyle } from '../styles';
import useCalendar from '../useCalendar';
import useDateCalendar from '../useDateCalendar';

const Day = forwardRef((
{
Expand All @@ -17,7 +17,7 @@ const Day = forwardRef((
},
ref,
) => {
const calendarContext = useCalendar();
const dateCalendarContext = useDateCalendar();
const {
activeDate,
date: selectedDate,
Expand All @@ -27,7 +27,7 @@ const Day = forwardRef((
onChange,
setActiveDate,
shouldDisableDate,
} = { ...calendarContext };
} = { ...dateCalendarContext };
const isSelectable = (() => {
if (minDate && isBefore(date, minDate)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import startOfWeek from 'date-fns/startOfWeek';
import React, { forwardRef } from 'react';
import { Box } from '../../../box';
import { Grid } from '../../../grid';
import useCalendar from '../useCalendar';
import useDateCalendar from '../useDateCalendar';
import { useDaysOfWeekStyle } from '../styles';

const DaysOfWeek = forwardRef((props, ref) => {
const calendarContext = useCalendar();
const dateCalendarContext = useDateCalendar();
const {
activeDate,
firstDayOfWeek,
formatDate,
} = { ...calendarContext };
} = { ...dateCalendarContext };
const startDateOfWeek = startOfWeek(activeDate, {
weekStartsOn: firstDayOfWeek,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import startOfMonth from 'date-fns/startOfMonth';
import startOfWeek from 'date-fns/startOfWeek';
import React, { forwardRef } from 'react';
import { Grid } from '../../../grid';
import useCalendar from '../useCalendar';
import useDateCalendar from '../useDateCalendar';
import Week from './Week';

const isWeekInMonth = (startDateOfWeek, activeDate) => {
Expand All @@ -17,11 +17,11 @@ const Weeks = forwardRef((
props,
ref,
) => {
const calendarContext = useCalendar();
const dateCalendarContext = useDateCalendar();
const {
activeDate,
firstDayOfWeek,
} = { ...calendarContext };
} = { ...dateCalendarContext };
const weeks = [];
let startDateOfWeek = startOfWeek(startOfMonth(activeDate), {
weekStartsOn: firstDayOfWeek,
Expand Down
Loading

0 comments on commit ae03b20

Please sign in to comment.