From 5e3970810789a3c6ee9bdd2430e238db2d244c2c Mon Sep 17 00:00:00 2001 From: John Simon <772985+whatisaphone@users.noreply.github.com> Date: Tue, 12 Mar 2019 10:20:29 -0400 Subject: [PATCH] Locales without globals (#1660) * Allow using locales without passing them through a global variable * Add an example of using locales without a global variable --- docs-site/src/example_components.jsx | 5 ++ .../locale_without_global_variable.jsx | 57 +++++++++++++++++++ src/calendar.jsx | 5 +- src/date_utils.js | 10 +++- src/index.jsx | 5 +- src/month.jsx | 5 +- src/week.jsx | 5 +- test/calendar_test.js | 15 +++++ 8 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 docs-site/src/examples/locale_without_global_variable.jsx diff --git a/docs-site/src/example_components.jsx b/docs-site/src/example_components.jsx index 8b6f86621..321d1d77d 100644 --- a/docs-site/src/example_components.jsx +++ b/docs-site/src/example_components.jsx @@ -10,6 +10,7 @@ import CustomDayClassNames from "./examples/custom_day_class_names"; import PlaceholderText from "./examples/placeholder_text"; import SpecificDateRange from "./examples/specific_date_range"; import Locale from "./examples/locale"; +import LocaleWithoutGlobalVariable from "./examples/locale_without_global_variable"; import ExcludeDates from "./examples/exclude_dates"; import HighlightDates from "./examples/highlight_dates"; import HighlightDatesRanges from "./examples/highlight_dates_with_ranges"; @@ -125,6 +126,10 @@ export default class exampleComponents extends React.Component { title: "Locale", component: }, + { + title: "Locale without global variables", + component: + }, { title: "Exclude dates", component: diff --git a/docs-site/src/examples/locale_without_global_variable.jsx b/docs-site/src/examples/locale_without_global_variable.jsx new file mode 100644 index 000000000..4d265bac0 --- /dev/null +++ b/docs-site/src/examples/locale_without_global_variable.jsx @@ -0,0 +1,57 @@ +import React from "react"; +import DatePicker, { registerLocale } from "react-datepicker"; +import fi from "date-fns/locale/fi"; + +export default class LocaleWithoutGlobalVariable extends React.Component { + state = { + startDate: null + }; + + handleChange = date => { + this.setState({ + startDate: date + }); + }; + + render() { + return ( +
+
+          
+            {
+              "// Note: Make sure to npm install the right version of date-fns as"
+            }
+            
+ { + "// specified in packaged.json. The default one may not be compatiable" + } +
+ {"// npm install --save date-fns@version"} +
+ {"import DatePicker from 'react-datepicker';"} +
+ {"import fi from 'date-fns/locale/fi';"} +
+
+ {" + {" selected={this.state.startDate}"} +
+ {" onChange={this.handleChange}"} +
+ {" locale={fi}"} +
+ {"/>"} +
+
+
+ +
+
+ ); + } +} diff --git a/src/calendar.jsx b/src/calendar.jsx index 62859347a..0264d8fca 100644 --- a/src/calendar.jsx +++ b/src/calendar.jsx @@ -65,7 +65,10 @@ export default class Calendar extends React.Component { includeTimes: PropTypes.array, injectTimes: PropTypes.array, inline: PropTypes.bool, - locale: PropTypes.string, + locale: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ locale: PropTypes.object }) + ]), maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), monthsShown: PropTypes.number, diff --git a/src/date_utils.js b/src/date_utils.js index fcb6d45f8..b3af46df9 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -256,8 +256,14 @@ export function getDefaultLocale() { return window.__localeId__; } -export function getLocaleObject(localeName) { - return window.__localeData__ ? window.__localeData__[localeName] : null; +export function getLocaleObject(localeSpec) { + if (typeof localeSpec === "string") { + // Treat it as a locale name registered by registerLocale + return window.__localeData__ ? window.__localeData__[localeSpec] : null; + } else { + // Treat it as a raw date-fns locale object + return localeSpec; + } } export function getFormattedWeekdayInLocale(date, formatFunc, locale) { diff --git a/src/index.jsx b/src/index.jsx index 5fd0c0682..4bbf127a5 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -100,7 +100,10 @@ export default class DatePicker extends React.Component { injectTimes: PropTypes.array, inline: PropTypes.bool, isClearable: PropTypes.bool, - locale: PropTypes.string, + locale: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ locale: PropTypes.object }) + ]), maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), monthsShown: PropTypes.number, diff --git a/src/month.jsx b/src/month.jsx index 7c10cd6a2..0f3c57094 100644 --- a/src/month.jsx +++ b/src/month.jsx @@ -20,7 +20,10 @@ export default class Month extends React.Component { highlightDates: PropTypes.instanceOf(Map), includeDates: PropTypes.array, inline: PropTypes.bool, - locale: PropTypes.string, + locale: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ locale: PropTypes.object }) + ]), maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), onDayClick: PropTypes.func, diff --git a/src/week.jsx b/src/week.jsx index d8ff91430..cd15a0f0e 100644 --- a/src/week.jsx +++ b/src/week.jsx @@ -21,7 +21,10 @@ export default class Week extends React.Component { highlightDates: PropTypes.instanceOf(Map), includeDates: PropTypes.array, inline: PropTypes.bool, - locale: PropTypes.string, + locale: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ locale: PropTypes.object }) + ]), maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), month: PropTypes.number, diff --git a/test/calendar_test.js b/test/calendar_test.js index 0db262167..69385c337 100644 --- a/test/calendar_test.js +++ b/test/calendar_test.js @@ -11,6 +11,7 @@ import DatePicker from "../src/index.jsx"; import { shallow, mount } from "enzyme"; import sinon from "sinon"; import * as utils from "../src/date_utils"; +import eo from "date-fns/locale/eo"; import fi from "date-fns/locale/fi"; // TODO Possibly rename @@ -983,6 +984,20 @@ describe("Calendar", function() { utils.setDefaultLocale(""); }); + it("should accept a raw date-fns locale object", function() { + // Note that we explicitly do not call `registerLocale`, because that + // would create a global variable, which we want to avoid. + const locale = eo; + const selected = utils.newDate(); + + const calendar = getCalendar({ selected, locale }); + testLocale(calendar, selected, locale); + + // Other tests touch this global, so it will always be present, but at the + // very least we can make sure the test worked without 'eo' being added. + expect(window.__localeData__).not.to.haveOwnProperty("eo"); + }); + it("should render empty custom header", function() { const calendar = getCalendar({ renderCustomHeader: () => {} });