Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
vovkasm committed Dec 14, 2016
0 parents commit 212d0e8
Show file tree
Hide file tree
Showing 12 changed files with 649 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["react-native"]
}
10 changes: 10 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
env: { browser: true },
extends: [ 'standard', 'standard-react' ],
plugins: [ 'import' ],
parser: 'babel-eslint',
rules: {
// For readability (TODO: sort imports in same group)
'import/order': ['error',{'newlines-between': 'always'}],
}
}
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml

# node.js
#
node_modules/
npm-debug.log

# BUCK
buck-out/
\.buckd/
android/app/libs
*.keystore
22 changes: 22 additions & 0 deletions Provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { Children, PropTypes } from 'react'

export default class Provider extends React.Component {
static propTypes = {
styleSheet: PropTypes.object.isRequired,
children: PropTypes.element.isRequired
}
static childContextTypes = {
styleSheetContext: PropTypes.object.isRequired
}

constructor (props, ctx) {
super(props, ctx)
this.styleSheet = props.styleSheet
}
getChildContext () {
return {styleSheetContext: {path: undefined, styleSheet: this.styleSheet}}
}
render () {
return Children.only(this.props.children)
}
}
122 changes: 122 additions & 0 deletions bench/bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@

import Benchmark from 'benchmark'

import Stylesheet from '../stylesheet'

const s = new Stylesheet()
s.addRules({
baseText: {
style: {
fontSize: 12
}
},
baseText2: {
style: {
fontSize: 11
}
},
Button: {
props: {
color: '#bf7650'
}
}
})
s.addDefaultRules({
'Rule1': {},
'Rule2': {},
'Rule3': {},
'Rule4': {},
'Rule5': {},
'Rule6': {},
'Rule7': {},
'Rule8': {},
'Rule9': {},
'Rule10': {}
})
s.addDefaultRules({
AppView: {
style: {
backgroundColor: '#ffffff',
justifyContent: 'center',
alignItems: 'stretch',
paddingTop: 20,
flexGrow: 1
}
}
})
s.addDefaultRules({
'AppView Item': {
style: {
borderWidth: 1,
borderColor: 'rgb(240,240,240)',
margin: 4,
flex: 1
}
},
'AppView Item Description': {
style: {
marginHorizontal: 12
}
},
'AppView Item PriceText': {
mixins: ['baseText'],
style: {
fontWeight: 'bold'
}
},
'AppView Item Text': {
mixins: ['baseText'],
style: {
marginVertical: 6
}
},
'AppView Item Image': {
style: {
left: 0,
right: 0,
height: 160
}
}
})
s.addDefaultRules({
'Rule1 Text': {style: {flex: 1}},
'Rule2 Text': {style: {flex: 1}},
'Rule3 Text': {style: {flex: 1}},
'Rule4 Text': {style: {flex: 1}},
'Rule5 Text': {style: {flex: 1}},
'Rule6 Text': {style: {flex: 1}},
'Rule7 Text': {style: {flex: 1}}
})

const suite = new Benchmark.Suite()
let props
suite.add('plain props', function () {
const p = {style: {fontSize: 8}}
props = p
if (props.style.fontSize !== 8) {
throw new Error('fontSize != 8')
}
})
suite.add('new theme & props (cached)', function () {
props = s.getProps('App AppView Elem Item Text', {prop1: 1})
if (props.style.fontSize !== 12) {
throw new Error('fontSize != 12')
}
})
suite.add('new theme & props (no cache)', function () {
props = s.getProps('App AppView Elem Item Text', {prop1: 1})
if (props.style.fontSize !== 12) {
throw new Error('fontSize != 12')
}
s.cache = {}
})
suite.on('cycle', function (e) {
console.log(String(e.target))
if (e.target.error) {
console.log('Error: ', e.target.error)
}
})
suite.on('complete', function () {
console.log('Done')
})
suite.run()
7 changes: 7 additions & 0 deletions components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ReactNative from 'react-native'

import stylable from './stylable'

export const Button = stylable('Button')(ReactNative.Button)
export const Text = stylable('Text')(ReactNative.Text)
export const View = stylable('View')(ReactNative.View)
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as StyleProvider } from './Provider'
export { Button, Text, View } from './components'
export { default as Stylesheet } from './stylesheet'
export { default as stylable } from './stylable'
36 changes: 36 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "react-native-stylable",
"version": "0.0.1",
"description": "Cascading styles for ReactNative",
"main": "index.js",
"scripts": {
"test": "mocha --require tests/setup tests/*.spec.js",
"bench": "node -r babel-register bench/bench.js"
},
"keywords": [
"react-native",
"styles",
"themes"
],
"author": "Vladimir Timofeev",
"license": "MIT",
"devDependencies": {
"babel-eslint": "^7.0.0",
"babel-preset-react-native": "^1.9.0",
"babel-register": "^6.18.0",
"benchmark": "^2.1.2",
"chai": "^3.5.0",
"eslint": "^3.3.1",
"eslint-config-standard": "^6.2.1",
"eslint-config-standard-react": "^4.2.0",
"eslint-plugin-classes": "^0.1.1",
"eslint-plugin-import": "^2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-react": "^6.8.0",
"eslint-plugin-react-native": "^2.0.0",
"eslint-plugin-standard": "^2.0.1",
"microtime": "^2.1.2",
"mocha": "^3.2.0",
"mocha-eslint": "^3.0.1"
}
}
55 changes: 55 additions & 0 deletions stylable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { PropTypes } from 'react'
import hoistStatics from 'hoist-non-react-statics'

function getDisplayName (comp) {
return comp.displayName || comp.name || 'Component'
}

export default function stylable (name) {
return function wrapWithComponent (WrappedComponent) {
const stylableDisplayName = `Stylable(${getDisplayName(WrappedComponent)})`

class Stylable extends React.Component {
static displayName = stylableDisplayName
static WrappedComponent = WrappedComponent
static contextTypes = {
styleSheetContext: PropTypes.object
}
static childContextTypes = {
styleSheetContext: PropTypes.object
}
static propTypes = {
styleSheet: PropTypes.object
}

constructor (props, ctx) {
super(props, ctx)
let sCtx
if (props.styleSheet !== undefined) {
sCtx = {
path: undefined,
styleSheet: props.styleSheet
}
} else {
const path = ctx.styleSheetContext === undefined ? name : ctx.styleSheetContext.path + ' ' + name
sCtx = {
path: path,
styleSheet: ctx.styleSheetContext.styleSheet
}
}
this.sCtx = sCtx
}

getChildContext () {
return {styleSheetContext: this.sCtx}
}

render () {
const props = this.sCtx.styleSheet.getProps(this.sCtx.path, this.props)
return React.createElement(WrappedComponent, props)
}
}

return hoistStatics(Stylable, WrappedComponent)
}
}
Loading

0 comments on commit 212d0e8

Please sign in to comment.