Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Replace moment #218

Merged
merged 24 commits into from
Feb 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
90cb877
Move all moment specific usages to utils
dmtrKovalenko Feb 13, 2018
fc9402d
Move missing moment usages to utils
dmtrKovalenko Feb 20, 2018
9f2d8fb
Add date-fns utils
dmtrKovalenko Feb 20, 2018
e20ec44
Add date-fns utils, imlement hoc for setting and getting utils from c…
dmtrKovalenko Feb 20, 2018
4245319
Improve utils, fix crashings
dmtrKovalenko Feb 20, 2018
47850ef
Add typings for utils and new components
dmtrKovalenko Feb 20, 2018
bb3051c
Add test setup for moment and date-fns separately, fix failing unit-t…
dmtrKovalenko Feb 20, 2018
46a1938
Fix not imported full componenets in some tests
dmtrKovalenko Feb 20, 2018
2e2db64
Remove console.log
dmtrKovalenko Feb 20, 2018
97ee95e
Change build system to direct import from components name (without src)
dmtrKovalenko Feb 21, 2018
fad69c5
Fix unit tests
dmtrKovalenko Feb 21, 2018
e8e5ec1
Change all moment types to Date or Moment in type defenitions
dmtrKovalenko Feb 21, 2018
1b567fd
Make date type unknown
dmtrKovalenko Feb 21, 2018
3ba037c
Merge pull request #224 from dmtrKovalenko/new-build-system
dmtrKovalenko Feb 22, 2018
dc16540
Merge conflicts
dmtrKovalenko Feb 22, 2018
9d6887c
Fix utils interface typings errors, fix typo in exported MuiPickerUti…
dmtrKovalenko Feb 22, 2018
36fa3e8
Add displaying texts methods to utils
dmtrKovalenko Feb 26, 2018
9d286e1
Merge conflicts
dmtrKovalenko Feb 26, 2018
4b18c46
Reimplement range countings for moment manually, remove moment-range dep
dmtrKovalenko Feb 26, 2018
d2dae09
Change any date type to MaterialUIPickersDate
dmtrKovalenko Feb 26, 2018
d986820
Update Readme.md to match new Utils architecture
dmtrKovalenko Feb 26, 2018
51d34ac
Change moment type defenitions in proptypes table
dmtrKovalenko Feb 26, 2018
51be3bb
Fix typo, comment persian pickers docs section
dmtrKovalenko Feb 28, 2018
0006018
Remove returnMoment prop
dmtrKovalenko Feb 28, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"react/no-find-dom-node": 0,
"no-param-reassign": 0,
"import/no-named-as-default": 0,
"import/no-extraneous-dependencies": 0
"import/no-extraneous-dependencies": 0,
"class-methods-use-this": 0
},
"globals": {
"document": true
Expand Down
76 changes: 36 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,35 @@
Changelog available [here](https://github.com/dmtrKovalenko/material-ui-pickers/releases)

### Installation
Available as npm package. Please note that we are using moment as a peer dependency
Available as npm package.
```sh
npm install moment material-ui-pickers -S
npm install material-ui-pickers -S
```
Now choose the library that pickers will use to work with date. We are providing interfaces for [moment](https://momentjs.com/) and [date-fns](https://date-fns.org/). If you are not using moment in the project (or dont have it in the bundle already) we suggest using date-fns, because it much more lightweight and will be correctly tree-shaked from the bundle.

We are using material-ui-icons font to display icons. Just add this to your html
Teach pickers how to use one of that library using `MuiPickersUtilsProvider`. This component takes an utils property, and makes it available down the React tree thanks to React context. It should preferably be used at the root of your component tree.

```jsx
import { MuiPickersUtilsProvider } from 'material-ui-pickers';
import MomentUtils from 'material-ui-pickers/utils/moment-utils';
import DateFnsUtils from 'material-ui-picker/utils/date-fns-utils'

function App() {
return (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Root />
</MuiPickersUtilsProvider>
);
}

render(<App />, document.querySelector('#app'));
```

We are using material-ui-icons icon font to display icons. Just add this to your html
```html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
```

If you dont want to use icon font, or you are already use `material-ui-icons` you can pass any icon to the components with the following props
* leftArrowIcon - arrow left for datepicker
* rightArrowIcon - arrow right for datepicker
* dateRangeIcon - date tab icon for datetimepicker
* timeIcon - time tab icon for datetimepicker
* keyboardIcon - icon for keyboard end adornmentic
If you dont want to use icon font, or you are already use `material-ui-icons` you can pass any icon to the components with [corresponding props](https://github.com/dmtrKovalenko/material-ui-pickers#props-documentation)

### Usage
Here is a quick example of how to use this package
Expand Down Expand Up @@ -83,12 +96,12 @@ Here is a list of available props
**Note:** Any prop not recognized by the pickers and their sub-components are passed down to material-ui [TextField](https://material-ui-next.com/api/text-field/#props) component.

#### Datepicker
* date - string, number, Date object, Moment object ([anything](https://momentjs.com/docs/#/parsing/), that can be parsed by moment)
* date - string, number, Date object or Moment object (if you are using moment utils)

Prop | Type | Default | Definition
------------ | ------------- | ------------- | -------------
value | date | new Date() | Datepicker value
format | string | 'MMMM Do' | Moment format string for input
format | string | 'MMMM Do' | Format string for input
autoOk | boolean | false | Auto accept date on selection
disablePast | boolean | false | Disable past dates
disableFuture | boolean | false | Disable future dates
Expand All @@ -97,7 +110,6 @@ openToYearSelection | boolean | false | Open datepicker from year selection
minDate | date | '1900-01-01' | Minimum selectable date
maxDate | date | '2100-01-01' | Maximum selectable date
onChange | func | required | Callback firing when date accepted
returnMoment | boolean | true | Will return moment object in onChange
invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed
emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear)
okLabel | string | 'OK' | The label for the ok button
Expand All @@ -123,7 +135,6 @@ value | date | new Date() | Timepicker value
format | string | 'MMMM Do' | Moment format string for input
autoOk | boolean | false | Auto accept time on selection
onChange | func | required | Callback firing when date accepted
returnMoment | boolean | true | Will return moment object in onChange
invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed
emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear)
okLabel | string | 'OK' | The label for the ok button
Expand Down Expand Up @@ -152,7 +163,6 @@ animateYearScrolling | boolean | false | Will animate year selection
minDate | date | '1900-01-01' | Minimum selectable date
maxDate | date | '2100-01-01' | Maximum selectable date
onChange | func | required | Callback firing when date accepted
returnMoment | boolean | true | Will return moment object in onChangeg
invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed
emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear)
okLabel | string | 'OK' | The label for the ok button
Expand All @@ -165,7 +175,7 @@ rightArrowIcon | react node | `<Icon>keyboard_arrow_right</Icon>`| Right arrow i
dateRangeIcon | react node | `<Icon>date_range</Icon>`| Date tab icon
timeIcon | react node | `<Icon>access_time</Icon>`| Time tab icon
ampm | boolean | true | 12h/24h view for hour selection clock
shouldDisableDate | (date: Moment) => boolean | () => false | Allow to disable custom date in calendar
shouldDisableDate | (date: Moment | Date) => boolean | () => false | Allow to disable custom date in calendar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we avoid passing moment object to this callback?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. We are poviding moment for api consistent. Moment utils is a way to use moment in this callback.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if we pass utils as second argument? This will allow data processing

Copy link
Member Author

@dmtrKovalenko dmtrKovalenko Feb 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cherniavskii read my answer to your previous coment :)

keyboard | boolean | false | Allow to manual input date to the text field
keyboardIcon | react node | `<Icon>event</Icon>` | Keyboard adornment icon
maxDateMessage | string | 'Date should not be after maximal date' | Maximum date error message for keyboard input
Expand All @@ -175,15 +185,7 @@ mask | text mask (read more [here](https://github.com/text-mask/text-mask/blob/m
clearable | boolean | false | If `true`, clear button will be displayed
TextFieldComponent | func, string | undefined | Component that should replace the default Material-UI TextField

### l10n
For l10n texts we're currently relying on moment which is stateful. To change the locale you have to import your langauge specific files an change the locale manually via `moment.locale(language)`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to provide at least links to moment/date-fns l10n docs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be a part of next release

```
import moment from 'moment'
import 'moment/locale/fr';

moment.locale('fr')
```

<!-- Delay support of material-ui-pickers probably to rc-2
### Jalali Calendar
We are fully supporting Jalali calendar system and [right-to-left](https://material-ui-next.com/guides/right-to-left/) material-ui api. Special thanks to @alitaheri.
Here is a little example of how to use it
Expand All @@ -195,23 +197,17 @@ npm install material-ui-pickers-jalali-utils
```

```jsx
import { TimePicker, DateTimePicker, DatePicker } from 'material-ui-pickers';
import { MuiPickersUtilsProvider } from 'material-ui-pickers';
import jalaliUtils from 'material-ui-pickers-jalali-utils';

jMoment.loadPersian({ dialect: 'persian-modern', usePersianDigits: true });

<DateTimePicker
okLabel="تأیید"
cancelLabel="لغو"
labelFunc={date => date === null ? '' : jMoment(date).format('jYYYY/jMM/jDD hh:mm A')}
value={selectedDate}
onChange={this.handleDateChange}
utils={jalaliUtils}
/>
```

### Migrate to date-fns?
If you are interested of using moment or date-fns as the peer of this project, please mention that in [this issue](https://github.com/dmtrKovalenko/material-ui-pickers/issues/61), we need to know which library if more useful to be in the peer dependencies of this project. Thank you.
function App() {
return (
<MuiPickersUtilsProvider utils={jalaliUtils}>
<Root />
</MuiPickersUtilsProvider>
);
}
``` -->

### Contributing
For information about how to contribute, see the [CONTRIBUTING](https://github.com/dmtrKovalenko/material-ui-pickers/blob/master/CONTRIBUTING.md) file.
Expand Down
24 changes: 16 additions & 8 deletions docs/src/App.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { MuiThemeProvider, createMuiTheme } from 'material-ui';

import Demo from './Demo/Demo';
import { setPrismTheme } from './utils/prism';
import { MuiPickersUtilsProvider, dateFnsUtils, momentUtils } from 'material-ui-pickers';

import { create } from 'jss';
import preset from 'jss-preset-default';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';

import Demo from './Demo/Demo';
import { setPrismTheme } from './utils/prism';

const jss = create({ plugins: [...preset().plugins, rtl()] });
jss.options.createGenerateClassName = createGenerateClassName;

export default class App extends Component {
static propTypes = {
toggleFrench: PropTypes.func.isRequired,
}

state = {
type: 'light',
direction: 'ltr',
Expand Down Expand Up @@ -50,11 +56,13 @@ export default class App extends Component {
<div className="root">
<JssProvider jss={jss}>
<MuiThemeProvider theme={this.getMuiTheme()}>
<Demo
toggleDirection={this.toggleDirection}
toggleThemeType={this.toggleThemeType}
toggleFrench={this.props.toggleFrench}
/>
<MuiPickersUtilsProvider utils={dateFnsUtils}>
<Demo
toggleDirection={this.toggleDirection}
toggleThemeType={this.toggleThemeType}
toggleFrench={this.props.toggleFrench}
/>
</MuiPickersUtilsProvider>
</MuiThemeProvider>
</JssProvider>
</div>
Expand Down
6 changes: 3 additions & 3 deletions docs/src/Demo/Demo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ class Demo extends Component {
>
<DateTimePickers />
</SourcablePanel>

{/*
<SourcablePanel
title="Custom Day Element"
sourceFile="CustomElements.jsx"
>
<CustomElements />
</SourcablePanel>

<SourcablePanel
<SourcablePanel
title="Persian Pickers"
description={
<p key="persian-desc">
Expand All @@ -123,7 +123,7 @@ class Demo extends Component {
sourceFile="PersianPickers.jsx"
>
<PersianPickers />
</SourcablePanel>
</SourcablePanel> */}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea 👍 I'll update my utils library and fix these demos 👍 👍

</div>
</main>
);
Expand Down
3 changes: 1 addition & 2 deletions docs/src/Demo/Examples/BasicUsage.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, { Fragment, Component } from 'react';
import moment from 'moment';
import { Typography } from 'material-ui';
import { TimePicker, DatePicker } from 'material-ui-pickers';

export default class BasicUsage extends Component {
state = {
selectedDate: moment(),
selectedDate: new Date(),
}

handleDateChange = (date) => {
Expand Down
1 change: 0 additions & 1 deletion docs/src/Demo/Examples/DateTimePickers.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { Fragment, Component } from 'react';
import { DateTimePicker } from 'material-ui-pickers';
import { IconButton, Typography, Icon, InputAdornment } from 'material-ui';
import moment from 'moment';

export default class BasicUsage extends Component {
state = {
Expand Down
4 changes: 2 additions & 2 deletions lib/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
"plugins": [
"transform-object-rest-spread",
"transform-react-jsx",
"transform-class-properties",
"transform-class-properties"
]
},
"production": {
"presets": [[ "es2015", { "modules": false } ]],
"plugins": [
"transform-object-rest-spread",
"transform-react-jsx",
"transform-class-properties",
"transform-class-properties"
]
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/__tests__/DatePicker/Calendar.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import moment from 'moment';
import { shallow } from 'enzyme';
import { shallow } from '../test-utils';
import { Calendar } from '../../src/DatePicker/Calendar';

describe('Calendar', () => {
Expand All @@ -11,7 +11,7 @@ describe('Calendar', () => {
});

it('Should renders', () => {
console.log(component.debug()); // TODO REMOVE ME
// console.log(component.debug());
expect(component).toBeTruthy();
});
});
4 changes: 2 additions & 2 deletions lib/__tests__/DatePicker/CalendarHeader.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import moment from 'moment';
import { shallow } from 'enzyme';
import { shallow } from '../test-utils';
import { CalendarHeader } from '../../src/DatePicker/CalendarHeader';

describe('CalendarHeader', () => {
Expand All @@ -11,7 +11,7 @@ describe('CalendarHeader', () => {
});

it('Should renders', () => {
console.log(component.debug()); // TODO REMOVE ME
// console.log(component.debug());
expect(component).toBeTruthy();
});
});
4 changes: 2 additions & 2 deletions lib/__tests__/DatePicker/DatePicker.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import moment from 'moment';
import { shallow } from 'enzyme';
import { shallow } from '../test-utils';
import { DatePicker } from '../../src/DatePicker/DatePicker';

describe('DatePicker', () => {
Expand All @@ -11,7 +11,7 @@ describe('DatePicker', () => {
});

it('Should renders', () => {
console.log(component.debug()); // TODO REMOVE ME
// console.log(component.debug());
expect(component).toBeTruthy();
});
});
40 changes: 21 additions & 19 deletions lib/__tests__/DatePicker/DatePickerWrapper.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import moment from 'moment';
import DatePickerWrapper from '../../src/DatePicker/DatePickerWrapper';
import { shallow } from '../test-utils';
import { DatePickerWrapper } from '../../src/DatePicker';

const spy = jest.fn();

Expand All @@ -16,30 +16,32 @@ describe('DatePickerWrapper', () => {
let component;

beforeEach(() => {
component = mount(<DatePickerWrapper {...props} />);
component = shallow(<DatePickerWrapper {...props} />);
});

it('Should renders', () => {
// console.log(component.debug()); // TODO REMOVE ME
// console.log(component.debug());
expect(component).toBeTruthy();
});

it('Should support keyboard input', () => {
const input = component.find('input');
input.simulate('change', { target: { value: '2019' } });
// 20.02.2018 -> TODO Move keyboard input tests to the text field

expect(spy).toHaveBeenCalled();
expect(component.state().date.format()).toEqual(moment('2019', 'YYYY').format());
});
// it('Should support keyboard input', () => {
// const input = component.find('input');
// input.simulate('change', { target: { value: '2019' } });

it('Should not pass disabled dates', () => {
component.setProps({
disableFuture: true,
});
const input = component.find('input');
input.simulate('change', { target: { value: '4000' } });
// expect(spy).toHaveBeenCalled();
// expect(component.state().date.format()).toEqual(moment('2019', 'YYYY').format());
// });

expect(spy).toHaveBeenCalled();
expect(component.state().date.format()).toEqual(moment(new Date().getFullYear(), 'YYYY').format());
});
// it('Should not pass disabled dates', () => {
// component.setProps({
// disableFuture: true,
// });
// const input = component.find('input');
// input.simulate('change', { target: { value: '4000' } });

// expect(spy).toHaveBeenCalled();
// expect(component.state().date.format()).toEqual(moment(new Date().getFullYear(), 'YYYY').format());
// });
});
Loading