# @haijindev/o-css

> Client side css compiler

Latest version **1.0.6** (published 2021-01-05) · ISC license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install @haijindev/o-css
pnpm add @haijindev/o-css
yarn add @haijindev/o-css
bun add @haijindev/o-css
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 1.0.6 |
| Published | 2021-01-05 |
| First published | 2020-07-04 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 11.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Martin Rubi |
| Maintainers | haijindev |
| Keywords | css, assets, react, dsl |

## Links

- npm: https://www.npmjs.com/package/@haijindev/o-css
- Homepage: http://o-programming-language.org
- npm.io page: https://npm.io/package/@haijindev/o-css

## Dependencies (1)

- [o-toolbox](https://npm.io/package/o-toolbox.md) ^5.0.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.0.6 (latest) — 2021-01-05
- 1.0.5 — 2021-01-03
- 1.0.4 — 2020-12-26
- 1.0.3 — 2020-11-14
- 1.0.2 — 2020-11-08
- 1.0.1 — 2020-10-17
- 1.0.0 — 2020-07-04

## README

# @haijindev/o-css

Javascript css builder

## Documentation

[http://o-programming-language.org/](http://o-programming-language.org/)

### What does `@haijindev/o-css` do?

Historically the workflow of the css styles of an application consisted in

* define or read a pseudo-css input file on the server side
* process it to generate a standard css file that a browser understands. For example replace variables by values, mix css classes o compile nested selectors
* expect the client to request for the compiled css file
* respond the css file to the client

Frameworks like `React` can dramatically change the workflow with a more dynamic, light and adaptable one.

This library provides a javascript DSL to declare css styles and implement the workflow that follows

* declare the styles the app uses in regular javascript sintax
* send to the client the declared styles as a regular js module in your `React` application
* make the client application to process the declared styles and convert them to the css the browser understands
* load the css compiled client side in the browser

It is also possible to use this DSL to compile the css server side using regular function calls
in Node.

## Installation

```
npm install @haijindev/o-css
```

## Usage

First define one or more styles to load.

Each style is a regular js class with a method call `injectInto(css)`


```javascript
class AppStyle {
  injectInto(css) {
    // styles definition goes here
  }
}
```

The parameter `css` is the css compiler and supports the following protocol


```javascript
class AppStyle {
  injectInto(css) {
    // Define the given cssSelector
    css.selector(
      '.row', {
        // ... css attributes
      }
    )

    // Define the given styles as children of the given cssSelector
    css.namespace('#container', () => {
      // child styles
    })

    // Append the styles defined in the given styleClass
    css.inject(anotherStyleClass)

    // Merge the styles defined in the given styleClass in the given cssSelector
    css.selector(
      '.row', {
        _import: anotherStyleClass,
        // ...
      }
    )

    // Merge the styles defined in the given styleClasses in the given cssSelector
    css.selector(
      '.row', {
        _import: [anotherStyleClass1, anotherStyleClass2],
        // ...
      }
    )
  }
}
```

Once you have a style object the application must load it into the DOM document using any of the following methods

```javascript
const {Css} = require('@haijindev/o-css')
const AppStyle = require('./AppStyle')

const style = new AppStyle()
Css.insertStyle({ style, document, element: document.head })

// And load the app like usual
ReactDOM.render(
  <MainComponent />,
  document.getElementById('root')
)
```

or first compile the styles to a css string and then load the string

```javascript
const {Css} = require('@haijindev/o-css')
const AppStyle = require('./AppStyle')

const cssString = Css.fromStyle(style)
Css.insertCss({ cssString, document, element: document.head })

// And load the app like usual
ReactDOM.render(
  <MainComponent app={ app } />,
  document.getElementById('root')
)
```

The styles can also be compiled to a file server side with

```javascript
const {Css} = require('@haijindev/o-css')
const fs = require('fs')
const AppStyle = require('./AppStyle')

const style = new AppStyle()
const cssString = Css.fromStyle(style)

fs.writeFileSync('public/main.css', cssString)
```

## Css definition

Define the class with the css definitions

```javascript
class AComponentStyle {
  injectInto(css) {
  }
}

module.exports = AComponentStyle
```

Then use any of the following definitions

### Define attributes to a css selector

```javascript
class AComponentStyle {
  injectInto(css) {
    css.selector('.btn', {
      'width': '10px',
      'height': '10px'
    })
  }
}

module.exports = AComponentStyle
```

### Define attributes to many css selectors

```javascript
class AComponentStyle {
  injectInto(css) {
    css.selector('.btn', {
      'width': '10px',
      'height': '10px'
    })

    css.selector('.btn:hover', {
      'height': '10px'
    })
  }
}

module.exports = AComponentStyle
```

### Define nested selectors

```javascript
class AComponentStyle {
  injectInto(css) {
    css.selector('.row', {
      'width': '10px'
    })

    css.selector('.row .col', {
      'height': '10px'
    })
  }
}

module.exports = AComponentStyle
```

### Define nested selectors using namespaces

Useful to override selectors for a specific element

```javascript
class AComponentStyle {
  injectInto(css) {
    css.namespace('#main', () => {
      css.selector('.row', {
        'width': '10px'
      })
    })
  }
}

module.exports = AComponentStyle
```

### Import (merge) attributes from another Style

Useful to reuse css values in different elements

```javascript
class CommonStyle {
  injectInto(css) {
    css.selector('common', {
      'color': 'blue'
    })
  }
}

module.exports = CommonStyle
```

```javascript
const CommonStyle = require('./CommonStyle')

class AComponentStyle {
  injectInto(css) {
    css.selector('.row', {
      _import: new CommonStyle(),
      'width': '10px'
    })
  }
}

module.exports = AComponentStyle
```

### Import (merge) attributes from many other Styles

```javascript
const CommonStyle1 = require('./CommonStyle1')
const CommonStyle2 = require('./CommonStyle2')

class AComponentStyle {
  injectInto(css) {
    css.selector('.row', {
      _import: [new CommonStyle1(), new CommonStyle2()],
      'width': '10px'
    })
  }
}

module.exports = AComponentStyle
```

### Bundle many Styles into a single Style

Useful to export and load a single Style class

```javascript
class Style1 {
  injectInto(css) {
    css.selector('.row', {
      'width': '10px'
    })
  }
}

module.exports = Style1
```

```javascript
class Style2 {
  injectInto(css) {
    css.selector('.btn', {
      'height': '10px'
    })
  }
}

module.exports = Style2
```

```javascript
const Style1 = require('./Style1')
const Style2 = require('./Style2')

class MainStyle {
  injectInto(css) {
    new Style1().injectInto(css)
    new Style2().injectInto(css)
  }
}

module.exports = MainStyle
```

### Dynamic css values

```javascript
const width = 10

class Style2 {
  injectInto(css) {
    css.selector('.btn', {
      'width': `${width}px`,
      'height': `${width/3}px`
    })
  }
}

module.exports = Style2
```

### Css parametrised values

```javascript
class Style {
  constructor({color}) {
    this.color = color
  }

  injectInto(css) {
    css.selector('.btn', {
      'width': `${width}px`,
      'color': this.color
    })
  }
}

module.exports = Style
```

```javascript
new Style({color: 'blue'})
```

### Themed styles

```javascript
const theme = {
  color: 'blue'
}
module.exports = theme
```

```javascript
class Component1 {
  constructor(theme) {
    this.theme = theme
  }
  injectInto(css) {
    css.selector('#id1', {
      'color': this.theme.color
    })
  }
}

module.exports = Component1
```

```javascript
class Component2 {
  constructor(theme) {
    this.theme = theme
  }
  injectInto(css) {
    css.selector('#id2', {
      'color': this.theme.color
    })
  }
}

module.exports = Component2
```

```javascript
const theme = require('./theme')
const Component1 = require('./Component1')
const Component2 = require('./Component2')

class MainStyle {
  injectInto(css) {
    new Component1(theme).injectInto(css)
    new Component2(theme).injectInto(css)
  }
}

module.exports = MainStyle
```

### Change the application theme on the fly

```javascript
const {Css} = require('@haijindev/o-css')
const MainStyle = require('./MainStyle')

function updateStyles(selectedTheme) {
  const styleElement = document.querySelector('head style')
  if (styleElement) { styleElement.remove() }

  const newStyle = new MainStyle(selectedTheme)
  Css.insertStyle({newStyle, document, element: document.head })
}

updateStyles(newTheme)
```

---
_Source: https://npm.io/package/@haijindev/o-css · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
