Date 支持配置 overlayPlacement

This commit is contained in:
2betop 2020-01-02 11:02:07 +08:00
parent 8f77a1e6f6
commit 2b0168176a
4 changed files with 107 additions and 98 deletions

View File

@ -2,14 +2,16 @@
表单项集合中,默认都是一行一个,如果想要一行多个,请用 Group 包裹起来。 表单项集合中,默认都是一行一个,如果想要一行多个,请用 Group 包裹起来。
- `type` 请设置成 `group` - `type` 请设置成 `group`
- `controls` 表单项集合。 - `controls` 表单项集合。
- `mode` 展示默认,跟 [Form](./Form.md) 中的模式一样,选择: `normal`、`horizontal`或者`inline`。 - `mode` 展示默认,跟 [Form](./Form.md) 中的模式一样,选择: `normal`、`horizontal`或者`inline`。
- `horizontal` 当为水平模式时,用来控制左右占比。 - `direction` 可以配置水平展示还是垂直展示。对应的配置项分别是:`vertical`、`horizontal`
- `horizontal.label` 左边 label 的宽度占比。 - `horizontal` 当为水平模式时,用来控制左右占比。
- `horizontal.right` 右边控制器的宽度占比。 - `horizontal.label` 左边 label 的宽度占比。
- `horizontal.offset` 当没有设置 label 时,右边控制器的偏移量。 - `horizontal.right` 右边控制器的宽度占比。
- `className` CSS 类名。 - `horizontal.offset` 当没有设置 label 时,右边控制器的偏移量。
- `className` CSS 类名。
- `label` Group 也可以配置个 label 来展示标题。
```schema:height="360" scope="body" ```schema:height="360" scope="body"
{ {

View File

@ -225,7 +225,8 @@
max-width: unset; max-width: unset;
margin: px2rem(30px); margin: px2rem(30px);
.#{$ns}Modal-body { > .#{$ns}Modal-body {
height: 0;
overflow: auto; overflow: auto;
} }
} }

View File

@ -4,85 +4,85 @@
* @author fex * @author fex
*/ */
import React from 'react'; import React from "react";
import cx from 'classnames'; import cx from "classnames";
import moment from 'moment'; import moment from "moment";
import 'moment/locale/zh-cn'; import "moment/locale/zh-cn";
import {Icon} from './icons'; import { Icon } from "./icons";
import PopOver from './PopOver'; import PopOver from "./PopOver";
import Overlay from './Overlay'; import Overlay from "./Overlay";
import {ClassNamesFn, themeable} from '../theme'; import { ClassNamesFn, themeable } from "../theme";
import {PlainObject} from '../types'; import { PlainObject } from "../types";
import Calendar from './calendar/Calendar'; import Calendar from "./calendar/Calendar";
const availableShortcuts: {[propName: string]: any} = { const availableShortcuts: { [propName: string]: any } = {
today: { today: {
label: '今天', label: "今天",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('day'); return now.startOf("day");
} }
}, },
yesterday: { yesterday: {
label: '昨天', label: "昨天",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(-1, 'days').startOf('day'); return now.add(-1, "days").startOf("day");
} }
}, },
thisweek: { thisweek: {
label: '本周一', label: "本周一",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('week').add(-1, 'weeks'); return now.startOf("week").add(-1, "weeks");
} }
}, },
thismonth: { thismonth: {
label: '本月初', label: "本月初",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('month'); return now.startOf("month");
} }
}, },
prevmonth: { prevmonth: {
label: '上个月初', label: "上个月初",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('month').add(-1, 'month'); return now.startOf("month").add(-1, "month");
} }
}, },
prevquarter: { prevquarter: {
label: '上个季节初', label: "上个季节初",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('quarter').add(-1, 'quarter'); return now.startOf("quarter").add(-1, "quarter");
} }
}, },
thisquarter: { thisquarter: {
label: '本季度初', label: "本季度初",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.startOf('quarter'); return now.startOf("quarter");
} }
}, },
tomorrow: { tomorrow: {
label: '明天', label: "明天",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(1, 'days').startOf('day'); return now.add(1, "days").startOf("day");
} }
}, },
endofthisweek: { endofthisweek: {
label: '本周日', label: "本周日",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.endOf('week'); return now.endOf("week");
} }
}, },
endofthismonth: { endofthismonth: {
label: '本月底', label: "本月底",
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.endOf('month'); return now.endOf("month");
} }
} }
}; };
@ -94,7 +94,7 @@ const advancedShortcuts = [
return { return {
label: `${days}天前`, label: `${days}天前`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.subtract(days, 'days'); return now.subtract(days, "days");
} }
}; };
} }
@ -105,7 +105,7 @@ const advancedShortcuts = [
return { return {
label: `${days}天后`, label: `${days}天后`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(days, 'days'); return now.add(days, "days");
} }
}; };
} }
@ -116,7 +116,7 @@ const advancedShortcuts = [
return { return {
label: `${weeks}周前`, label: `${weeks}周前`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.subtract(weeks, 'weeks'); return now.subtract(weeks, "weeks");
} }
}; };
} }
@ -127,7 +127,7 @@ const advancedShortcuts = [
return { return {
label: `${weeks}周后`, label: `${weeks}周后`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(weeks, 'weeks'); return now.add(weeks, "weeks");
} }
}; };
} }
@ -138,7 +138,7 @@ const advancedShortcuts = [
return { return {
label: `${months}月前`, label: `${months}月前`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.subtract(months, 'months'); return now.subtract(months, "months");
} }
}; };
} }
@ -149,7 +149,7 @@ const advancedShortcuts = [
return { return {
label: `${months}月后`, label: `${months}月后`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(months, 'months'); return now.add(months, "months");
} }
}; };
} }
@ -160,7 +160,7 @@ const advancedShortcuts = [
return { return {
label: `${quarters}季度前`, label: `${quarters}季度前`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.subtract(quarters, 'quarters'); return now.subtract(quarters, "quarters");
} }
}; };
} }
@ -171,7 +171,7 @@ const advancedShortcuts = [
return { return {
label: `${quarters}季度后`, label: `${quarters}季度后`,
date: (now: moment.Moment) => { date: (now: moment.Moment) => {
return now.add(quarters, 'quarters'); return now.add(quarters, "quarters");
} }
}; };
} }
@ -198,7 +198,7 @@ export type ShortCuts =
| ShortCutDateRange; | ShortCutDateRange;
export interface DateProps { export interface DateProps {
viewMode: 'years' | 'months' | 'days' | 'time'; viewMode: "years" | "months" | "days" | "time";
className?: string; className?: string;
classPrefix: string; classPrefix: string;
classnames: ClassNamesFn; classnames: ClassNamesFn;
@ -219,6 +219,7 @@ export interface DateProps {
onChange: (value: any) => void; onChange: (value: any) => void;
value: any; value: any;
shortcuts: string | Array<ShortCuts>; shortcuts: string | Array<ShortCuts>;
overlayPlacement: string;
[propName: string]: any; [propName: string]: any;
} }
@ -231,11 +232,12 @@ export interface DatePickerState {
export class DatePicker extends React.Component<DateProps, DatePickerState> { export class DatePicker extends React.Component<DateProps, DatePickerState> {
static defaultProps: Pick< static defaultProps: Pick<
DateProps, DateProps,
'viewMode' | 'shortcuts' | 'closeOnSelect' "viewMode" | "shortcuts" | "closeOnSelect" | "overlayPlacement"
> = { > = {
viewMode: 'days', viewMode: "days",
shortcuts: '', shortcuts: "",
closeOnSelect: true closeOnSelect: true,
overlayPlacement: "auto"
}; };
state: DatePickerState = { state: DatePickerState = {
isOpened: false, isOpened: false,
@ -302,7 +304,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
} }
handleKeyPress(e: React.KeyboardEvent) { handleKeyPress(e: React.KeyboardEvent) {
if (e.key === ' ') { if (e.key === " ") {
this.handleClick(); this.handleClick();
} }
} }
@ -336,7 +338,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const onChange = this.props.onChange; const onChange = this.props.onChange;
onChange(''); onChange("");
} }
handleChange(value: moment.Moment) { handleChange(value: moment.Moment) {
@ -354,9 +356,9 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
return; return;
} }
if (minTime && value && value.isBefore(minTime, 'second')) { if (minTime && value && value.isBefore(minTime, "second")) {
value = minTime; value = minTime;
} else if (maxTime && value && value.isAfter(maxTime, 'second')) { } else if (maxTime && value && value.isAfter(maxTime, "second")) {
value = maxTime; value = maxTime;
} }
@ -368,7 +370,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
} }
selectRannge(item: any) { selectRannge(item: any) {
const {closeOnSelect} = this.props; const { closeOnSelect } = this.props;
const now = moment(); const now = moment();
this.handleChange(item.date(now)); this.handleChange(item.date(now));
@ -376,11 +378,11 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
} }
checkIsValidDate(currentDate: moment.Moment) { checkIsValidDate(currentDate: moment.Moment) {
const {minDate, maxDate} = this.props; const { minDate, maxDate } = this.props;
if (minDate && currentDate.isBefore(minDate, 'day')) { if (minDate && currentDate.isBefore(minDate, "day")) {
return false; return false;
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) { } else if (maxDate && currentDate.isAfter(maxDate, "day")) {
return false; return false;
} }
@ -420,10 +422,10 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
if (!shortcuts) { if (!shortcuts) {
return null; return null;
} }
const {classPrefix: ns} = this.props; const { classPrefix: ns } = this.props;
let shortcutArr: Array<string | ShortCuts>; let shortcutArr: Array<string | ShortCuts>;
if (typeof shortcuts === 'string') { if (typeof shortcuts === "string") {
shortcutArr = shortcuts.split(','); shortcutArr = shortcuts.split(",");
} else { } else {
shortcutArr = shortcuts; shortcutArr = shortcuts;
} }
@ -434,7 +436,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
return null; return null;
} }
let shortcut: PlainObject = {}; let shortcut: PlainObject = {};
if (typeof item === 'string') { if (typeof item === "string") {
shortcut = this.getAvailableShortcuts(item); shortcut = this.getAvailableShortcuts(item);
shortcut.key = item; shortcut.key = item;
} else if ((item as ShortCutDate).date) { } else if ((item as ShortCutDate).date) {
@ -473,7 +475,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
clearable, clearable,
shortcuts, shortcuts,
utc, utc,
closeOnSelect overlayPlacement
} = this.props; } = this.props;
const isOpened = this.state.isOpened; const isOpened = this.state.isOpened;
@ -488,8 +490,8 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
className={cx( className={cx(
`${ns}DatePicker`, `${ns}DatePicker`,
{ {
'is-disabled': disabled, "is-disabled": disabled,
'is-focused': this.state.isFocused "is-focused": this.state.isFocused
}, },
className className
)} )}
@ -517,6 +519,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
target={this.getTarget} target={this.getTarget}
container={popOverContainer || this.getParent} container={popOverContainer || this.getParent}
rootClose={false} rootClose={false}
placement={overlayPlacement}
show show
> >
<PopOver <PopOver

View File

@ -1,10 +1,10 @@
import React from 'react'; import React from "react";
import {FormItem, FormControlProps} from './Item'; import { FormItem, FormControlProps } from "./Item";
import cx from 'classnames'; import cx from "classnames";
import {filterDate} from '../../utils/tpl-builtin'; import { filterDate } from "../../utils/tpl-builtin";
import moment from 'moment'; import moment from "moment";
import 'moment/locale/zh-cn'; import "moment/locale/zh-cn";
import DatePicker from '../../components/DatePicker'; import DatePicker from "../../components/DatePicker";
export interface DateProps extends FormControlProps { export interface DateProps extends FormControlProps {
placeholder?: string; placeholder?: string;
@ -22,18 +22,21 @@ interface DateControlState {
maxDate?: moment.Moment; maxDate?: moment.Moment;
} }
export default class DateControl extends React.PureComponent<DateProps> { export default class DateControl extends React.PureComponent<
DateProps,
DateControlState
> {
static defaultProps = { static defaultProps = {
format: 'X', format: "X",
viewMode: 'days', viewMode: "days",
inputFormat: 'YYYY-MM-DD', inputFormat: "YYYY-MM-DD",
timeConstrainst: { timeConstrainst: {
minutes: { minutes: {
step: 1 step: 1
} }
}, },
clearable: true, clearable: true,
iconClassName: 'fa fa-calendar' iconClassName: "fa fa-calendar"
}; };
componentWillMount() { componentWillMount() {
@ -85,60 +88,60 @@ export default class DateControl extends React.PureComponent<DateProps> {
render() { render() {
const { const {
className, className,
classPrefix: ns,
defaultValue, defaultValue,
defaultData, defaultData,
classnames: cx,
...rest ...rest
} = this.props; } = this.props;
return ( return (
<div className={cx(`${ns}DateControl`, className)}> <div className={cx(`DateControl`, className)}>
<DatePicker {...rest} {...this.state} classPrefix={ns} /> <DatePicker {...rest} {...this.state} classnames={cx} />
</div> </div>
); );
} }
} }
@FormItem({ @FormItem({
type: 'date', type: "date",
weight: -150 weight: -150
}) })
export class DateControlRenderer extends DateControl { export class DateControlRenderer extends DateControl {
static defaultProps = { static defaultProps = {
...DateControl.defaultProps, ...DateControl.defaultProps,
placeholder: '请选择日期', placeholder: "请选择日期",
dateFormat: 'YYYY-MM-DD', dateFormat: "YYYY-MM-DD",
timeFormat: '', timeFormat: "",
strictMode: false strictMode: false
}; };
} }
@FormItem({ @FormItem({
type: 'datetime' type: "datetime"
}) })
export class DatetimeControlRenderer extends DateControl { export class DatetimeControlRenderer extends DateControl {
static defaultProps = { static defaultProps = {
...DateControl.defaultProps, ...DateControl.defaultProps,
placeholder: '请选择日期以及时间', placeholder: "请选择日期以及时间",
inputFormat: 'YYYY-MM-DD HH:mm:ss', inputFormat: "YYYY-MM-DD HH:mm:ss",
dateFormat: 'LL', dateFormat: "LL",
timeFormat: 'HH:mm:ss', timeFormat: "HH:mm:ss",
closeOnSelect: false, closeOnSelect: false,
strictMode: false strictMode: false
}; };
} }
@FormItem({ @FormItem({
type: 'time' type: "time"
}) })
export class TimeControlRenderer extends DateControl { export class TimeControlRenderer extends DateControl {
static defaultProps = { static defaultProps = {
...DateControl.defaultProps, ...DateControl.defaultProps,
placeholder: '请选择时间', placeholder: "请选择时间",
inputFormat: 'HH:mm', inputFormat: "HH:mm",
dateFormat: '', dateFormat: "",
timeFormat: 'HH:mm', timeFormat: "HH:mm",
viewMode: 'time', viewMode: "time",
closeOnSelect: false closeOnSelect: false
}; };
} }