refactor: 💡 set semi true

This commit is contained in:
SIMDD 2019-05-08 13:38:22 +08:00
parent 9e5c689d20
commit 81e123179c
37 changed files with 1849 additions and 1847 deletions

View File

@ -3,7 +3,7 @@
"tabWidth": 4,
"useTabs": false,
"singleQuote": true,
"semi": false,
"semi": true,
"trailingComma": "es5",
"bracketSpacing": false,
"arrowParens": "avoid"

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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',
})
)
);

View File

@ -1,3 +1,3 @@
import {Collapse} from 'react-bootstrap'
import {Collapse} from 'react-bootstrap';
export default Collapse
export default Collapse;

View File

@ -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',
})
)
);

View File

@ -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};

View File

@ -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);

View File

@ -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));

View File

@ -1,3 +1,3 @@
import {DropdownButton} from 'react-bootstrap'
import {DropdownButton} from 'react-bootstrap';
export default DropdownButton
export default DropdownButton;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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>;
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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} />;
}
}

View File

@ -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);

View File

@ -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',
})
)
);

View File

@ -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',
})
)
);

View File

@ -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);

View File

@ -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',
}
};

View File

@ -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',
})
)
);

View File

@ -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);

View File

@ -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);

View File

@ -1,2 +1,2 @@
import * as Textarea from 'react-textarea-autosize'
export default Textarea
import * as Textarea from 'react-textarea-autosize';
export default Textarea;

View File

@ -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);

View File

@ -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'),
}
};

View File

@ -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);

View File

@ -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',
})
)
);

View File

@ -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);

View File

@ -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>
)
);

View File

@ -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,
}
};