npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@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)

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:

  1. 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: #eee

And 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.

  1. Convert any *StyleName attribute to the according *Style attribute. This is very useful for passing the sub-element styles (which are usually exposed by react-native libraries) directly from CSS.

  2. If the styleName value is an object or an array, automatically pipe it through the classnames-like library.

  3. 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-style

or

npm install --save-dev @startupjs/babel-plugin-rn-stylename-to-style

Step 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 part gets its styles from the {part}Style prop.
  • part='root' is magic -- it's linked to the pure style prop.

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