Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/clay-date-picker/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ To set internationalization of the component, you need to configure the props ac
<DatePickerLocale />

- [`firstDayOfWeek`](#api-firstDayOfWeek) by default the value by default the value is 0 (Sunday) and its values ​​are the days of the week, 1 (Monday), 2 (Tuesday), 3 (Wednesday), 4 (Thursday), 5 (Friday), 6 (Saturday).
- [`dateFormat`](#api-dateFormat) and `timeFormat` is defined according to the **formatting rules of [Moment.js](https://momentjs.com/docs/#/parsing/string-format/)**.
- [`dateFormat`](#api-dateFormat) and `timeFormat` is defined according to the **formatting rules of [date-fns](https://date-fns.org/v2.14.0/docs/format)** which is an implementation of the [unicode technical standards](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table).
- [`months`](#api-months) is an `Array<string>` with available months **starting January to December**.
- [`weekdaysShort`](#api-weekdaysShort) is an `Array<string>` with the **names of the days of the week in short form**, starting from **Sunday to Saturday**.

Expand All @@ -86,6 +86,10 @@ To customize the Date Picker content footer you can use the [`footerElement`](#a

If you want to expand or close the picker from outside of the component, use the props `expand` and `onExpandChange`.

## Note about Moment.js

In version 3.4.0, we made the decision to switch to use [date-fns](https://date-fns.org/v2.14.0) instead of Moment.js due to dependency size. Making this changed help reduce the size of @clayui/date-picker by almost 50 KB.

## API

<div>[APITable "clay-date-picker/src/index.tsx"]</div>
2 changes: 1 addition & 1 deletion packages/clay-date-picker/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const DatePickerLocale = () => {

return (
<ClayDatePicker
dateFormat="DD.MM.YYYY"
dateFormat="dd.MM.yyyy"
firstDayOfWeek={1}
months={[
'Январь',
Expand Down
2 changes: 1 addition & 1 deletion packages/clay-date-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@clayui/icon": "^3.0.5",
"@clayui/time-picker": "^3.1.3",
"classnames": "^2.2.6",
"moment": "^2.22.2"
"date-fns": "^2.14.0"
},
"peerDependencies": {
"@clayui/css": "3.x",
Expand Down
7 changes: 3 additions & 4 deletions packages/clay-date-picker/src/DateNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@

import Button from '@clayui/button';
import Icon from '@clayui/icon';
import moment from 'moment';
import React from 'react';

import * as Helpers from './Helpers';
import {addMonths, range} from './Helpers';
import Select, {ISelectOption} from './Select';
import {IAriaLabels, IYears} from './types';

Expand Down Expand Up @@ -40,7 +39,7 @@ const ClayDatePickerDateNavigation: React.FunctionComponent<IProps> = ({
}) => {
const memoizedYears: Array<ISelectOption> = React.useMemo(
() =>
Helpers.range(years).map((elem) => {
range(years).map((elem) => {
return {
label: elem,
value: elem,
Expand Down Expand Up @@ -69,7 +68,7 @@ const ClayDatePickerDateNavigation: React.FunctionComponent<IProps> = ({
* years in the range
*/
function handleChangeMonth(month: number) {
const date = moment(currentMonth).clone().add(month, 'M').toDate();
const date = addMonths(currentMonth, month);
const year = date.getFullYear();

if (memoizedYears.find((elem) => elem.value === year)) {
Expand Down
27 changes: 12 additions & 15 deletions packages/clay-date-picker/src/DayNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
*/

import classnames from 'classnames';
import moment from 'moment';
import React from 'react';

import {IDay} from './Helpers';
import {IDay, formatDate, setDate} from './Helpers';

interface IProps {
day: IDay;
Expand All @@ -25,27 +24,25 @@ const ClayDatePickerDayNumber: React.FunctionComponent<IProps> = ({
const classNames = classnames(
'date-picker-date date-picker-calendar-item',
{
active:
moment(day.date).format('YYYY-MM-DD') ===
moment(daySelected).format('YYYY-MM-DD'),
active: day.date.toDateString() === daySelected.toDateString(),
disabled: day.outside || disabled,
}
);

const handleClick = () => onClick(day.date);

return (
<button
aria-label={moment(day.date)
.clone()
.set('hour', 12)
.set('minute', 0)
.set('second', 0)
.set('millisecond', 0)
.format('YYYY MM DD')}
aria-label={formatDate(
setDate(day.date, {
hours: 12,
milliseconds: 0,
minutes: 0,
seconds: 0,
}),
'yyyy MM dd'
)}
className={classNames}
disabled={day.outside}
onClick={handleClick}
onClick={() => onClick(day.date)}
type="button"
>
{day.date.getDate()}
Expand Down
54 changes: 38 additions & 16 deletions packages/clay-date-picker/src/Helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

import moment from 'moment';
import {default as formatDate} from 'date-fns/format';
import {default as parseDate} from 'date-fns/parse';

export {formatDate, parseDate};

export interface IDay {
date: Date;
Expand All @@ -17,8 +20,8 @@ export type Month = Array<WeekDays>;
/**
* Clone a date object.
*/
export function clone(d: Date) {
return new Date(d.getTime());
export function clone(date: number | Date) {
return new Date(date instanceof Date ? date.getTime() : date);
}

export function getDaysInMonth(d: Date) {
Expand Down Expand Up @@ -103,17 +106,36 @@ export function range({end, start}: {end: number; start: number}) {
);
}

/**
* Helper function for getting certain props from `moment`.
* This allows users to not have to import and use `moment` themselves.
*/
export function getLocaleProps(locale: string) {
const localeData = moment.localeData(locale);

return {
dateFormat: localeData.longDateFormat('L'),
firstDayOfWeek: localeData.firstDayOfWeek(),
months: localeData.months(),
weekdaysShort: localeData.weekdaysShort(),
};
export function addMonths(date: number | Date, months: number) {
date = clone(date);

date.setMonth(date.getMonth() + months);

return date;
}

export function setDate(
date: Date,
obj: {
date?: number | string;
seconds?: number | string;
milliseconds?: number | string;
hours?: number | string;
minutes?: number | string;
year?: number | string;
}
) {
date = clone(date);

return Object.keys(obj).reduce((acc, key) => {
const method = `set${key.charAt(0).toUpperCase() + key.slice(1)}`;
// @ts-ignore
acc[method](obj[key]);

return acc;
}, date);
}

export function isValid(date: Date) {
return date instanceof Date && !isNaN(date.getTime());
}
19 changes: 10 additions & 9 deletions packages/clay-date-picker/src/Hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,46 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

import moment from 'moment';
import React from 'react';

import * as Helpers from './Helpers';
import {Month, formatDate, getWeekArray, setDate} from './Helpers';
import {FirstDayOfWeek} from './types';

/**
* Generates the table of days of the month.
*/
const useWeeks = (currentMonth: Date, firstDayOfWeek: FirstDayOfWeek) => {
const [weeks, set] = React.useState<Helpers.Month>(() =>
Helpers.getWeekArray(currentMonth, firstDayOfWeek)
const [weeks, set] = React.useState<Month>(() =>
getWeekArray(currentMonth, firstDayOfWeek)
);

function setWeeks(value: Date) {
set(Helpers.getWeekArray(value, firstDayOfWeek));
set(getWeekArray(value, firstDayOfWeek));
}

return [weeks, setWeeks] as [Helpers.Month, (value: Date) => void];
return [weeks, setWeeks] as [Month, (value: Date) => void];
};

/**
* Sets the current time
*/
const useCurrentTime = (format: string) => {
const [currentTime, set] = React.useState<string>(() =>
moment().set('h', 0).set('m', 0).format(format)
formatDate(setDate(new Date(), {hours: 0, minutes: 0}), format)
);

function setCurrentTime(
hours: number | string,
minutes: number | string
): void {
const date = setDate(new Date(), {hours, minutes});

if (typeof hours !== 'string') {
hours = moment().set('h', hours).format('H');
hours = formatDate(date, 'H');
}

if (typeof minutes !== 'string') {
minutes = moment().set('m', minutes).format('m');
minutes = formatDate(date, 'm');
}

set(`${hours}:${minutes}`);
Expand Down
11 changes: 4 additions & 7 deletions packages/clay-date-picker/src/InputDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
*/

import {ClayInput} from '@clayui/form';
import moment from 'moment';
import React from 'react';

import {formatDate, isValid} from './Helpers';

interface IProps extends React.HTMLAttributes<HTMLInputElement> {
ariaLabel?: string;
currentTime: string;
Expand All @@ -15,7 +16,6 @@ interface IProps extends React.HTMLAttributes<HTMLInputElement> {
inputName?: string;
placeholder?: string;
time: boolean;
timeFormat: string;
useNative: boolean;
value: string;
}
Expand All @@ -28,18 +28,15 @@ const ClayDatePickerInputDate = React.forwardRef<HTMLInputElement, IProps>(
dateFormat,
inputName = 'datePicker',
time = false,
timeFormat,
useNative = false,
value = '',
...otherProps
},
ref
) => {
const isValidValue = (value: string | Date): string => {
const format = time ? `${dateFormat} ${timeFormat}` : dateFormat;

if (moment(value, format).isValid() && value instanceof Date) {
const date = moment(value).clone().format(dateFormat);
if (value instanceof Date && isValid(value)) {
const date = formatDate(value, dateFormat);

return time ? `${date} ${currentTime}` : date;
}
Expand Down
Loading