Repository: teleporthq/teleport-code-generators (ts)

Issue:
Plugin for React external stylesheets
There are still considerable numbers of React users that do not use css-modules or css-in-js.

For that, we could have a plugin that extracts the css in a separate file next to the .js file and imports the style file: `import './component.css'`

Pull request description:
refactor(css): teleport-plugin-css now works for both html templates and jsx code chunks
`react` now supports: `CSS`, `CSSModules`, `InlineStyles`, `StyledJSX`, `StyledComponents`, `JSS`
`preact` now supports: `CSS`, `CSSModules`, `InlineStyles`

also closes #332 

Patch:
diff --git a/packages/teleport-component-generator-angular/src/index.ts b/packages/teleport-component-generator-angular/src/index.ts
index 8edbf3f0..67353ac9 100644
--- a/packages/teleport-component-generator-angular/src/index.ts
+++ b/packages/teleport-component-generator-angular/src/index.ts
@@ -13,7 +13,8 @@ import { Mapping, ComponentGenerator } from '@teleporthq/teleport-types'
 const importStatementsPlugin = createImportPlugin({ fileType: FILE_TYPE.TS })
 const prettierJS = createPostProcessor({ fileType: FILE_TYPE.TS })
 const stylePlugin = createStylePlugin({
-  dynamicStyleAttributeKey: () => '[ngStyle]',
+  inlineStyleAttributeKey: '[ngStyle]',
+  declareDependency: 'decorator',
 })
 
 export const createAngularComponentGenerator = (mapping: Mapping = {}): ComponentGenerator => {
diff --git a/packages/teleport-component-generator-preact/package.json b/packages/teleport-component-generator-preact/package.json
index 4ac9aaaa..2d6a0b9c 100644
--- a/packages/teleport-component-generator-preact/package.json
+++ b/packages/teleport-component-generator-preact/package.json
@@ -28,6 +28,8 @@
     "@teleporthq/teleport-component-generator": "^0.8.1",
     "@teleporthq/teleport-plugin-import-statements": "^0.8.1",
     "@teleporthq/teleport-plugin-preact-base-component": "^0.8.1",
+    "@teleporthq/teleport-plugin-react-inline-styles": "^0.8.1",
+    "@teleporthq/teleport-plugin-css": "^0.8.1",
     "@teleporthq/teleport-plugin-css-modules": "^0.8.1",
     "@teleporthq/teleport-plugin-jsx-proptypes": "^0.8.1",
     "@teleporthq/teleport-postprocessor-prettier-js": "^0.8.1",
diff --git a/packages/teleport-component-generator-preact/src/index.ts b/packages/teleport-component-generator-preact/src/index.ts
index f37f698f..967efabe 100644
--- a/packages/teleport-component-generator-preact/src/index.ts
+++ b/packages/teleport-component-generator-preact/src/index.ts
@@ -1,5 +1,7 @@
 import preactComponentPlugin from '@teleporthq/teleport-plugin-preact-base-component'
 import { createPlugin as createCSSModulesPlugin } from '@teleporthq/teleport-plugin-css-modules'
+import { createPlugin as createCSSPlugin } from '@teleporthq/teleport-plugin-css'
+import jsxInlineStylesPlugin from '@teleporthq/teleport-plugin-react-inline-styles'
 import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
 import proptypesPlugin from '@teleporthq/teleport-plugin-jsx-proptypes'
 
@@ -11,19 +13,35 @@ import preactMapping from './preact-mapping.json'
 
 import { ComponentGenerator, Mapping } from '@teleporthq/teleport-types'
 
+const cssPlugin = createCSSPlugin({
+  templateChunkName: 'jsx-component',
+  templateStyle: 'jsx',
+  declareDependency: 'import',
+})
+
 const cssModulesPlugin = createCSSModulesPlugin({
   classAttributeName: 'class',
   moduleExtension: false,
 })
 
-export const createPreactComponentGenerator = (mapping: Mapping = {}): ComponentGenerator => {
+const stylePlugins = {
+  InlineStyles: jsxInlineStylesPlugin,
+  CSSModules: cssModulesPlugin,
+  CSS: cssPlugin,
+}
+
+export const createPreactComponentGenerator = (
+  variation: string = 'CSS',
+  mapping: Mapping = {}
+): ComponentGenerator => {
   const generator = createComponentGenerator()
+  const stylePlugin = stylePlugins[variation] || cssPlugin
 
   generator.addMapping(preactMapping)
   generator.addMapping(mapping)
 
   generator.addPlugin(preactComponentPlugin)
-  generator.addPlugin(cssModulesPlugin)
+  generator.addPlugin(stylePlugin)
   generator.addPlugin(proptypesPlugin)
   generator.addPlugin(importStatementsPlugin)
 
diff --git a/packages/teleport-component-generator-react/package.json b/packages/teleport-component-generator-react/package.json
index 24e0fb4b..75f44a06 100644
--- a/packages/teleport-component-generator-react/package.json
+++ b/packages/teleport-component-generator-react/package.json
@@ -28,6 +28,7 @@
     "@teleporthq/teleport-component-generator": "^0.8.1",
     "@teleporthq/teleport-plugin-import-statements": "^0.8.1",
     "@teleporthq/teleport-plugin-react-base-component": "^0.8.1",
+    "@teleporthq/teleport-plugin-css": "^0.8.1",
     "@teleporthq/teleport-plugin-css-modules": "^0.8.1",
     "@teleporthq/teleport-plugin-react-inline-styles": "^0.8.1",
     "@teleporthq/teleport-plugin-react-jss": "^0.8.1",
diff --git a/packages/teleport-component-generator-react/src/index.ts b/packages/teleport-component-generator-react/src/index.ts
index 9285da2a..5b9f2acb 100644
--- a/packages/teleport-component-generator-react/src/index.ts
+++ b/packages/teleport-component-generator-react/src/index.ts
@@ -2,6 +2,7 @@ import reactComponentPlugin from '@teleporthq/teleport-plugin-react-base-compone
 import reactInlineStylesPlugin from '@teleporthq/teleport-plugin-react-inline-styles'
 import reactJSSPlugin from '@teleporthq/teleport-plugin-react-jss'
 import { createPlugin as createCSSModulesPlugin } from '@teleporthq/teleport-plugin-css-modules'
+import { createPlugin as createCSSPlugin } from '@teleporthq/teleport-plugin-css'
 import reactStyledComponentsPlugin from '@teleporthq/teleport-plugin-react-styled-components'
 import reactStyledJSXPlugin from '@teleporthq/teleport-plugin-react-styled-jsx'
 import propTypesPlugin from '@teleporthq/teleport-plugin-jsx-proptypes'
@@ -15,16 +16,25 @@ import reactMapping from './react-mapping.json'
 
 import { ComponentGenerator, Mapping } from '@teleporthq/teleport-types'
 
+const cssPlugin = createCSSPlugin({
+  templateChunkName: 'jsx-component',
+  templateStyle: 'jsx',
+  declareDependency: 'import',
+})
+
+const cssModulesPlugin = createCSSModulesPlugin({ moduleExtension: true })
+
 const stylePlugins = {
   InlineStyles: reactInlineStylesPlugin,
   StyledComponents: reactStyledComponentsPlugin,
   StyledJSX: reactStyledJSXPlugin,
-  CSSModules: createCSSModulesPlugin({ moduleExtension: true }),
+  CSSModules: cssModulesPlugin,
+  CSS: cssPlugin,
   JSS: reactJSSPlugin,
 }
 
 export const createReactComponentGenerator = (
-  variation: string = 'InlineStyles',
+  variation: string = 'CSS',
   mapping: Mapping = {}
 ): ComponentGenerator => {
   const stylePlugin = stylePlugins[variation] || reactInlineStylesPlugin
diff --git a/packages/teleport-component-generator-stencil/package.json b/packages/teleport-component-generator-stencil/package.json
index 2bcd0f40..1e1666b4 100644
--- a/packages/teleport-component-generator-stencil/package.json
+++ b/packages/teleport-component-generator-stencil/package.json
@@ -28,7 +28,7 @@
     "@teleporthq/teleport-component-generator": "^0.8.1",
     "@teleporthq/teleport-plugin-import-statements": "^0.8.1",
     "@teleporthq/teleport-plugin-stencil-base-component": "^0.8.1",
-    "@teleporthq/teleport-plugin-stencil-css": "^0.8.1",
+    "@teleporthq/teleport-plugin-css": "^0.8.1",
     "@teleporthq/teleport-postprocessor-prettier-js": "^0.8.1",
     "@teleporthq/teleport-shared": "^0.8.1",
     "@teleporthq/teleport-types": "^0.8.1"
diff --git a/packages/teleport-component-generator-stencil/src/index.ts b/packages/teleport-component-generator-stencil/src/index.ts
index 713d0dea..390af33f 100644
--- a/packages/teleport-component-generator-stencil/src/index.ts
+++ b/packages/teleport-component-generator-stencil/src/index.ts
@@ -1,5 +1,5 @@
 import stencilComponentPlugin from '@teleporthq/teleport-plugin-stencil-base-component'
-import stencilStylePlugin from '@teleporthq/teleport-plugin-stencil-css'
+import { createPlugin as createCSSPlugin } from '@teleporthq/teleport-plugin-css'
 import { createPlugin as createImportPlugin } from '@teleporthq/teleport-plugin-import-statements'
 import { FILE_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
 import { createPostProcessor } from '@teleporthq/teleport-postprocessor-prettier-js'
@@ -11,6 +11,11 @@ import { ComponentGenerator, Mapping } from '@teleporthq/teleport-types'
 import stencilMapping from './stencil-mapping.json'
 
 const importStatementsPlugin = createImportPlugin({ fileType: FILE_TYPE.TSX })
+const stencilStylePlugin = createCSSPlugin({
+  declareDependency: 'decorator',
+  templateStyle: 'jsx',
+  templateChunkName: 'jsx-component',
+})
 const prettierJS = createPostProcessor({ fileType: FILE_TYPE.TSX })
 
 export const createStencilComponentGenerator = (mapping: Mapping = {}): ComponentGenerator => {
diff --git a/packages/teleport-component-generator-vue/src/index.ts b/packages/teleport-component-generator-vue/src/index.ts
index eb2f222c..bd1a8981 100644
--- a/packages/teleport-component-generator-vue/src/index.ts
+++ b/packages/teleport-component-generator-vue/src/index.ts
@@ -15,7 +15,7 @@ import { Mapping, ComponentGenerator } from '@teleporthq/teleport-types'
 export const createVueComponentGenerator = (mapping: Mapping = {}): ComponentGenerator => {
   const generator = createComponentGenerator()
   const vueStylePlugin = createVueStylePlugin({
-    dynamicStyleAttributeKey: () => ':style',
+    inlineStyleAttributeKey: ':style',
   })
 
   generator.addMapping(vueMapping)
diff --git a/packages/teleport-plugin-angular-base-component/src/constants.ts b/packages/teleport-plugin-angular-base-component/src/constants.ts
index 2677d8fa..93f68cb1 100644
--- a/packages/teleport-plugin-angular-base-component/src/constants.ts
+++ b/packages/teleport-plugin-angular-base-component/src/constants.ts
@@ -2,7 +2,7 @@ export const DEFAULT_ANGULAR_TEMPLATE_CHUNK_NAME = 'template-chunk'
 
 export const DEFAULT_ANGULAR_TS_CHUNK_NAME = 'angular-ts-chunk'
 
-export const DEFAULT_ANGULAR_DECORATOR_CHUNK_NAME = 'decorator'
+export const DEFAULT_ANGULAR_DECORATOR_CHUNK_NAME = 'component-decorator'
 
 export const DEFAULT_TS_CHUNK_AFTER = ['import-lib', 'import-pack', 'import-local']
 
diff --git a/packages/teleport-plugin-angular-base-component/src/utils.ts b/packages/teleport-plugin-angular-base-component/src/utils.ts
index f1f70745..b5b305b3 100644
--- a/packages/teleport-plugin-angular-base-component/src/utils.ts
+++ b/packages/teleport-plugin-angular-base-component/src/utils.ts
@@ -3,10 +3,7 @@ import {
   convertValueToLiteral,
   getTSAnnotationForType,
 } from '@teleporthq/teleport-shared/dist/cjs/utils/ast-js-utils'
-import {
-  getComponentFileName,
-  getStyleFileName,
-} from '@teleporthq/teleport-shared/dist/cjs/utils/uidl-utils'
+import { getComponentFileName } from '@teleporthq/teleport-shared/dist/cjs/utils/uidl-utils'
 import { UIDLPropDefinition, UIDLStateDefinition, ComponentUIDL } from '@teleporthq/teleport-types'
 import { FILE_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
 
@@ -16,11 +13,7 @@ export const generateComponentDecorator = (uidl: ComponentUIDL, t = types) => {
       t.objectProperty(t.identifier('selector'), t.stringLiteral('app-root')),
       t.objectProperty(
         t.identifier('templateUrl'),
-        t.stringLiteral(`./${getComponentFileName(uidl)}.${FILE_TYPE.HTML}`)
-      ),
-      t.objectProperty(
-        t.identifier('styleUrls'),
-        t.stringLiteral(`./${getStyleFileName(uidl)}.${FILE_TYPE.CSS}`)
+        t.stringLiteral(`${getComponentFileName(uidl)}.${FILE_TYPE.HTML}`)
       ),
     ]),
   ]
diff --git a/packages/teleport-plugin-css/src/index.ts b/packages/teleport-plugin-css/src/index.ts
index ee2d0bd5..23cc24df 100644
--- a/packages/teleport-plugin-css/src/index.ts
+++ b/packages/teleport-plugin-css/src/index.ts
@@ -3,72 +3,106 @@ import {
   splitDynamicAndStaticStyles,
   cleanupNestedStyles,
   traverseElements,
+  transformDynamicStyles,
+  getStyleFileName,
 } from '@teleporthq/teleport-shared/dist/cjs/utils/uidl-utils'
-import { createCSSClass } from '@teleporthq/teleport-shared/dist/cjs/builders/css-builders'
+import {
+  createCSSClass,
+  createDynamicStyleExpression,
+} from '@teleporthq/teleport-shared/dist/cjs/builders/css-builders'
+
 import { getContentOfStyleObject } from '@teleporthq/teleport-shared/dist/cjs/utils/jss-utils'
 import {
   addClassToNode,
   addAttributeToNode,
 } from '@teleporthq/teleport-shared/dist/cjs/utils/html-utils'
+import {
+  addClassStringOnJSXTag,
+  addAttributeToJSXTag,
+} from '@teleporthq/teleport-shared/dist/cjs/utils/ast-jsx-utils'
+import { addPropertyToASTObject } from '@teleporthq/teleport-shared/dist/cjs/utils/ast-js-utils'
 import {
   ComponentPluginFactory,
   ComponentPlugin,
   UIDLDynamicReference,
+  UIDLStyleDefinitions,
 } from '@teleporthq/teleport-types'
 import { FILE_TYPE, CHUNK_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
 
-interface VueStyleChunkConfig {
+interface CSSPluginConfig {
   chunkName: string
-  vueJSChunk: string
-  vueTemplateChunk: string
-  dynamicStyleAttributeKey: () => string
+  templateChunkName: string
+  componentDecoratorChunkName: string
+  inlineStyleAttributeKey: string
+  templateStyle: 'html' | 'jsx'
+  declareDependency: 'import' | 'decorator' | 'none'
 }
 
-export const createPlugin: ComponentPluginFactory<VueStyleChunkConfig> = (config) => {
+export const createPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
   const {
     chunkName = 'style-chunk',
-    vueTemplateChunk = 'template-chunk',
-    dynamicStyleAttributeKey = () => ':style',
+    templateChunkName = 'template-chunk',
+    componentDecoratorChunkName = 'component-decorator',
+    inlineStyleAttributeKey = 'style',
+    templateStyle = 'html',
+    declareDependency = 'none',
   } = config || {}
 
-  const vueComponentStyleChunkPlugin: ComponentPlugin = async (structure) => {
-    const { uidl, chunks } = structure
+  const cssPlugin: ComponentPlugin = async (structure) => {
+    const { uidl, chunks, dependencies } = structure
 
     const { node } = uidl
 
-    const templateChunk = chunks.filter((chunk) => chunk.name === vueTemplateChunk)[0]
+    const templateChunk = chunks.find((chunk) => chunk.name === templateChunkName)
+    const componentDecoratorChunk = chunks.find(
+      (chunk) => chunk.name === componentDecoratorChunkName
+    )
 
     const templateLookup = templateChunk.meta.nodesLookup
 
+    // Only JSX based chunks have dynamicRefPrefix (eg: this.props. or props.)
+    const propsPrefix: string = templateChunk.meta.dynamicRefPrefix
+      ? templateChunk.meta.dynamicRefPrefix.prop
+      : ''
+
     const jssStylesArray = []
 
     traverseElements(node, (element) => {
       const { style, key } = element
 
-      if (style) {
-        const { staticStyles, dynamicStyles } = splitDynamicAndStaticStyles(style)
-        const root = templateLookup[key]
+      if (!style) {
+        return
+      }
 
-        if (Object.keys(staticStyles).length > 0) {
-          const className = camelCaseToDashCase(key)
-          jssStylesArray.push(createCSSClass(className, getContentOfStyleObject(staticStyles)))
-          addClassToNode(root, className)
-        }
+      const { staticStyles, dynamicStyles } = splitDynamicAndStaticStyles(style)
+      const root = templateLookup[key]
 
-        if (Object.keys(dynamicStyles).length) {
-          const rootStyles = cleanupNestedStyles(dynamicStyles)
+      if (Object.keys(staticStyles).length > 0) {
+        const className = camelCaseToDashCase(key)
+        jssStylesArray.push(createCSSClass(className, getContentOfStyleObject(staticStyles)))
 
-          const flavorFriendlyStyleBind = Object.keys(rootStyles).map((styleKey) => {
-            return `${styleKey}: ${(rootStyles[styleKey] as UIDLDynamicReference).content.id}`
-          })
+        if (templateStyle === 'html') {
+          addClassToNode(root, className)
+        } else {
+          addClassStringOnJSXTag(root, className)
+        }
+      }
 
-          // If dynamic styles are on nested-styles they are unfortunately lost, since inline style does not support that
-          if (Object.keys(flavorFriendlyStyleBind).length > 0) {
-            addAttributeToNode(
-              root,
-              dynamicStyleAttributeKey(),
-              `{${flavorFriendlyStyleBind.join(', ')}}`
+      if (Object.keys(dynamicStyles).length > 0) {
+        const rootStyles = cleanupNestedStyles(dynamicStyles)
+
+        // If dynamic styles are on nested-styles they are unfortunately lost, since inline style does not support that
+        if (Object.keys(rootStyles).length > 0) {
+          if (templateStyle === 'html') {
+            // simple string expression
+            const inlineStyles = createDynamicInlineStyle(rootStyles)
+            addAttributeToNode(root, inlineStyleAttributeKey, `{${inlineStyles}}`)
+          } else {
+            // jsx object expression
+            const inlineStyles = transformDynamicStyles(rootStyles, (styleValue) =>
+              createDynamicStyleExpression(styleValue, propsPrefix)
             )
+            addAttributeToJSXTag(root, inlineStyleAttributeKey, inlineStyles)
           }
         }
       }
@@ -82,12 +116,44 @@ export const createPlugin: ComponentPluginFactory<VueStyleChunkConfig> = (config
         content: jssStylesArray.join('\n'),
         linkAfter: [],
       })
+
+      /**
+       * Setup an import statement for the styles
+       * The name of the file is either in the meta of the component generator
+       * or we fallback to the name of the component
+       */
+      const cssFileName = getStyleFileName(uidl)
+
+      if (declareDependency === 'decorator' && componentDecoratorChunk) {
+        const decoratorAST = componentDecoratorChunk.content
+        const decoratorParam = decoratorAST.expression.arguments[0]
+        addPropertyToASTObject(decoratorParam, 'styleUrls', [`${cssFileName}.${FILE_TYPE.CSS}`])
+      }
+
+      if (declareDependency === 'import') {
+        dependencies.styles = {
+          // styles will not be used in this case as we have importJustPath flag set
+          type: 'local',
+          path: `./${cssFileName}.${FILE_TYPE.CSS}`,
+          meta: {
+            importJustPath: true,
+          },
+        }
+      }
     }
 
     return structure
   }
 
-  return vueComponentStyleChunkPlugin
+  return cssPlugin
 }
 
 export default createPlugin()
+
+const createDynamicInlineStyle = (styles: UIDLStyleDefinitions) => {
+  return Object.keys(styles)
+    .map((styleKey) => {
+      return `${styleKey}: ${(styles[styleKey] as UIDLDynamicReference).content.id}`
+    })
+    .join(', ')
+}
diff --git a/packages/teleport-plugin-import-statements/src/index.ts b/packages/teleport-plugin-import-statements/src/index.ts
index d27be9d6..cb632a69 100644
--- a/packages/teleport-plugin-import-statements/src/index.ts
+++ b/packages/teleport-plugin-import-statements/src/index.ts
@@ -59,6 +59,7 @@ const groupDependenciesByPackage = (
         result[dep.path] = [] // Initialize the dependencies from this path
       }
 
+      const importJustPath = (dep.meta && dep.meta.importJustPath) || false
       const namedImport = !!(dep.meta && dep.meta.namedImport)
       const originalName = dep.meta && dep.meta.originalName ? dep.meta.originalName : key
 
@@ -66,6 +67,7 @@ const groupDependenciesByPackage = (
         identifierName: key,
         namedImport,
         originalName,
+        importJustPath,
       })
     })
 
diff --git a/packages/teleport-plugin-stencil-base-component/src/constants.ts b/packages/teleport-plugin-stencil-base-component/src/constants.ts
index cf1d6bd6..f3955375 100644
--- a/packages/teleport-plugin-stencil-base-component/src/constants.ts
+++ b/packages/teleport-plugin-stencil-base-component/src/constants.ts
@@ -9,7 +9,7 @@ export const STENCIL_CORE_DEPENDENCY = {
 
 export const DEFAULT_COMPONENT_CHUNK_NAME = 'jsx-component'
 
-export const DEFAULT_COMPONENT_DECORATOR_CHUNK_NAME = 'decorator'
+export const DEFAULT_COMPONENT_DECORATOR_CHUNK_NAME = 'component-decorator'
 
 export const DEFAULT_EXPORT_CHUNK_NAME = 'export'
 
diff --git a/packages/teleport-plugin-stencil-css/README.md b/packages/teleport-plugin-stencil-css/README.md
deleted file mode 100644
index f987aba7..00000000
--- a/packages/teleport-plugin-stencil-css/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# teleport-plugin-stencil-css
-
-A plugin for creating the styles of a Stencil component.
-
-> This package is part of the [teleport ecosystem](https://github.com/teleporthq/teleport-code-generators). For a complete guide, check out the [official documentation](https://docs.teleporthq.io/).
-
-## Install
-```bash
-npm install @teleporthq/teleport-plugin-stencil-css
-```
-or
-```bash
-yarn add @teleporthq/teleport-plugin-stencil-css
-```
diff --git a/packages/teleport-plugin-stencil-css/package.json b/packages/teleport-plugin-stencil-css/package.json
deleted file mode 100644
index a2f269c0..00000000
--- a/packages/teleport-plugin-stencil-css/package.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "name": "@teleporthq/teleport-plugin-stencil-css",
-  "version": "0.8.1",
-  "description": "A plugin for creating the styles of a Stencil component",
-  "author": "teleportHQ",
-  "license": "MIT",
-  "homepage": "https://teleporthq.io/",
-  "main": "dist/cjs/index.js",
-  "types": "dist/cjs/index.d.ts",
-  "module": "dist/esm/index.js",
-  "repository": {
-    "type": "git",
-    "url": "git+ssh://git@github.com/teleporthq/teleport-code-generators.git"
-  },
-  "bugs": {
-    "url": "https://github.com/teleporthq/teleport-code-generators/issues"
-  },
-  "publishConfig": {
-    "access": "public"
-  },
-  "scripts": {
-    "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"
-  },
-  "dependencies": {
-    "@teleporthq/teleport-shared": "^0.8.1",
-    "@teleporthq/teleport-types": "^0.8.1"
-  }
-}
diff --git a/packages/teleport-plugin-stencil-css/src/index.ts b/packages/teleport-plugin-stencil-css/src/index.ts
deleted file mode 100644
index 1d0cea0c..00000000
--- a/packages/teleport-plugin-stencil-css/src/index.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import { camelCaseToDashCase } from '@teleporthq/teleport-shared/dist/cjs/utils/string-utils'
-import { addPropertyToASTObject } from '@teleporthq/teleport-shared/dist/cjs/utils/ast-js-utils'
-import {
-  splitDynamicAndStaticStyles,
-  cleanupNestedStyles,
-  traverseElements,
-  transformDynamicStyles,
-  getStyleFileName,
-} from '@teleporthq/teleport-shared/dist/cjs/utils/uidl-utils'
-import {
-  createCSSClass,
-  createDynamicStyleExpression,
-} from '@teleporthq/teleport-shared/dist/cjs/builders/css-builders'
-import { getContentOfStyleObject } from '@teleporthq/teleport-shared/dist/cjs/utils/jss-utils'
-import { addAttributeToJSXTag } from '@teleporthq/teleport-shared/dist/cjs/utils/ast-jsx-utils'
-import { ComponentPluginFactory, ComponentPlugin } from '@teleporthq/teleport-types'
-import { FILE_TYPE, CHUNK_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
-
-interface StencilStyleChunkConfig {
-  componentChunkName: string
-  componentDecoratorChunkName: string
-  styleChunkName: string
-}
-
-export const createPlugin: ComponentPluginFactory<StencilStyleChunkConfig> = (config) => {
-  const {
-    componentChunkName = 'jsx-component',
-    componentDecoratorChunkName = 'decorator',
-    styleChunkName = 'stencil-style',
-  } = config || {}
-
-  const stencilComponentStyleChunkPlugin: ComponentPlugin = async (structure) => {
-    const { uidl, chunks } = structure
-
-    const { node } = uidl
-
-    const stencilComponent = chunks.find((chunk) => chunk.name === componentChunkName)
-    const stencilDecorator = chunks.find((chunk) => chunk.name === componentDecoratorChunkName)
-    if (!stencilComponent || !stencilDecorator) {
-      throw new Error(
-        `JSX based component chunk with name '${componentChunkName}' and decorator with name '${componentDecoratorChunkName}' were required and not found.`
-      )
-    }
-
-    const jsxNodesLookup = stencilComponent.meta.nodesLookup
-    const propsPrefix = stencilComponent.meta.dynamicRefPrefix.prop
-
-    const jssStylesArray = []
-
-    traverseElements(node, (element) => {
-      const { style, key } = element
-
-      if (style) {
-        const { staticStyles, dynamicStyles } = splitDynamicAndStaticStyles(style)
-        const root = jsxNodesLookup[key]
-
-        if (Object.keys(dynamicStyles).length > 0) {
-          const rootStyles = cleanupNestedStyles(dynamicStyles)
-          const inlineStyles = transformDynamicStyles(rootStyles, (styleValue) =>
-            createDynamicStyleExpression(styleValue, propsPrefix)
-          )
-
-          // If dynamic styles are on nested-styles they are unfortunately lost, since inline style does not support that
-          if (Object.keys(inlineStyles).length > 0) {
-            addAttributeToJSXTag(root, 'style', inlineStyles)
-          }
-        }
-
-        if (Object.keys(staticStyles).length > 0) {
-          const className = camelCaseToDashCase(key)
-          jssStylesArray.push(createCSSClass(className, getContentOfStyleObject(staticStyles)))
-
-          addAttributeToJSXTag(root, 'class', className)
-        }
-      }
-    })
-
-    if (jssStylesArray.length > 0) {
-      const cssFileName = getStyleFileName(uidl)
-
-      const decoratorAST = stencilDecorator.content
-      const decoratorParam = decoratorAST.expression.arguments[0]
-      addPropertyToASTObject(decoratorParam, 'styleUrl', `${cssFileName}.css`)
-
-      chunks.push({
-        type: CHUNK_TYPE.STRING,
-        name: styleChunkName,
-        fileType: FILE_TYPE.CSS,
-        content: jssStylesArray.join('\n'),
-        linkAfter: [],
-      })
-    }
-
-    return structure
-  }
-
-  return stencilComponentStyleChunkPlugin
-}
-
-export default createPlugin()
diff --git a/packages/teleport-plugin-stencil-css/tsconfig-cjs.json b/packages/teleport-plugin-stencil-css/tsconfig-cjs.json
deleted file mode 100755
index c66b615a..00000000
--- a/packages/teleport-plugin-stencil-css/tsconfig-cjs.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "extends": "../../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "dist/cjs",
-    "module": "commonjs",
-    "target": "es5"
-  },
-  "include": [
-    "./src"
-  ]
-}
\ No newline at end of file
diff --git a/packages/teleport-plugin-stencil-css/tsconfig-esm.json b/packages/teleport-plugin-stencil-css/tsconfig-esm.json
deleted file mode 100755
index f8bed582..00000000
--- a/packages/teleport-plugin-stencil-css/tsconfig-esm.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "extends": "../../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "dist/esm",
-    "module": "esnext",
-    "target": "esnext",
-    "moduleResolution": "node"
-  },
-  "include": [
-    "./src"
-  ]
-}
\ No newline at end of file
diff --git a/packages/teleport-shared/src/builders/ast-builders.ts b/packages/teleport-shared/src/builders/ast-builders.ts
index e12f33c1..6ac8f696 100644
--- a/packages/teleport-shared/src/builders/ast-builders.ts
+++ b/packages/teleport-shared/src/builders/ast-builders.ts
@@ -35,8 +35,12 @@ export const createGenericImportStatement = (
 ) => {
   // Only one of the imports can be the default one so this is a fail safe for invalid UIDL data
   const defaultImport = imports.find((imp) => !imp.namedImport) // only one import can be default
+  const importJustPath = imports.some((imp) => imp.importJustPath)
   let importASTs: any[] = []
-  if (defaultImport) {
+  if (importJustPath) {
+    // Just the import path will be present, eg: import './styles.css'
+    importASTs = []
+  } else if (defaultImport) {
     const namedImports = imports.filter(
       (imp) => imp.identifierName !== defaultImport.identifierName
     )
diff --git a/packages/teleport-types/src/generators.ts b/packages/teleport-types/src/generators.ts
index 4d898174..9fa2c36e 100644
--- a/packages/teleport-types/src/generators.ts
+++ b/packages/teleport-types/src/generators.ts
@@ -87,9 +87,10 @@ export interface HastText {
 }
 
 export interface ImportIdentifier {
-  identifierName: string
-  namedImport: boolean
-  originalName: string
+  identifierName?: string
+  namedImport?: boolean
+  originalName?: string
+  importJustPath?: boolean
 }
 
 /* Project Types */
diff --git a/packages/teleport-types/src/uidl.ts b/packages/teleport-types/src/uidl.ts
index 6030c7e1..b0a6f62a 100755
--- a/packages/teleport-types/src/uidl.ts
+++ b/packages/teleport-types/src/uidl.ts
@@ -174,6 +174,7 @@ export interface ComponentDependency {
   meta?: {
     namedImport?: boolean
     originalName?: string
+    importJustPath?: boolean
   }
 }
 


Test patch:
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-style.ts b/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
index 8e4fb2a4..795feee0 100644
--- a/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
@@ -54,7 +54,7 @@ const findFileByType = (files: GeneratedFile[], type: string = FILE_TYPE.JS) =>
 describe('React Styles in Component', () => {
   describe('supports usage of state in styles', () => {
     it('Inline Styles should refer state in styles when state is mapped', async () => {
-      const generator = createReactComponentGenerator()
+      const generator = createReactComponentGenerator('InlineStyles')
       const result = await generator.generateComponent(ComponentWithStateReference)
       const jsFile = findFileByType(result.files, FILE_TYPE.JS)
 
@@ -73,6 +73,20 @@ describe('React Styles in Component', () => {
       expect(cssFile).toBeDefined()
       expect(jsFile.content).toContain('display: active')
       expect(jsFile.content).toContain('height: props.config.height')
+      expect(cssFile.content).toContain('align-self: center;')
+    })
+
+    it('Basic CSS should refer state in styles when state is mapped', async () => {
+      const generator = createReactComponentGenerator('CSS')
+      const result = await generator.generateComponent(ComponentWithStateReference)
+      const jsFile = findFileByType(result.files, FILE_TYPE.JS)
+      const cssFile = findFileByType(result.files, FILE_TYPE.CSS)
+
+      expect(jsFile).toBeDefined()
+      expect(cssFile).toBeDefined()
+      expect(jsFile.content).toContain('display: active')
+      expect(jsFile.content).toContain('height: props.config.height')
+      expect(cssFile.content).toContain('align-self: center;')
     })
 
     it('JSS should through error when state is refered', async () => {
@@ -87,7 +101,7 @@ describe('React Styles in Component', () => {
   })
 
   describe('supports props json declaration in styles', () => {
-    const generator = createReactComponentGenerator()
+    const generator = createReactComponentGenerator('InlineStyles')
 
     it('should add attributes on component', async () => {
       const result = await generator.generateComponent(ComponentWithValidStyle)
diff --git a/packages/teleport-plugin-css/__tests__/index.ts b/packages/teleport-plugin-css/__tests__/index.ts
index f43db090..3312a6e0 100644
--- a/packages/teleport-plugin-css/__tests__/index.ts
+++ b/packages/teleport-plugin-css/__tests__/index.ts
@@ -7,61 +7,139 @@ import { ComponentStructure, ChunkDefinition } from '@teleporthq/teleport-types'
 import { createPlugin } from '../src/index'
 import { CHUNK_TYPE, FILE_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
 
-describe('plugin-vue-style', () => {
-  const plugin = createPlugin({ vueTemplateChunk: 'vue-chunk' })
-  const componentChunk: ChunkDefinition = {
-    name: 'vue-chunk',
-    meta: {
-      nodesLookup: {
-        container: {
-          type: 'element',
-          tagName: 'div',
-          properties: {},
+describe('plugin-css', () => {
+  describe('on html template based components', () => {
+    const plugin = createPlugin({ templateChunkName: 'template' })
+    const componentChunk: ChunkDefinition = {
+      name: 'template',
+      meta: {
+        nodesLookup: {
+          container: {
+            type: 'element',
+            tagName: 'div',
+            properties: {},
+          },
         },
       },
-    },
-    fileType: FILE_TYPE.HTML,
-    type: CHUNK_TYPE.HAST,
-    linkAfter: [],
-    content: {},
-  }
-
-  it('generates no chunk if no styles exist', async () => {
-    const uidlSample = component('VueStyles', elementNode('container'))
-    const structure: ComponentStructure = {
-      uidl: uidlSample,
-      options: {},
-      chunks: [componentChunk],
-      dependencies: {},
+      fileType: FILE_TYPE.HTML,
+      type: CHUNK_TYPE.HAST,
+      linkAfter: [],
+      content: {},
     }
 
-    const { chunks } = await plugin(structure)
+    it('generates no chunk if no styles exist', async () => {
+      const uidlSample = component('CSSPlugin', elementNode('container'))
+      const structure: ComponentStructure = {
+        uidl: uidlSample,
+        options: {},
+        chunks: [componentChunk],
+        dependencies: {},
+      }
 
-    expect(chunks.length).toBe(1)
+      const { chunks } = await plugin(structure)
+
+      expect(chunks.length).toBe(1)
+    })
+
+    it('generates a string chunk out of the styles and adds the className', async () => {
+      const style = {
+        height: staticNode('100px'),
+      }
+      const element = elementNode('container', {}, [], null, style)
+      element.content.key = 'container'
+      const uidlSample = component('CSSPlugin', element)
+
+      const structure: ComponentStructure = {
+        uidl: uidlSample,
+        options: {},
+        chunks: [componentChunk],
+        dependencies: {},
+      }
+
+      const { chunks } = await plugin(structure)
+
+      expect(chunks.length).toBe(2)
+      expect(chunks[1].type).toBe('string')
+      expect(chunks[1].content).toContain('height: 100px;')
+
+      const nodeReference = componentChunk.meta.nodesLookup.container
+      expect(nodeReference.properties.class).toBe('container')
+    })
   })
 
-  it('generates a string chunk out of the styles and adds the className', async () => {
-    const style = {
-      height: staticNode('100px'),
+  describe('on jsx-based components', () => {
+    const plugin = createPlugin({
+      templateStyle: 'jsx',
+      declareDependency: 'decorator',
+      templateChunkName: 'jsx-component',
+      componentDecoratorChunkName: 'component-decorator',
+    })
+    const componentChunk: ChunkDefinition = {
+      name: 'jsx-component',
+      meta: {
+        nodesLookup: {
+          container: {
+            openingElement: {
+              name: {
+                name: '',
+              },
+              attributes: [],
+            },
+          },
+        },
+        dynamicRefPrefix: {
+          prop: 'props.',
+        },
+      },
+      type: CHUNK_TYPE.AST,
+      fileType: FILE_TYPE.TSX,
+      linkAfter: ['import-local'],
+      content: {},
     }
-    const element = elementNode('container', {}, [], null, style)
-    element.content.key = 'container'
-    const uidlSample = component('VueStyle', element)
-
-    const structure: ComponentStructure = {
-      uidl: uidlSample,
-      options: {},
-      chunks: [componentChunk],
-      dependencies: {},
+
+    const decoratorChunk: ChunkDefinition = {
+      name: 'component-decorator',
+      type: CHUNK_TYPE.AST,
+      fileType: FILE_TYPE.TSX,
+      linkAfter: ['import-local'],
+      content: {
+        expression: {
+          arguments: [
+            {
+              properties: [],
+            },
+          ],
+        },
+      },
     }
 
-    const { chunks } = await plugin(structure)
+    it('generates a string chunk out of the styles, adds the className and the decorator reference', async () => {
+      const style = {
+        height: staticNode('100px'),
+      }
+      const element = elementNode('container', {}, [], null, style)
+      element.content.key = 'container'
+      const uidlSample = component('test', element)
+
+      const structure: ComponentStructure = {
+        uidl: uidlSample,
+        options: {},
+        chunks: [componentChunk, decoratorChunk],
+        dependencies: {},
+      }
+
+      const { chunks } = await plugin(structure)
+
+      expect(chunks.length).toBe(3)
+      const decoratorAST = chunks[1].content
 
-    expect(chunks.length).toBe(2)
-    expect(chunks[1].type).toBe('string')
-    expect(chunks[1].content).toContain('height: 100px;')
+      // AST be crazy...
+      const styleReferenceInDecoratorAST =
+        decoratorAST.expression.arguments[0].properties[0].value.elements[0].value
 
-    const nodeReference = componentChunk.meta.nodesLookup.container
-    expect(nodeReference.properties.class).toBe('container')
+      expect(styleReferenceInDecoratorAST).toBe('test.css')
+      expect(chunks[2].type).toBe('string')
+      expect(chunks[2].content).toContain('height: 100px;')
+    })
   })
 })
diff --git a/packages/teleport-plugin-stencil-css/__tests__/index.ts b/packages/teleport-plugin-stencil-css/__tests__/index.ts
deleted file mode 100644
index ed730428..00000000
--- a/packages/teleport-plugin-stencil-css/__tests__/index.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import {
-  component,
-  elementNode,
-  staticNode,
-} from '@teleporthq/teleport-shared/dist/cjs/builders/uidl-builders'
-import { ComponentStructure, ChunkDefinition } from '@teleporthq/teleport-types'
-import { createPlugin } from '../src/index'
-import { CHUNK_TYPE, FILE_TYPE } from '@teleporthq/teleport-shared/dist/cjs/constants'
-
-describe('plugin-stencil-css', () => {
-  const plugin = createPlugin({
-    componentChunkName: 'jsx-component',
-    componentDecoratorChunkName: 'decorator',
-  })
-  const componentChunk: ChunkDefinition = {
-    name: 'jsx-component',
-    meta: {
-      nodesLookup: {
-        container: {
-          openingElement: {
-            name: {
-              name: '',
-            },
-            attributes: [],
-          },
-        },
-      },
-      dynamicRefPrefix: {
-        prop: 'props.',
-      },
-    },
-    type: CHUNK_TYPE.AST,
-    fileType: FILE_TYPE.TSX,
-    linkAfter: ['import-local'],
-    content: {},
-  }
-
-  const decoratorChunk: ChunkDefinition = {
-    name: 'decorator',
-    type: CHUNK_TYPE.AST,
-    fileType: FILE_TYPE.TSX,
-    linkAfter: ['import-local'],
-    content: {
-      expression: {
-        arguments: [
-          {
-            properties: [],
-          },
-        ],
-      },
-    },
-  }
-
-  it('generates no chunk if no styles exist', async () => {
-    const uidlSample = component('test', elementNode('container'))
-    const structure: ComponentStructure = {
-      uidl: uidlSample,
-      options: {},
-      chunks: [componentChunk, decoratorChunk],
-      dependencies: {},
-    }
-
-    const { chunks } = await plugin(structure)
-
-    expect(chunks.length).toBe(2)
-  })
-
-  it('generates a string chunk out of the styles and adds the className', async () => {
-    const style = {
-      height: staticNode('100px'),
-    }
-    const element = elementNode('container', {}, [], null, style)
-    element.content.key = 'container'
-    const uidlSample = component('test', element)
-
-    const structure: ComponentStructure = {
-      uidl: uidlSample,
-      options: {},
-      chunks: [componentChunk, decoratorChunk],
-      dependencies: {},
-    }
-
-    const { chunks } = await plugin(structure)
-
-    expect(chunks.length).toBe(3)
-    expect(chunks[2].type).toBe('string')
-    expect(chunks[2].content).toContain('height: 100px;')
-  })
-})