2018-02-12 09:28:31 -08:00
|
|
|
/**
|
|
|
|
* 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';
|
2018-02-12 10:25:02 -08:00
|
|
|
import {Row, Col, Button, Tabs} from 'antd';
|
|
|
|
import EditValue from './EditValue';
|
2018-02-12 09:28:31 -08:00
|
|
|
import type {LayoutRecordT} from './LayoutRecord';
|
|
|
|
import type {Yoga$Direction} from 'yoga-layout';
|
|
|
|
import InfoText from './InfoText';
|
|
|
|
import './Editor.css';
|
|
|
|
const TabPane = Tabs.TabPane;
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
node: ?LayoutRecordT,
|
|
|
|
onChangeLayout: (key: string, value: any) => void,
|
|
|
|
onChangeSetting: (key: string, value: any) => void,
|
|
|
|
direction: Yoga$Direction,
|
|
|
|
selectedNodeIsRoot: boolean,
|
|
|
|
onRemove?: () => void,
|
|
|
|
onAdd?: () => void,
|
|
|
|
};
|
|
|
|
|
|
|
|
export default class Editor extends Component<Props> {
|
|
|
|
componentDidMount() {
|
|
|
|
document.addEventListener('keydown', this.onKeyDown);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
document.removeEventListener('keydown', this.onKeyDown);
|
|
|
|
}
|
|
|
|
|
|
|
|
onKeyDown = (e: KeyboardEvent) => {
|
|
|
|
if (
|
|
|
|
(e.key === 'Delete' || e.key === 'Backspace') &&
|
|
|
|
this.props.onRemove &&
|
|
|
|
!(e.target instanceof HTMLInputElement)
|
|
|
|
) {
|
|
|
|
this.props.onRemove();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {node, selectedNodeIsRoot} = this.props;
|
|
|
|
const disabled = !Boolean(node);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="Editor">
|
|
|
|
<Tabs defaultActiveKey="1" className="EditorTabs">
|
|
|
|
<TabPane tab="Flex" key="1">
|
|
|
|
<h2>
|
|
|
|
Direction
|
|
|
|
<InfoText>
|
|
|
|
The direction property specifies the text direction/writing
|
|
|
|
direction
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
|
|
|
property="direction"
|
2018-02-12 09:28:31 -08:00
|
|
|
value={this.props.direction}
|
2018-02-13 06:13:29 -08:00
|
|
|
onChange={this.props.onChangeSetting}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
<h2>
|
|
|
|
Flex direction
|
|
|
|
<InfoText>Defining the direction of the main-axis</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="flexDirection"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.flexDirection : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
|
|
|
|
<Row gutter={15} style={{marginTop: 30}}>
|
|
|
|
<Col span={12}>
|
|
|
|
<h2>
|
|
|
|
Flex grow
|
|
|
|
<InfoText>
|
|
|
|
Grow factor defined how much space this element should take
|
|
|
|
up, relative to it's siblings
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
type="text"
|
2018-02-13 06:13:29 -08:00
|
|
|
property="flexGrow"
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled || selectedNodeIsRoot}
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.flexGrow : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
<Col span={12}>
|
|
|
|
<h2>
|
|
|
|
Flex shrink
|
|
|
|
<InfoText>
|
|
|
|
Shrink factor if elements don't fit into the parent node
|
|
|
|
anymore.
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
type="text"
|
2018-02-13 06:13:29 -08:00
|
|
|
property="flexShrink"
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled || selectedNodeIsRoot}
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.flexShrink : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
<h2>
|
|
|
|
Flex wrap
|
|
|
|
<InfoText>
|
|
|
|
Wrapping behaviour when child nodes don't fit into a single line
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="flexWrap"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.flexWrap : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</TabPane>
|
|
|
|
<TabPane tab="Alignment" key="2">
|
|
|
|
<h2>
|
|
|
|
Justify content
|
|
|
|
<InfoText>Aligns child nodes along the main-axis</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="justifyContent"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.justifyContent : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
|
|
|
|
<h2>
|
|
|
|
Align items
|
|
|
|
<InfoText>Aligns child nodes along the cross-axis</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="alignItems"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.alignItems : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
|
|
|
|
<h2>
|
|
|
|
Align self
|
|
|
|
<InfoText>
|
|
|
|
Specifies alignment on the cross-axis for the node itself
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled || selectedNodeIsRoot}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="alignSelf"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.alignSelf : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
|
|
|
|
<h2>
|
|
|
|
Align content
|
|
|
|
<InfoText>
|
|
|
|
Alignment of lines along the cross-axis when wrapping
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="alignContent"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.alignContent : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</TabPane>
|
|
|
|
<TabPane tab="Layout" key="3">
|
|
|
|
<h2>
|
|
|
|
Width × height
|
|
|
|
<InfoText>Dimensions of the node</InfoText>
|
|
|
|
</h2>
|
|
|
|
<Row gutter={15}>
|
|
|
|
<Col span={12}>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
type="text"
|
|
|
|
placeholder="width"
|
2018-02-13 06:13:29 -08:00
|
|
|
property="width"
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.width : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
<Col span={12}>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
type="text"
|
|
|
|
placeholder="height"
|
2018-02-13 06:13:29 -08:00
|
|
|
property="height"
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.height : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
<h2>
|
|
|
|
Aspect ratio
|
|
|
|
<InfoText>
|
|
|
|
Aspect radio is an additon by Yoga which is handy e.g. for nodes
|
|
|
|
displaying videos
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
type="text"
|
|
|
|
placeholder="Aspect ratio"
|
2018-02-13 06:13:29 -08:00
|
|
|
property="aspectRatio"
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.aspectRatio : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
|
|
|
|
<h2>Box model</h2>
|
|
|
|
{['padding', 'border', 'margin'].map(property => (
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
property={property}
|
|
|
|
key={property}
|
|
|
|
value={node ? node[property] : undefined}
|
2018-02-13 06:13:29 -08:00
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
))}
|
|
|
|
<h2>
|
|
|
|
Position
|
|
|
|
<InfoText>
|
|
|
|
Relative position offsets the node from it's calculated
|
|
|
|
position. Absolute position removes the node from the flexbox
|
|
|
|
flow and positions it at the given position.
|
|
|
|
</InfoText>
|
|
|
|
</h2>
|
|
|
|
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
disabled={disabled}
|
2018-02-12 10:25:02 -08:00
|
|
|
property="positionType"
|
2018-02-13 06:13:29 -08:00
|
|
|
value={node ? node.positionType : undefined}
|
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
2018-02-12 10:25:02 -08:00
|
|
|
<EditValue
|
2018-02-12 09:28:31 -08:00
|
|
|
property="position"
|
|
|
|
value={node ? node.position : undefined}
|
2018-02-13 06:13:29 -08:00
|
|
|
onChange={this.props.onChangeLayout}
|
2018-02-12 09:28:31 -08:00
|
|
|
/>
|
|
|
|
</TabPane>
|
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
<Row gutter={15} className="EditorButtons">
|
|
|
|
<Col span={12}>
|
|
|
|
<Button
|
|
|
|
icon="plus-circle-o"
|
|
|
|
disabled={!Boolean(this.props.onAdd)}
|
|
|
|
onClick={this.props.onAdd}
|
|
|
|
type="primary">
|
|
|
|
add child node
|
|
|
|
</Button>
|
|
|
|
</Col>
|
|
|
|
<Col span={12}>
|
|
|
|
<Button
|
|
|
|
icon="close-circle-o"
|
|
|
|
disabled={!Boolean(this.props.onRemove)}
|
|
|
|
onClick={this.props.onRemove}
|
|
|
|
type="danger">
|
|
|
|
remove node
|
|
|
|
</Button>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|