@teleporthq/teleport-plugin-react-styled-components
Advanced tools
Comparing version
import { component, elementNode } from '@teleporthq/teleport-uidl-builders' | ||
import { | ||
ComponentStructure, | ||
ChunkDefinition, | ||
ChunkType, | ||
FileType, | ||
} from '@teleporthq/teleport-types' | ||
import { ComponentStructure } from '@teleporthq/teleport-types' | ||
import { createReactStyledComponentsPlugin } from '../src/index' | ||
import { createElementWithStyle } from './mocks' | ||
import { createComponentChunk, createElementWithStyle } from './mocks' | ||
describe('Testing the functionality for StyledComponents', () => { | ||
const plugin = createReactStyledComponentsPlugin() | ||
const componentChunk: ChunkDefinition = { | ||
name: 'jsx-component', | ||
meta: { | ||
nodesLookup: { | ||
container: { | ||
openingElement: { | ||
name: { | ||
name: '', | ||
}, | ||
}, | ||
}, | ||
}, | ||
dynamicRefPrefix: { | ||
prop: 'props.', | ||
}, | ||
}, | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
linkAfter: ['import-local'], | ||
content: {}, | ||
} | ||
const componentChunk = createComponentChunk() | ||
@@ -35,0 +10,0 @@ it('Should not add styled as dependency', async () => { |
import { staticNode, elementNode } from '@teleporthq/teleport-uidl-builders' | ||
import { ChunkDefinition, ChunkType, FileType } from '@teleporthq/teleport-types' | ||
@@ -18,1 +19,27 @@ export const createElementWithStyle = () => { | ||
} | ||
export const createComponentChunk = () => { | ||
const componentChunk: ChunkDefinition = { | ||
name: 'jsx-component', | ||
meta: { | ||
nodesLookup: { | ||
container: { | ||
openingElement: { | ||
attributes: [], | ||
name: { | ||
name: '', | ||
}, | ||
}, | ||
}, | ||
}, | ||
dynamicRefPrefix: { | ||
prop: 'props', | ||
}, | ||
}, | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
linkAfter: ['import-local'], | ||
content: {}, | ||
} | ||
return componentChunk | ||
} |
@@ -1,32 +0,8 @@ | ||
import { | ||
ChunkDefinition, | ||
ChunkType, | ||
FileType, | ||
ComponentStructure, | ||
} from '@teleporthq/teleport-types' | ||
import { ComponentStructure, UIDLStyleSetDefinition } from '@teleporthq/teleport-types' | ||
import { createReactStyledComponentsPlugin } from '../src' | ||
import { component, elementNode, staticNode } from '@teleporthq/teleport-uidl-builders' | ||
import { createComponentChunk } from './mocks' | ||
describe('Referenced Styles on Node', () => { | ||
const componentChunk: ChunkDefinition = { | ||
name: 'jsx-component', | ||
meta: { | ||
nodesLookup: { | ||
container: { | ||
openingElement: { | ||
name: { | ||
name: '', | ||
}, | ||
}, | ||
}, | ||
}, | ||
dynamicRefPrefix: { | ||
prop: 'props.', | ||
}, | ||
}, | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
linkAfter: ['import-local'], | ||
content: {}, | ||
} | ||
const componentChunk = createComponentChunk() | ||
const uidl = component('MyComponent', elementNode('container', null, [], null, null, null, null)) | ||
@@ -38,3 +14,2 @@ | ||
'5ed659b1732f9b804f7b6381': { | ||
id: '5ed659b1732f9b804f7b6381', | ||
type: 'style-map', | ||
@@ -50,3 +25,2 @@ content: { | ||
'5ed659b1732f9b804f7b6382': { | ||
id: '5ed659b1732f9b804f7b6382', | ||
type: 'style-map', | ||
@@ -71,15 +45,15 @@ content: { | ||
const result = await plugin(structure) | ||
const { chunks, dependencies } = result | ||
const { chunks, dependencies } = await plugin(structure) | ||
const containerChunk = chunks.find((chunk) => chunk.name === 'Container') | ||
expect(chunks[1].name).toBe('Container') | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'display: block' | ||
) | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'display: none' | ||
) | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'@media(max-width: 991px)' | ||
) | ||
expect(containerChunk).toBeDefined() | ||
expect(containerChunk.content.type).toBe('VariableDeclaration') | ||
const declerationArguments = containerChunk.content.declarations[0].init.arguments | ||
expect(declerationArguments.length).toBe(1) | ||
expect(declerationArguments[0].name).not.toBe('projectStyleVariants') | ||
expect(declerationArguments[0].properties.length).toBe(2) | ||
expect(declerationArguments[0].properties[0].key.value).toBe('@media(max-width: 991px)') | ||
expect(declerationArguments[0].properties[1].key.value).toBe('&:hover') | ||
expect(Object.keys(dependencies).length).toBe(1) | ||
@@ -92,3 +66,2 @@ }) | ||
'5ed659b1732f9b804f7b6381': { | ||
id: '5ed659b1732f9b804f7b6381', | ||
type: 'style-map', | ||
@@ -104,3 +77,2 @@ content: { | ||
'5ed659b1732f9b804f7b6382': { | ||
id: '5ed659b1732f9b804f7b6382', | ||
type: 'style-map', | ||
@@ -116,7 +88,6 @@ content: { | ||
'5ed659b1732f9b804f7b6384': { | ||
id: '5ed659b1732f9b804f7b6384', | ||
type: 'style-map', | ||
content: { | ||
mapType: 'project-referenced', | ||
referenceId: '5ecfa1233b8e50f60ea2b64d', | ||
referenceId: 'primaryButton', | ||
}, | ||
@@ -134,6 +105,4 @@ }, | ||
const styleSetDefinitions = { | ||
'5ecfa1233b8e50f60ea2b64d': { | ||
id: '5ecfa1233b8e50f60ea2b64d', | ||
name: 'primaryButton', | ||
const styleSetDefinitions: Record<string, UIDLStyleSetDefinition> = { | ||
primaryButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -153,20 +122,18 @@ content: { | ||
const result = await plugin(structure) | ||
const { chunks, dependencies } = result | ||
const { chunks, dependencies } = await plugin(structure) | ||
const containerChunk = chunks.find((chunk) => chunk.name === 'Container') | ||
expect(chunks[1].name).toBe('Container') | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'display: block' | ||
) | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'display: none' | ||
) | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'@media(max-width: 991px)' | ||
) | ||
expect(chunks[1].content.declarations[0].init.quasi.quasis[0].value.raw).toContain( | ||
'${PrimaryButton' | ||
) | ||
expect(containerChunk).toBeDefined() | ||
expect(containerChunk.content.type).toBe('VariableDeclaration') | ||
const declerationArguments = containerChunk.content.declarations[0].init.arguments | ||
expect(declerationArguments.length).toBe(2) | ||
expect(declerationArguments[0].name).toBe('projectStyleVariants') | ||
expect(declerationArguments[1].properties.length).toBe(2) | ||
expect(declerationArguments[1].properties[0].key.value).toBe('@media(max-width: 991px)') | ||
expect(declerationArguments[1].properties[1].key.value).toBe('&:hover') | ||
expect(Object.keys(dependencies).length).toBe(2) | ||
}) | ||
}) |
import { | ||
ChunkDefinition, | ||
ChunkType, | ||
FileType, | ||
ComponentStructure, | ||
@@ -11,25 +8,6 @@ UIDLDesignTokens, | ||
import { component, elementNode, staticNode } from '@teleporthq/teleport-uidl-builders' | ||
import { createComponentChunk } from './mocks' | ||
describe('Style Sheet from styled components', () => { | ||
const componentChunk: ChunkDefinition = { | ||
name: 'jsx-component', | ||
meta: { | ||
nodesLookup: { | ||
container: { | ||
openingElement: { | ||
name: { | ||
name: '', | ||
}, | ||
}, | ||
}, | ||
}, | ||
dynamicRefPrefix: { | ||
prop: 'props.', | ||
}, | ||
}, | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
linkAfter: ['import-local'], | ||
content: {}, | ||
} | ||
const componentChunk = createComponentChunk() | ||
@@ -61,5 +39,3 @@ it('Generates a style sheet from the give JSON of styleSet', async () => { | ||
const styleSetDefinitions: Record<string, UIDLStyleSetDefinition> = { | ||
'5ecfa1233b8e50f60ea2b64d': { | ||
id: '5ecfa1233b8e50f60ea2b64d', | ||
name: 'primaryButton', | ||
primaryButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -71,5 +47,3 @@ content: { | ||
}, | ||
'5ecfa1233b8e50f60ea2b64b': { | ||
id: '5ecfa1233b8e50f60ea2b64b', | ||
name: 'secondaryButton', | ||
secondaryButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -81,5 +55,3 @@ content: { | ||
}, | ||
'5ecfa1233b8e50f60ea2b64c': { | ||
id: '5ecfa1233b8e50f60ea2b64c', | ||
name: 'conditionalButton', | ||
conditionalButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -121,4 +93,4 @@ conditions: [ | ||
expect(styleChunks.length).toBe(3) | ||
expect(dependencies.css.path).toBe('styled-components') | ||
expect(styleChunks.length).toBe(1) | ||
expect(dependencies.variant.path).toBe('styled-system') | ||
}) | ||
@@ -136,5 +108,3 @@ | ||
structure.uidl.styleSetDefinitions = { | ||
'5ecfa1233b8e50f60ea2b64d': { | ||
id: '5ecfa1233b8e50f60ea2b64d', | ||
name: 'primaryButton', | ||
primaryButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -146,5 +116,3 @@ content: { | ||
}, | ||
'5ecfa1233b8e50f60ea2b64b': { | ||
id: '5ecfa1233b8e50f60ea2b64b', | ||
name: 'secondaryButton', | ||
secondaryButton: { | ||
type: 'reusable-project-style-map', | ||
@@ -160,8 +128,12 @@ content: { | ||
const { chunks, dependencies } = result | ||
const styleChunks = chunks.filter((chunk) => chunk.name === 'style') | ||
const styleChunk = chunks.find((chunk) => chunk.name === 'index') | ||
const declaration = styleChunk.content.declaration.declarations[0] | ||
expect(styleChunks.length).toBe(0) | ||
expect(dependencies.css.path).toBe('styled-components') | ||
expect(styleChunk).toBeDefined() | ||
expect(dependencies.variant.path).toBe('styled-system') | ||
expect(result.uidl.outputOptions.fileName).toBe('index') | ||
expect(declaration.id.name).toBe('projectStyleVariants') | ||
expect(declaration.init.arguments[0].properties[0].value.value).toBe('projVariant') | ||
expect(declaration.init.arguments[0].properties[1].value.properties.length).toBe(2) | ||
}) | ||
}) |
@@ -8,2 +8,3 @@ import { ComponentPluginFactory, ComponentPlugin } from '@teleporthq/teleport-types'; | ||
illegalComponentNames?: string[]; | ||
classAttributeName?: string; | ||
} | ||
@@ -10,0 +11,0 @@ export declare const createReactStyledComponentsPlugin: ComponentPluginFactory<StyledComponentsConfig>; |
@@ -1,193 +0,449 @@ | ||
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __defProps = Object.defineProperties; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropDescs = Object.getOwnPropertyDescriptors; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __spreadValues = (a, b) => { | ||
for (var prop in b || (b = {})) | ||
if (__hasOwnProp.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
if (__getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(b)) { | ||
if (__propIsEnum.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
} | ||
return a; | ||
}; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __reExport = (target, module2, desc) => { | ||
if (module2 && typeof module2 === "object" || typeof module2 === "function") { | ||
for (let key of __getOwnPropNames(module2)) | ||
if (!__hasOwnProp.call(target, key) && key !== "default") | ||
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); | ||
} | ||
return target; | ||
}; | ||
var __toModule = (module2) => { | ||
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); | ||
}; | ||
var __async = (__this, __arguments, generator) => { | ||
return new Promise((resolve, reject) => { | ||
var fulfilled = (value) => { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
return __assign.apply(this, arguments); | ||
var rejected = (value) => { | ||
try { | ||
step(generator.throw(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); | ||
step((generator = generator.apply(__this, __arguments)).next()); | ||
}); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
// packages/teleport-plugin-react-styled-components/src/index.ts | ||
__markAsModule(exports); | ||
__export(exports, { | ||
createReactStyledComponentsPlugin: () => createReactStyledComponentsPlugin, | ||
createStyleSheetPlugin: () => createStyleSheetPlugin, | ||
default: () => src_default | ||
}); | ||
var types3 = __toModule(require("@babel/types")); | ||
var import_teleport_types3 = __toModule(require("@teleporthq/teleport-types")); | ||
var import_teleport_shared3 = __toModule(require("@teleporthq/teleport-shared")); | ||
var import_teleport_plugin_common = __toModule(require("@teleporthq/teleport-plugin-common")); | ||
// packages/teleport-plugin-react-styled-components/src/utils.ts | ||
var types = __toModule(require("@babel/types")); | ||
var import_teleport_shared = __toModule(require("@teleporthq/teleport-shared")); | ||
var import_teleport_types = __toModule(require("@teleporthq/teleport-types")); | ||
var generateStyledComponent = (params) => { | ||
const { | ||
name, | ||
elementType, | ||
styles, | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences | ||
} = params; | ||
let styleExpressions = styles; | ||
const expressionArguments = []; | ||
if (propsReferred.size > 0) { | ||
styleExpressions = types.arrowFunctionExpression([types.identifier("props")], styles); | ||
} | ||
if (projectStyleReferences.size > 0) { | ||
expressionArguments.push(...Array.from(projectStyleReferences).map((ref) => types.identifier(ref))); | ||
} | ||
if (styles && styles.properties.length > 0) { | ||
expressionArguments.push(styleExpressions); | ||
} | ||
if (componentStyleReferences.size > 0) { | ||
expressionArguments.push(...Array.from(componentStyleReferences).map((ref) => types.identifier(ref))); | ||
} | ||
return types.variableDeclaration("const", [ | ||
types.variableDeclarator(types.identifier(name), types.callExpression(types.callExpression(types.identifier("styled"), [types.stringLiteral(elementType)]), expressionArguments)) | ||
]); | ||
}; | ||
var removeUnusedDependencies = (dependencies, jsxNodesLookup) => { | ||
Object.keys(dependencies).forEach((depKey) => { | ||
const dependency = dependencies[depKey]; | ||
if (dependency.type === "library" && dependency.path === "react-native") { | ||
const dependencyIsStillNeeded = Object.keys(jsxNodesLookup).some((elementKey) => { | ||
const jsxNode = jsxNodesLookup[elementKey]; | ||
return jsxNode.openingElement.name.name === depKey; | ||
}); | ||
if (!dependencyIsStillNeeded) { | ||
delete dependencies[depKey]; | ||
} | ||
} | ||
}); | ||
}; | ||
var generateStyledComponentStyles = (params) => { | ||
const { | ||
styles, | ||
tokensReferred, | ||
propsReferred, | ||
propsPrefix = "props", | ||
tokensPrefix = "TOKENS" | ||
} = params; | ||
const properties = Object.keys(styles).reduce((acc, styleId) => { | ||
const style = styles[styleId]; | ||
const styleKey = types.stringLiteral(import_teleport_shared.StringUtils.camelCaseToDashCase(styleId)); | ||
if (style.type === "static") { | ||
const styleContent = typeof style.content === "string" ? types.stringLiteral(style.content) : types.numericLiteral(Number(style.content)); | ||
acc.push(types.objectProperty(styleKey, styleContent)); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "state") { | ||
throw new import_teleport_types.PluginStyledComponent(`Error running transformDynamicStyles in reactStyledComponentsPlugin. | ||
Unsupported styleValue.content.referenceType value ${style.content.referenceType}`); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "prop") { | ||
const isNestedProp = style.content.id.includes("."); | ||
acc.push(types.objectProperty(styleKey, types.memberExpression(types.identifier(propsPrefix), isNestedProp ? types.identifier(style.content.id) : types.identifier(`'${style.content.id}'`), !isNestedProp))); | ||
propsReferred == null ? void 0 : propsReferred.add(style.content.id); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "token") { | ||
const usedToken = import_teleport_shared.StringUtils.capitalize(import_teleport_shared.StringUtils.dashCaseToCamelCase(style.content.id)); | ||
acc.push(types.objectProperty(styleKey, types.memberExpression(types.identifier(tokensPrefix), types.identifier(usedToken)))); | ||
tokensReferred == null ? void 0 : tokensReferred.add(usedToken); | ||
} | ||
return acc; | ||
}, []); | ||
return types.objectExpression(properties); | ||
}; | ||
var generateVariantsfromStyleSet = (styleSets, variantPropPrefix, variantPropKey, tokensReferred) => { | ||
const variantExpressions = types.objectExpression(Object.keys(styleSets).reduce((acc, styleId) => { | ||
const style = styleSets[styleId]; | ||
const { content = {}, conditions = [] } = style; | ||
const property = types.objectProperty(types.stringLiteral(styleId), generateStyledComponentStyles(__spreadValues({ | ||
styles: content | ||
}, tokensReferred && { tokensReferred }))); | ||
conditions.forEach((cond) => { | ||
const mediaProperty = types.objectProperty(cond.type === "screen-size" ? types.stringLiteral(`@media(max-width: ${cond.meta.maxWidth}px)`) : types.stringLiteral(`&:${cond.meta.state}`), generateStyledComponentStyles(__spreadValues({ | ||
styles: cond.content | ||
}, tokensReferred && { tokensReferred }))); | ||
if (property.value.type === "ObjectExpression") { | ||
property.value.properties.push(mediaProperty); | ||
} | ||
}); | ||
acc.push(property); | ||
return acc; | ||
}, [])); | ||
return types.variableDeclaration("const", [ | ||
types.variableDeclarator(types.identifier(variantPropPrefix), types.callExpression(types.identifier("variant"), [ | ||
types.objectExpression([ | ||
types.objectProperty(types.identifier("prop"), types.stringLiteral(variantPropKey)), | ||
types.objectProperty(types.identifier("variants"), variantExpressions) | ||
]) | ||
])) | ||
]); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
// packages/teleport-plugin-react-styled-components/src/style-sheet.ts | ||
var types2 = __toModule(require("@babel/types")); | ||
var import_teleport_types2 = __toModule(require("@teleporthq/teleport-types")); | ||
var import_teleport_shared2 = __toModule(require("@teleporthq/teleport-shared")); | ||
// packages/teleport-plugin-react-styled-components/src/constants.ts | ||
var VARIANT_DEPENDENCY = { | ||
type: "package", | ||
path: "styled-system", | ||
version: "^5.1.5", | ||
meta: { | ||
namedImport: true | ||
} | ||
}; | ||
var componentVariantPropPrefix = "componentStyleVariants"; | ||
var componentVariantPropKey = "compVariant"; | ||
var projectVariantPropPrefix = "projectStyleVariants"; | ||
var projectVariantPropKey = "projVariant"; | ||
// packages/teleport-plugin-react-styled-components/src/style-sheet.ts | ||
var createStyleSheetPlugin = (config) => { | ||
const { fileName = "style" } = config || {}; | ||
const styleSheetPlugin = (structure) => __async(void 0, null, function* () { | ||
const { uidl, chunks, dependencies } = structure; | ||
const { styleSetDefinitions = {}, designLanguage: { tokens = {} } = {} } = uidl; | ||
if (Object.keys(styleSetDefinitions).length === 0 && Object.keys(tokens).length === 0) { | ||
return structure; | ||
} | ||
const tokensMap = Object.keys(tokens || {}).reduce((acc, key) => { | ||
const style = tokens[key]; | ||
const name = import_teleport_shared2.StringUtils.capitalize(import_teleport_shared2.StringUtils.dashCaseToCamelCase(key)); | ||
acc[name] = style.content; | ||
return acc; | ||
}, {}); | ||
if (Object.keys(styleSetDefinitions).length > 0) { | ||
const variants = generateVariantsfromStyleSet(styleSetDefinitions, projectVariantPropPrefix, projectVariantPropKey); | ||
chunks.push({ | ||
name: fileName, | ||
type: import_teleport_types2.ChunkType.AST, | ||
content: types2.exportNamedDeclaration(variants), | ||
fileType: import_teleport_types2.FileType.JS, | ||
linkAfter: ["tokens-chunk"] | ||
}); | ||
dependencies.variant = VARIANT_DEPENDENCY; | ||
} | ||
if (Object.keys(tokensMap).length > 0) { | ||
chunks.push({ | ||
name: "tokens-chunk", | ||
type: import_teleport_types2.ChunkType.AST, | ||
fileType: import_teleport_types2.FileType.JS, | ||
content: types2.exportNamedDeclaration(types2.variableDeclaration("const", [ | ||
types2.variableDeclarator(types2.identifier("TOKENS"), types2.objectExpression(Object.keys(tokensMap).reduce((acc, token) => { | ||
const value = typeof tokensMap[token] === "number" ? types2.numericLiteral(Number(tokensMap[token])) : types2.stringLiteral(String(tokensMap[token])); | ||
acc.push(types2.objectProperty(types2.identifier(token), value)); | ||
return acc; | ||
}, []))) | ||
])), | ||
linkAfter: ["import-local"] | ||
}); | ||
} | ||
uidl.outputOptions = uidl.outputOptions || {}; | ||
uidl.outputOptions.fileName = fileName; | ||
return structure; | ||
}); | ||
return styleSheetPlugin; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var teleport_types_1 = require("@teleporthq/teleport-types"); | ||
var teleport_shared_1 = require("@teleporthq/teleport-shared"); | ||
var teleport_plugin_common_1 = require("@teleporthq/teleport-plugin-common"); | ||
var utils_1 = require("./utils"); | ||
var style_sheet_1 = require("./style-sheet"); | ||
exports.createStyleSheetPlugin = style_sheet_1.createStyleSheetPlugin; | ||
exports.createReactStyledComponentsPlugin = function (config) { | ||
var _a = config || {}, _b = _a.componentChunkName, componentChunkName = _b === void 0 ? 'jsx-component' : _b, _c = _a.importChunkName, importChunkName = _c === void 0 ? 'import-local' : _c, _d = _a.componentLibrary, componentLibrary = _d === void 0 ? 'react' : _d, _e = _a.illegalComponentNames, illegalComponentNames = _e === void 0 ? [] : _e; | ||
var reactStyledComponentsPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () { | ||
var uidl, chunks, dependencies, options, node, name, projectStyleSet, componentChunk, jsxNodesLookup, propsPrefix, jssStyleMap, tokensReferred; | ||
return __generator(this, function (_a) { | ||
uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options; | ||
node = uidl.node, name = uidl.name; | ||
projectStyleSet = options.projectStyleSet; | ||
componentChunk = chunks.find(function (chunk) { return chunk.name === componentChunkName; }); | ||
if (!componentChunk) { | ||
return [2 /*return*/, structure]; | ||
} | ||
jsxNodesLookup = componentChunk.meta.nodesLookup; | ||
propsPrefix = componentChunk.meta.dynamicRefPrefix.prop; | ||
jssStyleMap = {}; | ||
tokensReferred = []; | ||
teleport_shared_1.UIDLUtils.traverseElements(node, function (element) { | ||
var _a; | ||
var style = element.style; | ||
var key = element.key, elementType = element.elementType, referencedStyles = element.referencedStyles; | ||
if (!style && !referencedStyles) { | ||
return; | ||
// packages/teleport-plugin-react-styled-components/src/index.ts | ||
var createReactStyledComponentsPlugin = (config) => { | ||
const { | ||
componentChunkName = "jsx-component", | ||
importChunkName = "import-local", | ||
componentLibrary = "react", | ||
illegalComponentNames = [], | ||
classAttributeName = "className" | ||
} = config || {}; | ||
const reactStyledComponentsPlugin = (structure) => __async(void 0, null, function* () { | ||
const { uidl, chunks, dependencies, options } = structure; | ||
const { node, name, styleSetDefinitions: componentStyleSheet = {} } = uidl; | ||
const { projectStyleSet } = options; | ||
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName); | ||
if (!componentChunk) { | ||
return structure; | ||
} | ||
const jsxNodesLookup = componentChunk.meta.nodesLookup; | ||
const propsPrefix = componentChunk.meta.dynamicRefPrefix.prop; | ||
const cssMap = {}; | ||
const tokensReferred = new Set(); | ||
if (Object.keys(componentStyleSheet).length > 0) { | ||
const variants = generateVariantsfromStyleSet(componentStyleSheet, componentVariantPropPrefix, componentVariantPropKey, tokensReferred); | ||
chunks.push({ | ||
name: "variant", | ||
type: import_teleport_types3.ChunkType.AST, | ||
content: variants, | ||
fileType: import_teleport_types3.FileType.JS, | ||
linkAfter: ["jsx-component"] | ||
}); | ||
dependencies.variant = VARIANT_DEPENDENCY; | ||
} | ||
import_teleport_shared3.UIDLUtils.traverseElements(node, (element) => { | ||
var _a; | ||
const { style = {} } = element; | ||
const { key, elementType, referencedStyles = {} } = element; | ||
const propsReferred = new Set(); | ||
const componentStyleReferences = new Set(); | ||
const projectStyleReferences = new Set(); | ||
const staticClasses = new Set(); | ||
if (Object.keys(style).length === 0 && Object.keys(referencedStyles).length === 0) { | ||
return; | ||
} | ||
const root = jsxNodesLookup[key]; | ||
let className = import_teleport_shared3.StringUtils.dashCaseToUpperCamelCase(key); | ||
if (style && Object.keys(style).length > 0) { | ||
if (illegalComponentNames.includes(className) || import_teleport_shared3.StringUtils.dashCaseToUpperCamelCase(key) === name || Object.keys(dependencies).includes(className)) { | ||
className = `Styled${className}`; | ||
} | ||
if (componentLibrary === "reactnative") { | ||
if (referencedStyles && Object.keys(referencedStyles).length > 0) { | ||
Object.keys(referencedStyles).forEach((styleId) => { | ||
const styleRef = referencedStyles[styleId]; | ||
if (styleRef.content.mapType === "inlined") { | ||
referencedStyles[styleId] = __spreadProps(__spreadValues({}, referencedStyles[styleId]), { | ||
content: __spreadProps(__spreadValues({}, referencedStyles[styleId].content), { | ||
styles: styleRef.content.styles | ||
}) | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
cssMap[className] = generateStyledComponentStyles({ | ||
styles: style, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
}); | ||
} | ||
if (referencedStyles && ((_a = Object.keys(referencedStyles)) == null ? void 0 : _a.length) > 0) { | ||
Object.values(referencedStyles).forEach((styleRef) => { | ||
var _a2; | ||
switch ((_a2 = styleRef.content) == null ? void 0 : _a2.mapType) { | ||
case "inlined": { | ||
const { conditions } = styleRef.content; | ||
const [condition] = conditions; | ||
if (condition.conditionType === "screen-size") { | ||
const nodeStyle = cssMap[className]; | ||
const mediaStyles = types3.objectProperty(types3.stringLiteral(`@media(max-width: ${condition.maxWidth}px)`), generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
})); | ||
if ((nodeStyle == null ? void 0 : nodeStyle.type) === "ObjectExpression") { | ||
nodeStyle.properties.push(mediaStyles); | ||
} else { | ||
cssMap[className] = import_teleport_plugin_common.ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]); | ||
} | ||
var root = jsxNodesLookup[key]; | ||
var className = teleport_shared_1.StringUtils.dashCaseToUpperCamelCase(key); | ||
var projectReferencedClassNames = []; | ||
var timesProsReferred = utils_1.countPropReferences(style, 0); | ||
timesProsReferred = utils_1.countPropRefernecesFromReferencedStyles(referencedStyles, timesProsReferred); | ||
if (style && Object.keys(style).length > 0) { | ||
/* Styled components might create an element that | ||
clashes with native element (Text, View, Image, etc.) */ | ||
if (illegalComponentNames.includes(className) || | ||
teleport_shared_1.StringUtils.dashCaseToUpperCamelCase(key) === name || | ||
Object.keys(dependencies).includes(className)) { | ||
className = "Styled" + className; | ||
} | ||
if (componentLibrary === 'reactnative') { | ||
if (referencedStyles && Object.keys(referencedStyles).length > 0) { | ||
Object.values(referencedStyles).forEach(function (styleRef) { | ||
if (styleRef.content.mapType === 'inlined') { | ||
referencedStyles[styleRef.id] = __assign(__assign({}, referencedStyles[styleRef.id]), { content: __assign(__assign({}, referencedStyles[styleRef.id].content), { | ||
// @ts-ignore | ||
styles: styleRef.content.styles }) }); | ||
} | ||
}); | ||
} | ||
} | ||
jssStyleMap[className] = utils_1.generatePropReferencesSyntax(style, timesProsReferred, tokensReferred, root, propsPrefix); | ||
} | ||
if (condition.conditionType === "element-state") { | ||
const nodeStyle = cssMap[className]; | ||
const mediaStyles = types3.objectProperty(types3.stringLiteral(`&:${condition.content}`), generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
})); | ||
if ((nodeStyle == null ? void 0 : nodeStyle.type) === "ObjectExpression") { | ||
nodeStyle.properties.push(mediaStyles); | ||
} else { | ||
cssMap[className] = import_teleport_plugin_common.ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]); | ||
} | ||
if (referencedStyles && ((_a = Object.keys(referencedStyles)) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||
Object.values(referencedStyles).forEach(function (styleRef) { | ||
var _a, _b; | ||
var _c, _d, _e; | ||
switch ((_c = styleRef.content) === null || _c === void 0 ? void 0 : _c.mapType) { | ||
case 'inlined': { | ||
var conditions = styleRef.content.conditions; | ||
var condition = conditions[0]; | ||
if (((_d = styleRef.content) === null || _d === void 0 ? void 0 : _d.styles) && Object.keys(styleRef.content.styles).length === 0) { | ||
return; | ||
} | ||
if (condition.conditionType === 'screen-size') { | ||
jssStyleMap[className] = __assign(__assign({}, jssStyleMap[className]), (_a = {}, _a["@media(max-width: " + condition.maxWidth + "px)"] = utils_1.generatePropReferencesSyntax(styleRef.content.styles, timesProsReferred, tokensReferred, root, propsPrefix), _a)); | ||
} | ||
if (condition.conditionType === 'element-state') { | ||
jssStyleMap[className] = __assign(__assign({}, jssStyleMap[className]), (_b = {}, _b["&:" + condition.content] = utils_1.generatePropReferencesSyntax(styleRef.content.styles, timesProsReferred, tokensReferred, root, propsPrefix), _b)); | ||
} | ||
return; | ||
} | ||
case 'project-referenced': { | ||
if (!projectStyleSet) { | ||
throw new Error("Project Style Sheet is missing, but the node is referring to it " + element); | ||
} | ||
var content = styleRef.content; | ||
if (content.referenceId && !((_e = content) === null || _e === void 0 ? void 0 : _e.conditions)) { | ||
var referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId]; | ||
if (!referedStyle) { | ||
throw new Error("Style that is being used for reference is missing - " + content.referenceId); | ||
} | ||
var styleName = teleport_shared_1.StringUtils.dashCaseToUpperCamelCase(referedStyle.name); | ||
projectReferencedClassNames.push(styleName); | ||
dependencies[styleName] = { | ||
type: 'local', | ||
path: projectStyleSet.path + "/" + projectStyleSet.fileName, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
}; | ||
} | ||
return; | ||
} | ||
default: { | ||
throw new Error("\n We support only inlined and project-referenced styles as of now, received " + styleRef.content + "\n "); | ||
} | ||
} | ||
}); | ||
} | ||
return; | ||
} | ||
case "component-referenced": { | ||
if (componentStyleReferences.size > 0) { | ||
throw new import_teleport_types3.PluginStyledComponent(`Styled Component can have only one reference per node. | ||
i.e either a direct static reference from component style sheet or from props. Got both. ${JSON.stringify(Array.from(componentStyleReferences), null, 2)}`); | ||
} | ||
if (styleRef.content.content.type === "static") { | ||
staticClasses.add(types3.identifier(`'${styleRef.content.content.content}'`)); | ||
} | ||
if (styleRef.content.content.type === "dynamic" && styleRef.content.content.content.referenceType === "comp") { | ||
componentStyleReferences.add(componentVariantPropPrefix); | ||
import_teleport_plugin_common.ASTUtils.addAttributeToJSXTag(root, componentVariantPropKey, styleRef.content.content.content.id); | ||
} | ||
if (styleRef.content.content.type === "dynamic" && styleRef.content.content.content.referenceType === "prop") { | ||
componentStyleReferences.add(componentVariantPropPrefix); | ||
import_teleport_plugin_common.ASTUtils.addDynamicAttributeToJSXTag(root, componentVariantPropKey, `${propsPrefix}.${styleRef.content.content.content.id}`); | ||
} | ||
return; | ||
} | ||
case "project-referenced": { | ||
if (!projectStyleSet) { | ||
throw new Error(`Project Style Sheet is missing, but the node is referring to it ${element}`); | ||
} | ||
const { content } = styleRef; | ||
const referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId]; | ||
if (!referedStyle) { | ||
throw new Error(`Style that is being used for reference is missing - ${content.referenceId}`); | ||
} | ||
dependencies[projectVariantPropPrefix] = { | ||
type: "local", | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true | ||
} | ||
if (timesProsReferred > 1) { | ||
teleport_plugin_common_1.ASTUtils.addSpreadAttributeToJSXTag(root, propsPrefix); | ||
} | ||
teleport_plugin_common_1.ASTUtils.renameJSXTag(root, className); | ||
var code = { | ||
type: teleport_types_1.ChunkType.AST, | ||
fileType: teleport_types_1.FileType.JS, | ||
name: className, | ||
linkAfter: [importChunkName], | ||
content: utils_1.generateStyledComponent(className, elementType, jssStyleMap[className], projectReferencedClassNames), | ||
}; | ||
chunks.push(code); | ||
}); | ||
if (Object.keys(jssStyleMap).length === 0) { | ||
return [2 /*return*/, structure]; | ||
}; | ||
projectStyleReferences.add(projectVariantPropPrefix); | ||
import_teleport_plugin_common.ASTUtils.addAttributeToJSXTag(root, projectVariantPropKey, content.referenceId); | ||
return; | ||
} | ||
if (tokensReferred.length > 0) { | ||
dependencies.TOKENS = { | ||
type: 'local', | ||
path: projectStyleSet.path + "/" + projectStyleSet.fileName, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
}; | ||
default: { | ||
throw new Error(` | ||
We support only inlined and project-referenced styles as of now, received ${JSON.stringify(styleRef.content, null, 2)} | ||
`); | ||
} | ||
dependencies.styled = { | ||
type: 'package', | ||
path: componentLibrary === 'react' ? 'styled-components' : 'styled-components/native', | ||
version: '4.2.0', | ||
}; | ||
/* React Native elements are imported from styled-components/native, | ||
so direct dependency to `react-native` is removed */ | ||
if (componentLibrary === 'reactnative') { | ||
utils_1.removeUnusedDependencies(dependencies, jsxNodesLookup); | ||
} | ||
return [2 /*return*/, structure]; | ||
} | ||
}); | ||
}); }; | ||
return reactStyledComponentsPlugin; | ||
} | ||
if (propsReferred.size > 0) { | ||
import_teleport_plugin_common.ASTUtils.addSpreadAttributeToJSXTag(root, propsPrefix); | ||
} | ||
if (staticClasses.size > 0) { | ||
import_teleport_plugin_common.ASTUtils.addMultipleDynamicAttributesToJSXTag(root, classAttributeName, Array.from(staticClasses)); | ||
} | ||
import_teleport_plugin_common.ASTUtils.renameJSXTag(root, className); | ||
const code = { | ||
type: import_teleport_types3.ChunkType.AST, | ||
fileType: import_teleport_types3.FileType.JS, | ||
name: className, | ||
linkAfter: [importChunkName], | ||
content: generateStyledComponent({ | ||
name: className, | ||
styles: cssMap[className], | ||
elementType, | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences | ||
}) | ||
}; | ||
chunks.push(code); | ||
}); | ||
if (Object.keys(cssMap).length === 0) { | ||
return structure; | ||
} | ||
if (tokensReferred.size > 0) { | ||
dependencies.TOKENS = { | ||
type: "local", | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true | ||
} | ||
}; | ||
} | ||
dependencies.styled = { | ||
type: "package", | ||
path: componentLibrary === "react" ? "styled-components" : "styled-components/native", | ||
version: "^5.3.0" | ||
}; | ||
if (componentLibrary === "reactnative") { | ||
removeUnusedDependencies(dependencies, jsxNodesLookup); | ||
} | ||
return structure; | ||
}); | ||
return reactStyledComponentsPlugin; | ||
}; | ||
exports.default = exports.createReactStyledComponentsPlugin(); | ||
//# sourceMappingURL=index.js.map | ||
var src_default = createReactStyledComponentsPlugin(); |
import { ComponentPluginFactory } from '@teleporthq/teleport-types'; | ||
interface StyleSheetPlugin { | ||
fileName?: string; | ||
componentLibrary?: string; | ||
} | ||
export declare const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin>; | ||
export {}; |
@@ -1,9 +0,19 @@ | ||
import * as t from '@babel/types'; | ||
import { UIDLStyleValue, UIDLDependency } from '@teleporthq/teleport-types'; | ||
export declare const generateStyledComponent: (name: string, type: string, styles: Record<string, unknown>, projectReferencedStyles?: string[]) => t.VariableDeclaration; | ||
export declare const generateCSSInterpolate: (name: string, styles: Record<string, unknown>) => t.VariableDeclaration; | ||
export declare const generateExportablCSSInterpolate: (name: string, styles: Record<string, unknown>) => t.ExportNamedDeclaration; | ||
export declare const countPropReferences: (style: Record<string, UIDLStyleValue>, timesReferred: number) => number; | ||
export declare const countPropRefernecesFromReferencedStyles: (styles: Record<string, import("@teleporthq/teleport-types").UIDLElementNodeReferenceStyles>, timesReferred: number) => number; | ||
export declare const removeUnusedDependencies: (dependencies: Record<string, UIDLDependency>, jsxNodesLookup: Record<string, t.JSXElement>) => void; | ||
export declare const generatePropReferencesSyntax: (style: Record<string, UIDLStyleValue>, timesPropsReferred?: number, tokensReferred?: string[], root?: t.JSXElement, propsPrefix?: unknown) => Record<string, any>; | ||
import * as types from '@babel/types'; | ||
import { UIDLStyleValue, UIDLDependency, UIDLStyleSetDefinition } from '@teleporthq/teleport-types'; | ||
export declare const generateStyledComponent: (params: { | ||
name: string; | ||
elementType: string; | ||
styles: types.ObjectExpression; | ||
propsReferred: Set<string>; | ||
componentStyleReferences: Set<string>; | ||
projectStyleReferences: Set<string>; | ||
}) => types.VariableDeclaration; | ||
export declare const removeUnusedDependencies: (dependencies: Record<string, UIDLDependency>, jsxNodesLookup: Record<string, types.JSXElement>) => void; | ||
export declare const generateStyledComponentStyles: (params: { | ||
styles: Record<string, UIDLStyleValue>; | ||
propsReferred?: Set<string>; | ||
tokensReferred?: Set<string>; | ||
propsPrefix?: string; | ||
tokensPrefix?: string; | ||
}) => types.ObjectExpression; | ||
export declare const generateVariantsfromStyleSet: (styleSets: Record<string, UIDLStyleSetDefinition>, variantPropPrefix: string, variantPropKey: string, tokensReferred?: Set<string>) => types.VariableDeclaration; |
@@ -1,154 +0,461 @@ | ||
import { ChunkType, FileType, } from '@teleporthq/teleport-types'; | ||
import { UIDLUtils, StringUtils } from '@teleporthq/teleport-shared'; | ||
import { ASTUtils } from '@teleporthq/teleport-plugin-common'; | ||
import { generateStyledComponent, countPropReferences, removeUnusedDependencies, generatePropReferencesSyntax, countPropRefernecesFromReferencedStyles, } from './utils'; | ||
import { createStyleSheetPlugin } from './style-sheet'; | ||
export const createReactStyledComponentsPlugin = (config) => { | ||
const { componentChunkName = 'jsx-component', importChunkName = 'import-local', componentLibrary = 'react', illegalComponentNames = [], } = config || {}; | ||
const reactStyledComponentsPlugin = async (structure) => { | ||
const { uidl, chunks, dependencies, options } = structure; | ||
const { node, name } = uidl; | ||
const { projectStyleSet } = options; | ||
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName); | ||
if (!componentChunk) { | ||
return structure; | ||
var __defProp = Object.defineProperty; | ||
var __defProps = Object.defineProperties; | ||
var __getOwnPropDescs = Object.getOwnPropertyDescriptors; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __spreadValues = (a, b) => { | ||
for (var prop in b || (b = {})) | ||
if (__hasOwnProp.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
if (__getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(b)) { | ||
if (__propIsEnum.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
} | ||
return a; | ||
}; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __async = (__this, __arguments, generator) => { | ||
return new Promise((resolve, reject) => { | ||
var fulfilled = (value) => { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var rejected = (value) => { | ||
try { | ||
step(generator.throw(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); | ||
step((generator = generator.apply(__this, __arguments)).next()); | ||
}); | ||
}; | ||
// packages/teleport-plugin-react-styled-components/src/index.ts | ||
import { | ||
identifier as identifier3, | ||
objectProperty as objectProperty3, | ||
stringLiteral as stringLiteral3 | ||
} from "@babel/types"; | ||
import { | ||
ChunkType as ChunkType2, | ||
FileType as FileType2, | ||
PluginStyledComponent as PluginStyledComponent2 | ||
} from "@teleporthq/teleport-types"; | ||
import { UIDLUtils, StringUtils as StringUtils3 } from "@teleporthq/teleport-shared"; | ||
import { ASTUtils } from "@teleporthq/teleport-plugin-common"; | ||
// packages/teleport-plugin-react-styled-components/src/utils.ts | ||
import { | ||
arrowFunctionExpression, | ||
callExpression, | ||
identifier, | ||
memberExpression, | ||
numericLiteral, | ||
objectExpression, | ||
objectProperty, | ||
stringLiteral, | ||
variableDeclaration, | ||
variableDeclarator | ||
} from "@babel/types"; | ||
import { StringUtils } from "@teleporthq/teleport-shared"; | ||
import { | ||
PluginStyledComponent | ||
} from "@teleporthq/teleport-types"; | ||
var generateStyledComponent = (params) => { | ||
const { | ||
name, | ||
elementType, | ||
styles, | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences | ||
} = params; | ||
let styleExpressions = styles; | ||
const expressionArguments = []; | ||
if (propsReferred.size > 0) { | ||
styleExpressions = arrowFunctionExpression([identifier("props")], styles); | ||
} | ||
if (projectStyleReferences.size > 0) { | ||
expressionArguments.push(...Array.from(projectStyleReferences).map((ref) => identifier(ref))); | ||
} | ||
if (styles && styles.properties.length > 0) { | ||
expressionArguments.push(styleExpressions); | ||
} | ||
if (componentStyleReferences.size > 0) { | ||
expressionArguments.push(...Array.from(componentStyleReferences).map((ref) => identifier(ref))); | ||
} | ||
return variableDeclaration("const", [ | ||
variableDeclarator(identifier(name), callExpression(callExpression(identifier("styled"), [stringLiteral(elementType)]), expressionArguments)) | ||
]); | ||
}; | ||
var removeUnusedDependencies = (dependencies, jsxNodesLookup) => { | ||
Object.keys(dependencies).forEach((depKey) => { | ||
const dependency = dependencies[depKey]; | ||
if (dependency.type === "library" && dependency.path === "react-native") { | ||
const dependencyIsStillNeeded = Object.keys(jsxNodesLookup).some((elementKey) => { | ||
const jsxNode = jsxNodesLookup[elementKey]; | ||
return jsxNode.openingElement.name.name === depKey; | ||
}); | ||
if (!dependencyIsStillNeeded) { | ||
delete dependencies[depKey]; | ||
} | ||
} | ||
}); | ||
}; | ||
var generateStyledComponentStyles = (params) => { | ||
const { | ||
styles, | ||
tokensReferred, | ||
propsReferred, | ||
propsPrefix = "props", | ||
tokensPrefix = "TOKENS" | ||
} = params; | ||
const properties = Object.keys(styles).reduce((acc, styleId) => { | ||
const style = styles[styleId]; | ||
const styleKey = stringLiteral(StringUtils.camelCaseToDashCase(styleId)); | ||
if (style.type === "static") { | ||
const styleContent = typeof style.content === "string" ? stringLiteral(style.content) : numericLiteral(Number(style.content)); | ||
acc.push(objectProperty(styleKey, styleContent)); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "state") { | ||
throw new PluginStyledComponent(`Error running transformDynamicStyles in reactStyledComponentsPlugin. | ||
Unsupported styleValue.content.referenceType value ${style.content.referenceType}`); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "prop") { | ||
const isNestedProp = style.content.id.includes("."); | ||
acc.push(objectProperty(styleKey, memberExpression(identifier(propsPrefix), isNestedProp ? identifier(style.content.id) : identifier(`'${style.content.id}'`), !isNestedProp))); | ||
propsReferred == null ? void 0 : propsReferred.add(style.content.id); | ||
} | ||
if (style.type === "dynamic" && style.content.referenceType === "token") { | ||
const usedToken = StringUtils.capitalize(StringUtils.dashCaseToCamelCase(style.content.id)); | ||
acc.push(objectProperty(styleKey, memberExpression(identifier(tokensPrefix), identifier(usedToken)))); | ||
tokensReferred == null ? void 0 : tokensReferred.add(usedToken); | ||
} | ||
return acc; | ||
}, []); | ||
return objectExpression(properties); | ||
}; | ||
var generateVariantsfromStyleSet = (styleSets, variantPropPrefix, variantPropKey, tokensReferred) => { | ||
const variantExpressions = objectExpression(Object.keys(styleSets).reduce((acc, styleId) => { | ||
const style = styleSets[styleId]; | ||
const { content = {}, conditions = [] } = style; | ||
const property = objectProperty(stringLiteral(styleId), generateStyledComponentStyles(__spreadValues({ | ||
styles: content | ||
}, tokensReferred && { tokensReferred }))); | ||
conditions.forEach((cond) => { | ||
const mediaProperty = objectProperty(cond.type === "screen-size" ? stringLiteral(`@media(max-width: ${cond.meta.maxWidth}px)`) : stringLiteral(`&:${cond.meta.state}`), generateStyledComponentStyles(__spreadValues({ | ||
styles: cond.content | ||
}, tokensReferred && { tokensReferred }))); | ||
if (property.value.type === "ObjectExpression") { | ||
property.value.properties.push(mediaProperty); | ||
} | ||
}); | ||
acc.push(property); | ||
return acc; | ||
}, [])); | ||
return variableDeclaration("const", [ | ||
variableDeclarator(identifier(variantPropPrefix), callExpression(identifier("variant"), [ | ||
objectExpression([ | ||
objectProperty(identifier("prop"), stringLiteral(variantPropKey)), | ||
objectProperty(identifier("variants"), variantExpressions) | ||
]) | ||
])) | ||
]); | ||
}; | ||
// packages/teleport-plugin-react-styled-components/src/style-sheet.ts | ||
import { | ||
exportNamedDeclaration, | ||
identifier as identifier2, | ||
numericLiteral as numericLiteral2, | ||
objectExpression as objectExpression2, | ||
objectProperty as objectProperty2, | ||
stringLiteral as stringLiteral2, | ||
variableDeclaration as variableDeclaration2, | ||
variableDeclarator as variableDeclarator2 | ||
} from "@babel/types"; | ||
import { | ||
ChunkType, | ||
FileType | ||
} from "@teleporthq/teleport-types"; | ||
import { StringUtils as StringUtils2 } from "@teleporthq/teleport-shared"; | ||
// packages/teleport-plugin-react-styled-components/src/constants.ts | ||
var VARIANT_DEPENDENCY = { | ||
type: "package", | ||
path: "styled-system", | ||
version: "^5.1.5", | ||
meta: { | ||
namedImport: true | ||
} | ||
}; | ||
var componentVariantPropPrefix = "componentStyleVariants"; | ||
var componentVariantPropKey = "compVariant"; | ||
var projectVariantPropPrefix = "projectStyleVariants"; | ||
var projectVariantPropKey = "projVariant"; | ||
// packages/teleport-plugin-react-styled-components/src/style-sheet.ts | ||
var createStyleSheetPlugin = (config) => { | ||
const { fileName = "style" } = config || {}; | ||
const styleSheetPlugin = (structure) => __async(void 0, null, function* () { | ||
const { uidl, chunks, dependencies } = structure; | ||
const { styleSetDefinitions = {}, designLanguage: { tokens = {} } = {} } = uidl; | ||
if (Object.keys(styleSetDefinitions).length === 0 && Object.keys(tokens).length === 0) { | ||
return structure; | ||
} | ||
const tokensMap = Object.keys(tokens || {}).reduce((acc, key) => { | ||
const style = tokens[key]; | ||
const name = StringUtils2.capitalize(StringUtils2.dashCaseToCamelCase(key)); | ||
acc[name] = style.content; | ||
return acc; | ||
}, {}); | ||
if (Object.keys(styleSetDefinitions).length > 0) { | ||
const variants = generateVariantsfromStyleSet(styleSetDefinitions, projectVariantPropPrefix, projectVariantPropKey); | ||
chunks.push({ | ||
name: fileName, | ||
type: ChunkType.AST, | ||
content: exportNamedDeclaration(variants), | ||
fileType: FileType.JS, | ||
linkAfter: ["tokens-chunk"] | ||
}); | ||
dependencies.variant = VARIANT_DEPENDENCY; | ||
} | ||
if (Object.keys(tokensMap).length > 0) { | ||
chunks.push({ | ||
name: "tokens-chunk", | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
content: exportNamedDeclaration(variableDeclaration2("const", [ | ||
variableDeclarator2(identifier2("TOKENS"), objectExpression2(Object.keys(tokensMap).reduce((acc, token) => { | ||
const value = typeof tokensMap[token] === "number" ? numericLiteral2(Number(tokensMap[token])) : stringLiteral2(String(tokensMap[token])); | ||
acc.push(objectProperty2(identifier2(token), value)); | ||
return acc; | ||
}, []))) | ||
])), | ||
linkAfter: ["import-local"] | ||
}); | ||
} | ||
uidl.outputOptions = uidl.outputOptions || {}; | ||
uidl.outputOptions.fileName = fileName; | ||
return structure; | ||
}); | ||
return styleSheetPlugin; | ||
}; | ||
// packages/teleport-plugin-react-styled-components/src/index.ts | ||
var createReactStyledComponentsPlugin = (config) => { | ||
const { | ||
componentChunkName = "jsx-component", | ||
importChunkName = "import-local", | ||
componentLibrary = "react", | ||
illegalComponentNames = [], | ||
classAttributeName = "className" | ||
} = config || {}; | ||
const reactStyledComponentsPlugin = (structure) => __async(void 0, null, function* () { | ||
const { uidl, chunks, dependencies, options } = structure; | ||
const { node, name, styleSetDefinitions: componentStyleSheet = {} } = uidl; | ||
const { projectStyleSet } = options; | ||
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName); | ||
if (!componentChunk) { | ||
return structure; | ||
} | ||
const jsxNodesLookup = componentChunk.meta.nodesLookup; | ||
const propsPrefix = componentChunk.meta.dynamicRefPrefix.prop; | ||
const cssMap = {}; | ||
const tokensReferred = new Set(); | ||
if (Object.keys(componentStyleSheet).length > 0) { | ||
const variants = generateVariantsfromStyleSet(componentStyleSheet, componentVariantPropPrefix, componentVariantPropKey, tokensReferred); | ||
chunks.push({ | ||
name: "variant", | ||
type: ChunkType2.AST, | ||
content: variants, | ||
fileType: FileType2.JS, | ||
linkAfter: ["jsx-component"] | ||
}); | ||
dependencies.variant = VARIANT_DEPENDENCY; | ||
} | ||
UIDLUtils.traverseElements(node, (element) => { | ||
var _a; | ||
const { style = {} } = element; | ||
const { key, elementType, referencedStyles = {} } = element; | ||
const propsReferred = new Set(); | ||
const componentStyleReferences = new Set(); | ||
const projectStyleReferences = new Set(); | ||
const staticClasses = new Set(); | ||
if (Object.keys(style).length === 0 && Object.keys(referencedStyles).length === 0) { | ||
return; | ||
} | ||
const root = jsxNodesLookup[key]; | ||
let className = StringUtils3.dashCaseToUpperCamelCase(key); | ||
if (style && Object.keys(style).length > 0) { | ||
if (illegalComponentNames.includes(className) || StringUtils3.dashCaseToUpperCamelCase(key) === name || Object.keys(dependencies).includes(className)) { | ||
className = `Styled${className}`; | ||
} | ||
const jsxNodesLookup = componentChunk.meta.nodesLookup; | ||
// @ts-ignore | ||
const propsPrefix = componentChunk.meta.dynamicRefPrefix.prop; | ||
const jssStyleMap = {}; | ||
const tokensReferred = []; | ||
UIDLUtils.traverseElements(node, (element) => { | ||
var _a; | ||
const { style } = element; | ||
const { key, elementType, referencedStyles } = element; | ||
if (!style && !referencedStyles) { | ||
return; | ||
} | ||
const root = jsxNodesLookup[key]; | ||
let className = StringUtils.dashCaseToUpperCamelCase(key); | ||
const projectReferencedClassNames = []; | ||
let timesProsReferred = countPropReferences(style, 0); | ||
timesProsReferred = countPropRefernecesFromReferencedStyles(referencedStyles, timesProsReferred); | ||
if (style && Object.keys(style).length > 0) { | ||
/* Styled components might create an element that | ||
clashes with native element (Text, View, Image, etc.) */ | ||
if (illegalComponentNames.includes(className) || | ||
StringUtils.dashCaseToUpperCamelCase(key) === name || | ||
Object.keys(dependencies).includes(className)) { | ||
className = `Styled${className}`; | ||
if (componentLibrary === "reactnative") { | ||
if (referencedStyles && Object.keys(referencedStyles).length > 0) { | ||
Object.keys(referencedStyles).forEach((styleId) => { | ||
const styleRef = referencedStyles[styleId]; | ||
if (styleRef.content.mapType === "inlined") { | ||
referencedStyles[styleId] = __spreadProps(__spreadValues({}, referencedStyles[styleId]), { | ||
content: __spreadProps(__spreadValues({}, referencedStyles[styleId].content), { | ||
styles: styleRef.content.styles | ||
}) | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
cssMap[className] = generateStyledComponentStyles({ | ||
styles: style, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
}); | ||
} | ||
if (referencedStyles && ((_a = Object.keys(referencedStyles)) == null ? void 0 : _a.length) > 0) { | ||
Object.values(referencedStyles).forEach((styleRef) => { | ||
var _a2; | ||
switch ((_a2 = styleRef.content) == null ? void 0 : _a2.mapType) { | ||
case "inlined": { | ||
const { conditions } = styleRef.content; | ||
const [condition] = conditions; | ||
if (condition.conditionType === "screen-size") { | ||
const nodeStyle = cssMap[className]; | ||
const mediaStyles = objectProperty3(stringLiteral3(`@media(max-width: ${condition.maxWidth}px)`), generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
})); | ||
if ((nodeStyle == null ? void 0 : nodeStyle.type) === "ObjectExpression") { | ||
nodeStyle.properties.push(mediaStyles); | ||
} else { | ||
cssMap[className] = ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]); | ||
} | ||
if (componentLibrary === 'reactnative') { | ||
if (referencedStyles && Object.keys(referencedStyles).length > 0) { | ||
Object.values(referencedStyles).forEach((styleRef) => { | ||
if (styleRef.content.mapType === 'inlined') { | ||
referencedStyles[styleRef.id] = { | ||
...referencedStyles[styleRef.id], | ||
content: { | ||
...referencedStyles[styleRef.id].content, | ||
// @ts-ignore | ||
styles: styleRef.content.styles, | ||
}, | ||
}; | ||
} | ||
}); | ||
} | ||
} | ||
if (condition.conditionType === "element-state") { | ||
const nodeStyle = cssMap[className]; | ||
const mediaStyles = objectProperty3(stringLiteral3(`&:${condition.content}`), generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
propsPrefix, | ||
tokensPrefix: "TOKENS" | ||
})); | ||
if ((nodeStyle == null ? void 0 : nodeStyle.type) === "ObjectExpression") { | ||
nodeStyle.properties.push(mediaStyles); | ||
} else { | ||
cssMap[className] = ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]); | ||
} | ||
jssStyleMap[className] = generatePropReferencesSyntax(style, timesProsReferred, tokensReferred, root, propsPrefix); | ||
} | ||
return; | ||
} | ||
if (referencedStyles && ((_a = Object.keys(referencedStyles)) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||
Object.values(referencedStyles).forEach((styleRef) => { | ||
var _a, _b, _c; | ||
switch ((_a = styleRef.content) === null || _a === void 0 ? void 0 : _a.mapType) { | ||
case 'inlined': { | ||
const { conditions } = styleRef.content; | ||
const [condition] = conditions; | ||
if (((_b = styleRef.content) === null || _b === void 0 ? void 0 : _b.styles) && Object.keys(styleRef.content.styles).length === 0) { | ||
return; | ||
} | ||
if (condition.conditionType === 'screen-size') { | ||
jssStyleMap[className] = { | ||
...jssStyleMap[className], | ||
[`@media(max-width: ${condition.maxWidth}px)`]: generatePropReferencesSyntax(styleRef.content.styles, timesProsReferred, tokensReferred, root, propsPrefix), | ||
}; | ||
} | ||
if (condition.conditionType === 'element-state') { | ||
jssStyleMap[className] = { | ||
...jssStyleMap[className], | ||
[`&:${condition.content}`]: generatePropReferencesSyntax(styleRef.content.styles, timesProsReferred, tokensReferred, root, propsPrefix), | ||
}; | ||
} | ||
return; | ||
} | ||
case 'project-referenced': { | ||
if (!projectStyleSet) { | ||
throw new Error(`Project Style Sheet is missing, but the node is referring to it ${element}`); | ||
} | ||
const { content } = styleRef; | ||
if (content.referenceId && !((_c = content) === null || _c === void 0 ? void 0 : _c.conditions)) { | ||
const referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId]; | ||
if (!referedStyle) { | ||
throw new Error(`Style that is being used for reference is missing - ${content.referenceId}`); | ||
} | ||
const styleName = StringUtils.dashCaseToUpperCamelCase(referedStyle.name); | ||
projectReferencedClassNames.push(styleName); | ||
dependencies[styleName] = { | ||
type: 'local', | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
}; | ||
} | ||
return; | ||
} | ||
default: { | ||
throw new Error(` | ||
We support only inlined and project-referenced styles as of now, received ${styleRef.content} | ||
`); | ||
} | ||
} | ||
}); | ||
case "component-referenced": { | ||
if (componentStyleReferences.size > 0) { | ||
throw new PluginStyledComponent2(`Styled Component can have only one reference per node. | ||
i.e either a direct static reference from component style sheet or from props. Got both. ${JSON.stringify(Array.from(componentStyleReferences), null, 2)}`); | ||
} | ||
if (styleRef.content.content.type === "static") { | ||
staticClasses.add(identifier3(`'${styleRef.content.content.content}'`)); | ||
} | ||
if (styleRef.content.content.type === "dynamic" && styleRef.content.content.content.referenceType === "comp") { | ||
componentStyleReferences.add(componentVariantPropPrefix); | ||
ASTUtils.addAttributeToJSXTag(root, componentVariantPropKey, styleRef.content.content.content.id); | ||
} | ||
if (styleRef.content.content.type === "dynamic" && styleRef.content.content.content.referenceType === "prop") { | ||
componentStyleReferences.add(componentVariantPropPrefix); | ||
ASTUtils.addDynamicAttributeToJSXTag(root, componentVariantPropKey, `${propsPrefix}.${styleRef.content.content.content.id}`); | ||
} | ||
return; | ||
} | ||
if (timesProsReferred > 1) { | ||
ASTUtils.addSpreadAttributeToJSXTag(root, propsPrefix); | ||
case "project-referenced": { | ||
if (!projectStyleSet) { | ||
throw new Error(`Project Style Sheet is missing, but the node is referring to it ${element}`); | ||
} | ||
const { content } = styleRef; | ||
const referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId]; | ||
if (!referedStyle) { | ||
throw new Error(`Style that is being used for reference is missing - ${content.referenceId}`); | ||
} | ||
dependencies[projectVariantPropPrefix] = { | ||
type: "local", | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true | ||
} | ||
}; | ||
projectStyleReferences.add(projectVariantPropPrefix); | ||
ASTUtils.addAttributeToJSXTag(root, projectVariantPropKey, content.referenceId); | ||
return; | ||
} | ||
ASTUtils.renameJSXTag(root, className); | ||
const code = { | ||
type: ChunkType.AST, | ||
fileType: FileType.JS, | ||
name: className, | ||
linkAfter: [importChunkName], | ||
content: generateStyledComponent(className, elementType, jssStyleMap[className], projectReferencedClassNames), | ||
}; | ||
chunks.push(code); | ||
default: { | ||
throw new Error(` | ||
We support only inlined and project-referenced styles as of now, received ${JSON.stringify(styleRef.content, null, 2)} | ||
`); | ||
} | ||
} | ||
}); | ||
if (Object.keys(jssStyleMap).length === 0) { | ||
return structure; | ||
} | ||
if (propsReferred.size > 0) { | ||
ASTUtils.addSpreadAttributeToJSXTag(root, propsPrefix); | ||
} | ||
if (staticClasses.size > 0) { | ||
ASTUtils.addMultipleDynamicAttributesToJSXTag(root, classAttributeName, Array.from(staticClasses)); | ||
} | ||
ASTUtils.renameJSXTag(root, className); | ||
const code = { | ||
type: ChunkType2.AST, | ||
fileType: FileType2.JS, | ||
name: className, | ||
linkAfter: [importChunkName], | ||
content: generateStyledComponent({ | ||
name: className, | ||
styles: cssMap[className], | ||
elementType, | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences | ||
}) | ||
}; | ||
chunks.push(code); | ||
}); | ||
if (Object.keys(cssMap).length === 0) { | ||
return structure; | ||
} | ||
if (tokensReferred.size > 0) { | ||
dependencies.TOKENS = { | ||
type: "local", | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true | ||
} | ||
if (tokensReferred.length > 0) { | ||
dependencies.TOKENS = { | ||
type: 'local', | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
}; | ||
} | ||
dependencies.styled = { | ||
type: 'package', | ||
path: componentLibrary === 'react' ? 'styled-components' : 'styled-components/native', | ||
version: '4.2.0', | ||
}; | ||
/* React Native elements are imported from styled-components/native, | ||
so direct dependency to `react-native` is removed */ | ||
if (componentLibrary === 'reactnative') { | ||
removeUnusedDependencies(dependencies, jsxNodesLookup); | ||
} | ||
return structure; | ||
}; | ||
} | ||
dependencies.styled = { | ||
type: "package", | ||
path: componentLibrary === "react" ? "styled-components" : "styled-components/native", | ||
version: "^5.3.0" | ||
}; | ||
return reactStyledComponentsPlugin; | ||
if (componentLibrary === "reactnative") { | ||
removeUnusedDependencies(dependencies, jsxNodesLookup); | ||
} | ||
return structure; | ||
}); | ||
return reactStyledComponentsPlugin; | ||
}; | ||
export { createStyleSheetPlugin }; | ||
export default createReactStyledComponentsPlugin(); | ||
//# sourceMappingURL=index.js.map | ||
var src_default = createReactStyledComponentsPlugin(); | ||
export { | ||
createReactStyledComponentsPlugin, | ||
createStyleSheetPlugin, | ||
src_default as default | ||
}; |
{ | ||
"name": "@teleporthq/teleport-plugin-react-styled-components", | ||
"version": "0.16.3", | ||
"version": "0.17.0", | ||
"description": "A plugin for injecting the styles through styled-components inside React components", | ||
@@ -11,2 +11,7 @@ "author": "teleportHQ", | ||
"module": "dist/esm/index.js", | ||
"exports": { | ||
"module": "./dist/esm/index.js", | ||
"require": "./dist/cjs/index.js", | ||
"import": "./dist/esm/index.js" | ||
}, | ||
"sideEffects": false, | ||
@@ -25,13 +30,11 @@ "repository": { | ||
"clean": "rimraf dist", | ||
"build": "npm run build:cjs & npm run build:esm", | ||
"build:cjs": "tsc -p tsconfig-cjs.json", | ||
"build:esm": "tsc -p tsconfig-esm.json" | ||
"types": "tsc -p tsconfig.json" | ||
}, | ||
"dependencies": { | ||
"@babel/types": "^7.5.5", | ||
"@teleporthq/teleport-plugin-common": "^0.16.3", | ||
"@teleporthq/teleport-shared": "^0.16.3", | ||
"@teleporthq/teleport-types": "^0.16.3" | ||
"@teleporthq/teleport-plugin-common": "^0.17.0", | ||
"@teleporthq/teleport-shared": "^0.17.0", | ||
"@teleporthq/teleport-types": "^0.17.0" | ||
}, | ||
"gitHead": "7e373501206d293ea7ac0494b563ee5f6a2fccb2" | ||
"gitHead": "959317a18068b52ffd8b912e41d123f70d97e7bc" | ||
} |
238
src/index.ts
@@ -7,2 +7,3 @@ import * as types from '@babel/types' | ||
FileType, | ||
PluginStyledComponent, | ||
} from '@teleporthq/teleport-types' | ||
@@ -13,8 +14,14 @@ import { UIDLUtils, StringUtils } from '@teleporthq/teleport-shared' | ||
generateStyledComponent, | ||
countPropReferences, | ||
removeUnusedDependencies, | ||
generatePropReferencesSyntax, | ||
countPropRefernecesFromReferencedStyles, | ||
generateVariantsfromStyleSet, | ||
generateStyledComponentStyles, | ||
} from './utils' | ||
import { createStyleSheetPlugin } from './style-sheet' | ||
import { | ||
componentVariantPropKey, | ||
componentVariantPropPrefix, | ||
projectVariantPropKey, | ||
projectVariantPropPrefix, | ||
VARIANT_DEPENDENCY, | ||
} from './constants' | ||
@@ -26,2 +33,3 @@ interface StyledComponentsConfig { | ||
illegalComponentNames?: string[] | ||
classAttributeName?: string | ||
} | ||
@@ -37,2 +45,3 @@ | ||
illegalComponentNames = [], | ||
classAttributeName = 'className', | ||
} = config || {} | ||
@@ -42,3 +51,3 @@ | ||
const { uidl, chunks, dependencies, options } = structure | ||
const { node, name } = uidl | ||
const { node, name, styleSetDefinitions: componentStyleSheet = {} } = uidl | ||
const { projectStyleSet } = options | ||
@@ -51,12 +60,32 @@ const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName) | ||
const jsxNodesLookup = componentChunk.meta.nodesLookup as Record<string, types.JSXElement> | ||
// @ts-ignore | ||
const propsPrefix = componentChunk.meta.dynamicRefPrefix.prop | ||
const jssStyleMap: Record<string, unknown> = {} | ||
const tokensReferred: string[] = [] | ||
const propsPrefix = componentChunk.meta.dynamicRefPrefix.prop as string | ||
const cssMap: Record<string, types.ObjectExpression> = {} | ||
const tokensReferred: Set<string> = new Set() | ||
if (Object.keys(componentStyleSheet).length > 0) { | ||
const variants = generateVariantsfromStyleSet( | ||
componentStyleSheet, | ||
componentVariantPropPrefix, | ||
componentVariantPropKey, | ||
tokensReferred | ||
) | ||
chunks.push({ | ||
name: 'variant', | ||
type: ChunkType.AST, | ||
content: variants, | ||
fileType: FileType.JS, | ||
linkAfter: ['jsx-component'], | ||
}) | ||
dependencies.variant = VARIANT_DEPENDENCY | ||
} | ||
UIDLUtils.traverseElements(node, (element) => { | ||
const { style } = element | ||
const { key, elementType, referencedStyles } = element | ||
const { style = {} } = element | ||
const { key, elementType, referencedStyles = {} } = element | ||
const propsReferred: Set<string> = new Set() | ||
const componentStyleReferences: Set<string> = new Set() | ||
const projectStyleReferences: Set<string> = new Set() | ||
const staticClasses: Set<types.Identifier> = new Set() | ||
if (!style && !referencedStyles) { | ||
if (Object.keys(style).length === 0 && Object.keys(referencedStyles).length === 0) { | ||
return | ||
@@ -67,14 +96,6 @@ } | ||
let className = StringUtils.dashCaseToUpperCamelCase(key) | ||
const projectReferencedClassNames: string[] = [] | ||
let timesProsReferred = countPropReferences(style, 0) | ||
timesProsReferred = countPropRefernecesFromReferencedStyles( | ||
referencedStyles, | ||
timesProsReferred | ||
) | ||
if (style && Object.keys(style).length > 0) { | ||
/* Styled components might create an element that | ||
clashes with native element (Text, View, Image, etc.) */ | ||
clashes with native element (Text, View, Image, etc.) */ | ||
if ( | ||
@@ -90,8 +111,9 @@ illegalComponentNames.includes(className) || | ||
if (referencedStyles && Object.keys(referencedStyles).length > 0) { | ||
Object.values(referencedStyles).forEach((styleRef) => { | ||
Object.keys(referencedStyles).forEach((styleId) => { | ||
const styleRef = referencedStyles[styleId] | ||
if (styleRef.content.mapType === 'inlined') { | ||
referencedStyles[styleRef.id] = { | ||
...referencedStyles[styleRef.id], | ||
referencedStyles[styleId] = { | ||
...referencedStyles[styleId], | ||
content: { | ||
...referencedStyles[styleRef.id].content, | ||
...referencedStyles[styleId].content, | ||
// @ts-ignore | ||
@@ -105,9 +127,9 @@ styles: styleRef.content.styles, | ||
} | ||
jssStyleMap[className] = generatePropReferencesSyntax( | ||
style, | ||
timesProsReferred, | ||
cssMap[className] = generateStyledComponentStyles({ | ||
styles: style, | ||
propsReferred, | ||
tokensReferred, | ||
root, | ||
propsPrefix | ||
) | ||
propsPrefix, | ||
tokensPrefix: 'TOKENS', | ||
}) | ||
} | ||
@@ -122,16 +144,18 @@ | ||
if (styleRef.content?.styles && Object.keys(styleRef.content.styles).length === 0) { | ||
return | ||
} | ||
if (condition.conditionType === 'screen-size') { | ||
jssStyleMap[className] = { | ||
...(jssStyleMap[className] as Record<string, string>), | ||
[`@media(max-width: ${condition.maxWidth}px)`]: generatePropReferencesSyntax( | ||
styleRef.content.styles, | ||
timesProsReferred, | ||
const nodeStyle = cssMap[className] | ||
const mediaStyles = types.objectProperty( | ||
types.stringLiteral(`@media(max-width: ${condition.maxWidth}px)`), | ||
generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
root, | ||
propsPrefix | ||
), | ||
propsPrefix, | ||
tokensPrefix: 'TOKENS', | ||
}) | ||
) | ||
if (nodeStyle?.type === 'ObjectExpression') { | ||
nodeStyle.properties.push(mediaStyles) | ||
} else { | ||
cssMap[className] = ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]) | ||
} | ||
@@ -141,11 +165,17 @@ } | ||
if (condition.conditionType === 'element-state') { | ||
jssStyleMap[className] = { | ||
...(jssStyleMap[className] as Record<string, string>), | ||
[`&:${condition.content}`]: generatePropReferencesSyntax( | ||
styleRef.content.styles, | ||
timesProsReferred, | ||
const nodeStyle = cssMap[className] | ||
const mediaStyles = types.objectProperty( | ||
types.stringLiteral(`&:${condition.content}`), | ||
generateStyledComponentStyles({ | ||
styles: styleRef.content.styles, | ||
propsReferred, | ||
tokensReferred, | ||
root, | ||
propsPrefix | ||
), | ||
propsPrefix, | ||
tokensPrefix: 'TOKENS', | ||
}) | ||
) | ||
if (nodeStyle?.type === 'ObjectExpression') { | ||
nodeStyle.properties.push(mediaStyles) | ||
} else { | ||
cssMap[className] = ASTUtils.wrapObjectPropertiesWithExpression([mediaStyles]) | ||
} | ||
@@ -156,2 +186,44 @@ } | ||
} | ||
case 'component-referenced': { | ||
if (componentStyleReferences.size > 0) { | ||
throw new PluginStyledComponent(`Styled Component can have only one reference per node. | ||
i.e either a direct static reference from component style sheet or from props. Got both. ${JSON.stringify( | ||
Array.from(componentStyleReferences), | ||
null, | ||
2 | ||
)}`) | ||
} | ||
if (styleRef.content.content.type === 'static') { | ||
staticClasses.add(types.identifier(`'${styleRef.content.content.content}'`)) | ||
} | ||
if ( | ||
styleRef.content.content.type === 'dynamic' && | ||
styleRef.content.content.content.referenceType === 'comp' | ||
) { | ||
componentStyleReferences.add(componentVariantPropPrefix) | ||
ASTUtils.addAttributeToJSXTag( | ||
root, | ||
componentVariantPropKey, | ||
styleRef.content.content.content.id | ||
) | ||
} | ||
if ( | ||
styleRef.content.content.type === 'dynamic' && | ||
styleRef.content.content.content.referenceType === 'prop' | ||
) { | ||
componentStyleReferences.add(componentVariantPropPrefix) | ||
ASTUtils.addDynamicAttributeToJSXTag( | ||
root, | ||
componentVariantPropKey, | ||
`${propsPrefix}.${styleRef.content.content.content.id}` | ||
) | ||
} | ||
return | ||
} | ||
case 'project-referenced': { | ||
@@ -164,20 +236,18 @@ if (!projectStyleSet) { | ||
const { content } = styleRef | ||
if (content.referenceId && !content?.conditions) { | ||
const referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId] | ||
if (!referedStyle) { | ||
throw new Error( | ||
`Style that is being used for reference is missing - ${content.referenceId}` | ||
) | ||
} | ||
const styleName = StringUtils.dashCaseToUpperCamelCase(referedStyle.name) | ||
projectReferencedClassNames.push(styleName) | ||
dependencies[styleName] = { | ||
type: 'local', | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
} | ||
const referedStyle = projectStyleSet.styleSetDefinitions[content.referenceId] | ||
if (!referedStyle) { | ||
throw new Error( | ||
`Style that is being used for reference is missing - ${content.referenceId}` | ||
) | ||
} | ||
dependencies[projectVariantPropPrefix] = { | ||
type: 'local', | ||
path: `${projectStyleSet.path}/${projectStyleSet.fileName}`, | ||
meta: { | ||
namedImport: true, | ||
}, | ||
} | ||
projectStyleReferences.add(projectVariantPropPrefix) | ||
ASTUtils.addAttributeToJSXTag(root, projectVariantPropKey, content.referenceId) | ||
return | ||
@@ -187,4 +257,8 @@ } | ||
throw new Error(` | ||
We support only inlined and project-referenced styles as of now, received ${styleRef.content} | ||
`) | ||
We support only inlined and project-referenced styles as of now, received ${JSON.stringify( | ||
styleRef.content, | ||
null, | ||
2 | ||
)} | ||
`) | ||
} | ||
@@ -195,6 +269,14 @@ } | ||
if (timesProsReferred > 1) { | ||
if (propsReferred.size > 0) { | ||
ASTUtils.addSpreadAttributeToJSXTag(root, propsPrefix) | ||
} | ||
if (staticClasses.size > 0) { | ||
ASTUtils.addMultipleDynamicAttributesToJSXTag( | ||
root, | ||
classAttributeName, | ||
Array.from(staticClasses) | ||
) | ||
} | ||
ASTUtils.renameJSXTag(root, className) | ||
@@ -207,8 +289,10 @@ | ||
linkAfter: [importChunkName], | ||
content: generateStyledComponent( | ||
className, | ||
content: generateStyledComponent({ | ||
name: className, | ||
styles: cssMap[className], | ||
elementType, | ||
jssStyleMap[className] as Record<string, unknown>, | ||
projectReferencedClassNames | ||
), | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences, | ||
}), | ||
} | ||
@@ -218,7 +302,7 @@ chunks.push(code) | ||
if (Object.keys(jssStyleMap).length === 0) { | ||
if (Object.keys(cssMap).length === 0) { | ||
return structure | ||
} | ||
if (tokensReferred.length > 0) { | ||
if (tokensReferred.size > 0) { | ||
dependencies.TOKENS = { | ||
@@ -236,3 +320,3 @@ type: 'local', | ||
path: componentLibrary === 'react' ? 'styled-components' : 'styled-components/native', | ||
version: '4.2.0', | ||
version: '^5.3.0', | ||
} | ||
@@ -239,0 +323,0 @@ |
@@ -1,2 +0,2 @@ | ||
import * as t from '@babel/types' | ||
import * as types from '@babel/types' | ||
import { | ||
@@ -8,12 +8,12 @@ ComponentPlugin, | ||
} from '@teleporthq/teleport-types' | ||
import { generateExportablCSSInterpolate, generatePropReferencesSyntax } from './utils' | ||
import { generateVariantsfromStyleSet } from './utils' | ||
import { StringUtils } from '@teleporthq/teleport-shared' | ||
import { projectVariantPropKey, projectVariantPropPrefix, VARIANT_DEPENDENCY } from './constants' | ||
interface StyleSheetPlugin { | ||
fileName?: string | ||
componentLibrary?: string | ||
} | ||
export const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin> = (config) => { | ||
const { fileName = 'style', componentLibrary = 'react' } = config || {} | ||
const { fileName = 'style' } = config || {} | ||
@@ -23,7 +23,3 @@ const styleSheetPlugin: ComponentPlugin = async (structure) => { | ||
const { styleSetDefinitions = {}, designLanguage: { tokens = {} } = {} } = uidl | ||
if ( | ||
(!styleSetDefinitions && !tokens) || | ||
(Object.keys(styleSetDefinitions).length === 0 && Object.keys(tokens).length === 0) | ||
) { | ||
if (Object.keys(styleSetDefinitions).length === 0 && Object.keys(tokens).length === 0) { | ||
return structure | ||
@@ -42,58 +38,18 @@ } | ||
Object.values(styleSetDefinitions).forEach((style) => { | ||
const { name, content, conditions = [] } = style | ||
const className = StringUtils.dashCaseToUpperCamelCase(name) | ||
let styles = {} | ||
styles = { | ||
...styles, | ||
...generatePropReferencesSyntax(content), | ||
} | ||
if (conditions.length > 0) { | ||
conditions.forEach((styleRef) => { | ||
if (Object.keys(styleRef.content).length === 0) { | ||
return | ||
} | ||
if (styleRef.type === 'screen-size') { | ||
styles = { | ||
...styles, | ||
...{ | ||
[`@media(max-width: ${styleRef.meta.maxWidth}px)`]: generatePropReferencesSyntax( | ||
styleRef.content | ||
), | ||
}, | ||
} | ||
} | ||
if (styleRef.type === 'element-state') { | ||
styles = { | ||
...styles, | ||
...{ | ||
[`&:${styleRef.meta.state}`]: generatePropReferencesSyntax(styleRef.content), | ||
}, | ||
} | ||
} | ||
}) | ||
} | ||
if (Object.keys(styleSetDefinitions).length > 0) { | ||
const variants = generateVariantsfromStyleSet( | ||
styleSetDefinitions, | ||
projectVariantPropPrefix, | ||
projectVariantPropKey | ||
) | ||
chunks.push({ | ||
name: fileName, | ||
type: ChunkType.AST, | ||
content: types.exportNamedDeclaration(variants), | ||
fileType: FileType.JS, | ||
content: generateExportablCSSInterpolate(className, styles), | ||
linkAfter: ['tokens-chunk'], | ||
}) | ||
dependencies.variant = VARIANT_DEPENDENCY | ||
} | ||
dependencies.css = { | ||
type: 'package', | ||
path: componentLibrary === 'react' ? 'styled-components' : 'styled-components/native', | ||
version: '4.2.0', | ||
meta: { | ||
namedImport: true, | ||
}, | ||
} | ||
}) | ||
if (Object.keys(tokensMap).length > 0) { | ||
@@ -104,13 +60,13 @@ chunks.push({ | ||
fileType: FileType.JS, | ||
content: t.exportNamedDeclaration( | ||
t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.identifier('TOKENS'), | ||
t.objectExpression( | ||
Object.keys(tokensMap).reduce((acc: t.ObjectProperty[], token) => { | ||
content: types.exportNamedDeclaration( | ||
types.variableDeclaration('const', [ | ||
types.variableDeclarator( | ||
types.identifier('TOKENS'), | ||
types.objectExpression( | ||
Object.keys(tokensMap).reduce((acc: types.ObjectProperty[], token) => { | ||
const value = | ||
typeof tokensMap[token] === 'number' | ||
? t.numericLiteral(Number(tokensMap[token])) | ||
: t.stringLiteral(String(tokensMap[token])) | ||
acc.push(t.objectProperty(t.identifier(token), value)) | ||
? types.numericLiteral(Number(tokensMap[token])) | ||
: types.stringLiteral(String(tokensMap[token])) | ||
acc.push(types.objectProperty(types.identifier(token), value)) | ||
return acc | ||
@@ -117,0 +73,0 @@ }, []) |
277
src/utils.ts
@@ -1,83 +0,60 @@ | ||
import * as t from '@babel/types' | ||
import { StringUtils, UIDLUtils } from '@teleporthq/teleport-shared' | ||
import { ASTUtils } from '@teleporthq/teleport-plugin-common' | ||
import { UIDLStyleValue, UIDLDependency, UIDLReferencedStyles } from '@teleporthq/teleport-types' | ||
import * as types from '@babel/types' | ||
import { StringUtils } from '@teleporthq/teleport-shared' | ||
import { | ||
UIDLStyleValue, | ||
UIDLDependency, | ||
UIDLStyleSetDefinition, | ||
PluginStyledComponent, | ||
} from '@teleporthq/teleport-types' | ||
export const generateStyledComponent = ( | ||
name: string, | ||
type: string, | ||
styles: Record<string, unknown>, | ||
projectReferencedStyles?: string[] | ||
) => { | ||
return t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.identifier(name), | ||
t.taggedTemplateExpression( | ||
t.memberExpression(t.identifier('styled'), t.identifier(type)), | ||
projectReferencedStyles?.length > 0 | ||
? ASTUtils.stringAsTemplateLiteral( | ||
`${projectReferencedStyles.map((item) => `\$\{${item}\};`)} ${mapStyles(styles)}` | ||
) | ||
: ASTUtils.stringAsTemplateLiteral(mapStyles(styles)) | ||
) | ||
), | ||
]) | ||
} | ||
export const generateStyledComponent = (params: { | ||
name: string | ||
elementType: string | ||
styles: types.ObjectExpression | ||
propsReferred: Set<string> | ||
componentStyleReferences: Set<string> | ||
projectStyleReferences: Set<string> | ||
}) => { | ||
const { | ||
name, | ||
elementType, | ||
styles, | ||
propsReferred, | ||
componentStyleReferences, | ||
projectStyleReferences, | ||
} = params | ||
let styleExpressions: types.ObjectExpression | types.ArrowFunctionExpression = styles | ||
const expressionArguments: Array< | ||
types.ObjectExpression | types.ArrowFunctionExpression | types.Identifier | ||
> = [] | ||
export const generateCSSInterpolate = (name: string, styles: Record<string, unknown>) => { | ||
return t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.identifier(name), | ||
t.taggedTemplateExpression( | ||
t.identifier('css'), | ||
ASTUtils.stringAsTemplateLiteral(mapStyles(styles)) | ||
) | ||
), | ||
]) | ||
} | ||
if (propsReferred.size > 0) { | ||
styleExpressions = types.arrowFunctionExpression([types.identifier('props')], styles) | ||
} | ||
export const generateExportablCSSInterpolate = (name: string, styles: Record<string, unknown>) => { | ||
return t.exportNamedDeclaration(generateCSSInterpolate(name, styles)) | ||
} | ||
if (projectStyleReferences.size > 0) { | ||
expressionArguments.push( | ||
...Array.from(projectStyleReferences).map((ref) => types.identifier(ref)) | ||
) | ||
} | ||
const mapStyles = (styles: Record<string, unknown>): string => { | ||
return Object.keys(styles || {}).reduce((acc: string, item) => { | ||
const value = styles[item] | ||
acc = | ||
typeof value === 'string' || typeof value === 'number' | ||
? `${acc} ${StringUtils.camelCaseToDashCase(item)}: ${value}; \n` | ||
: `${acc} ${item} {\n ${mapStyles(value as Record<string, unknown>)}};` | ||
return acc | ||
}, ``) | ||
} | ||
if (styles && styles.properties.length > 0) { | ||
expressionArguments.push(styleExpressions) | ||
} | ||
export const countPropReferences = ( | ||
style: Record<string, UIDLStyleValue>, | ||
timesReferred: number | ||
) => { | ||
if (style && Object.keys(style).length > 0) { | ||
Object.keys(style).map((item) => { | ||
const styleAttr = style[item] | ||
if (styleAttr.type === 'dynamic' && styleAttr.content.referenceType === 'prop') { | ||
timesReferred++ | ||
} | ||
}) | ||
return timesReferred | ||
if (componentStyleReferences.size > 0) { | ||
expressionArguments.push( | ||
...Array.from(componentStyleReferences).map((ref) => types.identifier(ref)) | ||
) | ||
} | ||
return timesReferred | ||
} | ||
export const countPropRefernecesFromReferencedStyles = ( | ||
styles: UIDLReferencedStyles, | ||
timesReferred: number | ||
) => { | ||
let propsCount = 0 | ||
if (styles && Object.keys(styles).length > 0) { | ||
Object.values(styles).forEach((styleRef) => { | ||
if (styleRef.content.mapType === 'inlined') { | ||
propsCount = countPropReferences(styleRef.content.styles, 0) | ||
} | ||
}) | ||
} | ||
return timesReferred + propsCount | ||
return types.variableDeclaration('const', [ | ||
types.variableDeclarator( | ||
types.identifier(name), | ||
types.callExpression( | ||
types.callExpression(types.identifier('styled'), [types.stringLiteral(elementType)]), | ||
expressionArguments | ||
) | ||
), | ||
]) | ||
} | ||
@@ -87,3 +64,3 @@ | ||
dependencies: Record<string, UIDLDependency>, | ||
jsxNodesLookup: Record<string, t.JSXElement> | ||
jsxNodesLookup: Record<string, types.JSXElement> | ||
) => { | ||
@@ -95,3 +72,3 @@ Object.keys(dependencies).forEach((depKey) => { | ||
const jsxNode = jsxNodesLookup[elementKey] | ||
return (jsxNode.openingElement.name as t.JSXIdentifier).name === depKey | ||
return (jsxNode.openingElement.name as types.JSXIdentifier).name === depKey | ||
}) | ||
@@ -106,35 +83,121 @@ | ||
export const generatePropReferencesSyntax = ( | ||
style: Record<string, UIDLStyleValue>, | ||
timesPropsReferred?: number, | ||
tokensReferred?: string[], | ||
root?: t.JSXElement, | ||
propsPrefix?: unknown | ||
) => { | ||
return UIDLUtils.transformDynamicStyles(style, (styleValue, attribute) => { | ||
switch (styleValue.content.referenceType) { | ||
case 'prop': { | ||
const dashCaseAttribute = StringUtils.dashCaseToCamelCase(attribute) | ||
if (timesPropsReferred && timesPropsReferred === 1 && root && propsPrefix) { | ||
ASTUtils.addDynamicAttributeToJSXTag( | ||
root, | ||
dashCaseAttribute, | ||
styleValue.content.id, | ||
propsPrefix as string | ||
export const generateStyledComponentStyles = (params: { | ||
styles: Record<string, UIDLStyleValue> | ||
propsReferred?: Set<string> | ||
tokensReferred?: Set<string> | ||
propsPrefix?: string | ||
tokensPrefix?: string | ||
}): types.ObjectExpression => { | ||
const { | ||
styles, | ||
tokensReferred, | ||
propsReferred, | ||
propsPrefix = 'props', | ||
tokensPrefix = 'TOKENS', | ||
} = params | ||
const properties: types.ObjectProperty[] = Object.keys(styles).reduce( | ||
(acc: types.ObjectProperty[], styleId) => { | ||
const style = styles[styleId] | ||
const styleKey = types.stringLiteral(StringUtils.camelCaseToDashCase(styleId)) | ||
if (style.type === 'static') { | ||
const styleContent = | ||
typeof style.content === 'string' | ||
? types.stringLiteral(style.content) | ||
: types.numericLiteral(Number(style.content)) | ||
acc.push(types.objectProperty(styleKey, styleContent)) | ||
} | ||
if (style.type === 'dynamic' && style.content.referenceType === 'state') { | ||
throw new PluginStyledComponent(`Error running transformDynamicStyles in reactStyledComponentsPlugin. | ||
Unsupported styleValue.content.referenceType value ${style.content.referenceType}`) | ||
} | ||
if (style.type === 'dynamic' && style.content.referenceType === 'prop') { | ||
const isNestedProp = style.content.id.includes('.') | ||
acc.push( | ||
types.objectProperty( | ||
styleKey, | ||
types.memberExpression( | ||
types.identifier(propsPrefix), | ||
isNestedProp | ||
? types.identifier(style.content.id) | ||
: types.identifier(`'${style.content.id}'`), | ||
!isNestedProp | ||
) | ||
) | ||
return `\$\{props => props.${dashCaseAttribute}\}` | ||
} | ||
return `\$\{props => props.${styleValue.content.id}\}` | ||
) | ||
propsReferred?.add(style.content.id) | ||
} | ||
case 'token': | ||
const token = StringUtils.capitalize(StringUtils.dashCaseToCamelCase(styleValue.content.id)) | ||
tokensReferred?.push(token) | ||
return `\$\{TOKENS.${token}\}` | ||
default: | ||
throw new Error( | ||
`Error running transformDynamicStyles in reactStyledComponentsPlugin. | ||
Unsupported styleValue.content.referenceType value ${styleValue.content.referenceType}` | ||
if (style.type === 'dynamic' && style.content.referenceType === 'token') { | ||
const usedToken = StringUtils.capitalize(StringUtils.dashCaseToCamelCase(style.content.id)) | ||
acc.push( | ||
types.objectProperty( | ||
styleKey, | ||
types.memberExpression(types.identifier(tokensPrefix), types.identifier(usedToken)) | ||
) | ||
) | ||
} | ||
}) | ||
tokensReferred?.add(usedToken) | ||
} | ||
return acc | ||
}, | ||
[] | ||
) | ||
return types.objectExpression(properties) | ||
} | ||
export const generateVariantsfromStyleSet = ( | ||
styleSets: Record<string, UIDLStyleSetDefinition>, | ||
variantPropPrefix: string, | ||
variantPropKey: string, | ||
tokensReferred?: Set<string> | ||
) => { | ||
const variantExpressions = types.objectExpression( | ||
Object.keys(styleSets).reduce((acc: types.ObjectProperty[], styleId) => { | ||
const style = styleSets[styleId] | ||
const { content = {}, conditions = [] } = style | ||
const property = types.objectProperty( | ||
types.stringLiteral(styleId), | ||
generateStyledComponentStyles({ | ||
styles: content, | ||
...(tokensReferred && { tokensReferred }), | ||
}) | ||
) | ||
conditions.forEach((cond) => { | ||
const mediaProperty = types.objectProperty( | ||
cond.type === 'screen-size' | ||
? types.stringLiteral(`@media(max-width: ${cond.meta.maxWidth}px)`) | ||
: types.stringLiteral(`&:${cond.meta.state}`), | ||
generateStyledComponentStyles({ | ||
styles: cond.content, | ||
...(tokensReferred && { tokensReferred }), | ||
}) | ||
) | ||
if (property.value.type === 'ObjectExpression') { | ||
property.value.properties.push(mediaProperty) | ||
} | ||
}) | ||
acc.push(property) | ||
return acc | ||
}, []) | ||
) | ||
return types.variableDeclaration('const', [ | ||
types.variableDeclarator( | ||
types.identifier(variantPropPrefix), | ||
types.callExpression(types.identifier('variant'), [ | ||
types.objectExpression([ | ||
types.objectProperty(types.identifier('prop'), types.stringLiteral(variantPropKey)), | ||
types.objectProperty(types.identifier('variants'), variantExpressions), | ||
]), | ||
]) | ||
), | ||
]) | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1966
15.38%154794
-55.4%20
-37.5%1
Infinity%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed