├── .nvmrc ├── e2e ├── support │ ├── commands.js │ └── index.js ├── tsconfig.json └── integration │ └── DatePicker.spec.ts ├── docs ├── .env ├── src │ ├── react-app-env.d.ts │ ├── assets │ │ ├── pickers-logo.png │ │ └── mui-logo.svg │ ├── Pages │ │ ├── Guides │ │ │ ├── CssOverridesTypescript.example.tsx │ │ │ ├── ControllingProgrammatically.jsx │ │ │ ├── Formik.jsx │ │ │ ├── StaticPickers.jsx │ │ │ ├── FormatsCustomization.example.jsx │ │ │ ├── StaticPickers.example.jsx │ │ │ ├── Formik.example.jsx │ │ │ ├── ControllingProgrammatically.example.jsx │ │ │ ├── CssOverrides.example.jsx │ │ │ ├── FormatsCustomization.jsx │ │ │ └── CssOverrides.jsx │ │ ├── Regression │ │ │ ├── RegressionDay.tsx │ │ │ └── Regression.tsx │ │ ├── GettingStarted │ │ │ ├── MuiPickersProvider.example.jsx │ │ │ ├── QuickStart.example.jsx │ │ │ ├── ParsingDates.jsx │ │ │ ├── Usage.jsx │ │ │ └── Installation.jsx │ │ ├── Components │ │ │ ├── TimePicker │ │ │ │ ├── KeyboardTimePicker.example.jsx │ │ │ │ ├── InlineTimePicker.example.jsx │ │ │ │ ├── SecondsTimePicker.example.jsx │ │ │ │ ├── TimePickerBasic.example.jsx │ │ │ │ └── TimePickerDemo.jsx │ │ │ ├── DateTimePicker │ │ │ │ ├── BasicDateTimePicker.example.jsx │ │ │ │ ├── DateTimePickerDemo.jsx │ │ │ │ └── InlineDateTimePicker.example.jsx │ │ │ └── DatePicker │ │ │ │ ├── BasicDatePicker.example.jsx │ │ │ │ ├── YearMonthPicker.example.jsx │ │ │ │ ├── InlineDatePicker.example.jsx │ │ │ │ ├── DatePickerDemo.jsx │ │ │ │ └── KeyboardDatePicker.example.jsx │ │ ├── Localization │ │ │ ├── Date-fns │ │ │ │ ├── DateFnsLocalization.tsx │ │ │ │ └── DateFnsLocalization.example.jsx │ │ │ ├── Moment │ │ │ │ ├── MomentLocalization.jsx │ │ │ │ └── MomentLocalization.example.jsx │ │ │ └── Persian │ │ │ │ ├── PersianCalendar.jsx │ │ │ │ └── PersianCalendar.example.jsx │ │ └── Router.tsx │ ├── index.css │ ├── _shared │ │ ├── svgIcons │ │ │ ├── LightbulbIcon.tsx │ │ │ └── GithubIcon.jsx │ │ ├── UtilsServiceContext.tsx │ │ ├── Code.tsx │ │ └── SourcablePanel.jsx │ ├── Landing │ │ ├── Landing.css │ │ └── components │ │ │ └── PatreonSponsors.jsx │ ├── utils │ │ ├── utilsService.ts │ │ └── helpers.ts │ ├── index.tsx │ ├── layout │ │ ├── DrawerMenu.tsx │ │ ├── NavigationMenu.jsx │ │ └── NavItem.jsx │ └── App.tsx ├── .firebaserc ├── public │ ├── icons │ │ ├── favicon.ico │ │ ├── apple-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── ms-icon-70x70.png │ │ ├── apple-icon-57x57.png │ │ ├── apple-icon-60x60.png │ │ ├── apple-icon-72x72.png │ │ ├── apple-icon-76x76.png │ │ ├── ms-icon-144x144.png │ │ ├── ms-icon-150x150.png │ │ ├── ms-icon-310x310.png │ │ ├── android-icon-36x36.png │ │ ├── android-icon-48x48.png │ │ ├── android-icon-72x72.png │ │ ├── android-icon-96x96.png │ │ ├── apple-icon-114x114.png │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-144x144.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-180x180.png │ │ ├── android-icon-144x144.png │ │ ├── android-icon-192x192.png │ │ └── apple-icon-precomposed.png │ ├── manifest.json │ └── index.html ├── README.md ├── firebase.json ├── tsconfig.json ├── scripts │ ├── generate-backers.js │ └── docgen.js └── package.json ├── .gitattributes ├── .npmignore ├── lerna.json ├── lib ├── src │ ├── constants │ │ ├── DatePickerView.ts │ │ ├── dimensions.ts │ │ ├── DateTimePickerView.ts │ │ ├── ClockType.ts │ │ └── prop-types.ts │ ├── __tests__ │ │ ├── tsconfig.json │ │ ├── _shared │ │ │ ├── PickerToolbar.test.tsx │ │ │ ├── ToolbarButton.test.tsx │ │ │ └── MaskedInput.test.tsx │ │ ├── TimePicker │ │ │ ├── ClockNumber.test.tsx │ │ │ ├── TimePickerModal.test.tsx │ │ │ ├── ClockPointer.test.tsx │ │ │ ├── TimePicker.test.tsx │ │ │ ├── TimePickerView.test.tsx │ │ │ └── Clock.test.tsx │ │ ├── DatePicker │ │ │ ├── DatePickerInline.test.tsx │ │ │ ├── DatePicker.test.tsx │ │ │ ├── YearSelection.test.tsx │ │ │ ├── DatePickerModal.test.tsx │ │ │ ├── CalendarHeader.test.tsx │ │ │ ├── Month.test.tsx │ │ │ ├── MonthSelection.test.tsx │ │ │ └── Calendar.test.tsx │ │ ├── DateTimePicker │ │ │ ├── DateTimePickerView.test.tsx │ │ │ ├── DateTimePickerModal.test.tsx │ │ │ ├── DateTimePicker.test.tsx │ │ │ ├── DateTimePickerInline.test.tsx │ │ │ ├── DateTimePickerTabs.test.tsx │ │ │ └── DateTimePickerHeader.test.tsx │ │ ├── MuiPickersUtilsProvider.test.tsx │ │ ├── setup.js │ │ ├── e2e │ │ │ ├── TimePicker.test.tsx │ │ │ ├── DateTimePicker.test.tsx │ │ │ ├── DateTimePickerInline.test.tsx │ │ │ └── DatePickerInline.test.tsx │ │ ├── wrappers │ │ │ └── ModalWrapper.test.tsx │ │ └── test-utils.tsx │ ├── typings │ │ ├── date.ts │ │ ├── extendMui.ts │ │ └── overrides.ts │ ├── wrappers │ │ └── ExtendWrapper.ts │ ├── DatePicker │ │ ├── index.ts │ │ ├── components │ │ │ ├── DayWrapper.tsx │ │ │ ├── Month.tsx │ │ │ ├── Year.tsx │ │ │ ├── Day.tsx │ │ │ └── MonthSelection.tsx │ │ ├── DatePickerInline.tsx │ │ └── DatePickerModal.tsx │ ├── TimePicker │ │ ├── index.tsx │ │ ├── TimePickerInline.tsx │ │ ├── TimePickerModal.tsx │ │ └── components │ │ │ ├── ClockNumbers.tsx │ │ │ └── ClockNumber.tsx │ ├── _shared │ │ ├── icons │ │ │ ├── ArrowLeftIcon.tsx │ │ │ ├── ArrowRightIcon.tsx │ │ │ ├── KeyboardIcon.tsx │ │ │ ├── DateRangeIcon.tsx │ │ │ └── TimeIcon.tsx │ │ ├── MaskedInput.tsx │ │ ├── WithUtils.tsx │ │ ├── ToolbarButton.tsx │ │ └── PickerToolbar.tsx │ ├── DateTimePicker │ │ ├── index.ts │ │ ├── components │ │ │ ├── DateTimePickerView.tsx │ │ │ └── DateTimePickerTabs.tsx │ │ └── DateTimePickerInline.tsx │ ├── MuiPickersUtilsProvider.tsx │ ├── index.ts │ └── _helpers │ │ ├── text-field-helper.ts │ │ ├── time-utils.ts │ │ └── date-utils.ts ├── tslint.json ├── rollup.config.dev.js ├── tsconfig.build.json ├── tsconfig.json ├── .size-snapshot.json ├── remove-prop-types.js └── copy.js ├── .prettierrc ├── .editorconfig ├── cypress.json ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── .travis.yml ├── .gitignore ├── tsconfig.base.json ├── .circleci └── config.yml ├── LICENSE └── package.json /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.env: -------------------------------------------------------------------------------- 1 | PORT="3002" 2 | NODE_PATH="src/" 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js text eol=lf 2 | *.jsx text eol=lf 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/* 2 | lib/* 3 | src/* 4 | node_modules/* -------------------------------------------------------------------------------- /docs/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["lib", "docs"], 3 | "version": "0.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /docs/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "material-ui-pickers" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/constants/DatePickerView.ts: -------------------------------------------------------------------------------- 1 | export type DatePickerViewType = 'year' | 'month' | 'day'; 2 | -------------------------------------------------------------------------------- /lib/src/constants/dimensions.ts: -------------------------------------------------------------------------------- 1 | export const DIALOG_WIDTH = 310; 2 | 3 | export const DIALOG_WIDTH_WIDER = 325; 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /docs/public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/favicon.ico -------------------------------------------------------------------------------- /docs/public/icons/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon.png -------------------------------------------------------------------------------- /docs/src/assets/pickers-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/src/assets/pickers-logo.png -------------------------------------------------------------------------------- /lib/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./**/*.tsx"], 4 | "exclude": [] 5 | } 6 | -------------------------------------------------------------------------------- /docs/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /docs/public/icons/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/ms-icon-70x70.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-57x57.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-60x60.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-72x72.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-76x76.png -------------------------------------------------------------------------------- /docs/public/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/icons/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/ms-icon-150x150.png -------------------------------------------------------------------------------- /docs/public/icons/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/ms-icon-310x310.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-36x36.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-48x48.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-72x72.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-96x96.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-114x114.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/icons/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/android-icon-192x192.png -------------------------------------------------------------------------------- /docs/public/icons/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinsagovac/material-ui-pickers/develop/docs/public/icons/apple-icon-precomposed.png -------------------------------------------------------------------------------- /lib/src/typings/date.ts: -------------------------------------------------------------------------------- 1 | // 21.02.2018 - TODO type date, if there would be any way to dynamicly type Moment | Date 2 | export type MaterialUiPickersDate = any; 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | trim_trailing_whitespace = true 9 | charset = utf-8 -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:3002", 3 | "integrationFolder": "e2e/integration", 4 | "supportFile": "e2e/support/index.js", 5 | "chromeWebSecurity": false, 6 | "projectId": "qow28y" 7 | } 8 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | This PR closes # 4 | 5 | ## Description 6 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Documentation website project for `material-ui-pickers` 2 | 3 | To run this project just move up to the root and run `npm start`. Thus docs folder will watch for any changes made in `lib` 4 | 5 | Happy hacking 😉 6 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "baseUrl": "../node_modules", 5 | "target": "es5", 6 | "lib": ["es5", "dom"], 7 | "types": ["cypress"] 8 | }, 9 | "include": ["**/*.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/CssOverridesTypescript.example.tsx: -------------------------------------------------------------------------------- 1 | export default `declare module '@material-ui/core/styles/overrides' { 2 | import { MuiPickersOverrides } from 'material-ui-pickers/typings/overrides' 3 | 4 | export interface Overrides extends MuiPickersOverrides { } 5 | }`; 6 | -------------------------------------------------------------------------------- /lib/src/constants/DateTimePickerView.ts: -------------------------------------------------------------------------------- 1 | enum DateTimePickerView { 2 | YEAR = 'year', 3 | 4 | DATE = 'date', 5 | 6 | HOUR = 'hours', 7 | 8 | MINUTES = 'minutes', 9 | } 10 | 11 | export type DateTimePickerViewType = 'year' | 'date' | 'hours' | 'minutes'; 12 | 13 | export default DateTimePickerView; 14 | -------------------------------------------------------------------------------- /lib/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:latest", "tslint-config-prettier"], 3 | "rules": { 4 | "no-submodule-imports": false, 5 | "interface-name": false, 6 | "object-literal-sort-keys": false, 7 | "no-object-literal-type-assertion": false, 8 | "no-implicit-dependencies": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/wrappers/ExtendWrapper.ts: -------------------------------------------------------------------------------- 1 | import { Omit } from '@material-ui/core'; 2 | import { InlineWrapperProps } from './InlineWrapper'; 3 | import { ModalWrapperProps } from './ModalWrapper'; 4 | 5 | export type ExtendWrapper = Omit< 6 | T, 7 | 'onChange' | 'value' | 'format' 8 | >; 9 | -------------------------------------------------------------------------------- /lib/src/constants/ClockType.ts: -------------------------------------------------------------------------------- 1 | enum ClockType { 2 | HOURS = 'hours', 3 | 4 | MINUTES = 'minutes', 5 | 6 | SECONDS = 'seconds', 7 | } 8 | 9 | // TODO: fix naming, this should be consistent with the DateTimePickerView file 10 | export type ClockTypeType = 'hours' | 'minutes' | 'seconds'; 11 | 12 | export default ClockType; 13 | -------------------------------------------------------------------------------- /docs/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Material ui pickers", 3 | "name": "Material ui pickers docs", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } 14 | -------------------------------------------------------------------------------- /lib/rollup.config.dev.js: -------------------------------------------------------------------------------- 1 | import fullConfig from './rollup.config'; 2 | 3 | // use only esm module generation for development 4 | const esmConfig = fullConfig.find(buildConfig => buildConfig.output.format === 'esm'); 5 | esmConfig.plugins = esmConfig.plugins.filter(plugin => 6 | ['node-resolve', 'typescript', 'babel'].includes(plugin.name) 7 | ); 8 | 9 | export default [esmConfig]; 10 | -------------------------------------------------------------------------------- /lib/src/typings/extendMui.ts: -------------------------------------------------------------------------------- 1 | import { Omit } from '@material-ui/core'; 2 | /** 3 | * All standard components exposed by `material-ui` are `StyledComponents` with 4 | * certain `classes`, on which one can also set a top-level `className` and inline 5 | * `style`. 6 | */ 7 | export type ExtendMui = Omit< 8 | C, 9 | 'classes' | 'theme' | Removals 10 | >; 11 | -------------------------------------------------------------------------------- /lib/src/DatePicker/index.ts: -------------------------------------------------------------------------------- 1 | import { DatePickerInlineProps } from './DatePickerInline'; 2 | import { DatePickerModalProps } from './DatePickerModal'; 3 | 4 | export type DatePickerProps = DatePickerModalProps; 5 | 6 | export type DatePickerInlineProps = DatePickerInlineProps; 7 | 8 | export { default } from './DatePickerModal'; 9 | 10 | export { default as InlineDatePicker } from './DatePickerInline'; 11 | -------------------------------------------------------------------------------- /lib/src/TimePicker/index.tsx: -------------------------------------------------------------------------------- 1 | import { TimePickerInlineProps } from './TimePickerInline'; 2 | import { TimePickerModalProps } from './TimePickerModal'; 3 | 4 | export type TimePickerProps = TimePickerModalProps; 5 | 6 | export type TimePickerInlineProps = TimePickerInlineProps; 7 | 8 | export { default } from './TimePickerModal'; 9 | 10 | export { default as InlineTimePicker } from './TimePickerInline'; 11 | -------------------------------------------------------------------------------- /lib/src/_shared/icons/ArrowLeftIcon.tsx: -------------------------------------------------------------------------------- 1 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 2 | import React from 'react'; 3 | 4 | export const ArrowLeftIcon: React.SFC = props => { 5 | return ( 6 | 7 | 8 | 9 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /lib/src/_shared/icons/ArrowRightIcon.tsx: -------------------------------------------------------------------------------- 1 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 2 | import React from 'react'; 3 | 4 | export const ArrowRightIcon: React.SFC = props => { 5 | return ( 6 | 7 | 8 | 9 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /lib/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | // rollup-plugin-typescript does not resolve `extends`, so tsconfig.build.json is the base and we just alter it for IDE and testing. 2 | { 3 | "extends": "../../tsconfig.base.json", 4 | "compilerOptions": { 5 | "module": "es6", 6 | "noEmit": true, 7 | "sourceMap": true, 8 | "jsx": "react" 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": ["./src/__tests__/**/*"] 12 | } 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | 5 | cache: 6 | # cache both npm modules and Cypress binary 7 | directories: 8 | - ~/.npm 9 | - ~/.cache 10 | override: 11 | - npm ci 12 | 13 | before_install: 14 | - cd lib 15 | 16 | env: 17 | - CMD='test:date-fns' 18 | - CMD='test:luxon' 19 | - CMD='test:moment' 20 | - CMD='build:analyze' 21 | - CMD='lint' 22 | 23 | script: npm run $CMD 24 | -------------------------------------------------------------------------------- /docs/src/assets/mui-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/src/DateTimePicker/index.ts: -------------------------------------------------------------------------------- 1 | import { DateTimePickerInlineProps } from './DateTimePickerInline'; 2 | import { DateTimePickerModalProps } from './DateTimePickerModal'; 3 | 4 | export type DateTimePickerProps = DateTimePickerModalProps; 5 | 6 | export type DateTimePickerInlineProps = DateTimePickerInlineProps; 7 | 8 | export { default } from './DateTimePickerModal'; 9 | 10 | export { default as InlineDateTimePicker } from './DateTimePickerInline'; 11 | -------------------------------------------------------------------------------- /lib/src/constants/prop-types.ts: -------------------------------------------------------------------------------- 1 | import * as PropTypes from 'prop-types'; 2 | 3 | const date = PropTypes.oneOfType([ 4 | PropTypes.object, 5 | PropTypes.string, 6 | PropTypes.number, 7 | PropTypes.instanceOf(Date), 8 | ]); 9 | 10 | const datePickerView = PropTypes.oneOf(['year', 'month', 'day']); 11 | 12 | export type DateType = object | string | number | Date | null | undefined; 13 | 14 | export const DomainPropTypes = { date, datePickerView }; 15 | -------------------------------------------------------------------------------- /lib/src/DateTimePicker/components/DateTimePickerView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface DateTimePickerViewProps { 4 | selected: boolean; 5 | children: React.ReactChild; 6 | } 7 | 8 | export const DateTimePickerView: React.SFC = ({ selected, children }) => { 9 | if (!selected) { 10 | return null; 11 | } 12 | 13 | return
; 14 | }; 15 | 16 | export default DateTimePickerView; 17 | -------------------------------------------------------------------------------- /lib/src/_shared/icons/KeyboardIcon.tsx: -------------------------------------------------------------------------------- 1 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 2 | import React from 'react'; 3 | 4 | export const KeyboardIcon: React.SFC = props => { 5 | return ( 6 | 7 | 8 | 9 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | // rollup-plugin-typescript does not resolve `extends`, so tsconfig.build.json is the base and we just alter it for IDE and testing. 2 | { 3 | "extends": "../tsconfig.base.json", 4 | "compilerOptions": { 5 | "module": "commonjs", 6 | "outDir": "build", 7 | "declaration": true, 8 | "lib": ["dom", "es2016"], 9 | "jsx": "react", 10 | "skipLibCheck": true 11 | }, 12 | "include": ["src/**/*"], 13 | "exclude": ["./src/__tests__/**/*", "build"] 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/Pages/Regression/RegressionDay.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { IconButtonProps } from '@material-ui/core/IconButton'; 3 | import { IUtils } from '@date-io/core/IUtils'; 4 | 5 | export const createRegressionDay = (utils: IUtils) => ( 6 | day: any, 7 | selectedDate: any, 8 | dayInCurrentMonth: boolean, 9 | dayComponent: React.ReactElement 10 | ) => { 11 | return {dayComponent}; 12 | }; 13 | -------------------------------------------------------------------------------- /docs/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "headers": [ 5 | { 6 | "source": "/service-worker.js", 7 | "headers": [{ "key": "Cache-Control", "value": "no-cache" }] 8 | }, 9 | { 10 | "source": "/index.html", 11 | "headers": [{ "key": "Cache-Control", "value": "no-cache" }] 12 | } 13 | ], 14 | "rewrites": [ 15 | { 16 | "source": "**", 17 | "destination": "/index.html" 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/_shared/icons/DateRangeIcon.tsx: -------------------------------------------------------------------------------- 1 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 2 | import React from 'react'; 3 | 4 | export const DateRangeIcon: React.SFC = props => { 5 | return ( 6 | 7 | 8 | 9 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | 4 | # build 5 | dist 6 | build 7 | 8 | # logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | .firebase/ 15 | 16 | # coverage 17 | coverage 18 | 19 | # Optional npm cache directory 20 | .npm 21 | cypress 22 | 23 | # Optional eslint cache 24 | .eslintcache 25 | 26 | # dotenv environment variables file 27 | .env.local 28 | 29 | # webstorm 30 | .idea/ 31 | /lib/yarn.lock 32 | /docs/yarn.lock 33 | 34 | # editors 35 | .vs 36 | .vscode 37 | .DS_Store 38 | -------------------------------------------------------------------------------- /docs/src/Pages/GettingStarted/MuiPickersProvider.example.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { MuiPickersUtilsProvider } from 'material-ui-pickers'; 3 | // pick utils 4 | import MomentUtils from '@date-io/moment'; 5 | import DateFnsUtils from '@date-io/date-fns'; 6 | import LuxonUtils from '@date-io/luxon'; 7 | 8 | function App() { 9 | return ( 10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | ReactDOM.render(, document.querySelector('#app')); 17 | -------------------------------------------------------------------------------- /lib/src/_shared/icons/TimeIcon.tsx: -------------------------------------------------------------------------------- 1 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 2 | import React from 'react'; 3 | 4 | export const TimeIcon: React.SFC = props => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "allowJs": true, 5 | "skipDefaultLibCheck": true, 6 | "lib": ["es6", "dom"], 7 | "skipLibCheck": false, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "preserve" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /docs/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 5 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 13 | monospace; 14 | } 15 | 16 | *, 17 | *::before, 18 | *::after { 19 | box-sizing: border-box; 20 | } 21 | 22 | a { 23 | text-decoration: none; 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/__tests__/_shared/PickerToolbar.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import PickerToolbar, { PickerToolbarProps } from '../../_shared/PickerToolbar'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('PickerToolbar', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow(); 11 | }); 12 | 13 | it('Should renders', () => { 14 | // console.log(component.debug()); 15 | expect(component).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | // cannot use `extends` here - rollup-plugin-typescript does not resolve it 2 | { 3 | "compilerOptions": { 4 | "outDir": "build", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "lib": ["es6", "dom"], 8 | "sourceMap": false, 9 | "jsx": "react", 10 | "moduleResolution": "node", 11 | "noImplicitAny": true, 12 | "strict": true, 13 | "declaration": true, 14 | "allowSyntheticDefaultImports": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "esModuleInterop": true, 17 | "suppressImplicitAnyIndexErrors": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/__tests__/_shared/ToolbarButton.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import ToolbarButton, { ToolbarButtonProps } from '../../_shared/ToolbarButton'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('ToolbarButton', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow(); 11 | }); 12 | 13 | it('Should renders', () => { 14 | // console.log(component.debug()); 15 | expect(component).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /lib/src/__tests__/TimePicker/ClockNumber.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { ClockNumber, ClockNumberProps } from '../../TimePicker/components/ClockNumber'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('ClockNumber', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow(); 11 | }); 12 | 13 | it('Should renders', () => { 14 | // console.log(component.debug()); 15 | expect(component).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /lib/src/__tests__/TimePicker/TimePickerModal.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { TimePickerModal, TimePickerModalProps } from '../../TimePicker/TimePickerModal'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('TimePickerModal', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow(); 11 | }); 12 | 13 | it('Should renders', () => { 14 | // console.log(component.debug()); 15 | expect(component).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /lib/.size-snapshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "build/dist/material-ui-pickers.esm.js": { 3 | "bundled": 115422, 4 | "minified": 67034, 5 | "gzipped": 15647, 6 | "treeshaked": { 7 | "rollup": { 8 | "code": 52955, 9 | "import_statements": 1273 10 | }, 11 | "webpack": { 12 | "code": 60087 13 | } 14 | } 15 | }, 16 | "build/dist/material-ui-pickers.umd.js": { 17 | "bundled": 224698, 18 | "minified": 98396, 19 | "gzipped": 25684 20 | }, 21 | "build/dist/material-ui-pickers.umd.min.js": { 22 | "bundled": 203961, 23 | "minified": 92093, 24 | "gzipped": 24334 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/src/_shared/svgIcons/LightbulbIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; 3 | 4 | function LightbulbOutline(props: SvgIconProps) { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | } 11 | 12 | LightbulbOutline.muiName = 'SvgIcon'; 13 | 14 | export default LightbulbOutline; 15 | -------------------------------------------------------------------------------- /lib/src/__tests__/TimePicker/ClockPointer.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { ClockPointer, ClockPointerProps } from '../../TimePicker/components/ClockPointer'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('ClockPointer', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 12 | ); 13 | }); 14 | 15 | it('Should renders', () => { 16 | // console.log(component.debug()); 17 | expect(component).toBeTruthy(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /docs/src/Landing/Landing.css: -------------------------------------------------------------------------------- 1 | .text-light { 2 | font-weight: 200 !important; 3 | } 4 | 5 | .title { 6 | margin-top: 20px !important; 7 | } 8 | 9 | main { 10 | margin-top: 55px; 11 | } 12 | 13 | @media (min-width: 600px) { 14 | main { 15 | margin-top: 64px; 16 | } 17 | } 18 | 19 | .material-ui-logo { 20 | width: 100%; 21 | height: 40vw; 22 | max-height: 230px; 23 | } 24 | 25 | .picker { 26 | display: flex; 27 | justify-content: center; 28 | flex-direction: column; 29 | align-items: center; 30 | margin-bottom: 40px; 31 | margin: 10px 40px 40px; 32 | } 33 | 34 | @media (max-width: 600px) { 35 | .picker { 36 | flex-basis: 100%; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/src/utils/utilsService.ts: -------------------------------------------------------------------------------- 1 | import { UtilsLib } from '../App'; 2 | 3 | export const createUtilsService = (lib: UtilsLib) => ({ 4 | getFormatString(formats: { moment: string; dateFns: string; dayjs?: string; luxon?: string }) { 5 | switch (lib) { 6 | case 'date-fns': 7 | return formats.dateFns; 8 | case 'luxon': 9 | return formats.luxon || formats.dateFns; 10 | case 'moment': 11 | return formats.moment; 12 | case 'dayjs': 13 | return formats.dayjs || formats.moment; 14 | default: 15 | return formats.dateFns; 16 | } 17 | }, 18 | }); 19 | 20 | export type UtilsService = ReturnType; 21 | -------------------------------------------------------------------------------- /docs/src/utils/helpers.ts: -------------------------------------------------------------------------------- 1 | import moment, { Moment } from 'moment'; 2 | import { DateTime } from 'luxon'; 3 | import dayjs, { Dayjs } from 'dayjs'; 4 | 5 | export default function cloneCrossUtils(date: Date | Moment | DateTime | Dayjs) { 6 | if (date instanceof dayjs) { 7 | return (date as Dayjs).clone().toDate(); 8 | } 9 | 10 | if (date instanceof moment) { 11 | return (date as Moment).clone().toDate(); 12 | } 13 | 14 | if (date instanceof DateTime) { 15 | return date.toJSDate(); 16 | } 17 | 18 | if (date instanceof Date) { 19 | return new Date(date.getTime()); 20 | } 21 | 22 | throw new Error('Cannot properly parse argument passed to cloneCrossUtils'); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/DatePickerInline.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { DatePickerInline, DatePickerInlineProps } from '../../DatePicker/DatePickerInline'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('DatePicker', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 12 | ); 13 | }); 14 | 15 | it('Should renders', () => { 16 | // console.log(component.debug()); 17 | expect(component).toBeTruthy(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePickerView.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { 4 | DateTimePickerView, 5 | DateTimePickerViewProps, 6 | } from '../../DateTimePicker/components/DateTimePickerView'; 7 | import { shallow } from '../test-utils'; 8 | 9 | describe('DateTimePickerView', () => { 10 | let component: ShallowWrapper; 11 | 12 | beforeEach(() => { 13 | component = shallow(foo); 14 | }); 15 | 16 | it('Should renders', () => { 17 | // console.log(component.debug()); 18 | expect(component).toBeTruthy(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePickerModal.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { 4 | DateTimePickerModal, 5 | DateTimePickerModalProps, 6 | } from '../../DateTimePicker/DateTimePickerModal'; 7 | import { shallow } from '../test-utils'; 8 | 9 | describe('DateTimePickerModal', () => { 10 | let component: ShallowWrapper; 11 | 12 | beforeEach(() => { 13 | component = shallow(); 14 | }); 15 | 16 | it('Should renders', () => { 17 | // console.log(component.debug()); 18 | expect(component).toBeTruthy(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /lib/src/__tests__/_shared/MaskedInput.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import MaskedInput, { CustomMaskedInputProps } from '../../_shared/MaskedInput'; 4 | import { shallow } from '../test-utils'; 5 | 6 | describe('MaskedInput', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | { 14 | return; 15 | }} 16 | /> 17 | ); 18 | }); 19 | 20 | it('Should renders', () => { 21 | // console.log(component.debug()); 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/DatePicker.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { DatePicker, DatePickerProps } from '../../DatePicker/DatePicker'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('DatePicker', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 17 | ); 18 | }); 19 | 20 | it('Should renders', () => { 21 | // console.log(component.debug()); 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | require('./commands'); 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /docs/src/_shared/UtilsServiceContext.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { UtilsService, createUtilsService } from '../utils/utilsService'; 3 | import { Omit } from '@material-ui/core'; 4 | 5 | export const { Provider: UtilsServiceContextProvider, Consumer } = React.createContext< 6 | UtilsService 7 | >(createUtilsService('date-fns')); 8 | 9 | export const withUtilsService =

(Component: React.ComponentType

) => { 10 | const withUtilsService: React.SFC> = props => ( 11 | {service => } 12 | ); 13 | 14 | withUtilsService.displayName = `withUtilsService(${Component.displayName || Component.name})`; 15 | 16 | return withUtilsService; 17 | }; 18 | -------------------------------------------------------------------------------- /lib/src/__tests__/MuiPickersUtilsProvider.test.tsx: -------------------------------------------------------------------------------- 1 | import DateFnsUtils from '@date-io/date-fns'; 2 | import { shallow, ShallowWrapper } from 'enzyme'; // required to use just shallow here because utils prop override 3 | import * as React from 'react'; 4 | import MuiPickersUtilsProvider, { MuiPickersUtilsProviderProps } from '../MuiPickersUtilsProvider'; 5 | 6 | describe('MuiPickersUtilsProvider', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 12 |

13 | 14 | ); 15 | }); 16 | 17 | it('Should render context provider', () => { 18 | expect(component).toBeTruthy(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/YearSelection.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { YearSelection, YearSelectionProps } from '../../DatePicker/components/YearSelection'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('YearSelection', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 17 | ); 18 | }); 19 | 20 | it('Should renders', () => { 21 | // console.log(component.debug()); 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePicker.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { DateTimePicker, DateTimePickerProps } from '../../DateTimePicker/DateTimePicker'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('DateTimePicker', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 17 | ); 18 | }); 19 | 20 | it('Should renders', () => { 21 | // console.log(component.debug()); 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /lib/src/__tests__/TimePicker/TimePicker.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { TimePicker, TimePickerProps } from '../../TimePicker/TimePicker'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('TimePicker', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 18 | ); 19 | }); 20 | 21 | it('Should renders', () => { 22 | // console.log(component.debug()); 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /lib/src/__tests__/setup.js: -------------------------------------------------------------------------------- 1 | const Enzyme = require('enzyme'); 2 | const EnzymeAdapter = require('enzyme-adapter-react-16'); 3 | 4 | // Setup enzyme's react adapter 5 | Enzyme.configure({ adapter: new EnzymeAdapter() }); 6 | 7 | // Convert any console error into a thrown error 8 | const error = console.error; 9 | console.error = (...args) => { 10 | error.apply(console, args); 11 | if (args[0] instanceof Error) { 12 | throw args[0]; 13 | } else { 14 | // combine multi args into a string 15 | const message = args 16 | .map(value => { 17 | if (typeof value === 'object') { 18 | return JSON.stringify(value); 19 | } else { 20 | return value; 21 | } 22 | }) 23 | .join(' '); 24 | throw new Error(message); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/DatePickerModal.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { DatePickerModal, DatePickerModalProps } from '../../DatePicker/DatePickerModal'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | const spy = jest.fn(); 7 | 8 | const props = { 9 | keyboard: true, 10 | format: 'YYYY', 11 | onChange: spy, 12 | value: utilsToUse.date('2018'), 13 | }; 14 | 15 | describe('DatePickerModal', () => { 16 | let component: ShallowWrapper; 17 | 18 | beforeEach(() => { 19 | component = shallow(); 20 | }); 21 | 22 | it('Should renders', () => { 23 | // console.log(component.debug()); 24 | expect(component).toBeTruthy(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/ControllingProgrammatically.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SourcablePanel from '_shared/SourcablePanel'; 3 | import { Typography } from '@material-ui/core'; 4 | 5 | const ControllingProgrammatically = () => ( 6 |
7 | 8 | Control programmatically 9 | 10 | 11 | 12 | Any picker can be controlled by ref 13 | property which add an ability open any picker from the code. See an example below 14 | 15 | 16 | 20 |
21 | ); 22 | 23 | export default ControllingProgrammatically; 24 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePickerInline.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { DateTimePickerInlineProps, InlineDateTimePicker } from '../../DateTimePicker'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | const spy = jest.fn(); 7 | 8 | const props = { 9 | keyboard: true, 10 | format: 'YYYY', 11 | onChange: spy, 12 | value: utilsToUse.date('2018'), 13 | }; 14 | 15 | describe('DatePickerModal', () => { 16 | let component: ShallowWrapper; 17 | 18 | beforeEach(() => { 19 | component = shallow(); 20 | }); 21 | 22 | it('Should renders', () => { 23 | // console.log(component.debug()); 24 | expect(component).toBeTruthy(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature request 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | ![A GIF or MEME to give some spice of the internet](url) 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/CalendarHeader.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { CalendarHeader, CalendarHeaderProps } from '../../DatePicker/components/CalendarHeader'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('CalendarHeader', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 19 | ); 20 | }); 21 | 22 | it('Should renders', () => { 23 | // console.log(component.debug()); 24 | expect(component).toBeTruthy(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/TimePicker/KeyboardTimePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import { TimePicker } from 'material-ui-pickers'; 3 | 4 | export default class BasicUsage extends PureComponent { 5 | state = { 6 | selectedDate: new Date(), 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 |
18 | 27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: cypress/base:8 6 | environment: 7 | ## this enables colors in the output 8 | TERM: xterm 9 | working_directory: ~/app 10 | 11 | steps: 12 | - checkout 13 | - restore_cache: 14 | keys: 15 | - v1-deps-{{ .Branch }}-{{ checksum "package.json" }} 16 | - v1-deps-{{ .Branch }} 17 | - v1-deps 18 | - run: 19 | name: Install Dependencies 20 | command: npm ci && npx lerna bootstrap 21 | - save_cache: 22 | key: v1-deps-{{ .Branch }}-{{ checksum "package.json" }} 23 | paths: 24 | - ~/.npm 25 | - ~/.cache 26 | - run: npx lerna run build 27 | - run: npx lerna run serve & npx wait-on http://localhost:3002 && npm run e2e:run -- --record 28 | -------------------------------------------------------------------------------- /docs/scripts/generate-backers.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production'; 2 | require('react-scripts/config/env'); 3 | 4 | const fse = require('fs-extra'); 5 | const path = require('path'); 6 | const patreonApi = require('patreon').patreon; 7 | 8 | const patreonAPIClient = patreonApi(process.env.CREATOR_TOKEN); 9 | 10 | patreonAPIClient('/campaigns/1559688/pledges') 11 | .then(({ rawJson }) => 12 | rawJson.data 13 | // sort by pledge amount 14 | .sort((a, b) => a.attributes.amount_cents - b.attributes.amount_cents) 15 | .reverse() 16 | .map(({ relationships }) => { 17 | const patronId = relationships.patron.data.id; 18 | const user = rawJson.included.find(entity => entity.id === patronId); 19 | 20 | return user.attributes; 21 | }) 22 | ) 23 | .then(users => 24 | fse.writeFile( 25 | path.resolve(__dirname, '..', 'src', 'patrons.json'), 26 | JSON.stringify(users) 27 | ) 28 | ); 29 | -------------------------------------------------------------------------------- /docs/src/_shared/svgIcons/GithubIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SvgIcon from '@material-ui/core/SvgIcon'; 3 | 4 | const GitHub = props => ( 5 | 6 | 7 | 8 | ); 9 | 10 | export default GitHub; 11 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePickerTabs.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { 4 | DateTimePickerTabs, 5 | DateTimePickerTabsProps, 6 | } from '../../DateTimePicker/components/DateTimePickerTabs'; 7 | import { DateTimePicker } from '../../DateTimePicker/DateTimePicker'; 8 | import { shallow } from '../test-utils'; 9 | 10 | describe('DateTimePickerTabs', () => { 11 | let component: ShallowWrapper; 12 | 13 | beforeEach(() => { 14 | component = shallow( 15 | 23 | ); 24 | }); 25 | 26 | it('Should renders', () => { 27 | // console.log(component.debug()); 28 | expect(component).toBeTruthy(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /docs/src/Pages/Localization/Date-fns/DateFnsLocalization.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SourcablePanel from '../../../_shared/SourcablePanel'; 3 | import { Typography } from '@material-ui/core'; 4 | 5 | const DateFnsLocalization = () => ( 6 |
7 | 8 | Localization date-fns 9 | 10 | 11 | 12 | Date-fns localization simply performs by passing date-fns locale object to the 13 | MuiPickerUtilsProvider 14 | 15 | 16 | 21 | Note that pickers would be rerender automatically on locale change 22 | 23 | } 24 | /> 25 |
26 | ); 27 | 28 | export default DateFnsLocalization; 29 | -------------------------------------------------------------------------------- /lib/src/__tests__/DateTimePicker/DateTimePickerHeader.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { 4 | DateTimePickerHeader, 5 | DateTimePickerHeaderProps, 6 | } from '../../DateTimePicker/components/DateTimePickerHeader'; 7 | import { shallow, utilsToUse } from '../test-utils'; 8 | 9 | describe('DateTimePickerHeader', () => { 10 | let component: ShallowWrapper; 11 | 12 | beforeEach(() => { 13 | component = shallow( 14 | jest.fn()} 16 | date={utilsToUse.date('01-01-2017')} 17 | classes={{} as any} 18 | meridiemMode="am" 19 | openView="year" 20 | onOpenViewChange={jest.fn()} 21 | utils={utilsToUse} 22 | /> 23 | ); 24 | }); 25 | 26 | it('Should renders', () => { 27 | // console.log(component.debug()); 28 | expect(component).toBeTruthy(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /docs/scripts/docgen.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const parser = require('react-docgen-typescript').withDefaultConfig({ 4 | skipPropsWithoutDoc: true, 5 | }); 6 | 7 | const doc = {}; 8 | const srcPath = path.resolve(__dirname, '..', '..', 'lib', 'src'); 9 | const files = [ 10 | 'DatePicker/DatePickerModal.tsx', 11 | 'TimePicker/TimePickerModal.tsx', 12 | 'DateTimePicker/DateTimePickerModal.tsx', 13 | ]; 14 | 15 | files.forEach(filePart => { 16 | const file = path.join(srcPath, filePart); 17 | const parsedDoc = parser.parse(file)[0]; 18 | 19 | doc[filePart] = Object.entries(parsedDoc.props) 20 | .filter( 21 | ([key, value]) => 22 | value.description && !value.parent.fileName.includes('@types') 23 | ) 24 | .reduce((obj, [key, value]) => { 25 | obj[key] = value; 26 | return obj; 27 | }, {}); 28 | }); 29 | 30 | fs.writeFileSync( 31 | path.resolve(__dirname, '..', 'src', 'prop-types.json'), 32 | JSON.stringify(doc) 33 | ); 34 | -------------------------------------------------------------------------------- /docs/src/Pages/GettingStarted/QuickStart.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import DateFnsUtils from '@date-io/date-fns'; 3 | import { MuiPickersUtilsProvider } from 'material-ui-pickers'; 4 | import { TimePicker } from 'material-ui-pickers'; 5 | import { DatePicker } from 'material-ui-pickers'; 6 | import { DateTimePicker } from 'material-ui-pickers'; 7 | 8 | export default class App extends PureComponent { 9 | state = { 10 | selectedDate: new Date(), 11 | }; 12 | 13 | handleDateChange = date => { 14 | this.setState({ selectedDate: date }); 15 | }; 16 | 17 | render() { 18 | const { selectedDate } = this.state; 19 | 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/src/index.tsx: -------------------------------------------------------------------------------- 1 | import rtl from 'jss-rtl'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import App from './App'; 6 | import { BrowserRouter } from 'react-router-dom'; 7 | import { create } from 'jss'; 8 | import { createGenerateClassName, jssPreset } from '@material-ui/core/styles'; 9 | import JssProvider from 'react-jss/lib/JssProvider'; 10 | 11 | import * as serviceWorker from './serviceWorker'; 12 | import './index.css'; 13 | 14 | // @ts-ignore 15 | window.__MUI_USE_NEXT_TYPOGRAPHY_VARIANTS__ = true; 16 | 17 | // @ts-ignore Configure JSS 18 | const jss = create({ plugins: [...jssPreset().plugins, rtl()] }); 19 | 20 | // Custom Material-UI class name generator. 21 | const generateClassName = createGenerateClassName(); 22 | 23 | ReactDOM.render( 24 | 25 | 26 | 27 | 28 | , 29 | document.getElementById('root') 30 | ); 31 | 32 | // do not cache the docs 33 | serviceWorker.unregister(); 34 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/TimePicker/InlineTimePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { InlineTimePicker } from 'material-ui-pickers'; 3 | 4 | export default class InlineTimePickerDemo extends PureComponent { 5 | state = { 6 | selectedDate: '2018-01-01T00:00:00.000Z', 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 20 |
21 | 22 |
23 | 30 |
31 |
32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/Formik.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SourcablePanel from '_shared/SourcablePanel'; 3 | import { Typography } from '@material-ui/core'; 4 | 5 | const Formik = () => ( 6 |
7 | 8 | Integration to form 9 | 10 | 11 | 12 | Pickers are quite complex controls, where date can be submitted 13 | from different places, so we can't provide event as argument in 14 | onChange callback. Also we are providing date validation out of 15 | the box, so it may be tricky to integrate pickers to the form. 16 | Here are some examples! 17 | 18 | 19 | 24 | Here is example of how to use material-ui-pickers with formik 25 | 26 | } 27 | /> 28 |
29 | ); 30 | 31 | export default Formik; 32 | -------------------------------------------------------------------------------- /lib/remove-prop-types.js: -------------------------------------------------------------------------------- 1 | const removePropTypes = api => { 2 | const { types, template } = api; 3 | const visitedKey = `remove-prop-types-${Date.now()}`; 4 | return { 5 | visitor: { 6 | AssignmentExpression(path) { 7 | if ( 8 | types.isMemberExpression(path.node.left) && 9 | types.isIdentifier(path.node.left.property) && 10 | path.node.left.property.name === 'propTypes' 11 | ) { 12 | // Prevent infinity loop. 13 | if (path.node[visitedKey]) { 14 | return; 15 | } 16 | path.node[visitedKey] = true; 17 | 18 | const unsafeWrapTemplate = template( 19 | ` 20 | if (process.env.NODE_ENV !== "production") { 21 | NODE; 22 | } 23 | `, 24 | { placeholderPattern: /^NODE$/ } 25 | ); 26 | path.replaceWith( 27 | unsafeWrapTemplate({ 28 | NODE: path.node, 29 | }) 30 | ); 31 | } 32 | }, 33 | }, 34 | }; 35 | }; 36 | 37 | module.exports = removePropTypes; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dmitriy Kovalenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/Month.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { Month, MonthProps } from '../../DatePicker/components/Month'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('Month', () => { 7 | let component: ShallowWrapper; 8 | 9 | beforeEach(() => { 10 | component = shallow( 11 | 12 | Oct 13 | 14 | ); 15 | }); 16 | 17 | it('Should render', () => { 18 | expect(component).toBeTruthy(); 19 | }); 20 | }); 21 | 22 | describe('Month - disabled state', () => { 23 | let component: ShallowWrapper; 24 | 25 | beforeEach(() => { 26 | component = shallow( 27 | 33 | Oct 34 | 35 | ); 36 | }); 37 | 38 | it('Should render in disabled state', () => { 39 | expect(component.prop('tabIndex')).toBe(-1); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/TimePicker/SecondsTimePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { TimePicker } from 'material-ui-pickers'; 3 | 4 | export default class BasicUsage extends PureComponent { 5 | state = { 6 | selectedDate: new Date(), 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 26 |
27 | 28 |
29 | 37 |
38 |
39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/_shared/MaskedInput.tsx: -------------------------------------------------------------------------------- 1 | import * as PropTypes from 'prop-types'; 2 | import * as React from 'react'; 3 | import MaskedInput, { MaskedInputProps } from 'react-text-mask'; 4 | 5 | export interface CustomMaskedInputProps extends MaskedInputProps { 6 | mask?: MaskedInputProps['mask']; 7 | inputRef: React.Ref; 8 | } 9 | 10 | export default class Input extends React.PureComponent { 11 | public static propTypes: any = { 12 | mask: PropTypes.any, 13 | inputRef: PropTypes.func.isRequired, 14 | }; 15 | 16 | public createInputRef = (ref: MaskedInput | null) => { 17 | const { inputRef } = this.props; 18 | 19 | if (inputRef && typeof inputRef === 'function') { 20 | // @ts-ignore inputElement exists in Masked input. Issue in typings 21 | inputRef(ref ? ref.inputElement : null); 22 | } 23 | }; 24 | 25 | public render() { 26 | const { inputRef, keepCharPositions, ...rest } = this.props; 27 | 28 | return this.props.mask ? ( 29 | 30 | ) : ( 31 | 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/src/Pages/Localization/Moment/MomentLocalization.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SourcablePanel from '_shared/SourcablePanel'; 3 | import { Typography } from '@material-ui/core'; 4 | 5 | const MomentLocalization = () => ( 6 |
7 | 8 | Localization moment 9 | 10 | 11 | Moment localization relying on the global moment object used. 12 | 13 | 14 | It is possible to pass configured global moment with selected locale, default timezone, etc. 15 | Also pass selected locale as string to the provider to make pickers rerenders automatically on 16 | locale change. 17 | 18 | 23 | Note that pickers would be rerender automatically on locale change 24 | 25 | } 26 | /> 27 |
28 | ); 29 | 30 | export default MomentLocalization; 31 | -------------------------------------------------------------------------------- /lib/src/__tests__/DatePicker/MonthSelection.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import Month from '../../DatePicker/components/Month'; 4 | import { MonthSelection, MonthSelectionProps } from '../../DatePicker/components/MonthSelection'; 5 | import { shallow, utilsToUse } from '../test-utils'; 6 | 7 | describe('MonthSelection', () => { 8 | let component: ShallowWrapper; 9 | 10 | beforeEach(() => { 11 | component = shallow( 12 | 20 | ); 21 | }); 22 | 23 | it('Should render disabled months before min date and after max date', () => { 24 | expect(component.find(Month).map(month => month.prop('disabled'))).toEqual([ 25 | true, 26 | true, 27 | false, 28 | false, 29 | false, 30 | true, 31 | true, 32 | true, 33 | true, 34 | true, 35 | true, 36 | true, 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | 13 | ![A GIF or MEME to give some spice of the internet](url) 14 | 15 | ## Environment 16 | 17 | | Tech | Version | 18 | |---------------------|---------| 19 | | material-ui-pickers | | 20 | | material-ui | | 21 | | React | | 22 | | Browser | | 23 | | Peer library | | 24 | 25 | ## Steps to reproduce 26 | 1. 27 | 2. 28 | 3. 29 | 30 | ## Expected behavior 31 | 32 | 33 | ## Actual behavior 34 | 35 | 36 | ## Live example 37 | 43 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/StaticPickers.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Typography } from '@material-ui/core'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | 5 | const StaticPickers = () => ( 6 |
7 | 8 | Static pickers 9 | 10 | 11 | 12 | Somewhere its required to use some internal control for calendar or some timeinput. Here you 13 | are! You can use directly any sub-control of the pickers. Please note - if you want to use 14 | internal controls ALL your imports must be from the relative paths 15 | 16 | 17 | 18 | Also you can use our own HOC that is using for any picker which provide managing temporary 19 | chosen date and submitting state logic. 20 | 21 | 22 | 27 | Please make sure that your imports are consistent 28 | 29 | } 30 | /> 31 |
32 | ); 33 | 34 | export default StaticPickers; 35 | -------------------------------------------------------------------------------- /docs/src/Landing/components/PatreonSponsors.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import { withStyles, Avatar, List, ListItem, ListItemText } from '@material-ui/core'; 5 | import patrons from '../../patrons.json'; 6 | 7 | class PatreonSponsors extends Component { 8 | static propTypes = { 9 | classes: PropTypes.object.isRequired, 10 | }; 11 | 12 | render() { 13 | const { classes } = this.props; 14 | 15 | if (patrons.length === 0) { 16 | return 'There is no sponsors yet 😢'; 17 | } 18 | 19 | return ( 20 | 21 | {patrons.map(patron => ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | ))} 29 | 30 | ); 31 | } 32 | } 33 | 34 | const styles = { 35 | spinner: { 36 | margin: '0 auto', 37 | }, 38 | patronList: { 39 | maxWidth: 400, 40 | margin: '0 auto', 41 | }, 42 | }; 43 | 44 | export default withStyles(styles)(PatreonSponsors); 45 | -------------------------------------------------------------------------------- /lib/src/_shared/WithUtils.tsx: -------------------------------------------------------------------------------- 1 | import { IUtils } from '@date-io/core/IUtils'; 2 | import { Omit } from '@material-ui/core'; 3 | import * as React from 'react'; 4 | import { MuiPickersContext } from '../MuiPickersUtilsProvider'; 5 | import { MaterialUiPickersDate } from '../typings/date'; 6 | 7 | export interface WithUtilsProps { 8 | utils: IUtils; 9 | } 10 | 11 | const checkUtils = (utils: IUtils | null | undefined) => { 12 | if (!utils) { 13 | // tslint:disable-next-line 14 | throw new Error( 15 | 'Can not find utils in context. You either a) forgot to wrap your component tree in MuiPickersUtilsProvider; or b) mixed named and direct file imports. Recommendation: use named imports from the module index.' 16 | ); 17 | } 18 | }; 19 | 20 | export const withUtils = () =>

(Component: React.ComponentType

) => { 21 | const WithUtils: React.SFC> = props => ( 22 | 23 | {utils => { 24 | checkUtils(utils); 25 | return ; 26 | }} 27 | 28 | ); 29 | 30 | WithUtils.displayName = `WithUtils(${Component.displayName || Component.name})`; 31 | 32 | return WithUtils; 33 | }; 34 | -------------------------------------------------------------------------------- /lib/src/DatePicker/components/DayWrapper.tsx: -------------------------------------------------------------------------------- 1 | import * as PropTypes from 'prop-types'; 2 | import * as React from 'react'; 3 | 4 | export interface DayWrapperProps { 5 | children: React.ReactNode; 6 | dayInCurrentMonth?: boolean; 7 | disabled?: boolean; 8 | onSelect: (value: any) => void; 9 | value: any; 10 | } 11 | 12 | class DayWrapper extends React.PureComponent { 13 | public static propTypes: any = { 14 | children: PropTypes.node.isRequired, 15 | dayInCurrentMonth: PropTypes.bool, 16 | disabled: PropTypes.bool, 17 | onSelect: PropTypes.func.isRequired, 18 | value: PropTypes.any.isRequired, 19 | }; 20 | 21 | public static defaultProps = { 22 | dayInCurrentMonth: true, 23 | disabled: false, 24 | }; 25 | 26 | public handleClick = () => { 27 | this.props.onSelect(this.props.value); 28 | }; 29 | 30 | public render() { 31 | const { children, value, dayInCurrentMonth, disabled, onSelect, ...other } = this.props; 32 | 33 | return ( 34 |

40 | {children} 41 |
42 | ); 43 | } 44 | } 45 | 46 | export default DayWrapper; 47 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/FormatsCustomization.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import format from 'date-fns/format'; 3 | import frLocale from 'date-fns/locale/fr'; 4 | import { DatePicker } from 'material-ui-pickers'; 5 | import DateFnsUtils from '@date-io/date-fns'; 6 | import { MuiPickersUtilsProvider } from 'material-ui-pickers'; 7 | 8 | class LocalizedUtils extends DateFnsUtils { 9 | getDatePickerHeaderText(date) { 10 | return format(date, 'd MMM yyyy', { locale: this.locale }); 11 | } 12 | } 13 | 14 | export default class DateFnsLocalizationExample extends PureComponent { 15 | state = { 16 | selectedDate: new Date(), 17 | }; 18 | 19 | handleDateChange = date => { 20 | this.setState({ selectedDate: date }); 21 | }; 22 | 23 | render() { 24 | const { selectedDate } = this.state; 25 | 26 | return ( 27 | 28 |
29 | 38 |
39 |
40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/TimePicker/TimePickerBasic.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { TimePicker } from 'material-ui-pickers'; 3 | 4 | export default class BasicUsage extends PureComponent { 5 | state = { 6 | selectedDate: new Date(), 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 25 |
26 | 27 |
28 | 35 |
36 | 37 |
38 | 46 |
47 |
48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DateTimePicker/BasicDateTimePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { DateTimePicker } from 'material-ui-pickers'; 3 | 4 | export default class BasicDateTimePicker extends PureComponent { 5 | state = { 6 | selectedDate: new Date(), 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 24 |
25 | 26 |
27 | 35 |
36 | 37 |
38 | 45 |
46 |
47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/MuiPickersUtilsProvider.tsx: -------------------------------------------------------------------------------- 1 | import { IUtils } from '@date-io/core/IUtils'; 2 | import * as PropTypes from 'prop-types'; 3 | import * as React from 'react'; 4 | import { MaterialUiPickersDate } from './typings/date'; 5 | 6 | export const MuiPickersContext = React.createContext | null>(null); 7 | // TODO remove in v3.0 8 | export const MuiPickersContextConsumer = MuiPickersContext.Consumer; 9 | 10 | export interface MuiPickersUtilsProviderProps { 11 | utils: any; 12 | children: React.ReactNode; 13 | locale?: any; 14 | moment?: any; 15 | } 16 | 17 | export default class MuiPickersUtilsProvider extends React.Component { 18 | public static propTypes: any = { 19 | utils: PropTypes.func.isRequired, 20 | locale: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), 21 | children: PropTypes.oneOfType([ 22 | PropTypes.element.isRequired, 23 | PropTypes.arrayOf(PropTypes.element.isRequired), 24 | ]).isRequired, 25 | moment: PropTypes.func, 26 | }; 27 | 28 | public static getDerivedStateFromProps({ 29 | utils: Utils, 30 | locale, 31 | moment, 32 | }: MuiPickersUtilsProviderProps) { 33 | return { 34 | utils: new Utils({ locale, moment }), 35 | }; 36 | } 37 | 38 | public state = { 39 | utils: null, 40 | }; 41 | 42 | public render() { 43 | return ; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/__tests__/TimePicker/TimePickerView.test.tsx: -------------------------------------------------------------------------------- 1 | import { ShallowWrapper } from 'enzyme'; 2 | import * as React from 'react'; 3 | import { TimePickerView, TimePickerViewProps } from '../../TimePicker/components/TimePickerView'; 4 | import { shallow, utilsToUse } from '../test-utils'; 5 | 6 | describe('TimePickerView', () => { 7 | let component: ShallowWrapper; 8 | let onChangeMock: any; 9 | 10 | beforeEach(() => { 11 | onChangeMock = jest.fn(); 12 | component = shallow( 13 | 22 | ); 23 | }); 24 | 25 | it('Should renders', () => { 26 | expect(component).toBeTruthy(); 27 | }); 28 | 29 | if (process.env.UTILS !== 'moment') { 30 | it('Should dispatch onChange onSecondsChange', () => { 31 | (component.instance() as TimePickerView).handleSecondsChange(45, true); 32 | expect(onChangeMock).toHaveBeenCalledWith(utilsToUse.date('01-01-2017 12:00:45'), true); 33 | }); 34 | 35 | it('Should dispatch onChange on', () => { 36 | (component.instance() as TimePickerView).handleMinutesChange(45, true); 37 | expect(onChangeMock).toHaveBeenCalledWith(utilsToUse.date('01-01-2017 12:45'), true); 38 | }); 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DateTimePicker/DateTimePickerDemo.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypesTable from '_shared/PropTypesTable'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | 6 | const DateTimePickerDemo = () => ( 7 |
8 | 9 | Date & time picker 10 | 11 | 12 | This component is not from material design guidelines. 13 | 14 | 15 | Its a combination of date & time picker and allows that uses the modal to select both date and 16 | time with one control. 17 | 18 | 19 | 23 | 24 | 28 | 29 | 34 | Applied mostly all customization, that available for date & time pickers 35 | 36 | } 37 | /> 38 | 39 | 40 |
41 | ); 42 | 43 | export default DateTimePickerDemo; 44 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/StaticPickers.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import Paper from '@material-ui/core/Paper'; 3 | 4 | import DateFnsUtils from '@date-io/date-fns'; 5 | import { BasePicker, MuiPickersUtilsProvider, TimePickerView, Calendar } from 'material-ui-pickers'; 6 | 7 | class StaticPickers extends PureComponent { 8 | state = { 9 | selectedDate: new Date(), 10 | }; 11 | 12 | handleDateChange = date => { 13 | this.setState({ selectedDate: date }); 14 | }; 15 | 16 | render() { 17 | const { selectedDate } = this.state; 18 | 19 | return ( 20 | 21 | 22 | {({ 23 | date, 24 | handleAccept, 25 | handleChange, 26 | handleClear, 27 | handleDismiss, 28 | handleSetTodayDate, 29 | handleTextFieldChange, 30 | pick12hOr24hFormat, 31 | }) => ( 32 |
33 |
34 | 35 | 36 | 37 |
38 | 39 | 40 |
41 | )} 42 |
43 |
44 | ); 45 | } 46 | } 47 | 48 | export default StaticPickers; 49 | -------------------------------------------------------------------------------- /lib/src/index.ts: -------------------------------------------------------------------------------- 1 | import { DatePickerInlineProps, DatePickerProps } from './DatePicker'; 2 | import { DateTimePickerInlineProps, DateTimePickerProps } from './DateTimePicker'; 3 | import { TimePickerInlineProps, TimePickerProps } from './TimePicker'; 4 | import { MaterialUiPickersDate } from './typings/date'; 5 | 6 | export type TimePickerProps = TimePickerProps; 7 | 8 | export type TimePickerInlineProps = TimePickerInlineProps; 9 | 10 | export type DatePickerProps = DatePickerProps; 11 | 12 | export type DatePickerInlineProps = DatePickerInlineProps; 13 | 14 | export type DateTimePickerProps = DateTimePickerProps; 15 | 16 | export type DateTimePickerInlineProps = DateTimePickerInlineProps; 17 | 18 | export type MaterialUiPickersDate = MaterialUiPickersDate; 19 | 20 | export { default as DatePicker, InlineDatePicker } from './DatePicker'; 21 | 22 | export { default as TimePicker, InlineTimePicker } from './TimePicker'; 23 | 24 | export { default as DateTimePicker, InlineDateTimePicker } from './DateTimePicker'; 25 | 26 | export { default as BasePicker } from './_shared/BasePicker'; 27 | 28 | export { default as Calendar } from './DatePicker/components/Calendar'; 29 | 30 | export { default as Day } from './DatePicker/components/Day'; 31 | 32 | export { default as TimePickerView } from './TimePicker/components/TimePickerView'; 33 | 34 | export { default as Clock } from './TimePicker/components/Clock'; 35 | 36 | export { 37 | default as MuiPickersUtilsProvider, 38 | MuiPickersContext, 39 | MuiPickersContextConsumer, 40 | } from './MuiPickersUtilsProvider'; 41 | -------------------------------------------------------------------------------- /lib/src/_shared/ToolbarButton.tsx: -------------------------------------------------------------------------------- 1 | import { Theme } from '@material-ui/core'; 2 | import withStyles, { WithStyles } from '@material-ui/core/styles/withStyles'; 3 | import Typography, { TypographyProps } from '@material-ui/core/Typography'; 4 | import clsx from 'clsx'; 5 | import * as PropTypes from 'prop-types'; 6 | import * as React from 'react'; 7 | import { ExtendMui } from '../typings/extendMui'; 8 | 9 | export interface ToolbarButtonProps extends ExtendMui, WithStyles { 10 | selected: boolean; 11 | label: string; 12 | } 13 | 14 | const ToolbarButton: React.SFC = ({ 15 | classes, 16 | selected, 17 | label, 18 | className = null, 19 | ...other 20 | }) => ( 21 | 27 | {label} 28 | 29 | ); 30 | 31 | (ToolbarButton as any).propTypes = { 32 | selected: PropTypes.bool.isRequired, 33 | label: PropTypes.string.isRequired, 34 | classes: PropTypes.any.isRequired, 35 | className: PropTypes.string, 36 | innerRef: PropTypes.any, 37 | }; 38 | 39 | ToolbarButton.defaultProps = { 40 | className: '', 41 | }; 42 | 43 | export const styles = (theme: Theme) => ({ 44 | toolbarBtn: { 45 | cursor: 'pointer', 46 | color: 'rgba(255, 255, 255, 0.54)', 47 | }, 48 | toolbarBtnSelected: { 49 | color: theme.palette.common.white, 50 | }, 51 | }); 52 | 53 | export default withStyles(styles, { name: 'MuiPickersToolbarButton' })(ToolbarButton); 54 | -------------------------------------------------------------------------------- /docs/src/Pages/GettingStarted/ParsingDates.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Typography } from '@material-ui/core'; 3 | 4 | const ParsingDates = () => ( 5 |
6 | 7 | Parsing dates 8 | 9 | 10 | 11 | Material-UI pickers rely on the date management library when the date should be parsed. For 12 | any prop-types, that accept actually the date (e.g. 13 | minDate , maxDate ) 14 | accept string, number, Date object and so on. 15 | 16 | 17 | 18 | Find more information about parsing dates in docs for your library: 19 | 20 | 21 | 34 | 35 | 36 | Pass any value to the picker, and if it won`t be parsed as expected feel free to open issue on 37 | our github 😎 38 | 39 |
40 | ); 41 | 42 | export default ParsingDates; 43 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DatePicker/BasicDatePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { DatePicker } from 'material-ui-pickers'; 3 | 4 | export default class BasicDatePicker extends PureComponent { 5 | state = { 6 | selectedDate: new Date(), 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 25 |
26 | 27 |
28 | 36 |
37 | 38 |
39 | 51 |
52 |
53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/src/Pages/Localization/Persian/PersianCalendar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Code from '_shared/Code'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | 6 | const PersianCalendar = () => ( 7 |
8 | 9 | Persian Calendar System 10 | 11 | 12 | 13 | Make sure you have read the{' '} 14 | right to left section of the 15 | material-ui documentation page before proceeding. 16 | 17 | 18 | 19 | You will also need to install the 20 | @date-io/jalaali 21 | package from npm. 22 | 23 | 24 | 25 | 26 | 31 | 32 | You can use the examples below. It is recommended that you change the font. 33 | 34 | 35 | 36 | Also, to make sure the example is fully functional, don't forget to change the 37 | direction of the page to Right to Left from the top right corner. 38 | 39 |
40 | } 41 | /> 42 |
43 | ); 44 | 45 | export default PersianCalendar; 46 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DatePicker/YearMonthPicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { DatePicker } from 'material-ui-pickers'; 3 | 4 | export default class YearMonthPicker extends PureComponent { 5 | state = { 6 | selectedDate: '2018-04-01T00:00:00.000Z', 7 | }; 8 | 9 | handleDateChange = date => { 10 | this.setState({ selectedDate: date }); 11 | }; 12 | 13 | render() { 14 | const { selectedDate } = this.state; 15 | 16 | return ( 17 | 18 |
19 | 26 |
27 | 28 |
29 | 38 |
39 | 40 |
41 | 49 |
50 |
51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/Formik.example.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DatePicker } from 'material-ui-pickers'; 3 | import { Formik, Form, Field } from 'formik'; 4 | import Code from '_shared/Code'; 5 | import Grid from '@material-ui/core/Grid'; 6 | 7 | const DatePickerField = ({ field, form, ...other }) => { 8 | const currentError = form.errors[field.name]; 9 | return ( 10 | form.setFieldError(field.name, error)} 20 | onChange={date => form.setFieldValue(field.name, date, true)} 21 | mask={value => (value ? [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/] : [])} 22 | {...other} 23 | /> 24 | ); 25 | }; 26 | 27 | const FormikExample = () => { 28 | return ( 29 | 30 | {({ values, errors }) => ( 31 |
32 | 33 | 34 |
35 | 36 |
37 |
38 | 39 | 40 | 41 | 42 |
43 | 44 | )} 45 |
46 | ); 47 | }; 48 | 49 | export default FormikExample; 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-ui-pickers", 3 | "version": "2.0.0", 4 | "description": "Material-ui pickers root package", 5 | "main": "index.js", 6 | "directories": { 7 | "doc": "docs", 8 | "lib": "lib" 9 | }, 10 | "scripts": { 11 | "start": "lerna run start --parallel", 12 | "bump:patch": "lerna exec -- npm version patch", 13 | "bump:minor": "lerna exec -- npm version minor", 14 | "release": "lerna run release --scope --parallel material-ui-pickers && lerna run deploy --scope --parallel docs", 15 | "release:patch": "npm run bump:patch && npm run release", 16 | "release:minor": "npm run bump:minor && npm run release", 17 | "postinstall": "lerna bootstrap", 18 | "e2e:open": "cypress open", 19 | "e2e:run": "cypress run" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/dmtrKovalenko/material-ui-pickers.git" 24 | }, 25 | "keywords": [], 26 | "author": "", 27 | "license": "ISC", 28 | "bugs": { 29 | "url": "https://github.com/dmtrKovalenko/material-ui-pickers/issues" 30 | }, 31 | "homepage": "https://github.com/dmtrKovalenko/material-ui-pickers#readme", 32 | "devDependencies": { 33 | "husky": "^1.1.2", 34 | "lerna": "^3.4.3", 35 | "lint-staged": "^7.3.0", 36 | "prettier": "^1.14.3" 37 | }, 38 | "husky": { 39 | "hooks": { 40 | "pre-commit": "lint-staged" 41 | } 42 | }, 43 | "lint-staged": { 44 | "*.{js,jsx,ts,tsx,json,css,md}": [ 45 | "prettier --write", 46 | "git add" 47 | ] 48 | }, 49 | "dependencies": { 50 | "cypress": "^3.1.4", 51 | "wait-on": "^3.2.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/_helpers/text-field-helper.ts: -------------------------------------------------------------------------------- 1 | import { DateTextFieldProps } from '../_shared/DateTextField'; 2 | import { MaterialUiPickersDate } from '../typings/date'; 3 | 4 | export const getDisplayDate = ({ 5 | utils, 6 | value, 7 | format, 8 | invalidLabel, 9 | emptyLabel, 10 | labelFunc, 11 | }: DateTextFieldProps) => { 12 | const isEmpty = value === null; 13 | const date = utils.date(value); 14 | 15 | if (labelFunc) { 16 | return labelFunc(isEmpty ? null : date, invalidLabel!); 17 | } 18 | 19 | if (isEmpty) { 20 | return emptyLabel; 21 | } 22 | 23 | return utils.isValid(date) ? utils.format(date, format) : invalidLabel; 24 | }; 25 | 26 | export const getError = ( 27 | value: MaterialUiPickersDate, 28 | props: DateTextFieldProps 29 | ): React.ReactNode => { 30 | const { 31 | utils, 32 | maxDate, 33 | minDate, 34 | disablePast, 35 | disableFuture, 36 | maxDateMessage, 37 | minDateMessage, 38 | invalidDateMessage, 39 | } = props; 40 | 41 | // if null - do not show error 42 | if (utils.isNull(value)) { 43 | return ''; 44 | } 45 | 46 | if (!utils.isValid(value)) { 47 | return invalidDateMessage; 48 | } 49 | 50 | if ( 51 | (maxDate && utils.isAfter(value, utils.endOfDay(utils.date(maxDate)))) || 52 | (disableFuture && utils.isAfter(value, utils.endOfDay(utils.date()))) 53 | ) { 54 | return maxDateMessage; 55 | } 56 | 57 | if ( 58 | (minDate && utils.isBefore(value, utils.startOfDay(utils.date(minDate)))) || 59 | (disablePast && utils.isBefore(value, utils.startOfDay(utils.date()))) 60 | ) { 61 | return minDateMessage; 62 | } 63 | 64 | return ''; 65 | }; 66 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/ControllingProgrammatically.example.jsx: -------------------------------------------------------------------------------- 1 | import Button from '@material-ui/core/Button'; 2 | import withStyles from '@material-ui/core/styles/withStyles'; 3 | import { InlineDatePicker } from 'material-ui-pickers'; 4 | import PropTypes from 'prop-types'; 5 | import React, { PureComponent } from 'react'; 6 | 7 | class ControllingProgrammaticallyExample extends PureComponent { 8 | static propTypes = { 9 | classes: PropTypes.object.isRequired, 10 | }; 11 | 12 | state = { 13 | selectedDate: new Date(), 14 | }; 15 | 16 | handleDateChange = date => { 17 | this.setState({ selectedDate: date }); 18 | }; 19 | 20 | openPicker = e => { 21 | // do not pass Event for default pickers 22 | this.picker.open(e); 23 | }; 24 | 25 | render() { 26 | const { selectedDate } = this.state; 27 | 28 | return ( 29 |
30 | 31 | 32 |
33 | { 40 | console.log(node); // check console to view the api of wrapper 41 | this.picker = node; 42 | }} 43 | /> 44 |
45 |
46 | ); 47 | } 48 | } 49 | 50 | const styles = { 51 | container: { 52 | display: 'flex', 53 | flexDirection: 'column', 54 | }, 55 | }; 56 | 57 | export default withStyles(styles)(ControllingProgrammaticallyExample); 58 | -------------------------------------------------------------------------------- /lib/copy.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fse = require('fs-extra'); 3 | 4 | function copyReadme() { 5 | return fse.copyFile( 6 | path.resolve(__dirname, '..', 'README.md'), 7 | path.resolve(__dirname, 'build', 'README.md') 8 | ); 9 | } 10 | 11 | function createPackageFile() { 12 | return new Promise(resolve => { 13 | fse.readFile(path.resolve(__dirname, 'package.json'), 'utf8', (err, data) => { 14 | if (err) { 15 | throw err; 16 | } 17 | 18 | resolve(data); 19 | }); 20 | }) 21 | .then(data => JSON.parse(data)) 22 | .then(packageData => { 23 | // cleanup produced package 24 | const { 25 | devDependencies, 26 | jest, 27 | husky, 28 | main, 29 | module, 30 | typings, 31 | 'lint-staged': ls, 32 | scripts: { postinstall }, 33 | ...other 34 | } = packageData; 35 | 36 | const newPackage = { 37 | ...other, 38 | private: false, 39 | main: main.replace('build/', ''), 40 | module: module.replace('build/', ''), 41 | typings: typings.replace('build/', ''), 42 | scripts: { 43 | postinstall, 44 | }, 45 | }; 46 | 47 | return new Promise(resolve => { 48 | const buildPath = path.resolve(__dirname, 'build', 'package.json'); 49 | const data = JSON.stringify(newPackage, null, 2); 50 | fse.writeFile(buildPath, data, err => { 51 | if (err) throw err; 52 | console.log(`Created package.json in ${buildPath}`); 53 | resolve(); 54 | }); 55 | }); 56 | }); 57 | } 58 | 59 | createPackageFile().then(() => copyReadme()); 60 | -------------------------------------------------------------------------------- /docs/src/layout/DrawerMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import { 4 | Divider, 5 | Toolbar, 6 | Typography, 7 | withStyles, 8 | createStyles, 9 | Theme, 10 | WithStyles, 11 | } from '@material-ui/core'; 12 | 13 | import NavigationMenu from './NavigationMenu'; 14 | import { version } from '../../package.json'; 15 | 16 | const DrawerMenu: React.SFC> = ({ classes }) => ( 17 |
18 | 19 | 20 | 21 | Material-UI pickers 22 | 23 | 24 | 25 | 30 | 31 | {version} 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | ); 40 | 41 | const styles = (theme: Theme) => 42 | createStyles({ 43 | drawerRoot: { 44 | width: 250, 45 | }, 46 | drawerToolbar: { 47 | display: 'flex', 48 | flexDirection: 'column', 49 | justifyContent: 'center', 50 | alignItems: 'flex-start', 51 | }, 52 | headerLink: { 53 | transition: 'color .2s ease-in-out', 54 | '&:hover': { 55 | color: theme.palette.primary.dark, 56 | textDecoration: 'underline', 57 | }, 58 | }, 59 | }); 60 | 61 | export default withStyles(styles)(DrawerMenu); 62 | -------------------------------------------------------------------------------- /lib/src/_shared/PickerToolbar.tsx: -------------------------------------------------------------------------------- 1 | import { Theme } from '@material-ui/core'; 2 | import createStyles from '@material-ui/core/styles/createStyles'; 3 | import withStyles, { WithStyles } from '@material-ui/core/styles/withStyles'; 4 | import Toolbar, { ToolbarProps } from '@material-ui/core/Toolbar'; 5 | import clsx from 'clsx'; 6 | import * as PropTypes from 'prop-types'; 7 | import * as React from 'react'; 8 | import { ExtendMui } from '../typings/extendMui'; 9 | 10 | export interface PickerToolbarProps extends ExtendMui, WithStyles { 11 | children: React.ReactNodeArray; 12 | } 13 | 14 | const PickerToolbar: React.SFC = ({ 15 | children, 16 | className = null, 17 | classes, 18 | ...other 19 | }) => { 20 | return ( 21 | 22 | {children} 23 | 24 | ); 25 | }; 26 | 27 | (PickerToolbar as any).propTypes = { 28 | children: PropTypes.arrayOf(PropTypes.node).isRequired, 29 | className: PropTypes.string, 30 | classes: PropTypes.any.isRequired, 31 | innerRef: PropTypes.any, 32 | }; 33 | 34 | PickerToolbar.defaultProps = { 35 | className: '', 36 | }; 37 | 38 | export const styles = (theme: Theme) => 39 | createStyles({ 40 | toolbar: { 41 | display: 'flex', 42 | flexDirection: 'column', 43 | alignItems: 'flex-start', 44 | justifyContent: 'center', 45 | height: 100, 46 | backgroundColor: 47 | theme.palette.type === 'light' 48 | ? theme.palette.primary.main 49 | : theme.palette.background.default, 50 | }, 51 | }); 52 | 53 | export default withStyles(styles, { name: 'MuiPickersToolbar' })(PickerToolbar); 54 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/CssOverrides.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import { DatePicker } from 'material-ui-pickers'; 3 | import { MuiThemeProvider, createMuiTheme } from '@material-ui/core'; 4 | 5 | import lightBlue from '@material-ui/core/colors/lightBlue'; 6 | 7 | const materialTheme = createMuiTheme({ 8 | overrides: { 9 | MuiPickersToolbar: { 10 | toolbar: { 11 | backgroundColor: lightBlue.A200, 12 | }, 13 | }, 14 | MuiPickersCalendarHeader: { 15 | switchHeader: { 16 | // backgroundColor: lightBlue.A200, 17 | // color: 'white', 18 | }, 19 | }, 20 | MuiPickersDay: { 21 | day: { 22 | color: lightBlue.A700, 23 | }, 24 | isSelected: { 25 | backgroundColor: lightBlue['400'], 26 | }, 27 | current: { 28 | color: lightBlue['900'], 29 | }, 30 | }, 31 | MuiPickersModal: { 32 | dialogAction: { 33 | color: lightBlue['400'], 34 | }, 35 | }, 36 | }, 37 | }); 38 | 39 | export default class BasicDatePicker extends PureComponent { 40 | state = { 41 | selectedDate: new Date(), 42 | }; 43 | 44 | handleDateChange = date => { 45 | this.setState({ selectedDate: date }); 46 | }; 47 | 48 | render() { 49 | const { selectedDate } = this.state; 50 | 51 | return ( 52 | 53 |
54 | 60 |
61 |
62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/FormatsCustomization.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Code from '_shared/Code'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | 6 | // eslint-disable-next-line import/no-webpack-loader-syntax 7 | import utilsInterfaceCode from '!raw-loader!@date-io/core/IUtils.d.ts'; 8 | 9 | const FormatCustomization = () => ( 10 |
11 | 12 | Format customization 13 | 14 | 15 | 16 | For localization purpose may be needed to change displaying values in the pickers modal, 17 | because default formats can be not idiomatic for some localizations. There utils can help you. 18 | 19 | 20 | 21 | It`s possible to override any of displaying date values by inheritance of utils passed to 22 | MuiPickersProvider. 23 | 24 | 25 | 30 | You can use ES6 class syntax or override values with a help of .prototype property 31 | 32 | } 33 | /> 34 | 35 | 36 | Utils interface 37 | 38 | 39 | 40 | Where TDate - date object passed from state (moment, native Date or Luxon`s DateTime) 41 | 42 | 43 | 44 |
45 | ); 46 | 47 | export default FormatCustomization; 48 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DatePicker/InlineDatePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import { InlineDatePicker } from 'material-ui-pickers'; 2 | import React, { Fragment, PureComponent } from 'react'; 3 | import { withUtilsService } from '../../../_shared/UtilsServiceContext'; 4 | 5 | class InlineDatePickerDemo extends PureComponent { 6 | state = { 7 | selectedDate: '2018-01-01T00:00:00.000Z', 8 | }; 9 | 10 | handleDateChange = date => { 11 | this.setState({ selectedDate: date }); 12 | }; 13 | 14 | render() { 15 | const { selectedDate } = this.state; 16 | 17 | return ( 18 | 19 |
20 | 25 |
26 | 27 |
28 | 35 |
36 | 37 |
38 | 51 |
52 |
53 | ); 54 | } 55 | } 56 | 57 | export default withUtilsService(InlineDatePickerDemo); 58 | -------------------------------------------------------------------------------- /docs/src/Pages/Regression/Regression.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from 'react'; 2 | import { Grid, Typography } from '@material-ui/core'; 3 | import { DatePicker } from 'material-ui-pickers'; 4 | import { createRegressionDay as createRegressionDayRenderer } from './RegressionDay'; 5 | import { MuiPickersContext } from 'material-ui-pickers'; 6 | import LeftArrowIcon from '@material-ui/icons/KeyboardArrowLeft'; 7 | import RightArrowIcon from '@material-ui/icons/KeyboardArrowRight'; 8 | 9 | export function Regression() { 10 | const utils = useContext(MuiPickersContext); 11 | const [date, changeDate] = useState(new Date('2019-01-01T00:00:00.000Z')); 12 | 13 | const sharedProps = { 14 | value: date, 15 | onChange: changeDate, 16 | style: { margin: '0 10px' }, 17 | leftArrowIcon: , 18 | rightArrowIcon: , 19 | renderDay: createRegressionDayRenderer(utils!), 20 | KeyboardButtonProps: { 21 | className: 'keyboard-btn', 22 | }, 23 | }; 24 | 25 | return ( 26 | <> 27 | 28 | This page is using for the automate regression of material-ui-pickers. 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /docs/src/Pages/Guides/CssOverrides.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Code from '_shared/Code'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | import typescriptOverrideCode from './CssOverridesTypescript.example'; // eslint-disable-line 6 | 7 | const CssOverrides = () => ( 8 |
9 | 10 | Override stylesheet 11 | 12 | 13 | 14 | Default pickers appearance built based on material-ui theme provided. So pickers will take all 15 | colors/fonts/theme setting as any other material-ui components. 16 | 17 | 18 | 19 | But we are not providing any for-component classes api to override stylesheet for particular 20 | component. Only one way to override existed stylesheet - usage of global material-ui theme 21 | overrides. 22 | 23 | 24 | 29 | You can find the override component name and class in the generated classnames for pickers 30 | components. 31 | 32 | } 33 | /> 34 | 35 | 36 | For typescript users 37 | 38 | 39 | 40 | Override default material-ui theme to attach picker's component override. (This will also 41 | autocomplete classnames for overrides) 42 | 43 | 44 | 45 |
46 | ); 47 | 48 | export default CssOverrides; 49 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/TimePicker/TimePickerDemo.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypesTable from '_shared/PropTypesTable'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | 6 | const TimePickerDemo = () => ( 7 |
8 | 9 | Time picker 10 | 11 | 12 | Time pickers use a dialog to select a single time (in the hours:minutes format). 13 | 14 | 15 | The selected time is indicated by the filled circle at the end of the clock hand. 16 | 17 | 18 | 23 | A time picker should adjusts to a user’s preferred time setting, i.e. the 12-hour or 24 | 24-hour format. 25 | 26 | } 27 | /> 28 | 29 | 34 | Seconds input can be used for selection of precise time point 35 | 36 | } 37 | /> 38 | 39 | 43 | 44 | 48 | 49 | 50 |
51 | ); 52 | 53 | export default TimePickerDemo; 54 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DatePicker/DatePickerDemo.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypesTable from '_shared/PropTypesTable'; 3 | import SourcablePanel from '_shared/SourcablePanel'; 4 | import { Typography } from '@material-ui/core'; 5 | 6 | const DatePickerDemo = () => ( 7 |
8 | 9 | Date picker 10 | 11 | 12 | Date pickers use a dialog window to select a single date. 13 | 14 | 15 | The selected day is indicated by a filled circle. The current day is indicated by a different 16 | color and type weight. 17 | 18 | 19 | 23 | 24 | 28 | 29 | 33 | 34 | 38 | 39 | 44 | Customization performing by overriding render method for Day component. 45 | Here example with moment-js 46 | 47 | } 48 | /> 49 | 50 | 51 |
52 | ); 53 | 54 | export default DatePickerDemo; 55 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DatePicker/KeyboardDatePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, PureComponent } from 'react'; 2 | import { DatePicker } from 'material-ui-pickers'; 3 | import { withUtilsService } from '../../../_shared/UtilsServiceContext'; 4 | 5 | class KeyboardDatePicker extends PureComponent { 6 | state = { 7 | selectedDate: new Date(), 8 | }; 9 | 10 | handleDateChange = date => { 11 | this.setState({ selectedDate: date }); 12 | }; 13 | 14 | render() { 15 | const { selectedDate } = this.state; 16 | 17 | return ( 18 | 19 |
20 | console.log('Keyboard Input:', e.target.value)} 29 | /> 30 |
31 | 32 |
33 | pass plain array if you are not controlling value outside 42 | mask={value => 43 | value ? [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/] : [] 44 | } 45 | value={selectedDate} 46 | onChange={this.handleDateChange} 47 | disableOpenOnEnter 48 | animateYearScrolling={false} 49 | /> 50 |
51 |
52 | ); 53 | } 54 | } 55 | 56 | export default withUtilsService(KeyboardDatePicker); 57 | -------------------------------------------------------------------------------- /docs/src/Pages/Components/DateTimePicker/InlineDateTimePicker.example.jsx: -------------------------------------------------------------------------------- 1 | import { InlineDateTimePicker } from 'material-ui-pickers'; 2 | import React, { Fragment, PureComponent } from 'react'; 3 | import { withUtilsService } from '../../../_shared/UtilsServiceContext'; 4 | 5 | class InlineDateTimePickerDemo extends PureComponent { 6 | state = { 7 | selectedDate: '2018-01-01T00:00:00.000Z', 8 | }; 9 | 10 | handleDateChange = date => { 11 | this.setState({ selectedDate: date }); 12 | }; 13 | 14 | render() { 15 | const { selectedDate } = this.state; 16 | 17 | return ( 18 | 19 |
20 | 25 |
26 | 27 |
28 | 59 |
60 |
61 | ); 62 | } 63 | } 64 | 65 | export default withUtilsService(InlineDateTimePickerDemo); 66 | -------------------------------------------------------------------------------- /lib/src/TimePicker/TimePickerInline.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import BasePicker, { BasePickerProps } from '../_shared/BasePicker'; 4 | import { ExtendWrapper } from '../wrappers/ExtendWrapper'; 5 | import InlineWrapper, { OuterInlineWrapperProps } from '../wrappers/InlineWrapper'; 6 | import TimePicker, { BaseTimePickerProps } from './TimePicker'; 7 | 8 | export interface TimePickerInlineProps 9 | extends BasePickerProps, 10 | BaseTimePickerProps, 11 | ExtendWrapper {} 12 | 13 | export const TimePickerInline: React.SFC = props => { 14 | const { 15 | ampm, 16 | format, 17 | forwardedRef, 18 | initialFocusedDate, 19 | minutesStep, 20 | onChange, 21 | seconds, 22 | value, 23 | ...other 24 | } = props; 25 | 26 | return ( 27 | 28 | {({ 29 | date, 30 | utils, 31 | handleChange, 32 | handleTextFieldChange, 33 | isAccepted, 34 | pick12hOr24hFormat, 35 | handleAccept, 36 | handleClear, 37 | }) => ( 38 | 48 | 55 | 56 | )} 57 | 58 | ); 59 | }; 60 | 61 | export default React.forwardRef((props: TimePickerInlineProps, ref) => ( 62 | 63 | )); 64 | -------------------------------------------------------------------------------- /docs/src/Pages/GettingStarted/Usage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Code from '_shared/Code'; 4 | import { Typography, withStyles } from '@material-ui/core'; 5 | import quickStartCode from '!raw-loader!./QuickStart.example'; // eslint-disable-line 6 | 7 | const sandBoxId = 'q9l2j10wr4'; 8 | 9 | const Usage = ({ classes }) => ( 10 |
11 | 12 | Usage 13 | 14 | 15 | 16 | Material-UI-pickers rely only on material-ui controls and the date-management lib you have 17 | choose. Please note that all components are controlled, thats means that its required to pass 18 | value and 19 | onChange props. 20 | 21 | 22 | 23 | Quick Start 24 | 25 | 26 | 27 | Here is a quick example you to get started 28 | 29 | 30 | 31 | 32 | 33 | Interactive example 34 | 35 | 36 |