From fb1b31a128c5792cbf4c20724ff3f7356cc2029d Mon Sep 17 00:00:00 2001 From: Nosferatu31 Date: Wed, 31 May 2023 20:19:10 +0100 Subject: [PATCH] [Feature] Add locale support by adding another type of config - Fix typo in filename --- src/index.tsx | 2 +- src/range.tsx | 50 +++++++++++++++++++++++++++---- src/single.tsx | 50 +++++++++++++++++++++++++++---- src/utils/calanderUtils.ts | 39 ------------------------ src/utils/calendarUtils.ts | 61 ++++++++++++++++++++++++++++++++++++++ src/utils/commonTypes.ts | 14 +++++++++ 6 files changed, 164 insertions(+), 52 deletions(-) delete mode 100644 src/utils/calanderUtils.ts create mode 100644 src/utils/calendarUtils.ts diff --git a/src/index.tsx b/src/index.tsx index 335dc6d..10a9f67 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,6 @@ export type { DatepickerConfigs, OnDateSelected } from './utils/commonTypes'; export type { CalendarPanelProps } from './components/calendarPanel'; -export * from './utils/calanderUtils'; +export * from './utils/calendarUtils'; export { CalendarPanel } from './components/calendarPanel'; export * from './single'; export * from './range'; diff --git a/src/range.tsx b/src/range.tsx index ab1bd37..586e58a 100644 --- a/src/range.tsx +++ b/src/range.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { Props as DayzedHookProps } from 'dayzed'; -import { Month_Names_Short, Weekday_Names_Short } from './utils/calanderUtils'; +import { Month_Names_Short, Weekday_Names_Short } from './utils/calendarUtils'; import { Flex, Input, @@ -14,13 +14,17 @@ import { import { CalendarPanel } from './components/calendarPanel'; import { CalendarConfigs, + CalendarLocaleConfigs, DatepickerConfigs, + DatepickerLocaleConfigs, DatepickerProps, OnDateSelected, PropsConfigs, } from './utils/commonTypes'; import { format } from 'date-fns'; import FocusLock from 'react-focus-lock'; +import { daysForLocale, monthsForLocale } from './utils/calendarUtils'; +import * as dateFnsLocales from 'date-fns/locale'; interface RangeCalendarPanelProps { dayzedHookProps: DayzedHookProps; @@ -82,7 +86,7 @@ export const RangeCalendarPanel: React.FC = ({ export interface RangeDatepickerProps extends DatepickerProps { selectedDates: Date[]; - configs?: DatepickerConfigs; + configs?: DatepickerConfigs | DatepickerLocaleConfigs; disabled?: boolean; defaultIsOpen?: boolean; closeOnSelect?: boolean; @@ -99,6 +103,13 @@ const DefaultConfigs: CalendarConfigs = { firstDayOfWeek: 0, }; +const DefaultLocaleConfigs: CalendarLocaleConfigs = { + locale: 'en-US', + month: 'short', + day: 'short', + firstDayOfWeek: 0, +}; + export const RangeDatepicker: React.FC = ({ configs, propsConfigs = {}, @@ -116,10 +127,37 @@ export const RangeDatepicker: React.FC = ({ const [offset, setOffset] = useState(0); const { onOpen, onClose, isOpen } = useDisclosure({ defaultIsOpen }); - const calendarConfigs: CalendarConfigs = { - ...DefaultConfigs, - ...configs, - }; + let calendarConfigs: CalendarConfigs; + + if (configs !== undefined && 'locale' in configs) { + let calendarLocaleConfigs = { + ...DefaultLocaleConfigs, + ...configs, + }; + + let currentDateFns = + Object.values(dateFnsLocales) + .filter((dateFns) => dateFns.code === calendarLocaleConfigs.locale) + .pop() || dateFnsLocales.enUS; + + calendarConfigs = { + dateFormat: currentDateFns.formatLong?.date({ width: 'short' }), + dayNames: daysForLocale( + calendarLocaleConfigs.locale, + calendarLocaleConfigs.day + ), + monthNames: monthsForLocale( + calendarLocaleConfigs.locale, + calendarLocaleConfigs.month + ), + firstDayOfWeek: calendarLocaleConfigs.firstDayOfWeek, + }; + } else { + calendarConfigs = { + ...DefaultConfigs, + ...configs, + }; + } const onPopoverClose = () => { onClose(); diff --git a/src/single.tsx b/src/single.tsx index 9ceaac6..ea65a3b 100644 --- a/src/single.tsx +++ b/src/single.tsx @@ -10,19 +10,23 @@ import { } from '@chakra-ui/react'; import { format } from 'date-fns'; import FocusLock from 'react-focus-lock'; -import { Month_Names_Short, Weekday_Names_Short } from './utils/calanderUtils'; +import { Month_Names_Short, Weekday_Names_Short } from './utils/calendarUtils'; import { CalendarPanel } from './components/calendarPanel'; import { CalendarConfigs, DatepickerConfigs, DatepickerProps, + CalendarLocaleConfigs, + DatepickerLocaleConfigs, OnDateSelected, } from './utils/commonTypes'; +import { daysForLocale, monthsForLocale } from './utils/calendarUtils'; +import * as dateFnsLocales from 'date-fns/locale'; export interface SingleDatepickerProps extends DatepickerProps { date?: Date; onDateChange: (date: Date) => void; - configs?: DatepickerConfigs; + configs?: DatepickerConfigs | DatepickerLocaleConfigs; disabled?: boolean; /** * disabledDates: `Uses startOfDay as comparison` @@ -42,6 +46,13 @@ const DefaultConfigs: CalendarConfigs = { firstDayOfWeek: 0, }; +const DefaultLocaleConfigs: CalendarLocaleConfigs = { + locale: 'en-US', + month: 'short', + day: 'short', + firstDayOfWeek: 0, +}; + export const SingleDatepicker: React.FC = ({ configs, propsConfigs, @@ -66,10 +77,37 @@ export const SingleDatepicker: React.FC = ({ const { onOpen, onClose, isOpen } = useDisclosure({ defaultIsOpen }); - const calendarConfigs: CalendarConfigs = { - ...DefaultConfigs, - ...configs, - }; + let calendarConfigs: CalendarConfigs; + + if (configs !== undefined && 'locale' in configs) { + let calendarLocaleConfigs = { + ...DefaultLocaleConfigs, + ...configs, + }; + + let currentDateFns = + Object.values(dateFnsLocales) + .filter((dateFns) => dateFns.code === calendarLocaleConfigs.locale) + .pop() || dateFnsLocales.enUS; + + calendarConfigs = { + dateFormat: currentDateFns.formatLong?.date({ width: 'short' }), + dayNames: daysForLocale( + calendarLocaleConfigs.locale, + calendarLocaleConfigs.day + ), + monthNames: monthsForLocale( + calendarLocaleConfigs.locale, + calendarLocaleConfigs.month + ), + firstDayOfWeek: calendarLocaleConfigs.firstDayOfWeek, + }; + } else { + calendarConfigs = { + ...DefaultConfigs, + ...configs, + }; + } const onPopoverClose = () => { onClose(); diff --git a/src/utils/calanderUtils.ts b/src/utils/calanderUtils.ts deleted file mode 100644 index cafc41a..0000000 --- a/src/utils/calanderUtils.ts +++ /dev/null @@ -1,39 +0,0 @@ -export const Month_Names_Full = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', -]; - -export const Month_Names_Short = [ - 'Jan', - 'Feb', - 'Mar', - 'Apr', - 'May', - 'Jun', - 'Jul', - 'Aug', - 'Sep', - 'Oct', - 'Nov', - 'Dec', -]; - -export const Weekday_Names_Short = [ - 'Sun', - 'Mon', - 'Tue', - 'Wed', - 'Thu', - 'Fri', - 'Sat', -]; diff --git a/src/utils/calendarUtils.ts b/src/utils/calendarUtils.ts new file mode 100644 index 0000000..f46cc81 --- /dev/null +++ b/src/utils/calendarUtils.ts @@ -0,0 +1,61 @@ +export const Month_Names_Full = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +export const Month_Names_Short = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', +]; + +export const Weekday_Names_Short = [ + 'Sun', + 'Mon', + 'Tue', + 'Wed', + 'Thu', + 'Fri', + 'Sat', +]; + +export function daysForLocale( + localeName: string = 'en-US', + weekday: 'short' | 'long' = 'short' +) { + const { format } = new Intl.DateTimeFormat(localeName, { weekday }); + return [...Array(7).keys()].map((day) => + format(new Date(Date.UTC(2021, 5, day - 1))) + ); +} + +export function monthsForLocale( + localeName: string = 'en-US', + monthFormat: 'short' | 'long' = 'short' +) { + const { format } = new Intl.DateTimeFormat(localeName, { + month: monthFormat, + }); + return [...Array(12).keys()].map((m) => + format(new Date(Date.UTC(2021, m % 12))) + ); +} diff --git a/src/utils/commonTypes.ts b/src/utils/commonTypes.ts index 2546854..c46422e 100644 --- a/src/utils/commonTypes.ts +++ b/src/utils/commonTypes.ts @@ -46,3 +46,17 @@ export interface CalendarConfigs { dayNames: string[]; firstDayOfWeek: 0 | 1 | 2 | 3 | 4 | 5 | 6; } + +export interface DatepickerLocaleConfigs { + locale?: string; + month?: 'long' | 'short'; + day?: 'long' | 'short'; + firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6; +} + +export interface CalendarLocaleConfigs { + locale: string; + month: 'long' | 'short'; + day: 'long' | 'short'; + firstDayOfWeek: 0 | 1 | 2 | 3 | 4 | 5 | 6; +}