From 71416df07419308a8d69a58a5eb0eee523744794 Mon Sep 17 00:00:00 2001 From: zombiej Date: Fri, 22 Nov 2019 11:05:52 +0800 Subject: [PATCH] fix init logic --- .eslintrc.js | 1 + examples/basic.tsx | 4 +++ src/PanelContext.tsx | 2 +- src/Picker.tsx | 51 +++++++++++++++++++-------- src/PickerPanel.tsx | 26 +++++++++----- src/interface.ts | 2 +- src/panels/DatePanel/index.tsx | 5 ++- src/panels/DatetimePanel/index.tsx | 13 +++++-- src/panels/DecadePanel/DecadeBody.tsx | 11 +++--- src/panels/DecadePanel/index.tsx | 51 +++++++++++++++++++++++---- src/panels/MonthPanel/index.tsx | 5 ++- src/panels/TimePanel/index.tsx | 5 ++- src/panels/YearPanel/index.tsx | 5 ++- src/utils/uiUtil.ts | 49 +++++++++++++++++++------ 14 files changed, 169 insertions(+), 61 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6868ace5e..a06a91418 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,5 +10,6 @@ module.exports = { 'react/sort-comp': 0, '@typescript-eslint/no-explicit-any': 0, 'default-case': 0, + 'jsx-a11y/no-autofocus': 0, }, }; diff --git a/examples/basic.tsx b/examples/basic.tsx index f49cac03a..bbdc3c270 100644 --- a/examples/basic.tsx +++ b/examples/basic.tsx @@ -173,6 +173,10 @@ export default () => {

Basic

{...sharedProps} locale={zhCN} /> +
+

Datetime

+ {...sharedProps} locale={zhCN} showTime /> +
); diff --git a/src/PanelContext.tsx b/src/PanelContext.tsx index 2936f8aa5..652578980 100644 --- a/src/PanelContext.tsx +++ b/src/PanelContext.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; export type ContextOperationRefProps = { - onKeyDown: React.KeyboardEventHandler; + onKeyDown: (e: React.KeyboardEvent) => boolean; }; export interface PanelContextProps { diff --git a/src/Picker.tsx b/src/Picker.tsx index 0f1684350..a9e822504 100644 --- a/src/Picker.tsx +++ b/src/Picker.tsx @@ -8,11 +8,14 @@ import { Locale } from './interface'; import { isEqual } from './utils/dateUtil'; import { toArray } from './utils/miscUtil'; import PanelContext, { ContextOperationRefProps } from './PanelContext'; +import { SharedTimeProps } from './panels/TimePanel'; export interface PickerProps { prefixCls?: string; generateConfig: GenerateConfig; locale: Locale; + autoFocus?: boolean; + showTime?: boolean | SharedTimeProps; value?: DateType; open?: boolean; format?: string | string[]; @@ -25,7 +28,9 @@ function Picker(props: PickerProps) { prefixCls = 'rc-picker', generateConfig, locale, - format = 'YYYY-MM-DD', + autoFocus, + showTime, + format = showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD', value, open, onChange, @@ -121,6 +126,19 @@ function Picker(props: PickerProps) { } }; + const forwardKeyDown = (e: React.KeyboardEvent) => { + if ( + !typing && + mergedOpen && + operationRef.current && + operationRef.current.onKeyDown + ) { + // Let popup panel handle keyboard + return operationRef.current.onKeyDown(e); + } + return false; + }; + const onInputKeyDown: React.KeyboardEventHandler = e => { switch (e.which) { case KeyCode.ENTER: { @@ -129,37 +147,38 @@ function Picker(props: PickerProps) { } else { triggerChange(selectedValue); triggerOpen(false); + setTyping(true); } - break; + return; } case KeyCode.TAB: { - if (typing && mergedOpen) { + if (typing && mergedOpen && !e.shiftKey) { setTyping(false); e.preventDefault(); - } else if (!typing && mergedOpen && e.shiftKey) { - setTyping(true); - e.preventDefault(); + } else if (!typing && mergedOpen) { + if (!forwardKeyDown(e) && e.shiftKey) { + setTyping(true); + e.preventDefault(); + } } - break; + return; } case KeyCode.ESC: { triggerChange(mergedValue); setSelectedValue(mergedValue); triggerOpen(false); + setTyping(true); return; } } - // Let popup panel handle keyboard - if ( - !typing && - mergedOpen && - operationRef.current && - operationRef.current.onKeyDown - ) { - operationRef.current.onKeyDown(e); + if (!mergedOpen && ![KeyCode.SHIFT].includes(e.which)) { + triggerOpen(true); + } else { + // Let popup panel handle keyboard + forwardKeyDown(e); } }; @@ -190,6 +209,7 @@ function Picker(props: PickerProps) { // ============================= Panel ============================= const panel = ( + {...props} generateConfig={generateConfig} className={classNames({ [`${prefixCls}-panel-focused`]: !typing, @@ -224,6 +244,7 @@ function Picker(props: PickerProps) { value={textValue} onChange={onInputChange} onKeyDown={onInputKeyDown} + autoFocus={autoFocus} /> diff --git a/src/PickerPanel.tsx b/src/PickerPanel.tsx index 67ae6c9c5..e00b50e4a 100644 --- a/src/PickerPanel.tsx +++ b/src/PickerPanel.tsx @@ -52,6 +52,9 @@ function Picker(props: PickerProps) { const { operationRef } = React.useContext(PanelContext); const panelRef = React.useRef({}); + // Handle init logic + const initRef = React.useRef(true); + // View date control const [viewDate, setViewDate] = React.useState( defaultPickerValue || value || generateConfig.getNow(), @@ -89,14 +92,8 @@ function Picker(props: PickerProps) { } }; - React.useEffect(() => { - if (value) { - setViewDate(value); - } - }, [value]); - // ========================= Interactive ========================== - const onInternalKeyDown: React.KeyboardEventHandler = e => { + const onInternalKeyDown = (e: React.KeyboardEvent) => { if (panelRef.current && panelRef.current.onKeyDown) { if ( [ @@ -111,8 +108,9 @@ function Picker(props: PickerProps) { ) { e.preventDefault(); } - panelRef.current.onKeyDown(e); + return panelRef.current.onKeyDown(e); } + return false; }; const onInternalBlur: React.FocusEventHandler = e => { @@ -127,6 +125,17 @@ function Picker(props: PickerProps) { }; } + // ============================ Effect ============================ + React.useEffect(() => { + if (value && !initRef.current) { + setViewDate(value); + } + }, [value]); + + React.useEffect(() => { + initRef.current = false; + }, []); + // ============================ Panels ============================ let panelNode: React.ReactNode; @@ -146,7 +155,6 @@ function Picker(props: PickerProps) { {...pickerProps} onSelect={date => { - onInternalPanelChange('year', date); setViewDate(date); }} /> diff --git a/src/interface.ts b/src/interface.ts index 92a18ea91..e2e437464 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -49,7 +49,7 @@ export type PanelMode = | 'decade'; export interface PanelRefProps { - onKeyDown?: React.KeyboardEventHandler; + onKeyDown?: (e: React.KeyboardEvent) => boolean; onBlur?: React.FocusEventHandler; } diff --git a/src/panels/DatePanel/index.tsx b/src/panels/DatePanel/index.tsx index 70a5bcd40..6b5259a36 100644 --- a/src/panels/DatePanel/index.tsx +++ b/src/panels/DatePanel/index.tsx @@ -28,7 +28,7 @@ function DatePanel(props: DatePanelProps) { // ======================= Keyboard ======================= operationRef.current = { - onKeyDown: event => { + onKeyDown: event => createKeyDownHandler(event, { onLeftRight: diff => { onSelect(generateConfig.addDate(value, diff)); @@ -42,8 +42,7 @@ function DatePanel(props: DatePanelProps) { onPageUpDown: diff => { onSelect(generateConfig.addMonth(value, diff)); }, - }); - }, + }), }; // ==================== View Operation ==================== diff --git a/src/panels/DatetimePanel/index.tsx b/src/panels/DatetimePanel/index.tsx index 747d564d4..a3254f957 100644 --- a/src/panels/DatetimePanel/index.tsx +++ b/src/panels/DatetimePanel/index.tsx @@ -38,20 +38,29 @@ function DatetimePanel(props: DatetimePanelProps) { if (nextActivePanel) { event.preventDefault(); } - } else if (activePanel) { + + return true; + } + if (activePanel) { const ref = activePanel === 'date' ? dateOperationRef : timeOperationRef; if (ref.current && ref.current.onKeyDown) { ref.current.onKeyDown(event); } - } else if ( + + return true; + } + if ( [KeyCode.LEFT, KeyCode.RIGHT, KeyCode.UP, KeyCode.DOWN].includes( event.which, ) ) { setActivePanel('date'); + return true; } + + return false; }, onBlur: e => { if (timeOperationRef.current.onBlur) { diff --git a/src/panels/DecadePanel/DecadeBody.tsx b/src/panels/DecadePanel/DecadeBody.tsx index 4cf88022d..b973c939e 100644 --- a/src/panels/DecadePanel/DecadeBody.tsx +++ b/src/panels/DecadePanel/DecadeBody.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import classNames from 'classnames'; import { GenerateConfig } from '../../utils/generateUtil'; -import { DECADE_DISTANCE_COUNT } from '.'; +import { DECADE_DISTANCE_COUNT, DECADE_UNIT_DIFF } from '.'; const DECADE_COL_COUNT = 3; const DECADE_ROW_COUNT = 4; @@ -23,7 +23,8 @@ function YearBody({ const rows: React.ReactNode[] = []; const yearNumber = generateConfig.getYear(viewDate); - const decadeYearNumber = Math.floor(yearNumber / 10) * 10; + const decadeYearNumber = + Math.floor(yearNumber / DECADE_UNIT_DIFF) * DECADE_UNIT_DIFF; const startDecadeYear = Math.floor(yearNumber / DECADE_DISTANCE_COUNT) * DECADE_DISTANCE_COUNT; @@ -32,14 +33,16 @@ function YearBody({ const baseDecadeYear = startDecadeYear - Math.ceil( - (DECADE_COL_COUNT * DECADE_ROW_COUNT * 10 - DECADE_DISTANCE_COUNT) / 2, + (DECADE_COL_COUNT * DECADE_ROW_COUNT * DECADE_UNIT_DIFF - + DECADE_DISTANCE_COUNT) / + 2, ); for (let i = 0; i < DECADE_ROW_COUNT; i += 1) { const row: React.ReactNode[] = []; for (let j = 0; j < DECADE_COL_COUNT; j += 1) { - const diffDecade = (i * DECADE_COL_COUNT + j) * 10; + const diffDecade = (i * DECADE_COL_COUNT + j) * DECADE_UNIT_DIFF; const startDecadeNumber = baseDecadeYear + diffDecade; const endDecadeNumber = baseDecadeYear + diffDecade + 9; diff --git a/src/panels/DecadePanel/index.tsx b/src/panels/DecadePanel/index.tsx index d4cf0c69f..1e21b991b 100644 --- a/src/panels/DecadePanel/index.tsx +++ b/src/panels/DecadePanel/index.tsx @@ -2,25 +2,58 @@ import * as React from 'react'; import DecadeHeader from './DecadeHeader'; import DecadeBody from './DecadeBody'; import { PanelSharedProps } from '../../interface'; +import { createKeyDownHandler } from '../../utils/uiUtil'; -export type DecadePanelProps = Omit< - PanelSharedProps, - 'onPanelChange' ->; +export type DecadePanelProps = PanelSharedProps; -export const DECADE_DISTANCE_COUNT = 100; +export const DECADE_UNIT_DIFF = 10; +export const DECADE_DISTANCE_COUNT = DECADE_UNIT_DIFF * 10; function DecadePanel(props: DecadePanelProps) { - const { prefixCls, onViewDateChange, generateConfig, viewDate } = props; + const { + prefixCls, + onViewDateChange, + generateConfig, + viewDate, + operationRef, + onSelect, + onPanelChange, + } = props; const panelPrefixCls = `${prefixCls}-year-panel`; + // ======================= Keyboard ======================= + operationRef.current = { + onKeyDown: event => + createKeyDownHandler(event, { + onLeftRight: diff => { + console.log('>>>>', diff); + onSelect(generateConfig.addYear(viewDate, diff * DECADE_UNIT_DIFF)); + }, + // onCtrlLeftRight: diff => { + // onSelect(generateConfig.addYear(value, diff * YEAR_DECADE_COUNT)); + // }, + // onUpDown: diff => { + // onSelect(generateConfig.addYear(value, diff * YEAR_COL_COUNT)); + // }, + // onEnter: () => { + // onSelect(viewDate); + // }, + }), + }; + + // ==================== View Operation ==================== const onDecadesChange = (diff: number) => { onViewDateChange( generateConfig.addYear(viewDate, diff * DECADE_DISTANCE_COUNT), ); }; + const onInternalSelect = (date: DateType) => { + onSelect(date); + onPanelChange('year', date); + }; + return (
(props: DecadePanelProps) { onDecadesChange(1); }} /> - +
); } diff --git a/src/panels/MonthPanel/index.tsx b/src/panels/MonthPanel/index.tsx index 53bf5ff35..2b8fa6156 100644 --- a/src/panels/MonthPanel/index.tsx +++ b/src/panels/MonthPanel/index.tsx @@ -22,7 +22,7 @@ function MonthPanel(props: MonthPanelProps) { // ======================= Keyboard ======================= operationRef.current = { - onKeyDown: event => { + onKeyDown: event => createKeyDownHandler(event, { onLeftRight: diff => { onSelect(generateConfig.addMonth(value, diff)); @@ -36,8 +36,7 @@ function MonthPanel(props: MonthPanelProps) { onEnter: () => { onPanelChange('date', value); }, - }); - }, + }), }; // ==================== View Operation ==================== diff --git a/src/panels/TimePanel/index.tsx b/src/panels/TimePanel/index.tsx index ff766a11d..a8b7a2aa4 100644 --- a/src/panels/TimePanel/index.tsx +++ b/src/panels/TimePanel/index.tsx @@ -55,7 +55,7 @@ function TimePanel(props: TimePanelProps) { ]); operationRef.current = { - onKeyDown: event => { + onKeyDown: event => createKeyDownHandler(event, { onLeftRight: diff => { setActiveColumnIndex( @@ -73,8 +73,7 @@ function TimePanel(props: TimePanelProps) { onSelect(value); setActiveColumnIndex(-1); }, - }); - }, + }), onBlur: () => { setActiveColumnIndex(-1); diff --git a/src/panels/YearPanel/index.tsx b/src/panels/YearPanel/index.tsx index 73c62ae84..89409bbb6 100644 --- a/src/panels/YearPanel/index.tsx +++ b/src/panels/YearPanel/index.tsx @@ -24,7 +24,7 @@ function YearPanel(props: YearPanelProps) { // ======================= Keyboard ======================= operationRef.current = { - onKeyDown: event => { + onKeyDown: event => createKeyDownHandler(event, { onLeftRight: diff => { onSelect(generateConfig.addYear(value, diff)); @@ -38,8 +38,7 @@ function YearPanel(props: YearPanelProps) { onEnter: () => { onPanelChange('month', value); }, - }); - }, + }), }; // ==================== View Operation ==================== diff --git a/src/utils/uiUtil.ts b/src/utils/uiUtil.ts index c143d9843..5201c3a7c 100644 --- a/src/utils/uiUtil.ts +++ b/src/utils/uiUtil.ts @@ -61,37 +61,66 @@ export function createKeyDownHandler( onPageUpDown, onEnter, }: KeyboardConfig, -) { +): boolean { const { which, ctrlKey, metaKey } = event; switch (which) { case KeyCode.LEFT: if (ctrlKey || metaKey) { - if (onCtrlLeftRight) onCtrlLeftRight(-1); - } else if (onLeftRight) onLeftRight(-1); + if (onCtrlLeftRight) { + onCtrlLeftRight(-1); + return true; + } + } else if (onLeftRight) { + onLeftRight(-1); + return true; + } break; case KeyCode.RIGHT: if (ctrlKey || metaKey) { - if (onCtrlLeftRight) onCtrlLeftRight(1); - } else if (onLeftRight) onLeftRight(1); + if (onCtrlLeftRight) { + onCtrlLeftRight(1); + return true; + } + } else if (onLeftRight) { + onLeftRight(1); + return true; + } break; case KeyCode.UP: - if (onUpDown) onUpDown(-1); + if (onUpDown) { + onUpDown(-1); + return true; + } break; case KeyCode.DOWN: - if (onUpDown) onUpDown(1); + if (onUpDown) { + onUpDown(1); + return true; + } break; case KeyCode.PAGE_UP: - if (onPageUpDown) onPageUpDown(-1); + if (onPageUpDown) { + onPageUpDown(-1); + return true; + } break; case KeyCode.PAGE_DOWN: - if (onPageUpDown) onPageUpDown(1); + if (onPageUpDown) { + onPageUpDown(1); + return true; + } break; case KeyCode.ENTER: - if (onEnter) onEnter(); + if (onEnter) { + onEnter(); + return true; + } break; } + + return false; }