Skip to content

Commit

Permalink
Merge pull request #6 from Dev-Elevate/feat/virtual-components
Browse files Browse the repository at this point in the history
Adding support for virtual components
  • Loading branch information
rayan1810 authored Mar 16, 2024
2 parents 1240988 + 9ff276f commit 1897c72
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 37 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,6 @@ android/keystores/debug.keystore

# generated by bob
lib/

# testbed
babel-plugin-development-testbed/
176 changes: 149 additions & 27 deletions babel-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,59 @@ const configAST = parse(fileContent, {
plugins: ['typescript'],
});

traverse(configAST, {
CallExpression(path) {
if (path.node.callee.name === 'createConfig') {
if (ObjectExpressionASTtoJSObject(path.node.arguments[0].expression)) {
CONFIG = ObjectExpressionASTtoJSObject(
path.node.arguments[0].expression
);
if (configAST) {
traverse(configAST, {
CallExpression(path) {

Check warning on line 26 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
if (path.node.callee.name === 'createConfig') {
if (ObjectExpressionASTtoJSObject(path.node.arguments[0].expression)) {
CONFIG = ObjectExpressionASTtoJSObject(
path.node.arguments[0].expression
);
}
}
}
},
});
},
});
}

// -------------------------------------------------------------------------------------------------

function traceAndUpdateImportedComponentsForVC(
programPath,
localName,
importedComponents
) {
programPath.traverse({
VariableDeclarator(path) {

Check warning on line 46 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
if (
localName === path.node.init.name &&
path.node.id.type === 'ObjectPattern'
) {
path.node.id.properties.forEach((property) => {
if (property.type === 'ObjectProperty') {
importedComponents.push(property.key.name);
}
});
path.remove();
}
},
});
// CONFIG.components[localName].components.forEach((component) => {
// if (importedComponents.includes(component)) {
// return;
// } else {
// importedComponents.push(component);
// traceAndUpdateImportedComponentsForVC(component, importedComponents);
// }
// });
}

module.exports = function (babel) {
const { types: t } = babel;

let importName = 'react-native-ustyle';
let VIRTUAL_COMPONENT_EXPORT_NAME = 'VC';
let virtualComponentLocalImportName = 'VC';
let rnuImportDeclarationPath;
let importedComponents = [];
let styleId = 0;
let Styles = [];
Expand Down Expand Up @@ -122,48 +157,135 @@ module.exports = function (babel) {
});
return obj;
}
function isVirtualComponentJSXElement(CONFIG, localImportName, path) {

Check warning on line 160 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'CONFIG' is already declared in the upper scope on line 3 column 5

Check warning on line 160 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
if (
path.node.name.type === 'JSXMemberExpression' &&
path.node.name.object.name === localImportName &&
CONFIG.components[path.node.name.property.name]
) {
return true;
}
return false;
}

return {
name: 'ast-transform', // not required
visitor: {
ImportDeclaration(path, opts) {

Check warning on line 174 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
if (
opts.filename.includes('node_modules') ||
opts.filename.includes('.expo') ||
opts.filename.includes('.next')
opts?.filename?.includes('node_modules') ||
opts?.filename?.includes('.expo') ||
opts?.filename?.includes('.next')
)
return;
if (path.node.source.value === importName) {
rnuImportDeclarationPath = path;
// path.node.specifiers.push(
// t.importSpecifier(
// t.identifier("StyleSheet"),
// t.identifier("StyleSheet")
// )
// );
path.traverse({
path?.traverse({
ImportSpecifier(path) {

Check warning on line 190 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 174 column 25
importedComponents.push(path.node.local.name);
if (path.node?.imported?.name !== VIRTUAL_COMPONENT_EXPORT_NAME) {
importedComponents.push(path.node?.local?.name);
} else {
virtualComponentLocalImportName = path.node?.local?.name;
traceAndUpdateImportedComponentsForVC(
path.parentPath.parentPath,
path.node.local.name,
importedComponents
);
path.remove();
}
},
});
path.node.source.value = 'react-native';
}
},
JSXOpeningElement(path, f, o) {

Check warning on line 207 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
let isVC = false;
if (
f.filename.includes('node_modules') ||
f.filename.includes('.expo') ||
f.filename.includes('.next')
f?.filename?.includes('node_modules') ||
f?.filename?.includes('.expo') ||
f?.filename?.includes('.next')
)
return;
if (
isVirtualComponentJSXElement(
CONFIG,
virtualComponentLocalImportName,
path
)
) {
let JSXTag = path.node.name.property.name;
path.node.name = t.jsxIdentifier(JSXTag);
importedComponents.push(JSXTag);
}
if (importedComponents.includes(path.node.name.name)) {
if (CONFIG.components[path.node.name.name]) {
isVC = true;
}
// Create a variable declaration for the object
addRnuStyleIdInStyleArrayOfComponent(path.node.attributes, styleId);
styleExpression.push(
t.objectProperty(
t.identifier('styles' + styleId++),
t.valueToNode(attributesToObject(path.node.attributes))
)
);
if (isVC) {
styleExpression.push(
t.objectProperty(
t.identifier('styles' + styleId++),
t.valueToNode({
...(CONFIG.components[path.node.name.name]?.baseStyle ?? {}),
...attributesToObject(path.node.attributes),
})
)
);
// check if variants are present in attributes and add them to the styleExpression
path.node.attributes.forEach((attributeNode) => {
if (
CONFIG.components[path.node.name.name]?.variants?.[
attributeNode.name.name
]
) {
const variantName = attributeNode.name.name;
const variantValue =
CONFIG.components[path.node.name.name]?.variants?.[
variantName
][attributeNode?.value?.value];
addRnuStyleIdInStyleArrayOfComponent(
path.node.attributes,
styleId
);
styleExpression.push(
t.objectProperty(
t.identifier('styles' + styleId++),
t.valueToNode(variantValue)
)
);
}
});
path.node.name.name = CONFIG.components[path.node.name.name].tag;
if (
rnuImportDeclarationPath.node?.specifiers.find(
(specifier) => specifier.local.name === path.node.name.name
)
) {
path.node.name.name = path.node.name.name;
} else {
rnuImportDeclarationPath.node?.specifiers.push(
t.importSpecifier(
t.identifier(path.node.name.name),
t.identifier(path.node.name.name)
)
);
}
} else {
styleExpression.push(
t.objectProperty(
t.identifier('styles' + styleId++),
t.valueToNode(attributesToObject(path.node.attributes))
)
);
}
// check if rnuStyles is already declared
let declaration = f.file.ast.program.body.find(
(node) =>
Expand Down Expand Up @@ -193,9 +315,9 @@ module.exports = function (babel) {
},
Program(path, opts) {

Check warning on line 316 in babel-plugin/index.js

View workflow job for this annotation

GitHub Actions / lint

'path' is already declared in the upper scope on line 2 column 7
if (
opts.filename.includes('node_modules') ||
opts.filename.includes('.expo') ||
opts.filename.includes('.next')
opts?.filename?.includes('node_modules') ||
opts?.filename?.includes('.expo') ||
opts?.filename?.includes('.next')
)
return;
checkIfStylesheetImportedAndImport(path);
Expand Down
2 changes: 1 addition & 1 deletion babel-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "babel-plugin-react-native-ustyle",
"version": "1.1.0",
"version": "1.2.0-alpha.0",
"description": "Official support babel plugin for react-native-ustyle",
"main": "out.js",
"module": "out.js",
Expand Down
68 changes: 68 additions & 0 deletions example/rnu.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,74 @@ export const CONFIG = createConfig({
'7': 28,
},
},
components: {
Box: {
tag: 'View',
baseStyle: {
padding: 8,
backgroundColor: 'blue',
},
variants: {
variant: {
primary: {
backgroundColor: '#0F006F',
borderRadius: 8,
},
},
},
},
Random2: {
tag: 'View',
baseStyle: {
padding: 8,
backgroundColor: '$secondary',
},
variants: {
size: {
xl: {},
},
variant: {
primary: {
backgroundColor: '$primary',
borderRadius: 8,
},
sec: {},
},
},
},
Center: {
tag: 'View',
baseStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
// variants: {
// variant: {
// primary: {
// backgroundColor: '$primary',
// borderRadius: 8,
// },
// },
// },
},
Heading: {
tag: 'Text',
baseStyle: {
color: 'white',
fontSize: 24,
fontWeight: 'bold',
},
variants: {
variant: {
primary: {
backgroundColor: '$primary',
borderRadius: 8,
},
},
},
},
},
} as const);

type ConfigType = typeof CONFIG;
Expand Down
17 changes: 10 additions & 7 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from 'react';
import { Text, View } from 'react-native-ustyle';

import { VC } from 'react-native-ustyle';
const { Box, Center, Heading } = VC;
export default function App() {
return (
<View
bg={'$primary'}
p={'$space$4'}
<Box
bg={'$secondary'}
p={8}
mx={'$space$5'}
mr="-$space$4"
roundedBottom={8}
>
<Text c="$secondary">Open up App.js to start working on your app!</Text>
</View>
<Center>
<Heading variant="primary">Hello World</Heading>
</Center>
<Heading c="red">Open up App.js to start working on your app!</Heading>
</Box>
);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-ustyle",
"version": "1.3.0",
"version": "1.4.0-alpha.3",
"description": "Easy and configurable utiltity styling props support for React Native",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
Loading

0 comments on commit 1897c72

Please sign in to comment.