diff --git a/packages/ui-toolkit/package.json b/packages/ui-toolkit/package.json
index 0f2a4f2f..05a0f43e 100644
--- a/packages/ui-toolkit/package.json
+++ b/packages/ui-toolkit/package.json
@@ -1,6 +1,6 @@
{
"name": "@groww-tech/ui-toolkit",
- "version": "0.4.5",
+ "version": "0.4.6",
"description": "A lightning nature UI",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/Calendar.tsx b/packages/ui-toolkit/src/components/molecules/Calendar/Calendar.tsx
index 87a085b7..91884086 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/Calendar.tsx
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/Calendar.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import MonthCalendar from './MonthCalendar';
import DateCalendar from './DateCalendar';
+import { CalendarProps } from './calendar.types';
export const CALENDAR_TYPE = {
MONTH: 'MONTH',
@@ -22,34 +23,22 @@ const Calendar = (props:Props) => {
const emptyFunction = () => void 0;
- if (type === CALENDAR_TYPE.MONTH) {
-
- return (
-
- );
-
- } else if (type === CALENDAR_TYPE.DATE) {
- return (
-
- );
-
- }
-
- return
;
+ const CalendarComponent = type === CALENDAR_TYPE.MONTH ? MonthCalendar : DateCalendar;
+
+ return (
+
+ );
};
export type Props = {
- type: ValueOf;
-} & Partial>
-& Partial>;
+ type: keyof typeof CALENDAR_TYPE;
+} & CalendarProps;
export default Calendar;
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendar.css b/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendar.css
index 060ecfea..364ccb7b 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendar.css
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendar.css
@@ -5,12 +5,7 @@
cursor: auto;
}
-.cc12YearBox {
- justify-content: space-between;
-}
-
.cc12WeekNameBox {
- justify-content: space-between;
margin-top: 14px;
text-align: center;
}
@@ -32,14 +27,15 @@
.cc12DateNotSelected {}
-.cc12DateSelected {
- background: var(--green500);
-}
-
+/* NOTE: Here below order matters as active, hover state color override */
.cc12DateNotSelected:hover {
background: var(--overlay30);
}
+.cc12DateCurrent {
+ background: var(--green300);
+}
+
.cc12DateRow {
justify-content: space-between;
margin-top: 8px;
@@ -52,4 +48,5 @@
.cc12DisableDate {
opacity: 0.2;
+ cursor: default;
}
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/index.tsx b/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/index.tsx
index 0f04686d..d0a9d769 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/index.tsx
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/index.tsx
@@ -7,7 +7,8 @@ import {
KeyboardDoubleArrowRight
} from '@groww-tech/icon-store/mi';
-import { getDatesArray, getMonthAbbrByIndex } from './dateCalendarUtils';
+import { compareDate, getDatesArray, getMonthAbbrByIndex } from '../calendarUtils';
+import { CalendarProps as Props } from '../calendar.types';
import './dateCalendar.css';
@@ -16,7 +17,7 @@ const WEEK_DAYS = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
class DateCalendar extends React.PureComponent {
static defaultProps = {
- highlightCurrentDate: false,
+ highlightCurrentDate: true,
minDate: null,
maxDate: null
};
@@ -24,12 +25,14 @@ class DateCalendar extends React.PureComponent {
state:State = {
dateToShow: this.props.currentDate,
- dates: getDatesArray(this.props.currentDate)
+ dates: getDatesArray(this.props.currentDate),
+ selectedDate: null
};
componentDidUpdate(prevProps: Props) {
- if (prevProps.currentDate.getDate() != this.props.currentDate.getDate()) {
+
+ if (prevProps.currentDate.getDate() !== this.props.currentDate.getDate()) {
this.setState({
dateToShow: this.props.currentDate,
dates: getDatesArray(this.props.currentDate)
@@ -43,15 +46,9 @@ class DateCalendar extends React.PureComponent {
return (
-
- {this.getYearUI()}
-
-
- {this.getMonthUI()}
-
-
- {this.getDatesUI()}
-
+ {this.getYearUI()}
+ {this.getMonthUI()}
+ {this.getDatesUI()}
);
@@ -60,35 +57,59 @@ class DateCalendar extends React.PureComponent {
getYearUI = () => {
const { dateToShow } = this.state;
+ const maxDate = this.props.maxDate ? new Date(this.props.maxDate) : null;
+ const minDate = this.props.minDate ? new Date(this.props.minDate) : null;
+
+ const hasNextYear = !(maxDate && dateToShow.getFullYear() === maxDate.getFullYear());
+ const hasPrevYear = !(minDate && dateToShow.getFullYear() === minDate.getFullYear());
+ const hasNextMonth = !(maxDate && dateToShow.getMonth() === maxDate.getMonth() && dateToShow.getFullYear() === maxDate.getFullYear());
+ const hasPrevMonth = !(minDate && dateToShow.getMonth() === minDate.getMonth() && dateToShow.getFullYear() === minDate.getFullYear());
+
+ const handlers = {
+ 'PREVIOUS_YEAR': () => {
+ if (hasPrevYear) this.goToPreviousYear();
+ },
+ 'PREVIOUS_MONTH': () => {
+ if (hasPrevMonth) this.goToPreviousMonth();
+ },
+ 'NEXT_MONTH': () => {
+ if (hasNextMonth) this.goToNextMonth();
+ },
+ 'NEXT_YEAR': () => {
+ if (hasNextYear) this.goToNextYear();
+ }
+ };
return (
-
-
-
-
-
-
-
-
-
-
{getMonthAbbrByIndex(dateToShow.getMonth() + 1)} {dateToShow.getFullYear()}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {getMonthAbbrByIndex(dateToShow.getMonth() + 1)} {dateToShow.getFullYear()}
+
+
+
+
+
+
);
@@ -97,74 +118,83 @@ class DateCalendar extends React.PureComponent
{
getMonthUI = () => {
return (
- (
-
- {
- WEEK_DAYS.map(day => (
-
- ))
- }
-
-
)
+
+ {
+ WEEK_DAYS.map((day) => (
+
+ {day}
+
+ ))
+ }
+
);
}
getDatesUI = () => {
- const { dates, dateToShow } = this.state;
+ const { dates, dateToShow, selectedDate } = this.state;
const { minDate, maxDate } = this.props;
return (
-
- {
- dates.map((dateArr, datesArrIndex) => {
- return (
-
- {
- dateArr.map((date) => {
- if (date !== null) {
- const newDate = new Date(dateToShow);
-
- newDate.setDate(date);
-
- const dateSelected = this.isDateSelected(date);
-
- return (
- (
-
this.onDateClick(date)}
- >
- {date}
-
-
)
- );
- }
+ {
+ dates.map((dateArr, datesArrIndex) => {
+
+ return (
+
+ {
+ dateArr.map((date, index) => {
+ if (date !== null) {
+ const newDate = new Date(dateToShow);
+
+ newDate.setDate(date);
+
+ const dateSelected = newDate.getTime() === selectedDate?.getTime();
+ const isDisabled = (minDate && compareDate(minDate, newDate)) || (maxDate && compareDate(newDate, maxDate));
+
+
+ const onClickHandler = () => {
+ if (!isDisabled) this.onDateClick(date);
+ };
return (
-
+
+
+ {date}
+
+
);
- })
- }
-
- );
- })
- }
-
+ }
+
+ // NOTE: Renders the empty date block or date offsets
+ return (
+
+ );
+ })
+ }
+
+ );
+ })
+ }
);
}
@@ -215,46 +245,27 @@ class DateCalendar extends React.PureComponent {
onDateClick = (date: number) => {
- const { minDate, maxDate, onDateChange } = this.props;
+ const { onDateChange } = this.props;
const { dateToShow } = this.state;
const newDate = new Date(dateToShow);
newDate.setDate(date);
- if (minDate && (this.compareDate(minDate, newDate))) {
- return;
- }
-
- if (maxDate && (this.compareDate(newDate, maxDate))) {
- return;
- }
-
onDateChange(newDate);
- }
- /* check date1 is greater than date2 */
- compareDate = (date1: Date, date2: Date) => {
- const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), 0, 0, 0);
- const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), 0, 0, 0);
-
- return d1.getTime() > d2.getTime();
+ this.setState({
+ dateToShow: newDate,
+ selectedDate: newDate
+ });
}
}
-type Props = {
- currentDate: Date;
- onDateChange: (date:Date)=>void;
- highlightCurrentDate: boolean;
- minDate: Date | null;
- maxDate: Date | null;
-};
-
-
type State = {
dateToShow: Date;
dates: (number | null)[][];
+ selectedDate: Date | null;
}
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/index.tsx b/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/index.tsx
index 6911a423..01479958 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/index.tsx
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/index.tsx
@@ -3,61 +3,96 @@ import cn from 'classnames';
import { KeyboardArrowLeft, KeyboardArrowRight } from '@groww-tech/icon-store/mi';
import './monthCalendar.css';
+import { compareDate } from '../calendarUtils';
+import { CalendarProps as Props } from '../calendar.types';
const MONTHS = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
class MonthCalendar extends React.PureComponent {
+ static defaultProps = {
+ highlightCurrentDate: true,
+ minDate: null,
+ maxDate: null
+ };
+
state:State = {
- dateToShow: this.props.currentDate
+ dateToShow: this.props.currentDate,
+ selectedDate: null
};
render() {
- const { dateToShow } = this.state;
- const { currentDate } = this.props;
-
- const currentMonthIndex = currentDate.getMonth();
- const presentDate = new Date();
+ const { dateToShow, selectedDate } = this.state;
+ const maxDate = this.props.maxDate ? new Date(this.props.maxDate) : null;
+ const minDate = this.props.minDate ? new Date(this.props.minDate) : null;
+
+ const hasNextYear = !(maxDate && dateToShow.getFullYear() === maxDate.getFullYear());
+ const hasPrevYear = !(minDate && dateToShow.getFullYear() === minDate.getFullYear());
+
+ const handlers = {
+ 'PREVIOUS_MONTH': () => {
+ if (hasPrevYear) this.goToPreviousYear();
+ },
+ 'NEXT_MONTH': () => {
+ if (hasNextYear) this.goToNextYear();
+ }
+ };
return (
-
-
-
+
+
+
-
{dateToShow.getFullYear()}
-
-
+
{dateToShow.getFullYear()}
+
+
-
+
{
- MONTHS.map((month, index) => (
-
-
presentDate.getMonth()) && (presentDate.getFullYear() === dateToShow.getFullYear()))
- })
- }
- onClick={() => this.onMonthClick(index)}
+ MONTHS.map((month, index) => {
+ const newDate = new Date(dateToShow);
+
+ newDate.setMonth(index);
+ const monthSelected = newDate.getTime() === selectedDate?.getTime();
+ const isDisabled = (minDate && compareDate(minDate, newDate)) || (maxDate && compareDate(newDate, maxDate));
+
+
+ const onClickHandler = () => {
+ if (!isDisabled) this.onMonthClick(index);
+ };
+
+ return (
+
-
- ))
+ );
+ })
}
@@ -66,57 +101,53 @@ class MonthCalendar extends React.PureComponent
{
}
- onMonthClick = (index:number) => {
- const dateToShow = this.state.dateToShow;
- const newDate = new Date(dateToShow.toString());
- const presentDate = new Date();
- const presentMonth = presentDate.getMonth();
+ isMonthSelected = (month: number) => {
+ const { currentDate } = this.props;
+ const { dateToShow } = this.state;
+ const currentMonthIndex = currentDate.getMonth();
- if ((index > presentMonth) && (presentDate.getFullYear() === newDate.getFullYear())) {
- return;
- }
+ return month === currentMonthIndex && currentDate.getFullYear() === dateToShow.getFullYear();
+ }
+
+
+ onMonthClick = (index:number) => {
+ const { onDateChange } = this.props;
+ const { dateToShow } = this.state;
+ const newDate = new Date(dateToShow);
- newDate.setDate(1);
newDate.setMonth(index);
- this.props.onDateChange(newDate);
+ onDateChange(newDate);
this.setState({
- dateToShow: newDate
+ dateToShow: newDate,
+ selectedDate: newDate
});
}
- handlePrevYearClick = () => {
- const dateToShow = this.state.dateToShow;
- const newDate = new Date(dateToShow.toString());
+ goToPreviousYear = () => {
+ const { dateToShow } = this.state;
+ const newDate = new Date(dateToShow);
newDate.setFullYear(dateToShow.getFullYear() - 1);
this.setState({ dateToShow: newDate });
- }
-
+ };
- handleForwardYearClick = () => {
- const dateToShow = this.state.dateToShow;
- if (dateToShow.getFullYear() !== new Date().getFullYear()) {
- const newDate = new Date(dateToShow.toString());
+ goToNextYear = () => {
+ const { dateToShow } = this.state;
+ const newDate = new Date(dateToShow);
- newDate.setFullYear(dateToShow.getFullYear() + 1);
- this.setState({ dateToShow: newDate });
- }
- }
+ newDate.setFullYear(dateToShow.getFullYear() + 1);
+ this.setState({ dateToShow: newDate });
+ };
}
-type Props = {
- currentDate: Date;
- onDateChange: (date:Date) => void;
-};
-
-
type State = {
dateToShow: Date;
+ selectedDate: Date | null;
}
export default MonthCalendar;
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/monthCalendar.css b/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/monthCalendar.css
index 3b3f8444..2f31e09e 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/monthCalendar.css
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/MonthCalendar/monthCalendar.css
@@ -3,10 +3,6 @@
width: 220px;
}
-.mn12YearRow {
- justify-content: space-between;
-}
-
.mn12Month {
text-align: center;
min-width: 33%;
@@ -20,20 +16,25 @@
margin: 3px auto;
}
+/* NOTE: Here below order matters as active, hover state color override */
.mn12MonthBack:hover {
background-color: var(--overlay30);
}
-.mn12MonthTextSelected {
- background-color: var(--green500);
+.mn12MonthCurrent {
+ background-color: var(--green300);
}
.mn12MonthBox {
flex-wrap: wrap;
- justify-content: space-between;
margin-top: 12px;
}
.mn12YearIcon {
font-size: 22px !important;
}
+
+.cc12DisableDate {
+ opacity: 0.2;
+ cursor: default;
+}
\ No newline at end of file
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/calendar.types.ts b/packages/ui-toolkit/src/components/molecules/Calendar/calendar.types.ts
new file mode 100644
index 00000000..cca56198
--- /dev/null
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/calendar.types.ts
@@ -0,0 +1,7 @@
+export type CalendarProps = {
+ currentDate: Date;
+ onDateChange: (date:Date)=>void;
+ highlightCurrentDate?: boolean;
+ minDate?: Date | null;
+ maxDate?: Date | null;
+};
diff --git a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendarUtils.ts b/packages/ui-toolkit/src/components/molecules/Calendar/calendarUtils.ts
similarity index 72%
rename from packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendarUtils.ts
rename to packages/ui-toolkit/src/components/molecules/Calendar/calendarUtils.ts
index 9a6ae793..1f9e3631 100644
--- a/packages/ui-toolkit/src/components/molecules/Calendar/DateCalendar/dateCalendarUtils.ts
+++ b/packages/ui-toolkit/src/components/molecules/Calendar/calendarUtils.ts
@@ -47,3 +47,15 @@ export function getMonthAbbrByIndex(monthNumber: number): string {
return monthNames[ monthNumber - 1 ];
}
+
+
+ /* check date1 is greater than date2 */
+export function compareDate(date1: Date, date2: Date) {
+ // This conversion is required because there is no validation below and .get methods only exists on Date instance unix timestamp will fail
+ date1 = new Date(date1);
+ date2 = new Date(date2);
+ const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), 0, 0, 0);
+ const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), 0, 0, 0);
+
+ return d1.getTime() > d2.getTime();
+}
diff --git a/packages/ui-toolkit/stories/Calander.stories.tsx b/packages/ui-toolkit/stories/Calander.stories.tsx
index 4d797ceb..e699f50a 100644
--- a/packages/ui-toolkit/stories/Calander.stories.tsx
+++ b/packages/ui-toolkit/stories/Calander.stories.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import { Story } from '@storybook/react';
import { Calendar } from '../src/components/molecules';
-import { Props as CalendarProps, CALENDAR_TYPE } from '../src/components/molecules/Calendar/Calendar';
+import { Props, CALENDAR_TYPE } from '../src/components/molecules/Calendar/Calendar';
export default {
title: 'Calendar',
@@ -11,7 +11,7 @@ export default {
};
-const Template: Story = (args) => ;
+const Template: Story = (args) => ;
export const Month = Template.bind({});