Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: only pass props to top level #63

Merged
merged 1 commit into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function Test(props: TestProps): JSX.Element {
fontFamily=\\"Times New Roman\\"
fontSize=\\"20px\\"
{...props}
{...getOverrideProps(props.overrides, \\"View\\")}
{...getOverrideProps(props.overrides, \\"Box\\")}
></View>
);
}
Expand Down Expand Up @@ -93,12 +93,11 @@ export type BoxWithButtonProps = {} & {
};
export default function BoxWithButton(props: BoxWithButtonProps): JSX.Element {
return (
<View {...props} {...getOverrideProps(props.overrides, \\"View\\")}>
<View {...props} {...getOverrideProps(props.overrides, \\"Box\\")}>
<Button
color=\\"#ff0000\\"
width=\\"20px\\"
{...props}
{...getOverrideProps(props.overrides, \\"Button\\")}
{...getOverrideProps(props.overrides, \\"Box.Button\\")}
></Button>
</View>
);
Expand All @@ -124,7 +123,7 @@ export default function BoxWithCustomButton(
props: BoxWithCustomButtonProps
): JSX.Element {
return (
<View {...props} {...getOverrideProps(props.overrides, \\"View\\")}>
<View {...props} {...getOverrideProps(props.overrides, \\"Box\\")}>
<CustomButton
color=\\"#ff0000\\"
width=\\"20px\\"
Expand All @@ -151,12 +150,11 @@ export type BoxWithButtonProps = {} & {
};
export default function BoxWithButton(props: BoxWithButtonProps): JSX.Element {
return (
<View {...props} {...getOverrideProps(props.overrides, \\"View\\")}>
<View {...props} {...getOverrideProps(props.overrides, \\"Box\\")}>
<Button
color=\\"#ff0000\\"
width=\\"20px\\"
{...props}
{...getOverrideProps(props.overrides, \\"Button\\")}
{...getOverrideProps(props.overrides, \\"Box.Button\\")}
></Button>
</View>
);
Expand All @@ -175,16 +173,17 @@ import {
} from \\"@aws-amplify/ui-react\\";

export type ComponentWithDataBindingProps = {
width: Number,
isDisabled: Boolean,
width?: Number,
isDisabled?: Boolean,
buttonUser?: User,
buttonColor: String,
buttonColor?: String,
} & {
overrides?: EscapeHatchProps | undefined | null,
};
export default function ComponentWithDataBinding(
props: ComponentWithDataBindingProps
): JSX.Element {
const { width, isDisabled, buttonUser, buttonColor } = props;
return (
<Button
label={buttonUser.username || \\"hspain@gmail.com\\"}
Expand Down Expand Up @@ -220,13 +219,12 @@ import { Button, View, getOverrideProps } from \\"@aws-amplify/ui-react\\";
export default function BoxWithButton(props) {
return React.createElement(
View,
__assign({}, props, getOverrideProps(props.overrides, \\"View\\")),
__assign({}, props, getOverrideProps(props.overrides, \\"Box\\")),
React.createElement(
Button,
__assign(
{ color: \\"#ff0000\\", width: \\"20px\\" },
props,
getOverrideProps(props.overrides, \\"Button\\")
getOverrideProps(props.overrides, \\"Box.Button\\")
)
)
);
Expand All @@ -240,12 +238,11 @@ import React from \\"react\\";
import { Button, View, getOverrideProps } from \\"@aws-amplify/ui-react\\";
export default function BoxWithButton(props) {
return (
<View {...props} {...getOverrideProps(props.overrides, \\"View\\")}>
<View {...props} {...getOverrideProps(props.overrides, \\"Box\\")}>
<Button
color=\\"#ff0000\\"
width=\\"20px\\"
{...props}
{...getOverrideProps(props.overrides, \\"Button\\")}
{...getOverrideProps(props.overrides, \\"Box.Button\\")}
></Button>
</View>
);
Expand All @@ -265,14 +262,13 @@ function BoxWithButton(props) {
Object.assign(
{},
props,
ui_react_1.getOverrideProps(props.overrides, \\"View\\")
ui_react_1.getOverrideProps(props.overrides, \\"Box\\")
),
react_1.default.createElement(
ui_react_1.Button,
Object.assign(
{ color: \\"#ff0000\\", width: \\"20px\\" },
props,
ui_react_1.getOverrideProps(props.overrides, \\"Button\\")
ui_react_1.getOverrideProps(props.overrides, \\"Box.Button\\")
)
)
);
Expand All @@ -297,11 +293,7 @@ export type BoxWithButtonProps = {} & {
};
export default function BoxWithButton(props: BoxWithButtonProps): JSX.Element {
return (
<View
padding-left
{...props}
{...getOverrideProps(props.overrides, \\"View\\")}
>
<View padding-left {...props} {...getOverrideProps(props.overrides, \\"Box\\")}>
<CustomButton
color=\\"#ff0000\\"
width=\\"20px\\"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { StudioComponent, StudioComponentChild } from '@amzn/amplify-ui-codegen-schema';
import { StudioNode } from '@amzn/studio-ui-codegen';
import { factory, JsxElement, JsxFragment } from 'typescript';
import { ReactStudioTemplateRenderer } from '../react-studio-template-renderer';
import { ReactRenderConfig } from '../react-render-config';
Expand All @@ -20,54 +21,56 @@ export class AmplifyRenderer extends ReactStudioTemplateRenderer {
super(component, renderConfig);
}

renderJsx(component: StudioComponent | StudioComponentChild): JsxElement | JsxFragment {
renderJsx(component: StudioComponent | StudioComponentChild, parent?: StudioNode): JsxElement | JsxFragment {
console.log(parent);
const node = new StudioNode(component, parent);
switch (component.componentType) {
case 'Collection':
return new CollectionRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new CollectionRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);
case 'Badge':
return new BadgeRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new BadgeRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);

case 'Button':
return new ButtonRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new ButtonRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);

case 'Box':
return new BoxRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new BoxRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);

case 'Card':
return new CardRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new CardRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);

case 'Divider':
return new DividerRenderer(component, this.importCollection).renderElement();
return new DividerRenderer(component, this.importCollection, parent).renderElement();

case 'Flex':
return new FlexRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
return new FlexRenderer(component, this.importCollection, parent).renderElement((children) =>
children.map((child) => this.renderJsx(child, node)),
);

case 'Image':
return new ImageRenderer(component, this.importCollection).renderElement();
return new ImageRenderer(component, this.importCollection, parent).renderElement();

case 'String':
return renderString(component);

case 'Text':
return new TextRenderer(component, this.importCollection).renderElement();
return new TextRenderer(component, this.importCollection, parent).renderElement();
}

console.warn(`${component.componentType} is not one of the primitives - assuming CustomComponent`);

return new CustomComponentRenderer(component, this.importCollection).renderElement((children) =>
children.map((child) => this.renderJsx(child)),
children.map((child) => this.renderJsx(child, node)),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { StudioComponent, StudioComponentChild, StudioComponentProperties } from '@amzn/amplify-ui-codegen-schema';
import { ComponentRendererBase } from '@amzn/studio-ui-codegen';
import { ComponentRendererBase, StudioNode } from '@amzn/studio-ui-codegen';
import { JsxAttribute, JsxAttributeLike, JsxElement, JsxOpeningElement, NodeFactory } from 'typescript';

import { addBindingPropertiesImports, buildOpeningElementAttributes } from './react-component-render-helper';
import { ImportCollection } from './import-collection';

export abstract class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<TPropIn, JsxElement> {
constructor(component: StudioComponent | StudioComponentChild, protected importCollection: ImportCollection) {
super(component);
constructor(
component: StudioComponent | StudioComponentChild,
protected importCollection: ImportCollection,
protected parent?: StudioNode,
) {
super(component, parent);
addBindingPropertiesImports(component, importCollection);
}

Expand All @@ -32,16 +36,24 @@ export abstract class ReactComponentRenderer<TPropIn> extends ComponentRendererB
}

private addPropsSpreadAttributes(factory: NodeFactory, attributes: JsxAttributeLike[], tagName: string) {
const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props'));
attributes.push(propsAttr);
if (this.node.isRoot()) {
const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props'));
attributes.push(propsAttr);
}

const overrideAttr = factory.createJsxSpreadAttribute(
factory.createCallExpression(factory.createIdentifier('getOverrideProps'), undefined, [
factory.createPropertyAccessExpression(
factory.createIdentifier('props'),
factory.createIdentifier('overrides'),
),
factory.createStringLiteral(tagName),
factory.createStringLiteral(
this.node
.getComponentPathToRoot()
.reverse()
.map((component) => component.componentType)
.join('.'),
),
]),
);
this.importCollection.addImport('@aws-amplify/ui-react', 'getOverrideProps');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComponentWithChildrenRendererBase } from '@amzn/studio-ui-codegen';
import { ComponentWithChildrenRendererBase, StudioNode } from '@amzn/studio-ui-codegen';
import { StudioComponent, StudioComponentChild, StudioComponentProperties } from '@amzn/amplify-ui-codegen-schema';

import {
Expand All @@ -19,8 +19,12 @@ export abstract class ReactComponentWithChildrenRenderer<TPropIn> extends Compon
JsxElement,
JsxChild
> {
constructor(component: StudioComponent | StudioComponentChild, protected importCollection: ImportCollection) {
super(component);
constructor(
component: StudioComponent | StudioComponentChild,
protected importCollection: ImportCollection,
protected parent?: StudioNode,
) {
super(component, parent);
addBindingPropertiesImports(component, importCollection);
}

Expand Down Expand Up @@ -92,16 +96,24 @@ export abstract class ReactComponentWithChildrenRenderer<TPropIn> extends Compon
}

private addPropsSpreadAttributes(factory: NodeFactory, attributes: JsxAttributeLike[], tagName: string) {
const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props'));
attributes.push(propsAttr);
if (this.node.isRoot()) {
const propsAttr = factory.createJsxSpreadAttribute(factory.createIdentifier('props'));
attributes.push(propsAttr);
}

const overrideAttr = factory.createJsxSpreadAttribute(
factory.createCallExpression(factory.createIdentifier('getOverrideProps'), undefined, [
factory.createPropertyAccessExpression(
factory.createIdentifier('props'),
factory.createIdentifier('overrides'),
),
factory.createStringLiteral(tagName),
factory.createStringLiteral(
this.node
.getComponentPathToRoot()
.reverse()
.map((component) => component.componentType)
.join('.'),
),
]),
);
this.importCollection.addImport('@aws-amplify/ui-react', 'getOverrideProps');
Expand Down
1 change: 1 addition & 0 deletions packages/studio-ui-codegen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './lib/mapper/mapper-base';
export * from './lib/renderer-helper';
export * from './lib/framework-output-config';
export * from './lib/framework-render-config';
export * from './lib/studio-node';
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@ import {
WrappedComponentProperties,
} from '@amzn/amplify-ui-codegen-schema';

import { StudioNode } from './studio-node';

/**
* Shared class for rendering components.
* Mostly contains helper functions for mapping the Studio schema to actual props.
*/
export abstract class CommonComponentRenderer<TPropIn> {
protected inputProps: WrappedComponentProperties<TPropIn>;

constructor(protected component: StudioComponent | StudioComponentChild) {
protected node: StudioNode;

constructor(protected component: StudioComponent | StudioComponentChild, protected parent?: StudioNode) {
const flattenedProps = Object.entries(component.properties).map((prop) => {
return [prop[0], prop[1]];
});
this.inputProps = Object.fromEntries(flattenedProps);
this.node = new StudioNode(component, parent);
}
}
23 changes: 23 additions & 0 deletions packages/studio-ui-codegen/lib/studio-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { StudioComponent, StudioComponentChild } from '@amzn/amplify-ui-codegen-schema';

export class StudioNode {
component: StudioComponent | StudioComponentChild;

parent?: StudioNode;

constructor(component: StudioComponent | StudioComponentChild, parent?: StudioNode) {
this.component = component;
this.parent = parent;
}

isRoot(): boolean {
return this.parent === undefined;
}

getComponentPathToRoot(): (StudioComponent | StudioComponentChild)[] {
if (this.parent !== undefined) {
return [this.component].concat(this.parent.getComponentPathToRoot());
}
return [this.component];
}
}