Skip to content

Commit

Permalink
feat(DateInputRange): 增加时间区间选择组件 (#536) (#568)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullptr-z committed Feb 28, 2022
1 parent e1a154c commit 6f6198b
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 50 deletions.
139 changes: 100 additions & 39 deletions packages/react-date-input/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ DateInput 日期输入框
[![npm version](https://img.shields.io/npm/v/@uiw/react-date-input.svg?label=@uiw/react-date-input)](https://npmjs.com/@uiw/react-date-input)

显示一个月的日历,并允许用户选择单个日期。
在v4.12.3版本中增加 DateInputRange组件

```jsx
import { DateInput } from 'uiw';
import { DateInput, DateInputRange } from 'uiw';
// or
import DateInput from '@uiw/react-date-input';
import DateInput,{ DateInputRange } from '@uiw/react-date-input';
```

## 基本使用
Expand All @@ -19,32 +20,46 @@ import DateInput from '@uiw/react-date-input';
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { DateInput, Row, Col } from 'uiw';
import { DateInput, DateInputRange, Row, Col } from 'uiw';

class Demo extends React.Component {
onChange(selectedDate) {
console.log('selectedDate:', selectedDate)
function Demo () {

const [dataRange,dataRangeSet] =React.useState(['2022-02-25 15:06:24','2022-02-27 14:47:32'])

function onChange(selectedDate,dataRange) {
console.log('selectedDate',selectedDate,dataRange)
}
render() {
return (
<Row gutter={10} style={{ maxWidth: 360 }}>
<Col fixed>
<DateInput
value={new Date()}
datePickerProps={{ todayButton: '今天' }}
onChange={this.onChange.bind(this)}
/>
</Col>
<Col>
<DateInput
value={new Date()}
disabled
onChange={this.onChange.bind(this)}
/>
</Col>
</Row>
<div>
<Row gutter={10} style={{ maxWidth: 360,marginBottom:10 }}>
<Col fixed>
<DateInput
value={new Date()}
datePickerProps={{ todayButton: '今天' }}
onChange={onChange}
/>
</Col>
<Col>
<DateInput
value={new Date()}
disabled
onChange={onChange}
/>
</Col>
</Row>
<Row gutter={10}>
<Col>
<DateInputRange
bodyStyle={{width:350}}
format="YYYY/MM/DD HH:mm:ss"
value={dataRange}
datePickerProps={{ todayButton: '今天',showTime:true }}
onChange={onChange}
/>
</Col>
</Row>
</div>
)
}
}
ReactDOM.render(<Demo />, _mount_);
```
Expand All @@ -55,13 +70,26 @@ ReactDOM.render(<Demo />, _mount_);

<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { DateInput, Notify, Button, Form, Row, Col } from 'uiw';
import { DateInput,DateInputRange, Notify, Button, Form, Row, Col } from 'uiw';

ReactDOM.render(
<Form
onSubmit={({initial, current}) => {
if(current.date) {
function Demo(){
const form = React.useRef(null)

const resetDateRange = () => {
form.current.resetForm()
}

const setDateRange = () => {
form.current.setFields({dateRange:[new Date(),new Date()]})
}

return (
<Form
ref={form}
onSubmit={({ initial, current }) => {
if (current.date) {
Notify.success({
title: '提交成功!',
description: `表单提交时间成功,时间为:${current.date}`,
Expand All @@ -72,7 +100,6 @@ ReactDOM.render(
description: `表单提交时间成功,时间为:${current.date},将自动填充初始化值!`,
});
}
console.log('-->>', initial, current);
}}
fields={{
date: {
Expand All @@ -81,21 +108,38 @@ ReactDOM.render(
labelFor: 'date-inline',
children: <DateInput datePickerProps={{ todayButton: '今天' }} id="date-inline" />
},
dateRange: {
initialValue: ['2019/02/17', '2019/02/20'],
labelClassName: 'fieldLabel',
labelFor: 'date-inline',
children: <DateInputRange datePickerProps={{ todayButton: '今天' }} id="date-inline" />
},
}}
>
{({ fields, state, canSubmit }) => {
return (
<Row gutter={10}>
<Col fixed>{fields.date}</Col>
<Col>
<Button disabled={!canSubmit()} type="primary" htmlType="submit">提交</Button>
</Col>
</Row>
<div>
<Row gutter={10}>
<Col fixed>{fields.date}</Col>
</Row>
<Row gutter={10}>
<Col fixed>{fields.dateRange}</Col>
</Row>
<Row gutter={10}>
<Col>
<Button disabled={!canSubmit()} type="primary" htmlType="submit">提交</Button>
<Button onClick={resetDateRange} >重置</Button>
<Button onClick={setDateRange}>setValue</Button>
</Col>
</Row>
</div>
)
}}
</Form>,
_mount_
);
</Form>
)
}

ReactDOM.render(<Demo />, _mount_);
```

## 日期格式
Expand Down Expand Up @@ -166,3 +210,20 @@ ReactDOM.render(<Demo />, _mount_);
| disabled | 组件 [`<Input>`](#/components/input) 的属性,禁用日历 | Boolean | - |

更多属性文档请参考 [`<Input>`](#/components/input)

## DateInputRange

| 参数 | 说明 | 类型 | 默认值 |
|--------- |-------- |--------- |-------- |
| value | 初始时间值 | Array<Date, string> | - |
| placeholder | 输入框提示文字 | String | - |
| allowClear | 是否显示清除按钮 | Boolean | true |
| format | 格式化时间,规则查看 [`<formatter>`](#/components/formatter) 文档 | String | `YYYY/MM/DD` |
| onChange | 选择一天时调用。 | Function(selectedDate:Date, dateRange: Array<Date>) | - |
| popoverProps | 将参数传递给 [`<Popover>`](#/components/popover) 组件 | Object | - |
| datePickerProps | 将参数传递给 [`<DatePicker>`](#/components/date-picker) 组件 | Object | - |
| disabled | 组件 [`<Input>`](#/components/input) 的属性,禁用日历 | Boolean | - |
| bodyStyle | 选择框样式 | Object | { width: 300 } | - |

更多属性文档请参考 [`<Input>`](#/components/input)

112 changes: 112 additions & 0 deletions packages/react-date-input/src/DateInputRange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { useEffect, useState } from 'react';
import Input, { InputProps } from '@uiw/react-input';
import Popover, { PopoverProps } from '@uiw/react-popover';
import DatePicker, { DatePickerProps } from '@uiw/react-date-picker';
import Icon from '@uiw/react-icon';
import { IProps } from '@uiw/utils';
import formatter from '@uiw/formatter';
import './style/date-input-range.less';

export interface DateInputRangeProps<V> extends IProps, Omit<InputProps, 'onChange' | 'value'> {
popoverProps?: PopoverProps;
datePickerProps?: DatePickerProps;
value?: Array<V>;
format?: string;
allowClear?: boolean;
bodyStyle?: object;
onChange?: (selectedDate?: Date, dateRange?: Array<Date | undefined>) => void;
}

export function DateInputRange<V extends string | Date>(props: DateInputRangeProps<V>) {
const {
prefixCls = 'w-dateinputrange',
bodyStyle = undefined,
className,
popoverProps,
datePickerProps,
allowClear = true,
format = 'YYYY/MM/DD',
onChange,
value,
...inputProps
} = props;

const [dateRange, setDateRange] = useState<Array<Date | undefined>>([]);
useEffect(() => {
let valueTemp: Array<Date> = [];
const propsValue = value;
if (Array.isArray(propsValue) && !!propsValue?.length) {
propsValue.forEach((date, index) => {
valueTemp[index] = typeof propsValue[index] === 'string' ? new Date(date) : (date as Date);
});
}
setDateRange(valueTemp);
}, [JSON.stringify(value)]);

function handleChange(cdate: Date | undefined, idx?: number) {
const changeValue = [...dateRange];
changeValue[idx!] = cdate;
setDateRange(changeValue);
onChange && onChange(cdate, changeValue);
}

return (
<div
className={[`${prefixCls}-contents`, `${prefixCls}-inner`].filter(Boolean).join(' ').trim()}
style={{ width: 300, ...bodyStyle }}
>
<Popover
trigger="focus"
placement="bottomLeft"
autoAdjustOverflow
{...popoverProps}
content={
<DatePicker
date={dateRange[0]}
className={`${prefixCls}-popover`}
{...datePickerProps}
onChange={(selectedDate) => handleChange(selectedDate, 0)}
/>
}
>
<Input
placeholder="请选择日期"
readOnly
{...(inputProps as InputProps)}
// onChange={(v) => console.log('v', v)}
value={dateRange[0] ? formatter(format, dateRange[0]) : ''}
className={[prefixCls, className].filter(Boolean).join(' ').trim()}
/>
</Popover>

<Icon type="swap-right" verticalAlign="baseline" style={{ fontSize: 21, top: -1, margin: '0px 8px 0px 5px' }} />

<Popover
trigger="focus"
placement="bottomLeft"
autoAdjustOverflow
{...popoverProps}
content={
<DatePicker
date={dateRange[1]}
className={`${prefixCls}-popover`}
{...datePickerProps}
onChange={(selectedDate) => handleChange(selectedDate, 1)}
/>
}
>
<Input
placeholder="请选择日期"
readOnly
{...(inputProps as InputProps)}
value={dateRange[1] ? formatter(format, dateRange[1]) : ''}
// onChange={(v) => console.log('v2', v)}
className={[prefixCls, className].filter(Boolean).join(' ').trim()}
/>
</Popover>
{allowClear && dateRange.length > 0 && (
<Icon className={`${prefixCls}-close-btn`} color="#ccc" onClick={() => setDateRange([])} type="close" />
)}
</div>
);
}
1 change: 1 addition & 0 deletions packages/react-date-input/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DatePicker, { DatePickerProps } from '@uiw/react-date-picker';
import Icon from '@uiw/react-icon';
import { IProps } from '@uiw/utils';
import formatter from '@uiw/formatter';
export * from './DateInputRange';
import './style/index.less';

export interface DateInputProps extends IProps, Omit<InputProps, 'onChange' | 'value'> {
Expand Down
68 changes: 68 additions & 0 deletions packages/react-date-input/src/style/date-input-range.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@dateinputrange-prefix: ~'w-dateinputrange';

.@{dateinputrange-prefix} {
&-contents {
display: flex;
justify-content: space-between;
input {
box-shadow: none;
padding: 0px;
height: 20px;
}

.w-input-inner {
&:hover {
box-shadow: none !important;
}

&:focus {
box-shadow: none !important;
}
}
}

&-inner {
display: flex;
// overflow: hidden;
justify-content: space-between;
outline: none;
border: none;
align-items: center;
border-radius: 3px;
box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.15),
inset 0 1px 1px rgba(16, 22, 26, 0.2);
box-sizing: border-box;
background: #fff;
min-height: 30px;
margin: 0 !important;
padding: 3px 10px 3px 10px;
vertical-align: middle;
line-height: 30px;
color: #393e48;
font-weight: 400;
font-size: inherit;
transition: box-shadow 0.3s cubic-bezier(0.4, 1, 0.75, 0.9);
appearance: none;

&:focus {
box-shadow: 0 0 0 1px #393e48, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2);
}

&:hover {
box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0), inset 0 1px 1px rgba(16, 22, 26, 0.2);
}

&:focus&:hover {
box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2);
}

&:disabled {
box-shadow: none;
background: #dddddd;
opacity: 0.75;
color: #a5a5a5;
cursor: not-allowed;
resize: none;
}
}
}
Loading

0 comments on commit 6f6198b

Please sign in to comment.