├── .gitignore ├── example.js ├── example ├── index.html └── styles.css ├── example-src └── index.html ├── styl ├── colors.styl ├── mixins.styl ├── example.styl └── chartbuilder-ui.styl ├── index.js ├── README.md ├── components ├── Alert.jsx ├── AlertGroup.jsx ├── LabelledTangle.jsx ├── ButtonGroup.jsx ├── Dropdown.jsx ├── Button.jsx ├── Toggle.jsx ├── TextArea.jsx ├── TextInput.jsx └── ColorPicker.jsx ├── package.json ├── Example.jsx └── dist └── styles.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .lvimrc 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var React = require("react"); 2 | var ReactDOM = require("react-dom") 3 | global.p = require("react-addons-perf"); 4 | 5 | var container = document.querySelector(".chartbuilder-ui"); 6 | var Example = require("./Example.jsx"); 7 | 8 | document.addEventListener("DOMContentLoaded", function() { 9 | // Render parent chartbuilder component 10 | ReactDOM.render(, container); 11 | }); 12 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Chartbuidler UI 8 | 9 | 10 | 11 |
12 |
13 |

Chartbuilder UI

14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /example-src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Chartbuidler UI 8 | 9 | 10 | 11 |
12 |
13 |

Chartbuilder UI

14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /styl/colors.styl: -------------------------------------------------------------------------------- 1 | // Colors 2 | 3 | $color-background = #F9F9F9 4 | 5 | $color-body-text = #333333 6 | $color-border = #e2e2e2 7 | $color-border-active = #CCC 8 | $color-input-placeholder = #CACACA 9 | 10 | $color-button-fill = #F9F9F9 11 | $color-button-fill-disabled = #BEBEBE 12 | $color-button-hover = #FFF 13 | $color-button-hover-fill = #E2E2E2 14 | 15 | $color-button-group-fill = #F1F1F1 16 | 17 | $color-share-button = #A1A1A1 18 | 19 | $color-error = #e55151 20 | $color-warning = #f59b60 21 | $color-success = #1e866c 22 | 23 | $color-toggle-toggled = #AB5787 24 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Alert: require("./components/Alert.jsx"), 3 | AlertGroup: require("./components/AlertGroup.jsx"), 4 | Button: require("./components/Button.jsx"), 5 | ButtonGroup: require("./components/ButtonGroup.jsx"), 6 | ColorPicker: require("./components/ColorPicker.jsx"), 7 | Dropdown: require("./components/Dropdown.jsx"), 8 | TextArea: require("./components/TextArea.jsx"), 9 | TextInput: require("./components/TextInput.jsx"), 10 | LabelledTangle: require("./components/LabelledTangle.jsx"), 11 | Toggle: require("./components/Toggle.jsx") 12 | }; 13 | -------------------------------------------------------------------------------- /styl/mixins.styl: -------------------------------------------------------------------------------- 1 | vendor(prop, args) 2 | -webkit-{prop} args 3 | -moz-{prop} args 4 | -ms-{prop} args 5 | -o-{prop} args 6 | {prop} args 7 | 8 | transition() 9 | vendor('transition', arguments) 10 | 11 | transform() 12 | vendor('transform', arguments) 13 | 14 | transform-origin() 15 | vendor('transform-origin', arguments) 16 | 17 | user-select() 18 | user-select arguments 19 | -moz-user-select arguments 20 | -webkit-user-select arguments 21 | -ms-user-select arguments 22 | 23 | // from nib -- http://visionmedia.github.io/nib/ 24 | placeholder() 25 | for v in ':-webkit-input' '-moz' ':-moz' '-ms-input' 26 | &:{v}-placeholder 27 | for pair in arguments 28 | if typeof(pair) == 'function' 29 | pair() 30 | else if pair is not null && pair[0] is not null 31 | {pair[0]}: type(pair[1]) == 'string' ? s(pair[1]) : pair[1] 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Chartbuilder UI React components 2 | 3 | React components that make up the UI for [Quartz Chartbuilder](https://github.com/Quartz/Chartbuilder). 4 | 5 | Here's a dead-simple [demo page](http://quartz.github.io/chartbuilder-ui/). 6 | 7 | To use in your React project: 8 | 9 | 1. npm install chartbuilder-ui 10 | 2. `require` any of the components defined by Chartbuilder UI. 11 | 12 | Chartbuilder UI's components: 13 | 14 | * Alert 15 | * Button 16 | * ButtonGroup 17 | * ColorPicker 18 | * Dropdown 19 | * TextArea 20 | * TextInput 21 | * LabelledTangle 22 | * Toggle 23 | 24 | Developing locally: 25 | 26 | * Clone this repo and run `npm install` 27 | 28 | To view an example page and develop locally: 29 | 30 | 1. `npm run dev` to watch files for changes 31 | 2. `npm start` to launch a simple http server 32 | 3. Navigate to `localhost:8080` 33 | 34 | To build the css that modules using Chartbuilder UI will consume: 35 | 36 | npm run build 37 | 38 | More docs are coming. For now, [Example.jsx](Example.jsx) shows how each 39 | component ought to be used. 40 | -------------------------------------------------------------------------------- /components/Alert.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * 7 | */ 8 | 9 | var React = require("react"); 10 | var PropTypes = React.PropTypes; 11 | 12 | var Alert = React.createClass({ 13 | 14 | propTypes: { 15 | type: PropTypes.string.isRequired, 16 | text: PropTypes.string.isRequired, 17 | className: PropTypes.string, 18 | onClick: PropTypes.func 19 | }, 20 | 21 | getDefaultProps: function() { 22 | return { 23 | type: "default", 24 | text: "Hello!" 25 | }; 26 | }, 27 | 28 | render: function() { 29 | 30 | if( typeof(this.props.onClick) === 'undefined' ){ 31 | this.props.onClick = null; 32 | } 33 | 34 | return ( 35 |
36 | 37 |

38 | {this.props.text} 39 |

40 |
41 | ); 42 | } 43 | }); 44 | 45 | module.exports = Alert; 46 | -------------------------------------------------------------------------------- /styl/example.styl: -------------------------------------------------------------------------------- 1 | // Styles only relevant to the example 2 | 3 | $font-sans = Calibri,Candara,Segoe,"Segoe UI",Optima,Arial,sans-serif 4 | $font-serif = Cambria,Georgia,serif 5 | $font-monospace = Consolas,monaco,monospace 6 | 7 | $chart-colors = \ 8 | #a50026 \ 9 | #fdae61 \ 10 | #d73027 \ 11 | #abd9e9 \ 12 | #f46d43 \ 13 | #74add1 \ 14 | #4575b4 \ 15 | #313695 \ 16 | #999 \ 17 | #666 \ 18 | #ccc 19 | 20 | for c, i in $chart-colors 21 | .cb-colorpicker-color-{i} 22 | background-color (c) 23 | 24 | .cb-colorpicker-label-{i} 25 | color (c) 26 | 27 | body 28 | background-color $color-background 29 | font-family $font-sans 30 | 31 | input 32 | font-family $font-sans 33 | 34 | @import "chartbuilder-ui" 35 | 36 | .container 37 | max-width 80% 38 | margin 0 auto 39 | 40 | .examples 41 | display inline-block 42 | max-width 650px 43 | 44 | .cb-text-area 45 | font-family $font-monospace 46 | 47 | .current-state 48 | max-width 40% 49 | position fixed 50 | background-color #f9f9f9 51 | padding 16px 52 | border 1px gray solid 53 | border-radius 2px 54 | font-family $font-monospace 55 | margin-left 40px 56 | display inline-block 57 | -------------------------------------------------------------------------------- /components/AlertGroup.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * 7 | */ 8 | 9 | var React = require("react"); 10 | var PropTypes = React.PropTypes; 11 | var ReactCSSTransitionGroup = require('react-addons-css-transition-group'); 12 | 13 | var Alert = require('./Alert.jsx'); 14 | 15 | var AlertGroup = React.createClass({ 16 | 17 | propTypes: { 18 | alerts: PropTypes.arrayOf(React.PropTypes.shape({ 19 | type: PropTypes.string, 20 | text: PropTypes.string 21 | })).isRequired, 22 | className: PropTypes.string 23 | }, 24 | 25 | render: function() { 26 | 27 | var alerts = this.props.alerts.map(function(alert, i) { 28 | return ( 29 | 34 | ); 35 | }, this); 36 | 37 | return ( 38 |
39 | 40 | {alerts} 41 | 42 |
43 | ); 44 | } 45 | }); 46 | 47 | module.exports = AlertGroup; 48 | -------------------------------------------------------------------------------- /components/LabelledTangle.jsx: -------------------------------------------------------------------------------- 1 | // wrapper around react-tangle, with a label 2 | 3 | var React = require("react"); 4 | var PropTypes = React.PropTypes; 5 | var TangleText = require("react-tangle"); 6 | 7 | var LabelledTangle = React.createClass({ 8 | 9 | propTypes: { 10 | className: PropTypes.string, 11 | onChange: PropTypes.func, 12 | onInput: PropTypes.func, 13 | min: PropTypes.number, 14 | max: PropTypes.number, 15 | pixelDistance: PropTypes.number, 16 | step: PropTypes.number, 17 | value: PropTypes.number.isRequired 18 | }, 19 | 20 | getDefaultProps: function() { 21 | return { 22 | pixelDistance: 10, 23 | step: 1 24 | }; 25 | }, 26 | 27 | render: function() { 28 | return ( 29 |
30 | 31 | 41 |
42 | ); 43 | } 44 | }); 45 | 46 | module.exports = LabelledTangle; 47 | -------------------------------------------------------------------------------- /components/ButtonGroup.jsx: -------------------------------------------------------------------------------- 1 | // Button group with an active state based on currently selected button 2 | 3 | var React = require("react"); 4 | var cx = require("classnames"); 5 | var PropTypes = React.PropTypes; 6 | 7 | var Button = require('./Button.jsx'); 8 | 9 | var ButtonGroup = React.createClass({ 10 | 11 | propTypes: { 12 | value: React.PropTypes.any.isRequired, 13 | buttons: React.PropTypes.arrayOf(React.PropTypes.shape({ 14 | value: React.PropTypes.any.isRequired, 15 | content: React.PropTypes.node, 16 | title: React.PropTypes.string 17 | })).isRequired, 18 | onClick: React.PropTypes.func.isRequired, 19 | className: React.PropTypes.string 20 | }, 21 | 22 | _handleClick: function(e) { 23 | var val = e.target.value; 24 | this.props.onClick(val); 25 | }, 26 | 27 | render: function() { 28 | var buttons = this.props.buttons.map(function(button, i) { 29 | return ( 30 | 58 | ); 59 | } 60 | }); 61 | 62 | module.exports = Button; 63 | -------------------------------------------------------------------------------- /components/Toggle.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * 8 | */ 9 | 10 | var React = require("react"); 11 | var PropTypes = React.PropTypes; 12 | var PureRenderMixin = require("react-addons-pure-render-mixin"); 13 | 14 | var Toggle = React.createClass({ 15 | 16 | mixins: [ PureRenderMixin ], 17 | 18 | propTypes: { 19 | className: PropTypes.string, 20 | label: PropTypes.string.isRequired, 21 | onToggle: PropTypes.func, 22 | toggled: PropTypes.bool 23 | }, 24 | 25 | getDefaultProps: function() { 26 | return { 27 | toggled: false 28 | }; 29 | }, 30 | 31 | getInitialState: function() { 32 | return { 33 | toggled: this.props.toggled || 34 | false 35 | }; 36 | }, 37 | 38 | handleClick: function() { 39 | this.setState({ toggled: !this.state.toggled }, function() { 40 | if (this.props.onToggle) { 41 | this.props.onToggle(this.state.toggled); 42 | } 43 | }); 44 | }, 45 | 46 | render: function() { 47 | var toggleClass = this.state.toggled ? 'toggled' : ''; 48 | return ( 49 |
50 |
51 |
52 | 58 | 59 |
60 | ); 61 | } 62 | }); 63 | 64 | module.exports = Toggle; 65 | -------------------------------------------------------------------------------- /components/TextArea.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | *