diff --git a/. eslintignore b/. eslintignore index c98508c3f..cd275d762 100644 --- a/. eslintignore +++ b/. eslintignore @@ -1,3 +1,4 @@ /node_modules/* /lib/* /dist/* +**/*.snap diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1c3e7c475..f23c2e278 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,13 +10,13 @@ Make sure your issue or feature doesn't have any related issue at [react-date-ra 3. Run `yarn` to install the dependencies. -4. Run `yarn dev` to start development server. +4. Run `yarn run dev` to start development server. ## Building -. Run `run test` and `run lint` for make sure tests passes and linter doesn't throw any error. +. Run `yarn run test` and `yarn run lint` for make sure tests passes and linter doesn't throw any error. -. Run `yarn build` compile the library and demo source. +. Run `yarn run build` compile the library and demo source. . Push your changes and create a PR and apply code review decisions. diff --git a/README.md b/README.md index 485c795c4..fd265a5c4 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ showPreview(DateRange) | bool | true | visibility dragSelectionEnabled(Calendar) | bool | true | whether dates can be selected via drag n drop onPreviewChange(DateRange) | Object | | Callback function for preview changes dateDisplayFormat(DateRange) | String | `MMM D, YYYY` | selected range preview formatter. Check out [date-fns's format option](https://date-fns.org/v2.0.0-alpha.7/docs/format) +renderStaticRangeLabel(`DefinedRange`)| Function | | Callback function to be triggered for the static range configurations that have `hasCustomRendering: true` on them. Instead of rendering `staticRange.label`, return value of this callback will be rendered. staticRanges(`DefinedRange`, `DateRangePicker`) | Array | [default preDefined ranges](https://github.com/Adphorus/react-date-range/blob/master/src/defaultRanges.js) | - inputRanges(`DefinedRange`, `DateRangePicker`) | Array | [default input ranges](https://github.com/Adphorus/react-date-range/blob/master/src/defaultRanges.js) | - diff --git a/demo/src/components/Main.js b/demo/src/components/Main.js index 06e0b5356..feb0a65be 100644 --- a/demo/src/components/Main.js +++ b/demo/src/components/Main.js @@ -4,6 +4,51 @@ import * as rdrLocales from '../../../src/locale'; import { format, addDays } from 'date-fns'; import Section from './Section'; +function renderStaticRangeLabel(staticRange) { + return ( + + ); +} + +class CustomStaticRangeLabelContent extends React.Component { + constructor(props) { + super(props); + + this.state = { + currentDateString: Date(), + }; + + this.intervalId = setInterval( + () => { + this.setState({ + currentDateString: Date(), + }); + }, + 1000 + ); + } + + componentWillUnmount() { + if (this.intervalId) { + clearInterval(this.intervalId); + } + } + + render() { + const { currentDateString } = this.state; + const { text } = this.props; + + return ( + + {text} + + {currentDateString} + + + ); + } +} + const nameMapper = { ar: 'Arabic (Modern Standard Arabic - Al-fussha)', bg: 'Bulgarian', @@ -135,6 +180,7 @@ export default class Main extends Component { [which]: payload, }); } + handleRangeChange(which, payload) { console.log(which, payload); this.setState({ @@ -217,7 +263,7 @@ export default class Main extends Component { readOnly value={formatDateDisplay(this.state.multipleRanges.selection1.endDate, 'Continuous')} /> -
+
-
+
({ + startDate: new Date(), + endDate: new Date(), + }), + isSelected() { + return ( + true + ); + }, + }]} onChange={this.handleRangeChange.bind(this, 'definedRange')} className={'centered'} - /> + > +
@@ -348,6 +409,25 @@ export default class Main extends Component { disabledDates={[new Date(), addDays(new Date(), 3)]} minDate={addDays(new Date(), -3)} /> + + ({ + startDate: new Date(), + endDate: new Date(), + }), + isSelected() { + return ( + true + ); + }, + }]} + onChange={this.handleRangeChange.bind(this, 'definedRange')} + className={'centered'} + />
); diff --git a/package.json b/package.json index af3f12920..874a09a27 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ ], "contributors": [ "Burak Can (https://github.com/burakcan)", - "Mehmet Kamil Morcay (https://github.com/mkg0)" + "Mehmet Kamil Morcay (https://github.com/mkg0)", + "Engin Semih Basmacı (https://github.com/mortargrind)" ], "license": "MIT", "repository": { diff --git a/src/components/DefinedRange.js b/src/components/DefinedRange.js index 45d2ea774..2d94d686f 100644 --- a/src/components/DefinedRange.js +++ b/src/components/DefinedRange.js @@ -14,6 +14,7 @@ class DefinedRanges extends Component { }; this.handleRangeChange = this.handleRangeChange.bind(this); } + handleRangeChange(range) { const { onChange, ranges, focusedRange } = this.props; const selectedRange = ranges[focusedRange[0]]; @@ -22,6 +23,7 @@ class DefinedRanges extends Component { [selectedRange.key || `range${focusedRange[0] + 1}`]: { ...selectedRange, ...range }, }); } + getSelectedRange(ranges, staticRange) { const focusedRangeIndex = ranges.findIndex(range => { if (!range.startDate || !range.endDate || range.disabled) return false; @@ -30,14 +32,24 @@ class DefinedRanges extends Component { const selectedRange = ranges[focusedRangeIndex]; return { selectedRange, focusedRangeIndex }; } + render() { - const { onPreviewChange, ranges, rangeColors, className } = this.props; + const { onPreviewChange, ranges, renderStaticRangeLabel, rangeColors, className } = this.props; + return (
{this.props.headerContent}
{this.props.staticRanges.map((staticRange, i) => { const { selectedRange, focusedRangeIndex } = this.getSelectedRange(ranges, staticRange); + let labelContent; + + if (staticRange.hasCustomRendering) { + labelContent = renderStaticRangeLabel(staticRange); + } else { + labelContent = staticRange.label; + } + return ( ); @@ -106,6 +118,7 @@ DefinedRanges.propTypes = { headerContent: PropTypes.any, rangeColors: PropTypes.arrayOf(PropTypes.string), className: PropTypes.string, + renderStaticRangeLabel: PropTypes.func, }; DefinedRanges.defaultProps = { diff --git a/src/components/DefinedRange.test.js b/src/components/DefinedRange.test.js new file mode 100644 index 000000000..9e9711c61 --- /dev/null +++ b/src/components/DefinedRange.test.js @@ -0,0 +1,135 @@ +import React from 'react'; +import { mount, shallow } from 'enzyme'; + +import DefinedRange from './DefinedRange'; +import { isSameDay } from 'date-fns'; + +describe('DefinedRange tests', () => { + test('Should call "renderStaticRangeLabel" callback correct amount of times according to the "hasCustomRendering" option', () => { + const renderStaticRangeLabel = jest.fn(); + + mount( + + ); + + expect(renderStaticRangeLabel).toHaveBeenCalledTimes(2); + }); + + test('Should render dynamic static label contents correctly', () => { + const renderItalicLabelContent = () => ( + {'Italic Content'} + ); + const renderBoldLabelContent = () => {'Bold Content'}; + const renderSomethingElse = () => ; + + const renderStaticRangeLabel = function(staticRange) { + let result; + + if (staticRange.id === 'italic') { + result = renderItalicLabelContent(); + } else if (staticRange.id === 'bold') { + result = renderBoldLabelContent(); + } else { + result = renderSomethingElse(); + } + + return result; + }; + + const wrapper = shallow( + + ); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/src/components/__snapshots__/DefinedRange.test.js.snap b/src/components/__snapshots__/DefinedRange.test.js.snap new file mode 100644 index 000000000..1f8b93115 --- /dev/null +++ b/src/components/__snapshots__/DefinedRange.test.js.snap @@ -0,0 +1,1322 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DefinedRange tests Should render dynamic static label contents correctly 1`] = ` +ShallowWrapper { + "length": 1, + Symbol(enzyme.__root__): [Circular], + Symbol(enzyme.__unrendered__): , + Symbol(enzyme.__renderer__): Object { + "batchedUpdates": [Function], + "getNode": [Function], + "render": [Function], + "simulateEvent": [Function], + "unmount": [Function], + }, + Symbol(enzyme.__node__): Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + undefined, +
+ + + + +
, +
+
+ + + days up to today + +
+
+ + + days starting today + +
+
, + undefined, + ], + "className": "rdrDefinedRangesWrapper", + }, + "ref": null, + "rendered": Array [ + undefined, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + , + , + , + ], + "className": "rdrStaticRanges", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": "0", + "nodeType": "host", + "props": Object { + "children": + + Italic Content + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": + Italic Content + , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Italic Content", + "className": "italic-label-content", + }, + "ref": null, + "rendered": "Italic Content", + "type": "i", + }, + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "1", + "nodeType": "host", + "props": Object { + "children": + Static Label + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Static Label", + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": "Static Label", + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "2", + "nodeType": "host", + "props": Object { + "children": + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "random-image", + }, + "ref": null, + "rendered": null, + "type": "img", + }, + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "3", + "nodeType": "host", + "props": Object { + "children": + + Bold Content + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": + Bold Content + , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Bold Content", + "className": "bold-label-content", + }, + "ref": null, + "rendered": "Bold Content", + "type": "b", + }, + "type": "span", + }, + "type": "button", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ +
+ + + days up to today + +
, +
+ + + days starting today + +
, + ], + "className": "rdrInputRanges", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": "0", + "nodeType": "host", + "props": Object { + "children": Array [ + , + + days up to today + , + ], + "className": "rdrInputRange", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "rdrInputRangeInput", + "max": 99999, + "min": 0, + "onBlur": [Function], + "onChange": [Function], + "onFocus": [Function], + "value": "-", + }, + "ref": null, + "rendered": null, + "type": "input", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "days up to today", + "className": undefined, + }, + "ref": null, + "rendered": "days up to today", + "type": "span", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": "1", + "nodeType": "host", + "props": Object { + "children": Array [ + , + + days starting today + , + ], + "className": "rdrInputRange", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "rdrInputRangeInput", + "max": 99999, + "min": 0, + "onBlur": [Function], + "onChange": [Function], + "onFocus": [Function], + "value": "-", + }, + "ref": null, + "rendered": null, + "type": "input", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "days starting today", + "className": undefined, + }, + "ref": null, + "rendered": "days starting today", + "type": "span", + }, + ], + "type": "div", + }, + ], + "type": "div", + }, + undefined, + ], + "type": "div", + }, + Symbol(enzyme.__nodes__): Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + undefined, +
+ + + + +
, +
+
+ + + days up to today + +
+
+ + + days starting today + +
+
, + undefined, + ], + "className": "rdrDefinedRangesWrapper", + }, + "ref": null, + "rendered": Array [ + undefined, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + , + , + , + ], + "className": "rdrStaticRanges", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": "0", + "nodeType": "host", + "props": Object { + "children": + + Italic Content + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": + Italic Content + , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Italic Content", + "className": "italic-label-content", + }, + "ref": null, + "rendered": "Italic Content", + "type": "i", + }, + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "1", + "nodeType": "host", + "props": Object { + "children": + Static Label + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Static Label", + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": "Static Label", + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "2", + "nodeType": "host", + "props": Object { + "children": + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "random-image", + }, + "ref": null, + "rendered": null, + "type": "img", + }, + "type": "span", + }, + "type": "button", + }, + Object { + "instance": null, + "key": "3", + "nodeType": "host", + "props": Object { + "children": + + Bold Content + + , + "className": "rdrStaticRange", + "onClick": [Function], + "onFocus": [Function], + "onMouseLeave": [Function], + "onMouseOver": [Function], + "style": Object { + "color": null, + }, + "type": "button", + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": + Bold Content + , + "className": "rdrStaticRangeLabel", + "tabIndex": -1, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Bold Content", + "className": "bold-label-content", + }, + "ref": null, + "rendered": "Bold Content", + "type": "b", + }, + "type": "span", + }, + "type": "button", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ +
+ + + days up to today + +
, +
+ + + days starting today + +
, + ], + "className": "rdrInputRanges", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": "0", + "nodeType": "host", + "props": Object { + "children": Array [ + , + + days up to today + , + ], + "className": "rdrInputRange", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "rdrInputRangeInput", + "max": 99999, + "min": 0, + "onBlur": [Function], + "onChange": [Function], + "onFocus": [Function], + "value": "-", + }, + "ref": null, + "rendered": null, + "type": "input", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "days up to today", + "className": undefined, + }, + "ref": null, + "rendered": "days up to today", + "type": "span", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": "1", + "nodeType": "host", + "props": Object { + "children": Array [ + , + + days starting today + , + ], + "className": "rdrInputRange", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "className": "rdrInputRangeInput", + "max": 99999, + "min": 0, + "onBlur": [Function], + "onChange": [Function], + "onFocus": [Function], + "value": "-", + }, + "ref": null, + "rendered": null, + "type": "input", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "days starting today", + "className": undefined, + }, + "ref": null, + "rendered": "days starting today", + "type": "span", + }, + ], + "type": "div", + }, + ], + "type": "div", + }, + undefined, + ], + "type": "div", + }, + ], + Symbol(enzyme.__options__): Object { + "adapter": ReactSixteenAdapter { + "options": Object { + "enableComponentDidUpdateOnSetState": true, + }, + }, + }, +} +`;