Skip to content

Commit

Permalink
refactor: focus manager
Browse files Browse the repository at this point in the history
  • Loading branch information
fikyair committed Sep 5, 2021
1 parent 0bc0e1a commit b2f6fa8
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 18 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"@types/classnames": "^2.2.10",
"@types/highlight.js": "^10.1.0",
"@types/jest": "^26.0.9",
"@types/lodash": "^4.14.172",
"@types/node": "^14.0.27",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
Expand Down
33 changes: 26 additions & 7 deletions src/components/InputDatePicker/calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,51 @@
import React, { useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import DateView from "./dateView";
import MonthYearView from "./monthYearView";
import getYear from "date-fns/get_year";
import getMonth from "date-fns/get_month";

function Calendar() {
const [isDateView, setDateView] = useState(false);
const [isDateView, setDateView] = useState(true);
const calendarRef = useRef(null);

const today = new Date();
const initialCalendar = {
year: getYear(today),
monthIndex: getMonth(today),
};
const [calendar, setCalendar] = useState(initialCalendar);
function onSelectMonth (selectedMonthIndex: number) {
setCalendar({...calendar, monthIndex: selectedMonthIndex})

function onSelectMonth(selectedMonthIndex: number) {
setCalendar({ ...calendar, monthIndex: selectedMonthIndex });
}
function onSelectYear(selectedYear: number) {
setCalendar({ ...calendar, year: selectedYear });
}
const onSetMonthYearView = setDateView.bind(null, false);

const onSetDateView = setDateView.bind(null, true);

useEffect(() => {
if (calendarRef) {
calendarRef.current.focus();
}
}, [isDateView]);

return (
<div className="chocolate-picker">
<div className="chocolate-picker" ref={calendarRef}>
{isDateView ? (
<DateView calendar={calendar} onSelectMonthYear={setCalendar} onTitleClick={onSetMonthYearView} />
<DateView
calendar={calendar}
onSelectMonthYear={setCalendar}
onTitleClick={onSetMonthYearView}
/>
) : (
<MonthYearView calendar={calendar} onSelectMonth={onSelectMonth} onBackClick={onSetDateView} onSelectYear={onSelectYear}/>
<MonthYearView
calendar={calendar}
onSelectMonth={onSelectMonth}
onBackClick={onSetDateView}
onSelectYear={onSelectYear}
/>
)}
</div>
);
Expand Down
11 changes: 7 additions & 4 deletions src/components/InputDatePicker/headerTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import { CalendarType } from "./datePicker";
import YearPicker from "./yearPicker";
import scopedClass from "../../utils/scopedClass";

const sc = scopedClass('chocolate-picker-header-title')
const sc = scopedClass("chocolate-picker-header-title");
function HeaderTitle(props: CalendarType) {

const { year, monthIndex, onTitleClick, onSelectYear } = props;
const firstDayOfMonth = new Date(year, monthIndex);
const monthLabel = format(firstDayOfMonth, "MMM");
const yearLabel = format(firstDayOfMonth, "YYYY");

if (onSelectYear) {
return (
<div className={sc('wrapper')}>
<div className={sc("wrapper")}>
<span>{monthLabel}</span>
<YearPicker selectedYear={year} defaultValue={yearLabel} onSelectYear={onSelectYear} />
<YearPicker
selectedYear={year}
defaultValue={yearLabel}
onSelectYear={onSelectYear}
/>
</div>
);
} else {
Expand Down
19 changes: 16 additions & 3 deletions src/components/InputDatePicker/inputDatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import React, { FC, ChangeEvent } from "react";
import React, { FC, ChangeEvent, useState } from "react";
import FocusManager from "../../utils/focusManager";
import { Input } from "../inputs/input";
import Calendar from "./calendar";

export interface InputDatePickerProps {
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
}

export const InputDatePicker: FC<InputDatePickerProps> = (props) => {
const {} = props;
const [showPicker, setShowPicker] = useState(false);
const openPicker = setShowPicker.bind(null, true);
const closePicker = setShowPicker.bind(null, false);
function onFocus() {
openPicker();
}
function onBlur() {
closePicker();
}
return (
<Calendar />
<FocusManager onFocus={onFocus} onBlur={onBlur}>
<Input size="sm"/>
{showPicker && <Calendar />}
</FocusManager>
);
};

Expand Down
3 changes: 1 addition & 2 deletions src/components/InputDatePicker/monthYearView.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { Dispatch, MouseEventHandler, SetStateAction } from "react";
import React, { MouseEventHandler } from "react";
import MonthPicker from "./monthPicker";
import ViewLayout from "./viewLayout";
import { Button } from "../Button/button";
import Icon from "../icons";
import { CalendarType } from "./datePicker";
import YearPicker from "./yearPicker";
import HeaderTitle from "./headerTitle";

interface DateViewProps {
Expand Down
2 changes: 0 additions & 2 deletions src/components/InputDatePicker/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

.chocolate-picker {
width: 29rem;
height: 35rem;
padding: $padding-normal;
border: 0.1rem solid $border-color;


&-wrapper {
position: relative;
width: 100%;
Expand Down
1 change: 1 addition & 0 deletions src/components/InputDatePicker/yearPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Option from "../Select//selectOption";
interface YearPickerProps {
selectedYear: number;
defaultValue: string;
onSelectYear: (value: number) => void;
}

function YearPicker(props: YearPickerProps) {
Expand Down
35 changes: 35 additions & 0 deletions src/utils/focusManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import PropTypes from "prop-types";
import omit from "lodash/omit";

function FocusManager(props) {
let timeoutId;
function onBlur(e) {
e.persist();
timeoutId = setTimeout(() => {
props.onBlur(e);
});
}
function onFocus(e) {
if (timeoutId) {
clearTimeout(timeoutId);
}
props.onFocus(e);
}
return (
<div
onFocus={onFocus}
onBlur={onBlur}
{...omit(props, ["onFocus", "onBlur"])}
>
{props.children}
</div>
);
}

FocusManager.propTypes = {
onFocus: PropTypes.func.isRequired,
onBlur: PropTypes.func.isRequired
};

export default FocusManager;

0 comments on commit b2f6fa8

Please sign in to comment.