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

Datepicker defaultProps refactoring #1821

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
444 changes: 226 additions & 218 deletions src/components/ui/calendar/baseCalendar.component.tsx

Large diffs are not rendered by default.

103 changes: 64 additions & 39 deletions src/components/ui/calendar/calendar.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { DateService, NativeDateService } from '@ui-kitten/components';
import React from 'react';
import {
styled,
Expand All @@ -12,9 +13,10 @@ import {
import {
BaseCalendarComponent,
BaseCalendarProps,
BaseCalendarRef,
} from './baseCalendar.component';
import { CalendarPickerCellProps } from './components/picker/calendarPickerCell.component';
import { DateBatch } from './service/calendarData.service';
import { CalendarDataService, DateBatch } from './service/calendarData.service';

export interface CalendarProps<D = Date> extends StyledComponentProps, BaseCalendarProps<D> {
date?: D;
Expand All @@ -23,6 +25,10 @@ export interface CalendarProps<D = Date> extends StyledComponentProps, BaseCalen

export type CalendarElement<D = Date> = React.ReactElement<CalendarProps<D>>;

export type CalendarRef<D = Date> = BaseCalendarRef<D> & {
dataService: CalendarDataService<D>;
};

/**
* Calendar provides a simple way to select a date.
*
Expand Down Expand Up @@ -127,54 +133,73 @@ export type CalendarElement<D = Date> = React.ReactElement<CalendarProps<D>>;
* @overview-example CalendarTheming
* Styling of the calendar is possible with [configuring a custom theme](guides/branding).
*/

@styled('Calendar')
export class Calendar<D = Date> extends BaseCalendarComponent<CalendarProps<D>, D> {

constructor(props: CalendarProps<D>) {
super(props);

this.createDates = this.createDates.bind(this);
this.selectedDate = this.selectedDate.bind(this);
this.onDateSelect = this.onDateSelect.bind(this);
this.isDateSelected = this.isDateSelected.bind(this);
this.shouldUpdateDate = this.shouldUpdateDate.bind(this);
}

// BaseCalendarComponent

protected createDates(date: D): DateBatch<D> {
return this.dataService.createDayPickerData(date);
}

protected selectedDate(): D | undefined {
return this.props.date;
}

protected onDateSelect(date: D): void {
this.props.onSelect?.(date);
}

protected isDateSelected(date: D): boolean {
return this.dateService.isSameDaySafe(date, this.selectedDate());
}

protected shouldUpdateDate(props: CalendarPickerCellProps<D>, nextProps: CalendarPickerCellProps<D>): boolean {
const dateChanged: boolean = this.dateService.compareDatesSafe(props.date.date, nextProps.date.date) !== 0;
function Calendar <D = Date> (
props: CalendarProps<D>,
ref: React.RefObject<CalendarRef<D>>,
): CalendarElement<D> {
const dateService = props.dateService ?? new NativeDateService() as unknown as DateService<D>;
const dataService: CalendarDataService<D> = new CalendarDataService(dateService);

React.useImperativeHandle(ref, () => ({
...ref.current,
dataService,
}), [dataService]);

const createDates = (date: D): DateBatch<D> => {
return dataService.createDayPickerData(date);
};

const selectedDate = (): D | undefined => {
return props.date;
};

const onDateSelect = (date: D): void => {
props.onSelect?.(date);
};

const isDateSelected = (date: D): boolean => {
return dateService.isSameDaySafe(date, selectedDate());
};

const shouldUpdateDate = (prevProps: CalendarPickerCellProps<D>, nextProps: CalendarPickerCellProps<D>): boolean => {
const dateChanged: boolean = dateService.compareDatesSafe(
prevProps.date.date,
nextProps.date.date,
) !== 0;

if (dateChanged) {
return true;
}

const selectionChanged: boolean = props.selected !== nextProps.selected;
const disablingChanged: boolean = props.disabled !== nextProps.disabled;
const selectionChanged: boolean = prevProps.selected !== nextProps.selected;
const disablingChanged: boolean = prevProps.disabled !== nextProps.disabled;

const value: boolean = selectionChanged || disablingChanged;

if (value) {
return true;
}

return props.eva.theme !== nextProps.eva.theme;
}
return prevProps.eva.theme !== nextProps.eva.theme;
};

return (
<BaseCalendarComponent
{...props}
dateService={dateService}
dataService={dataService}
ref={ref}
createDates={createDates}
selectedDate={selectedDate}
onDateSelect={onDateSelect}
isDateSelected={isDateSelected}
shouldUpdateDate={shouldUpdateDate}
/>
);
}

const component = styled('Calendar')(React.forwardRef(Calendar));

export {
component as Calendar,
};
22 changes: 11 additions & 11 deletions src/components/ui/calendar/calendar.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import { ApplicationProvider } from '../../theme';
import {
Calendar,
CalendarProps,
CalendarProps, CalendarRef,
} from './calendar.component';
import { CalendarViewModes } from './type';
import { MomentDateService } from '@ui-kitten/moment';
Expand All @@ -46,7 +46,7 @@ describe('@calendar: component checks', () => {

const TestCalendar = React.forwardRef((
props: Partial<CalendarProps<Date | Moment>>,
ref: React.Ref<Calendar>,
ref: React.Ref<CalendarRef>,
) => {

const [date, setDate] = React.useState<Date | Moment>(props.date);
Expand Down Expand Up @@ -125,7 +125,7 @@ describe('@calendar: component checks', () => {
});

it('should be rendered with view passed to startView prop', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
render(
<TestCalendar
ref={componentRef}
Expand All @@ -137,7 +137,7 @@ describe('@calendar: component checks', () => {
});

it('should change month to next when navigation button pressed', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
const component = render(
<TestCalendar ref={componentRef} />,
);
Expand All @@ -153,7 +153,7 @@ describe('@calendar: component checks', () => {
});

it('should change month to previous when navigation button pressed', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
const component = render(
<TestCalendar ref={componentRef} />,
);
Expand All @@ -169,7 +169,7 @@ describe('@calendar: component checks', () => {
});

it('should change year to next when navigation button pressed', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
const component = render(
<TestCalendar
ref={componentRef}
Expand All @@ -189,7 +189,7 @@ describe('@calendar: component checks', () => {
});

it('should change year to previous when navigation button pressed', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
const component = render(
<TestCalendar
ref={componentRef}
Expand All @@ -210,7 +210,7 @@ describe('@calendar: component checks', () => {

it('should show the selected date on load provided by date prop', () => {
const date = new Date(2021, 2, 1);
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
render(
<TestCalendar
ref={componentRef}
Expand All @@ -225,7 +225,7 @@ describe('@calendar: component checks', () => {

it('should show the specific date on load provided by initialVisibleDate prop', () => {
const initialDate = new Date(2021, 2, 1);
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
render(
<TestCalendar
ref={componentRef}
Expand All @@ -240,7 +240,7 @@ describe('@calendar: component checks', () => {
});

it('should scroll to current month when scrollToToday called', () => {
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
render(
<TestCalendar
ref={componentRef}
Expand All @@ -255,7 +255,7 @@ describe('@calendar: component checks', () => {

it('should scroll to the specific date when scrollToDate called', () => {
const dateToScroll = new Date(2021, 2, 1);
const componentRef = React.createRef<Calendar>();
const componentRef = React.createRef<CalendarRef>();
render(
<TestCalendar
ref={componentRef}
Expand Down
106 changes: 62 additions & 44 deletions src/components/ui/calendar/rangeCalendar.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { DateService, NativeDateService } from '@ui-kitten/components';
import React from 'react';
import {
styled,
Expand All @@ -12,9 +13,10 @@ import {
import {
BaseCalendarComponent,
BaseCalendarProps,
BaseCalendarRef,
} from './baseCalendar.component';
import { CalendarPickerCellProps } from './components/picker/calendarPickerCell.component';
import { DateBatch } from './service/calendarData.service';
import { CalendarDataService, DateBatch } from './service/calendarData.service';
import { RangeDateService } from './service/rangeDate.service';
import { CalendarRange } from './type';

Expand All @@ -25,6 +27,8 @@ export interface RangeCalendarProps<D = Date> extends StyledComponentProps, Base

export type RangeCalendarElement<D = Date> = React.ReactElement<RangeCalendarProps<D>>;

export type RangeCalendarRef<D = Date> = BaseCalendarRef<D>;

/**
* Range Calendar provides a simple way to select a date range.
*
Expand Down Expand Up @@ -109,59 +113,53 @@ export type RangeCalendarElement<D = Date> = React.ReactElement<RangeCalendarPro
* }
* ```
*/
@styled('Calendar')
export class RangeCalendar<D = Date> extends BaseCalendarComponent<RangeCalendarProps<D>, D> {

static defaultProps: Partial<RangeCalendarProps> = {
...BaseCalendarComponent.defaultProps,
range: {},
function RangeCalendar <D = Date> (
{
range = {},
...props
}: RangeCalendarProps<D>,
ref: React.RefObject<RangeCalendarRef<D>>,
): RangeCalendarElement {
const dateService = props.dateService ?? new NativeDateService() as unknown as DateService<D>;
const rangeDateService: RangeDateService<D> = new RangeDateService(dateService);
const dataService: CalendarDataService<D> = new CalendarDataService(dateService);

React.useImperativeHandle(ref, () => ({
...ref.current,
dataService,
}), [dataService]);

const createDates = (date: D): DateBatch<D> => {
return dataService.createDayPickerData(date, range);
};

private rangeDateService: RangeDateService<D> = new RangeDateService(this.dateService);

constructor(props: RangeCalendarProps<D>) {
super(props);

this.createDates = this.createDates.bind(this);
this.selectedDate = this.selectedDate.bind(this);
this.onDateSelect = this.onDateSelect.bind(this);
this.isDateSelected = this.isDateSelected.bind(this);
this.shouldUpdateDate = this.shouldUpdateDate.bind(this);
}

// BaseCalendarComponent

protected createDates(date: D): DateBatch<D> {
return this.dataService.createDayPickerData(date, this.props.range);
}

protected selectedDate(): D | undefined {
return this.props.range?.startDate;
}
const selectedDate = (): D | undefined => {
return range.startDate;
};

protected onDateSelect(date: D): void {
if (this.props.onSelect) {
const range: CalendarRange<D> = this.rangeDateService.createRange(this.props.range, date);
this.props.onSelect(range);
const onDateSelect = (date: D): void => {
if (props.onSelect) {
const calendarRange: CalendarRange<D> = rangeDateService.createRange(range, date);
props.onSelect(calendarRange);
}
}
};

protected isDateSelected(): boolean {
const isDateSelected = (): boolean => {
return false;
}
};

protected shouldUpdateDate(props: CalendarPickerCellProps<D>, nextProps: CalendarPickerCellProps<D>): boolean {
const dateChanged: boolean = this.dateService.compareDatesSafe(props.date.date, nextProps.date.date) !== 0;
const shouldUpdateDate = (prevProps: CalendarPickerCellProps<D>, nextProps: CalendarPickerCellProps<D>): boolean => {
const dateChanged: boolean = dateService.compareDatesSafe(prevProps.date.date, nextProps.date.date) !== 0;

if (dateChanged) {
return true;
}

const selectionChanged: boolean = props.selected !== nextProps.selected;
const disablingChanged: boolean = props.disabled !== nextProps.disabled;
const rangeChanged: boolean = props.range !== nextProps.range;
const rangeStartPlaceChanged: boolean = props.firstRangeItem !== nextProps.firstRangeItem;
const rangeEndPlaceChanged: boolean = props.lastRangeItem !== nextProps.lastRangeItem;
const selectionChanged: boolean = prevProps.selected !== nextProps.selected;
const disablingChanged: boolean = prevProps.disabled !== nextProps.disabled;
const rangeChanged: boolean = prevProps.range !== nextProps.range;
const rangeStartPlaceChanged: boolean = prevProps.firstRangeItem !== nextProps.firstRangeItem;
const rangeEndPlaceChanged: boolean = prevProps.lastRangeItem !== nextProps.lastRangeItem;

const shouldUpdate: boolean =
selectionChanged ||
Expand All @@ -174,6 +172,26 @@ export class RangeCalendar<D = Date> extends BaseCalendarComponent<RangeCalendar
return true;
}

return props.eva.theme !== nextProps.eva.theme;
}
return prevProps.eva.theme !== nextProps.eva.theme;
};

return (
<BaseCalendarComponent
{...props}
dateService={dateService}
dataService={dataService}
ref={ref}
createDates={createDates}
selectedDate={selectedDate}
onDateSelect={onDateSelect}
isDateSelected={isDateSelected}
shouldUpdateDate={shouldUpdateDate}
/>
);
}

const Component = styled('Calendar')(React.forwardRef(RangeCalendar));

export {
Component as RangeCalendar,
};
Loading