add share and code buttons

Summary: Adds code and share buttons to the editor

Reviewed By: emilsjolander

Differential Revision: D6989097

fbshipit-source-id: 67478fe0810a0af43524f24458c520acf2999219
This commit is contained in:
Daniel Büchele
2018-02-14 10:51:57 -08:00
committed by Facebook Github Bot
parent b1222bf83e
commit 43fda26275
14 changed files with 321 additions and 320 deletions

View File

@@ -1,29 +0,0 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
.Code {
display: flex;
flex-direction: column;
max-height: 100%;
}
.CodeContainer {
overflow: scroll;
}
.CodeLanguageSelector.ant-radio-group {
display: flex;
margin: 10px 15px;
}
.CodeLanguageSelector.ant-radio-group .ant-radio-button-wrapper {
flex-grow: 1;
flex-basis: 0;
text-align: center;
}

View File

@@ -1,114 +0,0 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
import React, {Component} from 'react';
import SyntaxHighlighter, {
registerLanguage,
} from 'react-syntax-highlighter/prism-light';
import styles from 'react-syntax-highlighter/styles/prism/prism';
import jsx from 'react-syntax-highlighter/languages/prism/jsx';
//import javascript from 'react-syntax-highlighter/languages/prism/javascript';
import java from 'react-syntax-highlighter/languages/prism/java';
import objectivec from 'react-syntax-highlighter/languages/prism/objectivec';
import type {LayoutRecordT} from './LayoutRecord';
import {Radio} from 'antd';
import CodeJavaScript from './CodeJavaScript';
import CodeLitho from './CodeLitho';
import CodeReactNative from './CodeReactNative';
import CodeComponentKit from './CodeComponentKit';
import './Code.css';
import type {Yoga$Direction} from 'yoga-layout';
const RadioButton = Radio.Button;
const RadioGroup = Radio.Group;
registerLanguage('jsx', jsx);
//registerLanguage('javascript', javascript);
registerLanguage('java', java);
registerLanguage('objectivec', objectivec);
type Language = 'JavaScript' | 'Litho' | 'ComponentKit' | 'React Native';
type Props = {
layoutDefinition: LayoutRecordT,
direction: Yoga$Direction,
languages: Array<Language>,
};
type State = {
language: Language,
};
export default class Code extends Component<Props, State> {
static defaultProps = {
languages: [/*'JavaScript', */ 'Litho', 'ComponentKit', 'React Native'],
};
state = {
language: 'Litho',
};
generateCode(lang: Language): string {
if (lang === 'JavaScript') {
return CodeJavaScript(this.props.layoutDefinition, this.props.direction);
} else if (lang === 'Litho') {
return CodeLitho(this.props.layoutDefinition, this.props.direction);
} else if (lang === 'ComponentKit') {
return CodeComponentKit(
this.props.layoutDefinition,
this.props.direction,
);
} else if (lang === 'React Native') {
return CodeReactNative(this.props.layoutDefinition, this.props.direction);
} else {
return '';
}
}
getLanguage(): string {
if (this.state.language === 'Litho') {
return 'java';
} else if (this.state.language === 'React Native') {
return 'javascript';
} else if (this.state.language === 'ComponentKit') {
return 'objectivec';
} else {
return this.state.language;
}
}
render() {
return (
<div className="Code">
<RadioGroup
className="CodeLanguageSelector"
onChange={e => this.setState({language: e.target.value})}
value={this.state.language}>
{this.props.languages.map(lang => (
<RadioButton key={lang} value={lang}>
{lang}
</RadioButton>
))}
</RadioGroup>
<div className="CodeContainer">
<SyntaxHighlighter
language={this.getLanguage()}
style={styles}
customStyle={{fontSize: '13px', backgroundColor: 'white'}}
lineNumberStyle={{userSelect: 'none', opacity: 0.5}}
codeTagProps={{style: {tabSize: 4}}}
showLineNumbers>
{this.generateCode(this.state.language)}
</SyntaxHighlighter>
</div>
</div>
);
}
}

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
import React, {Component} from 'react';
import {Menu, Button, Row, Col, Dropdown, Icon, Modal} from 'antd';
import SyntaxHighlighter, {
registerLanguage,
} from 'react-syntax-highlighter/prism-light';
import styles from 'react-syntax-highlighter/styles/prism/prism';
import CodeJavaScript from './CodeJavaScript';
import CodeLitho from './CodeLitho';
import CodeReactNative from './CodeReactNative';
import CodeComponentKit from './CodeComponentKit';
import jsx from 'react-syntax-highlighter/languages/prism/jsx';
//import javascript from 'react-syntax-highlighter/languages/prism/javascript';
import java from 'react-syntax-highlighter/languages/prism/java';
import objectivec from 'react-syntax-highlighter/languages/prism/objectivec';
registerLanguage('jsx', jsx);
//registerLanguage('javascript', javascript);
registerLanguage('java', java);
registerLanguage('objectivec', objectivec);
import type {LayoutRecordT} from './LayoutRecord';
import type {Yoga$Direction} from 'yoga-layout';
type Props = {
layoutDefinition: LayoutRecordT,
direction: Yoga$Direction,
};
type State = {
showModal: ?string,
};
const LANGUAGES = {
litho: {
title: 'Litho',
generator: CodeLitho,
syntax: 'java',
},
componentKit: {
title: 'ComponentKit',
generator: CodeComponentKit,
syntax: 'objectivec',
},
reactNative: {
title: 'React Native',
generator: CodeReactNative,
syntax: 'jsx',
},
};
['Litho', 'ComponentKit', 'React Native'];
export default class CodeGenerators extends Component<Props, State> {
state = {
showModal: null,
};
onClick = ({key}: {key: string}) => this.setState({showModal: key});
render() {
const {showModal} = this.state;
const menu = (
<Menu onClick={this.onClick}>
{Object.keys(LANGUAGES).map(key => (
<Menu.Item key={key}>{LANGUAGES[key].title}</Menu.Item>
))}
</Menu>
);
return [
<Modal
key="modal"
title={showModal ? LANGUAGES[showModal].title : ''}
visible={Boolean(showModal)}
footer={null}
bodyStyle={{padding: 0}}
onCancel={() => this.setState({showModal: null})}>
{showModal && (
<SyntaxHighlighter
language={LANGUAGES[showModal].syntax}
style={styles}
customStyle={{fontSize: '13px', backgroundColor: 'white'}}
lineNumberStyle={{userSelect: 'none', opacity: 0.5}}
codeTagProps={{style: {tabSize: 4}}}
showLineNumbers>
{LANGUAGES[showModal].generator(
this.props.layoutDefinition,
this.props.direction,
)}
</SyntaxHighlighter>
)}
</Modal>,
<Dropdown overlay={menu} key="dropdown">
<Button>
Get Code <Icon type="down" />
</Button>
</Dropdown>,
];
}
}

View File

@@ -11,6 +11,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
border-top: 1px solid #E8E8E8;
} }
.Editor .field { .Editor .field {

View File

@@ -58,7 +58,9 @@ export default class Editor extends Component<Props> {
<TabPane tab="Flex" key="1"> <TabPane tab="Flex" key="1">
<h2> <h2>
Direction Direction
<InfoText doclink="/docs/layout-direction">Defines the direction of which text and items are laid out</InfoText> <InfoText doclink="/docs/layout-direction">
Defines the direction of which text and items are laid out
</InfoText>
</h2> </h2>
<EditValue <EditValue
property="direction" property="direction"
@@ -67,7 +69,9 @@ export default class Editor extends Component<Props> {
/> />
<h2> <h2>
Flex direction Flex direction
<InfoText doclink="/docs/flex-direction">Defines the direction of the main-axis</InfoText> <InfoText doclink="/docs/flex-direction">
Defines the direction of the main-axis
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled}
@@ -77,10 +81,27 @@ export default class Editor extends Component<Props> {
/> />
<Row gutter={15} style={{marginTop: 30}}> <Row gutter={15} style={{marginTop: 30}}>
<Col span={12}> <Col span={8}>
<h2> <h2>
Flex grow Basis
<InfoText doclink="/docs/flex">The factor of remaining space should be given to this node</InfoText> <InfoText doclink="/docs/flex">
The factor of remaining space should be given to this node
</InfoText>
</h2>
<EditValue
type="text"
property="flexBasis"
disabled={disabled || selectedNodeIsRoot}
value={node ? node.flexBasis : undefined}
onChange={this.props.onChangeLayout}
/>
</Col>
<Col span={8}>
<h2>
Grow
<InfoText doclink="/docs/flex">
The factor of remaining space should be given to this node
</InfoText>
</h2> </h2>
<EditValue <EditValue
type="text" type="text"
@@ -90,10 +111,13 @@ export default class Editor extends Component<Props> {
onChange={this.props.onChangeLayout} onChange={this.props.onChangeLayout}
/> />
</Col> </Col>
<Col span={12}> <Col span={8}>
<h2> <h2>
Flex shrink Shrink
<InfoText doclink="/docs/flex">The shrink factor of this element if parent has no space left</InfoText> <InfoText doclink="/docs/flex">
The shrink factor of this element if parent has no space
left
</InfoText>
</h2> </h2>
<EditValue <EditValue
type="text" type="text"
@@ -107,7 +131,9 @@ export default class Editor extends Component<Props> {
<h2> <h2>
Flex wrap Flex wrap
<InfoText doclink="/docs/flex-wrap">Wrapping behaviour when child nodes don't fit into a single line</InfoText> <InfoText doclink="/docs/flex-wrap">
Wrapping behaviour when child nodes don't fit into a single line
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled}
@@ -119,7 +145,9 @@ export default class Editor extends Component<Props> {
<TabPane tab="Alignment" key="2"> <TabPane tab="Alignment" key="2">
<h2> <h2>
Justify content Justify content
<InfoText doclink="/docs/justify-content">Aligns child nodes along the main-axis</InfoText> <InfoText doclink="/docs/justify-content">
Aligns child nodes along the main-axis
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled}
@@ -130,7 +158,9 @@ export default class Editor extends Component<Props> {
<h2> <h2>
Align items Align items
<InfoText doclink="/docs/align-items">Aligns child nodes along the cross-axis</InfoText> <InfoText doclink="/docs/align-items">
Aligns child nodes along the cross-axis
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled}
@@ -141,7 +171,9 @@ export default class Editor extends Component<Props> {
<h2> <h2>
Align self Align self
<InfoText doclink="/docs/align-items">Override align items of parent</InfoText> <InfoText doclink="/docs/align-items">
Override align items of parent
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled || selectedNodeIsRoot} disabled={disabled || selectedNodeIsRoot}
@@ -152,7 +184,9 @@ export default class Editor extends Component<Props> {
<h2> <h2>
Align content Align content
<InfoText doclink="/docs/align-content">Alignment of lines along the cross-axis when wrapping</InfoText> <InfoText doclink="/docs/align-content">
Alignment of lines along the cross-axis when wrapping
</InfoText>
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled}
@@ -164,13 +198,15 @@ export default class Editor extends Component<Props> {
<TabPane tab="Layout" key="3"> <TabPane tab="Layout" key="3">
<h2> <h2>
Width &times; height Width &times; height
<InfoText doclink="/docs/width-height">Dimensions of the node</InfoText> <InfoText doclink="/docs/width-height">
Dimensions of the node
</InfoText>
</h2> </h2>
<Row gutter={15}> <Row gutter={15}>
<Col span={12}> <Col span={12}>
<EditValue <EditValue
type="text" type="text"
placeholder="width" placeholder="auto"
property="width" property="width"
disabled={disabled} disabled={disabled}
value={node ? node.width : undefined} value={node ? node.width : undefined}
@@ -180,7 +216,7 @@ export default class Editor extends Component<Props> {
<Col span={12}> <Col span={12}>
<EditValue <EditValue
type="text" type="text"
placeholder="height" placeholder="auto"
property="height" property="height"
disabled={disabled} disabled={disabled}
value={node ? node.height : undefined} value={node ? node.height : undefined}
@@ -191,11 +227,13 @@ export default class Editor extends Component<Props> {
<h2> <h2>
Aspect ratio Aspect ratio
<InfoText doclink="/docs/aspect-ratio">Width/Height aspect ratio of node</InfoText> <InfoText doclink="/docs/aspect-ratio">
Width/Height aspect ratio of node
</InfoText>
</h2> </h2>
<EditValue <EditValue
type="text" type="text"
placeholder="Aspect ratio" placeholder="none"
property="aspectRatio" property="aspectRatio"
disabled={disabled} disabled={disabled}
value={node ? node.aspectRatio : undefined} value={node ? node.aspectRatio : undefined}
@@ -209,6 +247,7 @@ export default class Editor extends Component<Props> {
key={property} key={property}
value={node ? node[property] : undefined} value={node ? node[property] : undefined}
onChange={this.props.onChangeLayout} onChange={this.props.onChangeLayout}
disabled={property === 'margin' && selectedNodeIsRoot}
/> />
))} ))}
<h2> <h2>
@@ -221,12 +260,13 @@ export default class Editor extends Component<Props> {
</h2> </h2>
<EditValue <EditValue
disabled={disabled} disabled={disabled || selectedNodeIsRoot}
property="positionType" property="positionType"
value={node ? node.positionType : undefined} value={node ? node.positionType : undefined}
onChange={this.props.onChangeLayout} onChange={this.props.onChangeLayout}
/> />
<EditValue <EditValue
disabled={selectedNodeIsRoot}
property="position" property="position"
value={node ? node.position : undefined} value={node ? node.position : undefined}
onChange={this.props.onChangeLayout} onChange={this.props.onChangeLayout}

View File

@@ -26,11 +26,10 @@ export default class InfoText extends Component<Props> {
<Popover <Popover
content={ content={
<div className="InfoText"> <div className="InfoText">
{ <p>{this.props.children}</p>
[ <Link className="docs-link" to={this.props.doclink}>
<p>{[...this.props.children]}</p>, DOCUMENTATION
<Link className="docs-link" to={this.props.doclink}>DOCUMENTATION</Link>] </Link>
}
</div> </div>
} }
trigger="hover"> trigger="hover">

View File

@@ -21,7 +21,7 @@ import type {
Yoga$JustifyContent, Yoga$JustifyContent,
Yoga$FlexDirection, Yoga$FlexDirection,
Yoga$FlexWrap, Yoga$FlexWrap,
Yoga$Yoga$PositionType, Yoga$PositionType,
} from 'yoga-layout'; } from 'yoga-layout';
export type LayoutRecordT = RecordOf<{ export type LayoutRecordT = RecordOf<{
@@ -32,17 +32,18 @@ export type LayoutRecordT = RecordOf<{
border: PositionRecordT, border: PositionRecordT,
margin: PositionRecordT, margin: PositionRecordT,
position: PositionRecordT, position: PositionRecordT,
positionType: Yoga$Yoga$PositionType, positionType: Yoga$PositionType,
alignItems?: Yoga$Align, alignItems?: Yoga$Align,
alignSelf?: Yoga$Align, alignSelf?: Yoga$Align,
alignContent?: Yoga$Align, alignContent?: Yoga$Align,
flexDirection?: Yoga$FlexDirection, flexDirection?: Yoga$FlexDirection,
flexBasis?: number | 'auto',
flexGrow?: number, flexGrow?: number,
flexShrink?: number, flexShrink?: number,
padding?: number, padding?: number,
flexWrap?: Yoga$FlexWrap, flexWrap?: Yoga$FlexWrap,
aspectRatio?: number, aspectRatio?: number,
children?: List<LayoutDefinition>, children?: List<LayoutRecordT>,
}>; }>;
const r: LayoutRecordT = Record({ const r: LayoutRecordT = Record({
@@ -59,6 +60,7 @@ const r: LayoutRecordT = Record({
position: PositionRecord(), position: PositionRecord(),
positionType: yoga.POSITION_TYPE_RELATIVE, positionType: yoga.POSITION_TYPE_RELATIVE,
flexWrap: yoga.WRAP_NO_WRAP, flexWrap: yoga.WRAP_NO_WRAP,
flexBasis: 'auto',
flexGrow: 0, flexGrow: 0,
flexShrink: 1, flexShrink: 1,
children: List(), children: List(),

View File

@@ -12,50 +12,13 @@
z-index: 3; z-index: 3;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0;
width: 350px; width: 350px;
background: white; background: white;
border-left: 1px solid #dddfe2;
transform: translateX(100%);
transition: 0.2s transform;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
pointer-events: none;
}
.Sidebar.floating {
margin: 25px; margin: 25px;
max-height: calc(100% - 50px); max-height: calc(100% - 50px);
border-radius: 6px; border-radius: 6px;
bottom: auto; bottom: auto;
box-shadow: 3px 3px 15px rgba(0, 0, 0, 0.15); box-shadow: 3px 3px 15px rgba(0, 0, 0, 0.15);
opacity: 0;
transform: translateY(15px);
transition: 0.2s all;
transition-timing-function: ease-out;
}
.Sidebar.visible {
transform: translateX(0);
pointer-events: all;
}
.Sidebar.floating.visible {
transform: translateY(0);
opacity: 1;
}
.SidebarClose {
text-align: right;
padding: 15px;
padding-bottom: 0;
}
.SidebarClose i {
cursor: pointer;
opacity: 0.4;
}
.SidebarClose i:hover {
opacity: 0.6;
} }

View File

@@ -11,29 +11,17 @@
*/ */
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Icon} from 'antd';
import './Sidebar.css'; import './Sidebar.css';
type Props = { type Props = {
onClose?: () => void,
width?: number, width?: number,
children: any, children: any,
floating?: boolean,
}; };
export default class Sidebar extends Component<Props> { export default class Sidebar extends Component<Props> {
render() { render() {
return ( return (
<div <div className="Sidebar" style={{width: this.props.width}}>
className={`Sidebar ${this.props.visible ? 'visible' : ''} ${
this.props.floating ? 'floating' : ''
}`}
style={{width: this.props.width}}>
{this.props.onClose && (
<div className="SidebarClose">
<Icon type="close" onClick={this.props.onClose} />
</div>
)}
{this.props.children} {this.props.children}
</div> </div>
); );

View File

@@ -1,7 +1,2 @@
.URLShortener { .URLShortener {
position: absolute;
bottom: 30px;
left: 30px;
z-index: 4;
box-shadow: 1px 1px 15px rgba(0, 0, 0, 0.2);
} }

View File

@@ -16,10 +16,37 @@ import './URLShortener.css';
const API_KEY = 'AIzaSyCRvdtNY07SGUokChS8oA9EaYJafFL0zMI'; const API_KEY = 'AIzaSyCRvdtNY07SGUokChS8oA9EaYJafFL0zMI';
export default class URLShortener extends Component<{}> { type State = {
shortURL: ?string,
loading: boolean,
};
export default class URLShortener extends Component<{}, State> {
_ref: ?HTMLElement = null; _ref: ?HTMLElement = null;
state = {
loading: false,
shortURL: null,
};
componentDidMount() {
window.addEventListener('hashchange', this.onHashChange);
}
componentWillUnmount() {
window.removeEventListener('hashchange', this.onHashChange);
}
onHashChange = () => {
this.setState({shortURL: null});
};
onClick = () => { onClick = () => {
this.setState(
{
loading: true,
},
() => {
fetch(`https://www.googleapis.com/urlshortener/v1/url?key=${API_KEY}`, { fetch(`https://www.googleapis.com/urlshortener/v1/url?key=${API_KEY}`, {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -32,12 +59,16 @@ export default class URLShortener extends Component<{}> {
}), }),
}) })
.then(res => res.json()) .then(res => res.json())
.then(({id}) => { .then(({id}) => this.setState({shortURL: id, loading: false}))
notification.open({ .catch(() => this.setState({shortURL: null, loading: false}));
message: 'Created short URL', },
description: ( );
};
render() {
return this.state.shortURL ? (
<Input <Input
value={id} value={this.state.shortURL}
autoFocus autoFocus
ref={ref => { ref={ref => {
if (ref) { if (ref) {
@@ -45,24 +76,15 @@ export default class URLShortener extends Component<{}> {
} }
}} }}
/> />
), ) : (
placement: 'bottomLeft',
});
});
};
render() {
return (
<Tooltip title="Copy URL">
<Button <Button
className="URLShortener" className="URLShortener"
onClick={this.onClick} onClick={this.onClick}
icon="share-alt" icon="share-alt"
type="primary" disabled={this.state.loading}
shape="circle" type="primary">
size="large" Share URL
/> </Button>
</Tooltip>
); );
} }
} }

View File

@@ -21,6 +21,7 @@ type Property = 'position' | 'margin' | 'padding' | 'border';
type Props = { type Props = {
value: PositionRecordT, value: PositionRecordT,
property: Property, property: Property,
disabled?: boolean,
onChange: (property: Property, value: PositionRecordT) => void, onChange: (property: Property, value: PositionRecordT) => void,
}; };
@@ -32,18 +33,22 @@ export default class YogaPositionEditor extends Component<Props> {
}; };
render() { render() {
const {onChange, value, property} = this.props; const {onChange, value, property, disabled} = this.props;
return ( return (
<div className="YogaPositionEditor"> <div className="YogaPositionEditor">
<Input <Input
type="text" type="text"
value={value.top} value={value.top}
disabled={disabled}
placeholder="0"
onChange={e => onChange(property, value.set('top', e.target.value))} onChange={e => onChange(property, value.set('top', e.target.value))}
/> />
<div className="YogaPositionEditorRow"> <div className="YogaPositionEditorRow">
<Input <Input
type="text" type="text"
value={value.left} value={value.left}
disabled={disabled}
placeholder="0"
onChange={e => onChange={e =>
onChange(property, value.set('left', e.target.value)) onChange(property, value.set('left', e.target.value))
} }
@@ -52,6 +57,8 @@ export default class YogaPositionEditor extends Component<Props> {
<Input <Input
type="text" type="text"
value={value.right} value={value.right}
disabled={disabled}
placeholder="0"
onChange={e => onChange={e =>
onChange(property, value.set('right', e.target.value)) onChange(property, value.set('right', e.target.value))
} }
@@ -60,6 +67,8 @@ export default class YogaPositionEditor extends Component<Props> {
<Input <Input
type="text" type="text"
value={value.bottom} value={value.bottom}
disabled={disabled}
placeholder="0"
onChange={e => onChange={e =>
onChange(property, value.set('bottom', e.target.value)) onChange(property, value.set('bottom', e.target.value))
} }

View File

@@ -43,9 +43,30 @@
100px 100px, 100px 100px, 100px 100px; 100px 100px, 100px 100px, 100px 100px;
} }
.Playground > .YogaNode { .Playground > .YogaNode {
margin: auto; margin: auto;
position: static; position: static;
align-self: center; align-self: center;
} }
.Playground .Actions {
padding: 15px;
}
.Playground .Actions .ant-btn {
width: 100%;
}
.Playground .NoContent {
border-top: 1px solid #E8E8E8;
font-size: 18px;
padding: 30px 50px;
text-align: center;
color: #D9D9D9;
font-weight: 300;
line-height: 130%;
}
.ant-modal-content {
overflow: hidden;
}

View File

@@ -13,13 +13,14 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import yoga from 'yoga-layout/dist/entry-browser'; import yoga from 'yoga-layout/dist/entry-browser';
import YogaNode from './YogaNode'; import YogaNode from './YogaNode';
import CodeGenerators from './CodeGenerators';
import URLShortener from './URLShortener';
import Editor from './Editor'; import Editor from './Editor';
import {List, setIn} from 'immutable'; import {List, setIn} from 'immutable';
import PositionRecord from './PositionRecord'; import PositionRecord from './PositionRecord';
import LayoutRecord from './LayoutRecord'; import LayoutRecord from './LayoutRecord';
import URLShortener from './URLShortener';
import Code from './Code';
import Sidebar from './Sidebar'; import Sidebar from './Sidebar';
import {Row, Col} from 'antd';
import type {LayoutRecordT} from './LayoutRecord'; import type {LayoutRecordT} from './LayoutRecord';
import type {Yoga$Direction} from 'yoga-layout'; import type {Yoga$Direction} from 'yoga-layout';
import './index.css'; import './index.css';
@@ -42,7 +43,6 @@ type State = {
selectedNodePath: ?Array<number>, selectedNodePath: ?Array<number>,
layoutDefinition: LayoutRecordT, layoutDefinition: LayoutRecordT,
direction: Yoga$Direction, direction: Yoga$Direction,
showCode: boolean,
}; };
function getPath(path: Array<number>): Array<mixed> { function getPath(path: Array<number>): Array<mixed> {
@@ -60,7 +60,6 @@ export default class Playground extends Component<Props, State> {
}, },
direction: yoga.DIRECTION_LTR, direction: yoga.DIRECTION_LTR,
maxDepth: 3, maxDepth: 3,
showCode: false,
showGuides: true, showGuides: true,
persist: false, persist: false,
}; };
@@ -79,7 +78,6 @@ export default class Playground extends Component<Props, State> {
selectedNodePath: this.props.selectedNodePath, selectedNodePath: this.props.selectedNodePath,
layoutDefinition: this.rehydrate(this.props.layoutDefinition), layoutDefinition: this.rehydrate(this.props.layoutDefinition),
direction: this.props.direction, direction: this.props.direction,
showCode: false,
}; };
componentDidMount() { componentDidMount() {
@@ -118,7 +116,6 @@ export default class Playground extends Component<Props, State> {
// sidebar may rely on a certain node to be selected // sidebar may rely on a certain node to be selected
this.setState({ this.setState({
selectedNodePath: null, selectedNodePath: null,
showCode: false,
}); });
} }
} }
@@ -211,17 +208,8 @@ export default class Playground extends Component<Props, State> {
return selectedNode ? selectedNode.children.size : 0; return selectedNode ? selectedNode.children.size : 0;
}; };
onToggleCode = () => {
this.setState({
selectedNodePath: this.state.showCode
? this.state.selectedNodePath
: null,
showCode: !this.state.showCode,
});
};
render() { render() {
const {layoutDefinition, selectedNodePath} = this.state; const {layoutDefinition, selectedNodePath, direction} = this.state;
const {height} = this.props; const {height} = this.props;
const selectedNode: ?LayoutRecordT = selectedNodePath const selectedNode: ?LayoutRecordT = selectedNodePath
@@ -239,20 +227,26 @@ export default class Playground extends Component<Props, State> {
<YogaNode <YogaNode
layoutDefinition={layoutDefinition} layoutDefinition={layoutDefinition}
selectedNodePath={selectedNodePath} selectedNodePath={selectedNodePath}
onClick={selectedNodePath => onClick={selectedNodePath => this.setState({selectedNodePath})}
this.setState({selectedNodePath, showCode: false})
}
onDoubleClick={this.onAdd} onDoubleClick={this.onAdd}
direction={this.state.direction} direction={direction}
showGuides={this.props.showGuides} showGuides={this.props.showGuides}
/> />
<Sidebar <Sidebar>
visible={ <div className="Actions">
Boolean(selectedNodePath) && <Row gutter={15}>
!this.state.showCode && <Col span={12}>
!this.props.renderSidebar <CodeGenerators
} layoutDefinition={layoutDefinition}
floating> direction={direction}
/>
</Col>
<Col span={12}>
<URLShortener />
</Col>
</Row>
</div>
{this.state.selectedNodePath ? (
<Editor <Editor
node={selectedNode} node={selectedNode}
selectedNodeIsRoot={ selectedNodeIsRoot={
@@ -260,25 +254,25 @@ export default class Playground extends Component<Props, State> {
} }
onChangeLayout={this.onChangeLayout} onChangeLayout={this.onChangeLayout}
onChangeSetting={(key, value) => this.setState({[key]: value})} onChangeSetting={(key, value) => this.setState({[key]: value})}
direction={this.state.direction} direction={direction}
onRemove={ onRemove={
selectedNodePath && selectedNodePath.length > 0 selectedNodePath && selectedNodePath.length > 0
? this.onRemove ? this.onRemove
: undefined : undefined
} }
onAdd={ onAdd={
selectedNodePath && selectedNodePath.length < this.props.maxDepth selectedNodePath &&
selectedNodePath.length < this.props.maxDepth
? this.onAdd ? this.onAdd
: undefined : undefined
} }
/> />
) : (
<div className="NoContent">
Select a node to edit its properties
</div>
)}
</Sidebar> </Sidebar>
<Sidebar
width={500}
visible={this.state.showCode}
onClose={() => this.setState({showCode: false})}
/>
{this.props.persist && <URLShortener />}
</div> </div>
); );