forked from p96170835/amis
refactor: 💡 set semi true
This commit is contained in:
parent
9e5c689d20
commit
81e123179c
|
@ -3,7 +3,7 @@
|
|||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"semi": true,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid"
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {themeable, ClassNamesFn} from '../theme'
|
||||
import * as React from 'react';
|
||||
import {themeable, ClassNamesFn} from '../theme';
|
||||
|
||||
interface NotFoundProps {
|
||||
code?: string | number
|
||||
description?: string
|
||||
links?: React.ReactNode
|
||||
footerText?: React.ReactNode
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
code?: string | number;
|
||||
description?: string;
|
||||
links?: React.ReactNode;
|
||||
footerText?: React.ReactNode;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class NotFound extends React.Component<NotFoundProps, any> {
|
||||
render() {
|
||||
const {links, footerText, description, children, code} = this.props
|
||||
const {links, footerText, description, children, code} = this.props;
|
||||
|
||||
return (
|
||||
<div className="container w-xxl w-auto-xs">
|
||||
|
@ -38,8 +38,8 @@ export class NotFound extends React.Component<NotFoundProps, any> {
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(NotFound)
|
||||
export default themeable(NotFound);
|
||||
|
|
|
@ -3,62 +3,62 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {render} from 'react-dom'
|
||||
import Modal from './Modal'
|
||||
import Button from './Button'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import Modal from './Modal';
|
||||
import Button from './Button';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface AlertProps {
|
||||
container?: any
|
||||
confirmText?: string
|
||||
cancelText?: string
|
||||
title?: string
|
||||
confirmBtnLevel?: string
|
||||
alertBtnLevel?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
theme?: string
|
||||
container?: any;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
title?: string;
|
||||
confirmBtnLevel?: string;
|
||||
alertBtnLevel?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
export interface AlertState {
|
||||
show: boolean
|
||||
title?: string
|
||||
content: string
|
||||
confirm: boolean
|
||||
show: boolean;
|
||||
title?: string;
|
||||
content: string;
|
||||
confirm: boolean;
|
||||
}
|
||||
|
||||
export class Alert extends React.Component<AlertProps, AlertState> {
|
||||
static instance: any = null
|
||||
static instance: any = null;
|
||||
static getInstance() {
|
||||
if (!Alert.instance) {
|
||||
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了')
|
||||
const container = document.body
|
||||
const div = document.createElement('div')
|
||||
container.appendChild(div)
|
||||
render(<ThemedAlert />, div)
|
||||
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了');
|
||||
const container = document.body;
|
||||
const div = document.createElement('div');
|
||||
container.appendChild(div);
|
||||
render(<ThemedAlert />, div);
|
||||
}
|
||||
|
||||
return Alert.instance
|
||||
return Alert.instance;
|
||||
}
|
||||
|
||||
_resolve: (value: any) => void
|
||||
_modal: any
|
||||
_body: any
|
||||
_resolve: (value: any) => void;
|
||||
_modal: any;
|
||||
_body: any;
|
||||
state: AlertState = {
|
||||
show: false,
|
||||
title: '',
|
||||
content: '',
|
||||
confirm: false,
|
||||
}
|
||||
};
|
||||
constructor(props: AlertProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.close = this.close.bind(this)
|
||||
this.handleConfirm = this.handleConfirm.bind(this)
|
||||
this.handleCancel = this.handleCancel.bind(this)
|
||||
this.modalRef = this.modalRef.bind(this)
|
||||
this.bodyRef = this.bodyRef.bind(this)
|
||||
this.close = this.close.bind(this);
|
||||
this.handleConfirm = this.handleConfirm.bind(this);
|
||||
this.handleCancel = this.handleCancel.bind(this);
|
||||
this.modalRef = this.modalRef.bind(this);
|
||||
this.bodyRef = this.bodyRef.bind(this);
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
|
@ -67,43 +67,43 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
title: '系统消息',
|
||||
alertBtnLevel: 'primary',
|
||||
confirmBtnLevel: 'danger',
|
||||
}
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
Alert.instance = this
|
||||
Alert.instance = this;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._body && (this._body.innerHTML = this.state.content)
|
||||
this._body && (this._body.innerHTML = this.state.content);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: AlertProps, prevState: AlertState) {
|
||||
if (prevState.content !== this.state.content) {
|
||||
this._body && (this._body.innerHTML = this.state.content)
|
||||
this._body && (this._body.innerHTML = this.state.content);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Alert.instance = null
|
||||
Alert.instance = null;
|
||||
}
|
||||
|
||||
handleConfirm() {
|
||||
this.close(true)
|
||||
this.close(true);
|
||||
}
|
||||
|
||||
handleCancel() {
|
||||
this.close(false)
|
||||
this.close(false);
|
||||
}
|
||||
|
||||
close(confirmed: boolean) {
|
||||
const isConfirm = this.state.confirm
|
||||
const isConfirm = this.state.confirm;
|
||||
|
||||
this.setState(
|
||||
{
|
||||
show: false,
|
||||
},
|
||||
isConfirm ? () => this._resolve(confirmed) /*this._reject()*/ : undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
alert(content: string, title?: string) {
|
||||
|
@ -112,7 +112,7 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
content,
|
||||
show: true,
|
||||
confirm: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
confirm(content: string, title?: string) {
|
||||
|
@ -121,20 +121,20 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
content,
|
||||
show: true,
|
||||
confirm: true,
|
||||
})
|
||||
});
|
||||
|
||||
return new Promise(resolve => {
|
||||
this._resolve = resolve
|
||||
})
|
||||
this._resolve = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
modalRef(ref: any) {
|
||||
this._modal = ref
|
||||
this._modal = ref;
|
||||
}
|
||||
|
||||
bodyRef(ref: any) {
|
||||
this._body = ref
|
||||
this._body && (this._body.innerHTML = this.state.content)
|
||||
this._body = ref;
|
||||
this._body && (this._body.innerHTML = this.state.content);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -147,7 +147,7 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
alertBtnLevel,
|
||||
classnames: cx,
|
||||
classPrefix,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
return (
|
||||
<Modal show={this.state.show} onHide={this.handleCancel} container={container} ref={this.modalRef}>
|
||||
<div className={cx('Modal-header')}>
|
||||
|
@ -163,13 +163,13 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const alert: (content: string, title?: string) => void = (content, title) =>
|
||||
Alert.getInstance().alert(content, title)
|
||||
Alert.getInstance().alert(content, title);
|
||||
export const confirm: (content: string, title?: string) => Promise<any> = (content, title) =>
|
||||
Alert.getInstance().confirm(content, title)
|
||||
export const ThemedAlert = themeable(Alert)
|
||||
export default ThemedAlert
|
||||
Alert.getInstance().confirm(content, title);
|
||||
export const ThemedAlert = themeable(Alert);
|
||||
export default ThemedAlert;
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface AlertProps {
|
||||
level: 'danger' | 'info' | 'success' | 'warning'
|
||||
className: string
|
||||
showCloseButton: boolean
|
||||
onClose?: () => void
|
||||
classnames: ClassNamesFn
|
||||
classPrefix: string
|
||||
level: 'danger' | 'info' | 'success' | 'warning';
|
||||
className: string;
|
||||
showCloseButton: boolean;
|
||||
onClose?: () => void;
|
||||
classnames: ClassNamesFn;
|
||||
classPrefix: string;
|
||||
}
|
||||
|
||||
export interface AlertState {
|
||||
show: boolean
|
||||
show: boolean;
|
||||
}
|
||||
|
||||
export class Alert extends React.Component<AlertProps, AlertState> {
|
||||
|
@ -24,16 +24,16 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
level: 'info',
|
||||
className: '',
|
||||
showCloseButton: false,
|
||||
}
|
||||
static propsList: Array<string> = ['level', 'className', 'showCloseButton', 'onClose']
|
||||
};
|
||||
static propsList: Array<string> = ['level', 'className', 'showCloseButton', 'onClose'];
|
||||
|
||||
constructor(props: AlertProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.state = {
|
||||
show: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
|
@ -42,11 +42,11 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
show: false,
|
||||
},
|
||||
this.props.onClose
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx, className, level, children, showCloseButton} = this.props
|
||||
const {classnames: cx, className, level, children, showCloseButton} = this.props;
|
||||
|
||||
return this.state.show ? (
|
||||
<div className={cx('Alert', level ? `Alert--${level}` : '', className)}>
|
||||
|
@ -57,8 +57,8 @@ export class Alert extends React.Component<AlertProps, AlertState> {
|
|||
) : null}
|
||||
{children}
|
||||
</div>
|
||||
) : null
|
||||
) : null;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Alert)
|
||||
export default themeable(Alert);
|
||||
|
|
|
@ -4,46 +4,46 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {mapTree} from '../utils/helper'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {mapTree} from '../utils/helper';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export type LinkItem = LinkItemProps
|
||||
export type LinkItem = LinkItemProps;
|
||||
interface LinkItemProps {
|
||||
id?: number
|
||||
label: string
|
||||
hidden?: boolean
|
||||
open: boolean
|
||||
active: boolean
|
||||
className?: string
|
||||
children?: Array<LinkItem>
|
||||
id?: number;
|
||||
label: string;
|
||||
hidden?: boolean;
|
||||
open: boolean;
|
||||
active: boolean;
|
||||
className?: string;
|
||||
children?: Array<LinkItem>;
|
||||
}
|
||||
|
||||
interface Navigation {
|
||||
label: string
|
||||
children: Array<LinkItem>
|
||||
prefix?: JSX.Element
|
||||
affix?: JSX.Element
|
||||
className?: string
|
||||
[propName: string]: any
|
||||
label: string;
|
||||
children: Array<LinkItem>;
|
||||
prefix?: JSX.Element;
|
||||
affix?: JSX.Element;
|
||||
className?: string;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
interface AsideNavProps {
|
||||
id?: string
|
||||
className?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
renderLink: Function
|
||||
isActive: Function
|
||||
isOpen: (link: LinkItemProps) => boolean
|
||||
navigations: Array<Navigation>
|
||||
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, props: AsideNavProps) => React.ReactNode
|
||||
id?: string;
|
||||
className?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
renderLink: Function;
|
||||
isActive: Function;
|
||||
isOpen: (link: LinkItemProps) => boolean;
|
||||
navigations: Array<Navigation>;
|
||||
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, props: AsideNavProps) => React.ReactNode;
|
||||
}
|
||||
|
||||
interface AsideNavState {
|
||||
navigations: Array<Navigation>
|
||||
navigations: Array<Navigation>;
|
||||
}
|
||||
|
||||
export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
||||
|
@ -64,60 +64,60 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
|||
) : null,
|
||||
isActive: (link: LinkItem) => link.open,
|
||||
isOpen: (item: LinkItemProps) => (item.children ? item.children.some(item => item.open) : false),
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: AsideNavProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
const isOpen = props.isOpen
|
||||
let id = 1
|
||||
const isOpen = props.isOpen;
|
||||
let id = 1;
|
||||
this.state = {
|
||||
navigations: mapTree(
|
||||
props.navigations,
|
||||
(item: Navigation) => {
|
||||
const isActive =
|
||||
typeof item.active === 'undefined' ? (props.isActive as Function)(item) : item.active
|
||||
typeof item.active === 'undefined' ? (props.isActive as Function)(item) : item.active;
|
||||
|
||||
return {
|
||||
...item,
|
||||
id: id++,
|
||||
active: isActive,
|
||||
open: isActive || isOpen(item as LinkItemProps),
|
||||
}
|
||||
};
|
||||
},
|
||||
1,
|
||||
true
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
this.renderLink = this.renderLink.bind(this)
|
||||
this.toggleExpand = this.toggleExpand.bind(this)
|
||||
this.renderLink = this.renderLink.bind(this);
|
||||
this.toggleExpand = this.toggleExpand.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: AsideNavProps) {
|
||||
const props = this.props
|
||||
const isOpen = props.isOpen
|
||||
const props = this.props;
|
||||
const isOpen = props.isOpen;
|
||||
|
||||
if (props.navigations !== nextProps.navigations || props.isActive !== nextProps.isActive) {
|
||||
let id = 1
|
||||
let id = 1;
|
||||
this.setState({
|
||||
navigations: mapTree(
|
||||
nextProps.navigations,
|
||||
(item: Navigation) => {
|
||||
const isActive =
|
||||
typeof item.active === 'undefined' ? (nextProps.isActive as Function)(item) : item.active
|
||||
typeof item.active === 'undefined' ? (nextProps.isActive as Function)(item) : item.active;
|
||||
|
||||
return {
|
||||
...item,
|
||||
id: id++,
|
||||
active: isActive,
|
||||
open: isActive || isOpen(item as LinkItemProps),
|
||||
}
|
||||
};
|
||||
},
|
||||
1,
|
||||
true
|
||||
),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,11 +132,11 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
|||
1,
|
||||
true
|
||||
),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
renderLink(link: LinkItemProps, key: any, props: Partial<AsideNavProps> = {}, depth = 1): React.ReactNode {
|
||||
const {renderLink, isActive, renderSubLinks, classnames: cx, ...others} = this.props
|
||||
const {renderLink, isActive, renderSubLinks, classnames: cx, ...others} = this.props;
|
||||
|
||||
const dom = (renderLink as Function)({
|
||||
link,
|
||||
|
@ -146,10 +146,10 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
|||
depth,
|
||||
classnames: cx,
|
||||
...others,
|
||||
})
|
||||
});
|
||||
|
||||
if (!dom) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -163,24 +163,26 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
|||
{dom}
|
||||
{renderSubLinks(link, this.renderLink, depth, this.props)}
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const navigations = this.state.navigations
|
||||
let links: Array<React.ReactNode> = []
|
||||
const {className, classnames: cx} = this.props
|
||||
const navigations = this.state.navigations;
|
||||
let links: Array<React.ReactNode> = [];
|
||||
const {className, classnames: cx} = this.props;
|
||||
|
||||
navigations.forEach((navigation, index) => {
|
||||
if (navigation.prefix) {
|
||||
const prefix: JSX.Element =
|
||||
typeof navigation.prefix === 'function' ? (navigation.prefix as any)(this.props) : navigation.prefix
|
||||
typeof navigation.prefix === 'function'
|
||||
? (navigation.prefix as any)(this.props)
|
||||
: navigation.prefix;
|
||||
links.push(
|
||||
React.cloneElement(prefix, {
|
||||
...prefix.props,
|
||||
key: `${index}-prefix`,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
navigation.label &&
|
||||
|
@ -188,31 +190,31 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
|
|||
<li key={`${index}-label`} className={cx(`AsideNav-label`, navigation.className)}>
|
||||
<span>{navigation.label}</span>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
|
||||
navigation.children.forEach((item, key) => {
|
||||
const link = this.renderLink(item, `${index}-${key}`)
|
||||
link && links.push(link)
|
||||
})
|
||||
const link = this.renderLink(item, `${index}-${key}`);
|
||||
link && links.push(link);
|
||||
});
|
||||
|
||||
if (navigation.affix) {
|
||||
const affix: JSX.Element =
|
||||
typeof navigation.affix === 'function' ? (navigation.affix as any)(this.props) : navigation.affix
|
||||
typeof navigation.affix === 'function' ? (navigation.affix as any)(this.props) : navigation.affix;
|
||||
links.push(
|
||||
React.cloneElement(affix, {
|
||||
...affix.props,
|
||||
key: `${index}-affix`,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<nav className={cx(`AsideNav`, className)}>
|
||||
<ul className={cx(`AsideNav-list`)}>{links}</ul>
|
||||
</nav>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(AsideNav)
|
||||
export default themeable(AsideNav);
|
||||
|
|
|
@ -3,31 +3,31 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import TooltipWrapper, {TooltipObject, Trigger} from './TooltipWrapper'
|
||||
import {pickEventsProps} from '../utils/helper'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import TooltipWrapper, {TooltipObject, Trigger} from './TooltipWrapper';
|
||||
import {pickEventsProps} from '../utils/helper';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface ButtonProps
|
||||
extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
||||
id?: string
|
||||
className?: string
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg'
|
||||
type: 'button' | 'reset' | 'submit'
|
||||
level: string // 'link' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'danger' | 'light' | 'dark' | 'default';
|
||||
tooltip?: string | TooltipObject
|
||||
placement: 'top' | 'right' | 'bottom' | 'left'
|
||||
tooltipContainer?: any
|
||||
tooltipTrigger: Trigger | Array<Trigger>
|
||||
tooltipRootClose: boolean
|
||||
disabled?: boolean
|
||||
active?: boolean
|
||||
block?: boolean
|
||||
iconOnly?: boolean
|
||||
disabledTip?: string | TooltipObject
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
componentClass: React.ReactType
|
||||
id?: string;
|
||||
className?: string;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg';
|
||||
type: 'button' | 'reset' | 'submit';
|
||||
level: string; // 'link' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'danger' | 'light' | 'dark' | 'default';
|
||||
tooltip?: string | TooltipObject;
|
||||
placement: 'top' | 'right' | 'bottom' | 'left';
|
||||
tooltipContainer?: any;
|
||||
tooltipTrigger: Trigger | Array<Trigger>;
|
||||
tooltipRootClose: boolean;
|
||||
disabled?: boolean;
|
||||
active?: boolean;
|
||||
block?: boolean;
|
||||
iconOnly?: boolean;
|
||||
disabledTip?: string | TooltipObject;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
componentClass: React.ReactType;
|
||||
}
|
||||
|
||||
export class Button extends React.Component<ButtonProps> {
|
||||
|
@ -41,7 +41,7 @@ export class Button extends React.Component<ButtonProps> {
|
|||
placement: 'top',
|
||||
tooltipTrigger: ['hover', 'focus'],
|
||||
tooltipRootClose: false,
|
||||
}
|
||||
};
|
||||
|
||||
renderButton() {
|
||||
const {
|
||||
|
@ -58,7 +58,7 @@ export class Button extends React.Component<ButtonProps> {
|
|||
active,
|
||||
iconOnly,
|
||||
...rest
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Comp
|
||||
|
@ -80,7 +80,7 @@ export class Button extends React.Component<ButtonProps> {
|
|||
>
|
||||
{children}
|
||||
</Comp>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -94,7 +94,7 @@ export class Button extends React.Component<ButtonProps> {
|
|||
disabledTip,
|
||||
classPrefix,
|
||||
classnames: cx,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<TooltipWrapper
|
||||
|
@ -110,8 +110,8 @@ export class Button extends React.Component<ButtonProps> {
|
|||
this.renderButton()
|
||||
)}
|
||||
</TooltipWrapper>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Button)
|
||||
export default themeable(Button);
|
||||
|
|
|
@ -3,38 +3,38 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 'i-checks-sm',
|
||||
lg: 'i-checks-lg',
|
||||
small: 'i-checks-sm',
|
||||
large: 'i-checks-lg',
|
||||
}
|
||||
};
|
||||
|
||||
interface CheckboxProps {
|
||||
id?: string
|
||||
key?: string | number
|
||||
style?: React.CSSProperties
|
||||
type?: string
|
||||
size?: 'sm' | 'lg' | 'small' | 'large'
|
||||
label?: string
|
||||
className?: string
|
||||
onChange?: (value: any) => void
|
||||
value?: any
|
||||
containerClass?: string
|
||||
inline?: boolean
|
||||
trueValue?: boolean
|
||||
falseValue?: boolean
|
||||
disabled?: boolean
|
||||
readOnly?: boolean
|
||||
checked?: boolean
|
||||
name?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
partial?: boolean
|
||||
id?: string;
|
||||
key?: string | number;
|
||||
style?: React.CSSProperties;
|
||||
type?: string;
|
||||
size?: 'sm' | 'lg' | 'small' | 'large';
|
||||
label?: string;
|
||||
className?: string;
|
||||
onChange?: (value: any) => void;
|
||||
value?: any;
|
||||
containerClass?: string;
|
||||
inline?: boolean;
|
||||
trueValue?: boolean;
|
||||
falseValue?: boolean;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
checked?: boolean;
|
||||
name?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
partial?: boolean;
|
||||
}
|
||||
|
||||
export class Checkbox extends React.Component<CheckboxProps, any> {
|
||||
|
@ -42,22 +42,22 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
|
|||
trueValue: true,
|
||||
falseValue: false,
|
||||
type: 'checkbox',
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: CheckboxProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.hanldeCheck = this.hanldeCheck.bind(this)
|
||||
this.hanldeCheck = this.hanldeCheck.bind(this);
|
||||
}
|
||||
|
||||
hanldeCheck(e: React.ChangeEvent<any>) {
|
||||
const {trueValue, falseValue, onChange} = this.props
|
||||
const {trueValue, falseValue, onChange} = this.props;
|
||||
|
||||
if (!onChange) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(e.currentTarget.checked ? trueValue : falseValue)
|
||||
onChange(e.currentTarget.checked ? trueValue : falseValue);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -75,9 +75,9 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
|
|||
checked,
|
||||
type,
|
||||
name,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
className = (className ? className : '') + (size && sizeMap[size] ? ` ${sizeMap[size]}` : '')
|
||||
className = (className ? className : '') + (size && sizeMap[size] ? ` ${sizeMap[size]}` : '');
|
||||
|
||||
return (
|
||||
<label
|
||||
|
@ -106,8 +106,8 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
|
|||
<i />
|
||||
<span>{children || label}</span>
|
||||
</label>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Checkbox)
|
||||
export default themeable(Checkbox);
|
||||
|
|
|
@ -4,51 +4,51 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import Checkbox from './Checkbox'
|
||||
import find = require('lodash/find')
|
||||
import chunk = require('lodash/chunk')
|
||||
import {flattenTree} from '../utils/helper'
|
||||
import {Option} from './Checkboxes'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import Checkbox from './Checkbox';
|
||||
import find = require('lodash/find');
|
||||
import chunk = require('lodash/chunk');
|
||||
import {flattenTree} from '../utils/helper';
|
||||
import {Option} from './Checkboxes';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
// import isPlainObject = require('lodash/isPlainObject');
|
||||
|
||||
export interface Option {
|
||||
label?: string
|
||||
value?: any
|
||||
disabled?: boolean
|
||||
children?: Options
|
||||
[propName: string]: any
|
||||
label?: string;
|
||||
value?: any;
|
||||
disabled?: boolean;
|
||||
children?: Options;
|
||||
[propName: string]: any;
|
||||
}
|
||||
export interface Options extends Array<Option> {}
|
||||
|
||||
export interface OptionProps {
|
||||
multi?: boolean
|
||||
multiple?: boolean
|
||||
valueField?: string
|
||||
options?: Options
|
||||
joinValues: boolean
|
||||
extractValue: boolean
|
||||
delimiter: string
|
||||
clearable: boolean
|
||||
placeholder?: string
|
||||
multi?: boolean;
|
||||
multiple?: boolean;
|
||||
valueField?: string;
|
||||
options?: Options;
|
||||
joinValues: boolean;
|
||||
extractValue: boolean;
|
||||
delimiter: string;
|
||||
clearable: boolean;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export type OptionValue = string | number | null | undefined | Option
|
||||
export type OptionValue = string | number | null | undefined | Option;
|
||||
|
||||
export function value2array(value: OptionValue | Array<OptionValue>, props: Partial<OptionProps>): Array<Option> {
|
||||
if (props.multi || props.multiple) {
|
||||
if (typeof value === 'string') {
|
||||
value = value.split(props.delimiter || ',')
|
||||
value = value.split(props.delimiter || ',');
|
||||
}
|
||||
|
||||
if (!Array.isArray(value)) {
|
||||
if (value === null || value === undefined) {
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
|
||||
value = [value]
|
||||
value = [value];
|
||||
}
|
||||
|
||||
return (value as Array<OptionValue>)
|
||||
|
@ -60,31 +60,31 @@ export function value2array(value: OptionValue | Array<OptionValue>, props: Part
|
|||
props
|
||||
)
|
||||
)
|
||||
.filter((item: Option) => item) as Array<Option>
|
||||
.filter((item: Option) => item) as Array<Option>;
|
||||
}
|
||||
|
||||
let expandedValue = expandValue(value as OptionValue, props)
|
||||
return expandedValue ? [expandedValue] : []
|
||||
let expandedValue = expandValue(value as OptionValue, props);
|
||||
return expandedValue ? [expandedValue] : [];
|
||||
}
|
||||
|
||||
export function expandValue(value: OptionValue, props: Partial<OptionProps>): Option | null {
|
||||
const valueType = typeof value
|
||||
const valueType = typeof value;
|
||||
|
||||
if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean' && valueType !== 'object') {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
let {options, valueField} = props
|
||||
let {options, valueField} = props;
|
||||
|
||||
if (!options) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
if (valueType === 'object') {
|
||||
value = (value as Option)[valueField || 'value'] || ''
|
||||
value = (value as Option)[valueField || 'value'] || '';
|
||||
}
|
||||
|
||||
return find(flattenTree(options), item => String(item[valueField || 'value']) === String(value)) as Option
|
||||
return find(flattenTree(options), item => String(item[valueField || 'value']) === String(value)) as Option;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,19 +99,19 @@ export function expandValue(value: OptionValue, props: Partial<OptionProps>): Op
|
|||
* ]
|
||||
*/
|
||||
interface CheckboxesProps extends OptionProps {
|
||||
id?: string
|
||||
key?: string
|
||||
className?: string
|
||||
type: string
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
value?: string
|
||||
onChange?: Function
|
||||
inline?: boolean
|
||||
columnsCount?: number
|
||||
checked?: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
id?: string;
|
||||
key?: string;
|
||||
className?: string;
|
||||
type: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
value?: string;
|
||||
onChange?: Function;
|
||||
inline?: boolean;
|
||||
columnsCount?: number;
|
||||
checked?: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
||||
|
@ -121,18 +121,18 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
|||
inline: false,
|
||||
delimiter: ',',
|
||||
columnsCount: 1, // 一行显示一个
|
||||
}
|
||||
};
|
||||
|
||||
toggleOption(option: Option) {
|
||||
const {value, onChange, joinValues, extractValue, delimiter, valueField, options} = this.props
|
||||
const {value, onChange, joinValues, extractValue, delimiter, valueField, options} = this.props;
|
||||
|
||||
let valueArray = value2array(value, {
|
||||
multiple: true,
|
||||
valueField,
|
||||
delimiter,
|
||||
options,
|
||||
})
|
||||
let idx = valueArray.indexOf(option)
|
||||
});
|
||||
let idx = valueArray.indexOf(option);
|
||||
|
||||
if (!~idx) {
|
||||
option =
|
||||
|
@ -141,25 +141,25 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
|||
valueField,
|
||||
delimiter,
|
||||
options,
|
||||
})[0] || option
|
||||
idx = valueArray.indexOf(option)
|
||||
})[0] || option;
|
||||
idx = valueArray.indexOf(option);
|
||||
}
|
||||
|
||||
if (~idx) {
|
||||
valueArray.splice(idx, 1)
|
||||
valueArray.splice(idx, 1);
|
||||
} else {
|
||||
valueArray.push(option)
|
||||
valueArray.push(option);
|
||||
}
|
||||
|
||||
let newValue: string | Array<Option> = valueArray
|
||||
let newValue: string | Array<Option> = valueArray;
|
||||
|
||||
if (joinValues) {
|
||||
newValue = newValue.map(item => item[valueField || 'value']).join(delimiter)
|
||||
newValue = newValue.map(item => item[valueField || 'value']).join(delimiter);
|
||||
} else if (extractValue) {
|
||||
newValue = newValue.map(item => item[valueField || 'value'])
|
||||
newValue = newValue.map(item => item[valueField || 'value']);
|
||||
}
|
||||
|
||||
onChange && onChange(newValue)
|
||||
onChange && onChange(newValue);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -173,15 +173,15 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
|||
columnsCount,
|
||||
disabled,
|
||||
inline,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
let valueArray = value2array(value, {
|
||||
multiple: true,
|
||||
valueField,
|
||||
delimiter,
|
||||
options,
|
||||
})
|
||||
let body: Array<React.ReactNode> = []
|
||||
});
|
||||
let body: Array<React.ReactNode> = [];
|
||||
|
||||
if (options) {
|
||||
body = options.map((option, key) => (
|
||||
|
@ -194,14 +194,14 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
|||
>
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
if (!inline && (columnsCount as number) > 1) {
|
||||
let cellClassName = `col-sm-${(12 / (columnsCount as number))
|
||||
.toFixed(1)
|
||||
.replace(/\.0$/, '')
|
||||
.replace(/\./, '-')}`
|
||||
.replace(/\./, '-')}`;
|
||||
body = chunk(body, columnsCount).map((group, groupIndex) => (
|
||||
<div className="row" key={groupIndex}>
|
||||
{group.map((item, index) => (
|
||||
|
@ -210,10 +210,10 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
return <div className={className}>{body && body.length ? body : placeholder}</div>
|
||||
return <div className={className}>{body && body.length ? body : placeholder}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,4 +221,4 @@ export default themeable(
|
|||
uncontrollable(Checkboxes, {
|
||||
value: 'onChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import {Collapse} from 'react-bootstrap'
|
||||
import {Collapse} from 'react-bootstrap';
|
||||
|
||||
export default Collapse
|
||||
export default Collapse;
|
||||
|
|
|
@ -4,35 +4,35 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import {SketchPicker, ColorResult} from 'react-color'
|
||||
import {closeIcon} from './icons'
|
||||
import Overlay from './Overlay'
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import PopOver from './PopOver'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import {SketchPicker, ColorResult} from 'react-color';
|
||||
import {closeIcon} from './icons';
|
||||
import Overlay from './Overlay';
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import PopOver from './PopOver';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface ColorProps {
|
||||
placeholder?: string
|
||||
format: string
|
||||
placeholder?: string;
|
||||
format: string;
|
||||
// closeOnSelect:boolean;
|
||||
clearable: boolean
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
popOverContainer?: any
|
||||
placement?: string
|
||||
value: any
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
onChange: (value: any) => void
|
||||
clearable: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
popOverContainer?: any;
|
||||
placement?: string;
|
||||
value: any;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
onChange: (value: any) => void;
|
||||
}
|
||||
|
||||
export interface ColorControlState {
|
||||
isOpened: boolean
|
||||
isFocused: boolean
|
||||
inputValue: string
|
||||
isOpened: boolean;
|
||||
isFocused: boolean;
|
||||
inputValue: string;
|
||||
}
|
||||
|
||||
export class ColorControl extends React.PureComponent<ColorProps, ColorControlState> {
|
||||
|
@ -41,107 +41,107 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
|
|||
clearable: true,
|
||||
placeholder: '请选择颜色',
|
||||
// closeOnSelect: true
|
||||
}
|
||||
};
|
||||
state = {
|
||||
isOpened: false,
|
||||
isFocused: false,
|
||||
inputValue: this.props.value || '',
|
||||
}
|
||||
popover: any
|
||||
closeTimer: number
|
||||
preview: React.RefObject<HTMLElement>
|
||||
input: React.RefObject<HTMLInputElement>
|
||||
};
|
||||
popover: any;
|
||||
closeTimer: number;
|
||||
preview: React.RefObject<HTMLElement>;
|
||||
input: React.RefObject<HTMLInputElement>;
|
||||
constructor(props: ColorProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.open = this.open.bind(this)
|
||||
this.close = this.close.bind(this)
|
||||
this.focus = this.focus.bind(this)
|
||||
this.blur = this.blur.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleFocus = this.handleFocus.bind(this)
|
||||
this.handleBlur = this.handleBlur.bind(this)
|
||||
this.clearValue = this.clearValue.bind(this)
|
||||
this.handleInputChange = this.handleInputChange.bind(this)
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.preview = React.createRef()
|
||||
this.input = React.createRef()
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
this.focus = this.focus.bind(this);
|
||||
this.blur = this.blur.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.clearValue = this.clearValue.bind(this);
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.preview = React.createRef();
|
||||
this.input = React.createRef();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ColorProps) {
|
||||
const props = this.props
|
||||
const props = this.props;
|
||||
|
||||
if (props.value !== nextProps.value) {
|
||||
this.setState({
|
||||
inputValue: nextProps.value || '',
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleFocus() {
|
||||
this.setState({
|
||||
isFocused: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
this.setState({
|
||||
isFocused: false,
|
||||
inputValue: this.props.value,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.input.current && this.input.current.focus()
|
||||
this.input.current && this.input.current.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input.current && this.input.current.blur()
|
||||
this.input.current && this.input.current.blur();
|
||||
}
|
||||
|
||||
open(fn?: () => void) {
|
||||
if (this.props.disabled) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.setState(
|
||||
{
|
||||
isOpened: true,
|
||||
},
|
||||
fn
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({
|
||||
isOpened: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
clearValue() {
|
||||
const onChange = this.props.onChange
|
||||
onChange('')
|
||||
const onChange = this.props.onChange;
|
||||
onChange('');
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
this.state.isOpened ? this.close() : this.open(this.focus)
|
||||
this.state.isOpened ? this.close() : this.open(this.focus);
|
||||
}
|
||||
|
||||
handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const onChange = this.props.onChange
|
||||
const onChange = this.props.onChange;
|
||||
|
||||
this.setState(
|
||||
{
|
||||
inputValue: e.currentTarget.value,
|
||||
},
|
||||
() => {
|
||||
const dom: HTMLElement = this.preview.current as HTMLElement
|
||||
const dom: HTMLElement = this.preview.current as HTMLElement;
|
||||
|
||||
// 通过读取dom上到值,确认当前输入值是否有效。
|
||||
if (dom && dom.style.backgroundColor === this.state.inputValue) {
|
||||
onChange(this.state.inputValue)
|
||||
onChange(this.state.inputValue);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
handleChange(color: ColorResult) {
|
||||
|
@ -149,18 +149,18 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
|
|||
onChange,
|
||||
format,
|
||||
// closeOnSelect
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
if (format === 'rgba') {
|
||||
onChange(`rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`)
|
||||
onChange(`rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`);
|
||||
} else if (format === 'rgb') {
|
||||
onChange(`rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`)
|
||||
onChange(`rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`);
|
||||
} else if (format === 'hsl') {
|
||||
onChange(
|
||||
`hsl(${Math.round(color.hsl.h)}, ${Math.round(color.hsl.s * 100)}%, ${Math.round(color.hsl.l * 100)}%)`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
onChange(color.hex)
|
||||
onChange(color.hex);
|
||||
}
|
||||
|
||||
// closeOnSelect && this.close();
|
||||
|
@ -178,10 +178,10 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
|
|||
clearable,
|
||||
placement,
|
||||
classnames: cx,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
const isOpened = this.state.isOpened
|
||||
const isFocused = this.state.isFocused
|
||||
const isOpened = this.state.isOpened;
|
||||
const isFocused = this.state.isFocused;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -242,7 +242,7 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
|
|||
</Overlay>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,4 +250,4 @@ export default themeable(
|
|||
uncontrollable(ColorControl, {
|
||||
value: 'onChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -4,122 +4,122 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import * as moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import * as moment from 'moment';
|
||||
import 'moment/locale/zh-cn';
|
||||
|
||||
// hack 进去,让 days view 用 CustomDaysView 代替
|
||||
import * as CalendarContainer from 'react-datetime/src/CalendarContainer'
|
||||
import * as ReactDatePicker from 'react-datetime'
|
||||
import Select from './Select'
|
||||
import {closeIcon} from './icons'
|
||||
import PopOver from './PopOver'
|
||||
import Overlay from './Overlay'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import * as CalendarContainer from 'react-datetime/src/CalendarContainer';
|
||||
import * as ReactDatePicker from 'react-datetime';
|
||||
import Select from './Select';
|
||||
import {closeIcon} from './icons';
|
||||
import PopOver from './PopOver';
|
||||
import Overlay from './Overlay';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
CalendarContainer.prototype.render = (function(_super) {
|
||||
return function() {
|
||||
if (this.props.view === 'days') {
|
||||
return <CustomDaysView {...this.props.viewProps} />
|
||||
return <CustomDaysView {...this.props.viewProps} />;
|
||||
}
|
||||
|
||||
return _super.apply(this, arguments)
|
||||
}
|
||||
})(CalendarContainer.prototype.render)
|
||||
return _super.apply(this, arguments);
|
||||
};
|
||||
})(CalendarContainer.prototype.render);
|
||||
|
||||
// hack 后,view 中可以调用 setDateTimeState
|
||||
class BaseDatePicker extends ReactDatePicker {
|
||||
__hacked: boolean
|
||||
__hacked: boolean;
|
||||
|
||||
render() {
|
||||
if (!this.__hacked) {
|
||||
this.__hacked = true
|
||||
const origin = (this as any).getComponentProps
|
||||
const setState = this.setState.bind(this)
|
||||
;(this as any).getComponentProps = function() {
|
||||
const props = origin.apply(this)
|
||||
props.setDateTimeState = setState
|
||||
;['onChange', 'onClose', 'requiredConfirm', 'classPrefix', 'prevIcon', 'nextIcon', 'isEndDate'].forEach(
|
||||
this.__hacked = true;
|
||||
const origin = (this as any).getComponentProps;
|
||||
const setState = this.setState.bind(this);
|
||||
(this as any).getComponentProps = function() {
|
||||
const props = origin.apply(this);
|
||||
props.setDateTimeState = setState;
|
||||
['onChange', 'onClose', 'requiredConfirm', 'classPrefix', 'prevIcon', 'nextIcon', 'isEndDate'].forEach(
|
||||
key => (props[key] = (this.props as any)[key])
|
||||
)
|
||||
);
|
||||
|
||||
return props
|
||||
return props;
|
||||
};
|
||||
}
|
||||
}
|
||||
return super.render()
|
||||
return super.render();
|
||||
}
|
||||
}
|
||||
|
||||
interface CustomDaysViewProps {
|
||||
classPrefix?: string
|
||||
prevIcon?: string
|
||||
nextIcon?: string
|
||||
viewDate: moment.Moment
|
||||
selectedDate: moment.Moment
|
||||
timeFormat: string
|
||||
requiredConfirm?: boolean
|
||||
isEndDate?: boolean
|
||||
renderDay?: Function
|
||||
onClose?: () => void
|
||||
onChange: (value: moment.Moment) => void
|
||||
setDateTimeState: (state: any) => void
|
||||
setTime: (type: string, amount: number) => void
|
||||
subtractTime: (amount: number, type: string, toSelected?: moment.Moment) => () => void
|
||||
addTime: (amount: number, type: string, toSelected?: moment.Moment) => () => void
|
||||
isValidDate?: (currentDate: moment.Moment, selected?: moment.Moment) => boolean
|
||||
showView: (view: string) => () => void
|
||||
updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void
|
||||
handleClickOutside: () => void
|
||||
classPrefix?: string;
|
||||
prevIcon?: string;
|
||||
nextIcon?: string;
|
||||
viewDate: moment.Moment;
|
||||
selectedDate: moment.Moment;
|
||||
timeFormat: string;
|
||||
requiredConfirm?: boolean;
|
||||
isEndDate?: boolean;
|
||||
renderDay?: Function;
|
||||
onClose?: () => void;
|
||||
onChange: (value: moment.Moment) => void;
|
||||
setDateTimeState: (state: any) => void;
|
||||
setTime: (type: string, amount: number) => void;
|
||||
subtractTime: (amount: number, type: string, toSelected?: moment.Moment) => () => void;
|
||||
addTime: (amount: number, type: string, toSelected?: moment.Moment) => () => void;
|
||||
isValidDate?: (currentDate: moment.Moment, selected?: moment.Moment) => boolean;
|
||||
showView: (view: string) => () => void;
|
||||
updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void;
|
||||
handleClickOutside: () => void;
|
||||
}
|
||||
|
||||
class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
||||
static defaultProps = {
|
||||
classPrefix: 'a-',
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: CustomDaysViewProps) {
|
||||
super(props)
|
||||
this.handleClickOutside = this.handleClickOutside.bind(this)
|
||||
this.handleYearChange = this.handleYearChange.bind(this)
|
||||
this.handleMonthChange = this.handleMonthChange.bind(this)
|
||||
this.handleDayChange = this.handleDayChange.bind(this)
|
||||
this.confirm = this.confirm.bind(this)
|
||||
this.cancel = this.cancel.bind(this)
|
||||
super(props);
|
||||
this.handleClickOutside = this.handleClickOutside.bind(this);
|
||||
this.handleYearChange = this.handleYearChange.bind(this);
|
||||
this.handleMonthChange = this.handleMonthChange.bind(this);
|
||||
this.handleDayChange = this.handleDayChange.bind(this);
|
||||
this.confirm = this.confirm.bind(this);
|
||||
this.cancel = this.cancel.bind(this);
|
||||
}
|
||||
|
||||
getDaysOfWeek(locale: moment.Locale) {
|
||||
const days: Array<string> = locale.weekdaysMin()
|
||||
const first = locale.firstDayOfWeek()
|
||||
const dow: Array<string> = []
|
||||
let i = 0
|
||||
const days: Array<string> = locale.weekdaysMin();
|
||||
const first = locale.firstDayOfWeek();
|
||||
const dow: Array<string> = [];
|
||||
let i = 0;
|
||||
|
||||
days.forEach(function(day) {
|
||||
dow[(7 + i++ - first) % 7] = day
|
||||
})
|
||||
dow[(7 + i++ - first) % 7] = day;
|
||||
});
|
||||
|
||||
return dow
|
||||
return dow;
|
||||
}
|
||||
|
||||
alwaysValidDate() {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
handleDayChange(event: React.MouseEvent<any>) {
|
||||
// need confirm
|
||||
if (this.props.requiredConfirm) {
|
||||
const viewDate = this.props.viewDate.clone()
|
||||
const currentDate = this.props.selectedDate || viewDate
|
||||
const viewDate = this.props.viewDate.clone();
|
||||
const currentDate = this.props.selectedDate || viewDate;
|
||||
|
||||
const target = event.target as HTMLElement
|
||||
let modifier = 0
|
||||
const target = event.target as HTMLElement;
|
||||
let modifier = 0;
|
||||
|
||||
if (~target.className.indexOf('rdtNew')) {
|
||||
modifier = 1
|
||||
modifier = 1;
|
||||
}
|
||||
if (~target.className.indexOf('rdtOld')) {
|
||||
modifier = -1
|
||||
modifier = -1;
|
||||
}
|
||||
|
||||
viewDate
|
||||
|
@ -128,16 +128,16 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
.hours(currentDate.hours())
|
||||
.minutes(currentDate.minutes())
|
||||
.seconds(currentDate.seconds())
|
||||
.milliseconds(currentDate.milliseconds())
|
||||
.milliseconds(currentDate.milliseconds());
|
||||
|
||||
this.props.setDateTimeState({
|
||||
viewDate,
|
||||
selectedDate: viewDate.clone(),
|
||||
})
|
||||
return
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.updateSelectedDate(event, true)
|
||||
this.props.updateSelectedDate(event, true);
|
||||
}
|
||||
|
||||
handleMonthChange(option: any) {
|
||||
|
@ -150,13 +150,13 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
|
||||
// this.props.updateSelectedDate(fakeEvent as any);
|
||||
|
||||
const viewDate = this.props.viewDate
|
||||
const viewDate = this.props.viewDate;
|
||||
this.props.setDateTimeState({
|
||||
viewDate: viewDate
|
||||
.clone()
|
||||
.month(option.value)
|
||||
.startOf('month'),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleYearChange(option: any) {
|
||||
|
@ -169,106 +169,106 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
|
||||
// this.props.updateSelectedDate(fakeEvent as any);
|
||||
|
||||
const viewDate = this.props.viewDate
|
||||
const newDate = viewDate.clone().year(option.value)
|
||||
const viewDate = this.props.viewDate;
|
||||
const newDate = viewDate.clone().year(option.value);
|
||||
this.props.setDateTimeState({
|
||||
viewDate: newDate[newDate.isBefore(viewDate) ? 'endOf' : 'startOf']('year'),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
setTime(type: 'hours' | 'minutes' | 'seconds' | 'milliseconds', value: number) {
|
||||
const date = (this.props.selectedDate || this.props.viewDate).clone()
|
||||
date[type](value)
|
||||
const date = (this.props.selectedDate || this.props.viewDate).clone();
|
||||
date[type](value);
|
||||
|
||||
this.props.setDateTimeState({
|
||||
viewDate: date.clone(),
|
||||
selectedDate: date.clone(),
|
||||
})
|
||||
});
|
||||
|
||||
if (!this.props.requiredConfirm) {
|
||||
this.props.onChange(date)
|
||||
this.props.onChange(date);
|
||||
}
|
||||
}
|
||||
|
||||
confirm() {
|
||||
const date = this.props.viewDate.clone()
|
||||
const date = this.props.viewDate.clone();
|
||||
|
||||
this.props.setDateTimeState({
|
||||
selectedDate: date,
|
||||
})
|
||||
this.props.onChange(date)
|
||||
this.props.onClose && this.props.onClose()
|
||||
});
|
||||
this.props.onChange(date);
|
||||
this.props.onClose && this.props.onClose();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.props.onClose && this.props.onClose()
|
||||
this.props.onClose && this.props.onClose();
|
||||
}
|
||||
|
||||
handleClickOutside() {
|
||||
this.props.handleClickOutside()
|
||||
this.props.handleClickOutside();
|
||||
}
|
||||
|
||||
renderYearsSelect() {
|
||||
const classPrefix = this.props.classPrefix
|
||||
const date = this.props.viewDate
|
||||
const years: Array<number> = []
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate
|
||||
const irrelevantMonth = 0
|
||||
const irrelevantDate = 1
|
||||
let year = date.year()
|
||||
let count = 0
|
||||
const classPrefix = this.props.classPrefix;
|
||||
const date = this.props.viewDate;
|
||||
const years: Array<number> = [];
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate;
|
||||
const irrelevantMonth = 0;
|
||||
const irrelevantDate = 1;
|
||||
let year = date.year();
|
||||
let count = 0;
|
||||
|
||||
years.push(year)
|
||||
years.push(year);
|
||||
while (count < 20) {
|
||||
year++
|
||||
year++;
|
||||
|
||||
let currentYear = date.clone().set({
|
||||
year: year,
|
||||
month: irrelevantMonth,
|
||||
date: irrelevantDate,
|
||||
})
|
||||
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10)
|
||||
});
|
||||
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10);
|
||||
const daysInYear = Array.from(
|
||||
{
|
||||
length: noOfDaysInYear,
|
||||
},
|
||||
(e, i) => i + 1
|
||||
)
|
||||
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)))
|
||||
);
|
||||
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)));
|
||||
|
||||
if (!validDay) {
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
years.push(year)
|
||||
count++
|
||||
years.push(year);
|
||||
count++;
|
||||
}
|
||||
|
||||
count = 0
|
||||
year = date.year()
|
||||
count = 0;
|
||||
year = date.year();
|
||||
while (count < 20) {
|
||||
year--
|
||||
year--;
|
||||
|
||||
let currentYear = date.clone().set({
|
||||
year: year,
|
||||
month: irrelevantMonth,
|
||||
date: irrelevantDate,
|
||||
})
|
||||
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10)
|
||||
});
|
||||
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10);
|
||||
const daysInYear = Array.from(
|
||||
{
|
||||
length: noOfDaysInYear,
|
||||
},
|
||||
(e, i) => i + 1
|
||||
)
|
||||
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)))
|
||||
);
|
||||
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)));
|
||||
|
||||
if (!validDay) {
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
years.unshift(year)
|
||||
count++
|
||||
years.unshift(year);
|
||||
count++;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -282,34 +282,34 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
clearable={false}
|
||||
searchable={false}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderMonthsSelect() {
|
||||
const classPrefix = this.props.classPrefix
|
||||
const date = this.props.viewDate
|
||||
const year = this.props.viewDate.year()
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate
|
||||
let i = 0
|
||||
const days = []
|
||||
const classPrefix = this.props.classPrefix;
|
||||
const date = this.props.viewDate;
|
||||
const year = this.props.viewDate.year();
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate;
|
||||
let i = 0;
|
||||
const days = [];
|
||||
|
||||
while (i < 12) {
|
||||
const currentMonth = date.clone().set({
|
||||
year,
|
||||
month: i,
|
||||
date: 1,
|
||||
})
|
||||
});
|
||||
|
||||
const noOfDaysInMonth = parseInt(currentMonth.endOf('month').format('D'), 10)
|
||||
const noOfDaysInMonth = parseInt(currentMonth.endOf('month').format('D'), 10);
|
||||
const daysInMonth = Array.from({length: noOfDaysInMonth}, function(e, i) {
|
||||
return i + 1
|
||||
})
|
||||
return i + 1;
|
||||
});
|
||||
|
||||
const validDay = daysInMonth.find(d => isValid(currentMonth.clone().set('date', d)))
|
||||
const validDay = daysInMonth.find(d => isValid(currentMonth.clone().set('date', d)));
|
||||
if (validDay) {
|
||||
days.push(i)
|
||||
days.push(i);
|
||||
}
|
||||
i++
|
||||
i++;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -324,23 +324,23 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
clearable={false}
|
||||
searchable={false}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderDay(props: any, currentDate: moment.Moment) {
|
||||
return <td {...props}>{currentDate.date()}</td>
|
||||
return <td {...props}>{currentDate.date()}</td>;
|
||||
}
|
||||
|
||||
renderTimes() {
|
||||
const {timeFormat, selectedDate, viewDate, isEndDate} = this.props
|
||||
const {timeFormat, selectedDate, viewDate, isEndDate} = this.props;
|
||||
|
||||
const date = selectedDate || (isEndDate ? viewDate.endOf('day') : viewDate)
|
||||
const inputs: Array<React.ReactNode> = []
|
||||
const date = selectedDate || (isEndDate ? viewDate.endOf('day') : viewDate);
|
||||
const inputs: Array<React.ReactNode> = [];
|
||||
|
||||
timeFormat.split(':').forEach((format, i) => {
|
||||
const type = /h/i.test(format) ? 'hours' : /m/i.test(format) ? 'minutes' : 'seconds'
|
||||
const min = 0
|
||||
const max = type === 'hours' ? 23 : 59
|
||||
const type = /h/i.test(format) ? 'hours' : /m/i.test(format) ? 'minutes' : 'seconds';
|
||||
const min = 0;
|
||||
const max = type === 'hours' ? 23 : 59;
|
||||
|
||||
inputs.push(
|
||||
<input
|
||||
|
@ -356,19 +356,19 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
)
|
||||
}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
||||
inputs.push(<span key={i + 'divider'}>:</span>)
|
||||
})
|
||||
inputs.push(<span key={i + 'divider'}>:</span>);
|
||||
});
|
||||
|
||||
inputs.length && inputs.pop()
|
||||
inputs.length && inputs.pop();
|
||||
|
||||
return <div>{inputs}</div>
|
||||
return <div>{inputs}</div>;
|
||||
}
|
||||
|
||||
renderFooter() {
|
||||
if (!this.props.timeFormat && !this.props.requiredConfirm) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -389,72 +389,72 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderDays() {
|
||||
const date = this.props.viewDate
|
||||
const selected = this.props.selectedDate && this.props.selectedDate.clone()
|
||||
const prevMonth = date.clone().subtract(1, 'months')
|
||||
const currentYear = date.year()
|
||||
const currentMonth = date.month()
|
||||
const weeks = []
|
||||
let days = []
|
||||
const renderer = this.props.renderDay || this.renderDay
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate
|
||||
let classes, isDisabled, dayProps: any, currentDate
|
||||
const date = this.props.viewDate;
|
||||
const selected = this.props.selectedDate && this.props.selectedDate.clone();
|
||||
const prevMonth = date.clone().subtract(1, 'months');
|
||||
const currentYear = date.year();
|
||||
const currentMonth = date.month();
|
||||
const weeks = [];
|
||||
let days = [];
|
||||
const renderer = this.props.renderDay || this.renderDay;
|
||||
const isValid = this.props.isValidDate || this.alwaysValidDate;
|
||||
let classes, isDisabled, dayProps: any, currentDate;
|
||||
|
||||
// Go to the last week of the previous month
|
||||
prevMonth.date(prevMonth.daysInMonth()).startOf('week')
|
||||
var lastDay = prevMonth.clone().add(42, 'd')
|
||||
prevMonth.date(prevMonth.daysInMonth()).startOf('week');
|
||||
var lastDay = prevMonth.clone().add(42, 'd');
|
||||
|
||||
while (prevMonth.isBefore(lastDay)) {
|
||||
classes = 'rdtDay'
|
||||
currentDate = prevMonth.clone()
|
||||
classes = 'rdtDay';
|
||||
currentDate = prevMonth.clone();
|
||||
|
||||
if (
|
||||
(prevMonth.year() === currentYear && prevMonth.month() < currentMonth) ||
|
||||
prevMonth.year() < currentYear
|
||||
)
|
||||
classes += ' rdtOld'
|
||||
classes += ' rdtOld';
|
||||
else if (
|
||||
(prevMonth.year() === currentYear && prevMonth.month() > currentMonth) ||
|
||||
prevMonth.year() > currentYear
|
||||
)
|
||||
classes += ' rdtNew'
|
||||
classes += ' rdtNew';
|
||||
|
||||
if (selected && prevMonth.isSame(selected, 'day')) classes += ' rdtActive'
|
||||
if (selected && prevMonth.isSame(selected, 'day')) classes += ' rdtActive';
|
||||
|
||||
if (prevMonth.isSame(moment(), 'day')) classes += ' rdtToday'
|
||||
if (prevMonth.isSame(moment(), 'day')) classes += ' rdtToday';
|
||||
|
||||
isDisabled = !isValid(currentDate, selected)
|
||||
if (isDisabled) classes += ' rdtDisabled'
|
||||
isDisabled = !isValid(currentDate, selected);
|
||||
if (isDisabled) classes += ' rdtDisabled';
|
||||
|
||||
dayProps = {
|
||||
key: prevMonth.format('M_D'),
|
||||
'data-value': prevMonth.date(),
|
||||
className: classes,
|
||||
}
|
||||
};
|
||||
|
||||
if (!isDisabled) dayProps.onClick = this.handleDayChange
|
||||
if (!isDisabled) dayProps.onClick = this.handleDayChange;
|
||||
|
||||
days.push(renderer(dayProps, currentDate, selected))
|
||||
days.push(renderer(dayProps, currentDate, selected));
|
||||
|
||||
if (days.length === 7) {
|
||||
weeks.push(<tr key={prevMonth.format('M_D')}>{days}</tr>)
|
||||
days = []
|
||||
weeks.push(<tr key={prevMonth.format('M_D')}>{days}</tr>);
|
||||
days = [];
|
||||
}
|
||||
|
||||
prevMonth.add(1, 'd')
|
||||
prevMonth.add(1, 'd');
|
||||
}
|
||||
|
||||
return weeks
|
||||
return weeks;
|
||||
}
|
||||
|
||||
render() {
|
||||
const footer = this.renderFooter()
|
||||
const date = this.props.viewDate
|
||||
const locale = date.localeData()
|
||||
const footer = this.renderFooter();
|
||||
const date = this.props.viewDate;
|
||||
const locale = date.localeData();
|
||||
|
||||
const tableChildren = [
|
||||
<thead key="th">
|
||||
|
@ -482,116 +482,116 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
|
|||
</thead>,
|
||||
|
||||
<tbody key="tb">{this.renderDays()}</tbody>,
|
||||
]
|
||||
];
|
||||
|
||||
footer && tableChildren.push(footer)
|
||||
footer && tableChildren.push(footer);
|
||||
|
||||
return (
|
||||
<div className="rdtDays">
|
||||
<table>{tableChildren}</table>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface DateProps {
|
||||
viewMode: 'years' | 'months' | 'days' | 'time'
|
||||
className?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
placeholder?: string
|
||||
inputFormat?: string
|
||||
timeFormat?: string
|
||||
format?: string
|
||||
timeConstrainst?: object
|
||||
closeOnSelect?: boolean
|
||||
disabled?: boolean
|
||||
minDate?: moment.Moment
|
||||
maxDate?: moment.Moment
|
||||
minTime?: moment.Moment
|
||||
maxTime?: moment.Moment
|
||||
clearable?: boolean
|
||||
defaultValue?: any
|
||||
onChange: (value: any) => void
|
||||
value: any
|
||||
[propName: string]: any
|
||||
viewMode: 'years' | 'months' | 'days' | 'time';
|
||||
className?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
placeholder?: string;
|
||||
inputFormat?: string;
|
||||
timeFormat?: string;
|
||||
format?: string;
|
||||
timeConstrainst?: object;
|
||||
closeOnSelect?: boolean;
|
||||
disabled?: boolean;
|
||||
minDate?: moment.Moment;
|
||||
maxDate?: moment.Moment;
|
||||
minTime?: moment.Moment;
|
||||
maxTime?: moment.Moment;
|
||||
clearable?: boolean;
|
||||
defaultValue?: any;
|
||||
onChange: (value: any) => void;
|
||||
value: any;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export interface DatePickerState {
|
||||
isOpened: boolean
|
||||
isFocused: boolean
|
||||
value: moment.Moment | undefined
|
||||
isOpened: boolean;
|
||||
isFocused: boolean;
|
||||
value: moment.Moment | undefined;
|
||||
}
|
||||
|
||||
export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
||||
static defaultProps: Pick<DateProps, 'viewMode'> = {
|
||||
viewMode: 'days',
|
||||
}
|
||||
};
|
||||
state: DatePickerState = {
|
||||
isOpened: false,
|
||||
isFocused: false,
|
||||
value: this.props.value ? moment(this.props.value, this.props.format) : undefined,
|
||||
}
|
||||
};
|
||||
constructor(props: DateProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.checkIsValidDate = this.checkIsValidDate.bind(this)
|
||||
this.open = this.open.bind(this)
|
||||
this.close = this.close.bind(this)
|
||||
this.handleFocus = this.handleFocus.bind(this)
|
||||
this.handleBlur = this.handleBlur.bind(this)
|
||||
this.clearValue = this.clearValue.bind(this)
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this)
|
||||
this.getParent = this.getParent.bind(this)
|
||||
this.getTarget = this.getTarget.bind(this)
|
||||
this.handlePopOverClick = this.handlePopOverClick.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.checkIsValidDate = this.checkIsValidDate.bind(this);
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.clearValue = this.clearValue.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
this.getParent = this.getParent.bind(this);
|
||||
this.getTarget = this.getTarget.bind(this);
|
||||
this.handlePopOverClick = this.handlePopOverClick.bind(this);
|
||||
}
|
||||
|
||||
dom: HTMLDivElement
|
||||
dom: HTMLDivElement;
|
||||
|
||||
componentWillReceiveProps(nextProps: DateProps) {
|
||||
if (this.props.value !== nextProps.value) {
|
||||
this.setState({
|
||||
value: nextProps.value ? moment(nextProps.value, nextProps.format) : undefined,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
if (!this.dom) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.dom.focus()
|
||||
this.dom.focus();
|
||||
}
|
||||
|
||||
handleFocus() {
|
||||
this.setState({
|
||||
isFocused: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
this.setState({
|
||||
isFocused: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ') {
|
||||
this.handleClick()
|
||||
this.handleClick();
|
||||
}
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
this.state.isOpened ? this.close() : this.open()
|
||||
this.state.isOpened ? this.close() : this.open();
|
||||
}
|
||||
|
||||
handlePopOverClick(e: React.MouseEvent<any>) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
open(fn?: () => void) {
|
||||
|
@ -601,65 +601,65 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||
isOpened: true,
|
||||
},
|
||||
fn
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({
|
||||
isOpened: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
clearValue(e: React.MouseEvent<any>) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const onChange = this.props.onChange
|
||||
onChange('')
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const onChange = this.props.onChange;
|
||||
onChange('');
|
||||
}
|
||||
|
||||
handleChange(value: moment.Moment) {
|
||||
const {onChange, format, minTime, maxTime, dateFormat, timeFormat} = this.props
|
||||
const {onChange, format, minTime, maxTime, dateFormat, timeFormat} = this.props;
|
||||
|
||||
if (!moment.isMoment(value)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (minTime && value && value.isBefore(minTime, 'second')) {
|
||||
value = minTime
|
||||
value = minTime;
|
||||
} else if (maxTime && value && value.isAfter(maxTime, 'second')) {
|
||||
value = maxTime
|
||||
value = maxTime;
|
||||
}
|
||||
|
||||
onChange(value.format(format))
|
||||
onChange(value.format(format));
|
||||
|
||||
if (dateFormat && !timeFormat) {
|
||||
this.close()
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
checkIsValidDate(currentDate: moment.Moment) {
|
||||
const {minDate, maxDate} = this.props
|
||||
const {minDate, maxDate} = this.props;
|
||||
|
||||
if (minDate && currentDate.isBefore(minDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
getTarget() {
|
||||
return this.dom
|
||||
return this.dom;
|
||||
}
|
||||
|
||||
getParent() {
|
||||
return this.dom
|
||||
return this.dom;
|
||||
}
|
||||
|
||||
domRef = (ref: HTMLDivElement) => {
|
||||
this.dom = ref
|
||||
}
|
||||
this.dom = ref;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -676,10 +676,10 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||
timeConstraints,
|
||||
popOverContainer,
|
||||
clearable,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
const isOpened = this.state.isOpened
|
||||
let date: moment.Moment | undefined = this.state.value
|
||||
const isOpened = this.state.isOpened;
|
||||
let date: moment.Moment | undefined = this.state.value;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -745,10 +745,10 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||
</Overlay>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(DatePicker)
|
||||
export default themeable(DatePicker);
|
||||
|
||||
export {BaseDatePicker}
|
||||
export {BaseDatePicker};
|
||||
|
|
|
@ -4,93 +4,93 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import React = require('react')
|
||||
import moment = require('moment')
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import * as cx from 'classnames'
|
||||
import {closeIcon} from './icons'
|
||||
import Overlay from './Overlay'
|
||||
import {BaseDatePicker} from './DatePicker'
|
||||
import PopOver from './PopOver'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import React = require('react');
|
||||
import moment = require('moment');
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import * as cx from 'classnames';
|
||||
import {closeIcon} from './icons';
|
||||
import Overlay from './Overlay';
|
||||
import {BaseDatePicker} from './DatePicker';
|
||||
import PopOver from './PopOver';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface DateRangePickerProps {
|
||||
className?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
placeholder?: string
|
||||
theme?: any
|
||||
format: string
|
||||
inputFormat?: string
|
||||
ranges?: string
|
||||
clearable?: boolean
|
||||
iconClassName?: string
|
||||
minDate?: moment.Moment
|
||||
maxDate?: moment.Moment
|
||||
joinValues: boolean
|
||||
delimiter: string
|
||||
value: any
|
||||
onChange: (value: any) => void
|
||||
data?: any
|
||||
disabled?: boolean
|
||||
[propName: string]: any
|
||||
className?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
placeholder?: string;
|
||||
theme?: any;
|
||||
format: string;
|
||||
inputFormat?: string;
|
||||
ranges?: string;
|
||||
clearable?: boolean;
|
||||
iconClassName?: string;
|
||||
minDate?: moment.Moment;
|
||||
maxDate?: moment.Moment;
|
||||
joinValues: boolean;
|
||||
delimiter: string;
|
||||
value: any;
|
||||
onChange: (value: any) => void;
|
||||
data?: any;
|
||||
disabled?: boolean;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export interface DateRangePickerState {
|
||||
isOpened: boolean
|
||||
isFocused: boolean
|
||||
startDate?: moment.Moment
|
||||
endDate?: moment.Moment
|
||||
isOpened: boolean;
|
||||
isFocused: boolean;
|
||||
startDate?: moment.Moment;
|
||||
endDate?: moment.Moment;
|
||||
}
|
||||
|
||||
const availableRanges: {[propName: string]: any} = {
|
||||
today: {
|
||||
label: '今天',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.startOf('day')
|
||||
return now.startOf('day');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
|
||||
yesterday: {
|
||||
label: '昨天',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.add(-1, 'days').startOf('day')
|
||||
return now.add(-1, 'days').startOf('day');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now.add(-1, 'days').endOf('day')
|
||||
return now.add(-1, 'days').endOf('day');
|
||||
},
|
||||
},
|
||||
|
||||
'1dayago': {
|
||||
label: '最近1天',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.add(-1, 'days')
|
||||
return now.add(-1, 'days');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
|
||||
'7daysago': {
|
||||
label: '最近7天',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.add(-7, 'days')
|
||||
return now.add(-7, 'days');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
|
||||
'90daysago': {
|
||||
label: '最近90天',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.add(-90, 'days')
|
||||
return now.add(-90, 'days');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -100,63 +100,63 @@ const availableRanges: {[propName: string]: any} = {
|
|||
return now
|
||||
.add(-1, 'days')
|
||||
.startOf('week')
|
||||
.add(-1, 'weeks')
|
||||
.add(-1, 'weeks');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
.add(-1, 'days')
|
||||
.startOf('week')
|
||||
.add(-1, 'day')
|
||||
.endOf('day')
|
||||
.endOf('day');
|
||||
},
|
||||
},
|
||||
|
||||
thismonth: {
|
||||
label: '本月',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.startOf('month')
|
||||
return now.startOf('month');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
|
||||
prevmonth: {
|
||||
label: '上个月',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.startOf('month').add(-1, 'month')
|
||||
return now.startOf('month').add(-1, 'month');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
.startOf('month')
|
||||
.add(-1, 'day')
|
||||
.endOf('day')
|
||||
.endOf('day');
|
||||
},
|
||||
},
|
||||
|
||||
prevquarter: {
|
||||
label: '上个季节',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.startOf('quarter').add(-1, 'quarter')
|
||||
return now.startOf('quarter').add(-1, 'quarter');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
.startOf('quarter')
|
||||
.add(-1, 'day')
|
||||
.endOf('day')
|
||||
.endOf('day');
|
||||
},
|
||||
},
|
||||
|
||||
thisquarter: {
|
||||
label: '本季度',
|
||||
startDate: (now: moment.Moment) => {
|
||||
return now.startOf('quarter')
|
||||
return now.startOf('quarter');
|
||||
},
|
||||
endDate: (now: moment.Moment) => {
|
||||
return now
|
||||
return now;
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export class DateRangePicker extends React.Component<DateRangePickerProps, DateRangePickerState> {
|
||||
static defaultProps = {
|
||||
|
@ -169,20 +169,20 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
ranges: 'yesterday,7daysago,prevweek,thismonth,prevmonth,prevquarter',
|
||||
iconClassName: 'fa fa-calendar',
|
||||
resetValue: '',
|
||||
}
|
||||
};
|
||||
|
||||
innerDom: any
|
||||
popover: any
|
||||
input?: HTMLInputElement
|
||||
innerDom: any;
|
||||
popover: any;
|
||||
input?: HTMLInputElement;
|
||||
|
||||
static formatValue(newValue: any, format: string, joinValues: boolean, delimiter: string) {
|
||||
newValue = [newValue.startDate.format(format), newValue.endDate.format(format)]
|
||||
newValue = [newValue.startDate.format(format), newValue.endDate.format(format)];
|
||||
|
||||
if (joinValues) {
|
||||
newValue = newValue.join(delimiter)
|
||||
newValue = newValue.join(delimiter);
|
||||
}
|
||||
|
||||
return newValue
|
||||
return newValue;
|
||||
}
|
||||
|
||||
static unFormatValue(value: any, format: string, joinValues: boolean, delimiter: string) {
|
||||
|
@ -190,95 +190,95 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
return {
|
||||
startDate: undefined,
|
||||
endDate: undefined,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (joinValues && typeof value === 'string') {
|
||||
value = value.split(delimiter)
|
||||
value = value.split(delimiter);
|
||||
}
|
||||
|
||||
return {
|
||||
startDate: value[0] ? moment(value[0], format) : undefined,
|
||||
endDate: value[1] ? moment(value[1], format) : undefined,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dom: React.RefObject<HTMLDivElement>
|
||||
dom: React.RefObject<HTMLDivElement>;
|
||||
|
||||
constructor(props: DateRangePickerProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.open = this.open.bind(this)
|
||||
this.close = this.close.bind(this)
|
||||
this.handleStartChange = this.handleStartChange.bind(this)
|
||||
this.handleEndChange = this.handleEndChange.bind(this)
|
||||
this.handleFocus = this.handleFocus.bind(this)
|
||||
this.handleBlur = this.handleBlur.bind(this)
|
||||
this.checkStartIsValidDate = this.checkStartIsValidDate.bind(this)
|
||||
this.checkEndIsValidDate = this.checkEndIsValidDate.bind(this)
|
||||
this.confirm = this.confirm.bind(this)
|
||||
this.clearValue = this.clearValue.bind(this)
|
||||
this.dom = React.createRef()
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this)
|
||||
this.handlePopOverClick = this.handlePopOverClick.bind(this)
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
this.handleStartChange = this.handleStartChange.bind(this);
|
||||
this.handleEndChange = this.handleEndChange.bind(this);
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.checkStartIsValidDate = this.checkStartIsValidDate.bind(this);
|
||||
this.checkEndIsValidDate = this.checkEndIsValidDate.bind(this);
|
||||
this.confirm = this.confirm.bind(this);
|
||||
this.clearValue = this.clearValue.bind(this);
|
||||
this.dom = React.createRef();
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
this.handlePopOverClick = this.handlePopOverClick.bind(this);
|
||||
|
||||
const {format, joinValues, delimiter, value} = this.props
|
||||
const {format, joinValues, delimiter, value} = this.props;
|
||||
|
||||
this.state = {
|
||||
isOpened: false,
|
||||
isFocused: false,
|
||||
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: DateRangePickerProps) {
|
||||
const props = this.props
|
||||
const {value, format, joinValues, delimiter} = nextProps
|
||||
const props = this.props;
|
||||
const {value, format, joinValues, delimiter} = nextProps;
|
||||
|
||||
if (props.value !== value) {
|
||||
this.setState({
|
||||
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
if (!this.dom.current || this.props.disabled) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.dom.current.focus()
|
||||
this.dom.current.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
if (!this.dom.current || this.props.disabled) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.dom.current.blur()
|
||||
this.dom.current.blur();
|
||||
}
|
||||
|
||||
handleFocus() {
|
||||
this.setState({
|
||||
isFocused: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
this.setState({
|
||||
isFocused: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this.props.disabled) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isOpened: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
|
@ -287,29 +287,29 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
isOpened: false,
|
||||
},
|
||||
this.blur
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
this.state.isOpened ? this.close() : this.open()
|
||||
this.state.isOpened ? this.close() : this.open();
|
||||
}
|
||||
|
||||
handlePopOverClick(e: React.MouseEvent<any>) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
handleKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ') {
|
||||
this.handleClick()
|
||||
this.handleClick();
|
||||
}
|
||||
}
|
||||
|
||||
confirm() {
|
||||
if (!this.state.startDate || !this.state.endDate) {
|
||||
return
|
||||
return;
|
||||
} else if (this.state.startDate.isAfter(this.state.endDate)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onChange(
|
||||
|
@ -322,72 +322,72 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
this.props.joinValues,
|
||||
this.props.delimiter
|
||||
)
|
||||
)
|
||||
this.close()
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
|
||||
handleStartChange(newValue: any) {
|
||||
this.setState({
|
||||
startDate: newValue.clone(),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleEndChange(newValue: any) {
|
||||
newValue = !this.state.endDate && !this.props.timeFormat ? newValue.endOf('day') : newValue
|
||||
newValue = !this.state.endDate && !this.props.timeFormat ? newValue.endOf('day') : newValue;
|
||||
this.setState({
|
||||
endDate: newValue.clone(),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
selectRannge(range: {
|
||||
startDate: (now: moment.Moment) => moment.Moment
|
||||
endDate: (now: moment.Moment) => moment.Moment
|
||||
startDate: (now: moment.Moment) => moment.Moment;
|
||||
endDate: (now: moment.Moment) => moment.Moment;
|
||||
}) {
|
||||
const now = moment()
|
||||
const now = moment();
|
||||
this.setState({
|
||||
startDate: range.startDate(now.clone()),
|
||||
endDate: range.endDate(now.clone()),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
clearValue(e: React.MouseEvent<any>) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const {resetValue, onChange} = this.props
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const {resetValue, onChange} = this.props;
|
||||
|
||||
onChange(resetValue)
|
||||
onChange(resetValue);
|
||||
}
|
||||
|
||||
checkStartIsValidDate(currentDate: moment.Moment) {
|
||||
let {endDate} = this.state
|
||||
let {endDate} = this.state;
|
||||
|
||||
let {minDate, maxDate} = this.props
|
||||
let {minDate, maxDate} = this.props;
|
||||
|
||||
maxDate = maxDate && endDate ? (maxDate.isBefore(endDate) ? maxDate : endDate) : maxDate || endDate
|
||||
maxDate = maxDate && endDate ? (maxDate.isBefore(endDate) ? maxDate : endDate) : maxDate || endDate;
|
||||
|
||||
if (minDate && currentDate.isBefore(minDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
checkEndIsValidDate(currentDate: moment.Moment) {
|
||||
let {startDate} = this.state
|
||||
let {startDate} = this.state;
|
||||
|
||||
let {minDate, maxDate} = this.props
|
||||
let {minDate, maxDate} = this.props;
|
||||
|
||||
minDate = minDate && startDate ? (minDate.isAfter(startDate) ? minDate : startDate) : minDate || startDate
|
||||
minDate = minDate && startDate ? (minDate.isAfter(startDate) ? minDate : startDate) : minDate || startDate;
|
||||
|
||||
if (minDate && currentDate.isBefore(minDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -406,16 +406,16 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
ranges,
|
||||
disabled,
|
||||
iconClassName,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
const {isOpened, isFocused, startDate, endDate} = this.state
|
||||
const {isOpened, isFocused, startDate, endDate} = this.state;
|
||||
|
||||
const selectedDate = DateRangePicker.unFormatValue(value, format, joinValues, delimiter)
|
||||
const startViewValue = selectedDate.startDate ? selectedDate.startDate.format(inputFormat) : ''
|
||||
const endViewValue = selectedDate.endDate ? selectedDate.endDate.format(inputFormat) : ''
|
||||
const arr = []
|
||||
startViewValue && arr.push(startViewValue)
|
||||
endViewValue && arr.push(endViewValue)
|
||||
const selectedDate = DateRangePicker.unFormatValue(value, format, joinValues, delimiter);
|
||||
const startViewValue = selectedDate.startDate ? selectedDate.startDate.format(inputFormat) : '';
|
||||
const endViewValue = selectedDate.endDate ? selectedDate.endDate.format(inputFormat) : '';
|
||||
const arr = [];
|
||||
startViewValue && arr.push(startViewValue);
|
||||
endViewValue && arr.push(endViewValue);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -537,8 +537,8 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
|
|||
</Overlay>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(DateRangePicker)
|
||||
export default themeable(DateRangePicker);
|
||||
|
|
|
@ -4,44 +4,44 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import Transition, {ENTERED, ENTERING, EXITING} from 'react-transition-group/Transition'
|
||||
import {Portal} from 'react-overlays'
|
||||
import {closeIcon} from './icons'
|
||||
import * as cx from 'classnames'
|
||||
import {current, addModal, removeModal} from './ModalManager'
|
||||
import onClickOutside from 'react-onclickoutside'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import {noop} from '../utils/helper'
|
||||
import * as React from 'react';
|
||||
import Transition, {ENTERED, ENTERING, EXITING} from 'react-transition-group/Transition';
|
||||
import {Portal} from 'react-overlays';
|
||||
import {closeIcon} from './icons';
|
||||
import * as cx from 'classnames';
|
||||
import {current, addModal, removeModal} from './ModalManager';
|
||||
import onClickOutside from 'react-onclickoutside';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {noop} from '../utils/helper';
|
||||
|
||||
type DrawerPosition = 'top' | 'right' | 'bottom' | 'left'
|
||||
type DrawerPosition = 'top' | 'right' | 'bottom' | 'left';
|
||||
|
||||
export interface DrawerProps {
|
||||
className?: string
|
||||
size: any
|
||||
overlay: boolean
|
||||
onHide: () => void
|
||||
closeOnEsc?: boolean
|
||||
container: any
|
||||
show?: boolean
|
||||
position: DrawerPosition
|
||||
disabled?: boolean
|
||||
closeOnOutside?: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
onExited?: () => void
|
||||
onEntered?: () => void
|
||||
disableOnClickOutside: () => void
|
||||
enableOnClickOutside: () => void
|
||||
className?: string;
|
||||
size: any;
|
||||
overlay: boolean;
|
||||
onHide: () => void;
|
||||
closeOnEsc?: boolean;
|
||||
container: any;
|
||||
show?: boolean;
|
||||
position: DrawerPosition;
|
||||
disabled?: boolean;
|
||||
closeOnOutside?: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
onExited?: () => void;
|
||||
onEntered?: () => void;
|
||||
disableOnClickOutside: () => void;
|
||||
enableOnClickOutside: () => void;
|
||||
}
|
||||
export interface DrawerState {}
|
||||
const fadeStyles: {
|
||||
[propName: string]: string
|
||||
[propName: string]: string;
|
||||
} = {
|
||||
[ENTERING]: 'in',
|
||||
[ENTERED]: 'in',
|
||||
}
|
||||
};
|
||||
export class Drawer extends React.Component<DrawerProps, DrawerState> {
|
||||
static defaultProps: Pick<
|
||||
DrawerProps,
|
||||
|
@ -53,48 +53,48 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
|
|||
overlay: true,
|
||||
disableOnClickOutside: noop,
|
||||
enableOnClickOutside: noop,
|
||||
}
|
||||
};
|
||||
|
||||
contentDom: any
|
||||
contentDom: any;
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.show) {
|
||||
this.handleEntered()
|
||||
this.handleEntered();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.show) {
|
||||
this.handleExited()
|
||||
this.handleExited();
|
||||
}
|
||||
}
|
||||
|
||||
contentRef = (ref: any) => (this.contentDom = ref)
|
||||
contentRef = (ref: any) => (this.contentDom = ref);
|
||||
handleEntered = () => {
|
||||
const onEntered = this.props.onEntered
|
||||
document.body.classList.add(`is-modalOpened`)
|
||||
onEntered && onEntered()
|
||||
}
|
||||
const onEntered = this.props.onEntered;
|
||||
document.body.classList.add(`is-modalOpened`);
|
||||
onEntered && onEntered();
|
||||
};
|
||||
handleExited = () => {
|
||||
const onExited = this.props.onExited
|
||||
onExited && onExited()
|
||||
const onExited = this.props.onExited;
|
||||
onExited && onExited();
|
||||
setTimeout(() => {
|
||||
document.querySelector('.amis-dialog-widget') || document.body.classList.remove(`is-modalOpened`)
|
||||
}, 200)
|
||||
}
|
||||
document.querySelector('.amis-dialog-widget') || document.body.classList.remove(`is-modalOpened`);
|
||||
}, 200);
|
||||
};
|
||||
|
||||
modalRef = (ref: any) => {
|
||||
if (ref) {
|
||||
addModal(this)
|
||||
;(ref as HTMLElement).classList.add(`${this.props.classPrefix}Modal--${current()}th`)
|
||||
addModal(this);
|
||||
(ref as HTMLElement).classList.add(`${this.props.classPrefix}Modal--${current()}th`);
|
||||
} else {
|
||||
removeModal()
|
||||
}
|
||||
removeModal();
|
||||
}
|
||||
};
|
||||
|
||||
handleClickOutside() {
|
||||
const {closeOnOutside, onHide} = this.props
|
||||
closeOnOutside && onHide && onHide()
|
||||
const {closeOnOutside, onHide} = this.props;
|
||||
closeOnOutside && onHide && onHide();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -109,7 +109,7 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
|
|||
onHide,
|
||||
disabled,
|
||||
overlay,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Portal container={container}>
|
||||
|
@ -126,7 +126,7 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
|
|||
// force reflow
|
||||
// 由于从 mount 进来到加上 in 这个 class 估计是时间太短,上次的样式还没应用进去,所以这里强制reflow一把。
|
||||
// 否则看不到动画。
|
||||
this.contentDom.offsetWidth
|
||||
this.contentDom.offsetWidth;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -151,12 +151,12 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
|
|||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</Transition>
|
||||
</Portal>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(onClickOutside(Drawer))
|
||||
export default themeable(onClickOutside(Drawer));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import {DropdownButton} from 'react-bootstrap'
|
||||
import {DropdownButton} from 'react-bootstrap';
|
||||
|
||||
export default DropdownButton
|
||||
export default DropdownButton;
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
function noJsExt(raw: string) {
|
||||
return raw.replace(/\.js$/, '')
|
||||
return raw.replace(/\.js$/, '');
|
||||
}
|
||||
|
||||
const defaultConfig = {
|
||||
|
@ -20,11 +20,11 @@ const defaultConfig = {
|
|||
},
|
||||
},
|
||||
paths: {},
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
// fis 编译的话,能正确赋值上,如果不是,那请通过外部参数传递。
|
||||
defaultConfig.url = __uri('monaco-editor/min/vs/loader.js')
|
||||
defaultConfig.url = __uri('monaco-editor/min/vs/loader.js');
|
||||
defaultConfig.paths = {
|
||||
vs: noJsExt(__uri('monaco-editor/min/vs/editor/editor.main.js')).replace(/\/vs\/.*$/, ''),
|
||||
'vs/base/worker/workerMain': noJsExt(__uri('monaco-editor/min/vs/base/worker/workerMain.js')),
|
||||
|
@ -115,10 +115,10 @@ try {
|
|||
|
||||
'vs/language/css/cssMode': noJsExt(__uri('monaco-editor/min/vs/language/css/cssMode.js')),
|
||||
'vs/language/css/cssWorker': noJsExt(__uri('monaco-editor/min/vs/language/css/cssWorker.js')),
|
||||
}
|
||||
};
|
||||
|
||||
// cdn 支持
|
||||
;/^(https?:)?\/\//.test(defaultConfig.paths.vs) &&
|
||||
/^(https?:)?\/\//.test(defaultConfig.paths.vs) &&
|
||||
((window as any).MonacoEnvironment = {
|
||||
getWorkerUrl: function() {
|
||||
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
|
||||
|
@ -126,9 +126,9 @@ try {
|
|||
baseUrl: '${defaultConfig.paths.vs}',
|
||||
paths: ${JSON.stringify(defaultConfig.paths)}
|
||||
};
|
||||
importScripts('${__uri('monaco-editor/min/vs/base/worker/workerMain.js')}');`)}`
|
||||
importScripts('${__uri('monaco-editor/min/vs/base/worker/workerMain.js')}');`)}`;
|
||||
},
|
||||
})
|
||||
});
|
||||
} catch (e) {}
|
||||
|
||||
export function monacoFactory(containerElement, monaco, options) {
|
||||
|
@ -143,35 +143,35 @@ export function monacoFactory(containerElement, monaco, options) {
|
|||
enabled: false,
|
||||
},
|
||||
...options,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export interface EditorProps {
|
||||
value?: string
|
||||
defaultValue?: string
|
||||
width?: number | string
|
||||
height?: number | string
|
||||
onChange?: (value: string, event: any) => void
|
||||
language?: string
|
||||
editorTheme?: string
|
||||
value?: string;
|
||||
defaultValue?: string;
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
onChange?: (value: string, event: any) => void;
|
||||
language?: string;
|
||||
editorTheme?: string;
|
||||
options: {
|
||||
[propName: string]: any
|
||||
}
|
||||
classPrefix: string
|
||||
className?: string
|
||||
classnames: ClassNamesFn
|
||||
context?: any
|
||||
style?: any
|
||||
onFocus?: () => void
|
||||
onBlur?: () => void
|
||||
editorDidMount?: (editor: any, monaco: any) => void
|
||||
editorWillMount?: (monaco: any) => void
|
||||
editorFactory?: (conatainer: HTMLElement, monaco: any, options: any) => any
|
||||
[propName: string]: any;
|
||||
};
|
||||
classPrefix: string;
|
||||
className?: string;
|
||||
classnames: ClassNamesFn;
|
||||
context?: any;
|
||||
style?: any;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
editorDidMount?: (editor: any, monaco: any) => void;
|
||||
editorWillMount?: (monaco: any) => void;
|
||||
editorFactory?: (conatainer: HTMLElement, monaco: any, options: any) => any;
|
||||
requireConfig: {
|
||||
url: string
|
||||
paths?: any
|
||||
[propName: string]: any
|
||||
}
|
||||
url: string;
|
||||
paths?: any;
|
||||
[propName: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export class Editor extends React.Component<EditorProps, any> {
|
||||
|
@ -182,60 +182,60 @@ export class Editor extends React.Component<EditorProps, any> {
|
|||
width: '100%',
|
||||
height: '100%',
|
||||
options: {},
|
||||
}
|
||||
};
|
||||
|
||||
editor: any
|
||||
container: any
|
||||
currentValue: any
|
||||
preventTriggerChangeEvent: boolean
|
||||
disposes: Array<{dispose: () => void}> = []
|
||||
editor: any;
|
||||
container: any;
|
||||
currentValue: any;
|
||||
preventTriggerChangeEvent: boolean;
|
||||
disposes: Array<{dispose: () => void}> = [];
|
||||
constructor(props: EditorProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.wrapperRef = this.wrapperRef.bind(this)
|
||||
this.currentValue = props.value
|
||||
this.wrapperRef = this.wrapperRef.bind(this);
|
||||
this.currentValue = props.value;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: EditorProps) {
|
||||
if (this.props.options.readOnly !== nextProps.options.readOnly && this.editor) {
|
||||
this.editor.updateOptions && this.editor.updateOptions(nextProps.options)
|
||||
this.editor.updateOptions && this.editor.updateOptions(nextProps.options);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.value !== this.currentValue && this.editor) {
|
||||
let value = String(this.props.value)
|
||||
let value = String(this.props.value);
|
||||
|
||||
if (this.props.language === 'json') {
|
||||
try {
|
||||
value = JSON.stringify(JSON.parse(value), null, 4)
|
||||
value = JSON.stringify(JSON.parse(value), null, 4);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
this.preventTriggerChangeEvent = true
|
||||
this.editor.setValue && this.editor.setValue(value)
|
||||
this.preventTriggerChangeEvent = false
|
||||
this.preventTriggerChangeEvent = true;
|
||||
this.editor.setValue && this.editor.setValue(value);
|
||||
this.preventTriggerChangeEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.disposes.forEach(({dispose}) => dispose())
|
||||
this.disposes = []
|
||||
this.disposes.forEach(({dispose}) => dispose());
|
||||
this.disposes = [];
|
||||
}
|
||||
|
||||
wrapperRef(ref: any) {
|
||||
this.container = ref
|
||||
this.container = ref;
|
||||
if (ref) {
|
||||
this.loadMonaco()
|
||||
this.loadMonaco();
|
||||
} else {
|
||||
try {
|
||||
this.disposes.forEach(({dispose}) => dispose())
|
||||
this.disposes = []
|
||||
this.disposes.forEach(({dispose}) => dispose());
|
||||
this.disposes = [];
|
||||
if (this.editor) {
|
||||
this.editor.getModel().dispose()
|
||||
this.editor.dispose()
|
||||
this.editor.getModel().dispose();
|
||||
this.editor.dispose();
|
||||
}
|
||||
this.editor = null
|
||||
this.editor = null;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
@ -243,86 +243,86 @@ export class Editor extends React.Component<EditorProps, any> {
|
|||
}
|
||||
|
||||
loadMonaco() {
|
||||
const {requireConfig} = this.props
|
||||
const loaderUrl = requireConfig.url || 'vs/loader.js'
|
||||
const {requireConfig} = this.props;
|
||||
const loaderUrl = requireConfig.url || 'vs/loader.js';
|
||||
const context =
|
||||
(window as any).monacaAmd ||
|
||||
((window as any).monacaAmd = {
|
||||
document: window.document,
|
||||
})
|
||||
});
|
||||
|
||||
const onGotAmdLoader = () => {
|
||||
if (context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__) {
|
||||
// Do not use webpack
|
||||
if (requireConfig.paths && requireConfig.paths.vs) {
|
||||
context.require.config(requireConfig)
|
||||
context.require.config(requireConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Load monaco
|
||||
context['require'](['vs/editor/editor.main', 'vs/editor/editor.main.nls.zh-cn'], () => {
|
||||
this.initMonaco()
|
||||
})
|
||||
this.initMonaco();
|
||||
});
|
||||
|
||||
// Call the delayed callbacks when AMD loader has been loaded
|
||||
if (context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__) {
|
||||
context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__ = false
|
||||
let loaderCallbacks = context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__
|
||||
context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__ = false;
|
||||
let loaderCallbacks = context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__;
|
||||
if (loaderCallbacks && loaderCallbacks.length) {
|
||||
let currentCallback = loaderCallbacks.shift()
|
||||
let currentCallback = loaderCallbacks.shift();
|
||||
while (currentCallback) {
|
||||
currentCallback.fn.call(currentCallback.context)
|
||||
currentCallback = loaderCallbacks.shift()
|
||||
}
|
||||
currentCallback.fn.call(currentCallback.context);
|
||||
currentCallback = loaderCallbacks.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Load AMD loader if necessary
|
||||
if (context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__) {
|
||||
// We need to avoid loading multiple loader.js when there are multiple editors loading concurrently
|
||||
// delay to call callbacks except the first one
|
||||
context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ = context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ || []
|
||||
context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ = context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ || [];
|
||||
context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__.push({
|
||||
context: this,
|
||||
fn: onGotAmdLoader,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
if (typeof context.require === 'undefined') {
|
||||
var loaderScript = context.document.createElement('script')
|
||||
loaderScript.type = 'text/javascript'
|
||||
loaderScript.src = loaderUrl
|
||||
loaderScript.addEventListener('load', onGotAmdLoader)
|
||||
context.document.body.appendChild(loaderScript)
|
||||
context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__ = true
|
||||
var loaderScript = context.document.createElement('script');
|
||||
loaderScript.type = 'text/javascript';
|
||||
loaderScript.src = loaderUrl;
|
||||
loaderScript.addEventListener('load', onGotAmdLoader);
|
||||
context.document.body.appendChild(loaderScript);
|
||||
context.__REACT_MONACO_EDITOR_LOADER_ISPENDING__ = true;
|
||||
} else {
|
||||
onGotAmdLoader()
|
||||
onGotAmdLoader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initMonaco() {
|
||||
let value = this.props.value !== null ? this.props.value : this.props.defaultValue
|
||||
const {language, editorTheme, options, editorFactory} = this.props
|
||||
const containerElement = this.container
|
||||
let value = this.props.value !== null ? this.props.value : this.props.defaultValue;
|
||||
const {language, editorTheme, options, editorFactory} = this.props;
|
||||
const containerElement = this.container;
|
||||
if (!containerElement) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
const context = this.props.context || window
|
||||
const monaco = context.monaco || (window as any).monaco
|
||||
const context = this.props.context || window;
|
||||
const monaco = context.monaco || (window as any).monaco;
|
||||
if (typeof monaco !== 'undefined') {
|
||||
// Before initializing monaco editor
|
||||
this.editorWillMount(monaco)
|
||||
this.editorWillMount(monaco);
|
||||
|
||||
if (this.props.language === 'json') {
|
||||
try {
|
||||
value = JSON.stringify(typeof value === 'string' ? JSON.parse(value) : value, null, 4)
|
||||
value = JSON.stringify(typeof value === 'string' ? JSON.parse(value) : value, null, 4);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
const factory = editorFactory || monacoFactory
|
||||
const factory = editorFactory || monacoFactory;
|
||||
this.editor = factory(containerElement, monaco, {
|
||||
...options,
|
||||
automaticLayout: true,
|
||||
|
@ -330,45 +330,45 @@ export class Editor extends React.Component<EditorProps, any> {
|
|||
language,
|
||||
editorTheme,
|
||||
theme: editorTheme,
|
||||
})
|
||||
});
|
||||
|
||||
// After initializing monaco editor
|
||||
this.editorDidMount(this.editor, monaco)
|
||||
this.editorDidMount(this.editor, monaco);
|
||||
}
|
||||
}
|
||||
|
||||
editorWillMount(monaco: any) {
|
||||
const {editorWillMount} = this.props
|
||||
editorWillMount && editorWillMount(monaco)
|
||||
const {editorWillMount} = this.props;
|
||||
editorWillMount && editorWillMount(monaco);
|
||||
}
|
||||
editorDidMount(editor: any, monaco: any) {
|
||||
const {editorDidMount, onChange, onFocus, onBlur} = this.props
|
||||
editorDidMount && editorDidMount(editor, monaco)
|
||||
const {editorDidMount, onChange, onFocus, onBlur} = this.props;
|
||||
editorDidMount && editorDidMount(editor, monaco);
|
||||
editor.onDidChangeModelContent &&
|
||||
this.disposes.push(
|
||||
editor.onDidChangeModelContent((event: any) => {
|
||||
const value = editor.getValue()
|
||||
const value = editor.getValue();
|
||||
// Always refer to the latest value
|
||||
this.currentValue = value
|
||||
this.currentValue = value;
|
||||
|
||||
// Only invoking when user input changed
|
||||
if (!this.preventTriggerChangeEvent && onChange) {
|
||||
onChange(value, event)
|
||||
onChange(value, event);
|
||||
}
|
||||
})
|
||||
)
|
||||
onFocus && editor.onDidFocusEditorWidget && this.disposes.push(editor.onDidFocusEditorWidget(onFocus))
|
||||
onBlur && editor.onDidBlurEditorWidget && this.disposes.push(editor.onDidBlurEditorWidget(onBlur))
|
||||
);
|
||||
onFocus && editor.onDidFocusEditorWidget && this.disposes.push(editor.onDidFocusEditorWidget(onFocus));
|
||||
onBlur && editor.onDidBlurEditorWidget && this.disposes.push(editor.onDidBlurEditorWidget(onBlur));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className, classPrefix: ns, width, height} = this.props
|
||||
let style = this.props.style || {}
|
||||
style.width = width
|
||||
style.height = height
|
||||
const {className, classPrefix: ns, width, height} = this.props;
|
||||
let style = this.props.style || {};
|
||||
style.width = width;
|
||||
style.height = height;
|
||||
|
||||
return <div className={cx(`${ns}MonacoEditor`, className)} style={style} ref={this.wrapperRef} />
|
||||
return <div className={cx(`${ns}MonacoEditor`, className)} style={style} ref={this.wrapperRef} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Editor)
|
||||
export default themeable(Editor);
|
||||
|
|
|
@ -4,63 +4,63 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface HtmlProps {
|
||||
className?: string
|
||||
html?: string
|
||||
wrapperComponent?: any
|
||||
inline: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
className?: string;
|
||||
html?: string;
|
||||
wrapperComponent?: any;
|
||||
inline: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Html extends React.Component<HtmlProps> {
|
||||
static defaultProps = {
|
||||
inline: true,
|
||||
}
|
||||
};
|
||||
|
||||
dom: any
|
||||
dom: any;
|
||||
|
||||
constructor(props: HtmlProps) {
|
||||
super(props)
|
||||
this.htmlRef = this.htmlRef.bind(this)
|
||||
super(props);
|
||||
this.htmlRef = this.htmlRef.bind(this);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: HtmlProps) {
|
||||
if (this.props.html !== prevProps.html) {
|
||||
this._render()
|
||||
this._render();
|
||||
}
|
||||
}
|
||||
|
||||
htmlRef(dom: any) {
|
||||
this.dom = dom
|
||||
this.dom = dom;
|
||||
|
||||
if (!dom) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this._render()
|
||||
this._render();
|
||||
}
|
||||
|
||||
_render() {
|
||||
const {html} = this.props
|
||||
const {html} = this.props;
|
||||
|
||||
if (html) {
|
||||
this.dom.innerHTML = html
|
||||
this.dom.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className, wrapperComponent, inline, classPrefix: ns} = this.props
|
||||
const {className, wrapperComponent, inline, classPrefix: ns} = this.props;
|
||||
|
||||
const Component = wrapperComponent || (inline ? 'span' : 'div')
|
||||
const Component = wrapperComponent || (inline ? 'span' : 'div');
|
||||
|
||||
return <Component ref={this.htmlRef} className={cx(`${ns}Html`, className)} />
|
||||
return <Component ref={this.htmlRef} className={cx(`${ns}Html`, className)} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Html)
|
||||
export default themeable(Html);
|
||||
|
|
|
@ -16,26 +16,26 @@
|
|||
* * contentClassName 内容区域附加样式名称
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface LayoutProps {
|
||||
id: string
|
||||
header?: boolean | React.ReactNode
|
||||
aside?: boolean | React.ReactNode
|
||||
asideClassName: string
|
||||
folded?: boolean
|
||||
asideFixed: boolean
|
||||
headerFixed: boolean
|
||||
className?: string
|
||||
contentClassName?: string
|
||||
footer: boolean | React.ReactNode
|
||||
asideWide: boolean
|
||||
offScreen: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
size?: 'sm' | 'base' | 'md' | 'lg'
|
||||
id: string;
|
||||
header?: boolean | React.ReactNode;
|
||||
aside?: boolean | React.ReactNode;
|
||||
asideClassName: string;
|
||||
folded?: boolean;
|
||||
asideFixed: boolean;
|
||||
headerFixed: boolean;
|
||||
className?: string;
|
||||
contentClassName?: string;
|
||||
footer: boolean | React.ReactNode;
|
||||
asideWide: boolean;
|
||||
offScreen: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
size?: 'sm' | 'base' | 'md' | 'lg';
|
||||
}
|
||||
|
||||
export class Layout extends React.Component<LayoutProps, any> {
|
||||
|
@ -46,7 +46,7 @@ export class Layout extends React.Component<LayoutProps, any> {
|
|||
headerFixed: true,
|
||||
offScreen: false,
|
||||
footer: false,
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -65,16 +65,16 @@ export class Layout extends React.Component<LayoutProps, any> {
|
|||
size,
|
||||
classPrefix,
|
||||
classnames: cx,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
let body = <div className={cx(`Layout-body`, contentClassName)}>{children}</div>
|
||||
let body = <div className={cx(`Layout-body`, contentClassName)}>{children}</div>;
|
||||
|
||||
if (aside) {
|
||||
body = (
|
||||
<div className={cx('Layout-content')} role="main">
|
||||
{body}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -107,8 +107,8 @@ export class Layout extends React.Component<LayoutProps, any> {
|
|||
</footer>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Layout)
|
||||
export default themeable(Layout);
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import VisibilitySensor = require('react-visibility-sensor')
|
||||
import * as React from 'react';
|
||||
import VisibilitySensor = require('react-visibility-sensor');
|
||||
|
||||
export interface LazyComponentProps {
|
||||
component?: React.ReactType
|
||||
getComponent?: () => Promise<React.ReactType>
|
||||
placeholder?: React.ReactNode
|
||||
unMountOnHidden?: boolean
|
||||
childProps?: object
|
||||
visiblilityProps?: object
|
||||
[propName: string]: any
|
||||
component?: React.ReactType;
|
||||
getComponent?: () => Promise<React.ReactType>;
|
||||
placeholder?: React.ReactNode;
|
||||
unMountOnHidden?: boolean;
|
||||
childProps?: object;
|
||||
visiblilityProps?: object;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export interface LazyComponentState {
|
||||
visible: boolean
|
||||
component?: React.ReactType
|
||||
visible: boolean;
|
||||
component?: React.ReactType;
|
||||
}
|
||||
|
||||
export default class LazyComponent extends React.Component<LazyComponentProps, LazyComponentState> {
|
||||
|
@ -27,26 +27,26 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
|
|||
placeholder: '加载中...',
|
||||
unMountOnHidden: false,
|
||||
partialVisibility: true,
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: LazyComponentProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.handleVisibleChange = this.handleVisibleChange.bind(this)
|
||||
this.handleVisibleChange = this.handleVisibleChange.bind(this);
|
||||
|
||||
this.state = {
|
||||
visible: false,
|
||||
component: props.component as React.ReactType,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
handleVisibleChange(visible: boolean) {
|
||||
this.setState({
|
||||
visible: visible,
|
||||
})
|
||||
});
|
||||
|
||||
if (!visible || this.state.component || !this.props.getComponent) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.props
|
||||
|
@ -60,13 +60,13 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
|
|||
this.setState({
|
||||
component: () => <div className="alert alert-danger">{String(reason)}</div>,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {placeholder, unMountOnHidden, childProps, visiblilityProps, partialVisibility, ...rest} = this.props
|
||||
const {placeholder, unMountOnHidden, childProps, visiblilityProps, partialVisibility, ...rest} = this.props;
|
||||
|
||||
const {visible, component: Component} = this.state
|
||||
const {visible, component: Component} = this.state;
|
||||
|
||||
// 需要监听从可见到不可见。
|
||||
if (unMountOnHidden) {
|
||||
|
@ -80,7 +80,7 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
|
|||
{Component && visible ? <Component {...rest} {...childProps} /> : placeholder}
|
||||
</div>
|
||||
</VisibilitySensor>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!visible) {
|
||||
|
@ -92,12 +92,12 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
|
|||
>
|
||||
<div className="visibility-sensor">{placeholder}</div>
|
||||
</VisibilitySensor>
|
||||
)
|
||||
);
|
||||
} else if (Component) {
|
||||
// 只监听不可见到可见,一旦可见了,就销毁检查。
|
||||
return <Component {...rest} {...childProps} />
|
||||
return <Component {...rest} {...childProps} />;
|
||||
}
|
||||
|
||||
return <div>{placeholder}</div>
|
||||
return <div>{placeholder}</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,81 +4,81 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition'
|
||||
import {Portal} from 'react-overlays'
|
||||
import * as cx from 'classnames'
|
||||
import {current, addModal, removeModal} from './ModalManager'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition';
|
||||
import {Portal} from 'react-overlays';
|
||||
import * as cx from 'classnames';
|
||||
import {current, addModal, removeModal} from './ModalManager';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface ModalProps {
|
||||
className?: string
|
||||
size?: any
|
||||
overlay?: boolean
|
||||
onHide: () => void
|
||||
closeOnEsc?: boolean
|
||||
container?: any
|
||||
show?: boolean
|
||||
disabled?: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
onExited?: () => void
|
||||
onEntered?: () => void
|
||||
className?: string;
|
||||
size?: any;
|
||||
overlay?: boolean;
|
||||
onHide: () => void;
|
||||
closeOnEsc?: boolean;
|
||||
container?: any;
|
||||
show?: boolean;
|
||||
disabled?: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
onExited?: () => void;
|
||||
onEntered?: () => void;
|
||||
}
|
||||
export interface ModalState {}
|
||||
const fadeStyles: {
|
||||
[propName: string]: string
|
||||
[propName: string]: string;
|
||||
} = {
|
||||
[ENTERING]: 'in',
|
||||
[ENTERED]: 'in',
|
||||
}
|
||||
};
|
||||
export class Modal extends React.Component<ModalProps, ModalState> {
|
||||
static defaultProps = {
|
||||
container: document.body,
|
||||
size: '',
|
||||
overlay: true,
|
||||
}
|
||||
};
|
||||
|
||||
contentDom: any
|
||||
contentDom: any;
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.show) {
|
||||
this.handleEntered()
|
||||
this.handleEntered();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.show) {
|
||||
this.handleExited()
|
||||
this.handleExited();
|
||||
}
|
||||
}
|
||||
|
||||
contentRef = (ref: any) => (this.contentDom = ref)
|
||||
contentRef = (ref: any) => (this.contentDom = ref);
|
||||
handleEntered = () => {
|
||||
const onEntered = this.props.onEntered
|
||||
document.body.classList.add(`is-modalOpened`)
|
||||
onEntered && onEntered()
|
||||
}
|
||||
const onEntered = this.props.onEntered;
|
||||
document.body.classList.add(`is-modalOpened`);
|
||||
onEntered && onEntered();
|
||||
};
|
||||
handleExited = () => {
|
||||
const onExited = this.props.onExited
|
||||
onExited && onExited()
|
||||
const onExited = this.props.onExited;
|
||||
onExited && onExited();
|
||||
setTimeout(() => {
|
||||
document.querySelector('.amis-dialog-widget') || document.body.classList.remove(`is-modalOpened`)
|
||||
}, 200)
|
||||
}
|
||||
document.querySelector('.amis-dialog-widget') || document.body.classList.remove(`is-modalOpened`);
|
||||
}, 200);
|
||||
};
|
||||
|
||||
modalRef = (ref: any) => {
|
||||
const {classPrefix: ns} = this.props
|
||||
const {classPrefix: ns} = this.props;
|
||||
if (ref) {
|
||||
addModal(this)
|
||||
;(ref as HTMLElement).classList.add(`${ns}Modal--${current()}th`)
|
||||
addModal(this);
|
||||
(ref as HTMLElement).classList.add(`${ns}Modal--${current()}th`);
|
||||
} else {
|
||||
removeModal()
|
||||
}
|
||||
removeModal();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {className, children, container, show, size, overlay, classPrefix: ns} = this.props
|
||||
const {className, children, container, show, size, overlay, classPrefix: ns} = this.props;
|
||||
|
||||
return (
|
||||
<Portal container={container}>
|
||||
|
@ -95,7 +95,7 @@ export class Modal extends React.Component<ModalProps, ModalState> {
|
|||
// force reflow
|
||||
// 由于从 mount 进来到加上 in 这个 class 估计是时间太短,上次的样式还没应用进去,所以这里强制reflow一把。
|
||||
// 否则看不到动画。
|
||||
this.contentDom.offsetWidth
|
||||
this.contentDom.offsetWidth;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -115,12 +115,12 @@ export class Modal extends React.Component<ModalProps, ModalState> {
|
|||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</Transition>
|
||||
</Portal>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Modal)
|
||||
export default themeable(Modal);
|
||||
|
|
|
@ -4,46 +4,46 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as keycode from 'keycode'
|
||||
import * as keycode from 'keycode';
|
||||
|
||||
interface ModalComponent
|
||||
extends React.Component<{
|
||||
onHide: () => void
|
||||
disabled?: boolean
|
||||
closeOnEsc?: boolean
|
||||
onHide: () => void;
|
||||
disabled?: boolean;
|
||||
closeOnEsc?: boolean;
|
||||
}> {}
|
||||
|
||||
let modals: Array<ModalComponent> = []
|
||||
let modals: Array<ModalComponent> = [];
|
||||
|
||||
export function current() {
|
||||
return modals.length
|
||||
return modals.length;
|
||||
}
|
||||
|
||||
export function currentModal(): ModalComponent | void {
|
||||
return modals[modals.length - 1]
|
||||
return modals[modals.length - 1];
|
||||
}
|
||||
|
||||
export function addModal(modal: ModalComponent) {
|
||||
modals.push(modal)
|
||||
modals.push(modal);
|
||||
}
|
||||
|
||||
export function removeModal() {
|
||||
modals.pop()
|
||||
modals.pop();
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleWindowKeyDown)
|
||||
window.addEventListener('keydown', handleWindowKeyDown);
|
||||
|
||||
function handleWindowKeyDown(e: Event) {
|
||||
const code = keycode(e)
|
||||
const code = keycode(e);
|
||||
if (code !== 'esc') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let modal = currentModal()
|
||||
let modal = currentModal();
|
||||
if (!modal) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
const {disabled, closeOnEsc} = modal.props
|
||||
const {disabled, closeOnEsc} = modal.props;
|
||||
if (closeOnEsc && !disabled) {
|
||||
modal.props.onHide()
|
||||
modal.props.onHide();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import {Position, Overlay as BaseOverlay} from 'react-overlays'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import * as React from 'react'
|
||||
import {calculatePosition, getContainer, ownerDocument} from '../utils/dom'
|
||||
import {Position, Overlay as BaseOverlay} from 'react-overlays';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import * as React from 'react';
|
||||
import {calculatePosition, getContainer, ownerDocument} from '../utils/dom';
|
||||
|
||||
Position.propTypes.placement = BaseOverlay.propTypes.placement = () => null
|
||||
Position.propTypes.placement = BaseOverlay.propTypes.placement = () => null;
|
||||
|
||||
Position.prototype.updatePosition = function(target: any) {
|
||||
this._lastTarget = target
|
||||
this._lastTarget = target;
|
||||
|
||||
if (!target) {
|
||||
return this.setState({
|
||||
|
@ -20,29 +20,29 @@ Position.prototype.updatePosition = function(target: any) {
|
|||
positionTop: 0,
|
||||
arrowOffsetLeft: null,
|
||||
arrowOffsetTop: null,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const overlay = findDOMNode(this)
|
||||
const container = getContainer(this.props.container, ownerDocument(this).body)
|
||||
const overlay = findDOMNode(this);
|
||||
const container = getContainer(this.props.container, ownerDocument(this).body);
|
||||
|
||||
this.setState(calculatePosition(this.props.placement, overlay, target, container, this.props.containerPadding))
|
||||
}
|
||||
this.setState(calculatePosition(this.props.placement, overlay, target, container, this.props.containerPadding));
|
||||
};
|
||||
|
||||
interface OverlayProps {
|
||||
placement?: string
|
||||
show?: boolean
|
||||
rootClose?: boolean
|
||||
onHide?(props: any, ...args: any[]): any
|
||||
container?: React.ReactNode | Function
|
||||
target?: React.ReactNode | Function
|
||||
placement?: string;
|
||||
show?: boolean;
|
||||
rootClose?: boolean;
|
||||
onHide?(props: any, ...args: any[]): any;
|
||||
container?: React.ReactNode | Function;
|
||||
target?: React.ReactNode | Function;
|
||||
}
|
||||
export default class Overlay extends React.Component<OverlayProps> {
|
||||
constructor(props: OverlayProps) {
|
||||
super(props as any)
|
||||
super(props as any);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <BaseOverlay {...this.props as any} />
|
||||
return <BaseOverlay {...this.props as any} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,35 +4,35 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface Offset {
|
||||
x: number
|
||||
y: number
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface PopOverPorps {
|
||||
className?: string
|
||||
placement?: string
|
||||
positionTop?: number
|
||||
positionLeft?: number
|
||||
arrowOffsetLeft?: number
|
||||
arrowOffsetTop?: number
|
||||
offset?: ((clip: object, offset: object) => Offset) | Offset
|
||||
style?: object
|
||||
overlay?: boolean
|
||||
onHide?: () => void
|
||||
onClick?: (e: React.MouseEvent<any>) => void
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
[propName: string]: any
|
||||
className?: string;
|
||||
placement?: string;
|
||||
positionTop?: number;
|
||||
positionLeft?: number;
|
||||
arrowOffsetLeft?: number;
|
||||
arrowOffsetTop?: number;
|
||||
offset?: ((clip: object, offset: object) => Offset) | Offset;
|
||||
style?: object;
|
||||
overlay?: boolean;
|
||||
onHide?: () => void;
|
||||
onClick?: (e: React.MouseEvent<any>) => void;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
interface PopOverState {
|
||||
xOffset: number
|
||||
yOffset: number
|
||||
xOffset: number;
|
||||
yOffset: number;
|
||||
}
|
||||
|
||||
export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
|
||||
|
@ -44,41 +44,41 @@ export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
|
|||
},
|
||||
overlay: false,
|
||||
placement: 'bottom',
|
||||
}
|
||||
};
|
||||
|
||||
state = {
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.mayUpdateOffset()
|
||||
this.mayUpdateOffset();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.mayUpdateOffset()
|
||||
this.mayUpdateOffset();
|
||||
}
|
||||
|
||||
mayUpdateOffset() {
|
||||
let offset: Offset
|
||||
let getOffset = this.props.offset
|
||||
let offset: Offset;
|
||||
let getOffset = this.props.offset;
|
||||
|
||||
if (getOffset && typeof getOffset === 'function') {
|
||||
const {placement, positionTop: y, positionLeft: x} = this.props
|
||||
const {placement, positionTop: y, positionLeft: x} = this.props;
|
||||
|
||||
offset = getOffset((findDOMNode(this) as HTMLElement).getBoundingClientRect(), {
|
||||
x,
|
||||
y,
|
||||
placement,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
offset = getOffset as Offset
|
||||
offset = getOffset as Offset;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
xOffset: offset ? (offset as Offset).x : 0,
|
||||
yOffset: offset ? offset.y : 0,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -97,24 +97,24 @@ export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
|
|||
classnames: cx,
|
||||
className,
|
||||
...rest
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
const {xOffset, yOffset} = this.state
|
||||
const {xOffset, yOffset} = this.state;
|
||||
|
||||
const outerStyle = {
|
||||
display: 'block',
|
||||
...style,
|
||||
top: (positionTop as number) + yOffset,
|
||||
left: (positionLeft as number) + xOffset,
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cx(`${ns}PopOver`, className, `${ns}PopOver--${placement}`)} style={outerStyle} {...rest}>
|
||||
{overlay ? <div className={`${ns}PopOver-overlay`} onClick={onHide} /> : null}
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(PopOver)
|
||||
export default themeable(PopOver);
|
||||
|
|
|
@ -13,25 +13,25 @@
|
|||
* ]
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import Checkbox from './Checkbox'
|
||||
import {value2array, OptionProps, Option} from './Checkboxes'
|
||||
import chunk = require('lodash/chunk')
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import Checkbox from './Checkbox';
|
||||
import {value2array, OptionProps, Option} from './Checkboxes';
|
||||
import chunk = require('lodash/chunk');
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface RadioProps extends OptionProps {
|
||||
id?: string
|
||||
type: string
|
||||
value?: string
|
||||
className?: string
|
||||
style?: React.CSSProperties
|
||||
inline?: boolean
|
||||
disabled?: boolean
|
||||
onChange?: Function
|
||||
columnsCount: number
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
id?: string;
|
||||
type: string;
|
||||
value?: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
inline?: boolean;
|
||||
disabled?: boolean;
|
||||
onChange?: Function;
|
||||
columnsCount: number;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Radios extends React.Component<RadioProps, any> {
|
||||
|
@ -39,36 +39,36 @@ export class Radios extends React.Component<RadioProps, any> {
|
|||
joinValues: true,
|
||||
clearable: false,
|
||||
columnsCount: 1, // 一行显示一个
|
||||
}
|
||||
};
|
||||
|
||||
toggleOption(option: Option) {
|
||||
const {value, onChange, joinValues, extractValue, valueField, clearable, delimiter, options} = this.props
|
||||
const {value, onChange, joinValues, extractValue, valueField, clearable, delimiter, options} = this.props;
|
||||
|
||||
let valueArray = value2array(value, {
|
||||
multiple: false,
|
||||
delimiter,
|
||||
valueField,
|
||||
options,
|
||||
})
|
||||
const idx = valueArray.indexOf(option)
|
||||
});
|
||||
const idx = valueArray.indexOf(option);
|
||||
|
||||
if (~idx) {
|
||||
clearable && valueArray.splice(idx, 1)
|
||||
clearable && valueArray.splice(idx, 1);
|
||||
} else {
|
||||
valueArray = [option]
|
||||
valueArray = [option];
|
||||
}
|
||||
|
||||
let newValue = valueArray[0]
|
||||
let newValue = valueArray[0];
|
||||
|
||||
if (newValue && (joinValues || extractValue)) {
|
||||
newValue = newValue[valueField || 'value']
|
||||
newValue = newValue[valueField || 'value'];
|
||||
}
|
||||
|
||||
// if (joinValues && newValue) {
|
||||
// newValue = newValue[valueField || 'value'];
|
||||
// }
|
||||
|
||||
onChange && onChange(newValue)
|
||||
onChange && onChange(newValue);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -84,15 +84,15 @@ export class Radios extends React.Component<RadioProps, any> {
|
|||
delimiter,
|
||||
valueField,
|
||||
classPrefix,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
let valueArray = value2array(value, {
|
||||
multiple: false,
|
||||
delimiter,
|
||||
valueField,
|
||||
options,
|
||||
})
|
||||
let body: Array<React.ReactNode> = []
|
||||
});
|
||||
let body: Array<React.ReactNode> = [];
|
||||
|
||||
if (options) {
|
||||
body = options.map((option, key) => (
|
||||
|
@ -108,12 +108,12 @@ export class Radios extends React.Component<RadioProps, any> {
|
|||
>
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
if (!inline && columnsCount > 1) {
|
||||
let weight = 12 / (columnsCount as number)
|
||||
let cellClassName = `Grid-col--sm${weight === Math.round(weight) ? weight : ''}`
|
||||
let weight = 12 / (columnsCount as number);
|
||||
let cellClassName = `Grid-col--sm${weight === Math.round(weight) ? weight : ''}`;
|
||||
body = chunk(body, columnsCount).map((group, groupIndex) => (
|
||||
<div className={cx('Grid')} key={groupIndex}>
|
||||
{group.map((item, index) => (
|
||||
|
@ -122,10 +122,10 @@ export class Radios extends React.Component<RadioProps, any> {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
return <div className={className}>{body && body.length ? body : placeholder}</div>
|
||||
return <div className={className}>{body && body.length ? body : placeholder}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,4 +133,4 @@ export default themeable(
|
|||
uncontrollable(Radios, {
|
||||
value: 'onChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -4,31 +4,31 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as InputRange from 'react-input-range'
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import * as cx from 'classnames'
|
||||
import {RendererProps} from '../factory'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as InputRange from 'react-input-range';
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import * as cx from 'classnames';
|
||||
import {RendererProps} from '../factory';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface RangeProps extends RendererProps {
|
||||
id?: string
|
||||
className?: string
|
||||
min: number
|
||||
max: number
|
||||
value?: number
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
id?: string;
|
||||
className?: string;
|
||||
min: number;
|
||||
max: number;
|
||||
value?: number;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Range extends React.Component<RangeProps, any> {
|
||||
static defaultProps: Partial<RangeProps> = {
|
||||
min: 1,
|
||||
max: 100,
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {min, max, value, className, classPrefix: ns} = this.props
|
||||
const {min, max, value, className, classPrefix: ns} = this.props;
|
||||
|
||||
const classNames = {
|
||||
activeTrack: `${ns}InputRange-track is-active`,
|
||||
|
@ -41,7 +41,7 @@ export class Range extends React.Component<RangeProps, any> {
|
|||
sliderContainer: `${ns}InputRange-sliderContainer`,
|
||||
track: `${ns}InputRange-track ${ns}InputRange-track--background`,
|
||||
valueLabel: `${ns}InputRange-label ${ns}InputRange-label--value`,
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<InputRange
|
||||
|
@ -52,7 +52,7 @@ export class Range extends React.Component<RangeProps, any> {
|
|||
maxValue={max}
|
||||
value={typeof value === 'number' ? value : min}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,4 +60,4 @@ export default themeable(
|
|||
uncontrollable(Range, {
|
||||
value: 'onChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -4,25 +4,25 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface RatingProps {
|
||||
id?: string
|
||||
key?: string | number
|
||||
style?: React.CSSProperties
|
||||
count: number
|
||||
half: boolean
|
||||
char: string
|
||||
size: number
|
||||
className?: string
|
||||
onChange?: (value: any) => void
|
||||
value: number
|
||||
containerClass: string
|
||||
readOnly: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
id?: string;
|
||||
key?: string | number;
|
||||
style?: React.CSSProperties;
|
||||
count: number;
|
||||
half: boolean;
|
||||
char: string;
|
||||
size: number;
|
||||
className?: string;
|
||||
onChange?: (value: any) => void;
|
||||
value: number;
|
||||
containerClass: string;
|
||||
readOnly: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Rating extends React.Component<RatingProps, any> {
|
||||
|
@ -34,10 +34,10 @@ export class Rating extends React.Component<RatingProps, any> {
|
|||
count: 5,
|
||||
char: '★',
|
||||
size: 24,
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: RatingProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: props.value || 0,
|
||||
|
@ -46,21 +46,21 @@ export class Rating extends React.Component<RatingProps, any> {
|
|||
at: Math.floor(props.value),
|
||||
hidden: props.half && props.value % 1 < 0.5,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
this.getRate = this.getRate.bind(this)
|
||||
this.getStars = this.getStars.bind(this)
|
||||
this.moreThanHalf = this.moreThanHalf.bind(this)
|
||||
this.mouseOver = this.mouseOver.bind(this)
|
||||
this.mouseLeave = this.mouseLeave.bind(this)
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.getRate = this.getRate.bind(this);
|
||||
this.getStars = this.getStars.bind(this);
|
||||
this.moreThanHalf = this.moreThanHalf.bind(this);
|
||||
this.mouseOver = this.mouseOver.bind(this);
|
||||
this.mouseLeave = this.mouseLeave.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {value} = this.state
|
||||
const {value} = this.state;
|
||||
this.setState({
|
||||
stars: this.getStars(value),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props: RatingProps) {
|
||||
|
@ -71,114 +71,114 @@ export class Rating extends React.Component<RatingProps, any> {
|
|||
at: Math.floor(props.value),
|
||||
hidden: props.half && props.value % 1 < 0.5,
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getRate() {
|
||||
let stars
|
||||
const {value} = this.state
|
||||
const {half} = this.props
|
||||
let stars;
|
||||
const {value} = this.state;
|
||||
const {half} = this.props;
|
||||
if (half) {
|
||||
stars = Math.floor(value)
|
||||
stars = Math.floor(value);
|
||||
} else {
|
||||
stars = Math.round(value)
|
||||
stars = Math.round(value);
|
||||
}
|
||||
return stars
|
||||
return stars;
|
||||
}
|
||||
|
||||
getStars(activeCount?: number) {
|
||||
if (typeof activeCount === 'undefined') {
|
||||
activeCount = this.getRate()
|
||||
activeCount = this.getRate();
|
||||
}
|
||||
let stars = []
|
||||
const {count} = this.props
|
||||
let stars = [];
|
||||
const {count} = this.props;
|
||||
for (let i = 0; i < count; i++) {
|
||||
stars.push({
|
||||
active: i <= activeCount - 1,
|
||||
})
|
||||
});
|
||||
}
|
||||
return stars
|
||||
return stars;
|
||||
}
|
||||
|
||||
mouseOver(event: React.ChangeEvent<any>) {
|
||||
let {readOnly, size, half} = this.props
|
||||
if (readOnly) return
|
||||
let index = Number(event.target.getAttribute('data-index'))
|
||||
let {readOnly, size, half} = this.props;
|
||||
if (readOnly) return;
|
||||
let index = Number(event.target.getAttribute('data-index'));
|
||||
if (half) {
|
||||
const isAtHalf = this.moreThanHalf(event, size)
|
||||
if (isAtHalf) index = index + 1
|
||||
const isAtHalf = this.moreThanHalf(event, size);
|
||||
if (isAtHalf) index = index + 1;
|
||||
this.setState({
|
||||
halfStar: {
|
||||
at: index,
|
||||
hidden: isAtHalf,
|
||||
},
|
||||
})
|
||||
});
|
||||
} else {
|
||||
index = index + 1
|
||||
index = index + 1;
|
||||
}
|
||||
this.setState({
|
||||
stars: this.getStars(index),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
moreThanHalf(event: any, size: number) {
|
||||
let {target} = event
|
||||
let mouseAt = event.clientX - target.getBoundingClientRect().left
|
||||
mouseAt = Math.round(Math.abs(mouseAt))
|
||||
return mouseAt > size / 2
|
||||
let {target} = event;
|
||||
let mouseAt = event.clientX - target.getBoundingClientRect().left;
|
||||
mouseAt = Math.round(Math.abs(mouseAt));
|
||||
return mouseAt > size / 2;
|
||||
}
|
||||
|
||||
mouseLeave() {
|
||||
let {value} = this.state
|
||||
const {half, readOnly} = this.props
|
||||
if (readOnly) return
|
||||
let {value} = this.state;
|
||||
const {half, readOnly} = this.props;
|
||||
if (readOnly) return;
|
||||
if (half) {
|
||||
this.setState({
|
||||
halfStar: {
|
||||
at: Math.floor(value),
|
||||
hidden: value % 1 === 0, // check value is decimal or not
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
stars: this.getStars(),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleClick(event: React.ChangeEvent<any>) {
|
||||
const {half, readOnly, onChange, size} = this.props
|
||||
if (readOnly) return
|
||||
let index = Number(event.target.getAttribute('data-index'))
|
||||
let value
|
||||
const {half, readOnly, onChange, size} = this.props;
|
||||
if (readOnly) return;
|
||||
let index = Number(event.target.getAttribute('data-index'));
|
||||
let value;
|
||||
if (half) {
|
||||
const isAtHalf = this.moreThanHalf(event, size)
|
||||
if (isAtHalf) index = index + 1
|
||||
value = isAtHalf ? index : index + 0.5
|
||||
const isAtHalf = this.moreThanHalf(event, size);
|
||||
if (isAtHalf) index = index + 1;
|
||||
value = isAtHalf ? index : index + 0.5;
|
||||
this.setState({
|
||||
halfStar: {
|
||||
at: index,
|
||||
hidden: isAtHalf,
|
||||
},
|
||||
})
|
||||
});
|
||||
} else {
|
||||
value = index = index + 1
|
||||
value = index = index + 1;
|
||||
}
|
||||
this.setState({
|
||||
value: value,
|
||||
stars: this.getStars(index),
|
||||
})
|
||||
onChange && onChange(value)
|
||||
});
|
||||
onChange && onChange(value);
|
||||
}
|
||||
|
||||
renderStars() {
|
||||
const {halfStar, stars} = this.state
|
||||
const {char, half, readOnly, classnames: cx} = this.props
|
||||
const {halfStar, stars} = this.state;
|
||||
const {char, half, readOnly, classnames: cx} = this.props;
|
||||
return stars.map((star: any, i: number) => {
|
||||
let className = cx('Rating', {
|
||||
'Rating-half': half && !halfStar.hidden && halfStar.at === i,
|
||||
'is-active': star.active,
|
||||
'is-disabled': readOnly,
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
|
@ -193,15 +193,15 @@ export class Rating extends React.Component<RatingProps, any> {
|
|||
>
|
||||
{char}
|
||||
</span>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let {className} = this.props
|
||||
let {className} = this.props;
|
||||
|
||||
return <div className={cx(className ? className : '')}>{this.renderStars()}</div>
|
||||
return <div className={cx(className ? className : '')}>{this.renderStars()}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Rating)
|
||||
export default themeable(Rating);
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as $ from 'jquery'
|
||||
import * as React from 'react';
|
||||
import * as $ from 'jquery';
|
||||
|
||||
// Require Editor JS files.
|
||||
// import 'froala-editor/js/froala_editor.pkgd.min.js';
|
||||
;[
|
||||
[
|
||||
require('froala-editor/js/froala_editor.min.js'),
|
||||
require('froala-editor/js/plugins/align.min'),
|
||||
require('froala-editor/js/plugins/colors.min'),
|
||||
|
@ -30,160 +30,160 @@ import * as $ from 'jquery'
|
|||
// require('froala-editor/js/plugins/emotion'),
|
||||
require('froala-editor/js/plugins/fullscreen.min'),
|
||||
require('froala-editor/js/plugins/video.min'),
|
||||
].forEach(init => init())
|
||||
].forEach(init => init());
|
||||
|
||||
// Require Editor CSS files.
|
||||
import 'froala-editor/css/froala_style.min.css'
|
||||
import 'froala-editor/css/froala_editor.pkgd.min.css'
|
||||
import 'froala-editor/css/froala_style.min.css';
|
||||
import 'froala-editor/css/froala_editor.pkgd.min.css';
|
||||
|
||||
export default class FroalaEditor extends React.Component<any, any> {
|
||||
listeningEvents: Array<any> = []
|
||||
$element: any = null
|
||||
$editor: any = null
|
||||
listeningEvents: Array<any> = [];
|
||||
$element: any = null;
|
||||
$editor: any = null;
|
||||
config: any = {
|
||||
immediateReactModelUpdate: false,
|
||||
reactIgnoreAttrs: null,
|
||||
}
|
||||
editorInitialized: boolean = false
|
||||
oldModel: any = null
|
||||
};
|
||||
editorInitialized: boolean = false;
|
||||
oldModel: any = null;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.textareaRef = this.textareaRef.bind(this)
|
||||
super(props);
|
||||
this.textareaRef = this.textareaRef.bind(this);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (JSON.stringify(this.oldModel) == JSON.stringify(this.props.model)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.setContent()
|
||||
this.setContent();
|
||||
}
|
||||
|
||||
textareaRef(ref: any) {
|
||||
ref ? this.createEditor(ref) : this.destroyEditor()
|
||||
ref ? this.createEditor(ref) : this.destroyEditor();
|
||||
}
|
||||
|
||||
createEditor(ref: any) {
|
||||
if (this.editorInitialized) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.config = this.props.config || this.config
|
||||
this.$element = $(ref)
|
||||
this.setContent(true)
|
||||
this.registerEvents()
|
||||
this.$editor = this.$element.froalaEditor(this.config).data('froala.editor').$el
|
||||
this.initListeners()
|
||||
this.editorInitialized = true
|
||||
this.config = this.props.config || this.config;
|
||||
this.$element = $(ref);
|
||||
this.setContent(true);
|
||||
this.registerEvents();
|
||||
this.$editor = this.$element.froalaEditor(this.config).data('froala.editor').$el;
|
||||
this.initListeners();
|
||||
this.editorInitialized = true;
|
||||
}
|
||||
|
||||
setContent(firstTime: boolean = false) {
|
||||
if (!this.editorInitialized && !firstTime) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.model || this.props.model == '') {
|
||||
this.oldModel = this.props.model
|
||||
this.oldModel = this.props.model;
|
||||
|
||||
this.setNormalTagContent(firstTime)
|
||||
this.setNormalTagContent(firstTime);
|
||||
}
|
||||
}
|
||||
|
||||
setNormalTagContent(firstTime: boolean) {
|
||||
let self = this
|
||||
let self = this;
|
||||
|
||||
function htmlSet() {
|
||||
self.$element.froalaEditor('html.set', self.props.model || '', true)
|
||||
self.$element.froalaEditor('html.set', self.props.model || '', true);
|
||||
//This will reset the undo stack everytime the model changes externally. Can we fix this?
|
||||
self.$element.froalaEditor('undo.reset')
|
||||
self.$element.froalaEditor('undo.saveStep')
|
||||
self.$element.froalaEditor('undo.reset');
|
||||
self.$element.froalaEditor('undo.saveStep');
|
||||
}
|
||||
|
||||
if (firstTime) {
|
||||
this.registerEvent(this.$element, 'froalaEditor.initialized', htmlSet)
|
||||
this.registerEvent(this.$element, 'froalaEditor.initialized', htmlSet);
|
||||
} else {
|
||||
htmlSet()
|
||||
htmlSet();
|
||||
}
|
||||
}
|
||||
|
||||
getEditor() {
|
||||
if (this.$element) {
|
||||
return this.$element.froalaEditor.bind(this.$element)
|
||||
return this.$element.froalaEditor.bind(this.$element);
|
||||
}
|
||||
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
updateModel() {
|
||||
if (!this.props.onModelChange) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
let modelContent = ''
|
||||
let modelContent = '';
|
||||
|
||||
let returnedHtml = this.$element.froalaEditor('html.get')
|
||||
let returnedHtml = this.$element.froalaEditor('html.get');
|
||||
if (typeof returnedHtml === 'string') {
|
||||
modelContent = returnedHtml
|
||||
modelContent = returnedHtml;
|
||||
}
|
||||
|
||||
this.oldModel = modelContent
|
||||
this.props.onModelChange(modelContent)
|
||||
this.oldModel = modelContent;
|
||||
this.props.onModelChange(modelContent);
|
||||
}
|
||||
|
||||
initListeners() {
|
||||
let self = this
|
||||
let self = this;
|
||||
|
||||
// bind contentChange and keyup event to froalaModel
|
||||
this.registerEvent(this.$element, 'froalaEditor.contentChanged', function() {
|
||||
self.updateModel()
|
||||
})
|
||||
self.updateModel();
|
||||
});
|
||||
if (this.config.immediateReactModelUpdate) {
|
||||
this.registerEvent(this.$editor, 'keyup', function() {
|
||||
self.updateModel()
|
||||
})
|
||||
self.updateModel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// register event on jquery editor element
|
||||
registerEvent(element: any, eventName: any, callback: any) {
|
||||
if (!element || !eventName || !callback) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.listeningEvents.push(eventName)
|
||||
element.on(eventName, callback)
|
||||
this.listeningEvents.push(eventName);
|
||||
element.on(eventName, callback);
|
||||
}
|
||||
|
||||
registerEvents() {
|
||||
let events = this.config.events
|
||||
let events = this.config.events;
|
||||
if (!events) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
for (let event in events) {
|
||||
if (events.hasOwnProperty(event)) {
|
||||
this.registerEvent(this.$element, event, events[event])
|
||||
this.registerEvent(this.$element, event, events[event]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroyEditor() {
|
||||
if (this.$element) {
|
||||
this.listeningEvents && this.$element.off(this.listeningEvents.join(' '))
|
||||
this.$editor.off('keyup')
|
||||
this.$element.froalaEditor('destroy')
|
||||
this.listeningEvents.length = 0
|
||||
this.$element = null
|
||||
this.editorInitialized = false
|
||||
this.listeningEvents && this.$element.off(this.listeningEvents.join(' '));
|
||||
this.$editor.off('keyup');
|
||||
this.$element.froalaEditor('destroy');
|
||||
this.listeningEvents.length = 0;
|
||||
this.$element = null;
|
||||
this.editorInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <textarea ref={this.textareaRef} />
|
||||
return <textarea ref={this.textareaRef} />;
|
||||
}
|
||||
}
|
||||
|
||||
;($ as any).FE.VIDEO_PROVIDERS = [
|
||||
($ as any).FE.VIDEO_PROVIDERS = [
|
||||
{
|
||||
test_regex: /^.+(bcebos.com)\/[^_&]+/,
|
||||
url_regex: '',
|
||||
|
@ -191,8 +191,8 @@ export default class FroalaEditor extends React.Component<any, any> {
|
|||
html:
|
||||
'<span class="fr-video fr-dvb fr-draggable" contenteditable="false" draggable="true"><video class="fr-draggable" controls="" data-msg="ok" data-status="0" src="{url}" style="width: 600px;"></video></span>',
|
||||
},
|
||||
]
|
||||
;($ as any).FE.LANGUAGE['zh_cn'] = {
|
||||
];
|
||||
($ as any).FE.LANGUAGE['zh_cn'] = {
|
||||
translation: {
|
||||
// Place holder
|
||||
'Type something': '\u8f93\u5165\u4e00\u4e9b\u5185\u5bb9',
|
||||
|
@ -419,4 +419,4 @@ export default class FroalaEditor extends React.Component<any, any> {
|
|||
'Quick Insert': '\u5feb\u63d2',
|
||||
},
|
||||
direction: 'ltr',
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,84 +5,84 @@
|
|||
* @date 2017-11-07
|
||||
*/
|
||||
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import * as React from 'react'
|
||||
import 'react-datetime/css/react-datetime.css'
|
||||
import Overlay from './Overlay'
|
||||
import PopOver from './PopOver'
|
||||
import Downshift, {ControllerStateAndHelpers} from 'downshift'
|
||||
import * as cx from 'classnames'
|
||||
import {closeIcon} from './icons'
|
||||
import * as matchSorter from 'match-sorter'
|
||||
import {noop, anyChanged} from '../utils/helper'
|
||||
import find = require('lodash/find')
|
||||
import isPlainObject = require('lodash/isPlainObject')
|
||||
import {highlight} from '../renderers/Form/Options'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import * as React from 'react';
|
||||
import 'react-datetime/css/react-datetime.css';
|
||||
import Overlay from './Overlay';
|
||||
import PopOver from './PopOver';
|
||||
import Downshift, {ControllerStateAndHelpers} from 'downshift';
|
||||
import * as cx from 'classnames';
|
||||
import {closeIcon} from './icons';
|
||||
import * as matchSorter from 'match-sorter';
|
||||
import {noop, anyChanged} from '../utils/helper';
|
||||
import find = require('lodash/find');
|
||||
import isPlainObject = require('lodash/isPlainObject');
|
||||
import {highlight} from '../renderers/Form/Options';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface Option {
|
||||
label?: string
|
||||
value?: any
|
||||
disabled?: boolean
|
||||
children?: Options
|
||||
visible?: boolean
|
||||
hidden?: boolean
|
||||
[propName: string]: any
|
||||
label?: string;
|
||||
value?: any;
|
||||
disabled?: boolean;
|
||||
children?: Options;
|
||||
visible?: boolean;
|
||||
hidden?: boolean;
|
||||
[propName: string]: any;
|
||||
}
|
||||
export interface Options extends Array<Option> {}
|
||||
|
||||
export interface OptionProps {
|
||||
multi?: boolean
|
||||
multiple?: boolean
|
||||
valueField?: string
|
||||
options: Options
|
||||
joinValues?: boolean
|
||||
extractValue?: boolean
|
||||
delimiter?: string
|
||||
clearable?: boolean
|
||||
placeholder?: string
|
||||
multi?: boolean;
|
||||
multiple?: boolean;
|
||||
valueField?: string;
|
||||
options: Options;
|
||||
joinValues?: boolean;
|
||||
extractValue?: boolean;
|
||||
delimiter?: string;
|
||||
clearable?: boolean;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export type OptionValue = string | number | null | undefined | Option
|
||||
export type OptionValue = string | number | null | undefined | Option;
|
||||
|
||||
export function value2array(value: OptionValue | Array<OptionValue>, props: Partial<OptionProps>): Array<Option> {
|
||||
if (props.multi || props.multiple) {
|
||||
if (typeof value === 'string') {
|
||||
value = value.split(props.delimiter || ',')
|
||||
value = value.split(props.delimiter || ',');
|
||||
}
|
||||
|
||||
if (!Array.isArray(value)) {
|
||||
if (value === null || value === undefined) {
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
|
||||
value = [value]
|
||||
value = [value];
|
||||
}
|
||||
|
||||
return value.map((value: any) => expandValue(value, props)).filter((item: any) => item) as Array<Option>
|
||||
return value.map((value: any) => expandValue(value, props)).filter((item: any) => item) as Array<Option>;
|
||||
} else if (Array.isArray(value)) {
|
||||
value = value[0]
|
||||
value = value[0];
|
||||
}
|
||||
|
||||
let expandedValue = expandValue(value as OptionValue, props)
|
||||
return expandedValue ? [expandedValue] : []
|
||||
let expandedValue = expandValue(value as OptionValue, props);
|
||||
return expandedValue ? [expandedValue] : [];
|
||||
}
|
||||
|
||||
export function expandValue(value: OptionValue, props: Partial<OptionProps>): Option | null {
|
||||
const valueType = typeof value
|
||||
const valueType = typeof value;
|
||||
|
||||
if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') {
|
||||
return value as Option
|
||||
return value as Option;
|
||||
}
|
||||
|
||||
let {options} = props
|
||||
let {options} = props;
|
||||
|
||||
if (!options) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
return find(options, item => String(item[props.valueField || 'value']) === String(value)) as Option
|
||||
return find(options, item => String(item[props.valueField || 'value']) === String(value)) as Option;
|
||||
}
|
||||
|
||||
export function normalizeOptions(options: string | {[propName: string]: string} | Array<string> | Options): Options {
|
||||
|
@ -90,72 +90,72 @@ export function normalizeOptions(options: string | {[propName: string]: string}
|
|||
return options.split(',').map(item => ({
|
||||
label: item,
|
||||
value: item,
|
||||
}))
|
||||
}));
|
||||
} else if (Array.isArray(options as Array<string>) && typeof (options as Array<string>)[0] === 'string') {
|
||||
return (options as Array<string>).map(item => ({
|
||||
label: item,
|
||||
value: item,
|
||||
}))
|
||||
}));
|
||||
} else if (Array.isArray(options as Options)) {
|
||||
return (options as Options).map(item => {
|
||||
let option = {
|
||||
...item,
|
||||
value: item && item.value,
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof option.children !== 'undefined') {
|
||||
option.children = normalizeOptions(option.children)
|
||||
option.children = normalizeOptions(option.children);
|
||||
}
|
||||
|
||||
return option
|
||||
})
|
||||
return option;
|
||||
});
|
||||
} else if (isPlainObject(options)) {
|
||||
return Object.keys(options).map(key => ({
|
||||
label: (options as {[propName: string]: string})[key] as string,
|
||||
value: key,
|
||||
}))
|
||||
}));
|
||||
}
|
||||
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
|
||||
interface SelectProps {
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
className: string
|
||||
creatable: boolean
|
||||
multiple: boolean
|
||||
valueField: string
|
||||
labelField: string
|
||||
searchable: boolean
|
||||
options: Array<Option>
|
||||
value: Option | Array<Option>
|
||||
loadOptions?: Function
|
||||
searchPromptText: string
|
||||
loading?: boolean
|
||||
loadingPlaceholder: string
|
||||
spinnerClassName?: string
|
||||
noResultsText: string
|
||||
clearable: boolean
|
||||
clearAllText: string
|
||||
clearValueText: string
|
||||
placeholder: string
|
||||
inline: boolean
|
||||
disabled: boolean
|
||||
popOverContainer?: any
|
||||
promptTextCreator: (label: string) => string
|
||||
onChange: (value: void | string | Option | Array<Option>) => void
|
||||
onNewOptionClick: (value: Option) => void
|
||||
onFocus?: Function
|
||||
onBlur?: Function
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
className: string;
|
||||
creatable: boolean;
|
||||
multiple: boolean;
|
||||
valueField: string;
|
||||
labelField: string;
|
||||
searchable: boolean;
|
||||
options: Array<Option>;
|
||||
value: Option | Array<Option>;
|
||||
loadOptions?: Function;
|
||||
searchPromptText: string;
|
||||
loading?: boolean;
|
||||
loadingPlaceholder: string;
|
||||
spinnerClassName?: string;
|
||||
noResultsText: string;
|
||||
clearable: boolean;
|
||||
clearAllText: string;
|
||||
clearValueText: string;
|
||||
placeholder: string;
|
||||
inline: boolean;
|
||||
disabled: boolean;
|
||||
popOverContainer?: any;
|
||||
promptTextCreator: (label: string) => string;
|
||||
onChange: (value: void | string | Option | Array<Option>) => void;
|
||||
onNewOptionClick: (value: Option) => void;
|
||||
onFocus?: Function;
|
||||
onBlur?: Function;
|
||||
}
|
||||
|
||||
interface SelectState {
|
||||
isOpen: boolean
|
||||
isFocused: boolean
|
||||
inputValue: string
|
||||
highlightedIndex: number
|
||||
selection: Array<Option>
|
||||
isOpen: boolean;
|
||||
isFocused: boolean;
|
||||
inputValue: string;
|
||||
highlightedIndex: number;
|
||||
selection: Array<Option>;
|
||||
}
|
||||
|
||||
export class Select extends React.Component<SelectProps, SelectState> {
|
||||
|
@ -175,26 +175,26 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
promptTextCreator: (label: string) => `新增:${label}`,
|
||||
onNewOptionClick: noop,
|
||||
inline: false,
|
||||
}
|
||||
};
|
||||
|
||||
input: HTMLInputElement
|
||||
target: HTMLElement
|
||||
input: HTMLInputElement;
|
||||
target: HTMLElement;
|
||||
constructor(props: SelectProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.open = this.open.bind(this)
|
||||
this.close = this.close.bind(this)
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.onBlur = this.onBlur.bind(this)
|
||||
this.onFocus = this.onFocus.bind(this)
|
||||
this.focus = this.focus.bind(this)
|
||||
this.inputRef = this.inputRef.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleInputChange = this.handleInputChange.bind(this)
|
||||
this.clearValue = this.clearValue.bind(this)
|
||||
this.handleStateChange = this.handleStateChange.bind(this)
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this)
|
||||
this.getTarget = this.getTarget.bind(this)
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.onBlur = this.onBlur.bind(this);
|
||||
this.onFocus = this.onFocus.bind(this);
|
||||
this.focus = this.focus.bind(this);
|
||||
this.inputRef = this.inputRef.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
this.clearValue = this.clearValue.bind(this);
|
||||
this.handleStateChange = this.handleStateChange.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
this.getTarget = this.getTarget.bind(this);
|
||||
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
|
@ -202,22 +202,22 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
inputValue: '',
|
||||
highlightedIndex: -1,
|
||||
selection: value2array(props.value, props),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {loadOptions} = this.props
|
||||
const {loadOptions} = this.props;
|
||||
|
||||
loadOptions && loadOptions('')
|
||||
loadOptions && loadOptions('');
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: SelectProps) {
|
||||
const props = this.props
|
||||
const props = this.props;
|
||||
|
||||
if (props.value !== nextProps.value || JSON.stringify(props.options) !== JSON.stringify(nextProps.options)) {
|
||||
this.setState({
|
||||
selection: value2array(nextProps.value, nextProps),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,20 +225,20 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
this.props.disabled ||
|
||||
this.setState({
|
||||
isOpen: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.props.disabled ||
|
||||
this.setState({
|
||||
isOpen: !this.state.isOpen,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
onFocus(e: any) {
|
||||
|
@ -248,95 +248,95 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
isFocused: true,
|
||||
},
|
||||
this.focus
|
||||
)
|
||||
);
|
||||
|
||||
this.props.onFocus && this.props.onFocus(e)
|
||||
this.props.onFocus && this.props.onFocus(e);
|
||||
}
|
||||
|
||||
onBlur(e: any) {
|
||||
this.setState({
|
||||
isFocused: false,
|
||||
inputValue: '',
|
||||
})
|
||||
});
|
||||
|
||||
this.props.onBlur && this.props.onBlur(e)
|
||||
this.props.onBlur && this.props.onBlur(e);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.input ? this.input.focus() : this.getTarget() && this.getTarget().focus()
|
||||
this.input ? this.input.focus() : this.getTarget() && this.getTarget().focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input ? this.input.blur() : this.getTarget() && this.getTarget().blur()
|
||||
this.input ? this.input.blur() : this.getTarget() && this.getTarget().blur();
|
||||
}
|
||||
|
||||
getTarget() {
|
||||
if (!this.target) {
|
||||
this.target = findDOMNode(this) as HTMLElement
|
||||
this.target = findDOMNode(this) as HTMLElement;
|
||||
}
|
||||
return this.target as HTMLElement
|
||||
return this.target as HTMLElement;
|
||||
}
|
||||
|
||||
inputRef(ref: HTMLInputElement) {
|
||||
this.input = ref
|
||||
this.input = ref;
|
||||
}
|
||||
|
||||
removeItem(index: number, e?: React.MouseEvent<HTMLElement>) {
|
||||
let value = this.props.value
|
||||
const onChange = this.props.onChange
|
||||
let value = this.props.value;
|
||||
const onChange = this.props.onChange;
|
||||
|
||||
e && e.stopPropagation()
|
||||
value = Array.isArray(value) ? value.concat() : [value]
|
||||
value.splice(index, 1)
|
||||
onChange(value)
|
||||
e && e.stopPropagation();
|
||||
value = Array.isArray(value) ? value.concat() : [value];
|
||||
value.splice(index, 1);
|
||||
onChange(value);
|
||||
}
|
||||
|
||||
handleInputChange(evt: React.ChangeEvent<HTMLInputElement>) {
|
||||
const {loadOptions} = this.props
|
||||
const {loadOptions} = this.props;
|
||||
|
||||
this.setState(
|
||||
{
|
||||
inputValue: evt.currentTarget.value,
|
||||
},
|
||||
() => loadOptions && loadOptions(this.state.inputValue)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
handleChange(selectItem: any) {
|
||||
const {onChange, multiple, onNewOptionClick} = this.props
|
||||
const {onChange, multiple, onNewOptionClick} = this.props;
|
||||
|
||||
let selection = this.state.selection
|
||||
let selection = this.state.selection;
|
||||
|
||||
if (selectItem.isNew) {
|
||||
delete selectItem.isNew
|
||||
onNewOptionClick(selectItem)
|
||||
delete selectItem.isNew;
|
||||
onNewOptionClick(selectItem);
|
||||
}
|
||||
|
||||
if (multiple) {
|
||||
selection = selection.concat()
|
||||
const idx = selection.indexOf(selectItem)
|
||||
selection = selection.concat();
|
||||
const idx = selection.indexOf(selectItem);
|
||||
if (~idx) {
|
||||
selection.splice(idx, 1)
|
||||
selection.splice(idx, 1);
|
||||
} else {
|
||||
selection.push(selectItem)
|
||||
selection.push(selectItem);
|
||||
}
|
||||
onChange(selection)
|
||||
onChange(selection);
|
||||
} else {
|
||||
onChange(selectItem)
|
||||
onChange(selectItem);
|
||||
}
|
||||
}
|
||||
|
||||
handleStateChange(changes: any) {
|
||||
let update: any = {}
|
||||
const loadOptions = this.props.loadOptions
|
||||
let doLoad = false
|
||||
let update: any = {};
|
||||
const loadOptions = this.props.loadOptions;
|
||||
let doLoad = false;
|
||||
|
||||
if (changes.isOpen !== void 0) {
|
||||
update.isOpen = changes.isOpen
|
||||
update.isOpen = changes.isOpen;
|
||||
}
|
||||
|
||||
if (changes.highlightedIndex !== void 0) {
|
||||
update.highlightedIndex = changes.highlightedIndex
|
||||
update.highlightedIndex = changes.highlightedIndex;
|
||||
}
|
||||
|
||||
switch (changes.type) {
|
||||
|
@ -347,39 +347,39 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
inputValue: '',
|
||||
isOpen: false,
|
||||
isFocused: false,
|
||||
}
|
||||
doLoad = true
|
||||
break
|
||||
};
|
||||
doLoad = true;
|
||||
break;
|
||||
case Downshift.stateChangeTypes.changeInput:
|
||||
update.highlightedIndex = 0
|
||||
break
|
||||
update.highlightedIndex = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Object.keys(update).length) {
|
||||
this.setState(update, doLoad && loadOptions ? () => loadOptions('') : undefined)
|
||||
this.setState(update, doLoad && loadOptions ? () => loadOptions('') : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ') {
|
||||
this.toggle()
|
||||
this.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
clearValue(e: React.MouseEvent<any>) {
|
||||
const onChange = this.props.onChange
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onChange('')
|
||||
const onChange = this.props.onChange;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onChange('');
|
||||
}
|
||||
|
||||
renderValue({inputValue, isOpen}: ControllerStateAndHelpers<any>) {
|
||||
const {multiple, placeholder, classPrefix: ns, labelField, searchable, creatable} = this.props
|
||||
const {multiple, placeholder, classPrefix: ns, labelField, searchable, creatable} = this.props;
|
||||
|
||||
const selection = this.state.selection
|
||||
const selection = this.state.selection;
|
||||
|
||||
if (searchable && !creatable && inputValue && (multiple ? !selection.length : true)) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!selection.length) {
|
||||
|
@ -387,7 +387,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
<div key="placeholder" className={`${ns}Select-placeholder`}>
|
||||
{placeholder}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return selection.map((item, index) =>
|
||||
|
@ -403,7 +403,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
{item.label}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderOuter({selectedItem, getItemProps, highlightedIndex, inputValue, isOpen}: ControllerStateAndHelpers<any>) {
|
||||
|
@ -418,17 +418,17 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
promptTextCreator,
|
||||
multiple,
|
||||
classnames: cx,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
let filtedOptions: Array<Option> =
|
||||
inputValue && isOpen && !loadOptions
|
||||
? matchSorter(options, inputValue, {
|
||||
keys: [labelField || 'label', valueField || 'value'],
|
||||
})
|
||||
: options.concat()
|
||||
: options.concat();
|
||||
|
||||
if (multiple) {
|
||||
filtedOptions = filtedOptions.filter((option: any) => !~selectedItem.indexOf(option))
|
||||
filtedOptions = filtedOptions.filter((option: any) => !~selectedItem.indexOf(option));
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -445,7 +445,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
[labelField]: inputValue,
|
||||
[valueField]: inputValue,
|
||||
isNew: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const menu = (
|
||||
|
@ -478,7 +478,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
<div className={cx('Select-option Select-option--placeholder')}>{noResultsText}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
if (popOverContainer) {
|
||||
return (
|
||||
|
@ -490,9 +490,9 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
{menu}
|
||||
</PopOver>
|
||||
</Overlay>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return <div className={cx('Select-menuOuter')}>{menu}</div>
|
||||
return <div className={cx('Select-menuOuter')}>{menu}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,10 +509,10 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
clearable,
|
||||
labelField,
|
||||
disabled,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
const selection = this.state.selection
|
||||
const inputValue = this.state.inputValue
|
||||
const selection = this.state.selection;
|
||||
const inputValue = this.state.inputValue;
|
||||
|
||||
return (
|
||||
<Downshift
|
||||
|
@ -526,7 +526,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
itemToString={item => (item ? item[labelField] : '')}
|
||||
>
|
||||
{(options: ControllerStateAndHelpers<any>) => {
|
||||
const {isOpen, getInputProps} = options
|
||||
const {isOpen, getInputProps} = options;
|
||||
return (
|
||||
<div
|
||||
tabIndex={searchable || disabled ? -1 : 0}
|
||||
|
@ -557,7 +557,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
onBlur: this.onBlur,
|
||||
onKeyDown: event => {
|
||||
if (event.key === 'Backspace' && !inputValue) {
|
||||
this.removeItem(value.length - 1)
|
||||
this.removeItem(value.length - 1);
|
||||
}
|
||||
},
|
||||
onChange: this.handleInputChange,
|
||||
|
@ -580,10 +580,10 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||
<span className={cx('Select-arrow')} />
|
||||
{isOpen ? this.renderOuter(options) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</Downshift>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,4 +591,4 @@ export default themeable(
|
|||
uncontrollable(Select, {
|
||||
value: 'onChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
* @date 2017-11-07
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {Renderer, RendererProps} from '../factory'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import * as React from 'react';
|
||||
import {Renderer, RendererProps} from '../factory';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
|
||||
interface SpinnerProps extends RendererProps {
|
||||
overlay: boolean
|
||||
spinnerClassName: string
|
||||
mode: string
|
||||
size: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
overlay: boolean;
|
||||
spinnerClassName: string;
|
||||
mode: string;
|
||||
size: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class Spinner extends React.Component<SpinnerProps, object> {
|
||||
|
@ -25,10 +25,10 @@ export class Spinner extends React.Component<SpinnerProps, object> {
|
|||
spinnerClassName: '',
|
||||
mode: '',
|
||||
size: '',
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {mode, overlay, spinnerClassName, classPrefix: ns, classnames: cx, size} = this.props
|
||||
const {mode, overlay, spinnerClassName, classPrefix: ns, classnames: cx, size} = this.props;
|
||||
|
||||
const spinner = (
|
||||
<div
|
||||
|
@ -37,14 +37,14 @@ export class Spinner extends React.Component<SpinnerProps, object> {
|
|||
[`Spinner--${size}`]: !!size,
|
||||
})}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
||||
if (overlay) {
|
||||
return <div className={cx(`Spinner-overlay`)}>{spinner}</div>
|
||||
return <div className={cx(`Spinner-overlay`)}>{spinner}</div>;
|
||||
}
|
||||
|
||||
return spinner
|
||||
return spinner;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Spinner)
|
||||
export default themeable(Spinner);
|
||||
|
|
|
@ -4,61 +4,61 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
|
||||
const sizeMap = {
|
||||
md: 'i-switch-md',
|
||||
lg: 'i-switch-lg',
|
||||
middle: 'i-switch-md',
|
||||
large: 'i-switch-lg',
|
||||
}
|
||||
};
|
||||
|
||||
const levelMap = {
|
||||
info: 'bg-info',
|
||||
primary: 'bg-primary',
|
||||
danger: 'bg-danger',
|
||||
}
|
||||
};
|
||||
|
||||
interface SwitchProps {
|
||||
id?: string
|
||||
size?: 'md' | 'lg' | 'middle' | 'large'
|
||||
level?: 'info' | 'primary' | 'danger'
|
||||
className?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
onChange?: (checked: boolean) => void
|
||||
value?: any
|
||||
inline?: boolean
|
||||
trueValue?: any
|
||||
falseValue?: any
|
||||
disabled?: boolean
|
||||
readOnly?: boolean
|
||||
checked?: boolean
|
||||
id?: string;
|
||||
size?: 'md' | 'lg' | 'middle' | 'large';
|
||||
level?: 'info' | 'primary' | 'danger';
|
||||
className?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
onChange?: (checked: boolean) => void;
|
||||
value?: any;
|
||||
inline?: boolean;
|
||||
trueValue?: any;
|
||||
falseValue?: any;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
checked?: boolean;
|
||||
}
|
||||
|
||||
export class Switch extends React.PureComponent<SwitchProps, any> {
|
||||
static defaultProps = {
|
||||
trueValue: true,
|
||||
falseValue: false,
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props: SwitchProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.hanldeCheck = this.hanldeCheck.bind(this)
|
||||
this.hanldeCheck = this.hanldeCheck.bind(this);
|
||||
}
|
||||
|
||||
hanldeCheck(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const {trueValue, falseValue, onChange} = this.props
|
||||
const {trueValue, falseValue, onChange} = this.props;
|
||||
|
||||
if (!onChange) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(e.currentTarget.checked ? trueValue : falseValue)
|
||||
onChange(e.currentTarget.checked ? trueValue : falseValue);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -77,12 +77,12 @@ export class Switch extends React.PureComponent<SwitchProps, any> {
|
|||
checked,
|
||||
classnames: cx,
|
||||
...rest
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
className =
|
||||
(className ? className : '') +
|
||||
(size && sizeMap[size] ? ` ${sizeMap[size]}` : '') +
|
||||
(level && levelMap[level] ? ` ${levelMap[level]}` : '')
|
||||
(level && levelMap[level] ? ` ${levelMap[level]}` : '');
|
||||
|
||||
return (
|
||||
<label className={cx(`Switch`, disabled ? 'is-disabled' : '', className)}>
|
||||
|
@ -102,8 +102,8 @@ export class Switch extends React.PureComponent<SwitchProps, any> {
|
|||
/>
|
||||
<i />
|
||||
</label>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Switch)
|
||||
export default themeable(Switch);
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
import * as Textarea from 'react-textarea-autosize'
|
||||
export default Textarea
|
||||
import * as Textarea from 'react-textarea-autosize';
|
||||
export default Textarea;
|
||||
|
|
|
@ -8,17 +8,17 @@
|
|||
* right 可以传入右侧节点, 当有右侧时自动采用 hbox 来左右布局。
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface TitleBarProps {
|
||||
className?: string
|
||||
title: React.ReactNode
|
||||
titleClassName?: string
|
||||
right?: boolean
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
className?: string;
|
||||
title: React.ReactNode;
|
||||
titleClassName?: string;
|
||||
right?: boolean;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
export class TitleBar extends React.PureComponent<TitleBarProps, any> {
|
||||
|
@ -27,14 +27,14 @@ export class TitleBar extends React.PureComponent<TitleBarProps, any> {
|
|||
title: '标题',
|
||||
titleClassName: 'm-n font-thin h3',
|
||||
right: false,
|
||||
}
|
||||
};
|
||||
|
||||
render(): JSX.Element {
|
||||
const {className, title, titleClassName, right} = this.props
|
||||
const {className, title, titleClassName, right} = this.props;
|
||||
|
||||
let left = title ? <div className={titleClassName}>{title}</div> : null
|
||||
let left = title ? <div className={titleClassName}>{title}</div> : null;
|
||||
|
||||
let body = left
|
||||
let body = left;
|
||||
|
||||
if (right) {
|
||||
body = (
|
||||
|
@ -42,13 +42,13 @@ export class TitleBar extends React.PureComponent<TitleBarProps, any> {
|
|||
<div className="col bg-light b-b wrapper">{left}</div>
|
||||
<div className="col v-middle padder-md text-right bg-light b-b wrapper-sm">{right}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
body = <div className="wrapper">{left}</div>
|
||||
body = <div className="wrapper">{left}</div>;
|
||||
}
|
||||
|
||||
return <div className={className}>{body}</div>
|
||||
return <div className={className}>{body}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(TitleBar)
|
||||
export default themeable(TitleBar);
|
||||
|
|
|
@ -4,55 +4,55 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import Transition, {ENTERED, ENTERING, EXITING, EXITED} from 'react-transition-group/Transition'
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import Html from './Html'
|
||||
import {uuid, autobind} from '../utils/helper'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import Transition, {ENTERED, ENTERING, EXITING, EXITED} from 'react-transition-group/Transition';
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import Html from './Html';
|
||||
import {uuid, autobind} from '../utils/helper';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
const fadeStyles: {
|
||||
[propName: string]: string
|
||||
[propName: string]: string;
|
||||
} = {
|
||||
[ENTERING]: 'in',
|
||||
[ENTERED]: '',
|
||||
[EXITING]: 'out',
|
||||
[EXITED]: 'hidden',
|
||||
}
|
||||
};
|
||||
|
||||
let toastRef: any = null
|
||||
let toastRef: any = null;
|
||||
let config: {
|
||||
closeButton?: boolean
|
||||
timeOut?: number
|
||||
extendedTimeOut?: number
|
||||
} = {}
|
||||
closeButton?: boolean;
|
||||
timeOut?: number;
|
||||
extendedTimeOut?: number;
|
||||
} = {};
|
||||
|
||||
const show = (content: string, title: string = '', conf: any = {}, method: string) => {
|
||||
if (!toastRef || !toastRef[method]) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
toastRef[method](content, title || '', {...config, ...conf})
|
||||
}
|
||||
toastRef[method](content, title || '', {...config, ...conf});
|
||||
};
|
||||
|
||||
interface ToastComponentProps {
|
||||
position: 'top-right' | 'top-center' | 'top-left' | 'bottom-center' | 'bottom-left' | 'bottom-right'
|
||||
closeButton: boolean
|
||||
timeOut: number
|
||||
extendedTimeOut: number
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
className?: string
|
||||
position: 'top-right' | 'top-center' | 'top-left' | 'bottom-center' | 'bottom-left' | 'bottom-right';
|
||||
closeButton: boolean;
|
||||
timeOut: number;
|
||||
extendedTimeOut: number;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface Item {
|
||||
title?: string
|
||||
body: string
|
||||
level: 'info' | 'success' | 'error' | 'warning'
|
||||
id: string
|
||||
title?: string;
|
||||
body: string;
|
||||
level: 'info' | 'success' | 'error' | 'warning';
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface ToastComponentState {
|
||||
items: Array<Item>
|
||||
items: Array<Item>;
|
||||
}
|
||||
|
||||
export class ToastComponent extends React.PureComponent<ToastComponentProps, ToastComponentState> {
|
||||
|
@ -61,83 +61,83 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
|
|||
closeButton: false,
|
||||
timeOut: 5000,
|
||||
extendedTimeOut: 3000,
|
||||
}
|
||||
};
|
||||
|
||||
// 当前ToastComponent是否真正render了
|
||||
hasRendered = false
|
||||
hasRendered = false;
|
||||
state: ToastComponentState = {
|
||||
items: [],
|
||||
}
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
const {closeButton, timeOut, extendedTimeOut} = this.props
|
||||
const {closeButton, timeOut, extendedTimeOut} = this.props;
|
||||
config = {
|
||||
closeButton,
|
||||
timeOut,
|
||||
extendedTimeOut,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.hasRendered = true
|
||||
toastRef = this
|
||||
this.hasRendered = true;
|
||||
toastRef = this;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.hasRendered) {
|
||||
toastRef = null
|
||||
toastRef = null;
|
||||
}
|
||||
}
|
||||
|
||||
notifiy(level: string, content: string, title?: string, config?: any) {
|
||||
const items = this.state.items.concat()
|
||||
const items = this.state.items.concat();
|
||||
items.push({
|
||||
title: title,
|
||||
body: content,
|
||||
level,
|
||||
...config,
|
||||
id: uuid(),
|
||||
})
|
||||
});
|
||||
this.setState({
|
||||
items,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
success(content: string, title?: string, config?: any) {
|
||||
this.notifiy('success', content, title, config)
|
||||
this.notifiy('success', content, title, config);
|
||||
}
|
||||
|
||||
@autobind
|
||||
error(content: string, title?: string, config?: any) {
|
||||
this.notifiy('error', content, title, config)
|
||||
this.notifiy('error', content, title, config);
|
||||
}
|
||||
|
||||
@autobind
|
||||
info(content: string, title?: string, config?: any) {
|
||||
this.notifiy('info', content, title, config)
|
||||
this.notifiy('info', content, title, config);
|
||||
}
|
||||
|
||||
@autobind
|
||||
warning(content: string, title?: string, config?: any) {
|
||||
this.notifiy('warning', content, title, config)
|
||||
this.notifiy('warning', content, title, config);
|
||||
}
|
||||
|
||||
handleDismissed(index: number) {
|
||||
const items = this.state.items.concat()
|
||||
items.splice(index, 1)
|
||||
const items = this.state.items.concat();
|
||||
items.splice(index, 1);
|
||||
this.setState({
|
||||
items: items,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (toastRef && !this.hasRendered) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
const {classPrefix: ns, className, timeOut, position} = this.props
|
||||
const items = this.state.items
|
||||
const {classPrefix: ns, className, timeOut, position} = this.props;
|
||||
const items = this.state.items;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -158,25 +158,25 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
|
|||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(ToastComponent as React.ComponentType<ToastComponentProps>)
|
||||
export default themeable(ToastComponent as React.ComponentType<ToastComponentProps>);
|
||||
|
||||
interface ToastMessageProps {
|
||||
title?: string
|
||||
body: string
|
||||
level: 'info' | 'success' | 'error' | 'warning'
|
||||
timeOut: number
|
||||
position: 'top-right' | 'top-center' | 'top-left' | 'bottom-center' | 'bottom-left' | 'bottom-right'
|
||||
onDismiss?: () => void
|
||||
classPrefix: string
|
||||
allowHtml: boolean
|
||||
title?: string;
|
||||
body: string;
|
||||
level: 'info' | 'success' | 'error' | 'warning';
|
||||
timeOut: number;
|
||||
position: 'top-right' | 'top-center' | 'top-left' | 'bottom-center' | 'bottom-left' | 'bottom-right';
|
||||
onDismiss?: () => void;
|
||||
classPrefix: string;
|
||||
allowHtml: boolean;
|
||||
}
|
||||
|
||||
interface ToastMessageState {
|
||||
visible: boolean
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export class ToastMessage extends React.Component<ToastMessageProps> {
|
||||
|
@ -186,56 +186,56 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
|
|||
position: 'top-right',
|
||||
allowHtml: true,
|
||||
level: 'info',
|
||||
}
|
||||
};
|
||||
|
||||
state = {
|
||||
visible: false,
|
||||
}
|
||||
};
|
||||
|
||||
content: React.RefObject<HTMLDivElement>
|
||||
timer: NodeJS.Timeout
|
||||
content: React.RefObject<HTMLDivElement>;
|
||||
timer: NodeJS.Timeout;
|
||||
constructor(props: ToastMessageProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.content = React.createRef()
|
||||
this.handleMouseEnter = this.handleMouseEnter.bind(this)
|
||||
this.handleMouseLeave = this.handleMouseLeave.bind(this)
|
||||
this.handleEntered = this.handleEntered.bind(this)
|
||||
this.close = this.close.bind(this)
|
||||
this.content = React.createRef();
|
||||
this.handleMouseEnter = this.handleMouseEnter.bind(this);
|
||||
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
||||
this.handleEntered = this.handleEntered.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timer)
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
visible: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseEnter() {
|
||||
clearTimeout(this.timer)
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
handleMouseLeave() {
|
||||
this.handleEntered()
|
||||
this.handleEntered();
|
||||
}
|
||||
|
||||
handleEntered() {
|
||||
const timeOut = this.props.timeOut
|
||||
this.timer = setTimeout(this.close, timeOut)
|
||||
const timeOut = this.props.timeOut;
|
||||
this.timer = setTimeout(this.close, timeOut);
|
||||
}
|
||||
|
||||
close() {
|
||||
clearTimeout(this.timer)
|
||||
clearTimeout(this.timer);
|
||||
this.setState({
|
||||
visible: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {onDismiss, classPrefix: ns, position, title, body, allowHtml, level} = this.props
|
||||
const {onDismiss, classPrefix: ns, position, title, body, allowHtml, level} = this.props;
|
||||
|
||||
return (
|
||||
<Transition
|
||||
|
@ -251,7 +251,7 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
|
|||
// force reflow
|
||||
// 由于从 mount 进来到加上 in 这个 class 估计是时间太短,上次的样式还没应用进去,所以这里强制reflow一把。
|
||||
// 否则看不到动画。
|
||||
this.content.current && this.content.current.offsetWidth
|
||||
this.content.current && this.content.current.offsetWidth;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -265,10 +265,10 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
|
|||
{title ? <div className={`${ns}Toast-title`}>{title}</div> : null}
|
||||
<div className={`${ns}Toast-body`}>{allowHtml ? <Html html={body} /> : body}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</Transition>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,4 +278,4 @@ export const toast = {
|
|||
error: (content: string, title?: string, conf?: any) => show(content, title, conf, 'error'),
|
||||
info: (content: string, title?: string, conf?: any) => show(content, title, conf, 'info'),
|
||||
warning: (content: string, title?: string, conf?: any) => show(content, title, conf, 'warning'),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,27 +4,27 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as cx from 'classnames'
|
||||
import {classPrefix, classnames} from '../themes/default'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import * as React from 'react';
|
||||
import * as cx from 'classnames';
|
||||
import {classPrefix, classnames} from '../themes/default';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
interface TooltipProps extends React.HTMLProps<HTMLDivElement> {
|
||||
title?: string
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
theme?: string
|
||||
className?: string
|
||||
style?: any
|
||||
arrowProps?: any
|
||||
placement?: string
|
||||
[propName: string]: any
|
||||
title?: string;
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
theme?: string;
|
||||
className?: string;
|
||||
style?: any;
|
||||
arrowProps?: any;
|
||||
placement?: string;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export class Tooltip extends React.Component<TooltipProps> {
|
||||
static defaultProps = {
|
||||
className: '',
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -41,7 +41,7 @@ export class Tooltip extends React.Component<TooltipProps> {
|
|||
positionTop,
|
||||
classnames: cx,
|
||||
...rest
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -54,8 +54,8 @@ export class Tooltip extends React.Component<TooltipProps> {
|
|||
{title ? <div className={cx('Tooltip-title')}>{title}</div> : null}
|
||||
<div className={cx('Tooltip-body')}>{children}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Tooltip)
|
||||
export default themeable(Tooltip);
|
||||
|
|
|
@ -4,36 +4,36 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import React = require('react')
|
||||
import {Overlay} from 'react-overlays'
|
||||
import Html from './Html'
|
||||
import uncontrollable = require('uncontrollable')
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import Tooltip from './Tooltip'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import React = require('react');
|
||||
import {Overlay} from 'react-overlays';
|
||||
import Html from './Html';
|
||||
import uncontrollable = require('uncontrollable');
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import Tooltip from './Tooltip';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
|
||||
export interface TooltipObject {
|
||||
title?: string
|
||||
content?: string
|
||||
title?: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
export type Trigger = 'hover' | 'click' | 'focus'
|
||||
export type Trigger = 'hover' | 'click' | 'focus';
|
||||
|
||||
export interface TooltipWrapperProps {
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
placement: 'top' | 'right' | 'bottom' | 'left'
|
||||
tooltip?: string | TooltipObject
|
||||
container?: React.ReactNode
|
||||
trigger: Trigger | Array<Trigger>
|
||||
rootClose: boolean
|
||||
overlay?: any
|
||||
delay: number
|
||||
theme?: string
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
placement: 'top' | 'right' | 'bottom' | 'left';
|
||||
tooltip?: string | TooltipObject;
|
||||
container?: React.ReactNode;
|
||||
trigger: Trigger | Array<Trigger>;
|
||||
rootClose: boolean;
|
||||
overlay?: any;
|
||||
delay: number;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
interface TooltipWrapperState {
|
||||
show?: boolean
|
||||
show?: boolean;
|
||||
}
|
||||
|
||||
export class TooltipWrapper extends React.Component<TooltipWrapperProps, TooltipWrapperState> {
|
||||
|
@ -42,57 +42,57 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
|
|||
trigger: ['hover', 'focus'],
|
||||
rootClose: false,
|
||||
delay: 200,
|
||||
}
|
||||
};
|
||||
|
||||
target: HTMLElement
|
||||
timer: NodeJS.Timeout
|
||||
target: HTMLElement;
|
||||
timer: NodeJS.Timeout;
|
||||
constructor(props: TooltipWrapperProps) {
|
||||
super(props)
|
||||
super(props);
|
||||
|
||||
this.targetRef = this.targetRef.bind(this)
|
||||
this.getTarget = this.getTarget.bind(this)
|
||||
this.show = this.show.bind(this)
|
||||
this.hide = this.hide.bind(this)
|
||||
this.handleShow = this.handleShow.bind(this)
|
||||
this.handleHide = this.handleHide.bind(this)
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
this.handleFocus = this.handleFocus.bind(this)
|
||||
this.handleBlur = this.handleBlur.bind(this)
|
||||
this.handleMouseOver = this.handleMouseOver.bind(this)
|
||||
this.handleMouseOut = this.handleMouseOut.bind(this)
|
||||
this.targetRef = this.targetRef.bind(this);
|
||||
this.getTarget = this.getTarget.bind(this);
|
||||
this.show = this.show.bind(this);
|
||||
this.hide = this.hide.bind(this);
|
||||
this.handleShow = this.handleShow.bind(this);
|
||||
this.handleHide = this.handleHide.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.handleMouseOver = this.handleMouseOver.bind(this);
|
||||
this.handleMouseOut = this.handleMouseOut.bind(this);
|
||||
|
||||
this.state = {
|
||||
show: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timer)
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
getTarget() {
|
||||
return this.target ? findDOMNode(this.target) : null
|
||||
return this.target ? findDOMNode(this.target) : null;
|
||||
}
|
||||
|
||||
targetRef(ref: HTMLElement) {
|
||||
this.target = ref
|
||||
this.target = ref;
|
||||
}
|
||||
|
||||
show() {
|
||||
this.setState({
|
||||
show: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.setState({
|
||||
show: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getChildProps() {
|
||||
const child = React.Children.only(this.props.children)
|
||||
return child && (child as any).props
|
||||
const child = React.Children.only(this.props.children);
|
||||
return child && (child as any).props;
|
||||
}
|
||||
|
||||
handleShow() {
|
||||
|
@ -102,79 +102,79 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
|
|||
// } = this.props;
|
||||
|
||||
// this.timer = setTimeout(this.show, delay);
|
||||
this.show()
|
||||
this.show();
|
||||
}
|
||||
|
||||
handleHide() {
|
||||
clearTimeout(this.timer)
|
||||
const {delay} = this.props
|
||||
clearTimeout(this.timer);
|
||||
const {delay} = this.props;
|
||||
|
||||
this.timer = setTimeout(this.hide, delay)
|
||||
this.timer = setTimeout(this.hide, delay);
|
||||
}
|
||||
|
||||
handleFocus(e: any) {
|
||||
const {onFocus} = this.getChildProps()
|
||||
this.handleShow()
|
||||
onFocus && onFocus(e)
|
||||
const {onFocus} = this.getChildProps();
|
||||
this.handleShow();
|
||||
onFocus && onFocus(e);
|
||||
}
|
||||
|
||||
handleBlur(e: any) {
|
||||
const {onBlur} = this.getChildProps()
|
||||
this.handleHide()
|
||||
onBlur && onBlur(e)
|
||||
const {onBlur} = this.getChildProps();
|
||||
this.handleHide();
|
||||
onBlur && onBlur(e);
|
||||
}
|
||||
|
||||
handleMouseOver(e: any) {
|
||||
this.handleMouseOverOut(this.handleShow, e, 'fromElement')
|
||||
this.handleMouseOverOut(this.handleShow, e, 'fromElement');
|
||||
}
|
||||
|
||||
handleMouseOut(e: any) {
|
||||
this.handleMouseOverOut(this.handleHide, e, 'toElement')
|
||||
this.handleMouseOverOut(this.handleHide, e, 'toElement');
|
||||
}
|
||||
|
||||
handleMouseOverOut(handler: Function, e: React.MouseEvent<HTMLElement>, relatedNative: string) {
|
||||
const target = e.currentTarget
|
||||
const related: any = e.relatedTarget || (e as any).nativeEvent[relatedNative]
|
||||
const target = e.currentTarget;
|
||||
const related: any = e.relatedTarget || (e as any).nativeEvent[relatedNative];
|
||||
|
||||
if ((!related || related !== target) && !target.contains(related)) {
|
||||
handler(e)
|
||||
handler(e);
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e: any) {
|
||||
const {onClick} = this.getChildProps()
|
||||
this.state.show ? this.hide() : this.show()
|
||||
onClick && onClick(e)
|
||||
const {onClick} = this.getChildProps();
|
||||
this.state.show ? this.hide() : this.show();
|
||||
onClick && onClick(e);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {tooltip, children, placement, container, trigger, rootClose} = this.props
|
||||
const {tooltip, children, placement, container, trigger, rootClose} = this.props;
|
||||
|
||||
const child = React.Children.only(children)
|
||||
const child = React.Children.only(children);
|
||||
|
||||
if (!tooltip) {
|
||||
return child
|
||||
return child;
|
||||
}
|
||||
|
||||
const childProps: any = {
|
||||
ref: this.targetRef,
|
||||
key: 'target',
|
||||
}
|
||||
};
|
||||
|
||||
const triggers = Array.isArray(trigger) ? trigger.concat() : [trigger]
|
||||
const triggers = Array.isArray(trigger) ? trigger.concat() : [trigger];
|
||||
|
||||
if (~triggers.indexOf('click')) {
|
||||
childProps.onClick = this.handleClick
|
||||
childProps.onClick = this.handleClick;
|
||||
}
|
||||
|
||||
if (~triggers.indexOf('focus')) {
|
||||
childProps.onFocus = this.handleShow
|
||||
childProps.onBlur = this.handleHide
|
||||
childProps.onFocus = this.handleShow;
|
||||
childProps.onBlur = this.handleHide;
|
||||
}
|
||||
|
||||
if (~triggers.indexOf('hover')) {
|
||||
childProps.onMouseOver = this.handleMouseOver
|
||||
childProps.onMouseOut = this.handleMouseOut
|
||||
childProps.onMouseOver = this.handleMouseOver;
|
||||
childProps.onMouseOut = this.handleMouseOut;
|
||||
}
|
||||
|
||||
return [
|
||||
|
@ -193,7 +193,7 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
|
|||
<Html html={typeof tooltip === 'string' ? tooltip : tooltip.content} />
|
||||
</Tooltip>
|
||||
</Overlay>,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,4 +201,4 @@ export default themeable(
|
|||
uncontrollable(TooltipWrapper, {
|
||||
show: 'onVisibleChange',
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -4,58 +4,58 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import {eachTree, isVisible} from '../utils/helper'
|
||||
import {Option, Options, value2array} from './Checkboxes'
|
||||
import {ClassNamesFn, themeable} from '../theme'
|
||||
import {highlight} from '../renderers/Form/Options'
|
||||
import * as React from 'react';
|
||||
import {eachTree, isVisible} from '../utils/helper';
|
||||
import {Option, Options, value2array} from './Checkboxes';
|
||||
import {ClassNamesFn, themeable} from '../theme';
|
||||
import {highlight} from '../renderers/Form/Options';
|
||||
|
||||
interface TreeSelectorProps {
|
||||
classPrefix: string
|
||||
classnames: ClassNamesFn
|
||||
classPrefix: string;
|
||||
classnames: ClassNamesFn;
|
||||
|
||||
highlightTxt: string
|
||||
highlightTxt: string;
|
||||
|
||||
showIcon?: boolean
|
||||
showIcon?: boolean;
|
||||
// 是否默认都展开
|
||||
initiallyOpen?: boolean
|
||||
initiallyOpen?: boolean;
|
||||
// 默认展开的级数,从1开始,只有initiallyOpen不是true时生效
|
||||
unfoldedLevel?: number
|
||||
unfoldedLevel?: number;
|
||||
// 单选时,是否展示radio
|
||||
showRadio?: boolean
|
||||
multiple?: boolean
|
||||
showRadio?: boolean;
|
||||
multiple?: boolean;
|
||||
// 是否都不可用
|
||||
disabled?: boolean
|
||||
disabled?: boolean;
|
||||
// 多选时,选中父节点时,是否将其所有子节点也融合到取值中,默认是不融合
|
||||
withChildren?: boolean
|
||||
withChildren?: boolean;
|
||||
// 多选时,选中父节点时,是否只将起子节点加入到值中。
|
||||
onlyChildren?: boolean
|
||||
onlyChildren?: boolean;
|
||||
// 名称、取值等字段名映射
|
||||
nameField?: string
|
||||
valueField?: string
|
||||
iconField?: string
|
||||
unfoldedField?: string
|
||||
foldedField?: string
|
||||
disabledField?: string
|
||||
className?: string
|
||||
itemClassName?: string
|
||||
joinValues?: boolean
|
||||
extractValue?: boolean
|
||||
delimiter?: string
|
||||
data: Options
|
||||
value: any
|
||||
onChange: Function
|
||||
placeholder?: string
|
||||
hideRoot?: boolean
|
||||
rootLabel?: string
|
||||
rootValue?: any
|
||||
cascade?: boolean
|
||||
selfDisabledAffectChildren?: boolean
|
||||
nameField?: string;
|
||||
valueField?: string;
|
||||
iconField?: string;
|
||||
unfoldedField?: string;
|
||||
foldedField?: string;
|
||||
disabledField?: string;
|
||||
className?: string;
|
||||
itemClassName?: string;
|
||||
joinValues?: boolean;
|
||||
extractValue?: boolean;
|
||||
delimiter?: string;
|
||||
data: Options;
|
||||
value: any;
|
||||
onChange: Function;
|
||||
placeholder?: string;
|
||||
hideRoot?: boolean;
|
||||
rootLabel?: string;
|
||||
rootValue?: any;
|
||||
cascade?: boolean;
|
||||
selfDisabledAffectChildren?: boolean;
|
||||
}
|
||||
|
||||
interface TreeSelectorState {
|
||||
value: Array<any>
|
||||
unfolded: {[propName: string]: string}
|
||||
value: Array<any>;
|
||||
unfolded: {[propName: string]: string};
|
||||
}
|
||||
|
||||
export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelectorState> {
|
||||
|
@ -82,16 +82,16 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
rootValue: 0,
|
||||
cascade: false,
|
||||
selfDisabledAffectChildren: true,
|
||||
}
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.renderList = this.renderList.bind(this)
|
||||
this.handleSelect = this.handleSelect.bind(this)
|
||||
this.clearSelect = this.clearSelect.bind(this)
|
||||
this.handleCheck = this.handleCheck.bind(this)
|
||||
this.toggleUnfolded = this.toggleUnfolded.bind(this)
|
||||
this.renderList = this.renderList.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.clearSelect = this.clearSelect.bind(this);
|
||||
this.handleCheck = this.handleCheck.bind(this);
|
||||
this.toggleUnfolded = this.toggleUnfolded.bind(this);
|
||||
|
||||
const props = this.props
|
||||
const props = this.props;
|
||||
|
||||
this.setState({
|
||||
value: value2array(props.value, {
|
||||
|
@ -103,11 +103,11 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
options: props.data,
|
||||
}),
|
||||
unfolded: this.syncUnFolded(props),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: TreeSelectorProps) {
|
||||
const toUpdate: any = {}
|
||||
const toUpdate: any = {};
|
||||
|
||||
if (this.props.value !== nextProps.value || this.props.data !== nextProps.data) {
|
||||
toUpdate.value = value2array(nextProps.value, {
|
||||
|
@ -117,40 +117,40 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
delimiter: nextProps.delimiter,
|
||||
valueField: nextProps.valueField,
|
||||
options: nextProps.data,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.data !== nextProps.data) {
|
||||
toUpdate.unfolded = this.syncUnFolded(nextProps)
|
||||
toUpdate.unfolded = this.syncUnFolded(nextProps);
|
||||
}
|
||||
|
||||
this.setState(toUpdate)
|
||||
this.setState(toUpdate);
|
||||
}
|
||||
|
||||
syncUnFolded(props: TreeSelectorProps) {
|
||||
// 初始化树节点的展开状态
|
||||
let unfolded: {[propName: string]: string} = {}
|
||||
const {foldedField, unfoldedField} = this.props
|
||||
let unfolded: {[propName: string]: string} = {};
|
||||
const {foldedField, unfoldedField} = this.props;
|
||||
|
||||
eachTree(props.data, (node: Option, index, level) => {
|
||||
if (node.children && node.children.length) {
|
||||
let ret: any = true
|
||||
let ret: any = true;
|
||||
|
||||
if (unfoldedField && typeof node[unfoldedField] !== 'undefined') {
|
||||
ret = !!node[unfoldedField]
|
||||
ret = !!node[unfoldedField];
|
||||
} else if (foldedField && typeof node[foldedField] !== 'undefined') {
|
||||
ret = !node[foldedField]
|
||||
ret = !node[foldedField];
|
||||
} else {
|
||||
ret = !!props.initiallyOpen
|
||||
ret = !!props.initiallyOpen;
|
||||
if (!ret && level <= (props.unfoldedLevel as number)) {
|
||||
ret = true
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
unfolded[node[props.valueField as string]] = ret
|
||||
unfolded[node[props.valueField as string]] = ret;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return unfolded
|
||||
return unfolded;
|
||||
}
|
||||
|
||||
toggleUnfolded(node: any) {
|
||||
|
@ -159,7 +159,7 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
...this.state.unfolded,
|
||||
[node[this.props.valueField as string]]: !this.state.unfolded[node[this.props.valueField as string]],
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
clearSelect() {
|
||||
|
@ -168,11 +168,11 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
value: [],
|
||||
},
|
||||
() => {
|
||||
const {joinValues, rootValue, onChange} = this.props
|
||||
const {joinValues, rootValue, onChange} = this.props;
|
||||
|
||||
onChange(joinValues ? rootValue : [])
|
||||
onChange(joinValues ? rootValue : []);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
handleSelect(node: any, value?: any) {
|
||||
|
@ -181,73 +181,73 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
value: [node],
|
||||
},
|
||||
() => {
|
||||
const {joinValues, valueField, onChange} = this.props
|
||||
const {joinValues, valueField, onChange} = this.props;
|
||||
|
||||
onChange(joinValues ? node[valueField as string] : node)
|
||||
onChange(joinValues ? node[valueField as string] : node);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
handleCheck(item: any, checked: boolean) {
|
||||
const props = this.props
|
||||
const value = this.state.value.concat()
|
||||
const idx = value.indexOf(item)
|
||||
const onlyChildren = this.props.onlyChildren
|
||||
const props = this.props;
|
||||
const value = this.state.value.concat();
|
||||
const idx = value.indexOf(item);
|
||||
const onlyChildren = this.props.onlyChildren;
|
||||
|
||||
if (checked) {
|
||||
~idx || value.push(item)
|
||||
~idx || value.push(item);
|
||||
if (!props.cascade) {
|
||||
const children = item.children ? item.children.concat([]) : []
|
||||
const children = item.children ? item.children.concat([]) : [];
|
||||
|
||||
if (onlyChildren) {
|
||||
// 父级选中的时候,子节点也都选中,但是自己不选中
|
||||
!~idx && children.length && value.shift()
|
||||
!~idx && children.length && value.shift();
|
||||
|
||||
while (children.length) {
|
||||
let child = children.shift()
|
||||
let index = value.indexOf(child)
|
||||
let child = children.shift();
|
||||
let index = value.indexOf(child);
|
||||
|
||||
if (child.children) {
|
||||
children.push.apply(children, child.children)
|
||||
children.push.apply(children, child.children);
|
||||
} else {
|
||||
~index || value.push(child)
|
||||
~index || value.push(child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 只要父节点选择了,子节点就不需要了,全部去掉勾选. withChildren时相反
|
||||
while (children.length) {
|
||||
let child = children.shift()
|
||||
let index = value.indexOf(child)
|
||||
let child = children.shift();
|
||||
let index = value.indexOf(child);
|
||||
|
||||
if (~index) {
|
||||
value.splice(index, 1)
|
||||
value.splice(index, 1);
|
||||
}
|
||||
|
||||
if (props.withChildren) {
|
||||
value.push(child)
|
||||
value.push(child);
|
||||
}
|
||||
|
||||
if (child.children && child.children.length) {
|
||||
children.push.apply(children, child.children)
|
||||
children.push.apply(children, child.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!checked) {
|
||||
~idx && value.splice(idx, 1)
|
||||
~idx && value.splice(idx, 1);
|
||||
|
||||
if (!props.cascade && (props.withChildren || onlyChildren)) {
|
||||
const children = item.children ? item.children.concat([]) : []
|
||||
const children = item.children ? item.children.concat([]) : [];
|
||||
while (children.length) {
|
||||
let child = children.shift()
|
||||
let index = value.indexOf(child)
|
||||
let child = children.shift();
|
||||
let index = value.indexOf(child);
|
||||
|
||||
if (~index) {
|
||||
value.splice(index, 1)
|
||||
value.splice(index, 1);
|
||||
}
|
||||
|
||||
if (child.children && child.children.length) {
|
||||
children.push.apply(children, child.children)
|
||||
children.push.apply(children, child.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
value,
|
||||
},
|
||||
() => {
|
||||
const {joinValues, extractValue, valueField, delimiter, onChange} = this.props
|
||||
const {joinValues, extractValue, valueField, delimiter, onChange} = this.props;
|
||||
|
||||
onChange(
|
||||
joinValues
|
||||
|
@ -266,9 +266,9 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
: extractValue
|
||||
? value.map(item => item[valueField as string])
|
||||
: value
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderList(
|
||||
|
@ -292,20 +292,20 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
classnames: cx,
|
||||
highlightTxt,
|
||||
data,
|
||||
} = this.props
|
||||
} = this.props;
|
||||
|
||||
let childrenChecked = 0
|
||||
let childrenChecked = 0;
|
||||
let ret = list.map((item, key) => {
|
||||
if (!isVisible(item as any, data)) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
const checked = !!~value.indexOf(item)
|
||||
const selfDisabled = item[disabledField]
|
||||
let selfChecked = !!uncheckable || checked
|
||||
const checked = !!~value.indexOf(item);
|
||||
const selfDisabled = item[disabledField];
|
||||
let selfChecked = !!uncheckable || checked;
|
||||
|
||||
let childrenItems = null
|
||||
let tmpChildrenChecked = false
|
||||
let childrenItems = null;
|
||||
let tmpChildrenChecked = false;
|
||||
if (item.children && item.children.length) {
|
||||
childrenItems = this.renderList(
|
||||
item.children,
|
||||
|
@ -313,19 +313,19 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
cascade
|
||||
? false
|
||||
: uncheckable || (selfDisabledAffectChildren ? selfDisabled : false) || (multiple && checked)
|
||||
)
|
||||
tmpChildrenChecked = !!childrenItems.childrenChecked
|
||||
);
|
||||
tmpChildrenChecked = !!childrenItems.childrenChecked;
|
||||
if (!selfChecked && onlyChildren && item.children.length === childrenItems.childrenChecked) {
|
||||
selfChecked = true
|
||||
selfChecked = true;
|
||||
}
|
||||
childrenItems = childrenItems.dom
|
||||
childrenItems = childrenItems.dom;
|
||||
}
|
||||
|
||||
if (tmpChildrenChecked || checked) {
|
||||
childrenChecked++
|
||||
childrenChecked++;
|
||||
}
|
||||
|
||||
let nodeDisabled = !!uncheckable || !!disabled || selfDisabled
|
||||
let nodeDisabled = !!uncheckable || !!disabled || selfDisabled;
|
||||
|
||||
const checkbox: JSX.Element | null = multiple ? (
|
||||
<label className={cx(`Checkbox Checkbox--checkbox Checkbox--sm`)}>
|
||||
|
@ -347,9 +347,9 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
/>
|
||||
<i />
|
||||
</label>
|
||||
) : null
|
||||
) : null;
|
||||
|
||||
const isLeaf = !item.children || !item.children.length
|
||||
const isLeaf = !item.children || !item.children.length;
|
||||
|
||||
return (
|
||||
<li
|
||||
|
@ -403,20 +403,20 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
</ul>
|
||||
) : null}
|
||||
</li>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
dom: ret,
|
||||
childrenChecked,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className, placeholder, hideRoot, rootLabel, showIcon, classnames: cx} = this.props
|
||||
let data = this.props.data
|
||||
const {className, placeholder, hideRoot, rootLabel, showIcon, classnames: cx} = this.props;
|
||||
let data = this.props.data;
|
||||
|
||||
const value = this.state.value
|
||||
const value = this.state.value;
|
||||
return (
|
||||
<div className={cx(`Tree ${className || ''}`)}>
|
||||
{data && data.length ? (
|
||||
|
@ -446,8 +446,8 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
|
|||
<div className={cx('Tree-placeholder')}>{placeholder}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(TreeSelector)
|
||||
export default themeable(TreeSelector);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import * as React from 'react'
|
||||
import * as React from 'react';
|
||||
export const closeIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1463">
|
||||
<path
|
||||
|
@ -13,22 +13,22 @@ export const closeIcon = (
|
|||
data-spm-anchor-id="a313x.7781069.0.i0"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const unDoIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path d="M661.333333 341.333333H167.04l183.253333-183.253333L320 128 85.333333 362.666667l234.666667 234.666666 30.08-30.08L167.04 384H661.333333a234.666667 234.666667 0 0 1 0 469.333333H448v42.666667h213.333333a277.333333 277.333333 0 0 0 0-554.666667z" />
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const reDoIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path d="M704 128l-30.08 30.08L856.96 341.333333H362.666667a277.333333 277.333333 0 0 0 0 554.666667h213.333333v-42.666667H362.666667a234.666667 234.666667 0 0 1 0-469.333333h494.293333l-183.253333 183.253333L704 597.333333l234.666667-234.666666z" />
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const enterIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path d="M864 192c-19.2 0-32 12.8-32 32v224c0 89.6-70.4 160-160 160H236.8l105.6-105.6c12.8-12.8 12.8-32 0-44.8s-32-12.8-44.8 0l-160 160c-3.2 3.2-6.4 6.4-6.4 9.6-3.2 6.4-3.2 16 0 25.6 3.2 3.2 3.2 6.4 6.4 9.6l160 160c6.4 6.4 12.8 9.6 22.4 9.6s16-3.2 22.4-9.6c12.8-12.8 12.8-32 0-44.8L236.8 672H672c124.8 0 224-99.2 224-224V224c0-19.2-12.8-32-32-32z" />
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const volumeIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path
|
||||
|
@ -42,7 +42,7 @@ export const volumeIcon = (
|
|||
p-id="3606"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const muteIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path
|
||||
|
@ -51,7 +51,7 @@ export const muteIcon = (
|
|||
p-id="2312"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const playIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path
|
||||
|
@ -60,7 +60,7 @@ export const playIcon = (
|
|||
fill="#606670"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
export const pauseIcon = (
|
||||
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
|
||||
<path
|
||||
|
@ -74,4 +74,4 @@ export const pauseIcon = (
|
|||
fill="#606670"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
);
|
||||
|
|
|
@ -4,39 +4,39 @@
|
|||
* @author fex
|
||||
*/
|
||||
|
||||
import NotFound from './404'
|
||||
import {default as Alert, alert, confirm} from './Alert'
|
||||
import AsideNav from './AsideNav'
|
||||
import Button from './Button'
|
||||
import Checkbox from './Checkbox'
|
||||
import Checkboxes from './Checkboxes'
|
||||
import Collapse from './Collapse'
|
||||
import ColorPicker from './ColorPicker'
|
||||
import DatePicker from './DatePicker'
|
||||
import DateRangePicker from './DateRangePicker'
|
||||
import Drawer from './Drawer'
|
||||
import DropdownButton from './DropdownButton'
|
||||
import NotFound from './404';
|
||||
import {default as Alert, alert, confirm} from './Alert';
|
||||
import AsideNav from './AsideNav';
|
||||
import Button from './Button';
|
||||
import Checkbox from './Checkbox';
|
||||
import Checkboxes from './Checkboxes';
|
||||
import Collapse from './Collapse';
|
||||
import ColorPicker from './ColorPicker';
|
||||
import DatePicker from './DatePicker';
|
||||
import DateRangePicker from './DateRangePicker';
|
||||
import Drawer from './Drawer';
|
||||
import DropdownButton from './DropdownButton';
|
||||
// import Editor from './Editor';
|
||||
import Html from './Html'
|
||||
import * as Icons from './icons'
|
||||
import Layout from './Layout'
|
||||
import LazyComponent from './LazyComponent'
|
||||
import Modal from './Modal'
|
||||
import Overlay from './Overlay'
|
||||
import PopOver from './PopOver'
|
||||
import Radios from './Radios'
|
||||
import Range from './Range'
|
||||
import Rating from './Rating'
|
||||
import Html from './Html';
|
||||
import * as Icons from './icons';
|
||||
import Layout from './Layout';
|
||||
import LazyComponent from './LazyComponent';
|
||||
import Modal from './Modal';
|
||||
import Overlay from './Overlay';
|
||||
import PopOver from './PopOver';
|
||||
import Radios from './Radios';
|
||||
import Range from './Range';
|
||||
import Rating from './Rating';
|
||||
// import RichText from './RichText';
|
||||
import Select from './Select'
|
||||
import Spinner from './Spinner'
|
||||
import Switch from './Switch'
|
||||
import Textarea from './Textarea'
|
||||
import TitleBar from './TitleBar'
|
||||
import {default as ToastComponent, toast} from './Toast'
|
||||
import Tooltip from './Tooltip'
|
||||
import TooltipWrapper from './TooltipWrapper'
|
||||
import Tree from './Tree'
|
||||
import Select from './Select';
|
||||
import Spinner from './Spinner';
|
||||
import Switch from './Switch';
|
||||
import Textarea from './Textarea';
|
||||
import TitleBar from './TitleBar';
|
||||
import {default as ToastComponent, toast} from './Toast';
|
||||
import Tooltip from './Tooltip';
|
||||
import TooltipWrapper from './TooltipWrapper';
|
||||
import Tree from './Tree';
|
||||
|
||||
export {
|
||||
NotFound,
|
||||
|
@ -75,4 +75,4 @@ export {
|
|||
Tooltip,
|
||||
TooltipWrapper,
|
||||
Tree,
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue