amis/examples/components/App.tsx

432 lines
11 KiB
TypeScript
Raw Normal View History

2019-06-11 17:00:02 +08:00
import React from 'react';
2019-04-30 11:11:25 +08:00
import NotFound from '../../src/components/404';
import Layout from '../../src/components/Layout';
import AsideNav from '../../src/components/AsideNav';
import {AlertComponent, ToastComponent} from '../../src/components/index';
2019-09-09 00:53:39 +08:00
import {mapTree} from '../../src/utils/helper';
import {Icon} from '../../src/components/icons';
2020-06-02 20:41:51 +08:00
import '../../src/locale/en';
2019-11-07 10:41:14 +08:00
import {
Router,
Route,
IndexRoute,
browserHistory,
hashHistory,
Link,
Redirect,
withRouter
} from 'react-router';
2019-04-30 11:11:25 +08:00
import Select from '../../src/components/Select';
2019-06-04 16:24:09 +08:00
import DocSearch from './DocSearch';
2020-07-23 20:31:51 +08:00
import {groupBy} from 'lodash';
import classnames from 'classnames';
2020-07-24 17:20:08 +08:00
import Doc, {docs} from './Doc';
import Example, {examples} from './Example';
2019-04-30 11:11:25 +08:00
let PathPrefix = '/examples';
2019-06-04 20:13:40 +08:00
let ContextPath = '';
2019-04-30 11:11:25 +08:00
2019-05-09 19:40:59 +08:00
if (process.env.NODE_ENV === 'production') {
2019-11-07 10:41:14 +08:00
PathPrefix = '';
ContextPath = '/amis';
2019-05-09 19:40:59 +08:00
}
2019-04-30 11:11:25 +08:00
const themes = [
2019-11-07 10:41:14 +08:00
{
label: '默认主题',
ns: 'a-',
value: 'default'
},
{
label: '百度云舍',
ns: 'cxd-',
value: 'cxd'
},
{
label: 'Dark',
ns: 'dark-',
value: 'dark'
}
2019-04-30 11:11:25 +08:00
];
2020-06-02 20:41:51 +08:00
const locales = [
{
2020-07-23 20:31:51 +08:00
label: '中文',
2020-06-02 20:41:51 +08:00
value: 'zh-cn'
},
{
label: 'English',
value: 'en'
}
];
2019-05-20 12:03:25 +08:00
@withRouter
2019-04-30 11:11:25 +08:00
export class App extends React.PureComponent {
2019-11-07 10:41:14 +08:00
state = {
asideFolded: localStorage.getItem('asideFolded') === 'true',
offScreen: false,
headerVisible: true,
themeIndex: 0,
themes: themes,
2020-06-02 20:41:51 +08:00
theme: themes[localStorage.getItem('themeIndex') || 0],
2020-07-23 20:31:51 +08:00
locale: localStorage.getItem('locale') || '',
2020-07-28 18:23:02 +08:00
navigations: [],
scrollTop: 0
2019-11-07 10:41:14 +08:00
};
constructor(props) {
super(props);
this.toggleAside = this.toggleAside.bind(this);
this.setAsideFolded = this.setAsideFolded.bind(this);
this.setHeaderVisible = this.setHeaderVisible.bind(this);
2020-07-24 17:20:08 +08:00
this.setNavigations = this.setNavigations.bind(this);
2019-11-07 10:41:14 +08:00
}
componentDidMount() {
if (this.state.theme.value !== 'default') {
document.querySelectorAll('link[title]').forEach(item => {
item.disabled = true;
});
document.querySelector(
`link[title=${this.state.theme.value}]`
).disabled = false;
2020-07-29 20:25:04 +08:00
if (this.state.theme.value === 'dark') {
document.querySelector('body').classList.add('dark');
}
2019-11-07 10:41:14 +08:00
}
2020-07-28 18:23:02 +08:00
document.addEventListener('scroll', this.handleScroll.bind(this));
2019-11-07 10:41:14 +08:00
}
componentDidUpdate(preProps, preState) {
const props = this.props;
if (preState.theme.value !== this.state.theme.value) {
document.querySelector(
`link[title=${preState.theme.value}]`
).disabled = true;
document.querySelector(
`link[title=${this.state.theme.value}]`
).disabled = false;
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (props.location.pathname !== preProps.location.pathname) {
this.setState(
{
offScreen: false
},
() => window.scrollTo(0, 0)
);
const pageURL = props.location.pathname;
_hmt && _hmt.push(['_trackPageview', pageURL]);
2019-09-09 00:53:39 +08:00
}
2019-11-07 10:41:14 +08:00
}
2019-04-30 11:11:25 +08:00
2020-07-28 18:23:02 +08:00
componentWillUnmount() {
document.removeEventListener('scroll', this.handleScroll.bind(this));
}
handleScroll(e) {
this.setState({
scrollTop: e.target.scrollingElement.scrollTop
});
}
2019-11-07 10:41:14 +08:00
toggleAside() {
this.setAsideFolded(!this.state.asideFolded);
}
2019-05-20 12:03:25 +08:00
2019-11-07 10:41:14 +08:00
setAsideFolded(folded = false) {
localStorage.setItem('asideFolded', JSON.stringify(folded));
this.setState({
asideFolded: folded
});
}
2019-05-20 12:03:25 +08:00
2019-11-07 10:41:14 +08:00
setHeaderVisible(visible = false) {
this.setState({
headerVisible: visible
});
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
renderAside() {
return (
<AsideNav
2020-07-23 20:31:51 +08:00
renderLink={() => {
return null;
2019-11-07 10:41:14 +08:00
}}
/>
);
}
2020-07-24 17:20:08 +08:00
setNavigations(items) {
this.setState({
navigations: items
});
}
toggleOpen(e, item) {
e.stopPropagation();
e.preventDefault();
const navigations = mapTree(this.state.navigations, i => {
const defaultOpen =
i.isOpen ??
(Array.isArray(i.children) &&
i.children.length &&
!!~i.children.findIndex(item => item.path === location.pathname));
return {
...i,
isOpen: item.label === i.label ? !defaultOpen : defaultOpen
};
});
this.setState({
navigations
});
}
2019-11-07 10:41:14 +08:00
renderHeader() {
const location = this.props.location;
const theme = this.state.theme;
if (location.pathname === '/edit') {
return (
<div id="headerBar" className="box-shadow bg-dark">
<div className={`${theme.ns}Layout-brand`}>AMis </div>
</div>
);
2019-09-09 00:53:39 +08:00
}
2019-11-07 10:41:14 +08:00
return (
2020-07-23 20:31:51 +08:00
<>
2019-11-07 10:41:14 +08:00
<div className={`${theme.ns}Layout-brandBar`}>
2020-07-29 19:35:01 +08:00
{/* <button
2019-11-07 10:41:14 +08:00
onClick={() => this.setState({offScreen: !this.state.offScreen})}
className="pull-right visible-xs"
>
<i className="glyphicon glyphicon-align-justify" />
2020-07-29 19:35:01 +08:00
</button> */}
2020-07-23 20:31:51 +08:00
2019-11-07 10:41:14 +08:00
<div className={`${theme.ns}Layout-brand`}>
<i className="fa fa-paw" />
2020-07-23 20:31:51 +08:00
<span className="hidden-folded m-l-sm">AMIS</span>
2019-11-07 10:41:14 +08:00
</div>
</div>
2019-09-09 00:53:39 +08:00
2020-07-23 20:31:51 +08:00
<div className={`${theme.ns}Layout-headerBar`}>
<ul className={`${theme.ns}Layout-headerBar-links pull-left`}>
2020-07-24 17:20:08 +08:00
<Link to="/docs" activeClassName="is-active">
</Link>
<Link to="/examples" activeClassName="is-active">
</Link>
2020-07-23 20:31:51 +08:00
</ul>
<div className="hidden-xs p-t pull-right m-l-sm">
<Select
clearable={false}
theme={this.state.theme.value}
value={this.state.locale || 'zh-cn'}
options={locales}
onChange={locale => {
this.setState({locale: locale.value});
localStorage.setItem('locale', locale.value);
}}
/>
2020-06-02 20:41:51 +08:00
</div>
2020-07-23 20:31:51 +08:00
<div className="hidden-xs p-t pull-right">
<Select
clearable={false}
theme={this.state.theme.value}
value={this.state.theme}
options={this.state.themes}
onChange={theme => {
this.setState({theme});
localStorage.setItem(
'themeIndex',
this.state.themes.indexOf(theme)
);
2020-07-29 20:25:04 +08:00
document
.querySelector('body')
.classList[theme.value === 'dark' ? 'add' : 'remove']('dark');
2020-07-23 20:31:51 +08:00
}}
/>
2019-11-07 10:41:14 +08:00
</div>
2020-07-29 19:35:01 +08:00
</div>
<div className={`${theme.ns}Layout-searchBar`}>
2019-11-07 10:41:14 +08:00
<DocSearch theme={this.state.theme.value} />
</div>
2020-07-23 20:31:51 +08:00
</>
2019-11-07 10:41:14 +08:00
);
}
2019-04-30 11:11:25 +08:00
2020-07-24 17:20:08 +08:00
renderNavigation(navs, parent?: any) {
const pathname = location.pathname;
return navs.map(nav => {
const path = nav.path;
const hasChildren = Array.isArray(nav.children) && nav.children.length;
const isOpen =
nav.isOpen ||
(nav.isOpen !== false &&
hasChildren &&
!!~nav.children.findIndex(item => item.path === pathname));
2020-07-23 20:31:51 +08:00
return (
<div
2020-07-24 17:20:08 +08:00
key={nav.label}
2020-07-23 20:31:51 +08:00
className={classnames('Doc-navigation-item', {
'is-active': path === location.pathname,
'is-top': !parent,
2020-07-24 17:20:08 +08:00
'is-open': isOpen
2020-07-23 20:31:51 +08:00
})}
>
2020-07-28 14:55:49 +08:00
<Link
onClick={e => {
browserHistory.push(
`${path || (hasChildren && nav.children[0].path)}`
);
2020-07-29 15:33:25 +08:00
!isOpen && this.toggleOpen(e, nav);
2020-07-28 14:55:49 +08:00
}}
// to={`${path || (hasChildren && nav.children[0].path)}`}
>
2020-07-24 17:20:08 +08:00
{nav.label}
2020-07-23 20:31:51 +08:00
{hasChildren ? (
<i
className={`iconfont icon-xialajiantou ${
2020-07-24 17:20:08 +08:00
isOpen ? '' : 'is-flipped'
2020-07-23 20:31:51 +08:00
}`}
2020-07-24 17:20:08 +08:00
onClick={e => this.toggleOpen(e, nav)}
2020-07-23 20:31:51 +08:00
></i>
) : null}
</Link>
2020-07-24 17:20:08 +08:00
{isOpen
? this.renderNavigation(nav.children || [], {
...nav,
2020-07-23 20:31:51 +08:00
path
})
: null}
</div>
);
});
}
2019-11-07 10:41:14 +08:00
render() {
const theme = this.state.theme;
2020-07-24 17:20:08 +08:00
const navigations = this.state.navigations;
2020-07-23 20:31:51 +08:00
2019-11-07 10:41:14 +08:00
return (
<Layout
theme={theme.value}
2020-07-23 20:31:51 +08:00
boxed={true}
2019-11-07 10:41:14 +08:00
offScreen={this.state.offScreen}
header={this.state.headerVisible ? this.renderHeader() : null}
2020-07-23 20:31:51 +08:00
// folded={this.state.asideFolded}
// aside={this.renderAside()}
2019-11-07 10:41:14 +08:00
>
2020-06-02 20:41:51 +08:00
<ToastComponent theme={theme.value} locale={this.state.locale} />
<AlertComponent theme={theme.value} locale={this.state.locale} />
2020-07-23 20:31:51 +08:00
<div className="Doc">
<div className="Doc-nav">
<div className="Doc-navigation">
2020-07-24 17:20:08 +08:00
{navigations.map(item => (
<div className="Doc-navigationGroup" key={item.label}>
2020-07-23 20:31:51 +08:00
<div className="Doc-navigationGroup-name">
2020-07-24 17:20:08 +08:00
{item.label || '其他'}
2020-07-23 20:31:51 +08:00
</div>
2020-07-24 17:20:08 +08:00
{this.renderNavigation(item.children)}
2020-07-23 20:31:51 +08:00
</div>
))}
</div>
</div>
2020-07-28 18:23:02 +08:00
{/* 完了加个动画吧 */}
<div
className={`Backtop ${this.state.scrollTop > 450 ? 'visible' : ''}`}
onClick={() => scrollTo({top: 0})}
>
<i className="fa fa-rocket"></i>
</div>
2020-07-23 20:31:51 +08:00
{React.cloneElement(this.props.children, {
...this.props.children.props,
2020-07-24 17:20:08 +08:00
setNavigations: this.setNavigations,
2020-07-23 20:31:51 +08:00
setAsideFolded: this.setAsideFolded,
setHeaderVisible: this.setHeaderVisible,
theme: theme.value,
classPrefix: theme.ns,
locale: this.state.locale
})}
</div>
2019-11-07 10:41:14 +08:00
</Layout>
);
}
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
2020-07-24 17:20:08 +08:00
function navigations2route(pathPrefix = PathPrefix, navigations) {
2019-11-07 10:41:14 +08:00
let routes = [];
navigations.forEach(root => {
root.children &&
mapTree(root.children, item => {
if (item.path && item.component) {
routes.push(
<Route
key={routes.length + 1}
path={
item.path[0] === '/'
? ContextPath + item.path
: `${ContextPath}${pathPrefix}/${item.path}`
}
component={item.component}
/>
);
} else if (item.path && item.getComponent) {
routes.push(
<Route
key={routes.length + 1}
path={
item.path[0] === '/'
? ContextPath + item.path
: `${ContextPath}${pathPrefix}/${item.path}`
}
getComponent={item.getComponent}
/>
);
}
});
});
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return routes;
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
2019-09-09 00:53:39 +08:00
export default function entry({pathPrefix}) {
2019-11-07 10:41:14 +08:00
PathPrefix = pathPrefix || PathPrefix;
return (
2020-07-24 17:20:08 +08:00
<Router history={browserHistory}>
2019-11-07 10:41:14 +08:00
<Route component={App}>
2020-07-29 15:33:25 +08:00
<Redirect from={`${ContextPath}/`} to={`${ContextPath}/docs/index`} />
2020-07-24 17:20:08 +08:00
<Redirect from={`/examples`} to={`/examples/pages/simple`} />
2020-07-28 10:03:53 +08:00
<Redirect from={`/docs`} to={`/docs/index`} />
2020-07-24 17:20:08 +08:00
<Route path="/docs" component={Doc}>
{navigations2route('/docs', docs)}
</Route>
<Route path="/examples" component={Example}>
{navigations2route('/examples', examples)}
</Route>
2019-11-07 10:41:14 +08:00
</Route>
2020-07-24 17:20:08 +08:00
<Route path="*" component={NotFound} />
2019-11-07 10:41:14 +08:00
</Router>
);
2019-09-09 00:53:39 +08:00
}