diff --git a/src/components/Button/button.stories.tsx b/src/components/Button/button.stories.tsx index c3f00dde..2def2322 100644 --- a/src/components/Button/button.stories.tsx +++ b/src/components/Button/button.stories.tsx @@ -13,7 +13,7 @@ const BaseButton = (props: BaseButtonProps) => { disabled={disabled} className={className} btnType={btnType} - onClick={action('clicked')} + onClick={action('onClick')} > button ) } diff --git a/src/components/InputDatePicker/calendar.tsx b/src/components/InputDatePicker/calendar.tsx index 968dc523..2d522593 100644 --- a/src/components/InputDatePicker/calendar.tsx +++ b/src/components/InputDatePicker/calendar.tsx @@ -1,10 +1,20 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { MouseEvent, 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"; +import startOfDay from "date-fns/start_of_day"; -function Calendar() { +export interface CalendarProps { + selectedDate: Date; + onSelectDate: ( + e: MouseEvent, + date: Date | string | number + ) => void; +} + +function Calendar(props: CalendarProps) { + const { selectedDate, onSelectDate } = props; const [isDateView, setDateView] = useState(true); const calendarRef = useRef(null); @@ -14,7 +24,7 @@ function Calendar() { monthIndex: getMonth(today), }; const [calendar, setCalendar] = useState(initialCalendar); - + function onSelectMonth(selectedMonthIndex: number) { setCalendar({ ...calendar, monthIndex: selectedMonthIndex }); } @@ -31,6 +41,10 @@ function Calendar() { } }, [isDateView]); + const onClickToday = (e: MouseEvent) => { + onSelectDate(e, startOfDay(new Date())); + }; + return (
{isDateView ? ( @@ -38,6 +52,9 @@ function Calendar() { calendar={calendar} onSelectMonthYear={setCalendar} onTitleClick={onSetMonthYearView} + selectedDate={selectedDate} + onSelectDate={onSelectDate} + onClickToday={onClickToday} /> ) : ( )}
diff --git a/src/components/InputDatePicker/dateContext.tsx b/src/components/InputDatePicker/dateContext.tsx new file mode 100644 index 00000000..7f95d471 --- /dev/null +++ b/src/components/InputDatePicker/dateContext.tsx @@ -0,0 +1,8 @@ +import { createContext } from "react"; +import DateManagerState from './dateManager' + + +interface Provider { + defaultValue: (value: DateManagerState, onSelectDate: ) => void +} +export default createContext(Cell); \ No newline at end of file diff --git a/src/components/InputDatePicker/dateManager.tsx b/src/components/InputDatePicker/dateManager.tsx new file mode 100644 index 00000000..fbc79739 --- /dev/null +++ b/src/components/InputDatePicker/dateManager.tsx @@ -0,0 +1,54 @@ +import React, { ChangeEvent, createContext, useState } from "react"; +import { dateToStr } from "./utils/date-extraction"; + +interface DateManagerState { + date: Date; + textInput: string; +} + +interface DateManagerProps { + onChange?: ( + e: ChangeEvent, + value: DateManagerState + ) => void; + children: React.ReactNode; +} + +export interface IPickerContext { + value: DateManagerState; + onSelectDate: (e: ChangeEvent, date: Date) => void; +} +export const DateContext = createContext({ + value: { date: new Date(), textInput: "" }, + onSelectDate: () => {}, +}); + +function DateManager(props: DateManagerProps) { + const { onChange, children } = props; + const [state, setState] = useState({ + date: new Date(), + textInput: "", + }); + + function onSelectDate(e: ChangeEvent, date: Date) { + const nextState: DateManagerState = { + date, + textInput: dateToStr(date), + }; + setState(nextState); + onChange && onChange(e, nextState); + } + + const passedContext: IPickerContext = { + value: state, + onSelectDate, + }; + + return ( + + {children} + + ); +} + +export default DateManager; diff --git a/src/components/InputDatePicker/datePicker.stories.tsx b/src/components/InputDatePicker/datePicker.stories.tsx index 41236604..8ee7b5a4 100644 --- a/src/components/InputDatePicker/datePicker.stories.tsx +++ b/src/components/InputDatePicker/datePicker.stories.tsx @@ -1,27 +1,35 @@ -import React from 'react' -import { Story, Meta } from '@storybook/react' -import InputDatePicker from './inputDatePicker' -const BaseInputDatePicker = () =>
+import React from "react"; +import { Story, Meta } from "@storybook/react"; +import InputDatePicker, { InputDatePickerProps } from "./inputDatePicker"; +import { actions } from "@storybook/addon-actions"; + +const BaseInputDatePicker = (props: InputDatePickerProps) => { + return ( +
+ +
+ ); +}; export default { component: InputDatePicker, - title: 'InputDatePicker', + title: "InputDatePicker", argTypes: { defaultValue: { // options: [], // control: { type: 'date' } - } + }, }, parameters: { docs: { source: { - type: 'code' - } + type: "code", + }, }, - controls: { + controls: { include: [], - hideNoControlsWarning: true - } + hideNoControlsWarning: true, + }, }, } as Meta; diff --git a/src/components/InputDatePicker/datePicker.tsx b/src/components/InputDatePicker/datePicker.tsx index 11baa24b..81476b3c 100644 --- a/src/components/InputDatePicker/datePicker.tsx +++ b/src/components/InputDatePicker/datePicker.tsx @@ -1,12 +1,13 @@ -import React, { FC, ChangeEvent, useMemo, useState } from "react"; +import React, { FC, ChangeEvent, useMemo } from "react"; import classNames from "classnames"; import { scopedClass } from "../../utils/scopedClass"; -import buildWeeks, { buildDayNames } from "./generator"; +import buildWeeks, { buildDayNames } from "./utils/generator"; import getDate from "date-fns/get_date"; import getMonth from "date-fns/get_month"; import isSameDay from "date-fns/is_same_day"; import dateFnsIsToday from "date-fns/is_today"; import { Button } from "../Button/button"; +import { CalendarProps } from "./calendar"; const sc = scopedClass("chocolate-picker"); @@ -21,32 +22,53 @@ export interface DatePickerProps { selectedDate: Date; } -export const DatePicker: FC = (props) => { +export const DatePicker: FC = (props) => { const { calendar: { year, monthIndex }, className, selectedDate, + onSelectDate, } = props; const weeks = useMemo(() => buildWeeks(year, monthIndex), [monthIndex, year]); const dayNames = useMemo(() => buildDayNames(0), []); + const exchangeDayNames = (name: string) => { + switch (name) { + case "0": + return "星期日"; + case "1": + return "星期一"; + case "2": + return "星期二"; + case "3": + return "星期三"; + case "4": + return "星期四"; + case "5": + return "星期五"; + case "6": + return "星期六"; + default: + break; + } + }; return ( {dayNames.map((dayName, i) => ( - + ))} {weeks.map((week: [], i: number) => ( - {week.map((day: number, j: number) => { + {week.map((day: Date | string | number, j: number) => { // 目前是当前日期 const isToday = dateFnsIsToday(day); // 当前月日期 const isCurrentMonth = getMonth(day) === monthIndex; - // 选中日期 + // 选中日期 const isSelected = isSameDay(day, selectedDate); return (
{dayName}{exchangeDayNames(dayName)}
@@ -57,6 +79,7 @@ export const DatePicker: FC = (props) => { [`${sc("is-current-month")}`]: !isCurrentMonth, })} btnType="ghost" + onClick={(e) => onSelectDate(e, day)} > {getDate(day)} diff --git a/src/components/InputDatePicker/dateView.tsx b/src/components/InputDatePicker/dateView.tsx index 03c04279..e9af0120 100644 --- a/src/components/InputDatePicker/dateView.tsx +++ b/src/components/InputDatePicker/dateView.tsx @@ -1,9 +1,10 @@ -import React, { Dispatch, SetStateAction } from "react"; +import React, {MouseEvent, Dispatch, SetStateAction } from "react"; import { ViewLayout } from "./viewLayout"; import DatePicker, { CalendarType } from "./datePicker"; import { Button } from "../Button/button"; import Icon from "../icons/icon"; import HeaderTitle from "./headerTitle"; +import { CalendarProps } from "./calendar"; interface DateViewProps { calendar: CalendarType; @@ -11,16 +12,21 @@ interface DateViewProps { SetStateAction<{ year: number; monthIndex: number }> >; onTitleClick: () => void; + onClickToday: (e: MouseEvent) => void; } function module(m: number, n: number) { return ((m % n) + n) % n; } -function DateView(props: DateViewProps) { + +function DateView(props: DateViewProps & CalendarProps) { const { calendar: { year, monthIndex }, onSelectMonthYear, - onTitleClick + onTitleClick, + selectedDate, + onSelectDate, + onClickToday } = props; function incrementMonthIndex(increment: number) { @@ -41,23 +47,26 @@ function DateView(props: DateViewProps) { bodyElement={ } header={{ leftElement: , middleElement: (

- +

), rightElement: , }} - footerElement={} + footerElement={} > ); } -DateView.propTypes = {}; - export default DateView; diff --git a/src/components/InputDatePicker/headerTitle.tsx b/src/components/InputDatePicker/headerTitle.tsx index 1357edb2..9a67f4f2 100644 --- a/src/components/InputDatePicker/headerTitle.tsx +++ b/src/components/InputDatePicker/headerTitle.tsx @@ -9,16 +9,16 @@ 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 monthLabel = format(firstDayOfMonth, "MM"); const yearLabel = format(firstDayOfMonth, "YYYY"); if (onSelectYear) { return (
- {monthLabel} + {monthLabel} 月
@@ -26,7 +26,7 @@ function HeaderTitle(props: CalendarType) { } else { return ( ); } diff --git a/src/components/InputDatePicker/input.tsx b/src/components/InputDatePicker/input.tsx new file mode 100644 index 00000000..2893dcb9 --- /dev/null +++ b/src/components/InputDatePicker/input.tsx @@ -0,0 +1,10 @@ +import React, { useContext } from "react"; +import { DateContext, IPickerContext } from "./dateManager"; +import { Input } from "../inputs/input"; + +function InputComponent() { + const { value } = useContext(DateContext); + return ; +} + +export default InputComponent; diff --git a/src/components/InputDatePicker/inputDatePicker.tsx b/src/components/InputDatePicker/inputDatePicker.tsx index c87fb493..acf0fcd5 100644 --- a/src/components/InputDatePicker/inputDatePicker.tsx +++ b/src/components/InputDatePicker/inputDatePicker.tsx @@ -1,10 +1,11 @@ -import React, { FC, ChangeEvent, useState } from "react"; +import React, { FC, useState } from "react"; import FocusManager from "../../utils/focusManager"; -import { Input } from "../inputs/input"; -import Calendar from "./calendar"; +import DateManager from "./dateManager"; +import InputComponent from "./input"; +import Picker from "./picker"; export interface InputDatePickerProps { - onChange?: (e: ChangeEvent) => void; + onChange?: () => void; } export const InputDatePicker: FC = (props) => { @@ -19,12 +20,13 @@ export const InputDatePicker: FC = (props) => { } return ( - - {showPicker && } + + + {showPicker && } + ); }; - InputDatePicker.defaultProps = {}; export default InputDatePicker; diff --git a/src/components/InputDatePicker/monthPicker.tsx b/src/components/InputDatePicker/monthPicker.tsx index c5a86d7c..db2ddc6a 100644 --- a/src/components/InputDatePicker/monthPicker.tsx +++ b/src/components/InputDatePicker/monthPicker.tsx @@ -1,7 +1,7 @@ -import React, { Dispatch, SetStateAction } from "react"; +import React from "react"; import scopedClass from "../../utils/scopedClass"; import { Button } from "../Button/button"; -import { buildMonths } from "./generator"; +import { buildMonths } from "./utils/generator"; import classNames from "classnames"; const sc = scopedClass("chocolate-picker-month"); @@ -44,6 +44,4 @@ function MonthPicker(props: MonthPickerProps) { ); } -MonthPicker.propTypes = {}; - export default MonthPicker; diff --git a/src/components/InputDatePicker/monthYearView.tsx b/src/components/InputDatePicker/monthYearView.tsx index c55da1a6..fe468c92 100644 --- a/src/components/InputDatePicker/monthYearView.tsx +++ b/src/components/InputDatePicker/monthYearView.tsx @@ -1,4 +1,4 @@ -import React, { MouseEventHandler } from "react"; +import React, { MouseEvent, MouseEventHandler } from "react"; import MonthPicker from "./monthPicker"; import ViewLayout from "./viewLayout"; import { Button } from "../Button/button"; @@ -11,22 +11,35 @@ interface DateViewProps { onSelectMonth: (value: number) => void; onSelectYear: (value: number) => void; onBackClick: MouseEventHandler; + onClickToday: (e: MouseEvent) => void; } function MonthYearView(props: DateViewProps) { - const { calendar, onSelectMonth, onBackClick, onSelectYear } = props; + const { + calendar, + onSelectMonth, + onBackClick, + onSelectYear, + onClickToday, + } = props; const { monthIndex } = calendar; return ( , - middleElement: , - rightElement: {}} />, + middleElement: ( + + ), + rightElement:
, }} bodyElement={ } - footerElement={} + footerElement={ + + } /> ); } diff --git a/src/components/InputDatePicker/picker.tsx b/src/components/InputDatePicker/picker.tsx new file mode 100644 index 00000000..3a32d889 --- /dev/null +++ b/src/components/InputDatePicker/picker.tsx @@ -0,0 +1,10 @@ +import React, { useContext } from "react"; +import { DateContext, IPickerContext } from "./dateManager"; +import Calendar from "./calendar"; + +function Picker() { + const { value, onSelectDate } = useContext(DateContext); + return ; +} + +export default Picker; diff --git a/src/components/InputDatePicker/utils/date-extraction.ts b/src/components/InputDatePicker/utils/date-extraction.ts new file mode 100644 index 00000000..cc51f7dc --- /dev/null +++ b/src/components/InputDatePicker/utils/date-extraction.ts @@ -0,0 +1,4 @@ +import format from "date-fns/format"; +export function dateToStr(date: Date) { + return format(date, "YYYY-MM-DD"); +} diff --git a/src/components/InputDatePicker/generator.ts b/src/components/InputDatePicker/utils/generator.ts similarity index 94% rename from src/components/InputDatePicker/generator.ts rename to src/components/InputDatePicker/utils/generator.ts index c79bfa3a..c61c6a16 100644 --- a/src/components/InputDatePicker/generator.ts +++ b/src/components/InputDatePicker/utils/generator.ts @@ -4,7 +4,7 @@ import addDays from "date-fns/add_days"; import setDay from "date-fns/set_day"; import setMonth from "date-fns/set_month"; import format from "date-fns/format"; -import { MonthOfYear } from "./monthPicker"; +import { MonthOfYear } from "../monthPicker"; export default function buildWeeks(year: number, monthIndex: number) { const firstDayOfMonth = new Date(year, monthIndex); @@ -21,7 +21,7 @@ export function buildDayNames(weekStartsOn: number): string[] { .map((_, i) => (i + weekStartsOn) % 7) .map((dayOfWeek) => { const day = setDay(new Date(0), dayOfWeek); - return format(day, "ddd"); + return format(day, "d"); }); } diff --git a/src/components/InputDatePicker/yearPicker.tsx b/src/components/InputDatePicker/yearPicker.tsx index 174acbc7..9eda8b7b 100644 --- a/src/components/InputDatePicker/yearPicker.tsx +++ b/src/components/InputDatePicker/yearPicker.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Select } from "../Select/select"; -import { buildYears } from "./generator"; +import { buildYears } from "./utils/generator"; import Option from "../Select//selectOption"; interface YearPickerProps { @@ -28,6 +28,4 @@ function YearPicker(props: YearPickerProps) { ); } -YearPicker.propTypes = {}; - export default YearPicker;