Fix ComponentKit code generation

Summary: Fixes ComponentKit code generation to outpput valid code.

Reviewed By: emilsjolander

Differential Revision: D6902924

fbshipit-source-id: f03a69268d22084f30aea46297b59aec28ba68d2
This commit is contained in:
Daniel Büchele
2018-02-06 08:13:17 -08:00
committed by Facebook Github Bot
parent 7199902316
commit bd46344a4e
4 changed files with 95 additions and 51 deletions

View File

@@ -3,7 +3,9 @@ import yoga from 'yoga-layout';
import LayoutRecord from './LayoutRecord'; import LayoutRecord from './LayoutRecord';
import PositionRecord from './PositionRecord'; import PositionRecord from './PositionRecord';
import type {LayoutRecordT} from './LayoutRecord'; import type {LayoutRecordT} from './LayoutRecord';
import type {Yoga$Direction} from 'yoga-layout'; import type {Yoga$Direction /* Yoga$Node */} from 'yoga-layout';
type Yoga$Node = any;
const enumLookup = { const enumLookup = {
flexDirection: { flexDirection: {
@@ -53,6 +55,9 @@ const enumLookup = {
}, },
}; };
const untouchedLayout = LayoutRecord({});
const untouchedPosition = PositionRecord({});
function keyLookup(key: string): string { function keyLookup(key: string): string {
const keyLookup = { const keyLookup = {
flexWrap: 'wrap', flexWrap: 'wrap',
@@ -67,54 +72,51 @@ function getLayoutCode(
isRoot?: boolean, isRoot?: boolean,
): string { ): string {
const lines = []; const lines = [];
const isFlexbox = node.children.size > 0;
lines.push(indent + `[CKFlexboxComponent`); lines.push(
lines.push(indent + ` newWithView:kWhiteBackgroundView`); indent +
`${isRoot ? '' : `.component = \n${indent}`}[${
isFlexbox ? 'CKFlexboxComponent' : 'CKComponent'
}`,
);
lines.push(indent + ` newWithView:{}`);
lines.push(indent + ` size:{${node.width},${node.height}}`); lines.push(indent + ` size:{${node.width},${node.height}}`);
lines.push(indent + ` style:{`);
const untouchedLayout = LayoutRecord({});
const untouchedPosition = PositionRecord({});
Object.keys(node.toJSON()).forEach(key => { const CKFlexboxComponentStyle = [
if ( 'direction',
node[key] instanceof PositionRecord && 'margin',
!node[key].equals(untouchedPosition) 'justifyContent',
) { 'alignItems',
lines.push(indent + `\t.${key} = {`); 'alignContent',
'wrap',
'padding',
'border',
];
const CKFlexboxComponentChild = [
'margin',
'padding',
'flexGrow',
'flexShrink',
'flexBasis',
'alignSelf',
'position',
];
if (key === 'positionType') { if (isFlexbox) {
lines.push( // render styles
indent + lines.push(indent + ` style:{`);
`\t.position = ${enumLookup.positionType[node.positionType]},`, indent += '\t';
); CKFlexboxComponentStyle.forEach(key => {
let line = renderKey(node, key, indent);
if (line) {
lines.push(line);
} }
});
indent = indent.substr(-1);
lines.push(indent + ` }`);
['top', 'left', 'right', 'bottom'].forEach(pKey => { // render children
if (node[key][pKey]) {
lines.push(indent + `\t\t.${pKey} = ${node[key][pKey]},`);
}
});
lines.push(indent + `\t},`);
} else if (
key !== 'children' &&
key !== 'width' &&
key !== 'height' &&
node[key] !== untouchedLayout[key]
) {
if (enumLookup[key]) {
lines.push(
indent +
`\t.${keyLookup(key)} = ${enumLookup[key][node.flexDirection]},`,
);
} else {
console.error(`Unknown property ${key}`);
}
}
});
lines.push(indent + ` }`);
if (node.children.size > 0) {
lines.push(indent + ' children:{'); lines.push(indent + ' children:{');
lines.push( lines.push(
...node.children ...node.children
@@ -127,13 +129,51 @@ function getLayoutCode(
)}\n${indent}\t},`, )}\n${indent}\t},`,
), ),
); );
lines.push(indent + '}'); lines.push(indent + `}]${isRoot ? ';' : ''}`);
} else {
lines[lines.length - 1] += ']';
CKFlexboxComponentChild.forEach(key => {
let line = renderKey(node, key, indent);
if (line) {
lines.push(line);
}
});
} }
lines[lines.length - 1] += `]${isRoot ? ';' : ''}`;
return lines.join('\n'); return lines.join('\n');
} }
function renderKey(node: Yoga$Node, key: string, indent: string): ?string {
if (
node[key] instanceof PositionRecord &&
!node[key].equals(untouchedPosition)
) {
const lines = [];
lines.push(indent + `.${key} = {`);
if (key === 'position') {
lines.push(
indent + `\t.type = ${enumLookup.positionType[node.positionType]},`,
);
}
['top', 'left', 'right', 'bottom'].forEach(pKey => {
if (node[key][pKey]) {
lines.push(indent + `\t.${pKey} = ${node[key][pKey]},`);
}
});
lines.push(indent + `},`);
return lines.join('\n');
} else if (node[key] !== untouchedLayout[key]) {
if (enumLookup[key]) {
return indent + `.${keyLookup(key)} = ${enumLookup[key][node[key]]},`;
} else {
console.error(`Unknown property ${key}`);
}
}
}
export default function generateCode( export default function generateCode(
root: LayoutRecordT, root: LayoutRecordT,
direction: Yoga$Direction, direction: Yoga$Direction,

View File

@@ -14,6 +14,7 @@ type Props = {
onChangeLayout: (key: string, value: any) => void, onChangeLayout: (key: string, value: any) => void,
onChangeSetting: (key: string, value: any) => void, onChangeSetting: (key: string, value: any) => void,
direction: Yoga$Direction, direction: Yoga$Direction,
selectedNodeIsRoot: boolean,
onRemove?: () => void, onRemove?: () => void,
onAdd?: () => void, onAdd?: () => void,
}; };
@@ -38,8 +39,9 @@ export default class Editor extends Component<Props> {
}; };
render() { render() {
const {node} = this.props; const {node, selectedNodeIsRoot} = this.props;
const disabled = !Boolean(node); const disabled = !Boolean(node);
return ( return (
<div className="Editor"> <div className="Editor">
<Tabs defaultActiveKey="1" className="EditorTabs"> <Tabs defaultActiveKey="1" className="EditorTabs">
@@ -78,8 +80,7 @@ export default class Editor extends Component<Props> {
</h2> </h2>
<Input <Input
type="text" type="text"
placeholder="flexGrow" disabled={disabled || selectedNodeIsRoot}
disabled={disabled}
value={node ? node.flexGrow : ''} value={node ? node.flexGrow : ''}
onChange={e => onChange={e =>
this.props.onChangeLayout('flexGrow', e.target.value) this.props.onChangeLayout('flexGrow', e.target.value)
@@ -96,8 +97,7 @@ export default class Editor extends Component<Props> {
</h2> </h2>
<Input <Input
type="text" type="text"
placeholder="flexShrink" disabled={disabled || selectedNodeIsRoot}
disabled={disabled}
value={node ? node.flexShrink : ''} value={node ? node.flexShrink : ''}
onChange={e => onChange={e =>
this.props.onChangeLayout('flexShrink', e.target.value) this.props.onChangeLayout('flexShrink', e.target.value)
@@ -149,7 +149,7 @@ export default class Editor extends Component<Props> {
</InfoText> </InfoText>
</h2> </h2>
<YogaEnumSelect <YogaEnumSelect
disabled={disabled} disabled={disabled || selectedNodeIsRoot}
property="ALIGN" property="ALIGN"
value={node ? node.alignSelf : ''} value={node ? node.alignSelf : ''}
onChange={e => this.props.onChangeLayout('alignSelf', e)} onChange={e => this.props.onChangeLayout('alignSelf', e)}

View File

@@ -239,6 +239,9 @@ export default class App extends Component<Props, State> {
<Sidebar visible={Boolean(selectedNodePath) && !this.state.showCode}> <Sidebar visible={Boolean(selectedNodePath) && !this.state.showCode}>
<Editor <Editor
node={selectedNode} node={selectedNode}
selectedNodeIsRoot={
selectedNodePath ? selectedNodePath.length === 0 : false
}
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={this.state.direction}

View File

@@ -39,6 +39,7 @@ export default class YogaEnumSelect extends Component<Props> {
return this.values.length > 3 ? ( return this.values.length > 3 ? (
<Dropdown <Dropdown
disabled={props.disabled}
overlay={ overlay={
<Menu onClick={this.handleMenuClick}> <Menu onClick={this.handleMenuClick}>
{this.values.map(({key, value}) => ( {this.values.map(({key, value}) => (