2017-12-15 16:09:09 +02:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import styled from 'styled-components';
|
|
|
|
import is from 'styled-is';
|
|
|
|
import remcalc from 'remcalc';
|
|
|
|
|
|
|
|
const Wrapper = styled.section`
|
|
|
|
margin-top: ${remcalc(24)};
|
|
|
|
margin-bottom: ${remcalc(46)};
|
|
|
|
`;
|
|
|
|
|
|
|
|
const Tabs = styled.ul`
|
|
|
|
list-style: none;
|
|
|
|
display: flex;
|
|
|
|
padding: 0;
|
|
|
|
align-items: center;
|
|
|
|
border-bottom: ${remcalc(1)} solid ${props => props.theme.textDisabled};
|
|
|
|
`;
|
|
|
|
|
|
|
|
const TabHeader = styled.li`
|
|
|
|
position: relative;
|
|
|
|
height: ${remcalc(30)};
|
|
|
|
box-sizing: border-box;
|
|
|
|
line-height: inherit;
|
|
|
|
margin-right: ${remcalc(18)};
|
|
|
|
|
|
|
|
${is('active')`
|
|
|
|
border-bottom: ${remcalc(1)} solid ${props => props.theme.primary};
|
|
|
|
`};
|
|
|
|
|
|
|
|
li:hover {
|
|
|
|
border-bottom: ${remcalc(1)} solid ${props => props.theme.primary};
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const Button = styled.button`
|
|
|
|
font-family: 'Libre Franklin';
|
|
|
|
text-transform: uppercase;
|
|
|
|
font-size: ${remcalc(15)};
|
|
|
|
color: ${props => props.theme.textDisabled};
|
|
|
|
border: none;
|
|
|
|
background: ${props => props.theme.white};
|
|
|
|
transition: color 150ms ease-in;
|
|
|
|
cursor: pointer;
|
|
|
|
text-transform: none;
|
|
|
|
padding: 0;
|
|
|
|
margin: 0 ${remcalc(2)};
|
|
|
|
|
|
|
|
${is('active')`
|
|
|
|
color: ${props => props.theme.primary};
|
|
|
|
font-weight: bold;
|
|
|
|
`};
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
color: ${props => props.theme.primary};
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const Tab = styled.div`
|
|
|
|
height: 0;
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 150ms ease-in;
|
|
|
|
|
|
|
|
${is('active')`
|
|
|
|
height: auto;
|
|
|
|
opacity: 1;
|
2018-02-26 14:07:30 +02:00
|
|
|
transition-delay: 150ms;
|
|
|
|
transition: opacity 150ms ease-in;
|
2017-12-15 16:09:09 +02:00
|
|
|
`};
|
|
|
|
|
|
|
|
.CodeMirror-wrap {
|
|
|
|
border: none;
|
|
|
|
padding: 0;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
class Playground extends Component {
|
2018-02-26 14:07:30 +02:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
tab: 'component',
|
|
|
|
states: []
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
const code = this.props.preview.props.code;
|
|
|
|
const regex = /\/\/ Tab: \w+/g;
|
|
|
|
let m;
|
|
|
|
while ((m = regex.exec(code)) !== null) {
|
|
|
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
|
|
if (m.index === regex.lastIndex) {
|
|
|
|
regex.lastIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
m.forEach((match, groupIndex) => {
|
|
|
|
// MAKE THIS SYNCRONOUS
|
|
|
|
window.setTimeout(() =>
|
|
|
|
this.setState({
|
|
|
|
states: [...this.state.states, match.split(':')[1].trim()]
|
|
|
|
})
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// async componentDidMount() {
|
|
|
|
// const code = this.props.preview.props.code;
|
|
|
|
|
|
|
|
// const matches = (/Tab:\s*?(.*)/gi).exec(code)
|
|
|
|
|
|
|
|
// if (!matches) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// matches.unshift();
|
|
|
|
|
|
|
|
// await ForEach(
|
|
|
|
// matches,
|
|
|
|
// match =>
|
|
|
|
// new Promise(resolve =>
|
|
|
|
// this.setState(
|
|
|
|
// {
|
|
|
|
// states: [...this.state.states, match.trim()]
|
|
|
|
// },
|
|
|
|
// resolve
|
|
|
|
// )
|
|
|
|
// )
|
|
|
|
// );
|
|
|
|
// }
|
2017-12-15 16:09:09 +02:00
|
|
|
|
|
|
|
changeTab = tab => {
|
|
|
|
this.setState({
|
|
|
|
tab
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-02-26 14:07:30 +02:00
|
|
|
showPreview = (preview, code) => ({
|
|
|
|
...preview,
|
|
|
|
props: {
|
|
|
|
...preview.props,
|
|
|
|
code
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-12-15 16:09:09 +02:00
|
|
|
render() {
|
|
|
|
const { name, preview, tabBody } = this.props;
|
2018-02-26 14:07:30 +02:00
|
|
|
const { tab, states } = this.state;
|
|
|
|
const propCode = this.props.preview.props.code;
|
|
|
|
const regex = /\/\/ Tab: \w+/g;
|
|
|
|
const nameRegex = /\/\/ Name: /g;
|
|
|
|
|
2017-12-15 16:09:09 +02:00
|
|
|
return (
|
|
|
|
<Wrapper>
|
|
|
|
<Tabs>
|
2018-02-26 14:07:30 +02:00
|
|
|
<TabHeader active={tab === 'component'}>
|
2017-12-15 16:09:09 +02:00
|
|
|
<Button
|
2018-02-26 14:07:30 +02:00
|
|
|
active={tab === 'component'}
|
2017-12-15 16:09:09 +02:00
|
|
|
onClick={() => this.changeTab('component')}
|
|
|
|
>
|
2018-02-26 14:07:30 +02:00
|
|
|
{(propCode.split(nameRegex)[1] || 'Component').split(/\s/g)[0]}
|
2017-12-15 16:09:09 +02:00
|
|
|
</Button>
|
|
|
|
</TabHeader>
|
2018-02-26 14:07:30 +02:00
|
|
|
{states.length
|
|
|
|
? states.map(state => (
|
|
|
|
<TabHeader active={tab === state}>
|
|
|
|
<Button
|
|
|
|
active={tab === state}
|
|
|
|
onClick={() => this.changeTab(state)}
|
|
|
|
>
|
|
|
|
{state}
|
|
|
|
</Button>
|
|
|
|
</TabHeader>
|
|
|
|
))
|
|
|
|
: null}
|
|
|
|
<TabHeader active={tab === 'code'}>
|
2017-12-15 16:09:09 +02:00
|
|
|
<Button
|
2018-02-26 14:07:30 +02:00
|
|
|
active={tab === 'code'}
|
2017-12-15 16:09:09 +02:00
|
|
|
onClick={() => this.changeTab('code')}
|
|
|
|
>
|
|
|
|
Code
|
|
|
|
</Button>
|
|
|
|
</TabHeader>
|
|
|
|
</Tabs>
|
2018-02-26 14:07:30 +02:00
|
|
|
<Tab active={tab === 'component'} data-preview={name}>
|
|
|
|
{this.showPreview(preview, propCode.split(regex)[0])}
|
2017-12-15 16:09:09 +02:00
|
|
|
</Tab>
|
2018-02-26 14:07:30 +02:00
|
|
|
{states.length
|
|
|
|
? states.map((state, i) => (
|
|
|
|
<Tab active={tab === state} data-preview={name}>
|
|
|
|
{this.showPreview(preview, propCode.split(regex)[i + 1])}
|
|
|
|
</Tab>
|
|
|
|
))
|
|
|
|
: null}
|
|
|
|
<Tab active={tab === 'code'}>{tabBody}</Tab>
|
2017-12-15 16:09:09 +02:00
|
|
|
</Wrapper>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Playground;
|