├── .circleci └── config.yml ├── .dependabot └── config.yml ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 1.bug.md │ ├── 2.feature.md │ ├── 3.material-design.md │ └── config.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .percy.yml ├── .prettierignore ├── .prettierrc ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cypress.json ├── cypress └── fixtures │ └── example.json ├── docs ├── .gitignore ├── _constants.ts ├── _shared │ ├── Ad.tsx │ ├── Code.tsx │ ├── Example.tsx │ ├── LinkedComponents.tsx │ ├── PageMeta.tsx │ ├── PatreonSponsors.jsx │ ├── PropTypesTable.tsx │ ├── UtilsServiceContext.tsx │ └── svgIcons │ │ ├── GithubIcon.jsx │ │ ├── KawaiiIcon.tsx │ │ ├── LightbulbIcon.tsx │ │ └── Logo.tsx ├── babel.config.js ├── fakeApi │ └── randomDate.ts ├── layout │ ├── Layout.tsx │ ├── PageWithContext.tsx │ ├── components │ │ ├── DrawerMenu.tsx │ │ ├── NavItem.jsx │ │ ├── NavigationMenu.tsx │ │ └── navigationMap.ts │ └── styleOverrides.ts ├── loaders │ └── example-loader.js ├── next.config.js ├── notifications.json ├── package.json ├── pages │ ├── _app.tsx │ ├── _document.tsx │ ├── _error.tsx │ ├── api │ │ └── props.tsx │ ├── demo │ │ ├── datepicker │ │ │ ├── BasicDatePicker.example.tsx │ │ │ ├── CustomDay.example.tsx │ │ │ ├── CustomInput.example.tsx │ │ │ ├── DatePickers.example.tsx │ │ │ ├── ServerRequest.example.tsx │ │ │ ├── StaticDatePicker.example.tsx │ │ │ ├── ViewsDatePicker.example.tsx │ │ │ └── index.mdx │ │ ├── daterangepicker │ │ │ ├── BasicDateRangePicker.example.tsx │ │ │ ├── CalendarsDateRangePicker.example.tsx │ │ │ ├── CustomRangeInputs.example.tsx │ │ │ ├── MinMaxDateRangePicker.example.tsx │ │ │ ├── ResponsiveDateRangePicker.example.tsx │ │ │ ├── StaticDateRangePicker.example.tsx │ │ │ └── index.mdx │ │ ├── datetime-picker │ │ │ ├── BasicDateTimePicker.example.tsx │ │ │ ├── CustomDateTimePicker.example.tsx │ │ │ ├── DateTimePickers.example.tsx │ │ │ ├── DateTimeValidation.example.tsx │ │ │ └── index.mdx │ │ └── timepicker │ │ │ ├── BasicTimePicker.example.tsx │ │ │ ├── SecondsTimePicker.example.tsx │ │ │ ├── StaticTimePicker.example.tsx │ │ │ ├── TimePickers.example.tsx │ │ │ ├── TimeValidation.example.tsx │ │ │ └── index.mdx │ ├── getting-started │ │ ├── installation.mdx │ │ ├── parsing.mdx │ │ └── usage.mdx │ ├── guides │ │ ├── Accessibility.example.tsx │ │ ├── ControllingProgrammatically.example.tsx │ │ ├── CssOverrides.example.tsx │ │ ├── CssTheme.example.tsx │ │ ├── CssThemeSpacing.example.tsx │ │ ├── DateAdapterProp.example.tsx │ │ ├── Formats.example.tsx │ │ ├── FormikOurValidation.example.tsx │ │ ├── FormikValidationSchema.example.tsx │ │ ├── OverrideLogic.example.tsx │ │ ├── StaticComponents.example.tsx │ │ ├── accessibility.mdx │ │ ├── controlling-programmatically.mdx │ │ ├── css-overrides.mdx │ │ ├── date-adapter-passing.mdx │ │ ├── date-io-customization.mdx │ │ ├── forms.mdx │ │ ├── static-components.mdx │ │ ├── typescript.mdx │ │ └── upgrading-to-v3.mdx │ ├── index │ │ ├── Landing.tsx │ │ ├── LandingProperty.tsx │ │ └── index.tsx │ ├── localization │ │ ├── Date-fns.example.tsx │ │ ├── Hijri.example.tsx │ │ ├── Moment.example.tsx │ │ ├── Persian.example.tsx │ │ ├── calendar-systems.mdx │ │ ├── date-fns.mdx │ │ └── moment.mdx │ ├── regression │ │ ├── Regression.tsx │ │ ├── RegressionDay.tsx │ │ └── index.tsx │ └── releases.tsx ├── patrons.json ├── prop-types.json ├── scripts │ ├── assign-production-domains.js │ ├── docgen.js │ └── generate-backers.js ├── static │ ├── android-icon-144x144.png │ ├── android-icon-192x192.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 │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── manifest.json │ ├── meta-image.png │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ └── ms-icon-70x70.png ├── tsconfig.json ├── typings.d.ts └── utils │ ├── NotificationManager.tsx │ ├── anchor-autolink.js │ ├── getPageContext.ts │ ├── github-api.ts │ ├── helpers.ts │ ├── prism.ts │ ├── table-styler.js │ └── utilsService.ts ├── e2e ├── component │ ├── DatePicker.spec.tsx │ ├── DateTimePicker.spec.tsx │ └── KeyboardNavigation.spec.tsx ├── integration │ ├── App.spec.ts │ ├── DatePicker.spec.ts │ ├── DateRange.spec.ts │ └── VisualRegression.spec.ts ├── plugins │ └── index.js ├── support │ ├── commands.ts │ └── index.js ├── test-utils.tsx └── tsconfig.json ├── lib ├── .size-snapshot.json ├── adapter │ ├── date-fns.ts │ ├── dayjs.ts │ ├── luxon.ts │ └── moment.ts ├── babel.config.js ├── cypress.json ├── jest.config.js ├── package.json ├── prepare-build-files.js ├── remove-prop-types.js ├── rollup.config.js ├── src │ ├── CalendarSkeleton.tsx │ ├── DatePicker │ │ ├── DatePicker.ts │ │ ├── DatePickerToolbar.tsx │ │ └── index.ts │ ├── DateRangePicker │ │ ├── DateRangeDelimiter.tsx │ │ ├── DateRangePicker.tsx │ │ ├── DateRangePickerDay.tsx │ │ ├── DateRangePickerInput.tsx │ │ ├── DateRangePickerToolbar.tsx │ │ ├── DateRangePickerView.tsx │ │ ├── DateRangePickerViewDesktop.tsx │ │ ├── DateRangePickerViewMobile.tsx │ │ ├── RangeTypes.ts │ │ └── date-range-manager.ts │ ├── DateTimePicker │ │ ├── DateTimePicker.tsx │ │ ├── DateTimePickerTabs.tsx │ │ ├── DateTimePickerToolbar.tsx │ │ ├── date-time-utils.ts │ │ └── index.ts │ ├── LocalizationProvider.tsx │ ├── Picker │ │ ├── Picker.tsx │ │ ├── SharedPickerProps.tsx │ │ └── makePickerWithState.tsx │ ├── TimePicker │ │ ├── TimePicker.tsx │ │ ├── TimePickerToolbar.tsx │ │ └── index.tsx │ ├── __tests__ │ │ ├── DatePicker.test.tsx │ │ ├── DatePickerProps.test.tsx │ │ ├── DatePickerRoot.test.tsx │ │ ├── DatePickerTestingLib.test.tsx │ │ ├── DateRangePicker.test.tsx │ │ ├── DateRangePickerLegacy.test.tsx │ │ ├── DateTimePicker.test.tsx │ │ ├── DateTimePickerRoot.test.tsx │ │ ├── DateTimePickerTestingLib.test.tsx │ │ ├── KeyboardDatePicker.test.tsx │ │ ├── KeyboardDateTimePicker.test.tsx │ │ ├── Theme.test.tsx │ │ ├── TimePicker.test.tsx │ │ ├── Validation.test.tsx │ │ ├── commands.tsx │ │ ├── createClientRender.tsx │ │ ├── setup.ts │ │ ├── shallow │ │ │ ├── Month.test.tsx │ │ │ └── MonthSelection.test.tsx │ │ ├── test-utils.tsx │ │ ├── tsconfig.json │ │ ├── typescript │ │ │ ├── GenericValues.spec.tsx │ │ │ ├── Overrides.tstest.tsx │ │ │ └── ThemeDefaultProps.tstest.tsx │ │ ├── typings.d.ts │ │ └── unit │ │ │ ├── date-range-manager.test.ts │ │ │ ├── date-utils.test.ts │ │ │ └── text-field-helper.test.ts │ ├── _helpers │ │ ├── date-utils.ts │ │ ├── text-field-helper.ts │ │ ├── time-utils.ts │ │ └── utils.ts │ ├── _shared │ │ ├── ArrowSwitcher.tsx │ │ ├── KeyboardDateInput.tsx │ │ ├── PickerToolbar.tsx │ │ ├── PickersModalDialog.tsx │ │ ├── PickersPopper.tsx │ │ ├── PureDateInput.tsx │ │ ├── ToolbarButton.tsx │ │ ├── ToolbarText.tsx │ │ ├── hooks │ │ │ ├── date-helpers-hooks.tsx │ │ │ ├── useCanAutoFocus.tsx │ │ │ ├── useIsLandscape.tsx │ │ │ ├── useKeyDown.ts │ │ │ ├── useMaskedInput.tsx │ │ │ ├── useOpenState.ts │ │ │ ├── usePickerState.ts │ │ │ ├── useTraceUpdate.tsx │ │ │ ├── useUtils.ts │ │ │ ├── useValidation.ts │ │ │ └── useViews.tsx │ │ ├── icons │ │ │ ├── ArrowDropDown.tsx │ │ │ ├── ArrowLeft.tsx │ │ │ ├── ArrowRight.tsx │ │ │ ├── CalendarIcon.tsx │ │ │ ├── Clock.tsx │ │ │ ├── DateRange.tsx │ │ │ ├── Pen.tsx │ │ │ └── Time.tsx │ │ ├── withDateAdapterProp.tsx │ │ └── withDefaultProps.tsx │ ├── constants │ │ ├── ClockType.ts │ │ ├── dimensions.ts │ │ └── prop-types.ts │ ├── index.ts │ ├── typings │ │ ├── BasePicker.tsx │ │ ├── helpers.ts │ │ ├── index.ts │ │ ├── overrides.ts │ │ └── props.ts │ ├── views │ │ ├── Calendar │ │ │ ├── Calendar.tsx │ │ │ ├── CalendarHeader.tsx │ │ │ ├── CalendarView.tsx │ │ │ ├── Day.tsx │ │ │ ├── FadeTransitionGroup.tsx │ │ │ ├── Month.tsx │ │ │ ├── MonthSelection.tsx │ │ │ ├── SlideTransition.tsx │ │ │ ├── Year.tsx │ │ │ ├── YearSelection.tsx │ │ │ └── useCalendarState.tsx │ │ ├── Clock │ │ │ ├── Clock.tsx │ │ │ ├── ClockNumber.tsx │ │ │ ├── ClockNumbers.tsx │ │ │ ├── ClockPointer.tsx │ │ │ └── ClockView.tsx │ │ └── MobileKeyboardInputView.tsx │ └── wrappers │ │ ├── DesktopTooltipWrapper.tsx │ │ ├── DesktopWrapper.tsx │ │ ├── MobileWrapper.tsx │ │ ├── ResponsiveWrapper.tsx │ │ ├── StaticWrapper.tsx │ │ ├── Wrapper.tsx │ │ ├── WrapperVariantContext.tsx │ │ └── makeWrapperComponent.tsx ├── tsconfig.adapters.json ├── tsconfig.json └── typings.d.ts ├── now.json ├── package.json ├── scripts └── deduplicate.js └── yarn.lock /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | # https://dependabot.com/docs/config-file/ 2 | # validate with https://dependabot.com/docs/config-file/validator/ 3 | version: 1 4 | update_configs: 5 | - package_manager: 'javascript' 6 | directory: '/' 7 | update_schedule: 'weekly' 8 | version_requirement_updates: 'auto' 9 | ignored_updates: 10 | - match: 11 | # These should be grouped. Maintainer advise: Watch https://github.com/babel/babel 12 | # for new releases and file a PR if you got time. 13 | dependency_name: '@babel/*' 14 | - match: 15 | # https://github.com/mui-org/material-ui/pull/17604#issuecomment-536262291 16 | dependency_name: 'core-js' 17 | - match: 18 | # 2.0 started using ES modules instead of CommonJS modules 19 | dependency_name: 'raw-loader' 20 | # not ignoring `react`. We'll hijack those PRs and also upgrade the other 21 | # packages in the facebook/react repository 22 | - match: 23 | # should be grouped with `react` 24 | dependency_name: 'react-dom' 25 | - match: 26 | # should be grouped with `react` 27 | dependency_name: 'react-is' 28 | - match: 29 | # should be grouped with `react` 30 | dependency_name: 'react-test-renderer' 31 | - match: 32 | # as of 3.x requires node@10. We can upgrade once we do as well 33 | dependency_name: 'url-loader' 34 | version_requirement: '>= 3.0' 35 | - match: 36 | # Stop investment in the documentation per https://github.com/mui-org/material-ui/issues/19706 37 | dependency_name: 'next' 38 | - match: 39 | # Stop investment in the documentation per https://github.com/mui-org/material-ui/issues/19706 40 | dependency_name: '@types/next' 41 | - match: 42 | # Stop investment in the documentation per https://github.com/mui-org/material-ui/issues/19706 43 | dependency_name: 'next-transpile-modules' 44 | -------------------------------------------------------------------------------- /.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 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js text eol=lf 2 | *.jsx text eol=lf 3 | docs/prop-types.json linguist-generated=true 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: material-ui 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/@material-ui/core 8 | custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1.bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 🐛 3 | about: Create a bug report for Material-UI. 4 | labels: 'status: needs triage' 5 | --- 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | - [ ] The issue is present in the latest release. 17 | - [ ] I have searched the [issues](https://github.com/mui-org/material-ui-pickers/issues) of this repository and believe that this is not a duplicate. 18 | 19 | ## Current Behavior 😯 20 | 21 | 22 | 23 | ## Expected Behavior 🤔 24 | 25 | 26 | 27 | ## Steps to Reproduce 🕹 28 | 29 | 37 | 38 | Steps: 39 | 40 | 1. 41 | 2. 42 | 3. 43 | 4. 44 | 45 | ## Context 🔦 46 | 47 | 51 | 52 | ## Your Environment 🌎 53 | 54 | 58 | 59 | | Tech | Version | 60 | | ----------- | ------- | 61 | | @material-ui/core | v4.?.? | 62 | | @material-ui/pickers | v4.?.? | 63 | | React | | 64 | | Browser | | 65 | | TypeScript | | 66 | | etc. | | 67 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2.feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 💄 3 | about: Suggest a new idea for the project. 4 | labels: 'status: needs triage' 5 | --- 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | - [ ] I have searched the [issues](https://github.com/mui-org/material-ui-pickers/issues) of this repository and believe that this is not a duplicate. 17 | 18 | ## Summary 💡 19 | 20 | 21 | 22 | ## Examples 🌈 23 | 24 | 28 | 29 | ## Motivation 🔦 30 | 31 | 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3.material-design.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Material design issue 3 | about: An issue with one of our components regarding the Material design guidelines. 4 | labels: 'status: needs triage, material design system' 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false # force the usage of a template 2 | contact_links: 3 | - name: Support ❔ 4 | url: https://material-ui.com/getting-started/support/ 5 | about: I need support with Material-UI. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [ ] I have followed (at least) the [PR section of the contributing guide](https://github.com/mui-org/material-ui/blob/master/CONTRIBUTING.md#sending-a-pull-request). 4 | -------------------------------------------------------------------------------- /.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 | .env 16 | 17 | # coverage 18 | coverage 19 | 20 | # Cache directory 21 | .npm 22 | ./cypress/**/* 23 | .next 24 | 25 | # Optional eslint cache 26 | .eslintcache 27 | 28 | # dotenv environment variables file 29 | .env.local 30 | 31 | # webstorm 32 | .idea/ 33 | /lib/yarn.lock 34 | /docs/yarn.lock 35 | 36 | # editors 37 | .vs 38 | .DS_Store 39 | 40 | .vercel -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/* 2 | lib/* 3 | src/* 4 | node_modules/* -------------------------------------------------------------------------------- /.percy.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | snapshot: 3 | percy-css: | 4 | #codefund { 5 | display: none; 6 | } 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node-modules/ 2 | build/ 3 | coverage/ 4 | *.mp4 5 | .next 6 | docs/prop-types.json 7 | .github/ 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Jest Current File", 11 | "program": "${workspaceFolder}/lib/node_modules/.bin/jest", 12 | "args": [ 13 | "--runInBand", 14 | "--config", 15 | "${workspaceFolder}/lib/jest.config.js", 16 | "${fileBasenameNoExtension}" 17 | ], 18 | "sourceMaps": true, 19 | "preLaunchTask": "npm: test:typescript - lib", 20 | "outFiles": [ "${workspaceFolder}/lib/src/__tests__/dist/**/*.js"], 21 | "console": "integratedTerminal", 22 | "internalConsoleOptions": "neverOpen", 23 | "disableOptimisticBPs": true, 24 | "env": { 25 | "UTILS": "date-fns" 26 | }, 27 | "windows": { 28 | "program": "${workspaceFolder}/lib/node_modules/jest/bin/jest" 29 | } 30 | }, 31 | { 32 | "type": "chrome", 33 | "request": "launch", 34 | "name": "Launch Chrome against localhost", 35 | "url": "http://localhost:3001", 36 | "webRoot": "${workspaceFoler}" 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "Formik", 4 | "Notistack", 5 | "Sourcable", 6 | "Unparsed", 7 | "ampm", 8 | "datetimepicker", 9 | "patreon" 10 | ], 11 | "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], 12 | "typescript.tsdk": "node_modules/typescript/lib", 13 | "javascript.implicitProjectConfig.checkJs": true 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "test:typescript", 7 | "path": "lib/", 8 | "problemMatcher": [], 9 | "label": "npm: test:typescript - lib", 10 | "detail": "rimraf src/__tests__/dist && tsc -p src/__tests__/tsconfig.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### [Versions](https://material-ui.com/versions/) 2 | 3 | ## 4.0.0-alpha.11 4 | 5 | ###### _Aug 1, 2020_ 6 | 7 | Big thanks to the 9 contributors who made this release possible. 8 | 9 | ### `@material-ui/pickers@v4.0.0-alpha.11` 10 | 11 | #### Breaking changes 12 | 13 | - [DatePicker] Require Material-UI v5 alpha (#2053) @eps1lon 14 | 15 | #### Changes 16 | 17 | - [DateTimePicker] Allow same date selection (#2016) @dmtrKovalenko 18 | 19 | ### Docs 20 | 21 | - [docs] Fix `inputRef` date picker customization demo (#2028) @Chee7ah 22 | - [docs] Migrate demos to TypeScript (#2030) @dmtrKovalenko 23 | - [docs] Remove mention of removed `autoOk` prop (#2020) @dandv 24 | - [docs] Update guides links to point to next (#2048) @aamirafridi 25 | 26 | ### Core 27 | 28 | - [test] Add test for textbox aria-invalid (#1955) @PaulSavignano 29 | - [test] check prettier on CI (#2025) @dmtrKovalenko 30 | - [test] Add yarn deduplicate step (#2036) @oliviertassinari 31 | - [Security] Bump codecov from 3.6.5 to 3.7.1 (#2014) @dependabot-preview 32 | - [Security] Bump elliptic from 6.5.1 to 6.5.3 (#2049) @dependabot-preview 33 | - [core] Batch small changes (#2034) @oliviertassinari 34 | - [core] Continue eslint sync with main repo (#2004) @oliviertassinari 35 | - [core] Upgrade prettier (#2005) @oliviertassinari 36 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ⚠️ The end of @material-ui/pickers 🙈, long live @mui/x-date-pickers 2 | 3 | See [#2157](https://github.com/mui/material-ui-pickers/issues/2157) for more details. 4 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:3001", 3 | "integrationFolder": "e2e/integration", 4 | "supportFile": "e2e/support/index.js", 5 | "pluginsFile": "e2e/plugins/index.js", 6 | "chromeWebSecurity": false, 7 | "projectId": "qow28y", 8 | "experimentalComponentTesting": true, 9 | "componentFolder": "./e2e/component" 10 | } 11 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel -------------------------------------------------------------------------------- /docs/_constants.ts: -------------------------------------------------------------------------------- 1 | export const CODESANDBOX_EXAMPLE_ID = 'material-ui-pickers-v4-jfm6g'; 2 | 3 | export const DOMAIN = 'material-ui-pickers.dev'; 4 | 5 | export const HOST_URL = `https://${DOMAIN}`; 6 | 7 | export const LOGO_URL = `${HOST_URL}/static/meta-image.png`; 8 | 9 | export const GITHUB_URL = 'https://github.com/mui-org/material-ui-pickers'; 10 | 11 | export const GITHUB_EDIT_URL = `${GITHUB_URL}/edit/next/docs/`; 12 | -------------------------------------------------------------------------------- /docs/_shared/Ad.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { loadScript } from 'utils/helpers'; 3 | import { Grid, makeStyles } from '@material-ui/core'; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | '@global': { 7 | '#carbonads': { 8 | fontFamily: theme.typography.fontFamily, 9 | display: 'flex', 10 | maxWidth: '330px', 11 | backgroundColor: theme.palette.background.paper, 12 | boxShadow: theme.shadows[3], 13 | }, 14 | '#carbonads a': { color: 'inherit', textDecoration: 'none' }, 15 | '#carbonads a:hover': { color: 'inherit' }, 16 | '#carbonads span': { 17 | position: 'relative', 18 | display: 'block', 19 | overflow: 'hidden', 20 | }, 21 | '#carbonads .carbon-wrap': { display: 'flex' }, 22 | '.carbon-img': { display: 'block', margin: '0', lineHeight: '1' }, 23 | '.carbon-img img': { display: 'block' }, 24 | '.carbon-text': { 25 | fontSize: '13px', 26 | padding: '10px', 27 | lineHeight: '1.5', 28 | textAlign: 'left', 29 | }, 30 | '.carbon-poweredby': { 31 | display: 'block', 32 | padding: '8px 10px', 33 | background: 34 | 'repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4)', 35 | textAlign: 'center', 36 | fontStyle: 'italic', 37 | textTransform: 'capitalize', 38 | 39 | fontSize: '9px', 40 | lineHeight: '1', 41 | }, 42 | '@media only percy': { 43 | '#ad-script-position': { 44 | display: 'none', 45 | }, 46 | }, 47 | }, 48 | })); 49 | 50 | const Ad: React.FC = () => { 51 | useStyles(); 52 | 53 | React.useEffect(() => { 54 | // @ts-expect-error Need to extend window 55 | if (window && window.Cypress) { 56 | return; 57 | } 58 | 59 | const adScriptPosition = document.querySelector('#ad-script-position'); 60 | if (adScriptPosition) { 61 | let script = loadScript( 62 | 'https://cdn.carbonads.com/carbon.js?serve=CKYIL27L&placement=material-uicom', 63 | adScriptPosition 64 | ); 65 | 66 | script.id = '_carbonads_js'; 67 | } 68 | }, []); 69 | 70 | if (process.env.VISUAL_TESTING) { 71 | return null; 72 | } 73 | 74 | return ( 75 | 76 | 77 | 78 | ); 79 | }; 80 | 81 | export default Ad; 82 | -------------------------------------------------------------------------------- /docs/_shared/Code.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import React from 'react'; 3 | import { highlight } from '../utils/prism'; 4 | import { makeStyles } from '@material-ui/core'; 5 | 6 | const useStyles = makeStyles((theme) => ({ 7 | root: { 8 | margin: 0, 9 | fontFamily: theme.typography.fontFamily, 10 | fontSize: '1em', 11 | color: theme.palette.text.primary, 12 | padding: 5, 13 | backgroundColor: theme.palette.background.paper, 14 | 15 | '& pre': { 16 | borderRadius: 3, 17 | overflow: 'auto !important', 18 | margin: '0 !important', 19 | backgroundColor: theme.palette.background.paper + ' !important', 20 | }, 21 | }, 22 | inlineRoot: { 23 | padding: 0, 24 | '& pre': { 25 | padding: 0, 26 | }, 27 | }, 28 | inlineCode: { 29 | fontSize: 14, 30 | // color: theme.palette.secondary.main, 31 | whiteSpace: 'pre-wrap', 32 | }, 33 | margin: { 34 | margin: '10px 0 30px', 35 | }, 36 | })); 37 | 38 | interface CodeProps { 39 | children: string; 40 | inline?: boolean; 41 | withMargin?: boolean; 42 | language?: 'jsx' | 'typescript' | 'markup'; 43 | } 44 | 45 | const Code: React.FC = ({ language = 'typescript', inline, children, withMargin }) => { 46 | const classes = useStyles(); 47 | const highlightedCode = highlight(children, language); 48 | 49 | return ( 50 |
56 |
57 |         
61 |       
62 |
63 | ); 64 | }; 65 | 66 | Code.defaultProps = { 67 | withMargin: false, 68 | language: 'jsx', 69 | }; 70 | 71 | export default Code; 72 | -------------------------------------------------------------------------------- /docs/_shared/LinkedComponents.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Link from 'next/link'; 3 | import { Typography } from '@material-ui/core'; 4 | 5 | interface LinkedComponentsProps { 6 | components: string[]; 7 | } 8 | 9 | const LinkedComponents: React.FunctionComponent = ({ components }) => { 10 | return ( 11 | 22 | ); 23 | }; 24 | 25 | export default LinkedComponents; 26 | -------------------------------------------------------------------------------- /docs/_shared/PageMeta.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Head from 'next/head'; 3 | import { LOGO_URL, HOST_URL } from '_constants'; 4 | import { withRouter, WithRouterProps } from 'next/router'; 5 | 6 | interface PageMetaProps extends WithRouterProps { 7 | title?: string; 8 | component?: string; 9 | description?: string; 10 | } 11 | 12 | export function PageMeta({ title, component, router, description }: PageMetaProps) { 13 | if (component) { 14 | title = `${component} - @material-ui/pickers component`; 15 | description = `${component} usage examples and API of @material-ui/pickers`; 16 | } 17 | 18 | if (!description) { 19 | description = title; 20 | } 21 | 22 | return ( 23 | 24 | {title} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {router && } 35 | 36 | ); 37 | } 38 | 39 | export default withRouter(PageMeta); 40 | -------------------------------------------------------------------------------- /docs/_shared/PatreonSponsors.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import patrons from '../patrons.json'; 3 | import { makeStyles, Avatar, List, ListItem, ListItemText } from '@material-ui/core'; 4 | 5 | const useStyles = makeStyles({ 6 | aboutMeDescription: { 7 | maxWidth: 250, 8 | overflow: 'hidden', 9 | textOverflow: 'ellipsis', 10 | }, 11 | spinner: { 12 | margin: '0 auto', 13 | }, 14 | patronList: { 15 | maxWidth: 500, 16 | margin: '0 auto', 17 | }, 18 | link: { 19 | textDecoration: 'none', 20 | color: 'unset', 21 | }, 22 | avatar: { 23 | marginRight: 8, 24 | }, 25 | }); 26 | 27 | export default function PatreonSponsors() { 28 | const classes = useStyles(); 29 | if (patrons.length === 0) { 30 | return There is no sponsors yet 😢; 31 | } 32 | 33 | function getPatronSecondaryText(patron) { 34 | if (patron.twitter) { 35 | return @{patron.twitter}; 36 | } 37 | if (patron.about) { 38 | return ( 39 | 44 | ); 45 | } 46 | 47 | return patron.email; 48 | } 49 | 50 | return ( 51 | 52 | {patrons.map((patron, key) => ( 53 | 54 | 55 | 56 | 63 | 64 | 65 | ))} 66 | 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /docs/_shared/UtilsServiceContext.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Omit } from '@material-ui/core'; 3 | import { UtilsService, createUtilsService } from '../utils/utilsService'; 4 | 5 | export const UtilsContext = React.createContext(createUtilsService('date-fns')); 6 | 7 | export const withUtilsService =

(Component: React.ComponentType

) => { 8 | const withUtilsService: React.SFC> = (props) => ( 9 | 10 | {(service) => } 11 | 12 | ); 13 | 14 | withUtilsService.displayName = `withUtilsService(${Component.displayName || Component.name})`; 15 | 16 | return withUtilsService; 17 | }; 18 | -------------------------------------------------------------------------------- /docs/_shared/svgIcons/GithubIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SvgIcon } from '@material-ui/core'; 3 | 4 | const GitHub = (props) => ( 5 | 6 | 7 | 8 | ); 9 | 10 | export default GitHub; 11 | -------------------------------------------------------------------------------- /docs/_shared/svgIcons/KawaiiIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import useMediaQuery from '@material-ui/core/useMediaQuery'; 3 | import { NoSsr } from '@material-ui/core'; 4 | import { getRandomItem } from 'utils/helpers'; 5 | import { useTheme } from '@material-ui/core/styles'; 6 | import { Backpack, Ghost, Cat, IceCream, Browser, SpeechBubble, KawaiiProps } from 'react-kawaii'; 7 | 8 | const icons = { 9 | ghost: Ghost, 10 | cat: Cat, 11 | backpack: Backpack, 12 | iceCream: IceCream, 13 | browser: Browser, 14 | bubble: SpeechBubble, 15 | }; 16 | 17 | function getRandomIcon() { 18 | // @ts-ignore 19 | if (process.browser && window.Cypress) { 20 | return icons.ghost; 21 | } 22 | 23 | const icon = getRandomItem(Object.keys(icons)); 24 | return icons[icon as keyof typeof icons]; 25 | } 26 | 27 | interface KawaiiIconProps extends KawaiiProps { 28 | icon?: keyof typeof icons; 29 | className?: string; 30 | } 31 | 32 | const KawaiiIcon: React.FunctionComponent = ({ icon, size, ...other }) => { 33 | const theme = useTheme(); 34 | const isXs = useMediaQuery(theme.breakpoints.down('xs')); 35 | const calculatedSize = size || isXs ? 230 : 320; 36 | 37 | const Component = React.useMemo(() => (icon ? icons[icon] : getRandomIcon()), [icon]); 38 | 39 | return ( 40 | 41 | 42 | 43 | ); 44 | }; 45 | 46 | KawaiiIcon.defaultProps = { 47 | mood: 'excited', 48 | }; 49 | 50 | export default KawaiiIcon; 51 | -------------------------------------------------------------------------------- /docs/_shared/svgIcons/LightbulbIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SvgIcon } from '@material-ui/core'; 3 | 4 | function LightbulbOutline(props: any) { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | } 11 | 12 | LightbulbOutline.muiName = 'SvgIcon'; 13 | 14 | export default LightbulbOutline; 15 | -------------------------------------------------------------------------------- /docs/_shared/svgIcons/Logo.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useTheme } from '@material-ui/core/styles'; 3 | 4 | // ! This is very handcrafted svg for SSR. Don't make your logos this way 🤦🤦‍🤦‍ 5 | export default function Logo() { 6 | const theme = useTheme(); 7 | return ( 8 | 9 | 10 | 11 | 20 | 29 | 38 | 44 | 45 | 51 | 52 | 53 | 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['next/babel', '@zeit/next-typescript/babel'], 3 | plugins: [ 4 | '@babel/plugin-proposal-optional-chaining', 5 | '@babel/plugin-proposal-nullish-coalescing-operator', 6 | [ 7 | 'babel-plugin-module-resolver', 8 | { 9 | root: ['./'], 10 | alias: { 11 | '@material-ui/pickers/CalendarSkeleton': '@material-ui/pickers/src/CalendarSkeleton', 12 | }, 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /docs/fakeApi/randomDate.ts: -------------------------------------------------------------------------------- 1 | import { getDaysInMonth, isValid } from 'date-fns'; 2 | import { NowRequest, NowResponse } from '@now/node'; 3 | 4 | function getRandomNumber(min: number, max: number) { 5 | return Math.round(Math.random() * (max - min) + min); 6 | } 7 | 8 | // eslint-disable-next-line consistent-return 9 | export default function randomDate(req: NowRequest, res: NowResponse) { 10 | const { month } = req.query; 11 | 12 | if (!month || typeof month !== 'string') { 13 | res.status(400); 14 | return res.json({ 15 | reason: 'month query param is required', 16 | }); 17 | } 18 | 19 | const date = new Date(month); 20 | if (!isValid(date)) { 21 | res.status(422); 22 | return res.json({ 23 | reason: 'cannot parse month value', 24 | }); 25 | } 26 | 27 | setTimeout(() => { 28 | const daysInMonth = getDaysInMonth(date); 29 | const daysToHighlight = [1, 2, 3].map(() => getRandomNumber(1, daysInMonth)); 30 | 31 | res.json({ daysToHighlight }); 32 | }, 500); // fake some long work 33 | } 34 | -------------------------------------------------------------------------------- /docs/layout/components/DrawerMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Link from 'next/link'; 3 | import NavigationMenu from './NavigationMenu'; 4 | import { version } from '@material-ui/pickers/package.json'; 5 | import { Divider, Toolbar, Typography, Theme } from '@material-ui/core'; 6 | import { createStyles, withStyles, WithStyles } from '@material-ui/core/styles'; 7 | 8 | const styles = (theme: Theme) => 9 | createStyles({ 10 | drawerRoot: { 11 | width: 250, 12 | }, 13 | drawerToolbar: { 14 | display: 'flex', 15 | flexDirection: 'column', 16 | justifyContent: 'center', 17 | alignItems: 'flex-start', 18 | }, 19 | headerLink: { 20 | cursor: 'pointer', 21 | textDecoration: 'none', 22 | transition: 'color .2s ease-in-out', 23 | '&:hover': { 24 | color: theme.palette.primary.dark, 25 | textDecoration: 'underline', 26 | }, 27 | }, 28 | }); 29 | 30 | const DrawerMenu: React.SFC> = ({ classes }) => ( 31 |

32 | 33 | 34 | 35 | Material UI Pickers 36 | 37 | 38 | 39 | 40 | v{version} 41 | 42 | 43 | 44 | 45 | 46 |
47 | ); 48 | 49 | export default withStyles(styles)(DrawerMenu); 50 | -------------------------------------------------------------------------------- /docs/layout/components/NavigationMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import NavItem from './NavItem'; 3 | import { withRouter } from 'next/router'; 4 | import { List } from '@material-ui/core'; 5 | import { navItems } from './navigationMap'; 6 | import { stringToTestId } from 'utils/helpers'; 7 | 8 | class NavigationMenu extends React.Component { 9 | mapNavigation(depth: number) { 10 | return ({ title, children, href, as }: any) => { 11 | const { asPath } = this.props.router; 12 | const hasChildren = children && children.length > 0; 13 | const open = hasChildren 14 | ? children.some((item: any) => item.href === asPath || item.as === asPath) 15 | : false; 16 | 17 | return ( 18 | 27 | {children && children.length > 0 && children.map(this.mapNavigation(depth + 1))} 28 | 29 | ); 30 | }; 31 | } 32 | 33 | render() { 34 | return {navItems.map(this.mapNavigation(0))}; 35 | } 36 | } 37 | 38 | export default withRouter(NavigationMenu); 39 | -------------------------------------------------------------------------------- /docs/layout/components/navigationMap.ts: -------------------------------------------------------------------------------- 1 | import PropTypesDoc from '../../prop-types.json'; 2 | 3 | export const navItems = [ 4 | { 5 | title: 'Getting Started', 6 | children: [ 7 | { title: 'Installation', href: '/getting-started/installation' }, 8 | { title: 'Usage', href: '/getting-started/usage' }, 9 | { title: 'Parsing dates', href: '/getting-started/parsing' }, 10 | ], 11 | }, 12 | { 13 | title: 'Localization', 14 | children: [ 15 | { title: 'Using date-fns', href: '/localization/date-fns' }, 16 | { title: 'Using moment', href: '/localization/moment' }, 17 | { title: 'Additional Calendar Systems', href: '/localization/calendar-systems' }, 18 | ], 19 | }, 20 | { 21 | title: 'Components Demo', 22 | children: [ 23 | { title: 'Date Picker', href: '/demo/datepicker' }, 24 | { title: 'Date Range Picker', href: '/demo/daterangepicker' }, 25 | { title: 'Time Picker', href: '/demo/timepicker' }, 26 | { title: 'Date & Time Picker', href: '/demo/datetime-picker' }, 27 | ], 28 | }, 29 | { 30 | title: 'Components API', 31 | children: Object.keys(PropTypesDoc) 32 | .filter((component) => !component.match(/^(Mobile|Desktop|Static)/)) 33 | .map((component) => ({ 34 | title: component, 35 | as: `/api/${component}`, 36 | href: `/api/props?component=${component}`, 37 | })), 38 | }, 39 | { 40 | title: 'Guides', 41 | children: [ 42 | { title: 'TypeScript', href: '/guides/typescript' }, 43 | { title: 'Accessibility', href: '/guides/accessibility' }, 44 | { title: 'Form integration', href: '/guides/forms' }, 45 | { title: 'CSS overrides', href: '/guides/css-overrides' }, 46 | { title: 'Passing date adapter', href: '/guides/date-adapter-passing' }, 47 | { title: 'Date management customization', href: '/guides/date-io-customization' }, 48 | { 49 | title: 'Open pickers programmatically', 50 | href: '/guides/controlling-programmatically', 51 | }, 52 | { title: 'Static inner components', href: '/guides/static-components' }, 53 | { title: 'Updating to v3', href: '/guides/upgrading-to-v3' }, 54 | ], 55 | }, 56 | ] as const; 57 | -------------------------------------------------------------------------------- /docs/loaders/example-loader.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const path = require('path'); 3 | const safeJsonStringify = require('safe-json-stringify'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | 7 | module.exports = function exampleLoader(source) { 8 | const relativePath = path.relative(root, this.resource); 9 | 10 | const escapedRawSource = safeJsonStringify(source.replace(/'/g, '"')); 11 | const sourceWithExportedContext = 12 | source + 13 | `\nexport const raw = ${escapedRawSource}` + 14 | `\nexport const relativePath = "${relativePath}"`; 15 | 16 | return sourceWithExportedContext; 17 | }; 18 | -------------------------------------------------------------------------------- /docs/notifications.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /docs/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import sinon from 'sinon'; 2 | import React from 'react'; 3 | import App from 'next/app'; 4 | import cookies from 'next-cookies'; 5 | import getPageContext from '../utils/getPageContext'; 6 | import { PageWithContexts, ThemeType } from '../layout/PageWithContext'; 7 | 8 | if (process.env.VISUAL_TESTING) { 9 | const now = new Date('2019-01-01T09:41:00.000Z'); 10 | sinon.useFakeTimers(now.getTime()); 11 | } 12 | 13 | class MyApp extends App<{ theme: ThemeType }> { 14 | pageContext = getPageContext(); 15 | 16 | static async getInitialProps({ Component, ctx }: any) { 17 | let pageProps = {}; 18 | const { theme } = cookies(ctx); 19 | 20 | if (Component.getInitialProps) { 21 | pageProps = await Component.getInitialProps(ctx); 22 | } 23 | 24 | return { theme, pageProps }; 25 | } 26 | 27 | componentDidMount() { 28 | // Remove the server-side injected CSS. 29 | const jssStyles = document.querySelector('#jss-server-side'); 30 | if (jssStyles && jssStyles.parentNode) { 31 | jssStyles.parentNode.removeChild(jssStyles); 32 | } 33 | } 34 | 35 | render() { 36 | const { Component, pageProps, theme } = this.props; 37 | 38 | return ( 39 | 40 | 41 | 42 | ); 43 | } 44 | } 45 | 46 | export default MyApp; 47 | -------------------------------------------------------------------------------- /docs/pages/_error.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from 'react'; 3 | import KawaiiIcon from '_shared/svgIcons/KawaiiIcon'; 4 | import { styled } from '@material-ui/core/styles'; 5 | import { Grid, Typography, NoSsr } from '@material-ui/core'; 6 | 7 | const CenteredGrid = styled(Grid)({ 8 | position: 'relative', 9 | top: '15vh', 10 | }); 11 | 12 | const KawaiiIconWithMargin = styled(KawaiiIcon)({ 13 | marginBottom: 65, 14 | }); 15 | 16 | class Error extends React.Component<{ statusCode: number }> { 17 | static getInitialProps({ res, err }: any) { 18 | const statusCode = res ? res.statusCode : err ? err.statusCode : null; 19 | return { statusCode }; 20 | } 21 | 22 | render() { 23 | const { statusCode } = this.props; 24 | 25 | return ( 26 | 27 | 28 | 29 | 0.33 ? 'sad' : 'shocked'} /> 30 | 31 | 32 | 33 | Error {statusCode} 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | } 41 | 42 | export default Error; 43 | -------------------------------------------------------------------------------- /docs/pages/demo/datepicker/BasicDatePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { DatePicker } from '@material-ui/pickers'; 4 | 5 | export default function BasicDatePicker() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | setValue(newValue)} 13 | renderInput={(props) => } 14 | /> 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /docs/pages/demo/datepicker/CustomInput.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { styled } from '@material-ui/core/styles'; 3 | import { DesktopDatePicker } from '@material-ui/pickers'; 4 | 5 | const InputContainer = styled('div')({ 6 | display: 'flex', 7 | alignItems: 'center', 8 | }); 9 | 10 | export default function CustomInput() { 11 | const [value, setValue] = React.useState(new Date()); 12 | 13 | return ( 14 | setValue(newValue)} 18 | renderInput={({ inputRef, inputProps, InputProps }) => ( 19 | 20 | 21 | {InputProps?.endAdornment} 22 | 23 | )} 24 | /> 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /docs/pages/demo/datepicker/DatePickers.example.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-underscore-dangle */ 2 | import React from 'react'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import { MobileDatePicker, DesktopDatePicker, DatePicker } from '@material-ui/pickers'; 5 | 6 | export default function DatePickersVariants(demoProps: any) { 7 | const [value, setValue] = React.useState(new Date()); 8 | 9 | return ( 10 | 11 | setValue(newValue)} 21 | renderInput={(props) => } 22 | /> 23 | setValue(newValue)} 28 | renderInput={(props) => } 29 | /> 30 | setValue(newValue)} 37 | renderInput={(props) => } 38 | /> 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /docs/pages/demo/datepicker/StaticDatePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import isWeekend from 'date-fns/isWeekend'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import { StaticDatePicker } from '@material-ui/pickers'; 5 | import { makeJSDateObject } from '../../../utils/helpers'; 6 | 7 | function disableWeekends(date: Date) { 8 | // TODO: replace with implementation for your date library 9 | return isWeekend(makeJSDateObject(date)); 10 | } 11 | 12 | export default function StaticDatePickerExample() { 13 | const [value, setValue] = React.useState(new Date()); 14 | 15 | return ( 16 | 17 | setValue(newValue)} 22 | renderInput={(props) => } 23 | /> 24 | setValue(newValue)} 31 | renderInput={(props) => } 32 | /> 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /docs/pages/demo/datepicker/ViewsDatePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { DatePicker, MobileDatePicker } from '@material-ui/pickers'; 4 | 5 | export default function YearDatePicker() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | setValue(newValue)} 15 | renderInput={(props) => } 16 | /> 17 | setValue(newValue)} 24 | renderInput={(props) => } 25 | /> 26 | setValue(newValue)} 32 | renderInput={(props) => } 33 | /> 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/BasicDateRangePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { DateRangePicker, DateRange, DateRangeDelimiter } from '@material-ui/pickers'; 4 | 5 | export default function BasicDateRangePicker() { 6 | const [value, setValue] = React.useState>([null, null]); 7 | 8 | return ( 9 | setValue(newValue)} 14 | renderInput={(startProps, endProps) => ( 15 | 16 | 17 | to 18 | 19 | 20 | )} 21 | /> 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Grid from '@material-ui/core/Grid'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import TextField from '@material-ui/core/TextField'; 5 | import { DateRangePicker, DateRangeDelimiter, DateRange } from '@material-ui/pickers'; 6 | 7 | export default function CalendarsDateRangePicker() { 8 | const [value, setValue] = React.useState>([null, null]); 9 | 10 | return ( 11 | 12 | 1 calendar 13 | setValue(newValue)} 17 | renderInput={(startProps, endProps) => ( 18 | 19 | 20 | to 21 | 22 | 23 | )} 24 | /> 25 | 2 calendars 26 | setValue(newValue)} 30 | renderInput={(startProps, endProps) => ( 31 | 32 | 33 | to 34 | 35 | 36 | )} 37 | /> 38 | 3 calendars 39 | setValue(newValue)} 43 | renderInput={(startProps, endProps) => ( 44 | 45 | 46 | to 47 | 48 | 49 | )} 50 | /> 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/CustomRangeInputs.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { DateRangePicker, DateRange } from '@material-ui/pickers'; 3 | 4 | export default function CustomRangeInputs() { 5 | const [selectedDate, handleDateChange] = React.useState>([null, null]); 6 | 7 | return ( 8 | handleDateChange(date)} 12 | renderInput={(startProps, endProps) => ( 13 | 14 | } 16 | {...startProps.inputProps} 17 | /> 18 | } {...endProps.inputProps} /> 19 | 20 | )} 21 | /> 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import addWeeks from 'date-fns/addWeeks'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import { Dayjs } from 'dayjs'; 5 | import { Moment } from 'moment'; 6 | import { DateTime } from 'luxon'; 7 | import { DateRangePicker, DateRangeDelimiter, DateRange } from '@material-ui/pickers'; 8 | // TODO remove relative import 9 | import { makeJSDateObject } from '../../../utils/helpers'; 10 | 11 | function getWeeksAfter(date: Moment | DateTime | Dayjs | Date, amount: number) { 12 | // TODO: replace with implementation for your date library 13 | return date ? addWeeks(makeJSDateObject(date), amount) : undefined; 14 | } 15 | 16 | export default function MinMaxDateRangePicker() { 17 | const [value, setValue] = React.useState>([null, null]); 18 | 19 | return ( 20 | setValue(newValue)} 26 | renderInput={(startProps, endProps) => ( 27 | 28 | 29 | to 30 | 31 | 32 | )} 33 | /> 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/ResponsiveDateRangePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { 4 | MobileDateRangePicker, 5 | DateRangeDelimiter, 6 | DesktopDateRangePicker, 7 | DateRange, 8 | } from '@material-ui/pickers'; 9 | 10 | export default function ResponsiveDateRangePicker() { 11 | const [value, setValue] = React.useState>([null, null]); 12 | 13 | return ( 14 | 15 | setValue(newValue)} 19 | renderInput={(startProps, endProps) => ( 20 | 21 | 22 | to 23 | 24 | 25 | )} 26 | /> 27 | setValue(newValue)} 31 | renderInput={(startProps, endProps) => ( 32 | 33 | 34 | to 35 | 36 | 37 | )} 38 | /> 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /docs/pages/demo/daterangepicker/StaticDateRangePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { StaticDateRangePicker, DateRangeDelimiter, DateRange } from '@material-ui/pickers'; 4 | 5 | export default function StaticDateRangePickerExample() { 6 | const [value, setValue] = React.useState>([null, null]); 7 | 8 | return ( 9 | 10 | setValue(newValue)} 14 | renderInput={(startProps, endProps) => ( 15 | 16 | 17 | to 18 | 19 | 20 | )} 21 | /> 22 | setValue(newValue)} 26 | renderInput={(startProps, endProps) => ( 27 | 28 | 29 | to 30 | 31 | 32 | )} 33 | /> 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /docs/pages/demo/datetime-picker/BasicDateTimePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { DateTimePicker } from '@material-ui/pickers'; 4 | 5 | export default function BasicDateTimePicker() { 6 | const [selectedDate, handleDateChange] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | } 12 | label="DateTimePicker" 13 | value={selectedDate} 14 | onChange={handleDateChange} 15 | /> 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /docs/pages/demo/datetime-picker/CustomDateTimePicker.example.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-underscore-dangle, no-console */ 2 | import * as React from 'react'; 3 | import AlarmIcon from '@material-ui/icons/Alarm'; 4 | import SnoozeIcon from '@material-ui/icons/Snooze'; 5 | import TextField from '@material-ui/core/TextField'; 6 | import ClockIcon from '@material-ui/icons/AccessTime'; 7 | import { DateTimePicker, MobileDateTimePicker } from '@material-ui/pickers'; 8 | 9 | export default function CustomDateTimePicker(demoProps: any) { 10 | const [clearedDate, setClearedDate] = React.useState(null); 11 | const [value, setValue] = React.useState(new Date('2019-01-01T18:54')); 12 | 13 | return ( 14 | 15 | setValue(newValue)} 23 | minDate={new Date('2018-01-01')} 24 | leftArrowIcon={} 25 | rightArrowIcon={} 26 | leftArrowButtonText="Open previous month" 27 | rightArrowButtonText="Open next month" 28 | openPickerIcon={} 29 | minTime={new Date(0, 0, 0, 9)} 30 | maxTime={new Date(0, 0, 0, 20)} 31 | renderInput={(props) => ( 32 | 33 | )} 34 | /> 35 | setValue(newValue)} 38 | label="With error handler" 39 | onError={console.log} 40 | minDate={new Date('2018-01-01T00:00')} 41 | inputFormat={demoProps.__willBeReplacedGetFormatString({ 42 | moment: 'YYYY/MM/DD hh:mm A', 43 | dateFns: 'yyyy/MM/dd hh:mm a', 44 | })} 45 | mask="___/__/__ __:__ _M" 46 | renderInput={(props) => } 47 | /> 48 | setClearedDate(newValue)} 52 | renderInput={(props) => } 53 | /> 54 | 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /docs/pages/demo/datetime-picker/DateTimePickers.example.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-underscore-dangle, no-console */ 2 | import * as React from 'react'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import { MobileDateTimePicker, DesktopDateTimePicker, DateTimePicker } from '@material-ui/pickers'; 5 | 6 | export default function DateTimePickerDemo(demoProps: any) { 7 | const [value, setValue] = React.useState(new Date('2018-01-01T00:00:00.000Z')); 8 | 9 | return ( 10 | 11 | setValue(newValue)} 15 | label="24h clock" 16 | renderInput={(props) => } 17 | /> 18 | setValue(newValue)} 24 | renderInput={(props) => } 25 | /> 26 | } 28 | ampm={false} 29 | disablePast 30 | value={value} 31 | onChange={(newValue) => setValue(newValue)} 32 | onError={console.log} 33 | disableMaskedInput 34 | inputFormat={demoProps.__willBeReplacedGetFormatString({ 35 | moment: 'YYYY/MM/DD HH:mm', 36 | dateFns: 'yyyy/MM/dd HH:mm', 37 | })} 38 | /> 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /docs/pages/demo/datetime-picker/DateTimeValidation.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { DateTimePicker } from '@material-ui/pickers'; 4 | 5 | export default function DateTimePickerValidation() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | } 12 | label="Ignore date and time" 13 | value={value} 14 | onChange={(newValue) => setValue(newValue)} 15 | minDateTime={new Date()} 16 | /> 17 | } 19 | label="Ignore time in each day" 20 | value={value} 21 | onChange={(newValue) => setValue(newValue)} 22 | minDate={new Date('2020-02-14')} 23 | minTime={new Date(0, 0, 0, 8)} 24 | maxTime={new Date(0, 0, 0, 18, 45)} 25 | /> 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /docs/pages/demo/datetime-picker/index.mdx: -------------------------------------------------------------------------------- 1 | import Ad from '_shared/Ad'; 2 | import Example from '_shared/Example'; 3 | import PageMeta from '_shared/PageMeta'; 4 | import LinkedComponents from '_shared/LinkedComponents'; 5 | 6 | import * as BasicDateTimePicker from './BasicDateTimePicker.example'; 7 | import * as DateTimePickers from './DateTimePickers.example'; 8 | import * as CustomDateTimePicker from './CustomDateTimePicker.example'; 9 | import * as DateTimeValidation from './DateTimeValidation.example'; 10 | 11 | 12 | 13 | ## Date & Time picker 14 | 15 | This component combines date & time pickers. It allows to select both date and time with the same control. 16 | 17 | **Note:** This component is not listed in [material design guidelines](https://material.io/components/) 18 | 19 | 20 | 21 | #### Basic usage 22 | 23 | Allows choosing date then time. There are too many views, so tabs are required to visually distinguish date/time steps. 24 | 25 | 26 | 27 | #### Responsiveness 28 | 29 | The date time picker component is designed and optimized for the device it runs on. 30 | 31 | - The "Mobile" version works best for touch devices and small screens. 32 | - The "Desktop" version works best for mouse devices and large screens. 33 | 34 | By default, the `DateTimePicker` component uses a `@media (pointer: fine)` media query to determine which version to use. 35 | This can be customized by `desktopModeMediaQuery` prop. 36 | 37 | 38 | 39 | #### Date & Time validation 40 | 41 | It is possible to restrict date and time selection in two ways: 42 | 43 | - using `minDateTime`/`maxDateTime`, you can restrict time selection before or after a particular moment in time 44 | - using `minTime`/`maxTime`, you can disable selecting times before or after a certain time each day respectively 45 | 46 | 47 | 48 | #### Customization 49 | 50 | Here are some examples of heavily customized date & time pickers 51 | 52 | 53 | 54 | #### API 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/BasicTimePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { TimePicker } from '@material-ui/pickers'; 4 | 5 | export default function BasicTimePicker() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | } 12 | label="12 hours" 13 | value={value} 14 | onChange={(newValue) => setValue(newValue)} 15 | /> 16 | } 18 | ampm={false} // This is not needed if you are using localization 19 | label="24 hours" 20 | value={value} 21 | onChange={(newValue) => setValue(newValue)} 22 | /> 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/SecondsTimePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { TimePicker } from '@material-ui/pickers'; 4 | 5 | export default function SecondsTimePicker() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | } 12 | ampm={false} 13 | openTo="hours" 14 | views={['hours', 'minutes', 'seconds']} 15 | inputFormat="HH:mm:ss" 16 | mask="__:__:__" 17 | label="With seconds" 18 | value={value} 19 | onChange={(newValue) => setValue(newValue)} 20 | /> 21 | } 23 | ampmInClock 24 | openTo="minutes" 25 | views={['minutes', 'seconds']} 26 | inputFormat="mm:ss" 27 | mask="__:__" 28 | label="Minutes and seconds" 29 | value={value} 30 | onChange={(newValue) => setValue(newValue)} 31 | /> 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/StaticTimePicker.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { StaticTimePicker } from '@material-ui/pickers'; 4 | 5 | export default function StaticTimePickerExample() { 6 | const [value, setValue] = React.useState(new Date()); 7 | 8 | return ( 9 | 10 | setValue(newValue)} 14 | renderInput={(props) => } 15 | /> 16 | setValue(newValue)} 22 | renderInput={(props) => } 23 | /> 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/TimePickers.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { TimePicker, MobileTimePicker, DesktopTimePicker } from '@material-ui/pickers'; 4 | 5 | export default function TimePickers() { 6 | const [value, setValue] = React.useState(new Date('2018-01-01T00:00:00.000Z')); 7 | 8 | return ( 9 | 10 | setValue(newValue)} 15 | renderInput={(props) => } 16 | /> 17 | setValue(newValue)} 23 | renderInput={(props) => } 24 | /> 25 | {/* Alternative way to show am/pm */} 26 | } 36 | /> 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/TimeValidation.example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import TextField from '@material-ui/core/TextField'; 3 | import { TimePicker } from '@material-ui/pickers'; 4 | 5 | export default function TimeValidation() { 6 | const [value, setValue] = React.useState(new Date('2020-01-01 12:00')); 7 | 8 | return ( 9 | 10 | } 12 | value={value} 13 | onChange={(newValue) => setValue(newValue)} 14 | minTime={new Date(0, 0, 0, 8)} 15 | maxTime={new Date(0, 0, 0, 18, 45)} 16 | /> 17 | } 19 | ampm={false} 20 | label="24 hours" 21 | minTime={new Date(0, 0, 0, 8)} 22 | maxTime={new Date(0, 0, 0, 18, 45)} 23 | value={value} 24 | onChange={(newValue) => setValue(newValue)} 25 | /> 26 | } 28 | ampm={false} 29 | label="Disable odd hours" 30 | value={value} 31 | onChange={(newValue) => setValue(newValue)} 32 | shouldDisableTime={(timeValue, clockType) => { 33 | if (clockType === 'hours' && timeValue % 2) { 34 | return true; 35 | } 36 | 37 | return false; 38 | }} 39 | /> 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /docs/pages/demo/timepicker/index.mdx: -------------------------------------------------------------------------------- 1 | import Ad from '_shared/Ad'; 2 | import Example from '_shared/Example'; 3 | import PageMeta from '_shared/PageMeta'; 4 | import LinkedComponents from '_shared/LinkedComponents'; 5 | import { Hidden } from '@material-ui/core'; 6 | 7 | import * as TimeValidation from './TimeValidation.example'; 8 | import * as BasicTimePicker from './BasicTimePicker.example'; 9 | import * as TimePickers from './TimePickers.example'; 10 | import * as StaticTimePicker from './StaticTimePicker.example'; 11 | import * as SecondsTimePicker from './SecondsTimePicker.example'; 12 | 13 | 14 | 15 | ## Time Picker 16 | 17 | Time pickers let user select a single time (in the hours:minutes format). 18 | The selected time is indicated by the filled circle at the end of the clock hand. 19 | 20 | 21 | 22 | #### Basic usage 23 | 24 | A time picker should adjust to a user’s preferred time setting, i.e. the 12-hour or 24-hour format. 25 | 26 | 27 | 28 | #### Responsiveness 29 | 30 | The time picker component is designed and optimized for the device it runs on. 31 | 32 | - The "Mobile" version works best for touch devices and small screens. 33 | - The "Desktop" version works best for mouse devices and large screens. 34 | 35 | By default, the `TimePicker` component uses a `@media (pointer: fine)` media query to determine which version to use. 36 | This can be customized by `desktopModeMediaQuery` prop. 37 | 38 | 39 | 40 | #### Time Validation 41 | 42 | 43 | 44 | #### Static mode 45 | 46 | It is possible to render any picker inline. This will be really helpful to build custom popover/modal containers. 47 | For that use `variant="static"`. 48 | 49 | 50 | 51 | 52 | 53 | #### Seconds 54 | 55 | Seconds input can be used for selection of a precise time point. 56 | 57 | 58 | 59 | #### API 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/pages/getting-started/installation.mdx: -------------------------------------------------------------------------------- 1 | import PageMeta from '../../_shared/PageMeta'; 2 | 3 | 7 | 8 | ## Installation 9 | 10 | Material UI Pickers is available as an [npm package](https://www.npmjs.com/package/@material-ui/pickers): 11 | 12 | ``` 13 | npm i @material-ui/pickers 14 | 15 | yarn add @material-ui/pickers 16 | ``` 17 | 18 | #### Peer Library 19 | 20 | `@material-ui/pickers` was designed to use the date management library of your choice. 21 | We are providing interfaces for [date-fns 2](https://date-fns.org/), [luxon](https://moment.github.io/luxon/), [dayjs](https://github.com/iamkun/dayjs) and [moment](https://momentjs.com/). 22 | 23 | ``` 24 | npm i date-fns 25 | // or 26 | npm i moment 27 | // or 28 | npm i luxon 29 | // or 30 | npm i dayjs 31 | ``` 32 | 33 | Tell pickers which date management library it should use with `LocalizationProvider`. This component takes a `dateAdapter` 34 | prop, and makes it available down the React tree thanks to [React Context](https://reactjs.org/docs/context.html). It should 35 | be used at the root of your component tree, or at the highest level you wish the pickers to be available. 36 | 37 | ```jsx 38 | import { LocalizationProvider } from '@material-ui/pickers'; 39 | 40 | // pick an adapter for your date library 41 | import MomentUtils from '@material-ui/pickers/adapter/moment'; 42 | import DateFnsUtils from '@material-ui/pickers/adapter/date-fns'; 43 | import LuxonUtils from '@material-ui/pickers/adapter/luxon'; 44 | 45 | function App() { 46 | return ( 47 | 48 | 49 | 50 | ); 51 | } 52 | 53 | ReactDOM.render(, document.querySelector('#app')); 54 | ``` 55 | 56 | It is also possible to pass the [date adapter directly to the picker](/guides/date-adapter-passing) and avoid using context, 57 | but please use this possibility wisely. 58 | -------------------------------------------------------------------------------- /docs/pages/getting-started/parsing.mdx: -------------------------------------------------------------------------------- 1 | import Ad from '_shared/Ad'; 2 | import PageMeta from '_shared/PageMeta'; 3 | 4 | 5 | 6 | ## Parsing dates 7 | 8 | Material UI Pickers relies on the date management library when the date should be parsed. Any other prop-types that accepts dates (e.g. `minDate`, `maxDate`) it can take string, number, Date object and so on. 9 | 10 | 11 | 12 | Find more information about parsing dates in the documentation for your library: 13 | 14 | - [date-fns](https://date-fns.org/v2.19.0/docs/parse) 15 | - [dayjs](https://day.js.org/docs/en/parse/parse) 16 | - [luxon](https://moment.github.io/luxon/docs/manual/parsing.html) 17 | - [moment](https://momentjs.com/docs/#/parsing/) 18 | 19 | P.S.: Pass any value to the picker, and if it won't be parsed as expected feel free to open an issue 20 | on [GitHub](https://github.com/mui-org/material-ui-pickers) 😎 21 | -------------------------------------------------------------------------------- /docs/pages/getting-started/usage.mdx: -------------------------------------------------------------------------------- 1 | import Ad from '_shared/Ad'; 2 | import PageMeta from '_shared/PageMeta'; 3 | import { NoSsr } from '@material-ui/core'; 4 | import { CODESANDBOX_EXAMPLE_ID } from '_constants'; 5 | 6 | 7 | 8 | ## Usage 9 | 10 | @material-ui/pickers relies only on material-ui controls and the date management library of your choice. Please note that all components are controlled, meaning that it's required to pass the `value` and `onChange` props. 11 | 12 | 13 | 14 | #### Quick start 15 | 16 | **Note** `onChange` has a second parameter. So if you will not do `onChange={date => handleDateChange(date)}` you will get the console warning that [useState hook does not accept a second callback argument.](https://github.com/facebook/react/issues/14174) 17 | 18 | ```jsx 19 | import * as React from 'react'; 20 | import DateFnsAdapter from '@material-ui/pickers/adapter/date-fns'; // choose your lib 21 | import { DatePicker, TimePicker, DateTimePicker, LocalizationProvider } from '@material-ui/pickers'; 22 | 23 | function App() { 24 | const [selectedDate, handleDateChange] = React.useState(new Date()); 25 | 26 | return ( 27 | 28 | } 30 | value={selectedDate} 31 | onChange={(date) => handleDateChange(date)} 32 | /> 33 | } 35 | value={selectedDate} 36 | onChange={(date) => handleDateChange(date)} 37 | /> 38 | } 40 | value={selectedDate} 41 | onChange={(date) => handleDateChange(date)} 42 | /> 43 | 44 | ); 45 | } 46 | ``` 47 | 48 | 49 |