Skip to content

Commit

Permalink
'renderStaticRangeLabel' callback prop is added to DefinedRange compo…
Browse files Browse the repository at this point in the history
…nent to enable custom component rendering for static range labels.

-'react-test-renderer' is added to dev dependencies.
-README is updated for 'renderStaticRangeLabel'.
-eslintignore file is updated to ignore snapshot files.
-Existing demo is updated to display custom 'renderStaticRangeLabel' usage.
  • Loading branch information
mortargrind committed Jan 11, 2019
1 parent 2ffa7c8 commit c8ce7bd
Show file tree
Hide file tree
Showing 9 changed files with 417 additions and 9 deletions.
1 change: 1 addition & 0 deletions . eslintignore
@@ -1,3 +1,4 @@
/node_modules/*
/lib/*
/dist/*
**/*.snap
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Expand Up @@ -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 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.

1 change: 1 addition & 0 deletions README.md
Expand Up @@ -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) | -

Expand Down
86 changes: 83 additions & 3 deletions demo/src/components/Main.js
Expand Up @@ -4,6 +4,51 @@ import * as rdrLocales from '../../../src/locale';
import { format, addDays } from 'date-fns';
import Section from './Section';

function renderStaticRangeLabel(staticRange) {
return (
<CustomStaticRangeLabelContent text={'This is a custom label content: '}/>
);
}

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 (
<span>
<i>{text}</i>
<span className={'random-date-string'}>
<b>{currentDateString}</b>
</span>
</span>
);
}
}

const nameMapper = {
ar: 'Arabic (Modern Standard Arabic - Al-fussha)',
bg: 'Bulgarian',
Expand Down Expand Up @@ -135,6 +180,7 @@ export default class Main extends Component {
[which]: payload,
});
}

handleRangeChange(which, payload) {
console.log(which, payload);
this.setState({
Expand Down Expand Up @@ -217,7 +263,7 @@ export default class Main extends Component {
readOnly
value={formatDateDisplay(this.state.multipleRanges.selection1.endDate, 'Continuous')}
/>
<div className={'newLine'} />
<div className={'newLine'}/>

<label className={'label'}>Selection2 Start:</label>
<input
Expand All @@ -231,7 +277,7 @@ export default class Main extends Component {
readOnly
value={formatDateDisplay(this.state.multipleRanges.selection2.endDate, 'Continuous')}
/>
<div className={'newLine'} />
<div className={'newLine'}/>

<label className={'label'}>Selection3 Start:</label>
<input
Expand Down Expand Up @@ -319,9 +365,24 @@ export default class Main extends Component {

<DefinedRange
ranges={[this.state.definedRange.selection]}
renderStaticRangeLabel={renderStaticRangeLabel}
staticRanges={[{
label: "Hoy",
hasCustomRendering: true,
range: () => ({
startDate: new Date(),
endDate: new Date(),
}),
isSelected() {
return (
true
);
},
}]}
onChange={this.handleRangeChange.bind(this, 'definedRange')}
className={'centered'}
/>
>
</DefinedRange>
</Section>
<Section title="RangePicker with disabled dates">
<div>
Expand All @@ -348,6 +409,25 @@ export default class Main extends Component {
disabledDates={[new Date(), addDays(new Date(), 3)]}
minDate={addDays(new Date(), -3)}
/>

<DefinedRange
ranges={[this.state.definedRange.selection]}
renderStaticRangeLabel={renderStaticRangeLabel}
staticRanges={[{
hasCustomRendering: true,
range: () => ({
startDate: new Date(),
endDate: new Date(),
}),
isSelected() {
return (
true
);
},
}]}
onChange={this.handleRangeChange.bind(this, 'definedRange')}
className={'centered'}
/>
</Section>
</main>
);
Expand Down
4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -22,7 +22,8 @@
],
"contributors": [
"Burak Can <neoberg@gmail.com> (https://github.com/burakcan)",
"Mehmet Kamil Morcay <mehmetmorcay@gmail.com> (https://github.com/mkg0)"
"Mehmet Kamil Morcay <mehmetmorcay@gmail.com> (https://github.com/mkg0)",
"Engin Semih Basmacı <semih.basmaci@gmail.com> (https://github.com/mortargrind)"
],
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -73,6 +74,7 @@
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-hot-loader": "^3.1.3",
"react-test-renderer": "16.7.0",
"style-loader": "^0.19.1",
"webpack": "^3.10.0",
"webpack-dev-server": "^2.9.7",
Expand Down
17 changes: 15 additions & 2 deletions src/components/DefinedRange.js
Expand Up @@ -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]];
Expand All @@ -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;
Expand All @@ -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 (
<div className={cx(styles.definedRangesWrapper, className)}>
{this.props.headerContent}
<div className={styles.staticRanges}>
{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 (
<button
type="button"
Expand All @@ -59,7 +71,7 @@ class DefinedRanges extends Component {
this.props.onPreviewChange && this.props.onPreviewChange();
}}>
<span tabIndex={-1} className={styles.staticRangeLabel}>
{staticRange.label}
{labelContent}
</span>
</button>
);
Expand Down Expand Up @@ -106,6 +118,7 @@ DefinedRanges.propTypes = {
headerContent: PropTypes.any,
rangeColors: PropTypes.arrayOf(PropTypes.string),
className: PropTypes.string,
renderStaticRangeLabel: PropTypes.func,
};

DefinedRanges.defaultProps = {
Expand Down
138 changes: 138 additions & 0 deletions src/components/DefinedRange.test.js
@@ -0,0 +1,138 @@
import React from 'react';
import { mount } from 'enzyme';

import DefinedRange from './DefinedRange';
import { isSameDay } from 'date-fns';
import testRenderer from 'react-test-renderer';

describe('DefinedRange tests', () => {
test('Should call "renderStaticRangeLabel" callback correct amount of times according to the "hasCustomRendering" option', () => {
const renderStaticRangeLabel = jest.fn();

mount(
<DefinedRange
staticRanges={[
{
label: 'Dynamic Label',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
hasCustomRendering: true,
},
{
label: 'Static Label',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
},
{
label: 'Hede',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
hasCustomRendering: true,
},
]}
renderStaticRangeLabel={renderStaticRangeLabel}
/>
);

expect(renderStaticRangeLabel).toHaveBeenCalledTimes(2);
});

test('Should render dynamic static label contents correctly', () => {
const renderItalicLabelContent = () => (
<i className={'italic-label-content'}>{'Italic Content'}</i>
);
const renderBoldLabelContent = () => <b className={'bold-label-content'}>{'Bold Content'}</b>;
const renderSomethingElse = () => <img className={'random-image'} />;

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 tree = testRenderer
.create(
<DefinedRange
staticRanges={[
{
id: 'italic',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
hasCustomRendering: true,
},
{
label: 'Static Label',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
},
{
id: 'whatever',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
hasCustomRendering: true,
},
{
id: 'bold',
range: {},
isSelected(range) {
const definedRange = this.range();
return (
isSameDay(range.startDate, definedRange.startDate) &&
isSameDay(range.endDate, definedRange.endDate)
);
},
hasCustomRendering: true,
},
]}
renderStaticRangeLabel={renderStaticRangeLabel}
/>
)
.toJSON();

expect(tree).toMatchSnapshot();
});
});

0 comments on commit c8ce7bd

Please sign in to comment.