@cssxjs/babel-plugin-rn-stylename-to-style
v0.2.19
Published
Dynamically resolve styleName in RN with support for multi-class selectors (for easier modifiers)
Maintainers
Readme
@startupjs/babel-plugin-rn-stylename-to-style
Transform JSX styleName property to style property in react-native. The styleName attribute and syntax are based on babel-plugin-react-css-modules.
Information
This is the fork of https://github.com/kristerkari/babel-plugin-react-native-stylename-to-style
The differences are:
- Support resolving multi-class selectors in CSS:
import classnames from 'classnames'
function Button ({
variant, // [string] 'primary' | 'secondary'
dark, // [bool]
disabled // [bool]
}) {
return (
<Text
styleName={classnames('button', [variant, { dark, disabled }])}
>CLICK ME</Text>
)
}.button
background-color: blue
&.primary
color: #ff0000
&.disabled
color: rgba(#ff0000, 0.5)
&.secondary
color: #00ff00
&.disabled
color: rgba(#00ff00, 0.5)
&.disabled
color: #777
.dark
&.button
background-color: purple
&.primary
color: white
&.disabled
color: #ddd
&.disabled
color: #eeeAnd what's important is that selectors` specificity is properly emulated. For example:
Styles for .button.primary.disabled (specificity 30) will override styles of .button.disabled (specificity 20),
even though .button.disabled is written later in the CSS.
This simple change brings a lot more capabilities in theming your components for a dynamic look.
Convert any
*StyleNameattribute to the according*Styleattribute. This is very useful for passing the sub-element styles (which are usually exposed by react-native libraries) directly from CSS.If the
styleNamevalue is an object or an array, automatically pipe it through theclassnames-like library.Support for multiple named css file imports is removed
Usage
WARNING: This plugin is already built in into the babel-preset-startupjs and is included into the default StartupJS project.
If you want to use this plugin separately from StartupJS:
Step 1: Install
yarn add --dev @startupjs/babel-plugin-rn-stylename-to-styleor
npm install --save-dev @startupjs/babel-plugin-rn-stylename-to-styleStep 2: Configure .babelrc
You must give one or more file extensions inside an array in the plugin options.
{
"presets": [
"react-native"
],
"plugins": [
["react-native-dynamic-stylename-to-style", {
"extensions": ["css"]
}]
]
}Plugin Options
extensions
Default ['cssx.css', 'cssx.styl']
List of css extensions to process (css, styl, sass, etc.)
useImport
Default: false
Whether to generate ESM import instead of CJS require.
compileCssImports
Default: true
Whether to pre-process the css file imports, like import './index.styl' by this babel
plugin itself, instead of passing it further to the bundler to compile.
Note that if Babel is responsible for compiling these files then the changes in then
are not gonna be reactive and to see changes made to the separate CSS file
you would need to restart the whole bundling with an option to clear the Babel cache.
Storing styles in separate files should be avoided though, you should try to only use it when importing some 3rd party libraries or for you global theme definitions, so these files shouldn't frequently change.
cache
Default: undefined
Whether to use integration with some caching library. Currently supported ones:
"teamplay"
platform
Default: 'web'
Which platform is targeted for compilation. Supported ones:
"web""react-native"
Syntax
Anonymous reference
Anonymous reference can be used when there is only one stylesheet import.
Single class
import "./Button.css";
<View styleName="wrapper">
<Text>Foo</Text>
</View>;↓ ↓ ↓ ↓ ↓ ↓
import Button from "./Button.css";
<View style={Button.wrapper}>
<Text>Foo</Text>
</View>;Multiple classes
import "./Button.css";
<View styleName="wrapper red-background">
<Text>Foo</Text>
</View>;↓ ↓ ↓ ↓ ↓ ↓
import Button from "./Button.css";
<View style={[Button.wrapper, Button["red-background"]]}>
<Text>Foo</Text>
</View>;Expression
import "./Button.css";
const name = "wrapper";
<View styleName={name}>
<Text>Foo</Text>
</View>;↓ ↓ ↓ ↓ ↓ ↓
import Button from "./Button.css";
const name = "wrapper";
<View
style={(name || "")
.split(" ")
.filter(Boolean)
.map(function(name) {
Button[name];
})}
>
<Text>Foo</Text>
</View>;Expression with ternary
import "./Button.css";
const condition = true;
const name = "wrapper";
<View styleName={condition ? name : "bar"}>
<Text>Foo</Text>
</View>;↓ ↓ ↓ ↓ ↓ ↓
import Button from "./Button.css";
const condition = true;
const name = "wrapper";
<View
style={((condition ? name : "bar") || "")
.split(" ")
.filter(Boolean)
.map(function(name) {
Button[name];
})}
>
<Text>Foo</Text>
</View>;with styleName and style:
import "./Button.css";
<View styleName="wrapper" style={{ height: 10 }}>
<Text>Foo</Text>
</View>;↓ ↓ ↓ ↓ ↓ ↓
import Button from "./Button.css";
<View style={[Button.wrapper, { height: 10 }]}>
<Text>Foo</Text>
</View>;::part() selector
Preprocess part attribute.
- Each
partgets its styles from the{part}Styleprop. part='root'is magic -- it's linked to the purestyleprop.
Here is an example <Card> component which specifies its root container, title and footer as stylizable parts:
// Card.js
function Card ({ title }) {
return (
<View part='root'>
<Text part='header'>{title}</Text>
<Text part='footer'>Copyright</Text>
</View>
)
}↓ ↓ ↓ ↓ ↓ ↓
function Card ({ title, style, headerStyle, footerStyle }) {
return (
<View style={style}>
<Text style={headerStyle}>{title}</Text>
<Text style={footerStyle}>Copyright</Text>
</View>
)
}Preprocess ::part() selector from CSS file to style any component which uses part attributes.
Following an example <Card> component above, we can call <Card> from the <App> and customize its parts styles:
// App.js
import Card from './Card'
import './index.styl'
function App ({ users }) {
return users.map(user => (
<Card styleName='user' title={user.name} />
))
}// index.styl
.user
margin-top 16px
&:part(header)
background-color black
color white
&:part(footer)
font-weight bold