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 PositionRecord from './PositionRecord';
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 = {
flexDirection: {
@@ -53,6 +55,9 @@ const enumLookup = {
},
};
const untouchedLayout = LayoutRecord({});
const untouchedPosition = PositionRecord({});
function keyLookup(key: string): string {
const keyLookup = {
flexWrap: 'wrap',
@@ -67,54 +72,51 @@ function getLayoutCode(
isRoot?: boolean,
): string {
const lines = [];
const isFlexbox = node.children.size > 0;
lines.push(indent + `[CKFlexboxComponent`);
lines.push(indent + ` newWithView:kWhiteBackgroundView`);
lines.push(
indent +
`${isRoot ? '' : `.component = \n${indent}`}[${
isFlexbox ? 'CKFlexboxComponent' : 'CKComponent'
}`,
);
lines.push(indent + ` newWithView:{}`);
lines.push(indent + ` size:{${node.width},${node.height}}`);
lines.push(indent + ` style:{`);
const untouchedLayout = LayoutRecord({});
const untouchedPosition = PositionRecord({});
Object.keys(node.toJSON()).forEach(key => {
if (
node[key] instanceof PositionRecord &&
!node[key].equals(untouchedPosition)
) {
lines.push(indent + `\t.${key} = {`);
const CKFlexboxComponentStyle = [
'direction',
'margin',
'justifyContent',
'alignItems',
'alignContent',
'wrap',
'padding',
'border',
];
const CKFlexboxComponentChild = [
'margin',
'padding',
'flexGrow',
'flexShrink',
'flexBasis',
'alignSelf',
'position',
];
if (key === 'positionType') {
lines.push(
indent +
`\t.position = ${enumLookup.positionType[node.positionType]},`,
);
if (isFlexbox) {
// render styles
lines.push(indent + ` style:{`);
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 => {
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) {
// render children
lines.push(indent + ' children:{');
lines.push(
...node.children
@@ -127,13 +129,51 @@ function getLayoutCode(
)}\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');
}
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(
root: LayoutRecordT,
direction: Yoga$Direction,

View File

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

View File

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