Merge pull request #19 from simdd/master

format: add comment and fommat Component folder
This commit is contained in:
liaoxuezhi 2019-05-08 13:39:53 +08:00 committed by GitHub
commit 39afde9f97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1869 additions and 1838 deletions

View File

@ -1,10 +1,10 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "avoid"
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": true,
"semi": true,
"trailingComma": "es5",
"bracketSpacing": false,
"arrowParens": "avoid"
}

View File

@ -4,7 +4,7 @@
*/
import * as React from 'react';
import { themeable, ClassNamesFn } from '../theme';
import {themeable, ClassNamesFn} from '../theme';
interface NotFoundProps {
code?: string | number;
@ -17,28 +17,18 @@ interface NotFoundProps {
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">
<div className="text-center m-b-lg">
<h1 className="text-shadow text-white">{code || '404'}</h1>
{description ? (<div className="text-danger">{description}</div>) : null}
{description ? <div className="text-danger">{description}</div> : null}
</div>
{children}
{links ? (
<div className="list-group bg-info auto m-b-sm m-b-lg">
{links}
</div>
) : null}
{links ? <div className="list-group bg-info auto m-b-sm m-b-lg">{links}</div> : null}
{footerText ? (
<div className="text-center">
@ -52,4 +42,4 @@ export class NotFound extends React.Component<NotFoundProps, any> {
}
}
export default themeable(NotFound);
export default themeable(NotFound);

View File

@ -1,14 +1,13 @@
/**
* @file alert
* @author fex
*/
/* eslint fecs-indent: [0, "space", 2, 2] */
* @file Alert
* @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 {ClassNamesFn, themeable} from '../theme';
export interface AlertProps {
container?: any;
@ -20,18 +19,17 @@ export interface AlertProps {
classPrefix: string;
classnames: ClassNamesFn;
theme?: string;
};
}
export interface AlertState {
show: boolean;
title?:string;
content:string;
confirm: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 了');
@ -44,16 +42,16 @@ export class Alert extends React.Component<AlertProps, AlertState> {
return Alert.instance;
}
_resolve:(value:any) => void;
_modal:any;
_body:any;
state:AlertState = {
_resolve: (value: any) => void;
_modal: any;
_body: any;
state: AlertState = {
show: false,
title: '',
content: '',
confirm: false
confirm: false,
};
constructor(props:AlertProps) {
constructor(props: AlertProps) {
super(props);
this.close = this.close.bind(this);
@ -68,7 +66,7 @@ export class Alert extends React.Component<AlertProps, AlertState> {
cancelText: '取消',
title: '系统消息',
alertBtnLevel: 'primary',
confirmBtnLevel: 'danger'
confirmBtnLevel: 'danger',
};
componentWillMount() {
@ -79,8 +77,7 @@ export class Alert extends React.Component<AlertProps, AlertState> {
this._body && (this._body.innerHTML = this.state.content);
}
componentDidUpdate(prevProps:AlertProps, prevState:AlertState) {
componentDidUpdate(prevProps: AlertProps, prevState: AlertState) {
if (prevState.content !== this.state.content) {
this._body && (this._body.innerHTML = this.state.content);
}
@ -98,41 +95,44 @@ export class Alert extends React.Component<AlertProps, AlertState> {
this.close(false);
}
close(confirmed:boolean) {
close(confirmed: boolean) {
const isConfirm = this.state.confirm;
this.setState({
show: false
}, isConfirm ? () => this._resolve(confirmed)/*this._reject()*/ : undefined);
this.setState(
{
show: false,
},
isConfirm ? () => this._resolve(confirmed) /*this._reject()*/ : undefined
);
}
alert(content:string, title?:string) {
alert(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: false
confirm: false,
});
}
confirm(content:string, title?:string) {
confirm(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: true
confirm: true,
});
return new Promise((resolve) => {
return new Promise(resolve => {
this._resolve = resolve;
});
}
modalRef(ref:any) {
modalRef(ref: any) {
this._modal = ref;
}
bodyRef(ref:any) {
bodyRef(ref: any) {
this._body = ref;
this._body && (this._body.innerHTML = this.state.content);
}
@ -146,15 +146,10 @@ export class Alert extends React.Component<AlertProps, AlertState> {
confirmBtnLevel,
alertBtnLevel,
classnames: cx,
classPrefix
} = this.props;
classPrefix,
} = this.props;
return (
<Modal
show={this.state.show}
onHide={this.handleCancel}
container={container}
ref={this.modalRef}
>
<Modal show={this.state.show} onHide={this.handleCancel} container={container} ref={this.modalRef}>
<div className={cx('Modal-header')}>
<div className={cx('Modal-title')}>{this.state.title || title}</div>
</div>
@ -162,22 +157,19 @@ export class Alert extends React.Component<AlertProps, AlertState> {
<div ref={this.bodyRef} />
</div>
<div className={cx('Modal-footer')}>
{this.state.confirm ? (
<Button
onClick={this.handleCancel}
>{cancelText}</Button>
) : null}
<Button
level={this.state.confirm ? confirmBtnLevel : alertBtnLevel}
onClick={this.handleConfirm}
>{confirmText}</Button>
{this.state.confirm ? <Button onClick={this.handleCancel}>{cancelText}</Button> : null}
<Button level={this.state.confirm ? confirmBtnLevel : alertBtnLevel} onClick={this.handleConfirm}>
{confirmText}
</Button>
</div>
</Modal>
);
}
}
export const alert:(content:string, title?:string) => void = (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 const alert: (content: string, title?: string) => void = (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;

View File

@ -1,5 +1,10 @@
/**
* @file Alert2
* @author fex
*/
import * as React from 'react';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
export interface AlertProps {
level: 'danger' | 'info' | 'success' | 'warning';
@ -12,53 +17,43 @@ export interface AlertProps {
export interface AlertState {
show: boolean;
};
}
export class Alert extends React.Component<AlertProps, AlertState> {
static defaultProps:Pick<AlertProps, "level" | "className" | "showCloseButton"> = {
static defaultProps: Pick<AlertProps, 'level' | 'className' | 'showCloseButton'> = {
level: 'info',
className: '',
showCloseButton: false
showCloseButton: false,
};
static propsList: Array<string> = [
"level",
"className",
"showCloseButton",
"onClose"
];
static propsList: Array<string> = ['level', 'className', 'showCloseButton', 'onClose'];
constructor(props:AlertProps) {
constructor(props: AlertProps) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
show: true
}
show: true,
};
}
handleClick() {
this.setState({
show: false
}, this.props.onClose);
this.setState(
{
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)}>
<div className={cx('Alert', level ? `Alert--${level}` : '', className)}>
{showCloseButton ? (
<button
className={cx("Alert-close")}
onClick={this.handleClick}
type="button"
><span>×</span></button>
<button className={cx('Alert-close')} onClick={this.handleClick} type="button">
<span>×</span>
</button>
) : null}
{children}
</div>
@ -66,4 +61,4 @@ export class Alert extends React.Component<AlertProps, AlertState> {
}
}
export default themeable(Alert);
export default themeable(Alert);

View File

@ -1,16 +1,14 @@
/**
* @file AsideNav
*
* @description
* @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 {mapTree} from '../utils/helper';
import {classPrefix, classnames} from '../themes/default';
import {ClassNamesFn, themeable} from '../theme';
export type LinkItem = LinkItemProps;
interface LinkItemProps {
@ -29,8 +27,8 @@ interface Navigation {
prefix?: JSX.Element;
affix?: JSX.Element;
className?: string;
[propName:string]: any;
};
[propName: string]: any;
}
interface AsideNavProps {
id?: string;
@ -39,34 +37,33 @@ interface AsideNavProps {
classnames: ClassNamesFn;
renderLink: Function;
isActive: Function;
isOpen: (link:LinkItemProps) => boolean;
isOpen: (link: LinkItemProps) => boolean;
navigations: Array<Navigation>;
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, props:AsideNavProps) => React.ReactNode;
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, props: AsideNavProps) => React.ReactNode;
}
interface AsideNavState {
navigations: Array<Navigation>;
}
export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
static defaultProps = {
renderLink: (item: LinkItemProps) => (
<a>{item.label}</a>
),
renderSubLinks: (link:LinkItemProps, renderLink: Function, depth: number, {
classnames: cx
}: AsideNavProps) => link.children && link.children.length ? (
<ul className={cx('AsideNav-subList')}>
{link.label ? <li key="subHeader" className={cx('AsideNav-subHeader')}><a>{link.label}</a></li> : null}
{link.children.map((link, key) => renderLink(link, key, {}, depth + 1))}
</ul>
) : link.label && depth === 1 ? (
<div className={cx('AsideNav-tooltip')}>{link.label}</div>
) : null,
renderLink: (item: LinkItemProps) => <a>{item.label}</a>,
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, {classnames: cx}: AsideNavProps) =>
link.children && link.children.length ? (
<ul className={cx('AsideNav-subList')}>
{link.label ? (
<li key="subHeader" className={cx('AsideNav-subHeader')}>
<a>{link.label}</a>
</li>
) : null}
{link.children.map((link, key) => renderLink(link, key, {}, depth + 1))}
</ul>
) : link.label && depth === 1 ? (
<div className={cx('AsideNav-tooltip')}>{link.label}</div>
) : null,
isActive: (link: LinkItem) => link.open,
isOpen: (item:LinkItemProps) => item.children ? item.children.some(item => item.open) : false
isOpen: (item: LinkItemProps) => (item.children ? item.children.some(item => item.open) : false),
};
constructor(props: AsideNavProps) {
@ -75,16 +72,22 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
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;
navigations: mapTree(
props.navigations,
(item: Navigation) => {
const isActive =
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)
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps),
};
},
1,
true
),
};
this.renderLink = this.renderLink.bind(this);
@ -94,42 +97,46 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
componentWillReceiveProps(nextProps: AsideNavProps) {
const props = this.props;
const isOpen = props.isOpen;
if (props.navigations !== nextProps.navigations || props.isActive !== nextProps.isActive) {
if (props.navigations !== nextProps.navigations || props.isActive !== nextProps.isActive) {
let id = 1;
this.setState({
navigations: mapTree(nextProps.navigations, (item: Navigation) => {
const isActive = typeof item.active === 'undefined' ? (nextProps.isActive as Function)(item) : item.active;
navigations: mapTree(
nextProps.navigations,
(item: Navigation) => {
const isActive =
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)
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps),
};
},
1,
true
),
});
}
}
toggleExpand(link: LinkItemProps) {
this.setState({
navigations: mapTree(this.state.navigations, (item: Navigation) => ({
...item,
open: link.id === item.id ? !item.open : item.open
}), 1, true)
navigations: mapTree(
this.state.navigations,
(item: Navigation) => ({
...item,
open: link.id === item.id ? !item.open : item.open,
}),
1,
true
),
});
}
renderLink(link: LinkItemProps, key: any, props:Partial<AsideNavProps> = {}, depth = 1):React.ReactNode {
const {
renderLink,
isActive,
renderSubLinks,
classnames: cx,
...others
} = this.props;
renderLink(link: LinkItemProps, key: any, props: Partial<AsideNavProps> = {}, depth = 1): React.ReactNode {
const {renderLink, isActive, renderSubLinks, classnames: cx, ...others} = this.props;
const dom = (renderLink as Function)({
link,
@ -138,7 +145,7 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
toggleExpand: this.toggleExpand,
depth,
classnames: cx,
...others
...others,
});
if (!dom) {
@ -150,7 +157,7 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
{...props}
key={key}
className={cx(`AsideNav-item`, link.className, {
[`is-active`]: link.active || link.open
[`is-active`]: link.active || link.open,
})}
>
{dom}
@ -161,29 +168,29 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
render() {
const navigations = this.state.navigations;
let links:Array<React.ReactNode> = [];
const {
className,
classnames: cx
} = this.props;
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;
links.push(React.cloneElement(prefix, {
...prefix.props,
key: `${index}-prefix`
}))
const prefix: JSX.Element =
typeof navigation.prefix === 'function'
? (navigation.prefix as any)(this.props)
: navigation.prefix;
links.push(
React.cloneElement(prefix, {
...prefix.props,
key: `${index}-prefix`,
})
);
}
navigation.label && links.push(
<li
key={`${index}-label`}
className={cx(`AsideNav-label`, navigation.className)}
>
<span>{navigation.label}</span>
</li>
);
navigation.label &&
links.push(
<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}`);
@ -191,22 +198,23 @@ export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
});
if (navigation.affix) {
const affix:JSX.Element = typeof navigation.affix === 'function' ? (navigation.affix as any)(this.props) : navigation.affix;
links.push(React.cloneElement(affix, {
...affix.props,
key: `${index}-affix`
}))
const affix: JSX.Element =
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>
<ul className={cx(`AsideNav-list`)}>{links}</ul>
</nav>
);
}
}
export default themeable(AsideNav);
export default themeable(AsideNav);

View File

@ -1,21 +1,22 @@
/**
* @file
* @file Button
* @author fex
* fex
*/
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> {
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";
type: 'button' | 'reset' | 'submit';
level: string; // 'link' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'danger' | 'light' | 'dark' | 'default';
tooltip?: string | TooltipObject;
placement: "top" | "right" | "bottom" | "left";
placement: 'top' | 'right' | 'bottom' | 'left';
tooltipContainer?: any;
tooltipTrigger: Trigger | Array<Trigger>;
tooltipRootClose: boolean;
@ -30,13 +31,16 @@ interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes
}
export class Button extends React.Component<ButtonProps> {
static defaultProps:Pick<ButtonProps, "componentClass" | "level" | "type" | "placement" | "tooltipTrigger" | "tooltipRootClose"> = {
static defaultProps: Pick<
ButtonProps,
'componentClass' | 'level' | 'type' | 'placement' | 'tooltipTrigger' | 'tooltipRootClose'
> = {
componentClass: 'button',
level: 'default',
type: 'button',
placement: 'top',
tooltipTrigger: ['hover', 'focus'],
tooltipRootClose: false
tooltipRootClose: false,
};
renderButton() {
@ -60,14 +64,18 @@ export class Button extends React.Component<ButtonProps> {
<Comp
type={Comp === 'a' ? undefined : type}
{...pickEventsProps(rest)}
className={cx(`Button`, {
[`Button--${level}`]: level,
[`Button--${size}`]: size,
[`Button--block`]: block,
[`Button--iconOnly`]: iconOnly,
'is-disabled': disabled,
'is-active': active
}, className)}
className={cx(
`Button`,
{
[`Button--${level}`]: level,
[`Button--${size}`]: size,
[`Button--block`]: block,
[`Button--iconOnly`]: iconOnly,
'is-disabled': disabled,
'is-active': active,
},
className
)}
disabled={disabled}
>
{children}
@ -85,7 +93,7 @@ export class Button extends React.Component<ButtonProps> {
disabled,
disabledTip,
classPrefix,
classnames: cx
classnames: cx,
} = this.props;
return (
@ -96,12 +104,11 @@ export class Button extends React.Component<ButtonProps> {
trigger={tooltipTrigger}
rootClose={tooltipRootClose}
>
{disabled && disabledTip ?
<div className={cx('Button--disabled-wrap')}>
{this.renderButton()}
</div>
: this.renderButton()
}
{disabled && disabledTip ? (
<div className={cx('Button--disabled-wrap')}>{this.renderButton()}</div>
) : (
this.renderButton()
)}
</TooltipWrapper>
);
}

View File

@ -1,17 +1,17 @@
/**
* @file checkbox组件
* @file Checkbox
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
const sizeMap = {
sm: 'i-checks-sm',
lg: 'i-checks-lg',
small: 'i-checks-sm',
large: 'i-checks-lg'
large: 'i-checks-lg',
};
interface CheckboxProps {
@ -22,7 +22,7 @@ interface CheckboxProps {
size?: 'sm' | 'lg' | 'small' | 'large';
label?: string;
className?: string;
onChange?: (value:any) => void;
onChange?: (value: any) => void;
value?: any;
containerClass?: string;
inline?: boolean;
@ -41,21 +41,17 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
static defaultProps = {
trueValue: true,
falseValue: false,
type: 'checkbox'
type: 'checkbox',
};
constructor(props:CheckboxProps) {
constructor(props: CheckboxProps) {
super(props);
this.hanldeCheck = this.hanldeCheck.bind(this);
}
hanldeCheck(e:React.ChangeEvent<any>) {
const {
trueValue,
falseValue,
onChange
} = this.props;
hanldeCheck(e: React.ChangeEvent<any>) {
const {trueValue, falseValue, onChange} = this.props;
if (!onChange) {
return;
@ -78,20 +74,30 @@ export class Checkbox extends React.Component<CheckboxProps, any> {
readOnly,
checked,
type,
name
name,
} = this.props;
className = (className ? className : '') + (size && sizeMap[size] ? ` ${sizeMap[size]}` : '');
return (
<label
className={cx(`${ns}Checkbox ${ns}Checkbox--${type}`, {
[`${ns}Checkbox--full`]: !partial
}, className)}
<label
className={cx(
`${ns}Checkbox ${ns}Checkbox--${type}`,
{
[`${ns}Checkbox--full`]: !partial,
},
className
)}
>
<input
type={type}
checked={typeof checked !== 'undefined' ? checked : typeof value === 'undefined' ? value : value == trueValue}
checked={
typeof checked !== 'undefined'
? checked
: typeof value === 'undefined'
? value
: value == trueValue
}
onChange={this.hanldeCheck}
disabled={disabled}
readOnly={readOnly}

View File

@ -1,6 +1,6 @@
/**
* @file checkboxes
*
* @file Checkboxes
* @description
* @author fex
*/
@ -9,9 +9,9 @@ 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 {flattenTree} from '../utils/helper';
import {Option} from './Checkboxes';
import {ClassNamesFn, themeable} from '../theme';
// import isPlainObject = require('lodash/isPlainObject');
export interface Option {
@ -20,8 +20,8 @@ export interface Option {
disabled?: boolean;
children?: Options;
[propName: string]: any;
};
export interface Options extends Array<Option> { };
}
export interface Options extends Array<Option> {}
export interface OptionProps {
multi?: boolean;
@ -33,7 +33,7 @@ export interface OptionProps {
delimiter: string;
clearable: boolean;
placeholder?: string;
};
}
export type OptionValue = string | number | null | undefined | Option;
@ -52,7 +52,14 @@ export function value2array(value: OptionValue | Array<OptionValue>, props: Part
}
return (value as Array<OptionValue>)
.map((value: OptionValue) => expandValue(!props.joinValues && value && value.hasOwnProperty(props.valueField || 'value') ? (value as any)[props.valueField || 'value'] : value, props))
.map((value: OptionValue) =>
expandValue(
!props.joinValues && value && value.hasOwnProperty(props.valueField || 'value')
? (value as any)[props.valueField || 'value']
: value,
props
)
)
.filter((item: Option) => item) as Array<Option>;
}
@ -67,10 +74,7 @@ export function expandValue(value: OptionValue, props: Partial<OptionProps>): Op
return null;
}
let {
options,
valueField
} = props;
let {options, valueField} = props;
if (!options) {
return null;
@ -116,35 +120,28 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
extractValue: false,
inline: false,
delimiter: ',',
columnsCount: 1 // 一行显示一个
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
options,
});
let idx = valueArray.indexOf(option);
if (!~idx) {
option = value2array(option[valueField || 'value'], {
multiple: true,
valueField,
delimiter,
options
})[0] || option;
option =
value2array(option[valueField || 'value'], {
multiple: true,
valueField,
delimiter,
options,
})[0] || option;
idx = valueArray.indexOf(option);
}
@ -182,7 +179,7 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
multiple: true,
valueField,
delimiter,
options
options,
});
let body: Array<React.ReactNode> = [];
@ -201,24 +198,27 @@ export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
}
if (!inline && (columnsCount as number) > 1) {
let cellClassName = `col-sm-${(12 / (columnsCount as number)).toFixed(1).replace(/\.0$/, '').replace(/\./, '-')}`;
let cellClassName = `col-sm-${(12 / (columnsCount as number))
.toFixed(1)
.replace(/\.0$/, '')
.replace(/\./, '-')}`;
body = chunk(body, columnsCount).map((group, groupIndex) => (
<div className="row" key={groupIndex}>
{group.map((item, index) => (
<div key={index} className={cellClassName}>{item}</div>
<div key={index} className={cellClassName}>
{item}
</div>
))}
</div>
));
}
return (
<div className={className}>
{body && body.length ? body : placeholder}
</div>
);
return <div className={className}>{body && body.length ? body : placeholder}</div>;
}
}
export default themeable(uncontrollable(Checkboxes, {
value: 'onChange'
}));
export default themeable(
uncontrollable(Checkboxes, {
value: 'onChange',
})
);

View File

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

View File

@ -1,15 +1,18 @@
/**
* @file ColorPicker
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import {
findDOMNode
} from 'react-dom';
import { SketchPicker, ColorResult } from 'react-color';
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 {ClassNamesFn, themeable} from '../theme';
export interface ColorProps {
placeholder?: string;
@ -23,32 +26,32 @@ export interface ColorProps {
value: any;
classPrefix: string;
classnames: ClassNamesFn;
onChange: (value:any) => void;
};
onChange: (value: any) => void;
}
export interface ColorControlState {
isOpened: boolean;
isFocused: boolean;
inputValue: string;
};
}
export class ColorControl extends React.PureComponent<ColorProps, ColorControlState> {
static defaultProps = {
format: 'hex',
clearable: true,
placeholder: '请选择颜色'
placeholder: '请选择颜色',
// closeOnSelect: true
};
state = {
isOpened: false,
isFocused: false,
inputValue: this.props.value || ''
inputValue: this.props.value || '',
};
popover:any;
popover: any;
closeTimer: number;
preview: React.RefObject<HTMLElement>;
input: React.RefObject<HTMLInputElement>;
constructor(props:ColorProps) {
constructor(props: ColorProps) {
super(props);
this.open = this.open.bind(this);
@ -65,26 +68,26 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
this.input = React.createRef();
}
componentWillReceiveProps(nextProps:ColorProps) {
componentWillReceiveProps(nextProps: ColorProps) {
const props = this.props;
if (props.value !== nextProps.value) {
this.setState({
inputValue: nextProps.value || ''
inputValue: nextProps.value || '',
});
}
}
handleFocus() {
this.setState({
isFocused: true
isFocused: true,
});
}
handleBlur() {
this.setState({
isFocused: false,
inputValue: this.props.value
inputValue: this.props.value,
});
}
@ -96,18 +99,21 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
this.input.current && this.input.current.blur();
}
open(fn?:() => void) {
open(fn?: () => void) {
if (this.props.disabled) {
return;
}
this.setState({
isOpened: true
}, fn);
this.setState(
{
isOpened: true,
},
fn
);
}
close() {
this.setState({
isOpened: false
isOpened: false,
});
}
@ -123,31 +129,36 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
const onChange = this.props.onChange;
this.setState({
inputValue: e.currentTarget.value
}, () => {
const dom:HTMLElement = this.preview.current as HTMLElement;
// 通过读取dom上到值确认当前输入值是否有效。
if (dom && dom.style.backgroundColor === this.state.inputValue) {
onChange(this.state.inputValue);
this.setState(
{
inputValue: e.currentTarget.value,
},
() => {
const dom: HTMLElement = this.preview.current as HTMLElement;
// 通过读取dom上到值确认当前输入值是否有效。
if (dom && dom.style.backgroundColor === this.state.inputValue) {
onChange(this.state.inputValue);
}
}
});
);
}
handleChange(color:ColorResult) {
handleChange(color: ColorResult) {
const {
onChange,
format,
// closeOnSelect
} = this.props;
} = this.props;
if (format === 'rgba') {
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})`);
} else if (format === 'hsl') {
onChange(`hsl(${Math.round(color.hsl.h)}, ${Math.round(color.hsl.s * 100)}%, ${Math.round(color.hsl.l * 100)}%)`);
} 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);
}
@ -166,20 +177,24 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
format,
clearable,
placement,
classnames: cx
classnames: cx,
} = this.props;
const isOpened = this.state.isOpened;
const isFocused = this.state.isFocused;
return (
<div
className={cx(`ColorPicker`, {
'is-disabled': disabled,
'is-focused': isFocused
}, className)}
<div
className={cx(
`ColorPicker`,
{
'is-disabled': disabled,
'is-focused': isFocused,
},
className
)}
>
<input
<input
size={10}
ref={this.input}
type="text"
@ -195,10 +210,18 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
/>
{clearable && !disabled && value ? (
<a onClick={this.clearValue} className={cx('ColorPicker-clear')}>{closeIcon}</a>
<a onClick={this.clearValue} className={cx('ColorPicker-clear')}>
{closeIcon}
</a>
) : null}
<span onClick={this.handleClick} className={cx('ColorPicker-preview')}><i ref={this.preview} className={`${ns}ColorPicker-previewIcon`} style={{background: this.state.inputValue || '#ccc'}} /></span>
<span onClick={this.handleClick} className={cx('ColorPicker-preview')}>
<i
ref={this.preview}
className={`${ns}ColorPicker-previewIcon`}
style={{background: this.state.inputValue || '#ccc'}}
/>
</span>
{isOpened ? (
<Overlay
@ -209,13 +232,12 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
rootClose={false}
show
>
<PopOver
classPrefix={ns}
className={cx('ColorPicker-popover')}
onHide={this.close}
overlay
>
<SketchPicker disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)} color={value} onChangeComplete={this.handleChange} />
<PopOver classPrefix={ns} className={cx('ColorPicker-popover')} onHide={this.close} overlay>
<SketchPicker
disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)}
color={value}
onChangeComplete={this.handleChange}
/>
</PopOver>
</Overlay>
) : null}
@ -224,6 +246,8 @@ export class ColorControl extends React.PureComponent<ColorProps, ColorControlSt
}
}
export default themeable(uncontrollable(ColorControl, {
value: 'onChange'
}));
export default themeable(
uncontrollable(ColorControl, {
value: 'onChange',
})
);

View File

@ -1,3 +1,9 @@
/**
* @file DatePicker
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import * as moment from 'moment';
@ -7,16 +13,16 @@ import 'moment/locale/zh-cn';
import * as CalendarContainer from 'react-datetime/src/CalendarContainer';
import * as ReactDatePicker from 'react-datetime';
import Select from './Select';
import { closeIcon } from './icons';
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 () {
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);
@ -32,18 +38,12 @@ class BaseDatePicker extends ReactDatePicker {
this.__hacked = true;
const origin = (this as any).getComponentProps;
const setState = this.setState.bind(this);
(this as any).getComponentProps = function () {
(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]);
['onChange', 'onClose', 'requiredConfirm', 'classPrefix', 'prevIcon', 'nextIcon', 'isEndDate'].forEach(
key => (props[key] = (this.props as any)[key])
);
return props;
};
@ -72,11 +72,11 @@ interface CustomDaysViewProps {
showView: (view: string) => () => void;
updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void;
handleClickOutside: () => void;
};
}
class CustomDaysView extends React.Component<CustomDaysViewProps> {
static defaultProps = {
classPrefix: 'a-'
classPrefix: 'a-',
};
constructor(props: CustomDaysViewProps) {
@ -95,8 +95,8 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
const dow: Array<string> = [];
let i = 0;
days.forEach(function (day) {
dow[(7 + (i++) - first) % 7] = day;
days.forEach(function(day) {
dow[(7 + i++ - first) % 7] = day;
});
return dow;
@ -117,7 +117,8 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
if (~target.className.indexOf('rdtNew')) {
modifier = 1;
} if (~target.className.indexOf('rdtOld')) {
}
if (~target.className.indexOf('rdtOld')) {
modifier = -1;
}
@ -127,11 +128,11 @@ 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()
selectedDate: viewDate.clone(),
});
return;
}
@ -151,7 +152,10 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
const viewDate = this.props.viewDate;
this.props.setDateTimeState({
viewDate: viewDate.clone().month(option.value).startOf('month')
viewDate: viewDate
.clone()
.month(option.value)
.startOf('month'),
});
}
@ -168,7 +172,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
const viewDate = this.props.viewDate;
const newDate = viewDate.clone().year(option.value);
this.props.setDateTimeState({
viewDate: newDate[newDate.isBefore(viewDate) ? 'endOf' : 'startOf']('year')
viewDate: newDate[newDate.isBefore(viewDate) ? 'endOf' : 'startOf']('year'),
});
}
@ -178,7 +182,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
this.props.setDateTimeState({
viewDate: date.clone(),
selectedDate: date.clone()
selectedDate: date.clone(),
});
if (!this.props.requiredConfirm) {
@ -190,7 +194,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
const date = this.props.viewDate.clone();
this.props.setDateTimeState({
selectedDate: date
selectedDate: date,
});
this.props.onChange(date);
this.props.onClose && this.props.onClose();
@ -221,12 +225,15 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
let currentYear = date.clone().set({
year: year,
month: irrelevantMonth,
date: irrelevantDate
date: irrelevantDate,
});
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10);
const daysInYear = Array.from({
length: noOfDaysInYear
}, (e, i) => i + 1);
const daysInYear = Array.from(
{
length: noOfDaysInYear,
},
(e, i) => i + 1
);
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)));
if (!validDay) {
@ -245,12 +252,15 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
let currentYear = date.clone().set({
year: year,
month: irrelevantMonth,
date: irrelevantDate
date: irrelevantDate,
});
const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10);
const daysInYear = Array.from({
length: noOfDaysInYear
}, (e, i) => i + 1);
const daysInYear = Array.from(
{
length: noOfDaysInYear,
},
(e, i) => i + 1
);
const validDay = daysInYear.find(d => isValid(currentYear.clone().dayOfYear(d)));
if (!validDay) {
@ -266,7 +276,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
value={date.year()}
options={years.map(year => ({
label: `${year}`,
value: year
value: year,
}))}
onChange={this.handleYearChange}
clearable={false}
@ -287,15 +297,15 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
const currentMonth = date.clone().set({
year,
month: i,
date: 1
date: 1,
});
const noOfDaysInMonth = parseInt(currentMonth.endOf('month').format('D'), 10);
const daysInMonth = Array.from({ length: noOfDaysInMonth }, function (e, i) {
const daysInMonth = Array.from({length: noOfDaysInMonth}, function(e, i) {
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);
}
@ -308,7 +318,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
value={date.month()}
options={days.map(day => ({
label: `${day + 1}`,
value: day
value: day,
}))}
onChange={this.handleMonthChange}
clearable={false}
@ -318,18 +328,11 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
}
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> = [];
@ -346,22 +349,21 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
value={date.format(format)}
min={min}
max={max}
onChange={(e) => this.setTime(type, Math.max(min, Math.min(parseInt(e.currentTarget.value.replace(/\D/g, ''), 10) || 0, max)))}
onChange={e =>
this.setTime(
type,
Math.max(min, Math.min(parseInt(e.currentTarget.value.replace(/\D/g, ''), 10) || 0, max))
)
}
/>
);
inputs.push(
<span key={i + 'divider'}>:</span>
);
inputs.push(<span key={i + 'divider'}>:</span>);
});
inputs.length && inputs.pop();
return (
<div>
{inputs}
</div>
);
return <div>{inputs}</div>;
}
renderFooter() {
@ -376,8 +378,12 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
{this.props.timeFormat ? this.renderTimes() : null}
{this.props.requiredConfirm ? (
<div key="button" className="rdtActions">
<a className="rdtBtn rdtBtnConfirm" onClick={this.confirm}></a>
<a className="rdtBtn rdtBtnCancel" onClick={this.cancel}></a>
<a className="rdtBtn rdtBtnConfirm" onClick={this.confirm}>
</a>
<a className="rdtBtn rdtBtnCancel" onClick={this.cancel}>
</a>
</div>
) : null}
</td>
@ -406,36 +412,36 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
classes = 'rdtDay';
currentDate = prevMonth.clone();
if ((prevMonth.year() === currentYear && prevMonth.month() < currentMonth) || (prevMonth.year() < currentYear))
if (
(prevMonth.year() === currentYear && prevMonth.month() < currentMonth) ||
prevMonth.year() < currentYear
)
classes += ' rdtOld';
else if ((prevMonth.year() === currentYear && prevMonth.month() > currentMonth) || (prevMonth.year() > currentYear))
else if (
(prevMonth.year() === currentYear && prevMonth.month() > currentMonth) ||
prevMonth.year() > currentYear
)
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';
if (isDisabled) classes += ' rdtDisabled';
dayProps = {
key: prevMonth.format('M_D'),
'data-value': prevMonth.date(),
className: classes
className: classes,
};
if (!isDisabled)
dayProps.onClick = this.handleDayChange;
if (!isDisabled) dayProps.onClick = this.handleDayChange;
days.push(renderer(dayProps, currentDate, selected));
if (days.length === 7) {
weeks.push(
<tr key={prevMonth.format('M_D')}>{days}</tr>
);
weeks.push(<tr key={prevMonth.format('M_D')}>{days}</tr>);
days = [];
}
@ -455,21 +461,27 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
<tr>
<th colSpan={7}>
<div className="rdtHeader">
<a className="rdtBtn" onClick={this.props.subtractTime(1, 'months')}><i className="rdtBtnPrev" /></a>
<a className="rdtBtn" onClick={this.props.subtractTime(1, 'months')}>
<i className="rdtBtnPrev" />
</a>
<div className="rdtSelect">{this.renderYearsSelect()}</div>
<div className="rdtSelect">{this.renderMonthsSelect()}</div>
<a className="rdtBtn" onClick={this.props.addTime(1, 'months')}><i className="rdtBtnNext" /></a>
<a className="rdtBtn" onClick={this.props.addTime(1, 'months')}>
<i className="rdtBtnNext" />
</a>
</div>
</th>
</tr>
<tr>
{this.getDaysOfWeek(locale).map((day, index) => (
<th key={day + index} className="dow">{day}</th>
<th key={day + index} className="dow">
{day}
</th>
))}
</tr>
</thead>,
<tbody key="tb">{this.renderDays()}</tbody>
<tbody key="tb">{this.renderDays()}</tbody>,
];
footer && tableChildren.push(footer);
@ -483,7 +495,7 @@ class CustomDaysView extends React.Component<CustomDaysViewProps> {
}
export interface DateProps {
viewMode: "years" | "months" | "days" | "time";
viewMode: 'years' | 'months' | 'days' | 'time';
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
@ -499,26 +511,26 @@ export interface DateProps {
minTime?: moment.Moment;
maxTime?: moment.Moment;
clearable?: boolean;
defaultValue?: any;
onChange: (value:any) => void;
defaultValue?: any;
onChange: (value: any) => void;
value: any;
[propName:string]: any;
};
[propName: string]: any;
}
export interface DatePickerState {
isOpened: boolean;
isFocused: boolean;
value: moment.Moment | undefined;
};
}
export class DatePicker extends React.Component<DateProps, DatePickerState> {
static defaultProps:Pick<DateProps, 'viewMode'> = {
viewMode: 'days'
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
value: this.props.value ? moment(this.props.value, this.props.format) : undefined,
};
constructor(props: DateProps) {
super(props);
@ -539,14 +551,14 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
dom: HTMLDivElement;
componentWillReceiveProps(nextProps:DateProps) {
componentWillReceiveProps(nextProps: DateProps) {
if (this.props.value !== nextProps.value) {
this.setState({
value: nextProps.value ? moment(nextProps.value, nextProps.format) : undefined
value: nextProps.value ? moment(nextProps.value, nextProps.format) : undefined,
});
}
}
focus() {
if (!this.dom) {
return;
@ -557,17 +569,17 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
handleFocus() {
this.setState({
isFocused: true
isFocused: true,
});
}
handleBlur() {
this.setState({
isFocused: false
isFocused: false,
});
}
handleKeyPress(e:React.KeyboardEvent) {
handleKeyPress(e: React.KeyboardEvent) {
if (e.key === ' ') {
this.handleClick();
}
@ -583,14 +595,18 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
}
open(fn?: () => void) {
this.props.disabled || this.setState({
isOpened: true
}, fn);
this.props.disabled ||
this.setState(
{
isOpened: true,
},
fn
);
}
close() {
this.setState({
isOpened: false
isOpened: false,
});
}
@ -602,14 +618,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
}
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;
@ -629,10 +638,7 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
}
checkIsValidDate(currentDate: moment.Moment) {
const {
minDate,
maxDate
} = this.props;
const {minDate, maxDate} = this.props;
if (minDate && currentDate.isBefore(minDate, 'day')) {
return false;
@ -651,9 +657,9 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
return this.dom;
}
domRef = (ref:HTMLDivElement) => {
domRef = (ref: HTMLDivElement) => {
this.dom = ref;
}
};
render() {
const {
@ -669,22 +675,26 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
viewMode,
timeConstraints,
popOverContainer,
clearable
clearable,
} = this.props;
const isOpened = this.state.isOpened;
let date: moment.Moment | undefined = this.state.value;
return (
<div
tabIndex={0}
<div
tabIndex={0}
onKeyPress={this.handleKeyPress}
onFocus={this.handleFocus}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
className={cx(`${ns}DatePicker`, {
'is-disabled': disabled,
'is-focused': this.state.isFocused
}, className)}
className={cx(
`${ns}DatePicker`,
{
'is-disabled': disabled,
'is-focused': this.state.isFocused,
},
className
)}
ref={this.domRef}
onClick={this.handleClick}
>
@ -695,10 +705,12 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
)}
{clearable && value ? (
<a className={`${ns}DatePicker-clear`} onClick={this.clearValue}>{closeIcon}</a>
<a className={`${ns}DatePicker-clear`} onClick={this.clearValue}>
{closeIcon}
</a>
) : null}
<a className={`${ns}DatePicker-toggler`}></a>
<a className={`${ns}DatePicker-toggler`} />
{isOpened ? (
<Overlay
@ -739,6 +751,4 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
export default themeable(DatePicker);
export {
BaseDatePicker
};
export {BaseDatePicker};

View File

@ -1,12 +1,18 @@
import React = require("react");
import moment = require("moment");
import { findDOMNode } from "react-dom";
/**
* @file DateRangePicker
* @description
* @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 {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;
@ -24,38 +30,38 @@ export interface DateRangePickerProps {
joinValues: boolean;
delimiter: string;
value: any;
onChange: (value:any) => void;
onChange: (value: any) => void;
data?: any;
disabled?: boolean;
[propName:string]: any;
};
[propName: string]: any;
}
export interface DateRangePickerState {
isOpened: boolean;
isFocused: boolean;
startDate?: moment.Moment;
endDate?: moment.Moment;
};
}
const availableRanges: { [propName: string]: any } = {
'today': {
const availableRanges: {[propName: string]: any} = {
today: {
label: '今天',
startDate: (now: moment.Moment) => {
return now.startOf('day');
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
'yesterday': {
yesterday: {
label: '昨天',
startDate: (now: moment.Moment) => {
return now.add(-1, 'days').startOf('day');
},
endDate: (now: moment.Moment) => {
return now.add(-1, 'days').endOf('day');
}
},
},
'1dayago': {
@ -65,7 +71,7 @@ const availableRanges: { [propName: string]: any } = {
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
'7daysago': {
@ -75,7 +81,7 @@ const availableRanges: { [propName: string]: any } = {
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
'90daysago': {
@ -85,57 +91,70 @@ const availableRanges: { [propName: string]: any } = {
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
'prevweek': {
prevweek: {
label: '上周',
startDate: (now: moment.Moment) => {
return now.add(-1, 'days').startOf('week').add(-1, 'weeks');
return now
.add(-1, 'days')
.startOf('week')
.add(-1, 'weeks');
},
endDate: (now: moment.Moment) => {
return now.add(-1, 'days').startOf('week').add(-1, 'day').endOf('day');
}
return now
.add(-1, 'days')
.startOf('week')
.add(-1, 'day')
.endOf('day');
},
},
'thismonth': {
thismonth: {
label: '本月',
startDate: (now: moment.Moment) => {
return now.startOf('month');
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
'prevmonth': {
prevmonth: {
label: '上个月',
startDate: (now: moment.Moment) => {
return now.startOf('month').add(-1, 'month');
},
endDate: (now: moment.Moment) => {
return now.startOf('month').add(-1, 'day').endOf('day');
}
return now
.startOf('month')
.add(-1, 'day')
.endOf('day');
},
},
'prevquarter': {
prevquarter: {
label: '上个季节',
startDate: (now: moment.Moment) => {
return now.startOf('quarter').add(-1, 'quarter');
},
endDate: (now: moment.Moment) => {
return now.startOf('quarter').add(-1, 'day').endOf('day');
}
return now
.startOf('quarter')
.add(-1, 'day')
.endOf('day');
},
},
'thisquarter': {
thisquarter: {
label: '本季度',
startDate: (now: moment.Moment) => {
return now.startOf('quarter');
},
endDate: (now: moment.Moment) => {
return now;
}
},
},
};
@ -149,14 +168,14 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
delimiter: ',',
ranges: 'yesterday,7daysago,prevweek,thismonth,prevmonth,prevquarter',
iconClassName: 'fa fa-calendar',
resetValue: ''
}
resetValue: '',
};
innerDom: any;
popover: any;
input?: HTMLInputElement;
static formatValue(newValue: any, format:string, joinValues: boolean, delimiter: string) {
static formatValue(newValue: any, format: string, joinValues: boolean, delimiter: string) {
newValue = [newValue.startDate.format(format), newValue.endDate.format(format)];
if (joinValues) {
@ -166,12 +185,11 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
return newValue;
}
static unFormatValue(value: any, format:string, joinValues: boolean, delimiter: string) {
static unFormatValue(value: any, format: string, joinValues: boolean, delimiter: string) {
if (!value) {
return {
startDate: undefined,
endDate: undefined
endDate: undefined,
};
}
@ -181,9 +199,8 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
return {
startDate: value[0] ? moment(value[0], format) : undefined,
endDate: value[1] ? moment(value[1], format) : undefined
}
endDate: value[1] ? moment(value[1], format) : undefined,
};
}
dom: React.RefObject<HTMLDivElement>;
@ -206,32 +223,22 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
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)
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter),
};
}
componentWillReceiveProps(nextProps:DateRangePickerProps) {
componentWillReceiveProps(nextProps: DateRangePickerProps) {
const props = this.props;
const {
value,
format,
joinValues,
delimiter
} = nextProps;
const {value, format, joinValues, delimiter} = nextProps;
if (props.value !== value) {
this.setState({
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter)
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter),
});
}
}
@ -254,14 +261,14 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
handleFocus() {
this.setState({
isFocused: true
})
isFocused: true,
});
}
handleBlur() {
this.setState({
isFocused: false
})
isFocused: false,
});
}
open() {
@ -270,14 +277,17 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
}
this.setState({
isOpened: true
isOpened: true,
});
}
close() {
this.setState({
isOpened: false
}, this.blur);
this.setState(
{
isOpened: false,
},
this.blur
);
}
handleClick() {
@ -289,7 +299,7 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
e.preventDefault();
}
handleKeyPress(e:React.KeyboardEvent) {
handleKeyPress(e: React.KeyboardEvent) {
if (e.key === ' ') {
this.handleClick();
}
@ -302,56 +312,58 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
return;
}
this.props.onChange(DateRangePicker.formatValue({
startDate: this.state.startDate,
endDate: this.state.endDate
}, this.props.format, this.props.joinValues, this.props.delimiter));
this.props.onChange(
DateRangePicker.formatValue(
{
startDate: this.state.startDate,
endDate: this.state.endDate,
},
this.props.format,
this.props.joinValues,
this.props.delimiter
)
);
this.close();
}
handleStartChange(newValue: any) {
this.setState({
startDate: newValue.clone()
})
startDate: newValue.clone(),
});
}
handleEndChange(newValue: any) {
newValue = !this.state.endDate && !this.props.timeFormat ? newValue.endOf('day') : newValue;
this.setState({
endDate: newValue.clone()
endDate: newValue.clone(),
});
}
selectRannge(range: { startDate: (now: moment.Moment) => moment.Moment, endDate: (now: moment.Moment) => moment.Moment }) {
selectRannge(range: {
startDate: (now: moment.Moment) => moment.Moment;
endDate: (now: moment.Moment) => moment.Moment;
}) {
const now = moment();
this.setState({
startDate: range.startDate(now.clone()),
endDate: range.endDate(now.clone())
endDate: range.endDate(now.clone()),
});
}
clearValue(e: React.MouseEvent<any>) {
e.preventDefault();
e.stopPropagation();
const {
resetValue,
onChange
} = this.props;
const {resetValue, onChange} = this.props;
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;
@ -363,16 +375,11 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
}
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;
@ -398,15 +405,10 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
timeFormat,
ranges,
disabled,
iconClassName
iconClassName,
} = 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) : '';
@ -415,31 +417,38 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
startViewValue && arr.push(startViewValue);
endViewValue && arr.push(endViewValue);
return (
<div
tabIndex={0}
<div
tabIndex={0}
onKeyPress={this.handleKeyPress}
onFocus={this.handleFocus}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
className={cx(`${ns}DateRangePicker`, {
'is-disabled': disabled,
'is-focused': isFocused
}, className)}
className={cx(
`${ns}DateRangePicker`,
{
'is-disabled': disabled,
'is-focused': isFocused,
},
className
)}
ref={this.dom}
onClick={this.handleClick}
>
{arr.length ? (
<span className={`${ns}DateRangePicker-value`} >{arr.join(' 至 ')}</span>
<span className={`${ns}DateRangePicker-value`}>{arr.join(' 至 ')}</span>
) : (
<span className={`${ns}DateRangePicker-placeholder`}>{placeholder}</span>
)}
{clearable && value ? (
<a className={`${ns}DateRangePicker-clear`} onClick={this.clearValue}>{closeIcon}</a>
<a className={`${ns}DateRangePicker-clear`} onClick={this.clearValue}>
{closeIcon}
</a>
) : null}
<a className={`${ns}DateRangePicker-toggler`}><i className={iconClassName} /></a>
<a className={`${ns}DateRangePicker-toggler`}>
<i className={iconClassName} />
</a>
{isOpened ? (
<Overlay
@ -460,13 +469,22 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
<div className={`${ns}DateRangePicker-wrap`}>
{ranges ? (
<ul className={`${ns}DateRangePicker-rangers`}>
{
(typeof ranges === 'string' ? ranges.split(',') : Array.isArray(ranges) ? ranges : [])
.filter(key => !!availableRanges[key])
.map(key => (
<li className={`${ns}DateRangePicker-ranger`} onClick={() => this.selectRannge(availableRanges[key])} key={key}><a>{availableRanges[key].label}</a></li>
))
}
{(typeof ranges === 'string'
? ranges.split(',')
: Array.isArray(ranges)
? ranges
: []
)
.filter(key => !!availableRanges[key])
.map(key => (
<li
className={`${ns}DateRangePicker-ranger`}
onClick={() => this.selectRannge(availableRanges[key])}
key={key}
>
<a>{availableRanges[key].label}</a>
</li>
))}
</ul>
) : null}
@ -502,10 +520,17 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
/>
<div key="button" className={`${ns}DateRangePicker-actions`}>
<a className={cx("rdtBtn rdtBtnConfirm", {
"is-disabled": !this.state.startDate || !this.state.endDate
})} onClick={this.confirm}></a>
<a className="rdtBtn rdtBtnCancel" onClick={this.close}></a>
<a
className={cx('rdtBtn rdtBtnConfirm', {
'is-disabled': !this.state.startDate || !this.state.endDate,
})}
onClick={this.confirm}
>
</a>
<a className="rdtBtn rdtBtnCancel" onClick={this.close}>
</a>
</div>
</div>
</PopOver>
@ -516,4 +541,4 @@ export class DateRangePicker extends React.Component<DateRangePickerProps, DateR
}
}
export default themeable(DateRangePicker);
export default themeable(DateRangePicker);

View File

@ -1,25 +1,19 @@
/**
* @file Drawer
* @description
* @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 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 {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';
@ -40,24 +34,25 @@ export interface DrawerProps {
onEntered?: () => void;
disableOnClickOutside: () => void;
enableOnClickOutside: () => void;
};
export interface DrawerState {
}
export interface DrawerState {}
const fadeStyles: {
[propName: string]: string;
} = {
[ENTERING]: 'in',
[ENTERED]: 'in'
[ENTERED]: 'in',
};
export class Drawer extends React.Component<DrawerProps, DrawerState> {
static defaultProps:Pick<DrawerProps, "container" | "position" | "size" | "overlay" | "disableOnClickOutside" | "enableOnClickOutside"> = {
static defaultProps: Pick<
DrawerProps,
'container' | 'position' | 'size' | 'overlay' | 'disableOnClickOutside' | 'enableOnClickOutside'
> = {
container: document.body,
position: 'left',
size: 'md',
overlay: true,
disableOnClickOutside: noop,
enableOnClickOutside: noop
enableOnClickOutside: noop,
};
contentDom: any;
@ -74,7 +69,7 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
}
}
contentRef = (ref: any) => this.contentDom = ref;
contentRef = (ref: any) => (this.contentDom = ref);
handleEntered = () => {
const onEntered = this.props.onEntered;
document.body.classList.add(`is-modalOpened`);
@ -84,7 +79,7 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
const onExited = this.props.onExited;
onExited && onExited();
setTimeout(() => {
document.querySelector('.amis-dialog-widget') || (document.body.classList.remove(`is-modalOpened`));
document.querySelector('.amis-dialog-widget') || document.body.classList.remove(`is-modalOpened`);
}, 200);
};
@ -95,13 +90,10 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
} else {
removeModal();
}
}
};
handleClickOutside() {
const {
closeOnOutside,
onHide
} = this.props;
const {closeOnOutside, onHide} = this.props;
closeOnOutside && onHide && onHide();
}
@ -116,13 +108,11 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
size,
onHide,
disabled,
overlay
overlay,
} = this.props;
return (
<Portal
container={container}
>
<Portal container={container}>
<Transition
mountOnEnter
unmountOnExit
@ -140,12 +130,20 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
}
return (
<div ref={this.modalRef} role="dialog" className={cx(`amis-dialog-widget ${ns}Drawer`, {
[`${ns}Drawer--${position}`]: position,
[`${ns}Drawer--${size}`]: size,
[`${ns}Drawer--noOverlay`]: !overlay,
}, className)}>
{overlay ? (<div className={cx(`${ns}Drawer-overlay`, fadeStyles[status])} />) : null}
<div
ref={this.modalRef}
role="dialog"
className={cx(
`amis-dialog-widget ${ns}Drawer`,
{
[`${ns}Drawer--${position}`]: position,
[`${ns}Drawer--${size}`]: size,
[`${ns}Drawer--noOverlay`]: !overlay,
},
className
)}
>
{overlay ? <div className={cx(`${ns}Drawer-overlay`, fadeStyles[status])} /> : null}
<div ref={this.contentRef} className={cx(`${ns}Drawer-content`, fadeStyles[status])}>
<a onClick={disabled ? undefined : onHide} className={`${ns}Drawer-close`}>
{closeIcon}
@ -153,7 +151,7 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
{children}
</div>
</div>
)
);
}}
</Transition>
</Portal>
@ -161,4 +159,4 @@ export class Drawer extends React.Component<DrawerProps, DrawerState> {
}
}
export default themeable(onClickOutside(Drawer));
export default themeable(onClickOutside(Drawer));

View File

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

View File

@ -1,26 +1,32 @@
/**
* @file Editor
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
function noJsExt(raw:string) {
function noJsExt(raw: string) {
return raw.replace(/\.js$/, '');
}
const defaultConfig = {
url: 'vs/loader.js',
'vs/nls' : {
'vs/nls': {
availableLanguages: {
'*': 'zh-cn'
}
'*': 'zh-cn',
},
},
paths: {}
paths: {},
};
try {
// fis 编译的话,能正确赋值上,如果不是,那请通过外部参数传递。
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: 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')),
'vs/basic-languages/apex/apex': noJsExt(__uri('monaco-editor/min/vs/basic-languages/apex/apex')),
@ -31,39 +37,59 @@ try {
'vs/basic-languages/cpp/cpp': noJsExt(__uri('monaco-editor/min/vs/basic-languages/cpp/cpp')),
'vs/basic-languages/csharp/csharp': noJsExt(__uri('monaco-editor/min/vs/basic-languages/csharp/csharp')),
'vs/basic-languages/css/css': noJsExt(__uri('monaco-editor/min/vs/basic-languages/css/css')),
'vs/basic-languages/dockerfile/dockerfile': noJsExt(__uri('monaco-editor/min/vs/basic-languages/dockerfile/dockerfile')),
'vs/basic-languages/dockerfile/dockerfile': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/dockerfile/dockerfile')
),
'vs/basic-languages/fsharp/fsharp': noJsExt(__uri('monaco-editor/min/vs/basic-languages/fsharp/fsharp')),
'vs/basic-languages/go/go': noJsExt(__uri('monaco-editor/min/vs/basic-languages/go/go')),
'vs/basic-languages/handlebars/handlebars': noJsExt(__uri('monaco-editor/min/vs/basic-languages/handlebars/handlebars')),
'vs/basic-languages/handlebars/handlebars': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/handlebars/handlebars')
),
'vs/basic-languages/html/html': noJsExt(__uri('monaco-editor/min/vs/basic-languages/html/html')),
'vs/basic-languages/ini/ini': noJsExt(__uri('monaco-editor/min/vs/basic-languages/ini/ini')),
'vs/basic-languages/java/java': noJsExt(__uri('monaco-editor/min/vs/basic-languages/java/java')),
'vs/basic-languages/javascript/javascript': noJsExt(__uri('monaco-editor/min/vs/basic-languages/javascript/javascript')),
'vs/basic-languages/javascript/javascript': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/javascript/javascript')
),
'vs/basic-languages/less/less': noJsExt(__uri('monaco-editor/min/vs/basic-languages/less/less')),
'vs/basic-languages/lua/lua': noJsExt(__uri('monaco-editor/min/vs/basic-languages/lua/lua')),
'vs/basic-languages/markdown/markdown': noJsExt(__uri('monaco-editor/min/vs/basic-languages/markdown/markdown')),
'vs/basic-languages/markdown/markdown': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/markdown/markdown')
),
'vs/basic-languages/msdax/msdax': noJsExt(__uri('monaco-editor/min/vs/basic-languages/msdax/msdax')),
'vs/basic-languages/objective-c/objective-c': noJsExt(__uri('monaco-editor/min/vs/basic-languages/objective-c/objective-c')),
'vs/basic-languages/objective-c/objective-c': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/objective-c/objective-c')
),
'vs/basic-languages/php/php': noJsExt(__uri('monaco-editor/min/vs/basic-languages/php/php')),
'vs/basic-languages/postiats/postiats': noJsExt(__uri('monaco-editor/min/vs/basic-languages/postiats/postiats')),
'vs/basic-languages/powershell/powershell': noJsExt(__uri('monaco-editor/min/vs/basic-languages/powershell/powershell')),
'vs/basic-languages/postiats/postiats': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/postiats/postiats')
),
'vs/basic-languages/powershell/powershell': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/powershell/powershell')
),
'vs/basic-languages/pug/pug': noJsExt(__uri('monaco-editor/min/vs/basic-languages/pug/pug')),
'vs/basic-languages/python/python': noJsExt(__uri('monaco-editor/min/vs/basic-languages/python/python')),
'vs/basic-languages/r/r': noJsExt(__uri('monaco-editor/min/vs/basic-languages/r/r')),
'vs/basic-languages/razor/razor': noJsExt(__uri('monaco-editor/min/vs/basic-languages/razor/razor')),
'vs/basic-languages/redis/redis': noJsExt(__uri('monaco-editor/min/vs/basic-languages/redis/redis')),
'vs/basic-languages/redshift/redshift': noJsExt(__uri('monaco-editor/min/vs/basic-languages/redshift/redshift')),
'vs/basic-languages/redshift/redshift': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/redshift/redshift')
),
'vs/basic-languages/ruby/ruby': noJsExt(__uri('monaco-editor/min/vs/basic-languages/ruby/ruby')),
'vs/basic-languages/rust/rust': noJsExt(__uri('monaco-editor/min/vs/basic-languages/rust/rust')),
'vs/basic-languages/sb/sb': noJsExt(__uri('monaco-editor/min/vs/basic-languages/sb/sb')),
'vs/basic-languages/scheme/scheme': noJsExt(__uri('monaco-editor/min/vs/basic-languages/scheme/scheme')),
'vs/basic-languages/scss/scss': noJsExt(__uri('monaco-editor/min/vs/basic-languages/scss/scss')),
'vs/basic-languages/shell/shell': noJsExt(__uri('monaco-editor/min/vs/basic-languages/shell/shell')),
'vs/basic-languages/solidity/solidity': noJsExt(__uri('monaco-editor/min/vs/basic-languages/solidity/solidity')),
'vs/basic-languages/solidity/solidity': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/solidity/solidity')
),
'vs/basic-languages/sql/sql': noJsExt(__uri('monaco-editor/min/vs/basic-languages/sql/sql')),
'vs/basic-languages/st/st': noJsExt(__uri('monaco-editor/min/vs/basic-languages/st/st')),
'vs/basic-languages/swift/swift': noJsExt(__uri('monaco-editor/min/vs/basic-languages/swift/swift')),
'vs/basic-languages/typescript/typescript': noJsExt(__uri('monaco-editor/min/vs/basic-languages/typescript/typescript')),
'vs/basic-languages/typescript/typescript': noJsExt(
__uri('monaco-editor/min/vs/basic-languages/typescript/typescript')
),
'vs/basic-languages/vb/vb': noJsExt(__uri('monaco-editor/min/vs/basic-languages/vb/vb')),
'vs/basic-languages/xml/xml': noJsExt(__uri('monaco-editor/min/vs/basic-languages/xml/xml')),
'vs/basic-languages/yaml/yaml': noJsExt(__uri('monaco-editor/min/vs/basic-languages/yaml/yaml')),
@ -88,22 +114,22 @@ try {
'vs/language/html/htmlWorker': noJsExt(__uri('monaco-editor/min/vs/language/html/htmlWorker.js')),
'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'))
'vs/language/css/cssWorker': noJsExt(__uri('monaco-editor/min/vs/language/css/cssWorker.js')),
};
// cdn 支持
/^(https?:)?\/\//.test(defaultConfig.paths.vs) && ((window as any).MonacoEnvironment = {
getWorkerUrl: function() {
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
/^(https?:)?\/\//.test(defaultConfig.paths.vs) &&
((window as any).MonacoEnvironment = {
getWorkerUrl: function() {
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
self.MonacoEnvironment = {
baseUrl: '${defaultConfig.paths.vs}',
paths: ${JSON.stringify(defaultConfig.paths)}
};
importScripts('${__uri('monaco-editor/min/vs/base/worker/workerMain.js')}');`
)}`;
}
});
} catch (e) {};
importScripts('${__uri('monaco-editor/min/vs/base/worker/workerMain.js')}');`)}`;
},
});
} catch (e) {}
export function monacoFactory(containerElement, monaco, options) {
return monaco.editor.create(containerElement, {
@ -114,22 +140,22 @@ export function monacoFactory(containerElement, monaco, options) {
scrollBeyondLastLine: false,
folding: true,
minimap: {
enabled: false
enabled: false,
},
...options
...options,
});
}
export interface EditorProps {
value?:string;
value?: string;
defaultValue?: string;
width?: number | string;
height?: number | string;
onChange?: (value:string, event:any) => void;
onChange?: (value: string, event: any) => void;
language?: string;
editorTheme?: string;
options: {
[propName:string]: any;
[propName: string]: any;
};
classPrefix: string;
className?: string;
@ -138,13 +164,13 @@ export interface EditorProps {
style?: any;
onFocus?: () => void;
onBlur?: () => void;
editorDidMount?: (editor:any, monaco:any) => void;
editorWillMount?: (monaco:any) => void;
editorFactory?: (conatainer:HTMLElement, monaco:any, options:any) => any;
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;
[propName: string]: any;
};
}
@ -155,22 +181,22 @@ export class Editor extends React.Component<EditorProps, any> {
editorTheme: 'vs',
width: '100%',
height: '100%',
options: {}
options: {},
};
editor:any;
container:any;
currentValue:any;
editor: any;
container: any;
currentValue: any;
preventTriggerChangeEvent: boolean;
disposes:Array<{dispose:() => void}> = [];
constructor(props:EditorProps) {
disposes: Array<{dispose: () => void}> = [];
constructor(props: EditorProps) {
super(props);
this.wrapperRef = this.wrapperRef.bind(this);
this.currentValue = props.value;
}
componentWillReceiveProps(nextProps:EditorProps) {
componentWillReceiveProps(nextProps: EditorProps) {
if (this.props.options.readOnly !== nextProps.options.readOnly && this.editor) {
this.editor.updateOptions && this.editor.updateOptions(nextProps.options);
}
@ -183,9 +209,7 @@ export class Editor extends React.Component<EditorProps, any> {
if (this.props.language === 'json') {
try {
value = JSON.stringify(JSON.parse(value), null, 4);
} catch (e) {
}
} catch (e) {}
}
this.preventTriggerChangeEvent = true;
@ -199,7 +223,7 @@ export class Editor extends React.Component<EditorProps, any> {
this.disposes = [];
}
wrapperRef(ref:any) {
wrapperRef(ref: any) {
this.container = ref;
if (ref) {
this.loadMonaco();
@ -218,15 +242,15 @@ export class Editor extends React.Component<EditorProps, any> {
}
}
loadMonaco() {
const { requireConfig } = this.props;
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 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
@ -261,7 +285,7 @@ export class Editor extends React.Component<EditorProps, any> {
context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ = context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__ || [];
context.__REACT_MONACO_EDITOR_LOADER_CALLBACKS__.push({
context: this,
fn: onGotAmdLoader
fn: onGotAmdLoader,
});
} else {
if (typeof context.require === 'undefined') {
@ -279,7 +303,7 @@ export class Editor extends React.Component<EditorProps, any> {
initMonaco() {
let value = this.props.value !== null ? this.props.value : this.props.defaultValue;
const { language, editorTheme, options, editorFactory } = this.props;
const {language, editorTheme, options, editorFactory} = this.props;
const containerElement = this.container;
if (!containerElement) {
return;
@ -292,7 +316,7 @@ export class Editor extends React.Component<EditorProps, any> {
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
}
@ -305,7 +329,7 @@ export class Editor extends React.Component<EditorProps, any> {
value,
language,
editorTheme,
theme: editorTheme
theme: editorTheme,
});
// After initializing monaco editor
@ -313,46 +337,38 @@ export class Editor extends React.Component<EditorProps, any> {
}
}
editorWillMount(monaco:any) {
const { editorWillMount } = this.props;
editorWillMount(monaco: any) {
const {editorWillMount} = this.props;
editorWillMount && editorWillMount(monaco);
}
editorDidMount(editor:any, monaco:any) {
const { editorDidMount, onChange, onFocus, onBlur } = this.props;
editorDidMount(editor: any, monaco: any) {
const {editorDidMount, onChange, onFocus, onBlur} = this.props;
editorDidMount && editorDidMount(editor, monaco);
editor.onDidChangeModelContent && this.disposes.push(editor.onDidChangeModelContent((event:any) => {
const value = editor.getValue();
// Always refer to the latest value
this.currentValue = value;
editor.onDidChangeModelContent &&
this.disposes.push(
editor.onDidChangeModelContent((event: any) => {
const value = editor.getValue();
// Always refer to the latest value
this.currentValue = value;
// Only invoking when user input changed
if (!this.preventTriggerChangeEvent && onChange) {
onChange(value, event);
}
}));
// Only invoking when user input changed
if (!this.preventTriggerChangeEvent && onChange) {
onChange(value, event);
}
})
);
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;
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

@ -1,7 +1,13 @@
/**
* @file Html
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { classPrefix, classnames } from '../themes/default';
import { ClassNamesFn, themeable } from '../theme';
import {classPrefix, classnames} from '../themes/default';
import {ClassNamesFn, themeable} from '../theme';
export interface HtmlProps {
className?: string;
@ -14,24 +20,23 @@ export interface HtmlProps {
export class Html extends React.Component<HtmlProps> {
static defaultProps = {
inline: true
inline: true,
};
dom:any;
dom: any;
constructor(props:HtmlProps) {
constructor(props: HtmlProps) {
super(props);
this.htmlRef = this.htmlRef.bind(this);
}
componentDidUpdate(prevProps:HtmlProps) {
componentDidUpdate(prevProps: HtmlProps) {
if (this.props.html !== prevProps.html) {
this._render();
}
}
htmlRef(dom:any) {
htmlRef(dom: any) {
this.dom = dom;
if (!dom) {
@ -42,9 +47,7 @@ export class Html extends React.Component<HtmlProps> {
}
_render() {
const {
html,
} = this.props;
const {html} = this.props;
if (html) {
this.dom.innerHTML = html;
@ -52,19 +55,12 @@ export class Html extends React.Component<HtmlProps> {
}
render() {
const {
className,
wrapperComponent,
inline,
classPrefix: ns
} = this.props;
const {className, wrapperComponent, inline, classPrefix: ns} = this.props;
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

@ -1,8 +1,9 @@
/**
* @file 
*
*
* @file Layout
* @description 
* @author fex
*
* @param
* * children
* * header
* * aside
@ -13,12 +14,11 @@
* * asideFixed position:fixed .
* * className
* * contentClassName
*
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
interface LayoutProps {
id: string;
@ -39,14 +39,13 @@ interface LayoutProps {
}
export class Layout extends React.Component<LayoutProps, any> {
static defaultProps = {
// asideWide: false,
asideFixed: true,
asideClassName: '',
headerFixed: true,
offScreen: false,
footer: false
footer: false,
};
render() {
@ -65,16 +64,10 @@ export class Layout extends React.Component<LayoutProps, any> {
offScreen,
size,
classPrefix,
classnames: cx
classnames: cx,
} = 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 = (
@ -94,12 +87,10 @@ export class Layout extends React.Component<LayoutProps, any> {
'Layout--folded': folded,
'Layout--offScreen': offScreen,
[`Layout--${size}`]: size,
'Layout--noFooter': !footer
'Layout--noFooter': !footer,
})}
>
{header ? (
<div className={cx('Layout-header')}>{header}</div>
) : null}
{header ? <div className={cx('Layout-header')}>{header}</div> : null}
{aside ? (
<div className={cx(`Layout-aside`, asideClassName)}>
<div className={cx('Layout-asideWrap')}>
@ -111,10 +102,7 @@ export class Layout extends React.Component<LayoutProps, any> {
) : null}
{body}
{footer ? (
<footer
className={cx('Layout-footer')}
role="footer"
>
<footer className={cx('Layout-footer')} role="footer">
{footer}
</footer>
) : null}
@ -123,4 +111,4 @@ export class Layout extends React.Component<LayoutProps, any> {
}
}
export default themeable(Layout);
export default themeable(Layout);

View File

@ -1,3 +1,9 @@
/**
* @file LazyComponent
* @description
* @author fex
*/
import * as React from 'react';
import VisibilitySensor = require('react-visibility-sensor');
@ -8,7 +14,7 @@ export interface LazyComponentProps {
unMountOnHidden?: boolean;
childProps?: object;
visiblilityProps?: object;
[propName:string]: any;
[propName: string]: any;
}
export interface LazyComponentState {
@ -20,57 +26,47 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
static defaultProps = {
placeholder: '加载中...',
unMountOnHidden: false,
partialVisibility: true
partialVisibility: true,
};
constructor(props:LazyComponentProps) {
constructor(props: LazyComponentProps) {
super(props);
this.handleVisibleChange = this.handleVisibleChange.bind(this);
this.state = {
visible: false,
component: props.component as React.ReactType
component: props.component as React.ReactType,
};
}
handleVisibleChange(visible:boolean) {
handleVisibleChange(visible: boolean) {
this.setState({
visible: visible
visible: visible,
});
if (!visible || this.state.component || !this.props.getComponent) {
return;
}
this.props.getComponent()
.then(component => this.setState({
component: component
}))
.catch(reason => this.setState({
component: () => (
<div className="alert alert-danger">
{String(reason)}
</div>
)
}))
this.props
.getComponent()
.then(component =>
this.setState({
component: component,
})
)
.catch(reason =>
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) {
@ -81,12 +77,7 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
onChange={this.handleVisibleChange}
>
<div className="visibility-sensor">
{Component && visible ? (
<Component
{...rest}
{...childProps}
/>
) : placeholder}
{Component && visible ? <Component {...rest} {...childProps} /> : placeholder}
</div>
</VisibilitySensor>
);
@ -94,7 +85,7 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
if (!visible) {
return (
<VisibilitySensor
<VisibilitySensor
{...visiblilityProps}
partialVisibility={partialVisibility}
onChange={this.handleVisibleChange}
@ -102,15 +93,11 @@ export default class LazyComponent extends React.Component<LazyComponentProps, L
<div className="visibility-sensor">{placeholder}</div>
</VisibilitySensor>
);
} else if (Component) {
} else if (Component) {
// 只监听不可见到可见,一旦可见了,就销毁检查。
return (
<Component {...rest} {...childProps} />
);
return <Component {...rest} {...childProps} />;
}
return (
<div>{placeholder}</div>
);
return <div>{placeholder}</div>;
}
}

View File

@ -1,18 +1,15 @@
/**
* @file Modal
* @description
* @author fex
*/
import * as React from 'react';
import Transition, {
ENTERED,
ENTERING
} from 'react-transition-group/Transition';
import {
Portal
} from 'react-overlays';
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 {current, addModal, removeModal} from './ModalManager';
import {ClassNamesFn, themeable} from '../theme';
export interface ModalProps {
className?: string;
@ -27,21 +24,19 @@ export interface ModalProps {
classnames: ClassNamesFn;
onExited?: () => void;
onEntered?: () => void;
};
export interface ModalState {
}
export interface ModalState {}
const fadeStyles: {
[propName: string]: string;
} = {
[ENTERING]: 'in',
[ENTERED]: 'in'
[ENTERED]: 'in',
};
export class Modal extends React.Component<ModalProps, ModalState> {
static defaultProps = {
container: document.body,
size: '',
overlay: true
overlay: true,
};
contentDom: any;
@ -58,7 +53,7 @@ export class Modal extends React.Component<ModalProps, ModalState> {
}
}
contentRef = (ref: any) => this.contentDom = ref;
contentRef = (ref: any) => (this.contentDom = ref);
handleEntered = () => {
const onEntered = this.props.onEntered;
document.body.classList.add(`is-modalOpened`);
@ -68,37 +63,25 @@ export class Modal extends React.Component<ModalProps, ModalState> {
const onExited = this.props.onExited;
onExited && onExited();
setTimeout(() => {
document.querySelector('.amis-dialog-widget') || (document.body.classList.remove(`is-modalOpened`));
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`);
} else {
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}
>
<Portal container={container}>
<Transition
mountOnEnter
unmountOnExit
@ -116,15 +99,23 @@ export class Modal extends React.Component<ModalProps, ModalState> {
}
return (
<div ref={this.modalRef} role="dialog" className={cx(`amis-dialog-widget ${ns}Modal`, {
[`${ns}Modal--${size}`]: size
}, className)}>
{overlay ? (<div className={cx(`${ns}Modal-overlay`, fadeStyles[status])} />) : null}
<div
ref={this.modalRef}
role="dialog"
className={cx(
`amis-dialog-widget ${ns}Modal`,
{
[`${ns}Modal--${size}`]: size,
},
className
)}
>
{overlay ? <div className={cx(`${ns}Modal-overlay`, fadeStyles[status])} /> : null}
<div ref={this.contentRef} className={cx(`${ns}Modal-content`, fadeStyles[status])}>
{children}
</div>
</div>
)
);
}}
</Transition>
</Portal>
@ -132,4 +123,4 @@ export class Modal extends React.Component<ModalProps, ModalState> {
}
}
export default themeable(Modal);
export default themeable(Modal);

View File

@ -1,10 +1,17 @@
import * as keycode from "keycode";
/**
* @file ModalManager
* @description
* @author fex
*/
interface ModalComponent extends React.Component<{
onHide: () => void;
disabled?: boolean;
closeOnEsc?: boolean;
}> {}
import * as keycode from 'keycode';
interface ModalComponent
extends React.Component<{
onHide: () => void;
disabled?: boolean;
closeOnEsc?: boolean;
}> {}
let modals: Array<ModalComponent> = [];
@ -12,11 +19,11 @@ export function current() {
return modals.length;
}
export function currentModal():ModalComponent | void {
export function currentModal(): ModalComponent | void {
return modals[modals.length - 1];
}
export function addModal(modal:ModalComponent) {
export function addModal(modal: ModalComponent) {
modals.push(modal);
}
@ -26,7 +33,7 @@ export function removeModal() {
window.addEventListener('keydown', handleWindowKeyDown);
function handleWindowKeyDown(e:Event) {
function handleWindowKeyDown(e: Event) {
const code = keycode(e);
if (code !== 'esc') {
return;
@ -39,4 +46,4 @@ function handleWindowKeyDown(e:Event) {
if (closeOnEsc && !disabled) {
modal.props.onHide();
}
}
}

View File

@ -1,18 +1,17 @@
import {
Position,
Overlay as BaseOverlay
} from 'react-overlays';
/**
* @file Overlay
* @description
* @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 {calculatePosition, getContainer, ownerDocument} from '../utils/dom';
Position.propTypes.placement = BaseOverlay.propTypes.placement = () => null;
Position.prototype.updatePosition = function(target:any) {
Position.prototype.updatePosition = function(target: any) {
this._lastTarget = target;
if (!target) {
@ -20,25 +19,16 @@ Position.prototype.updatePosition = function(target:any) {
positionLeft: 0,
positionTop: 0,
arrowOffsetLeft: null,
arrowOffsetTop: null
arrowOffsetTop: null,
});
}
const overlay = findDOMNode(this);
const container = getContainer(
this.props.container, ownerDocument(this).body
);
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;
@ -48,14 +38,11 @@ interface OverlayProps {
target?: React.ReactNode | Function;
}
export default class Overlay extends React.Component<OverlayProps> {
constructor(props:OverlayProps) {
constructor(props: OverlayProps) {
super(props as any);
}
render() {
return (
<BaseOverlay {...this.props as any} />
)
return <BaseOverlay {...this.props as any} />;
}
};
}

View File

@ -1,17 +1,17 @@
/**
* @file simple-popover
* @author fex
*/
/* eslint fecs-indent: [0, "space", 2, 2] */
* @file PopOver
* @description
* @author fex
*/
import * as React from 'react';
import {findDOMNode} from 'react-dom';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
export interface Offset {
x: number;
y: number;
};
}
export interface PopOverPorps {
className?: string;
@ -20,14 +20,14 @@ export interface PopOverPorps {
positionLeft?: number;
arrowOffsetLeft?: number;
arrowOffsetTop?: number;
offset?: ((clip:object, offset:object) => Offset) | Offset;
offset?: ((clip: object, offset: object) => Offset) | Offset;
style?: object;
overlay?: boolean;
onHide?: () => void;
onClick?: (e:React.MouseEvent<any>) => void;
onClick?: (e: React.MouseEvent<any>) => void;
classPrefix: string;
classnames: ClassNamesFn;
[propName:string]: any;
[propName: string]: any;
}
interface PopOverState {
@ -40,49 +40,47 @@ export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
className: '',
offset: {
x: 0,
y: 0
y: 0,
},
overlay: false,
placement: 'bottom',
};
state = {
xOffset: 0,
yOffset: 0
yOffset: 0,
};
componentDidMount() {
this.mayUpdateOffset();
}
componentDidUpdate() {
this.mayUpdateOffset();
}
mayUpdateOffset() {
let offset: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
x,
y,
placement,
});
} else {
offset = getOffset as Offset;
}
this.setState({
xOffset: offset ? (offset as Offset).x : 0,
yOffset: offset ? offset.y : 0
yOffset: offset ? offset.y : 0,
});
}
render() {
const {
placement,
@ -100,32 +98,23 @@ export class PopOver extends React.PureComponent<PopOverPorps, PopOverState> {
className,
...rest
} = 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
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}
<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

@ -1,19 +1,9 @@
/**
* @file checkboxes
*
* @file Radios
* @description
* @author fex
*/
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';
/**
*
*
* @param
* options: [
* {
* label: '显示的名字',
@ -23,45 +13,42 @@ 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;
}
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;
}
export class Radios extends React.Component<RadioProps, any> {
static defaultProps = {
joinValues: true,
clearable: false,
columnsCount: 1 // 一行显示一个
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
options,
});
const idx = valueArray.indexOf(option);
@ -96,14 +83,14 @@ export class Radios extends React.Component<RadioProps, any> {
inline,
delimiter,
valueField,
classPrefix
classPrefix,
} = this.props;
let valueArray = value2array(value, {
multiple: false,
delimiter,
valueField,
options
options,
});
let body: Array<React.ReactNode> = [];
@ -125,25 +112,25 @@ export class Radios extends React.Component<RadioProps, any> {
}
if (!inline && columnsCount > 1) {
let weight = 12/(columnsCount as number);
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) => (
<div key={index} className={cx(cellClassName)}>{item}</div>
<div key={index} className={cx(cellClassName)}>
{item}
</div>
))}
</div>
));
}
return (
<div className={className}>
{body && body.length ? body : placeholder}
</div>
);
return <div className={className}>{body && body.length ? body : placeholder}</div>;
}
}
export default themeable(uncontrollable(Radios, {
value: 'onChange'
}));
export default themeable(
uncontrollable(Radios, {
value: 'onChange',
})
);

View File

@ -1,13 +1,15 @@
/**
* @file Input Range
* @file Range
* @description
* @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 {RendererProps} from '../factory';
import {ClassNamesFn, themeable} from '../theme';
interface RangeProps extends RendererProps {
id?: string;
@ -22,17 +24,11 @@ interface RangeProps extends RendererProps {
export class Range extends React.Component<RangeProps, any> {
static defaultProps: Partial<RangeProps> = {
min: 1,
max: 100
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`,
@ -45,14 +41,23 @@ 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 {...this.props} className={className} classNames={classNames} minValue={min} maxValue={max} value={typeof value === 'number' ? value : min} />
)
<InputRange
{...this.props}
className={className}
classNames={classNames}
minValue={min}
maxValue={max}
value={typeof value === 'number' ? value : min}
/>
);
}
}
export default themeable(uncontrollable(Range, {
value: 'onChange'
}));
export default themeable(
uncontrollable(Range, {
value: 'onChange',
})
);

View File

@ -1,11 +1,12 @@
/**
* @file rating组件
* @file Rating
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
interface RatingProps {
id?: string;
@ -16,7 +17,7 @@ interface RatingProps {
char: string;
size: number;
className?: string;
onChange?: (value:any) => void;
onChange?: (value: any) => void;
value: number;
containerClass: string;
readOnly: boolean;
@ -32,10 +33,10 @@ export class Rating extends React.Component<RatingProps, any> {
value: 0,
count: 5,
char: '★',
size: 24
size: 24,
};
constructor(props:RatingProps) {
constructor(props: RatingProps) {
super(props);
this.state = {
@ -43,9 +44,9 @@ export class Rating extends React.Component<RatingProps, any> {
stars: [],
halfStar: {
at: Math.floor(props.value),
hidden: props.half && props.value % 1 < 0.5
}
}
hidden: props.half && props.value % 1 < 0.5,
},
};
this.getRate = this.getRate.bind(this);
this.getStars = this.getStars.bind(this);
@ -56,27 +57,27 @@ export class Rating extends React.Component<RatingProps, any> {
}
componentDidMount() {
const { value } = this.state;
const {value} = this.state;
this.setState({
stars: this.getStars(value)
})
stars: this.getStars(value),
});
}
componentWillReceiveProps(props:RatingProps) {
componentWillReceiveProps(props: RatingProps) {
this.setState({
stars: this.getStars(props.value),
value: props.value,
halfStar: {
at: Math.floor(props.value),
hidden: props.half && props.value % 1 < 0.5
}
})
hidden: props.half && props.value % 1 < 0.5,
},
});
}
getRate() {
let stars;
const { value } = this.state;
const { half } = this.props;
const {value} = this.state;
const {half} = this.props;
if (half) {
stars = Math.floor(value);
} else {
@ -85,22 +86,22 @@ export class Rating extends React.Component<RatingProps, any> {
return stars;
}
getStars(activeCount?:number) {
getStars(activeCount?: number) {
if (typeof activeCount === 'undefined') {
activeCount = this.getRate();
}
let stars = [];
const { count } = this.props;
const {count} = this.props;
for (let i = 0; i < count; i++) {
stars.push({
active: i <= activeCount - 1
})
active: i <= activeCount - 1,
});
}
return stars;
}
mouseOver(event:React.ChangeEvent<any>) {
let { readOnly, size, half } = this.props;
mouseOver(event: React.ChangeEvent<any>) {
let {readOnly, size, half} = this.props;
if (readOnly) return;
let index = Number(event.target.getAttribute('data-index'));
if (half) {
@ -109,75 +110,75 @@ export class Rating extends React.Component<RatingProps, any> {
this.setState({
halfStar: {
at: index,
hidden: isAtHalf
}
})
hidden: isAtHalf,
},
});
} else {
index = index + 1;
}
this.setState({
stars: this.getStars(index)
})
stars: this.getStars(index),
});
}
moreThanHalf(event:any, size:number) {
let { target } = event;
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;
}
mouseLeave() {
let { value } = this.state;
const { half, readOnly } = this.props;
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
}
})
hidden: value % 1 === 0, // check value is decimal or not
},
});
}
this.setState({
stars: this.getStars()
})
stars: this.getStars(),
});
}
handleClick(event:React.ChangeEvent<any>) {
const { half, readOnly, onChange, size } = this.props;
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;
if (half) {
const isAtHalf = this.moreThanHalf(event, size);
if (isAtHalf) index = index + 1;
value = isAtHalf ? index : index + .5;
value = isAtHalf ? index : index + 0.5;
this.setState({
halfStar: {
at: index,
hidden: isAtHalf
}
})
hidden: isAtHalf,
},
});
} else {
value = index = index + 1;
}
this.setState({
value: value,
stars: this.getStars(index)
})
stars: this.getStars(index),
});
onChange && onChange(value);
}
renderStars() {
const { halfStar, stars } = this.state;
const { char, half, readOnly, classnames: cx } = this.props;
return stars.map((star:any, i:number) => {
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
})
'is-disabled': readOnly,
});
return (
<span
@ -188,22 +189,19 @@ export class Rating extends React.Component<RatingProps, any> {
onMouseOver={this.mouseOver}
onMouseMove={this.mouseOver}
onMouseLeave={this.mouseLeave}
onClick={this.handleClick}>
onClick={this.handleClick}
>
{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

@ -1,3 +1,9 @@
/**
* @file RichText
* @description
* @author fex
*/
import * as React from 'react';
import * as $ from 'jquery';
@ -23,26 +29,25 @@ import * as $ from 'jquery';
require('froala-editor/js/plugins/code_view.min'),
// require('froala-editor/js/plugins/emotion'),
require('froala-editor/js/plugins/fullscreen.min'),
require('froala-editor/js/plugins/video.min')
].forEach(init => init());
require('froala-editor/js/plugins/video.min'),
].forEach(init => init());
// Require Editor CSS files.
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;
config:any = {
listeningEvents: Array<any> = [];
$element: any = null;
$editor: any = null;
config: any = {
immediateReactModelUpdate: false,
reactIgnoreAttrs: null
reactIgnoreAttrs: null,
};
editorInitialized:boolean = false;
oldModel:any = null;
editorInitialized: boolean = false;
oldModel: any = null;
constructor(props:any) {
constructor(props: any) {
super(props);
this.textareaRef = this.textareaRef.bind(this);
}
@ -55,11 +60,11 @@ export default class FroalaEditor extends React.Component<any, any> {
this.setContent();
}
textareaRef(ref:any) {
textareaRef(ref: any) {
ref ? this.createEditor(ref) : this.destroyEditor();
}
createEditor(ref:any) {
createEditor(ref: any) {
if (this.editorInitialized) {
return;
}
@ -73,8 +78,7 @@ export default class FroalaEditor extends React.Component<any, any> {
this.editorInitialized = true;
}
setContent (firstTime:boolean = false) {
setContent(firstTime: boolean = false) {
if (!this.editorInitialized && !firstTime) {
return;
}
@ -86,7 +90,7 @@ export default class FroalaEditor extends React.Component<any, any> {
}
}
setNormalTagContent (firstTime:boolean) {
setNormalTagContent(firstTime: boolean) {
let self = this;
function htmlSet() {
@ -101,17 +105,16 @@ export default class FroalaEditor extends React.Component<any, any> {
} else {
htmlSet();
}
}
getEditor () {
getEditor() {
if (this.$element) {
return this.$element.froalaEditor.bind(this.$element);
}
return null;
}
updateModel () {
updateModel() {
if (!this.props.onModelChange) {
return;
}
@ -127,23 +130,22 @@ export default class FroalaEditor extends React.Component<any, any> {
this.props.onModelChange(modelContent);
}
initListeners () {
initListeners() {
let self = this;
// bind contentChange and keyup event to froalaModel
this.registerEvent(this.$element, 'froalaEditor.contentChanged',function () {
this.registerEvent(this.$element, 'froalaEditor.contentChanged', function() {
self.updateModel();
});
if (this.config.immediateReactModelUpdate) {
this.registerEvent(this.$editor, 'keyup', function () {
this.registerEvent(this.$editor, 'keyup', function() {
self.updateModel();
});
}
}
// register event on jquery editor element
registerEvent (element:any, eventName:any, callback:any) {
registerEvent(element: any, eventName: any, callback: any) {
if (!element || !eventName || !callback) {
return;
}
@ -152,7 +154,7 @@ export default class FroalaEditor extends React.Component<any, any> {
element.on(eventName, callback);
}
registerEvents () {
registerEvents() {
let events = this.config.events;
if (!events) {
return;
@ -165,9 +167,9 @@ export default class FroalaEditor extends React.Component<any, any> {
}
}
destroyEditor () {
destroyEditor() {
if (this.$element) {
this.listeningEvents && this.$element.off(this.listeningEvents.join(" "));
this.listeningEvents && this.$element.off(this.listeningEvents.join(' '));
this.$editor.off('keyup');
this.$element.froalaEditor('destroy');
this.listeningEvents.length = 0;
@ -177,241 +179,244 @@ export default class FroalaEditor extends React.Component<any, any> {
}
render() {
return (
<textarea ref={this.textareaRef}></textarea>
);
return <textarea ref={this.textareaRef} />;
}
}
($ as any).FE.VIDEO_PROVIDERS = [
{
test_regex: /^.+(bcebos.com)\/[^_&]+/,
url_regex: '',
url_text: '',
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>'
test_regex: /^.+(bcebos.com)\/[^_&]+/,
url_regex: '',
url_text: '',
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'] = {
translation: {
// Place holder
"Type something": "\u8f93\u5165\u4e00\u4e9b\u5185\u5bb9",
// Place holder
'Type something': '\u8f93\u5165\u4e00\u4e9b\u5185\u5bb9',
// Basic formatting
"Bold": "\u7c97\u4f53",
"Italic": "\u659c\u4f53",
"Underline": "\u4e0b\u5212\u7ebf",
"Strikethrough": "\u5220\u9664\u7ebf",
// Basic formatting
Bold: '\u7c97\u4f53',
Italic: '\u659c\u4f53',
Underline: '\u4e0b\u5212\u7ebf',
Strikethrough: '\u5220\u9664\u7ebf',
// Main buttons
"Insert": "\u63d2\u5165",
"Delete": "\u5220\u9664",
"Cancel": "\u53d6\u6d88",
"OK": "\u786e\u5b9a",
"Back": "\u80cc\u90e8",
"Remove": "\u53bb\u6389",
"More": "\u66f4\u591a",
"Update": "\u66f4\u65b0",
"Style": "\u98ce\u683c",
// Main buttons
Insert: '\u63d2\u5165',
Delete: '\u5220\u9664',
Cancel: '\u53d6\u6d88',
OK: '\u786e\u5b9a',
Back: '\u80cc\u90e8',
Remove: '\u53bb\u6389',
More: '\u66f4\u591a',
Update: '\u66f4\u65b0',
Style: '\u98ce\u683c',
// Font
"Font Family": "\u5b57\u4f53",
"Font Size": "\u5b57\u53f7",
// Font
'Font Family': '\u5b57\u4f53',
'Font Size': '\u5b57\u53f7',
// Colors
"Colors": "\u989c\u8272",
"Background": "\u80cc\u666f",
"Text": "\u6587\u5b57",
// Colors
Colors: '\u989c\u8272',
Background: '\u80cc\u666f',
Text: '\u6587\u5b57',
// Paragraphs
"Paragraph Format": "\u683c\u5f0f",
"Normal": "\u6b63\u5e38",
"Code": "\u4ee3\u7801",
"Heading 1": "\u6807\u98981",
"Heading 2": "\u6807\u98982",
"Heading 3": "\u6807\u98983",
"Heading 4": "\u6807\u98984",
// Paragraphs
'Paragraph Format': '\u683c\u5f0f',
Normal: '\u6b63\u5e38',
Code: '\u4ee3\u7801',
'Heading 1': '\u6807\u98981',
'Heading 2': '\u6807\u98982',
'Heading 3': '\u6807\u98983',
'Heading 4': '\u6807\u98984',
// Style
"Paragraph Style": "\u6bb5\u843d\u6837\u5f0f",
"Inline Style": "\u5185\u8054\u6837\u5f0f",
// Style
'Paragraph Style': '\u6bb5\u843d\u6837\u5f0f',
'Inline Style': '\u5185\u8054\u6837\u5f0f',
// Alignment
"Align": "\u5bf9\u9f50\u65b9\u5f0f",
"Align Left": "\u5de6\u5bf9\u9f50",
"Align Center": "\u5c45\u4e2d",
"Align Right": "\u53f3\u5bf9\u9f50",
"Align Justify": "\u4e24\u7aef\u5bf9\u9f50",
"None": "\u65e0",
// Alignment
Align: '\u5bf9\u9f50\u65b9\u5f0f',
'Align Left': '\u5de6\u5bf9\u9f50',
'Align Center': '\u5c45\u4e2d',
'Align Right': '\u53f3\u5bf9\u9f50',
'Align Justify': '\u4e24\u7aef\u5bf9\u9f50',
None: '\u65e0',
// Lists
"Ordered List": "\u7f16\u53f7\u5217\u8868",
"Unordered List": "\u9879\u76ee\u7b26\u53f7",
// Lists
'Ordered List': '\u7f16\u53f7\u5217\u8868',
'Unordered List': '\u9879\u76ee\u7b26\u53f7',
// Indent
"Decrease Indent": "\u51cf\u5c11\u7f29\u8fdb",
"Increase Indent": "\u589e\u52a0\u7f29\u8fdb",
// Indent
'Decrease Indent': '\u51cf\u5c11\u7f29\u8fdb',
'Increase Indent': '\u589e\u52a0\u7f29\u8fdb',
// Links
"Insert Link": "\u63d2\u5165\u94fe\u63a5",
"Open in new tab": "\u5f00\u542f\u5728\u65b0\u6807\u7b7e\u9875",
"Open Link": "\u6253\u5f00\u94fe\u63a5",
"Edit Link": "\u7f16\u8f91\u94fe\u63a5",
"Unlink": "\u5220\u9664\u94fe\u63a5",
"Choose Link": "\u9009\u62e9\u94fe\u63a5",
// Links
'Insert Link': '\u63d2\u5165\u94fe\u63a5',
'Open in new tab': '\u5f00\u542f\u5728\u65b0\u6807\u7b7e\u9875',
'Open Link': '\u6253\u5f00\u94fe\u63a5',
'Edit Link': '\u7f16\u8f91\u94fe\u63a5',
Unlink: '\u5220\u9664\u94fe\u63a5',
'Choose Link': '\u9009\u62e9\u94fe\u63a5',
// Images
"Insert Image": "\u63d2\u5165\u56fe\u7247",
"Upload Image": "\u4e0a\u4f20\u56fe\u7247",
"By URL": "\u901a\u8fc7\u7f51\u5740",
"Browse": "\u6d4f\u89c8",
"Drop image": "\u56fe\u50cf\u62d6\u653e",
"or click": "\u6216\u70b9\u51fb",
"Manage Images": "\u7ba1\u7406\u56fe\u50cf",
"Loading": "\u8f7d\u5165\u4e2d",
"Deleting": "\u5220\u9664",
"Tags": "\u6807\u7b7e",
"Are you sure? Image will be deleted.": "\u4f60\u786e\u5b9a\u5417\uff1f\u56fe\u50cf\u5c06\u88ab\u5220\u9664\u3002",
"Replace": "\u66f4\u6362",
"Uploading": "\u4e0a\u4f20",
"Loading image": "\u5bfc\u5165\u56fe\u50cf",
"Display": "\u663e\u793a",
"Inline": "\u6392\u961f",
"Break Text": "\u65ad\u5f00\u6587\u672c",
"Alternate Text": "\u5907\u7528\u6587\u672c",
"Change Size": "\u5c3a\u5bf8\u53d8\u5316",
"Width": "\u5bbd\u5ea6",
"Height": "\u9ad8\u5ea6",
"Something went wrong. Please try again.": "\u51fa\u4e86\u4e9b\u95ee\u9898\u3002 \u8bf7\u518d\u8bd5\u4e00\u6b21\u3002",
// Images
'Insert Image': '\u63d2\u5165\u56fe\u7247',
'Upload Image': '\u4e0a\u4f20\u56fe\u7247',
'By URL': '\u901a\u8fc7\u7f51\u5740',
Browse: '\u6d4f\u89c8',
'Drop image': '\u56fe\u50cf\u62d6\u653e',
'or click': '\u6216\u70b9\u51fb',
'Manage Images': '\u7ba1\u7406\u56fe\u50cf',
Loading: '\u8f7d\u5165\u4e2d',
Deleting: '\u5220\u9664',
Tags: '\u6807\u7b7e',
'Are you sure? Image will be deleted.':
'\u4f60\u786e\u5b9a\u5417\uff1f\u56fe\u50cf\u5c06\u88ab\u5220\u9664\u3002',
Replace: '\u66f4\u6362',
Uploading: '\u4e0a\u4f20',
'Loading image': '\u5bfc\u5165\u56fe\u50cf',
Display: '\u663e\u793a',
Inline: '\u6392\u961f',
'Break Text': '\u65ad\u5f00\u6587\u672c',
'Alternate Text': '\u5907\u7528\u6587\u672c',
'Change Size': '\u5c3a\u5bf8\u53d8\u5316',
Width: '\u5bbd\u5ea6',
Height: '\u9ad8\u5ea6',
'Something went wrong. Please try again.':
'\u51fa\u4e86\u4e9b\u95ee\u9898\u3002 \u8bf7\u518d\u8bd5\u4e00\u6b21\u3002',
// Video
"Insert Video": "\u63d2\u5165\u89c6\u9891",
"Embedded Code": "\u5d4c\u5165\u5f0f\u4ee3\u7801",
// Video
'Insert Video': '\u63d2\u5165\u89c6\u9891',
'Embedded Code': '\u5d4c\u5165\u5f0f\u4ee3\u7801',
// Tables
"Insert Table": "\u63d2\u5165\u8868\u683c",
"Table Header": "\u8868\u5934",
"Remove Table": "\u5220\u9664\u8868",
"Table Style": "\u8868\u683c\u6837\u5f0f",
"Horizontal Align": "\u6c34\u5e73\u5bf9\u9f50\u65b9\u5f0f",
"Row": "\u884c",
"Insert row above": "\u5728\u4e0a\u65b9\u63d2\u5165",
"Insert row below": "\u5728\u4e0b\u65b9\u63d2\u5165",
"Delete row": "\u5220\u9664\u884c",
"Column": "\u5217",
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
"Delete column": "\u5220\u9664\u5217",
"Cell": "\u5355\u5143\u683c",
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
"Horizontal split": "\u6c34\u5e73\u5206\u5272",
"Vertical split": "\u5782\u76f4\u5206\u5272",
"Cell Background": "\u5355\u5143\u683c\u80cc\u666f",
"Vertical Align": "\u5782\u76f4\u5bf9\u9f50\u65b9\u5f0f",
"Top": "\u6700\u4f73",
"Middle": "\u4e2d\u95f4",
"Bottom": "\u5e95\u90e8",
"Align Top": "\u9876\u90e8\u5bf9\u9f50",
"Align Middle": "\u4e2d\u95f4\u5bf9\u9f50",
"Align Bottom": "\u5e95\u90e8\u5bf9\u9f50",
"Cell Style": "\u5355\u5143\u683c\u6837\u5f0f",
// Tables
'Insert Table': '\u63d2\u5165\u8868\u683c',
'Table Header': '\u8868\u5934',
'Remove Table': '\u5220\u9664\u8868',
'Table Style': '\u8868\u683c\u6837\u5f0f',
'Horizontal Align': '\u6c34\u5e73\u5bf9\u9f50\u65b9\u5f0f',
Row: '\u884c',
'Insert row above': '\u5728\u4e0a\u65b9\u63d2\u5165',
'Insert row below': '\u5728\u4e0b\u65b9\u63d2\u5165',
'Delete row': '\u5220\u9664\u884c',
Column: '\u5217',
'Insert column before': '\u5728\u5de6\u4fa7\u63d2\u5165',
'Insert column after': '\u5728\u53f3\u4fa7\u63d2\u5165',
'Delete column': '\u5220\u9664\u5217',
Cell: '\u5355\u5143\u683c',
'Merge cells': '\u5408\u5e76\u5355\u5143\u683c',
'Horizontal split': '\u6c34\u5e73\u5206\u5272',
'Vertical split': '\u5782\u76f4\u5206\u5272',
'Cell Background': '\u5355\u5143\u683c\u80cc\u666f',
'Vertical Align': '\u5782\u76f4\u5bf9\u9f50\u65b9\u5f0f',
Top: '\u6700\u4f73',
Middle: '\u4e2d\u95f4',
Bottom: '\u5e95\u90e8',
'Align Top': '\u9876\u90e8\u5bf9\u9f50',
'Align Middle': '\u4e2d\u95f4\u5bf9\u9f50',
'Align Bottom': '\u5e95\u90e8\u5bf9\u9f50',
'Cell Style': '\u5355\u5143\u683c\u6837\u5f0f',
// Files
"Upload File": "\u4e0a\u4f20\u6587\u4ef6",
"Drop file": "\u6587\u4ef6\u62d6\u653e",
// Files
'Upload File': '\u4e0a\u4f20\u6587\u4ef6',
'Drop file': '\u6587\u4ef6\u62d6\u653e',
// Emoticons
"Emoticons": "\u8868\u60c5",
"Grinning face": "\u8138\u4e0a\u7b11\u563b\u563b",
"Grinning face with smiling eyes": "",
"Face with tears of joy": "\u7b11\u563b\u563b\u7684\u8138\uff0c\u542b\u7b11\u7684\u773c\u775b",
"Smiling face with open mouth": "\u7b11\u8138\u5f20\u5f00\u5634",
"Smiling face with open mouth and smiling eyes": "\u7b11\u8138\u5f20\u5f00\u5634\u5fae\u7b11\u7684\u773c\u775b",
"Smiling face with open mouth and cold sweat": "\u7b11\u8138\u5f20\u5f00\u5634\uff0c\u4e00\u8eab\u51b7\u6c57",
"Smiling face with open mouth and tightly-closed eyes": "\u7b11\u8138\u5f20\u5f00\u5634\uff0c\u7d27\u7d27\u95ed\u7740\u773c\u775b",
"Smiling face with halo": "\u7b11\u8138\u6655",
"Smiling face with horns": "\u5fae\u7b11\u7684\u8138\u89d2",
"Winking face": "\u7728\u773c\u8868\u60c5",
"Smiling face with smiling eyes": "\u9762\u5e26\u5fae\u7b11\u7684\u773c\u775b",
"Face savoring delicious food": "\u9762\u5bf9\u54c1\u5c1d\u7f8e\u5473\u7684\u98df\u7269",
"Relieved face": "\u9762\u5bf9\u5982\u91ca\u91cd\u8d1f",
"Smiling face with heart-shaped eyes": "\u5fae\u7b11\u7684\u8138\uff0c\u5fc3\u810f\u5f62\u7684\u773c\u775b",
"Smiling face with sunglasses": "\u7b11\u8138\u592a\u9633\u955c",
"Smirking face": "\u9762\u5bf9\u9762\u5e26\u7b11\u5bb9",
"Neutral face": "\u4e2d\u6027\u9762",
"Expressionless face": "\u9762\u65e0\u8868\u60c5",
"Unamused face": "\u4e00\u8138\u4e0d\u5feb\u7684\u8138",
"Face with cold sweat": "\u9762\u5bf9\u51b7\u6c57",
"Pensive face": "\u6c89\u601d\u7684\u8138",
"Confused face": "\u9762\u5bf9\u56f0\u60d1",
"Confounded face": "\u8be5\u6b7b\u7684\u8138",
"Kissing face": "\u9762\u5bf9\u63a5\u543b",
"Face throwing a kiss": "\u9762\u5bf9\u6295\u63b7\u4e00\u4e2a\u543b",
"Kissing face with smiling eyes": "\u63a5\u543b\u8138\uff0c\u542b\u7b11\u7684\u773c\u775b",
"Kissing face with closed eyes": "\u63a5\u543b\u7684\u8138\u95ed\u7740\u773c\u775b",
"Face with stuck out tongue": "\u9762\u5bf9\u4f38\u51fa\u820c\u5934",
"Face with stuck out tongue and winking eye": "\u9762\u5bf9\u4f38\u51fa\u820c\u5934\u548c\u7728\u52a8\u7684\u773c\u775b",
"Face with stuck out tongue and tightly-closed eyes": "\u9762\u5bf9\u4f38\u51fa\u820c\u5934\u548c\u7d27\u95ed\u7684\u773c\u775b",
"Disappointed face": "\u9762\u5bf9\u5931\u671b",
"Worried face": "\u9762\u5bf9\u62c5\u5fc3",
"Angry face": "\u6124\u6012\u7684\u8138",
"Pouting face": "\u9762\u5bf9\u5658\u5634",
"Crying face": "\u54ed\u6ce3\u7684\u8138",
"Persevering face": "\u600e\u5948\u8138",
"Face with look of triumph": "\u9762\u5e26\u770b\u7684\u80dc\u5229",
"Disappointed but relieved face": "\u5931\u671b\uff0c\u4f46\u8138\u4e0a\u91ca\u7136",
"Frowning face with open mouth": "\u9762\u5bf9\u76b1\u7740\u7709\u5934\u5f20\u53e3",
"Anguished face": "\u9762\u5bf9\u75db\u82e6",
"Fearful face": "\u53ef\u6015\u7684\u8138",
"Weary face": "\u9762\u5bf9\u538c\u5026",
"Sleepy face": "\u9762\u5bf9\u56f0",
"Tired face": "\u75b2\u60eb\u7684\u8138",
"Grimacing face": "\u72f0\u72de\u7684\u8138",
"Loudly crying face": "\u5927\u58f0\u54ed\u8138",
"Face with open mouth": "\u9762\u5bf9\u5f20\u5f00\u5634",
"Hushed face": "\u5b89\u9759\u7684\u8138",
"Face with open mouth and cold sweat": "",
"Face screaming in fear": "\u9762\u5bf9\u5f20\u5f00\u5634\uff0c\u4e00\u8eab\u51b7\u6c57",
"Astonished face": "\u9762\u5bf9\u60ca\u8bb6",
"Flushed face": "\u7ea2\u6251\u6251\u7684\u8138\u86cb",
"Sleeping face": "\u719f\u7761\u7684\u8138",
"Dizzy face": "\u9762\u5bf9\u7729",
"Face without mouth": "\u8138\u4e0a\u6ca1\u6709\u5634",
"Face with medical mask": "\u9762\u5bf9\u533b\u7597\u53e3\u7f69",
// Emoticons
Emoticons: '\u8868\u60c5',
'Grinning face': '\u8138\u4e0a\u7b11\u563b\u563b',
'Grinning face with smiling eyes': '',
'Face with tears of joy': '\u7b11\u563b\u563b\u7684\u8138\uff0c\u542b\u7b11\u7684\u773c\u775b',
'Smiling face with open mouth': '\u7b11\u8138\u5f20\u5f00\u5634',
'Smiling face with open mouth and smiling eyes': '\u7b11\u8138\u5f20\u5f00\u5634\u5fae\u7b11\u7684\u773c\u775b',
'Smiling face with open mouth and cold sweat': '\u7b11\u8138\u5f20\u5f00\u5634\uff0c\u4e00\u8eab\u51b7\u6c57',
'Smiling face with open mouth and tightly-closed eyes':
'\u7b11\u8138\u5f20\u5f00\u5634\uff0c\u7d27\u7d27\u95ed\u7740\u773c\u775b',
'Smiling face with halo': '\u7b11\u8138\u6655',
'Smiling face with horns': '\u5fae\u7b11\u7684\u8138\u89d2',
'Winking face': '\u7728\u773c\u8868\u60c5',
'Smiling face with smiling eyes': '\u9762\u5e26\u5fae\u7b11\u7684\u773c\u775b',
'Face savoring delicious food': '\u9762\u5bf9\u54c1\u5c1d\u7f8e\u5473\u7684\u98df\u7269',
'Relieved face': '\u9762\u5bf9\u5982\u91ca\u91cd\u8d1f',
'Smiling face with heart-shaped eyes': '\u5fae\u7b11\u7684\u8138\uff0c\u5fc3\u810f\u5f62\u7684\u773c\u775b',
'Smiling face with sunglasses': '\u7b11\u8138\u592a\u9633\u955c',
'Smirking face': '\u9762\u5bf9\u9762\u5e26\u7b11\u5bb9',
'Neutral face': '\u4e2d\u6027\u9762',
'Expressionless face': '\u9762\u65e0\u8868\u60c5',
'Unamused face': '\u4e00\u8138\u4e0d\u5feb\u7684\u8138',
'Face with cold sweat': '\u9762\u5bf9\u51b7\u6c57',
'Pensive face': '\u6c89\u601d\u7684\u8138',
'Confused face': '\u9762\u5bf9\u56f0\u60d1',
'Confounded face': '\u8be5\u6b7b\u7684\u8138',
'Kissing face': '\u9762\u5bf9\u63a5\u543b',
'Face throwing a kiss': '\u9762\u5bf9\u6295\u63b7\u4e00\u4e2a\u543b',
'Kissing face with smiling eyes': '\u63a5\u543b\u8138\uff0c\u542b\u7b11\u7684\u773c\u775b',
'Kissing face with closed eyes': '\u63a5\u543b\u7684\u8138\u95ed\u7740\u773c\u775b',
'Face with stuck out tongue': '\u9762\u5bf9\u4f38\u51fa\u820c\u5934',
'Face with stuck out tongue and winking eye':
'\u9762\u5bf9\u4f38\u51fa\u820c\u5934\u548c\u7728\u52a8\u7684\u773c\u775b',
'Face with stuck out tongue and tightly-closed eyes':
'\u9762\u5bf9\u4f38\u51fa\u820c\u5934\u548c\u7d27\u95ed\u7684\u773c\u775b',
'Disappointed face': '\u9762\u5bf9\u5931\u671b',
'Worried face': '\u9762\u5bf9\u62c5\u5fc3',
'Angry face': '\u6124\u6012\u7684\u8138',
'Pouting face': '\u9762\u5bf9\u5658\u5634',
'Crying face': '\u54ed\u6ce3\u7684\u8138',
'Persevering face': '\u600e\u5948\u8138',
'Face with look of triumph': '\u9762\u5e26\u770b\u7684\u80dc\u5229',
'Disappointed but relieved face': '\u5931\u671b\uff0c\u4f46\u8138\u4e0a\u91ca\u7136',
'Frowning face with open mouth': '\u9762\u5bf9\u76b1\u7740\u7709\u5934\u5f20\u53e3',
'Anguished face': '\u9762\u5bf9\u75db\u82e6',
'Fearful face': '\u53ef\u6015\u7684\u8138',
'Weary face': '\u9762\u5bf9\u538c\u5026',
'Sleepy face': '\u9762\u5bf9\u56f0',
'Tired face': '\u75b2\u60eb\u7684\u8138',
'Grimacing face': '\u72f0\u72de\u7684\u8138',
'Loudly crying face': '\u5927\u58f0\u54ed\u8138',
'Face with open mouth': '\u9762\u5bf9\u5f20\u5f00\u5634',
'Hushed face': '\u5b89\u9759\u7684\u8138',
'Face with open mouth and cold sweat': '',
'Face screaming in fear': '\u9762\u5bf9\u5f20\u5f00\u5634\uff0c\u4e00\u8eab\u51b7\u6c57',
'Astonished face': '\u9762\u5bf9\u60ca\u8bb6',
'Flushed face': '\u7ea2\u6251\u6251\u7684\u8138\u86cb',
'Sleeping face': '\u719f\u7761\u7684\u8138',
'Dizzy face': '\u9762\u5bf9\u7729',
'Face without mouth': '\u8138\u4e0a\u6ca1\u6709\u5634',
'Face with medical mask': '\u9762\u5bf9\u533b\u7597\u53e3\u7f69',
// Line breaker
"Break": "\u7834",
// Line breaker
Break: '\u7834',
// Math
"Subscript": "\u4e0b\u6807",
"Superscript": "\u4e0a\u6807",
// Math
Subscript: '\u4e0b\u6807',
Superscript: '\u4e0a\u6807',
// Full screen
"Fullscreen": "\u5168\u5c4f",
// Full screen
Fullscreen: '\u5168\u5c4f',
// Horizontal line
"Insert Horizontal Line": "\u63d2\u5165\u6c34\u5e73\u7ebf",
// Horizontal line
'Insert Horizontal Line': '\u63d2\u5165\u6c34\u5e73\u7ebf',
// Clear formatting
"Clear Formatting": "\u683c\u5f0f\u5316\u5220\u9664",
// Clear formatting
'Clear Formatting': '\u683c\u5f0f\u5316\u5220\u9664',
// Undo, redo
"Undo": "\u64a4\u6d88",
"Redo": "\u91cd\u590d",
// Undo, redo
Undo: '\u64a4\u6d88',
Redo: '\u91cd\u590d',
// Select all
"Select All": "\u5168\u9009",
// Select all
'Select All': '\u5168\u9009',
// Code view
"Code View": "\u4ee3\u7801\u89c6\u56fe",
// Code view
'Code View': '\u4ee3\u7801\u89c6\u56fe',
// Quote
"Quote": "\u5f15\u7528",
"Increase": "\u589e\u52a0\u5f15\u7528",
"Decrease": "\u5220\u9664\u5f15\u7528",
// Quote
Quote: '\u5f15\u7528',
Increase: '\u589e\u52a0\u5f15\u7528',
Decrease: '\u5220\u9664\u5f15\u7528',
// Quick Insert
"Quick Insert": "\u5feb\u63d2"
// Quick Insert
'Quick Insert': '\u5feb\u63d2',
},
direction: "ltr"
};
direction: 'ltr',
};

View File

@ -1,25 +1,25 @@
/**
* @file Select Component
* @author FEX
* @file Select
* @description
* @author fex
* @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 Downshift, {ControllerStateAndHelpers} from 'downshift';
import * as cx from 'classnames';
import { closeIcon } from './icons';
import {closeIcon} from './icons';
import * as matchSorter from 'match-sorter';
import { noop, anyChanged } from '../utils/helper';
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 {highlight} from '../renderers/Form/Options';
import {findDOMNode} from 'react-dom';
import {ClassNamesFn, themeable} from '../theme';
export interface Option {
label?: string;
@ -28,9 +28,9 @@ export interface Option {
children?: Options;
visible?: boolean;
hidden?: boolean;
[propName:string]: any;
};
export interface Options extends Array<Option> {};
[propName: string]: any;
}
export interface Options extends Array<Option> {}
export interface OptionProps {
multi?: boolean;
@ -42,11 +42,11 @@ export interface OptionProps {
delimiter?: string;
clearable?: boolean;
placeholder?: string;
};
}
export type OptionValue = string | number | null | undefined | Option;
export function value2array(value:OptionValue | Array<OptionValue>, props:Partial<OptionProps>):Array<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 || ',');
@ -60,9 +60,7 @@ export function value2array(value:OptionValue | Array<OptionValue>, props:Partia
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];
}
@ -71,16 +69,14 @@ export function value2array(value:OptionValue | Array<OptionValue>, props:Partia
return expandedValue ? [expandedValue] : [];
}
export function expandValue(value:OptionValue, props: Partial<OptionProps>):Option | null {
export function expandValue(value: OptionValue, props: Partial<OptionProps>): Option | null {
const valueType = typeof value;
if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') {
return value as Option;
}
let {
options
} = props;
let {options} = props;
if (!options) {
return null;
@ -89,22 +85,22 @@ export function expandValue(value:OptionValue, props: Partial<OptionProps>):Opti
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 {
export function normalizeOptions(options: string | {[propName: string]: string} | Array<string> | Options): Options {
if (typeof options === 'string') {
return options.split(',').map(item => ({
label: item,
value: 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
}))
value: item,
}));
} else if (Array.isArray(options as Options)) {
return (options as Options).map(item => {
let option = {
...item,
value: item && item.value
value: item && item.value,
};
if (typeof option.children !== 'undefined') {
@ -115,8 +111,8 @@ export function normalizeOptions(options:string|{[propName:string]: string} | Ar
});
} else if (isPlainObject(options)) {
return Object.keys(options).map(key => ({
label: (options as {[propName:string]: string})[key] as string,
value: key
label: (options as {[propName: string]: string})[key] as string,
value: key,
}));
}
@ -147,9 +143,9 @@ interface SelectProps {
inline: boolean;
disabled: boolean;
popOverContainer?: any;
promptTextCreator: (label:string) => string;
promptTextCreator: (label: string) => string;
onChange: (value: void | string | Option | Array<Option>) => void;
onNewOptionClick: (value:Option) => void;
onNewOptionClick: (value: Option) => void;
onFocus?: Function;
onBlur?: Function;
}
@ -176,14 +172,14 @@ export class Select extends React.Component<SelectProps, SelectState> {
valueField: 'value',
labelField: 'label',
spinnerClassName: 'fa fa-spinner fa-spin fa-1x fa-fw',
promptTextCreator: (label:string) => `新增:${label}`,
promptTextCreator: (label: string) => `新增:${label}`,
onNewOptionClick: noop,
inline: false
}
inline: false,
};
input:HTMLInputElement;
input: HTMLInputElement;
target: HTMLElement;
constructor(props:SelectProps) {
constructor(props: SelectProps) {
super(props);
this.open = this.open.bind(this);
@ -205,58 +201,62 @@ export class Select extends React.Component<SelectProps, SelectState> {
isFocused: false,
inputValue: '',
highlightedIndex: -1,
selection: value2array(props.value, props)
selection: value2array(props.value, props),
};
}
componentDidMount() {
const {
loadOptions
} = this.props;
const {loadOptions} = this.props;
loadOptions && loadOptions('');
}
componentWillReceiveProps(nextProps:SelectProps) {
componentWillReceiveProps(nextProps: SelectProps) {
const props = this.props;
if (props.value !== nextProps.value || JSON.stringify(props.options) !== JSON.stringify(nextProps.options)) {
this.setState({
selection: value2array(nextProps.value, nextProps)
selection: value2array(nextProps.value, nextProps),
});
}
}
open() {
this.props.disabled || this.setState({
isOpen: true
});
this.props.disabled ||
this.setState({
isOpen: true,
});
}
close() {
this.setState({
isOpen: false
isOpen: false,
});
}
toggle() {
this.props.disabled || this.setState({
isOpen: !this.state.isOpen
});
this.props.disabled ||
this.setState({
isOpen: !this.state.isOpen,
});
}
onFocus(e:any) {
this.props.disabled || this.setState({
isFocused: true,
}, this.focus);
onFocus(e: any) {
this.props.disabled ||
this.setState(
{
isFocused: true,
},
this.focus
);
this.props.onFocus && this.props.onFocus(e);
}
onBlur(e:any) {
onBlur(e: any) {
this.setState({
isFocused: false,
inputValue: ''
inputValue: '',
});
this.props.onBlur && this.props.onBlur(e);
@ -277,11 +277,11 @@ export class Select extends React.Component<SelectProps, SelectState> {
return this.target as HTMLElement;
}
inputRef(ref:HTMLInputElement) {
inputRef(ref: HTMLInputElement) {
this.input = ref;
}
removeItem(index:number, e?: React.MouseEvent<HTMLElement>) {
removeItem(index: number, e?: React.MouseEvent<HTMLElement>) {
let value = this.props.value;
const onChange = this.props.onChange;
@ -291,22 +291,19 @@ export class Select extends React.Component<SelectProps, SelectState> {
onChange(value);
}
handleInputChange(evt:React.ChangeEvent<HTMLInputElement>) {
const {
loadOptions
} = this.props;
handleInputChange(evt: React.ChangeEvent<HTMLInputElement>) {
const {loadOptions} = this.props;
this.setState({
inputValue: evt.currentTarget.value
}, () => loadOptions && loadOptions(this.state.inputValue));
this.setState(
{
inputValue: evt.currentTarget.value,
},
() => loadOptions && loadOptions(this.state.inputValue)
);
}
handleChange(selectItem:any) {
const {
onChange,
multiple,
onNewOptionClick,
} = this.props;
handleChange(selectItem: any) {
const {onChange, multiple, onNewOptionClick} = this.props;
let selection = this.state.selection;
@ -330,7 +327,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
}
handleStateChange(changes: any) {
let update:any = {};
let update: any = {};
const loadOptions = this.props.loadOptions;
let doLoad = false;
@ -349,46 +346,35 @@ export class Select extends React.Component<SelectProps, SelectState> {
...update,
inputValue: '',
isOpen: false,
isFocused: false
}
isFocused: false,
};
doLoad = true;
break;
case Downshift.stateChangeTypes.changeInput:
update.highlightedIndex = 0
update.highlightedIndex = 0;
break;
}
if (Object.keys(update).length) {
this.setState(update, doLoad && loadOptions ? () => loadOptions('') : undefined);
}
}
handleKeyPress(e:React.KeyboardEvent) {
handleKeyPress(e: React.KeyboardEvent) {
if (e.key === ' ') {
this.toggle();
}
}
clearValue(e:React.MouseEvent<any>) {
clearValue(e: React.MouseEvent<any>) {
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;
renderValue({inputValue, isOpen}: ControllerStateAndHelpers<any>) {
const {multiple, placeholder, classPrefix: ns, labelField, searchable, creatable} = this.props;
const selection = this.state.selection;
@ -397,30 +383,30 @@ export class Select extends React.Component<SelectProps, SelectState> {
}
if (!selection.length) {
return creatable && inputValue ? null : (
<div key="placeholder" className={`${ns}Select-placeholder`}>{placeholder}</div>
return creatable && inputValue ? null : (
<div key="placeholder" className={`${ns}Select-placeholder`}>
{placeholder}
</div>
);
}
return selection.map((item, index) => multiple ? (
<div className={`${ns}Select-value`} key={index}>
<span className={`${ns}Select-valueIcon`} onClick={this.removeItem.bind(this, index)}>×</span>
<span className={`${ns}Select-valueLabel`}>{item[labelField||'label']}</span>
</div>
) : inputValue && isOpen ? null : (
<div className={`${ns}Select-value`} key={index}>
{item.label}
</div>
));
return selection.map((item, index) =>
multiple ? (
<div className={`${ns}Select-value`} key={index}>
<span className={`${ns}Select-valueIcon`} onClick={this.removeItem.bind(this, index)}>
×
</span>
<span className={`${ns}Select-valueLabel`}>{item[labelField || 'label']}</span>
</div>
) : inputValue && isOpen ? null : (
<div className={`${ns}Select-value`} key={index}>
{item.label}
</div>
)
);
}
renderOuter({
selectedItem,
getItemProps,
highlightedIndex,
inputValue,
isOpen
}:ControllerStateAndHelpers<any>) {
renderOuter({selectedItem, getItemProps, highlightedIndex, inputValue, isOpen}: ControllerStateAndHelpers<any>) {
const {
popOverContainer,
options,
@ -431,52 +417,64 @@ export class Select extends React.Component<SelectProps, SelectState> {
creatable,
promptTextCreator,
multiple,
classnames: cx
classnames: cx,
} = this.props;
let filtedOptions:Array<Option> = inputValue && isOpen && !loadOptions ? matchSorter(options, inputValue, {keys: [labelField || 'label', valueField || 'value']}) : options.concat();
let filtedOptions: Array<Option> =
inputValue && isOpen && !loadOptions
? matchSorter(options, inputValue, {
keys: [labelField || 'label', valueField || 'value'],
})
: options.concat();
if (multiple) {
filtedOptions = filtedOptions.filter((option:any) => !~selectedItem.indexOf(option));
filtedOptions = filtedOptions.filter((option: any) => !~selectedItem.indexOf(option));
}
if (inputValue && creatable
&& (
!filtedOptions.length
|| isOpen && loadOptions
&& !matchSorter(options, inputValue, {
keys: [labelField || 'label',
valueField || 'value']
}).length
)) {
if (
inputValue &&
creatable &&
(!filtedOptions.length ||
(isOpen &&
loadOptions &&
!matchSorter(options, inputValue, {
keys: [labelField || 'label', valueField || 'value'],
}).length))
) {
filtedOptions.push({
[labelField]: inputValue,
[valueField]: inputValue,
isNew: true
isNew: true,
});
}
const menu = (
<div className={cx('Select-menu')}>
{filtedOptions.length ? filtedOptions.map((item, index) => (
<div
{...getItemProps({
key: index,
index,
item,
disabled: item.disabled
})}
className={cx(`Select-option`, {
'is-disabled': item.disabled,
'is-highlight': highlightedIndex === index,
'is-active': selectedItem === item || Array.isArray(selectedItem) && ~selectedItem.indexOf(item)
})}
>
{item.isNew ? (
promptTextCreator(item.label as string)
) : item.disabled ? item[labelField] : highlight(item[labelField], inputValue as string, cx('Select-option-hl'))}
</div>
)) : (
{filtedOptions.length ? (
filtedOptions.map((item, index) => (
<div
{...getItemProps({
key: index,
index,
item,
disabled: item.disabled,
})}
className={cx(`Select-option`, {
'is-disabled': item.disabled,
'is-highlight': highlightedIndex === index,
'is-active':
selectedItem === item ||
(Array.isArray(selectedItem) && ~selectedItem.indexOf(item)),
})}
>
{item.isNew
? promptTextCreator(item.label as string)
: item.disabled
? item[labelField]
: highlight(item[labelField], inputValue as string, cx('Select-option-hl'))}
</div>
))
) : (
<div className={cx('Select-option Select-option--placeholder')}>{noResultsText}</div>
)}
</div>
@ -484,13 +482,8 @@ export class Select extends React.Component<SelectProps, SelectState> {
if (popOverContainer) {
return (
<Overlay
container={popOverContainer}
placement="left-bottom-left-top"
target={this.getTarget}
show
>
<PopOver
<Overlay container={popOverContainer} placement="left-bottom-left-top" target={this.getTarget} show>
<PopOver
className={cx('Select-popover')}
style={{width: this.target ? this.target.offsetWidth : 'auto'}}
>
@ -499,13 +492,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
</Overlay>
);
} else {
return (
<div
className={cx('Select-menuOuter')}
>
{menu}
</div>
);
return <div className={cx('Select-menuOuter')}>{menu}</div>;
}
}
@ -536,64 +523,72 @@ export class Select extends React.Component<SelectProps, SelectState> {
onChange={this.handleChange}
onStateChange={this.handleStateChange}
onOuterClick={this.close}
itemToString={(item) => item ? item[labelField] : ''}
>{(options:ControllerStateAndHelpers<any>) => {
const {
isOpen,
getInputProps
} = options;
return (
<div
tabIndex={searchable || disabled ? -1 : 0}
onKeyPress={this.handleKeyPress}
onClick={this.toggle}
onFocus={this.onFocus}
onBlur={this.onBlur}
className={cx(`Select`, {
[`Select--multi`]: multiple,
[`Select--inline`]: inline,
[`Select--searchable`]: searchable,
'is-opened': isOpen,
'is-focused': this.state.isFocused,
'is-disabled': disabled
}, className)}
>
<div className={cx(`Select-valueWrap`)}>
{this.renderValue(options)}
{searchable ? (
<input
{...getInputProps({
className: cx(`Select-input`),
onFocus: this.onFocus,
onBlur: this.onBlur,
onKeyDown: (event) => {
if (event.key === 'Backspace' && !inputValue) {
this.removeItem(value.length - 1);
}
},
onChange: this.handleInputChange,
ref: this.inputRef
})}
/>
itemToString={item => (item ? item[labelField] : '')}
>
{(options: ControllerStateAndHelpers<any>) => {
const {isOpen, getInputProps} = options;
return (
<div
tabIndex={searchable || disabled ? -1 : 0}
onKeyPress={this.handleKeyPress}
onClick={this.toggle}
onFocus={this.onFocus}
onBlur={this.onBlur}
className={cx(
`Select`,
{
[`Select--multi`]: multiple,
[`Select--inline`]: inline,
[`Select--searchable`]: searchable,
'is-opened': isOpen,
'is-focused': this.state.isFocused,
'is-disabled': disabled,
},
className
)}
>
<div className={cx(`Select-valueWrap`)}>
{this.renderValue(options)}
{searchable ? (
<input
{...getInputProps({
className: cx(`Select-input`),
onFocus: this.onFocus,
onBlur: this.onBlur,
onKeyDown: event => {
if (event.key === 'Backspace' && !inputValue) {
this.removeItem(value.length - 1);
}
},
onChange: this.handleInputChange,
ref: this.inputRef,
})}
/>
) : null}
</div>
{clearable && !disabled && value && value.length ? (
<a onClick={this.clearValue} className={cx('Select-clear')}>
{closeIcon}
</a>
) : null}
{loading ? (
<span className={cx('Select-spinner')}>
<i className={spinnerClassName} />
</span>
) : null}
<span className={cx('Select-arrow')} />
{isOpen ? this.renderOuter(options) : null}
</div>
{clearable && !disabled && value && value.length ? (<a onClick={this.clearValue} className={cx('Select-clear')}>{closeIcon}</a>) : null}
{loading ? (
<span className={cx('Select-spinner')}>
<i className={spinnerClassName} />
</span>
) : null}
<span className={cx('Select-arrow')}></span>
{isOpen ? this.renderOuter(options) : null}
</div>
);
}}</Downshift>
);
}}
</Downshift>
);
}
}
export default themeable(uncontrollable(Select, {
value: 'onChange'
}));
export default themeable(
uncontrollable(Select, {
value: 'onChange',
})
);

View File

@ -1,10 +1,14 @@
/**
* @file Spinner
* @description
* @author fex
* @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 {Renderer, RendererProps} from '../factory';
import {ClassNamesFn, themeable} from '../theme';
import {classPrefix, classnames} from '../themes/default';
interface SpinnerProps extends RendererProps {
overlay: boolean;
@ -13,44 +17,34 @@ interface SpinnerProps extends RendererProps {
size: string;
classPrefix: string;
classnames: ClassNamesFn;
};
}
export class Spinner extends React.Component<SpinnerProps, object> {
static defaultProps= {
static defaultProps = {
overlay: false,
spinnerClassName: '',
mode: '',
size: ''
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 className={cx(`${ns}Spinner`, spinnerClassName, {
[`Spinner--${mode}`]: !!mode,
[`Spinner--${size}`]: !!size
})}>
</div>
<div
className={cx(`${ns}Spinner`, spinnerClassName, {
[`Spinner--${mode}`]: !!mode,
[`Spinner--${size}`]: !!size,
})}
/>
);
if (overlay) {
return (
<div className={cx(`Spinner-overlay`)}>
{spinner}
</div>
);
return <div className={cx(`Spinner-overlay`)}>{spinner}</div>;
}
return spinner;
}
}
export default themeable(Spinner);
export default themeable(Spinner);

View File

@ -1,36 +1,37 @@
/**
* @file switch组件
* @file Switch
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { ClassNamesFn, themeable } from '../theme';
import { classPrefix, classnames } from '../themes/default';
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'
large: 'i-switch-lg',
};
const levelMap = {
info: 'bg-info',
primary: 'bg-primary',
danger: 'bg-danger'
danger: 'bg-danger',
};
interface SwitchProps {
id?: string;
size?: 'md' | 'lg' | 'middle' | 'large',
level?: 'info' | 'primary' | 'danger',
className?: string,
size?: 'md' | 'lg' | 'middle' | 'large';
level?: 'info' | 'primary' | 'danger';
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
onChange?: (checked:boolean) => void,
value?: any,
inline?: boolean,
onChange?: (checked: boolean) => void;
value?: any;
inline?: boolean;
trueValue?: any;
falseValue?: any;
disabled?: boolean;
@ -41,21 +42,17 @@ interface SwitchProps {
export class Switch extends React.PureComponent<SwitchProps, any> {
static defaultProps = {
trueValue: true,
falseValue: false
falseValue: false,
};
constructor(props:SwitchProps) {
constructor(props: SwitchProps) {
super(props);
this.hanldeCheck = this.hanldeCheck.bind(this);
}
hanldeCheck(e:React.ChangeEvent<HTMLInputElement>) {
const {
trueValue,
falseValue,
onChange
} = this.props;
hanldeCheck(e: React.ChangeEvent<HTMLInputElement>) {
const {trueValue, falseValue, onChange} = this.props;
if (!onChange) {
return;
@ -82,26 +79,31 @@ export class Switch extends React.PureComponent<SwitchProps, any> {
...rest
} = this.props;
className = (className ? className : '')
+ (size && sizeMap[size] ? ` ${sizeMap[size]}` : '')
+ (level && levelMap[level] ? ` ${levelMap[level]}` : '');
className =
(className ? className : '') +
(size && sizeMap[size] ? ` ${sizeMap[size]}` : '') +
(level && levelMap[level] ? ` ${levelMap[level]}` : '');
return (
<label
className={cx(`Switch`, disabled ? 'is-disabled' : '', className)}
>
<label className={cx(`Switch`, disabled ? 'is-disabled' : '', className)}>
<input
type="checkbox"
checked={typeof checked !== 'undefined' ? checked : typeof value === 'undefined' ? false : value == trueValue}
checked={
typeof checked !== 'undefined'
? checked
: typeof value === 'undefined'
? false
: value == trueValue
}
onChange={this.hanldeCheck}
disabled={disabled}
readOnly={readOnly}
{...rest}
/>
/>
<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;
export default Textarea;

View File

@ -1,17 +1,16 @@
/**
* @file
*
*
* @file TitleBar
* @description
* @author fex
* @param
* title
* titleClassName bg-light lter b-b
* right , hbox
*
*
* @author fex
*/
import * as React from 'react';
import { classPrefix, classnames } from '../themes/default';
import { ClassNamesFn, themeable } from '../theme';
import {classPrefix, classnames} from '../themes/default';
import {ClassNamesFn, themeable} from '../theme';
interface TitleBarProps {
className?: string;
@ -23,27 +22,17 @@ interface TitleBarProps {
}
export class TitleBar extends React.PureComponent<TitleBarProps, any> {
static defaultProps = {
className: 'bg-light lter b-b',
title: '标题',
titleClassName: 'm-n font-thin h3',
right: false
right: false,
};
render() : JSX.Element {
const {
className,
title,
titleClassName,
right
} = this.props;
render(): JSX.Element {
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;
@ -55,17 +44,11 @@ export class TitleBar extends React.PureComponent<TitleBarProps, any> {
</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

@ -1,18 +1,15 @@
/**
* @file toast提示组件, App级别只需要一个ToastComponent
* @file Toast
* @description toast提示组件, App级别只需要一个ToastComponent
* @author fex
*/
import Transition, {
ENTERED,
ENTERING,
EXITING,
EXITED
} from 'react-transition-group/Transition';
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 {uuid, autobind} from '../utils/helper';
import {ClassNamesFn, themeable} from '../theme';
const fadeStyles: {
[propName: string]: string;
@ -20,11 +17,15 @@ const fadeStyles: {
[ENTERING]: 'in',
[ENTERED]: '',
[EXITING]: 'out',
[EXITED]: 'hidden'
[EXITED]: 'hidden',
};
let toastRef: any = null;
let config: {closeButton?: boolean; timeOut?: number; extendedTimeOut?: number;} = {};
let config: {
closeButton?: boolean;
timeOut?: number;
extendedTimeOut?: number;
} = {};
const show = (content: string, title: string = '', conf: any = {}, method: string) => {
if (!toastRef || !toastRef[method]) {
@ -48,36 +49,32 @@ interface Item {
body: string;
level: 'info' | 'success' | 'error' | 'warning';
id: string;
};
}
interface ToastComponentState {
items: Array<Item>;
}
export class ToastComponent extends React.PureComponent<ToastComponentProps, ToastComponentState> {
export class ToastComponent extends React.PureComponent<ToastComponentProps, ToastComponentState> {
static defaultProps = {
position: 'top-right',
closeButton: false,
timeOut: 5000,
extendedTimeOut: 3000
extendedTimeOut: 3000,
};
// 当前ToastComponent是否真正render了
hasRendered = false;
state:ToastComponentState = {
items: []
state: ToastComponentState = {
items: [],
};
componentWillMount() {
const {
closeButton,
timeOut,
extendedTimeOut
} = this.props;
const {closeButton, timeOut, extendedTimeOut} = this.props;
config = {
closeButton,
timeOut,
extendedTimeOut
extendedTimeOut,
};
}
@ -89,7 +86,7 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
componentWillUnmount() {
if (this.hasRendered) {
toastRef = null;
}
}
}
notifiy(level: string, content: string, title?: string, config?: any) {
@ -99,10 +96,10 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
body: content,
level,
...config,
id: uuid()
id: uuid(),
});
this.setState({
items
items,
});
}
@ -126,11 +123,11 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
this.notifiy('warning', content, title, config);
}
handleDismissed(index:number) {
handleDismissed(index: number) {
const items = this.state.items.concat();
items.splice(index, 1);
this.setState({
items: items
items: items,
});
}
@ -139,18 +136,18 @@ export class ToastComponent extends React.PureComponent<ToastComponentProps, Toa
return null;
}
const {
classPrefix: ns,
className,
timeOut,
position
} = this.props;
const {classPrefix: ns, className, timeOut, position} = this.props;
const items = this.state.items;
return (
<div className={cx(`${ns}Toast-wrap ${ns}Toast-wrap--${position.replace(/\-(\w)/g, (_, l) => l.toUpperCase())}`, className)}>
<div
className={cx(
`${ns}Toast-wrap ${ns}Toast-wrap--${position.replace(/\-(\w)/g, (_, l) => l.toUpperCase())}`,
className
)}
>
{items.map((item, index) => (
<ToastMessage
<ToastMessage
key={item.id}
classPrefix={ns}
title={item.title}
@ -180,7 +177,7 @@ interface ToastMessageProps {
interface ToastMessageState {
visible: boolean;
};
}
export class ToastMessage extends React.Component<ToastMessageProps> {
static defaultProps = {
@ -188,14 +185,14 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
classPrefix: '',
position: 'top-right',
allowHtml: true,
level: 'info'
level: 'info',
};
state = {
visible: false
visible: false,
};
content:React.RefObject<HTMLDivElement>;
content: React.RefObject<HTMLDivElement>;
timer: NodeJS.Timeout;
constructor(props: ToastMessageProps) {
super(props);
@ -213,7 +210,7 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
componentDidMount() {
this.setState({
visible: true
visible: true,
});
}
@ -224,7 +221,7 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
handleMouseLeave() {
this.handleEntered();
}
handleEntered() {
const timeOut = this.props.timeOut;
this.timer = setTimeout(this.close, timeOut);
@ -233,20 +230,12 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
close() {
clearTimeout(this.timer);
this.setState({
visible: false
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
@ -266,22 +255,20 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
}
return (
<div
<div
ref={this.content}
className={cx(`${ns}Toast ${ns}Toast--${level}`, fadeStyles[status])}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onClick={this.close}
>
{title ? (<div className={`${ns}Toast-title`}>{title}</div>) : null}
<div className={`${ns}Toast-body`}>
{allowHtml ? (<Html html={body} />) : body}
</div>
{title ? <div className={`${ns}Toast-title`}>{title}</div> : null}
<div className={`${ns}Toast-body`}>{allowHtml ? <Html html={body} /> : body}</div>
</div>
)
);
}}
</Transition>
)
);
}
}
@ -290,6 +277,5 @@ export const toast = {
success: (content: string, title?: string, conf?: any) => show(content, title, conf, 'success'),
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')
warning: (content: string, title?: string, conf?: any) => show(content, title, conf, 'warning'),
};

View File

@ -1,7 +1,13 @@
/**
* @file Tooltip
* @description
* @author fex
*/
import * as React from 'react';
import * as cx from 'classnames';
import { classPrefix, classnames } from '../themes/default';
import { ClassNamesFn, themeable } from '../theme';
import {classPrefix, classnames} from '../themes/default';
import {ClassNamesFn, themeable} from '../theme';
interface TooltipProps extends React.HTMLProps<HTMLDivElement> {
title?: string;
@ -12,13 +18,12 @@ interface TooltipProps extends React.HTMLProps<HTMLDivElement> {
style?: any;
arrowProps?: any;
placement?: string;
[propName:string]: any;
};
[propName: string]: any;
}
export class Tooltip extends React.Component<TooltipProps> {
static defaultProps = {
className: ''
className: '',
};
render() {
@ -39,22 +44,18 @@ export class Tooltip extends React.Component<TooltipProps> {
} = this.props;
return (
<div
<div
{...rest}
className={cx(`Tooltip`, placement ? `Tooltip--${placement}` : '', className)}
style={style}
role="tooltip"
>
<div className={cx(`Tooltip-arrow`)} {...arrowProps} />
{title ? (
<div className={cx('Tooltip-title')}>{title}</div>
) : null}
<div className={cx('Tooltip-body')}>
{children}
</div>
{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

@ -1,30 +1,28 @@
/**
* @file tooltip
* @file TooltipWrapper
* @description
* @author fex
*/
/* eslint fecs-indent: [0, "space", 2, 2] */
import React = require('react');
import {
Overlay
} from 'react-overlays';
import {Overlay} from 'react-overlays';
import Html from './Html';
import uncontrollable = require('uncontrollable');
import { findDOMNode } from 'react-dom';
import {findDOMNode} from 'react-dom';
import Tooltip from './Tooltip';
import { ClassNamesFn, themeable } from '../theme';
import {ClassNamesFn, themeable} from '../theme';
export interface TooltipObject {
title?: string;
content?: string;
};
}
export type Trigger = 'hover' | 'click' | 'focus';
export interface TooltipWrapperProps {
classPrefix: string;
classnames: ClassNamesFn;
placement: "top" | "right" | "bottom" | "left";
placement: 'top' | 'right' | 'bottom' | 'left';
tooltip?: string | TooltipObject;
container?: React.ReactNode;
trigger: Trigger | Array<Trigger>;
@ -39,11 +37,11 @@ interface TooltipWrapperState {
}
export class TooltipWrapper extends React.Component<TooltipWrapperProps, TooltipWrapperState> {
static defaultProps:Pick<TooltipWrapperProps, 'placement' | 'trigger' | 'rootClose' | 'delay'> = {
static defaultProps: Pick<TooltipWrapperProps, 'placement' | 'trigger' | 'rootClose' | 'delay'> = {
placement: 'top',
trigger: ['hover', 'focus'],
rootClose: false,
delay: 200
delay: 200,
};
target: HTMLElement;
@ -64,7 +62,7 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
this.handleMouseOut = this.handleMouseOut.bind(this);
this.state = {
show: false
show: false,
};
}
@ -76,19 +74,19 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
return this.target ? findDOMNode(this.target) : null;
}
targetRef(ref:HTMLElement) {
targetRef(ref: HTMLElement) {
this.target = ref;
}
show() {
this.setState({
show: true
show: true,
});
}
hide() {
this.setState({
show: false
show: false,
});
}
@ -109,58 +107,48 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
handleHide() {
clearTimeout(this.timer);
const {
delay
} = this.props;
const {delay} = this.props;
this.timer = setTimeout(this.hide, delay);
}
handleFocus(e:any) {
const { onFocus } = this.getChildProps();
handleFocus(e: any) {
const {onFocus} = this.getChildProps();
this.handleShow();
onFocus && onFocus(e);
}
handleBlur(e:any) {
const { onBlur } = this.getChildProps();
handleBlur(e: any) {
const {onBlur} = this.getChildProps();
this.handleHide();
onBlur && onBlur(e);
}
handleMouseOver(e:any) {
handleMouseOver(e: any) {
this.handleMouseOverOut(this.handleShow, e, 'fromElement');
}
handleMouseOut(e:any) {
handleMouseOut(e: any) {
this.handleMouseOverOut(this.handleHide, e, 'toElement');
}
handleMouseOverOut(handler:Function, e:React.MouseEvent<HTMLElement>, relatedNative:string) {
handleMouseOverOut(handler: Function, e: React.MouseEvent<HTMLElement>, relatedNative: string) {
const target = e.currentTarget;
const related:any = e.relatedTarget || (e as any).nativeEvent[relatedNative];
const related: any = e.relatedTarget || (e as any).nativeEvent[relatedNative];
if ((!related || related !== target) && !target.contains(related)) {
handler(e);
}
}
handleClick(e:any) {
const { onClick } = this.getChildProps();
handleClick(e: any) {
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);
@ -168,9 +156,9 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
return child;
}
const childProps:any = {
const childProps: any = {
ref: this.targetRef,
key: 'target'
key: 'target',
};
const triggers = Array.isArray(trigger) ? trigger.concat() : [trigger];
@ -201,18 +189,16 @@ export class TooltipWrapper extends React.Component<TooltipWrapperProps, Tooltip
placement={placement}
container={container}
>
<Tooltip
title={typeof tooltip !== 'string' ? tooltip.title : undefined}
>
<Html
html={typeof tooltip === 'string' ? tooltip : tooltip.content}
/>
<Tooltip title={typeof tooltip !== 'string' ? tooltip.title : undefined}>
<Html html={typeof tooltip === 'string' ? tooltip : tooltip.content} />
</Tooltip>
</Overlay>
</Overlay>,
];
}
}
export default themeable(uncontrollable(TooltipWrapper, {
show: 'onVisibleChange'
}));
export default themeable(
uncontrollable(TooltipWrapper, {
show: 'onVisibleChange',
})
);

View File

@ -1,18 +1,14 @@
/**
* @file
* @file Tree
* @description
* @author fex
*/
/* eslint fecs-indent: [2, "space", 2, 0] */
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 {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;
@ -59,7 +55,7 @@ interface TreeSelectorProps {
interface TreeSelectorState {
value: Array<any>;
unfolded: { [propName: string]: string };
unfolded: {[propName: string]: string};
}
export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelectorState> {
@ -85,7 +81,7 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
rootLabel: '顶级',
rootValue: 0,
cascade: false,
selfDisabledAffectChildren: true
selfDisabledAffectChildren: true,
};
componentWillMount() {
@ -97,7 +93,6 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
const props = this.props;
this.setState({
value: value2array(props.value, {
joinValues: props.joinValues,
@ -105,9 +100,9 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
multiple: props.multiple,
delimiter: props.delimiter,
valueField: props.valueField,
options: props.data
options: props.data,
}),
unfolded: this.syncUnFolded(props)
unfolded: this.syncUnFolded(props),
});
}
@ -121,12 +116,12 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
multiple: nextProps.multiple,
delimiter: nextProps.delimiter,
valueField: nextProps.valueField,
options: nextProps.data
options: nextProps.data,
});
}
if (this.props.data !== nextProps.data) {
toUpdate.unfolded = this.syncUnFolded(nextProps)
toUpdate.unfolded = this.syncUnFolded(nextProps);
}
this.setState(toUpdate);
@ -134,11 +129,8 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
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) {
@ -165,37 +157,35 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
this.setState({
unfolded: {
...this.state.unfolded,
[node[this.props.valueField as string]]: !this.state.unfolded[node[this.props.valueField as string]]
}
[node[this.props.valueField as string]]: !this.state.unfolded[node[this.props.valueField as string]],
},
});
}
clearSelect() {
this.setState({
value: []
}, () => {
const {
joinValues,
rootValue,
onChange
} = this.props;
this.setState(
{
value: [],
},
() => {
const {joinValues, rootValue, onChange} = this.props;
onChange(joinValues ? rootValue : []);
});
onChange(joinValues ? rootValue : []);
}
);
}
handleSelect(node: any, value?: any) {
this.setState({
value: [node]
}, () => {
const {
joinValues,
valueField,
onChange
} = this.props;
this.setState(
{
value: [node],
},
() => {
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) {
@ -263,22 +253,29 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
}
}
this.setState({
value
}, () => {
const {
joinValues,
extractValue,
valueField,
delimiter,
onChange
} = this.props;
this.setState(
{
value,
},
() => {
const {joinValues, extractValue, valueField, delimiter, onChange} = this.props;
onChange(joinValues ? value.map(item => item[valueField as string]).join(delimiter) : extractValue ? value.map(item => item[valueField as string]) : value);
});
onChange(
joinValues
? value.map(item => item[valueField as string]).join(delimiter)
: extractValue
? value.map(item => item[valueField as string])
: value
);
}
);
}
renderList(list: Options, value: Option[], uncheckable: boolean): { dom: Array<JSX.Element | null>; childrenChecked: number } {
renderList(
list: Options,
value: Option[],
uncheckable: boolean
): {dom: Array<JSX.Element | null>; childrenChecked: number} {
const {
itemClassName,
showIcon,
@ -310,7 +307,13 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
let childrenItems = null;
let tmpChildrenChecked = false;
if (item.children && item.children.length) {
childrenItems = this.renderList(item.children, value, cascade ? false : uncheckable || (selfDisabledAffectChildren ? selfDisabled : false) || multiple && checked);
childrenItems = this.renderList(
item.children,
value,
cascade
? false
: uncheckable || (selfDisabledAffectChildren ? selfDisabled : false) || (multiple && checked)
);
tmpChildrenChecked = !!childrenItems.childrenChecked;
if (!selfChecked && onlyChildren && item.children.length === childrenItems.childrenChecked) {
selfChecked = true;
@ -324,7 +327,7 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
let nodeDisabled = !!uncheckable || !!disabled || selfDisabled;
const checkbox: JSX.Element|null = (multiple ? (
const checkbox: JSX.Element | null = multiple ? (
<label className={cx(`Checkbox Checkbox--checkbox Checkbox--sm`)}>
<input
type="checkbox"
@ -334,119 +337,117 @@ export class TreeSelector extends React.Component<TreeSelectorProps, TreeSelecto
/>
<i />
</label>
) : (
showRadio ? (
<label className={cx(`Checkbox Checkbox--radio Checkbox--sm`)}>
<input
type="radio"
disabled={nodeDisabled}
checked={checked}
onChange={() => this.handleSelect(item)}
/>
<i />
</label>
) : null
)
);
) : showRadio ? (
<label className={cx(`Checkbox Checkbox--radio Checkbox--sm`)}>
<input
type="radio"
disabled={nodeDisabled}
checked={checked}
onChange={() => this.handleSelect(item)}
/>
<i />
</label>
) : null;
const isLeaf = !item.children || !item.children.length;
return (
<li key={key} className={cx(`Tree-item ${itemClassName || ''}`, {'Tree-item--isLeaf': isLeaf})}>
<li
key={key}
className={cx(`Tree-item ${itemClassName || ''}`, {
'Tree-item--isLeaf': isLeaf,
})}
>
<a>
{!isLeaf ? (
<i
onClick={() => this.toggleUnfolded(item)}
className={cx("Tree-itemArrow", {
'is-folded': !this.state.unfolded[item[valueField]]
className={cx('Tree-itemArrow', {
'is-folded': !this.state.unfolded[item[valueField]],
})}
/>
) : null}
{showIcon ? (
<i className={cx(`Tree-itemIcon ${item[iconField] || (childrenItems ? 'Tree-folderIcon' : 'Tree-leafIcon')}`)} />
<i
className={cx(
`Tree-itemIcon ${item[iconField] ||
(childrenItems ? 'Tree-folderIcon' : 'Tree-leafIcon')}`
)}
/>
) : null}
{checkbox}
<span
className={cx('Tree-itemText', {
'is-children-checked': multiple && !cascade && tmpChildrenChecked && !nodeDisabled,
'is-checked': checked,
'is-disabled': nodeDisabled
'is-disabled': nodeDisabled,
})}
onClick={() => !nodeDisabled && (multiple ? this.handleCheck(item, !selfChecked) : this.handleSelect(item))}
onClick={() =>
!nodeDisabled &&
(multiple ? this.handleCheck(item, !selfChecked) : this.handleSelect(item))
}
>
{highlightTxt ? highlight(item[nameField], highlightTxt) : item[nameField]}
</span>
</a>
{
childrenItems ? (
<ul
className={cx('Tree-sublist', {
'is-folded': !this.state.unfolded[item[valueField]]
})}
>
{childrenItems}
</ul>
) : null
}
{childrenItems ? (
<ul
className={cx('Tree-sublist', {
'is-folded': !this.state.unfolded[item[valueField]],
})}
>
{childrenItems}
</ul>
) : null}
</li>
);
});
return {
dom: ret,
childrenChecked
childrenChecked,
};
}
render() {
const {
className,
placeholder,
hideRoot,
rootLabel,
showIcon,
classnames: cx,
} = this.props;
const {className, placeholder, hideRoot, rootLabel, showIcon, classnames: cx} = this.props;
let data = this.props.data;
const value = this.state.value;
return (
<div className={cx(`Tree ${className || ''}`)}>
{data && data.length ? (
<ul className={cx("Tree-list")}>
{hideRoot ? this.renderList(data, value, false).dom : (
<li className={cx("Tree-item Tree-rootItem")}>
<ul className={cx('Tree-list')}>
{hideRoot ? (
this.renderList(data, value, false).dom
) : (
<li className={cx('Tree-item Tree-rootItem')}>
<a>
{showIcon ? (
<i className={cx('Tree-itemIcon Tree-rootIcon')} />
) : null}
{showIcon ? <i className={cx('Tree-itemIcon Tree-rootIcon')} /> : null}
<label
className={cx('Tree-itemLabel', {
'is-checked': !value || !value.length,
})}
>
<span
className={cx("Tree-itemText")}
onClick={this.clearSelect}
>
<span className={cx('Tree-itemText')} onClick={this.clearSelect}>
{rootLabel}
</span>
</label>
</a>
<ul className={cx("Tree-sublist")}>{this.renderList(data, value, false).dom}</ul>
<ul className={cx('Tree-sublist')}>{this.renderList(data, value, false).dom}</ul>
</li>
)}
</ul>
) : (
<div className={cx("Tree-placeholder")}>{placeholder}</div>
)}
<div className={cx('Tree-placeholder')}>{placeholder}</div>
)}
</div>
);
}
}
export default themeable(TreeSelector);
export default themeable(TreeSelector);

View File

@ -1,9 +1,77 @@
/**
* @file Icon
* @description
* @author fex
*/
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 d="M967.81435 106.836237 917.16274 56.18565 512 461.34839 106.836237 56.18565 56.184627 106.836237 461.34839 512 56.184627 917.163763 106.836237 967.815373 512 562.65161 917.16274 967.815373 967.81435 917.163763 562.650587 512Z" p-id="1464" data-spm-anchor-id="a313x.7781069.0.i0"></path></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"></path></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"></path></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"></path></svg>)
export const volumeIcon = (<svg className="icon" viewBox="0 0 1024 1024" version="1.1"><path d="M536.319574 5.11991a63.99888 63.99888 0 0 0-69.758779 13.439765L229.764939 255.99552H64.00784a63.99888 63.99888 0 0 0-63.99888 63.99888v383.99328a63.99888 63.99888 0 0 0 63.99888 63.99888h165.757099l236.795856 237.435845A63.99888 63.99888 0 0 0 512 1023.98208a53.759059 53.759059 0 0 0 24.319574-5.11991A63.99888 63.99888 0 0 0 575.99888 959.9832V63.99888a63.99888 63.99888 0 0 0-39.679306-58.87897zM192.0056 639.9888H128.00672V383.99328h63.99888z m255.99552 165.757099l-127.99776-127.99776V346.233941l127.99776-127.99776zM879.353571 148.477402a63.99888 63.99888 0 0 0-94.718342 87.038476 402.552955 402.552955 0 0 1 0 552.950324A63.99888 63.99888 0 0 0 831.9944 895.98432a63.99888 63.99888 0 0 0 46.719183-20.479641 531.830693 531.830693 0 0 0 0-727.027277z" fill="#606670" p-id="3605"></path><path d="M751.9958 277.11515a63.99888 63.99888 0 0 0-95.99832 85.7585A218.236181 218.236181 0 0 1 703.99664 511.99104a221.436125 221.436125 0 0 1-47.359171 149.117391 63.99888 63.99888 0 0 0 4.479921 90.23842A63.99888 63.99888 0 0 0 703.99664 767.98656a63.99888 63.99888 0 0 0 47.359171-21.11963A349.433885 349.433885 0 0 0 831.9944 511.99104a353.273818 353.273818 0 0 0-79.9986-234.87589z" fill="#606670" p-id="3606"></path></svg>)
export const muteIcon = (<svg className="icon" viewBox="0 0 1024 1024" version="1.1"><path d="M536.310615 5.11991a63.99888 63.99888 0 0 0-69.75878 13.439765L229.755979 255.99552H63.99888a63.99888 63.99888 0 0 0-63.99888 63.99888v383.99328a63.99888 63.99888 0 0 0 63.99888 63.99888h165.757099l236.795856 237.435845A63.99888 63.99888 0 0 0 511.99104 1023.98208a53.759059 53.759059 0 0 0 24.319575-5.11991A63.99888 63.99888 0 0 0 575.98992 959.9832V63.99888a63.99888 63.99888 0 0 0-39.679305-58.87897zM191.99664 639.9888H127.99776V383.99328h63.99888z m255.99552 165.757099l-127.99776-127.99776V346.233941l127.99776-127.99776zM914.543995 511.99104l90.87841-90.238421a63.99888 63.99888 0 1 0-90.87841-90.878409l-90.23842 90.878409-90.238421-90.878409a63.99888 63.99888 0 0 0-90.87841 90.878409L734.067154 511.99104l-90.87841 90.238421a63.99888 63.99888 0 0 0 90.87841 90.87841l90.238421-90.87841 90.23842 90.87841a63.99888 63.99888 0 1 0 90.87841-90.87841z" fill="#606670" p-id="2312"></path></svg>)
export const playIcon = (<svg className="icon" viewBox="0 0 1024 1024" version="1.1"><path d="M852.727563 392.447107C956.997809 458.473635 956.941389 565.559517 852.727563 631.55032L281.888889 993.019655C177.618644 1059.046186 93.090909 1016.054114 93.090909 897.137364L93.090909 126.860063C93.090909 7.879206 177.675064-35.013033 281.888889 30.977769L852.727563 392.447107 852.727563 392.447107Z" p-id="4494" fill="#606670"></path></svg>)
export const pauseIcon = (<svg className="icon" viewBox="0 0 1024 1024" version="1.1"><path d="M757.52 73.107h-62.493c-34.526 0-62.498 27.984-62.498 62.511v749.948c0 34.526 27.974 62.493 62.498 62.493h62.493c34.516 0 62.502-27.968 62.502-62.493v-749.953c-0.001-34.524-27.984-62.509-62.502-62.509z" p-id="7567" fill="#606670"></path><path d="M320.054 73.107h-62.502c-34.526 0-62.498 27.984-62.498 62.511v749.948c0 34.526 27.974 62.493 62.498 62.493h62.502c34.505 0 62.493-27.968 62.493-62.493v-749.953c-0.001-34.524-27.984-62.509-62.493-62.509z" p-id="7568" fill="#606670"></path></svg>)
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
d="M967.81435 106.836237 917.16274 56.18565 512 461.34839 106.836237 56.18565 56.184627 106.836237 461.34839 512 56.184627 917.163763 106.836237 967.815373 512 562.65161 917.16274 967.815373 967.81435 917.163763 562.650587 512Z"
p-id="1464"
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
d="M536.319574 5.11991a63.99888 63.99888 0 0 0-69.758779 13.439765L229.764939 255.99552H64.00784a63.99888 63.99888 0 0 0-63.99888 63.99888v383.99328a63.99888 63.99888 0 0 0 63.99888 63.99888h165.757099l236.795856 237.435845A63.99888 63.99888 0 0 0 512 1023.98208a53.759059 53.759059 0 0 0 24.319574-5.11991A63.99888 63.99888 0 0 0 575.99888 959.9832V63.99888a63.99888 63.99888 0 0 0-39.679306-58.87897zM192.0056 639.9888H128.00672V383.99328h63.99888z m255.99552 165.757099l-127.99776-127.99776V346.233941l127.99776-127.99776zM879.353571 148.477402a63.99888 63.99888 0 0 0-94.718342 87.038476 402.552955 402.552955 0 0 1 0 552.950324A63.99888 63.99888 0 0 0 831.9944 895.98432a63.99888 63.99888 0 0 0 46.719183-20.479641 531.830693 531.830693 0 0 0 0-727.027277z"
fill="#606670"
p-id="3605"
/>
<path
d="M751.9958 277.11515a63.99888 63.99888 0 0 0-95.99832 85.7585A218.236181 218.236181 0 0 1 703.99664 511.99104a221.436125 221.436125 0 0 1-47.359171 149.117391 63.99888 63.99888 0 0 0 4.479921 90.23842A63.99888 63.99888 0 0 0 703.99664 767.98656a63.99888 63.99888 0 0 0 47.359171-21.11963A349.433885 349.433885 0 0 0 831.9944 511.99104a353.273818 353.273818 0 0 0-79.9986-234.87589z"
fill="#606670"
p-id="3606"
/>
</svg>
);
export const muteIcon = (
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
<path
d="M536.310615 5.11991a63.99888 63.99888 0 0 0-69.75878 13.439765L229.755979 255.99552H63.99888a63.99888 63.99888 0 0 0-63.99888 63.99888v383.99328a63.99888 63.99888 0 0 0 63.99888 63.99888h165.757099l236.795856 237.435845A63.99888 63.99888 0 0 0 511.99104 1023.98208a53.759059 53.759059 0 0 0 24.319575-5.11991A63.99888 63.99888 0 0 0 575.98992 959.9832V63.99888a63.99888 63.99888 0 0 0-39.679305-58.87897zM191.99664 639.9888H127.99776V383.99328h63.99888z m255.99552 165.757099l-127.99776-127.99776V346.233941l127.99776-127.99776zM914.543995 511.99104l90.87841-90.238421a63.99888 63.99888 0 1 0-90.87841-90.878409l-90.23842 90.878409-90.238421-90.878409a63.99888 63.99888 0 0 0-90.87841 90.878409L734.067154 511.99104l-90.87841 90.238421a63.99888 63.99888 0 0 0 90.87841 90.87841l90.238421-90.87841 90.23842 90.87841a63.99888 63.99888 0 1 0 90.87841-90.87841z"
fill="#606670"
p-id="2312"
/>
</svg>
);
export const playIcon = (
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
<path
d="M852.727563 392.447107C956.997809 458.473635 956.941389 565.559517 852.727563 631.55032L281.888889 993.019655C177.618644 1059.046186 93.090909 1016.054114 93.090909 897.137364L93.090909 126.860063C93.090909 7.879206 177.675064-35.013033 281.888889 30.977769L852.727563 392.447107 852.727563 392.447107Z"
p-id="4494"
fill="#606670"
/>
</svg>
);
export const pauseIcon = (
<svg className="icon" viewBox="0 0 1024 1024" version="1.1">
<path
d="M757.52 73.107h-62.493c-34.526 0-62.498 27.984-62.498 62.511v749.948c0 34.526 27.974 62.493 62.498 62.493h62.493c34.516 0 62.502-27.968 62.502-62.493v-749.953c-0.001-34.524-27.984-62.509-62.502-62.509z"
p-id="7567"
fill="#606670"
/>
<path
d="M320.054 73.107h-62.502c-34.526 0-62.498 27.984-62.498 62.511v749.948c0 34.526 27.974 62.493 62.498 62.493h62.502c34.505 0 62.493-27.968 62.493-62.493v-749.953c-0.001-34.524-27.984-62.509-62.493-62.509z"
p-id="7568"
fill="#606670"
/>
</svg>
);

View File

@ -1,3 +1,9 @@
/**
* @file Index
* @description
* @author fex
*/
import NotFound from './404';
import {default as Alert, alert, confirm} from './Alert';
import AsideNav from './AsideNav';
@ -32,8 +38,6 @@ import Tooltip from './Tooltip';
import TooltipWrapper from './TooltipWrapper';
import Tree from './Tree';
export {
NotFound,
Alert as AlertComponent,
@ -70,5 +74,5 @@ export {
toast,
Tooltip,
TooltipWrapper,
Tree
};
Tree,
};