1.0.19 • Published 6 years ago

babel-preset-react-native-cascade v1.0.19

Weekly downloads
8
License
ISC
Repository
github
Last release
6 years ago

react-native-cascade

Travis Status

react-native-cascade is a Babel plugin that will pair css declarations in imported stylesheets with nodes matching their selectors in JSX, automatically. Let's make a new release! v17

Goals

  • Reduce boilerplate and unnecessary dev effort caused by manually pairing React Native stylesheets with JSX nodes
  • Feels like writing styles on web as much as possible and uses web style cascade priorities
  • Automatically pairs any css selectors from an imported stylesheet to nodes in a JSX template without any manual steps
  • Does not create global scope, all styles remain tightly bound to the component importing them
  • Usable with any utility that would create classname strings such as classnames

Installation

npm install babel-preset-react-native-cascade --save-dev

add it to the plugins list in your .babelrc

{
  "presets": ["env", "react-native"],
  "plugins": ["babel-preset-react-native-cascade"]
}

Supported JSX

Precompiled at build time

These cases can be pre-compiled at build time and do not include the runtime

JSXDescription
<* className="text-large">Single string classes
<* className="text-large container">Mutliple string classes
<* className="text-large" style={{color: 'red'}}>Single and mutliple class names when a style attribute is also defined as an object
<* className="text-large" style={[{color: 'red'}]}>Single and mutliple class names when a style attribute is also defined as an array

Will include the runtime

Classnames as variables require that the runtime is included, which is added automatically. The runtime is small and has zero depdndencies, but there is still a small performance impact of calculating the cascade on every render, since the value of the class name(s) may have changed

JSXDescription
<* className={foo}>Class names as variables
<* className={foo} style={{color: 'red'}}>Class names as variables when a style attribute is also defined as an object
<* className={foo} style={[{color: 'red'}]}>Class names as variables when a style attribute is also defined as an array

Selectors

Currently we only support very basic selectors:

SelectorExample
class.component {}
typeView {}

Stay tuned for child selectors View .component{} which are a bit more complicated to implement

How it works

Example.jsx

This component should look very familiar to anyone who as worked with React on web and have bundler/loader that handles css. The popular Facebook create react app boilerplate project uses webpack and by default ships with support to add stylesheets

import React, { Component } from 'react';
import { Text } from 'react-native';

import './Example.css';

export default class Example extends Component {
  render() {
    return <Text className="text-large container">Hello</Text>;
  }
}

Example.css

There is a webpack loader under development that will automatically translate a real stylesheet into this syntax. Its not pubically available yet, but stay tuned. This will allow developers to write normal css, which is familiar and plays nicer with editors. For the time being, external stylesheets must be defined in the following array syntax and use React Native declaration syntax, not web spec.

module.exports = [
  ['.container', [
    ['color', 'green']
  ]],
  ['.text-large', [
    ['fontSize', 24],
    ['color', 'red']
  ]],
  ['Text', [
    ['backgroundColor', 'chartreuse']
  ]]
]

after the transform the file will look like this(ish)

import React, { Component } from 'react';
import { Text } from 'react-native';

import _stylesheet from './styles.css';
const _stylesheets = [_stylesheet];

export default class Example extends Component {
  render() {
    return <Text className="text-large container"
        styles={computeStyle("text-large container", _stylesheets)}>Hello</Text>
  }
}


function computeStyle(classNames, stylesheets) {...}

Roadmap

  • Write more tests, Find bugs, Fix bugs
  • Handle named stylesheet imports
  • Support child selectors View .container {}
  • Release webpack plugin that javascriptifies stylesheets, possibly a gulp build step as well
  • Double check that JSX snippets outside the render method work
  • maybe Implement property inheritance within a single component scope (style won't inherit from one component to another, but will within a component)

Footnote - What does "cascade" mean anyway?

The word "cascade" gets thrown around a lot when talking about css. Theres an obvious reason for that since you cant say css without it! However, its also misused quite frequently. Acutually, Facebooks own document on how the style property works in React Native has one of those misuses at https://facebook.github.io/react-native/docs/style.html

One common pattern is to make your component accept a style prop which in turn is used to style subcomponents. You can use this to make styles "cascade" the way they do in CSS.

They at least were kind enough to put it in quotes, but thats not really what cascade means (although it certainly sounds reasonable). What that document is talking about is actually style inheritance, which is also useful ... and broken in React Native as well, but not not the real cascade.

Mozilla has a much better description at https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade

The cascade is an algorithm that defines how to combine property values originating from different sources. It lies at the core of CSS, as emphasized by the name: Cascading Style Sheets.

The key there is the bit about "defines how to combine property values" which is what this project attempts to recreate for React Native. The Mozilla definition briefly touches on cascading order but doesn't dive into what happens when there are duplicate selectors of equal specificity in a single source or how ordering of declarations of a single source. There is actually quite a bit that goes on and a lengthier article on MDN titled Cascade and inheritance goes into the details.

1.0.19

6 years ago

1.0.18

6 years ago

1.0.17

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago