Skip to content

Commit

Permalink
Merge pull request #2 from blueberryapps/rafactor
Browse files Browse the repository at this point in the history
Rafactor
  • Loading branch information
Jiří Orság committed Dec 17, 2015
2 parents 7a6d9a9 + 9b62b8e commit 38f3187
Show file tree
Hide file tree
Showing 73 changed files with 3,951 additions and 387 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,35 @@ export default function createRoutes(getState) {
}
```

## extend props of component library (functions)

If you have component which requires to get some function which will change some
props of same component, then you can use:
```
import React, {Component} from 'react'
export default class WithExtendedProps extends Component {
static extendComponentLibraryProps = (props, library) => ({
...props,
onEditingModeChange: value => library.setValue('editing', value)
});
render() {
return (null)
}
}
```

What it exactly does:
- it takes previous props
- merge to them your own defined functions or values
- this is returned to props in component library

you can use `library.setValue(propName, newValue)` which take two arguments:
- propName: name of the prop where you need to change value
- newValue: exact value which will be set to props

## Development of Component library
```
npm install
Expand Down
2 changes: 1 addition & 1 deletion example_app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ build
coverage
dist
node_modules
lib
!lib
26 changes: 18 additions & 8 deletions example_app/gulpfile.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ import createComponentLibraryGenerator from '../src/createGenerator';

createComponentLibraryGenerator({
// base file of start - this is location where componentsIndex.js will be generated to
baseDir: `${__dirname}/src/browser/componentLibrary`,
baseDir: path.join(__dirname, 'src', 'browser', 'componentLibrary'),
// relative paths from base dir where to look for components
paths: ['../components/'],
// directory to node modules
nodeModulesDir: path.join(__dirname, 'node_modules'),
// list of packages with components
packages: ['rc-tooltip'],
// if you want to use gulp tasks pass gulp
gulp: gulp,
// specify name for build command -> gulp build-component-library
Expand Down Expand Up @@ -46,18 +50,21 @@ gulp.task('env', () => {
});

gulp.task('build-component-library-lib', () => {
return gulp.src('../src/**/*.js')
return gulp.src('../src/**/*')
.pipe(gulp.dest('./lib'));
});

gulp.task('watch-component-library-lib', () => {
gulp.watch('../src/**/*.js', ['build-component-library-lib']);
gulp.watch('../src/**/*', ['build-component-library-lib']);
});

gulp.task('clean', done => del('build/*', done));

gulp.task('build-webpack', ['env'], webpackBuild);
gulp.task('build', ['build-component-library-lib', 'build-component-library', 'build-webpack']);
gulp.task(
'build',
['build-component-library-lib', 'build-component-library', 'build-webpack']
);

gulp.task('eslint', () => {
return runEslint();
Expand Down Expand Up @@ -99,21 +106,24 @@ gulp.task('server', ['env'], done => {
runSequence('server-hot', 'server-nodemon', done);
});

gulp.task('default', ['build-component-library-lib', 'build-component-library', 'server', 'watch-component-library-lib', 'watch-component-library']);
gulp.task(
'default',
['build-component-library-lib', 'build-component-library', 'server', 'watch-component-library-lib', 'watch-component-library']
);

// React Native

// Fix for custom .babelrc cache issue.
// https://github.com/facebook/react-native/issues/1924#issuecomment-120170512
gulp.task('clear-react-packager-cache', function() {
gulp.task('clear-react-packager-cache', () => {
// Clear react-packager cache
const tempDir = os.tmpdir();

const cacheFiles = fs.readdirSync(tempDir).filter(function(fileName) {
const cacheFiles = fs.readdirSync(tempDir).filter(fileName => {
return fileName.indexOf('react-packager-cache') === 0;
});

cacheFiles.forEach(function(cacheFile) {
cacheFiles.forEach(cacheFile => {
const cacheFilePath = path.join(tempDir, cacheFile);
fs.unlinkSync(cacheFilePath);
console.log('Deleted cache: ', cacheFilePath);
Expand Down
34 changes: 34 additions & 0 deletions example_app/lib/buildProps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Map} from 'immutable';

export default function buildProps(propsDefinition, allProps = false) {
const props = {}

Map(propsDefinition).map((data, prop) => {
if (data.defaultValue)
props[prop] = data.defaultValue.computed
? data.defaultValue.value
: eval(`(${data.defaultValue.value})`) // eslint-disable-line no-eval
else if (allProps || data.required)
props[prop] = calculateProp(data.type, prop)
})

return props
}

function calculateProp(type, prop) {
switch (type.name) {
case 'any': return 'Default ANY'
case 'node': return 'Default NODE'
case 'string': return `Default string ${prop}`
case 'bool': return true
case 'number': return 1
case 'func': return () => { alert('executed function') }
case 'enum': return type.value[0].value.replace(/'/g, '')
case 'shape': return Map(type.value)
.map((subType, name) => calculateProp(subType, name))
.toJS()
case 'arrayOf': return [calculateProp(type.value, prop)]
}

return null
}
63 changes: 63 additions & 0 deletions example_app/lib/components/Button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import color from 'color';
import Radium from 'radium';
import React, {Component, PropTypes as RPT} from 'react';
import {Link} from 'react-router';

const RadiumLink = Radium(Link);

@Radium
export default class Button extends Component {

static propTypes = {
children: RPT.any.isRequired,
kind: RPT.string,
onClick: RPT.func
}

render() {
const {children, onClick, kind} = this.props

return (
<button
onClick={onClick}
style={[styles.button, styles.kind[kind]]}
>
{children}
</button>
);
}

}

const styles = {
button: {
backgroundColor: 'hsl(202, 40%, 50%)',
border: 'none',
borderRadius: 0,
color: 'white',
fontSize: '14px',
fontWeight: 'bold',
padding: '5px 10px',
marginRight: '5px',
outline: 'none',
':hover': {
backgroundColor: color('hsl(202, 40%, 50%)').darken(0.2).hexString()
}
},

kind: {
primary: {
backgroundColor: 'hsl(26, 100%, 58%)',
':hover': {
backgroundColor: color('hsl(26, 100%, 58%)').darken(0.2).hexString()
}
},

secondary: {
backgroundColor: 'hsl(0, 0%, 50%)',
':hover': {
backgroundColor: color('hsl(0, 0%, 50%)').darken(0.2).hexString()
}
}
}
};
172 changes: 172 additions & 0 deletions example_app/lib/components/Component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import extendProps from '../extendProps';
import Button from './Button';
import ExampleSource from './ExampleSource';
import extendComponentProps from '../extendComponentProps';
import PropsTable from './PropsTable';
import Radium from 'radium';
import React, {Component, PropTypes as RPT} from 'react';
import resolveComponent from '../resolveComponent';
import Variants from './Variants';
import {fromJS} from 'immutable';

@Radium
export default class LibraryComponent extends Component {

static contextTypes = {
componentsIndex: RPT.object.isRequired
}

static propTypes = {
params: RPT.object.isRequired
}

state = {simpleProps: true}

getCurrentComponent() {
const {componentsIndex} = this.context
const {params: {atom}} = this.props

return componentsIndex[atom]
}

getCurrentProps() {
const {simpleProps} = this.state
const atom = this.getCurrentComponent()
const component = resolveComponent(atom.component)
const defaultProps = simpleProps ? atom.simpleProps : atom.fullProps
const customProps = this.state[atom.name] || {}

return extendProps(
defaultProps,
customProps,
component,
atom.propsDefinition,
this
)
}

getComponentExtendendProps() {
const {propsDefinition} = this.getCurrentComponent()

return extendComponentProps(this.getCurrentProps(), propsDefinition)
}

render() {
const {simpleProps} = this.state
const atom = this.getCurrentComponent()
const currentProps = this.getCurrentProps()
const ExampleAtom = resolveComponent(atom.component)

return (
<div>
<h1 style={styles.heading}>
{atom.componentName}
<small style={styles.headingSmall}>{atom.file}</small>
</h1>
<div style={styles.panel}>
<h3 style={styles.blockHeading}>Example</h3>
<div>
<ExampleAtom {...this.getComponentExtendendProps()} />
</div>
</div>
<div style={styles.panel}>
<h3 style={styles.blockHeading}>
Props
</h3>
<Button kind='primary' onClick={this.toggleProps.bind(this)}>{simpleProps ? 'All props' : 'Only required props'}</Button>
<Button kind='secondary' onClick={this.resetPropsToDefauls.bind(this)}>Reset props to default</Button>
<PropsTable atom={atom} componentProps={currentProps} handleChange={this.createHandleChange(this)} />
</div>
<div style={styles.panel}>
<h3 style={styles.blockHeading}>Code</h3>
<ExampleSource atom={atom} componentProps={currentProps} />
</div>
<Variants atom={atom} componentProps={currentProps} styles={styles} />
</div>
)
}

createHandleChange(main) {
return function(key, type, scope = []) {
return function(event) {
let value = event
// Get value from event
if (event.target && event.target.value !== undefined)
value = event.target.value

// Get value from {name, value} event
else if (event.value !== undefined)
value = event.value

// fix string to valid type
if (type === 'bool' && typeof value !== 'boolean')
value = event.target.checked
else if (type === 'number')
value = parseInt(value, 10)
else if (type === 'shape' || type === 'arrayOf')
value = JSON.parse(value)

main.setValue(key, value, scope)
}
}
}

setValue(key, value, scope = []) {
const {params: {atom}} = this.props

this.setState(
fromJS(this.state)
.setIn([atom].concat(scope).concat(key), value)
.toJS()
)
}

toggleProps() {
const {simpleProps} = this.state

this.setState({...this.state, simpleProps: !simpleProps})
}

resetPropsToDefauls() {
const {params: {atom}} = this.props

this.setState({...this.state, [atom]: {}})
}
}

const styles = {
heading: {
color: 'hsl(26, 100%, 58%)',
fontSize: '32px',
fontWeight: '400',
padding: '30px 10px 0 10px',
margin: '0',
},

headingSmall: {
color: 'hsl(202, 40%, 50%)',
fontSize: '14px',
fontWeight: '300',
display: 'block',
width: '100%'
},

blockHeading: {
color: 'hsl(202, 40%, 50%)',
marginRight: '20px',
display: 'inline-block'
},

panel: {
borderLeft: '10px solid hsl(202, 100%, 85%)',
marginTop: '2rem',
marginBottom: '2rem',
background: 'hsl(202, 100%, 96%)',
padding: '10px 10px 30px 20px'
},

pre: {
background: 'white',
border: '1px solid hsl(0, 0%, 70%)',
},
};
Loading

0 comments on commit 38f3187

Please sign in to comment.