替换掉react-bootstrap中的组件

This commit is contained in:
catchonme 2019-08-07 15:36:05 +08:00
parent 69e45a026a
commit 2f12a79858
10 changed files with 199 additions and 71 deletions

View File

@ -11,7 +11,6 @@ const mapping: {
'immutability-helper': __moduleId('react-addons-update'),
'react-cropper': __moduleId('react-cropper'),
'react-dropzone': __moduleId('react-dropzone'),
'react-bootstrap': __moduleId('react-bootstrap'),
'classnames': __moduleId('classnames'),
'axios': __moduleId('axios'),
'moment': __moduleId('moment'),

View File

@ -53,7 +53,6 @@
"rc-input-number": "4.4.5",
"react": "^16.8.6",
"react-addons-update": "15.6.2",
"react-bootstrap": "^0.32.3",
"react-overlays": "^0.8.3",
"react-color": "2.13.8",
"react-cropper": "1.0.0",
@ -88,7 +87,6 @@
"@types/qs": "^6.5.1",
"@types/react": "^16.8.1",
"@types/react-addons-update": "^0.14.19",
"@types/react-bootstrap": "^0.32.3",
"@types/react-color": "^2.13.3",
"@types/react-cropper": "^0.10.1",
"@types/react-dom": "^16.0.7",

View File

@ -1,6 +1,13 @@
.#{$ns}Tabs {
&-links {
border-bottom: $Tabs-borderWidth solid $Tabs-borderColor;
padding-left: 0;
margin-bottom: 0;
list-style: none;
&::before {
display: table;
content: " ";
}
> .#{$ns}Tabs-link {
margin-bottom: -$Tabs-borderWidth;
@ -17,6 +24,7 @@
padding: $gap-sm $gap-base;
text-decoration: none;
cursor: pointer;
display: block;
}
&:hover > a,
@ -49,6 +57,13 @@
border-style: solid;
border-width: 0 $Tabs-borderWidth $Tabs-borderWidth;
border-color: $Tabs-borderColor;
> .tab-pane {
display: none;
&.active {
display: block;
}
}
}
&--line {

View File

@ -1,3 +1,113 @@
import {Collapse} from 'react-bootstrap';
/**
* @file Collapse
* @description
* @author fex
*/
export default Collapse;
import React from 'react';
import cx from 'classnames';
import css = require('dom-helpers/style');
import {ClassNamesFn, themeable} from '../theme';
import Transition, { EXITED, ENTERED, ENTERING, EXITING } from 'react-transition-group/Transition';
import { autobind } from '../utils/helper';
const collapseStyles: {
[propName: string]: string;
} = {
[EXITED]: 'collapse',
[EXITING]: 'collapsing',
[ENTERING]: 'collapsing',
[ENTERED]: 'collapse show',
};
export interface CollapseProps {
show?: boolean,
mountOnEnter?: boolean,
unmountOnExit?: boolean,
className?: string,
classPrefix: string;
classnames: ClassNamesFn;
}
export class Collapse extends React.Component<CollapseProps, any> {
static defaultProps: Pick<
CollapseProps,
'show' | 'mountOnEnter' | 'unmountOnExit'
> = {
show: false,
mountOnEnter: false,
unmountOnExit: false
}
contentDom: any;
contentRef = (ref: any) => (this.contentDom = ref);
@autobind
handleEnter(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleEntering(elem: HTMLElement) {
elem.style['height'] = `${elem['scrollHeight']}px`;
}
@autobind
handleEntered(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleExit(elem: HTMLElement) {
let offsetHeight = elem['offsetHeight'];
const height = offsetHeight + parseInt(css(elem, 'marginTop'), 10) + parseInt(css(elem, 'marginBottom'), 10);
elem.style['height'] = `${height}px`;
// trigger browser reflow
elem.offsetHeight;
}
@autobind
handleExiting(elem: HTMLElement) {
elem.style['height'] = null;
}
render() {
const {
show,
children,
mountOnEnter,
unmountOnExit
} = this.props;
return (
<Transition
mountOnEnter={mountOnEnter}
unmountOnExit={unmountOnExit}
in={show}
timeout={300}
onEnter={this.handleEnter}
onEntering={this.handleEntering}
onEntered={this.handleEntered}
onExit={this.handleExit}
onExiting={this.handleExiting}
>
{(status:string, innerProps:any) => {
if (status === ENTERING) {
this.contentDom.offsetWidth;
}
return React.cloneElement(children as any, {
...innerProps,
ref: this.contentRef,
className: cx(
collapseStyles[status],
innerProps.className
)
})}
}
</Transition>
);
}
}
export default themeable(Collapse);

View File

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

View File

@ -15,7 +15,6 @@ import ColorPicker from './ColorPicker';
import DatePicker from './DatePicker';
import DateRangePicker from './DateRangePicker';
import Drawer from './Drawer';
import DropdownButton from './DropdownButton';
// import Editor from './Editor';
import Html from './Html';
import * as Icons from './icons';
@ -52,7 +51,6 @@ export {
DatePicker,
DateRangePicker,
Drawer,
DropdownButton,
// Editor,
Html,
Icons,

View File

@ -26,7 +26,6 @@ import {
DatePicker,
DateRangePicker,
Drawer,
DropdownButton,
// Editor,
Icons,
Html,
@ -192,7 +191,6 @@ export {
DatePicker,
DateRangePicker,
Drawer,
DropdownButton,
// Editor,
Html,
Icons,

View File

@ -1,7 +1,6 @@
import React from 'react';
import {Renderer, RendererProps} from '../factory';
import cx from 'classnames';
import {Collapse as BasicCollapse} from 'react-bootstrap';
import { Renderer, RendererProps } from '../factory';
import { Collapse as BasicCollapse } from '../components/Collapse';
export interface CollapseProps extends RendererProps {
title?: string; // 标题
@ -81,8 +80,6 @@ export default class Collapse extends React.Component<CollapseProps, CollapseSta
collapsable,
} = this.props;
// todo 换掉 bootstrap 的 collapse
return (
<WrapperComponent
className={cx(
@ -102,7 +99,7 @@ export default class Collapse extends React.Component<CollapseProps, CollapseSta
</HeadingComponent>
) : null}
<BasicCollapse in={collapsable ? !this.state.collapsed : true}>
<BasicCollapse show={collapsable ? !this.state.collapsed : true} classnames={cx} classPrefix={ns}>
<div className={cx(`Collapse-body`, bodyClassName)}>
{children
? typeof children === 'function'

View File

@ -11,7 +11,6 @@ import {
} from './Item';
import pick = require("lodash/pick");
import React from 'react';
import { Row, Col } from "react-bootstrap";
import cx from 'classnames';
export interface GridProps extends FormControlProps {};

View File

@ -1,14 +1,19 @@
import React from 'react';
import {Renderer, RendererProps} from '../factory';
import {ServiceStore, IServiceStore} from '../store/service';
import {Api, SchemaNode, Schema, Action} from '../types';
import {filter, evalExpression} from '../utils/tpl';
import {Tabs as BsTabs, TabContainer, TabContent, TabPane, NavItem, Nav, Tab} from 'react-bootstrap';
import cx = require('classnames');
import { Schema } from '../types';
import { evalExpression } from '../utils/tpl';
import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition';
import find = require('lodash/find');
import {isVisible} from '../utils/helper';
import { isVisible } from '../utils/helper';
import findIndex = require('lodash/findIndex');
const transitionStyles: {
[propName: string]: string;
} = {
[ENTERING]: 'in',
[ENTERED]: 'in'
};
export type TabProps = Schema & {
title?: string; // 标题
icon?: string;
@ -30,9 +35,9 @@ export interface TabsState {
prevKey: any;
}
let tabCount = 0;
export default class Tabs extends React.Component<TabsProps, TabsState> {
wrapperRef: React.RefObject<HTMLDivElement> = React.createRef();
static defaultProps: Partial<TabsProps> = {
className: '',
mode: '',
@ -40,7 +45,6 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
unmountOnExit: false,
};
id = '' + tabCount++;
constructor(props: TabsProps) {
super(props);
@ -155,7 +159,7 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
// 是 hash需要更新到地址栏
if (typeof key === 'string' && env) {
env.updateLocation(`#${key}`);
} else if (typeof this.state.prevKey === 'string' && env) {
} else if (typeof this.state.activeKey === 'string' && env) {
env.updateLocation(`#`);
}
@ -207,8 +211,7 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
const mode = tabsMode || dMode;
return (
<TabContainer
id={this.id}
<div
className={cx(
`Tabs`,
{
@ -216,49 +219,63 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
},
className
)}
activeKey={this.state.activeKey}
onSelect={this.handleSelect}
>
<div>
<Nav className={cx('Tabs-links')} role="tablist">
{tabs.map((tab, index) => isVisible(tab, data) ? (
<NavItem
className={cx('Tabs-link')}
key={index}
eventKey={tab.hash || index}
disabled={tab.disabled || (tab.disabledOn && evalExpression(tab.disabledOn, data))}
>
{tab.icon ? (
<div>
<i className={tab.icon} /> {tab.title}
</div>
) : (
tab.title
)}
</NavItem>
) : null)}
</Nav>
<ul className={cx('Tabs-links')} role="tablist">
{tabs.map((tab, index) => isVisible(tab, data) ? (
<li
className={cx(
'Tabs-link',
this.state.activeKey === tab.hash || this.state.activeKey === index ? 'active' : '',
tab.disabled || (tab.disabledOn && evalExpression(tab.disabledOn, data)) ? 'disabled' : ''
)}
key={index}
onClick={() => tab.disabled || (tab.disabledOn && evalExpression(tab.disabledOn, data)) ? '' : this.handleSelect(tab.hash || index)}
>
{tab.icon ? (
<div>
<i className={tab.icon} /><a>{tab.title}</a>
</div>
) : (
<a>{tab.title}</a>
)}
</li>
) : null)}
</ul>
<TabContent
className={cx('Tabs-content', contentClassName)}
mountOnEnter={mountOnEnter}
unmountOnExit={unmountOnExit}
>
{tabs.map((tab, index) => isVisible(tab, data) ? (
<TabPane
key={index}
eventKey={tab.hash || index}
mountOnEnter={mountOnEnter}
unmountOnExit={typeof tab.reload === 'boolean' ? tab.reload : tab.unmountOnExit}
>
{tabRender
? tabRender(tab, this.props)
: render(`tab/${index}`, tab.tab || tab.body || '')}
</TabPane>
) : null)}
</TabContent>
<div
ref={this.wrapperRef}
className={cx('Tabs-content', contentClassName, 'tab-content')}
>
{tabs.map((tab, index) => isVisible(tab, data) ? (
<Transition
in={this.state.activeKey === tab.hash || this.state.activeKey === index ? true : false}
mountOnEnter={mountOnEnter}
unmountOnExit={unmountOnExit}
timeout={500}
key={index}
>
{(status:string) => {
if (status === ENTERING) {
this.wrapperRef.current && this.wrapperRef.current.childNodes.forEach((item:HTMLElement) => item.offsetHeight);
}
return (
<div className={cx(
transitionStyles[status],
this.state.activeKey === tab.hash || this.state.activeKey === index ? 'active' : '',
'tab-pane',
'fade'
)}>
{tabRender
? tabRender(tab, this.props)
: render(`tab/${index}`, tab.tab || tab.body || '')}
</div>
)
}}
</Transition>
) : null)
}
</div>
</TabContainer>
</div>
);
}
}