From b07b704952b1c9f798b93cd552556aa864859fd2 Mon Sep 17 00:00:00 2001 From: Alexander Harris Date: Fri, 18 Feb 2022 14:49:12 -0800 Subject: [PATCH] feat: try and marshall variant values to json objects to support icon viewBox/paths --- .../studio-ui-codegen-react.test.ts.snap | 71 +++++++++++++++++++ .../__tests__/studio-ui-codegen-react.test.ts | 5 ++ .../react-studio-template-renderer-helper.ts | 19 ++++- .../lib/react-studio-template-renderer.ts | 2 +- .../componentWithObjectVariants.json | 30 ++++++++ 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 packages/codegen-ui/example-schemas/componentWithObjectVariants.json diff --git a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap index 8284b62c7..89469d297 100644 --- a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap +++ b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react.test.ts.snap @@ -4044,6 +4044,77 @@ export default function ViewPrimitive( } `; +exports[`amplify render tests component with variants should render object variants 1`] = ` +Object { + "componentText": "/* eslint-disable */ +import React from \\"react\\"; +import { + EscapeHatchProps, + Variant, + getOverrideProps, + getOverridesFromVariants, + mergeVariantsAndOverrides, +} from \\"@aws-amplify/ui-react/internal\\"; +import { Icon, IconProps } from \\"@aws-amplify/ui-react\\"; + +export type IconVariantsProps = React.PropsWithChildren< + Partial & { + variant?: \\"primary\\" | \\"secondary\\"; + } & { + overrides?: EscapeHatchProps | undefined | null; + } +>; +export default function IconVariants( + props: IconVariantsProps +): React.ReactElement { + const { overrides: overridesProp, ...rest } = props; + const variants: Variant[] = [ + { + variantValues: { variant: \\"primary\\" }, + overrides: { + IconVariants: { + paths: [ + { + d: \\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\\", + fill: \\"black\\", + }, + ], + }, + }, + }, + { + variantValues: { variant: \\"secondary\\" }, + overrides: { + IconVariants: { + paths: [ + { + d: \\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\\", + fill: \\"black\\", + }, + { + d: \\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\\", + fill: \\"white\\", + }, + ], + }, + }, + }, + ]; + const overrides = mergeVariantsAndOverrides( + getOverridesFromVariants(variants, props), + overridesProp || {} + ); + return ( + /* @ts-ignore: TS2322 */ + + ); +} +", + "declaration": undefined, + "renderComponentToFilesystem": [Function], +} +`; + exports[`amplify render tests component with variants should render variants with options provided 1`] = ` Object { "componentText": "/* eslint-disable */ diff --git a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react.test.ts b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react.test.ts index d06943094..59b96de68 100644 --- a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react.test.ts +++ b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react.test.ts @@ -223,6 +223,11 @@ describe('amplify render tests', () => { const generatedCode = generateWithAmplifyRenderer('componentWithVariants'); expect(generatedCode).toMatchSnapshot(); }); + + it('should render object variants', () => { + const generatedCode = generateWithAmplifyRenderer('componentWithObjectVariants'); + expect(generatedCode).toMatchSnapshot(); + }); }); describe('component with variants with mapped children prop', () => { diff --git a/packages/codegen-ui-react/lib/react-studio-template-renderer-helper.ts b/packages/codegen-ui-react/lib/react-studio-template-renderer-helper.ts index f348b54ea..1244fe0a8 100644 --- a/packages/codegen-ui-react/lib/react-studio-template-renderer-helper.ts +++ b/packages/codegen-ui-react/lib/react-studio-template-renderer-helper.ts @@ -151,6 +151,7 @@ export type json = string | number | boolean | null | json[] | { [key: string]: // eslint-disable-next-line consistent-return export function jsonToLiteral( jsonObject: json, + tryAndMarshallStringsToObjects?: boolean, ): ObjectLiteralExpression | StringLiteral | NumericLiteral | BooleanLiteral | NullLiteral | ArrayLiteralExpression { if (jsonObject === null) { return factory.createNull(); @@ -158,6 +159,14 @@ export function jsonToLiteral( // eslint-disable-next-line default-case switch (typeof jsonObject) { case 'string': + if (tryAndMarshallStringsToObjects) { + try { + const parsedObject = JSON.parse(jsonObject); + if (typeof parsedObject === 'object') { + return jsonToLiteral(parsedObject, tryAndMarshallStringsToObjects); + } + } catch (e) {} // eslint-disable-line no-empty + } return factory.createStringLiteral(jsonObject); case 'number': return factory.createNumericLiteral(jsonObject); @@ -169,12 +178,18 @@ export function jsonToLiteral( } case 'object': { if (jsonObject instanceof Array) { - return factory.createArrayLiteralExpression(jsonObject.map(jsonToLiteral), false); + return factory.createArrayLiteralExpression( + jsonObject.map((obj) => jsonToLiteral(obj, tryAndMarshallStringsToObjects)), + false, + ); } // else object return factory.createObjectLiteralExpression( Object.entries(jsonObject).map(([key, value]) => - factory.createPropertyAssignment(factory.createStringLiteral(key), jsonToLiteral(value)), + factory.createPropertyAssignment( + factory.createStringLiteral(key), + jsonToLiteral(value, tryAndMarshallStringsToObjects), + ), ), false, ); diff --git a/packages/codegen-ui-react/lib/react-studio-template-renderer.ts b/packages/codegen-ui-react/lib/react-studio-template-renderer.ts index b2cf0c783..d5d48f123 100644 --- a/packages/codegen-ui-react/lib/react-studio-template-renderer.ts +++ b/packages/codegen-ui-react/lib/react-studio-template-renderer.ts @@ -663,7 +663,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer factory.createArrayTypeNode( factory.createTypeReferenceNode(factory.createIdentifier('Variant'), undefined), ), - jsonToLiteral(variants as json), + jsonToLiteral(variants as json, true), ), ], ts.NodeFlags.Const, diff --git a/packages/codegen-ui/example-schemas/componentWithObjectVariants.json b/packages/codegen-ui/example-schemas/componentWithObjectVariants.json new file mode 100644 index 000000000..e3f4631cf --- /dev/null +++ b/packages/codegen-ui/example-schemas/componentWithObjectVariants.json @@ -0,0 +1,30 @@ +{ + "id": "1234-5678-9010", + "componentType": "Icon", + "name": "IconVariants", + "properties": {}, + "variants": [ + { + "variantValues": { + "variant": "primary" + }, + "overrides": { + "IconVariants": { + "paths": "[{\"d\":\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\",\"fill\":\"black\"}]" + } + } + }, + { + "variantValues": { + "variant": "secondary" + }, + "overrides": { + "IconVariants": { + "paths": "[{\"d\":\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\",\"fill\":\"black\"},{\"d\":\"M18 6V4h2V2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14v-2h-4.03c1.23-.91 2.03-2.36 2.03-4v-5H8v5c0 1.64.81 3.09 2.03 4H6V4h2v2c0 .55.45 1 1 1h8c.55 0 1-.45 1-1z\",\"fill\":\"white\"}]" + } + } + } + ], + "bindingProperties": {}, + "schemaVersion": "1.0" +}