Skip to content

Commit d480f14

Browse files
committed
Implement localization functionality with <LocalizationProvider /> powered by date-io
1 parent 9643fb7 commit d480f14

File tree

14 files changed

+185
-5
lines changed

14 files changed

+185
-5
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Ref: https://github.com/mui/mui-x/blob/5dc5bd4b04eecf21c45cf6ea1169727ba5ab3be3/packages/x-date-pickers/src/LocalizationProvider/LocalizationProvider.tsx
2+
3+
import * as React from "react";
4+
import { DateIOFormats } from "@date-io/core/IUtils";
5+
import { IUtils } from "@date-io/core/IUtils";
6+
7+
type DateAdapter<TDate> = IUtils<TDate>;
8+
9+
export interface DateAdapterContextValue<TDate> {
10+
utils: DateAdapter<TDate>;
11+
}
12+
13+
export const DateAdapterContext =
14+
React.createContext<DateAdapterContextValue<unknown> | null>(null);
15+
if (process.env.NODE_ENV !== "production") {
16+
DateAdapterContext.displayName = "DateAdapterContext";
17+
}
18+
19+
export interface LocalizationProviderProps {
20+
children?: React.ReactNode;
21+
/** DateIO adapter class function */
22+
dateAdapter: new (...args: any) => DateAdapter<unknown>;
23+
/** Formats that are used for the child dropdown */
24+
dateFormats?: Partial<DateIOFormats>;
25+
/**
26+
* Date library instance you are using, if it has some global overrides
27+
* ```jsx
28+
* dateLibInstance={momentTimeZone}
29+
* ```
30+
*/
31+
dateLibInstance?: any;
32+
/** Locale for the date library you are using */
33+
locale?: string | object;
34+
}
35+
36+
/**
37+
* @ignore - do not document.
38+
*/
39+
export function LocalizationProvider(props: LocalizationProviderProps) {
40+
const {
41+
children,
42+
dateAdapter: Utils,
43+
dateFormats,
44+
dateLibInstance,
45+
locale,
46+
} = props;
47+
const utils = React.useMemo(
48+
() =>
49+
new Utils({ locale, formats: dateFormats, instance: dateLibInstance }),
50+
[Utils, locale, dateFormats, dateLibInstance]
51+
);
52+
53+
const contextValue: DateAdapterContextValue<unknown> = React.useMemo(() => {
54+
return { utils };
55+
}, [utils]);
56+
57+
return (
58+
<DateAdapterContext.Provider value={contextValue}>
59+
{children}
60+
</DateAdapterContext.Provider>
61+
);
62+
}

src/LocalizationProvider/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./LocalizationProvider";
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as React from "react";
2+
import { DateAdapterContext } from "./LocalizationProvider";
3+
4+
export const useUtils = () => {
5+
const localization = React.useContext(DateAdapterContext);
6+
7+
if (localization == null) {
8+
return null;
9+
}
10+
11+
return localization.utils;
12+
};

src/adapters/date-fns-jalali.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "@date-io/date-fns-jalali";

src/adapters/date-fns.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "@date-io/date-fns";

src/adapters/dayjs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "@date-io/dayjs";

src/adapters/jalaali.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "@date-io/jalaali";

src/adapters/luxon.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "@date-io/luxon";

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export {
77
export * from "./use-date-select";
88
export { getDateString } from "./date-string";
99
export * from "./types";
10+
export * from "./LocalizationProvider";

src/use-date-select.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
22
import { range } from "./range";
33
import { compileDateString, parseDateString } from "./date-string";
44
import { Option, Options } from "./types";
5+
import { useUtils } from "./LocalizationProvider/useUtils";
56

67
const DEFAULT_MIN_YEAR = 1960;
78
const DEFAULT_MAX_YEAR = new Date().getFullYear();
@@ -17,9 +18,6 @@ function compileOption(value: string): Option {
1718
return { value, label: value }; // TODO: Be customizable for localization
1819
}
1920

20-
const monthOptions: Options = range(1, 12).map((i) =>
21-
compileOption(convertToSelectValue(i))
22-
);
2321
const dayOptions: Options = range(1, 31).map((i) =>
2422
compileOption(convertToSelectValue(i))
2523
);
@@ -169,6 +167,8 @@ export const useDateSelect = (
169167
}
170168
}, [setDate, value]);
171169

170+
const utils = useUtils();
171+
172172
const yearOptions = useMemo(() => {
173173
const minYear = opts.minYear != null ? opts.minYear : DEFAULT_MIN_YEAR;
174174
const maxYear = opts.maxYear != null ? opts.maxYear : DEFAULT_MAX_YEAR;
@@ -182,6 +182,15 @@ export const useDateSelect = (
182182
return raw;
183183
}, [opts.minYear, opts.maxYear, state.yearValue]);
184184

185+
const monthOptions: Options = useMemo(() => {
186+
return range(1, 12).map((i) => {
187+
const label = utils
188+
? utils.format(new Date(1960, i - 1, 1), "monthShort")
189+
: convertToSelectValue(i);
190+
return { value: convertToSelectValue(i), label };
191+
});
192+
}, [utils]);
193+
185194
return {
186195
yearValue: state.yearValue,
187196
monthValue: state.monthValue,

0 commit comments

Comments
 (0)