Skip to content

Commit

Permalink
Merge pull request #3 from react-component/master
Browse files Browse the repository at this point in the history
update master
  • Loading branch information
conquera99 authored Sep 22, 2020
2 parents 8d1449b + 92690f5 commit 3785bc7
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 28 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rc-picker",
"version": "2.0.11",
"version": "2.2.1",
"description": "React date & time picker",
"keywords": [
"react",
Expand Down Expand Up @@ -43,7 +43,7 @@
"date-fns": "^2.15.0",
"dayjs": "^1.8.30",
"moment": "^2.24.0",
"rc-trigger": "^4.0.0",
"rc-trigger": "^5.0.4",
"rc-util": "^5.0.1",
"shallowequal": "^1.1.0"
},
Expand All @@ -63,11 +63,11 @@
"enzyme": "^3.0.0",
"enzyme-adapter-react-16": "^1.0.1",
"enzyme-to-json": "^3.4.0",
"eslint": "~7.8.1",
"eslint": "~7.9.0",
"eslint-plugin-eslint-comments": "^3.1.2",
"eslint-plugin-jest": "^24.0.0",
"eslint-plugin-react-hooks": "^4.0.2",
"eslint-plugin-unicorn": "^21.0.0",
"eslint-plugin-unicorn": "^22.0.0",
"father": "^2.13.4",
"less": "^3.10.3",
"mockdate": "^3.0.2",
Expand Down
18 changes: 11 additions & 7 deletions src/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import PickerPanel, {
PickerPanelTimeProps,
} from './PickerPanel';
import PickerTrigger from './PickerTrigger';
import { isEqual } from './utils/dateUtil';
import { formatValue, isEqual, parseValue } from './utils/dateUtil';
import getDataOrAriaProps, { toArray } from './utils/miscUtil';
import PanelContext, { ContextOperationRefProps } from './PanelContext';
import { PickerMode } from './interface';
import { CustomFormat, PickerMode } from './interface';
import { getDefaultFormat, getInputSize, elementsContains } from './utils/uiUtil';
import usePickerInput from './hooks/usePickerInput';
import useTextValueMapping from './hooks/useTextValueMapping';
Expand Down Expand Up @@ -54,7 +54,7 @@ export interface PickerSharedProps<DateType> extends React.AriaAttributes {
id?: string;

// Value
format?: string | string[];
format?: string | CustomFormat<DateType> | Array<string | CustomFormat<DateType>>;

// Render
suffixIcon?: React.ReactNode;
Expand Down Expand Up @@ -225,7 +225,11 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
const [text, triggerTextChange, resetText] = useTextValueMapping({
valueTexts,
onTextChange: newText => {
const inputDate = generateConfig.locale.parse(locale.locale, newText, formatList);
const inputDate = parseValue(newText, {
locale,
formatList,
generateConfig,
});
if (inputDate && (!disabledDate || !disabledDate(inputDate))) {
setSelectedValue(inputDate);
}
Expand All @@ -240,7 +244,7 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
if (onChange && !isEqual(generateConfig, mergedValue, newValue)) {
onChange(
newValue,
newValue ? generateConfig.locale.format(locale.locale, newValue, formatList[0]) : '',
newValue ? formatValue(newValue, { generateConfig, locale, format: formatList[0] }) : '',
);
}
};
Expand Down Expand Up @@ -491,7 +495,7 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
id={id}
tabIndex={tabIndex}
disabled={disabled}
readOnly={inputReadOnly || !typing}
readOnly={inputReadOnly || typeof formatList[0] === 'function' || !typing}
value={hoverValue || text}
onChange={e => {
triggerTextChange(e.target.value);
Expand All @@ -501,7 +505,7 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
ref={inputRef}
title={text}
{...inputProps}
size={getInputSize(picker, formatList[0])}
size={getInputSize(picker, formatList[0], generateConfig)}
{...getDataOrAriaProps(props)}
autoComplete={autoComplete}
/>
Expand Down
24 changes: 16 additions & 8 deletions src/RangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
isSameDate,
isSameWeek,
isSameQuarter,
formatValue,
parseValue,
} from './utils/dateUtil';
import useValueTexts from './hooks/useValueTexts';
import useTextValueMapping from './hooks/useTextValueMapping';
Expand Down Expand Up @@ -229,7 +231,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
const endInputRef = useRef<HTMLInputElement>(null);

// ============================= Misc ==============================
const formatList = toArray(getDefaultFormat(format, picker, showTime, use12Hours));
const formatList = toArray(getDefaultFormat<DateType>(format, picker, showTime, use12Hours));

// Active picker
const [mergedActivePickerIndex, setMergedActivePickerIndex] = useMergedState<0 | 1>(0, {
Expand Down Expand Up @@ -425,11 +427,11 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {

const startStr =
values && values[0]
? generateConfig.locale.format(locale.locale, values[0], formatList[0])
? formatValue(values[0], { generateConfig, locale, format: formatList[0] })
: '';
const endStr =
values && values[1]
? generateConfig.locale.format(locale.locale, values[1], formatList[0])
? formatValue(values[1], { generateConfig, locale, format: formatList[0] })
: '';

if (onCalendarChange) {
Expand Down Expand Up @@ -515,7 +517,11 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
);

const onTextChange = (newText: string, index: 0 | 1) => {
const inputDate = generateConfig.locale.parse(locale.locale, newText, formatList);
const inputDate = parseValue(newText, {
locale,
formatList,
generateConfig,
});

const disabledFunc = index === 0 ? disabledStartDate : disabledEndDate;

Expand Down Expand Up @@ -813,7 +819,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
onOk={null}
onSelect={undefined}
onChange={undefined}
defaultValue={undefined}
defaultValue={
mergedActivePickerIndex === 0 ? getValue(selectedValue, 1) : getValue(selectedValue, 0)
}
defaultPickerValue={undefined}
/>
</RangeContext.Provider>
Expand Down Expand Up @@ -989,7 +997,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
}

const inputSharedProps = {
size: getInputSize(picker, formatList[0]),
size: getInputSize(picker, formatList[0], generateConfig),
};

let activeBarLeft: number = 0;
Expand Down Expand Up @@ -1068,7 +1076,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
<input
id={id}
disabled={mergedDisabled[0]}
readOnly={inputReadOnly || !startTyping}
readOnly={inputReadOnly || typeof formatList[0] === 'function' || !startTyping}
value={startHoverValue || startText}
onChange={e => {
triggerStartTextChange(e.target.value);
Expand All @@ -1093,7 +1101,7 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
>
<input
disabled={mergedDisabled[1]}
readOnly={inputReadOnly || !endTyping}
readOnly={inputReadOnly || typeof formatList[0] === 'function' || !endTyping}
value={endHoverValue || endText}
onChange={e => {
triggerEndTextChange(e.target.value);
Expand Down
7 changes: 4 additions & 3 deletions src/hooks/useValueTexts.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import shallowEqual from 'shallowequal';
import useMemo from 'rc-util/lib/hooks/useMemo';
import { GenerateConfig } from '../generate';
import { Locale } from '../interface';
import { CustomFormat, Locale } from '../interface';
import { formatValue } from '../utils/dateUtil';

export interface ValueTextConfig<DateType> {
formatList: string[];
formatList: Array<string | CustomFormat<DateType>>;
generateConfig: GenerateConfig<DateType>;
locale: Locale;
}
Expand All @@ -25,7 +26,7 @@ export default function useValueTexts<DateType>(

for (let i = 0; i < formatList.length; i += 1) {
const format = formatList[i];
const formatStr = generateConfig.locale.format(locale.locale, value, format);
const formatStr = formatValue(value, { generateConfig, locale, format });
fullValueTexts.push(formatStr);

if (i === 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,5 @@ export type RangeList = {
onMouseEnter: () => void;
onMouseLeave: () => void;
}[];

export type CustomFormat<DateType> = (value: DateType) => string;
38 changes: 37 additions & 1 deletion src/utils/dateUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GenerateConfig } from '../generate';
import { NullableDateType, PickerMode } from '../interface';
import { NullableDateType, PickerMode, Locale, CustomFormat } from '../interface';

export const WEEK_DAY_COUNT = 7;

Expand Down Expand Up @@ -192,3 +192,39 @@ export function getClosingViewDate<DateType>(
return generateConfig.addMonth(viewDate, offset);
}
}

export function formatValue<DateType>(
value: DateType,
{
generateConfig,
locale,
format,
}: {
generateConfig: GenerateConfig<DateType>;
locale: Locale;
format: string | CustomFormat<DateType>;
},
) {
return typeof format === 'function'
? format(value)
: generateConfig.locale.format(locale.locale, value, format);
}

export function parseValue<DateType>(
value: string,
{
generateConfig,
locale,
formatList,
}: {
generateConfig: GenerateConfig<DateType>;
locale: Locale;
formatList: Array<string | CustomFormat<DateType>>;
},
) {
if (!value || typeof formatList[0] === 'function') {
return null;
}

return generateConfig.locale.parse(locale.locale, value, formatList as string[]);
}
17 changes: 12 additions & 5 deletions src/utils/uiUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import KeyCode from 'rc-util/lib/KeyCode';
import { PanelMode, PickerMode } from '../interface';
import { GenerateConfig } from '../generate';
import { CustomFormat, PanelMode, PickerMode } from '../interface';

const scrollIds = new Map<HTMLElement, number>();

Expand Down Expand Up @@ -120,8 +121,8 @@ export function createKeyDownHandler(
}

// ===================== Format =====================
export function getDefaultFormat(
format: string | string[] | undefined,
export function getDefaultFormat<DateType>(
format: string | CustomFormat<DateType> | Array<string | CustomFormat<DateType>> | undefined,
picker: PickerMode | undefined,
showTime: boolean | object | undefined,
use12Hours: boolean | undefined,
Expand Down Expand Up @@ -157,9 +158,15 @@ export function getDefaultFormat(
return mergedFormat;
}

export function getInputSize(picker: PickerMode | undefined, format: string) {
export function getInputSize<DateType>(
picker: PickerMode | undefined,
format: string | CustomFormat<DateType>,
generateConfig: GenerateConfig<DateType>,
) {
const defaultSize = picker === 'time' ? 8 : 10;
return Math.max(defaultSize, format.length) + 2;
const length =
typeof format === 'function' ? format(generateConfig.getNow()).length : format.length;
return Math.max(defaultSize, length) + 2;
}

// ===================== Window =====================
Expand Down
21 changes: 21 additions & 0 deletions tests/picker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { act } from 'react-dom/test-utils';
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
import KeyCode from 'rc-util/lib/KeyCode';
import { resetWarned } from 'rc-util/lib/warning';
import { Moment } from 'moment';
import { PanelMode, PickerMode } from '../src/interface';
import { mount, getMoment, isSame, MomentPicker } from './util/commonUtil';

Expand Down Expand Up @@ -725,6 +726,26 @@ describe('Picker.Basic', () => {
expect(wrapper.find('input').prop('value')).toEqual('20000101');
});

it('custom format', () => {
const wrapper = mount(
<MomentPicker
allowClear
defaultValue={getMoment('2020-09-17')}
format={[(val: Moment) => `custom format:${val.format('YYYYMMDD')}`, 'YYYY-MM-DD']}
/>,
);
expect(wrapper.find('input').prop('readOnly')).toBeTruthy();
wrapper.openPicker();
wrapper.selectCell(24);
wrapper.closePicker();
expect(wrapper.find('input').prop('value')).toEqual('custom format:20200924');

// clear
const clearNode = wrapper.find('.rc-picker-clear');
expect(clearNode.simulate.bind(clearNode, 'mouseUp')).not.toThrow();
expect(wrapper.find('input').prop('value')).toEqual('');
});

it('panelRender', () => {
const wrapper = mount(<MomentPicker open panelRender={() => <h1>Light</h1>} />);
expect(wrapper.render()).toMatchSnapshot();
Expand Down
Loading

0 comments on commit 3785bc7

Please sign in to comment.