├── .babelrc ├── .gitignore ├── README.md ├── components ├── Box │ └── index.jsx ├── Button │ └── index.jsx ├── Card │ └── index.jsx ├── Checkbox │ └── index.jsx ├── Content │ └── index.jsx ├── Control │ └── index.jsx ├── Icon │ └── index.jsx ├── Image │ └── index.jsx ├── Input │ └── index.jsx ├── Label │ └── index.jsx ├── Link │ └── index.jsx ├── Message │ └── index.jsx ├── Modal │ └── index.jsx ├── ModalCard │ └── index.jsx ├── Notification │ └── index.jsx ├── Pagination │ └── index.jsx ├── Progress │ └── index.jsx ├── Radio │ └── index.jsx ├── Select │ └── index.jsx ├── Tag │ └── index.jsx ├── Textarea │ └── index.jsx ├── Title │ └── index.jsx ├── index.js └── utils.js ├── docs ├── box.jsx ├── button.jsx ├── card.jsx ├── checkbox.jsx ├── content.jsx ├── control.jsx ├── docs.css ├── icon.jsx ├── image.jsx ├── index.html ├── index.jsx ├── input.jsx ├── label.jsx ├── link.jsx ├── message.jsx ├── modal.jsx ├── modalcard.jsx ├── notification.jsx ├── pagination.jsx ├── progress.jsx ├── radio.jsx ├── select.jsx ├── tag.jsx ├── textarea.jsx └── title.jsx ├── package.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["stage-1", "react", "es2015"], 3 | "plugins": [ 4 | "transform-class-properties" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## hiromi 2 | 3 | Named so because of the original voice actress of Bulma in Dragonball, [Hiromi Tsuru](https://en.wikipedia.org/wiki/Hiromi_Tsuru) 4 | 5 | React components for [Bulma](http://bulma.io/). 6 | 7 | It's still in the early stages of development and is subject to breaking changes. 8 | 9 | To run the docs: 10 | 11 | `npm run docs` 12 | 13 | To build the production files: 14 | 15 | `npm run build` 16 | 17 | ### helpers 18 | 19 | Every component has a bunch of helper properties attached to them. Note that some of these properties may not effect the style. We made this a default for all components as it allows for less duplication as well as the ability to cover all helpers for all components. Also, Bulma does not give a detailed list of which element has what modifiers. For the full list of modifier classes, go [here](http://bulma.io/documentation/modifiers/syntax/). 20 | 21 | ### components 22 | 23 | - [x] Button 24 | - [x] Checkbox 25 | - [x] Content 26 | - [x] Control 27 | - [x] Icon 28 | - [x] Input 29 | - [x] Label 30 | - [x] Link (Anchor element, similar to Button in style) 31 | - [x] Radio 32 | - [x] Textarea 33 | - [x] Select 34 | - [x] Box 35 | - [x] Notification 36 | - [x] Progress 37 | - [x] Tag 38 | - [x] Titles 39 | - [x] Image 40 | - [x] Card 41 | - [ ] Level 42 | - [ ] Media 43 | - [ ] Menu 44 | - [x] Message 45 | - [ ] Nav 46 | - [x] Pagination 47 | - [ ] Panel 48 | - [ ] Tabs 49 | - [ ] Container 50 | - [ ] Hero 51 | - [ ] Section 52 | - [ ] Footer 53 | - [ ] Grid 54 | - [ ] Tiles 55 | - [ ] Shared helpers - In progress 56 | - [x] Modal 57 | - [x] Modal Card 58 | 59 | ### IE11 support 60 | Bulma has an IE11 bug: modal-card elements will not scroll correctly. We have included a small fix here but it requires the following CSS: 61 | ``` 62 | .modal-card-shell { 63 | display: flex; 64 | flex-direction: column; 65 | max-height: calc(100vh - 40px); 66 | justify-content: center; 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /components/Box/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Box = ({children, className, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames('box', className, classList); 12 | return ( 13 |
14 | {children} 15 |
16 | ); 17 | }; 18 | 19 | Box.propTypes = { 20 | children: PropTypes.node, 21 | ...defaultReactProps 22 | }; 23 | 24 | Box.defaultProps = { 25 | ...defaultReactPropsValues 26 | }; 27 | 28 | export default Box; 29 | -------------------------------------------------------------------------------- /components/Button/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Button = ({ 10 | className, isLink, isInverted, 11 | children, ...props 12 | }) => { 13 | let {classList, ...finalProps} = modifierClassList(props); 14 | classList = classnames('button', className, classList, { 15 | 'is-link': isLink, 16 | 'is-inverted': isInverted, 17 | }); 18 | 19 | return ( 20 | 23 | ); 24 | }; 25 | 26 | Button.propTypes = { 27 | isLink: PropTypes.bool, 28 | isInverted: PropTypes.bool, 29 | children: PropTypes.node, 30 | type: PropTypes.string, 31 | ...defaultReactProps 32 | }; 33 | 34 | Button.defaultProps = { 35 | isLink: false, 36 | isInverted: false, 37 | type: "button", 38 | ...defaultReactPropsValues 39 | }; 40 | 41 | export default Button; 42 | -------------------------------------------------------------------------------- /components/Card/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | import Link from '../Link'; 9 | import Icon from '../Icon'; 10 | 11 | const CardHeaderIcon = ({onIconClick, iconTag}) => { 12 | return ( 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | CardHeaderIcon.propTypes = { 20 | onIconClick: PropTypes.func, 21 | iconTag: PropTypes.string 22 | }; 23 | 24 | const CardFooter = ({children}) => { 25 | return ( 26 | 33 | ); 34 | }; 35 | 36 | CardFooter.propTypes = { 37 | children: PropTypes.arrayOf(PropTypes.element) 38 | }; 39 | 40 | const Card = ({footer, title, iconTag, onIconClick, className, children, ...props}) => { 41 | let {classList, ...finalProps} = modifierClassList(props); 42 | classList = classnames('card', className, classList); 43 | 44 | const icon = iconTag ? : null; 45 | 46 | const header = title || icon ? ( 47 |
48 |

49 | {title} 50 |

51 | {icon} 52 |
53 | ) : null; 54 | 55 | return ( 56 |
57 | {header} 58 |
59 | {children} 60 |
61 | {footer} 62 |
63 | ); 64 | }; 65 | 66 | Card.propTypes = { 67 | title: PropTypes.node, 68 | iconTag: PropTypes.string, 69 | onIconClick: PropTypes.func, 70 | footer: PropTypes.instanceOf(CardFooter), 71 | ...defaultReactProps 72 | }; 73 | 74 | Card.defaultProps = { 75 | ...defaultReactPropsValues 76 | }; 77 | 78 | export { 79 | Card as default, 80 | CardFooter 81 | }; 82 | -------------------------------------------------------------------------------- /components/Checkbox/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import Label from '../Label'; 6 | import {defaultReactProps, defaultReactPropsValues} from '../utils'; 7 | 8 | const Checkbox = ({input, children, ...props}) => { 9 | const inputElement = input ? input : ; 10 | 11 | return ( 12 | 16 | ); 17 | }; 18 | 19 | Checkbox.propTypes = { 20 | input: PropTypes.node, 21 | children: PropTypes.node, 22 | ...defaultReactProps 23 | }; 24 | 25 | Checkbox.defaultProps = { 26 | ...defaultReactPropsValues 27 | }; 28 | 29 | export default Checkbox; 30 | -------------------------------------------------------------------------------- /components/Content/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Content = ({children, className, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames('content', className, classList); 12 | return ( 13 |
14 | {children} 15 |
16 | ) 17 | }; 18 | 19 | Content.propTypes = { 20 | children: PropTypes.node, 21 | ...defaultReactProps 22 | }; 23 | 24 | Content.defaultProps = { 25 | ...defaultReactPropsValues 26 | }; 27 | 28 | export default Content; 29 | -------------------------------------------------------------------------------- /components/Control/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import Icon from '../Icon'; 6 | import Label from '../Label'; 7 | import { 8 | modifierClassList, defaultReactProps, defaultReactPropsValues 9 | } from '../utils'; 10 | 11 | const Control = ({ 12 | iconTag, iconRight, hasAddons, prefix, suffix, 13 | isGrouped, isHorizontal, className, children, ...props 14 | }) => { 15 | const hasIcon = !!iconTag; 16 | const icon = hasIcon ? : null; 17 | 18 | let {classList, ...finalProps} = modifierClassList(props); 19 | classList = classnames('control', className, classList, { 20 | 'has-icon': hasIcon, 21 | 'has-icon-right': iconRight, 22 | 'has-addons': hasAddons, 23 | 'is-grouped': isGrouped, 24 | }); 25 | 26 | return ( 27 |
28 | {prefix} 29 | {children} 30 | {icon} 31 | {suffix} 32 |
33 | ); 34 | }; 35 | 36 | Control.propTypes = { 37 | iconTag: PropTypes.string, 38 | iconRight: PropTypes.bool, 39 | hasAddons: PropTypes.bool, 40 | isGrouped: PropTypes.bool, 41 | prefix: PropTypes.node, 42 | suffix: PropTypes.node, 43 | children: PropTypes.node, 44 | ...defaultReactProps 45 | }; 46 | 47 | Control.defaultProps = { 48 | iconRight: false, 49 | hasAddons: false, 50 | isGrouped: false, 51 | ...defaultReactPropsValues 52 | }; 53 | 54 | const HorizontalControl = ({label, className, children, ...props}) => { 55 | let {classList, ...finalProps} = modifierClassList(props); 56 | classList = classnames('control', className, 'is-horizontal', classList); 57 | 58 | return ( 59 |
60 |
61 | 62 |
63 | {children} 64 |
65 | ); 66 | }; 67 | 68 | HorizontalControl.propTypes = { 69 | label: PropTypes.string, 70 | children: PropTypes.element.isRequired, 71 | ...defaultReactProps 72 | }; 73 | 74 | HorizontalControl.defaultProps = { 75 | ...defaultReactPropsValues 76 | }; 77 | 78 | export { 79 | Control as default, 80 | HorizontalControl 81 | }; 82 | -------------------------------------------------------------------------------- /components/Icon/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Icon = ({tag, hasSpan, className, ...props}) => { 10 | const iconElement = ; 11 | if (!hasSpan) { 12 | return iconElement; 13 | } 14 | 15 | let {classList, ...finalProps} = modifierClassList(props); 16 | classList = classnames('icon', className, classList); 17 | 18 | return ( 19 | 20 | {iconElement} 21 | 22 | ); 23 | }; 24 | 25 | Icon.propTypes = { 26 | tag: PropTypes.string.isRequired, 27 | hasSpan: PropTypes.bool, 28 | ...defaultReactProps 29 | }; 30 | 31 | Icon.defaultProps = { 32 | hasSpan: true, 33 | ...defaultReactPropsValues 34 | }; 35 | 36 | export default Icon; 37 | -------------------------------------------------------------------------------- /components/Image/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Image = ({src, size, ratio, className, children, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames( 12 | 'image', className, classList, 13 | size ? `is-${size}x${size}` : null, 14 | ratio ? `is-${ratio}` : null 15 | ); 16 | 17 | let content = src ? : children; 18 | 19 | return ( 20 |
21 | {content} 22 |
23 | ) 24 | }; 25 | 26 | Image.propTypes = { 27 | src: PropTypes.string, 28 | size: PropTypes.oneOf([16, 24, 32, 48, 64, 96, 128]), 29 | ratio: PropTypes.oneOf(['square', '1by1', '4by3', '3by2', '16by9', '2by1']), 30 | children: PropTypes.element, 31 | ...defaultReactProps 32 | }; 33 | 34 | Image.defaultProps = { 35 | ...defaultReactPropsValues 36 | }; 37 | 38 | export default Image; 39 | -------------------------------------------------------------------------------- /components/Input/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | import { 5 | modifierClassList, defaultReactProps, defaultReactPropsValues 6 | } from '../utils'; 7 | 8 | class Input extends Component { 9 | render() { 10 | let {classList, className, ...finalProps} = modifierClassList(this.props); 11 | classList = classnames('input', className, classList); 12 | return ( 13 | 14 | ); 15 | } 16 | } 17 | 18 | Input.propTypes = { 19 | ...defaultReactProps 20 | }; 21 | 22 | Input.defaultProps = { 23 | ...defaultReactPropsValues 24 | }; 25 | 26 | export default Input; 27 | -------------------------------------------------------------------------------- /components/Label/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Label = ({className, children, isCheckbox, isRadio, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames(className, classList, { 12 | 'label': !isCheckbox && !isRadio, 13 | 'checkbox': isCheckbox, 14 | 'radio': isRadio 15 | }); 16 | return ( 17 | 20 | ) 21 | }; 22 | 23 | Label.propTypes = { 24 | isDisabled: PropTypes.bool, 25 | isCheckbox: PropTypes.bool, 26 | isRadio: PropTypes.bool, 27 | children: PropTypes.node, 28 | ...defaultReactProps 29 | }; 30 | 31 | Label.defaultProps = { 32 | isDisabled: false, 33 | isCheckbox: false, 34 | isRadio: false, 35 | ...defaultReactPropsValues 36 | }; 37 | 38 | export default Label; 39 | -------------------------------------------------------------------------------- /components/Link/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Link = ({isButton, className, isLink, isInverted, children, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames(className, classList, { 12 | 'button': isButton, 13 | 'is-link': isLink, 14 | 'is-inverted': isInverted 15 | }); 16 | 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | }; 23 | 24 | Link.propTypes = { 25 | isButton: PropTypes.bool, 26 | isLink: PropTypes.bool, 27 | isInverted: PropTypes.bool, 28 | children: PropTypes.node, 29 | ...defaultReactProps 30 | }; 31 | 32 | Link.defaultProps = { 33 | isButton: true, 34 | isLink: false, 35 | isInverted: false, 36 | ...defaultReactPropsValues 37 | }; 38 | 39 | export default Link; 40 | -------------------------------------------------------------------------------- /components/Message/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Message = ({title, className, children, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames('message', className, classList); 12 | 13 | const header = title ?
{title}
: null; 14 | 15 | return ( 16 |
17 | {header} 18 |
19 | {children} 20 |
21 |
22 | ); 23 | }; 24 | 25 | Message.propTypes = { 26 | title: PropTypes.string, 27 | children: PropTypes.node.isRequired, 28 | ...defaultReactProps 29 | }; 30 | 31 | Message.defaultProps = { 32 | ...defaultReactPropsValues 33 | }; 34 | 35 | export default Message; 36 | -------------------------------------------------------------------------------- /components/Modal/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | import { 5 | modifierClassList, defaultReactProps, defaultReactPropsValues 6 | } from '../utils'; 7 | 8 | class Modal extends Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | open: props.visible 13 | }; 14 | this.handleClose = this.handleClose.bind(this); 15 | } 16 | 17 | componentWillReceiveProps(nextProps) { 18 | this.setState({open: nextProps.visible}); 19 | } 20 | 21 | componentDidUpdate(prevProps, prevState) { 22 | if (this.state.open !== prevState.open) { 23 | if (this.state.open) { 24 | if (this.props.onOpen) { this.props.onOpen(); } 25 | } else { 26 | if (this.props.onClose) { this.props.onClose(); } 27 | } 28 | } 29 | } 30 | 31 | get closeButton() { 32 | if (this.props.showClose) { 33 | return ; 34 | } 35 | } 36 | 37 | handleClose() { 38 | this.setState({open: false}); 39 | } 40 | 41 | render() { 42 | let {classList, ...finalProps} = modifierClassList(this.props); 43 | classList = classnames('modal', this.props.className, classList, {'is-active': this.state.open}); 44 | 45 | return ( 46 |
47 |
48 |
49 | {this.props.children} 50 |
51 | {this.closeButton} 52 |
53 | ); 54 | } 55 | }; 56 | 57 | Modal.propTypes = { 58 | visible: PropTypes.bool, 59 | showClose: PropTypes.bool, 60 | onOpen: PropTypes.func, 61 | onClose: PropTypes.func, 62 | ...defaultReactProps 63 | }; 64 | 65 | Modal.defaultProps = { 66 | visible: false, 67 | showClose: true, 68 | ...defaultReactPropsValues 69 | }; 70 | 71 | export default Modal; 72 | -------------------------------------------------------------------------------- /components/ModalCard/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | import { 5 | modifierClassList, defaultReactProps, defaultReactPropsValues 6 | } from '../utils'; 7 | 8 | const ModalCardFooter = ({children}) => { 9 | return ( 10 |
11 | {children} 12 |
13 | ); 14 | }; 15 | 16 | ModalCardFooter.propTypes = { 17 | children: PropTypes.node 18 | }; 19 | 20 | class ModalCard extends Component { 21 | constructor(props) { 22 | super(props); 23 | this.state = { 24 | open: props.visible 25 | }; 26 | this.handleClose = this.handleClose.bind(this); 27 | } 28 | 29 | componentWillReceiveProps(nextProps) { 30 | this.setState({open: nextProps.visible}); 31 | } 32 | 33 | componentDidUpdate(prevProps, prevState) { 34 | if (this.state.open !== prevState.open) { 35 | if (this.state.open) { 36 | if (this.props.onOpen) { this.props.onOpen(); } 37 | } else { 38 | if (this.props.onClose) { this.props.onClose(); } 39 | } 40 | } 41 | } 42 | 43 | get closeButton() { 44 | if (this.props.showClose) { 45 | return ; 46 | } 47 | } 48 | 49 | get renderHeader() { 50 | if (!this.props.title && !this.props.showClose) return; 51 | return ( 52 |
53 |

{this.props.title}

54 | {this.closeButton} 55 |
56 | ); 57 | } 58 | 59 | handleClose() { 60 | this.setState({open: false}); 61 | } 62 | 63 | render() { 64 | let {classList, ...finalProps} = modifierClassList(this.props); 65 | classList = classnames('modal', this.props.className, classList, {'is-active': this.state.open}); 66 | 67 | return ( 68 |
69 |
70 |
71 |
72 | {this.renderHeader} 73 |
74 | {this.props.children} 75 |
76 | {this.props.footer} 77 |
78 |
79 |
80 | ); 81 | } 82 | }; 83 | 84 | ModalCard.propTypes = { 85 | title: PropTypes.node, 86 | footer: PropTypes.node, 87 | visible: PropTypes.bool, 88 | showClose: PropTypes.bool, 89 | onOpen: PropTypes.func, 90 | onClose: PropTypes.func, 91 | ...defaultReactProps 92 | }; 93 | 94 | ModalCard.defaultProps = { 95 | visible: false, 96 | showClose: true, 97 | ...defaultReactPropsValues 98 | }; 99 | 100 | export { 101 | ModalCard as default, 102 | ModalCardFooter 103 | }; 104 | -------------------------------------------------------------------------------- /components/Notification/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import Button from '../Button'; 6 | import { 7 | modifierClassList, defaultReactProps, defaultReactPropsValues 8 | } from '../utils'; 9 | 10 | const Notification = ({onClose, children, className, ...props}) => { 11 | let {classList, ...finalProps} = modifierClassList(props); 12 | classList = classnames('notification', className, classList); 13 | return ( 14 |
15 | 16 | {children} 17 |
18 | ); 19 | }; 20 | 21 | Notification.propTypes = { 22 | onClose: PropTypes.func, 23 | children: PropTypes.node, 24 | ...defaultReactProps 25 | }; 26 | 27 | Notification.defaultProps = { 28 | ...defaultReactPropsValues 29 | }; 30 | 31 | export default Notification; 32 | -------------------------------------------------------------------------------- /components/Pagination/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | import Link from '../Link'; 9 | 10 | const PageItems = ({pagesVisible, onChange, pageCount, currentPage, ...props}) => { 11 | let items = []; 12 | // compute minLeft and maxRight indeces of page buttons 13 | // which exclude first and last pages. 14 | let minLeft = currentPage - Math.floor(pagesVisible/2); 15 | if (minLeft < 2) minLeft = 2; 16 | let maxRight = minLeft + pagesVisible - 1; 17 | if (maxRight >= pageCount) { 18 | maxRight = pageCount - 1; 19 | minLeft = maxRight - pagesVisible + 1; 20 | if (minLeft < 2) minLeft = 2; 21 | } 22 | 23 | for (let i = 1; i <= pageCount; i++) { 24 | if ( 25 | i !== 1 && i !== pageCount && 26 | (i < minLeft || i > maxRight) 27 | ) { 28 | continue; 29 | } 30 | 31 | // If it's the min left visible, and there were skipped items 32 | if (i === minLeft && minLeft > 2) { 33 | items.push( 34 |
  • 35 | ... 36 |
  • 37 | ); 38 | } 39 | 40 | const active = i === currentPage; 41 | const className = classnames({ 42 | 'is-active': active 43 | }); 44 | items.push( 45 |
  • 46 | {i} 47 |
  • 48 | ); 49 | 50 | // If it's the max right visible, and there will be skipped items 51 | if (i === maxRight && maxRight < pageCount - 1) { 52 | items.push( 53 |
  • 54 | ... 55 |
  • 56 | ); 57 | } 58 | } 59 | return ; 60 | }; 61 | 62 | const onPaginate = (onChange, pageIndex) => { 63 | return (event) => { 64 | let args = [...arguments]; 65 | args.splice(0, 0, pageIndex); 66 | onChange(...args); 67 | }; 68 | }; 69 | 70 | const LeftLevel = ({ 71 | hasFirst, hasPrevious, first, previous, onChange, currentPage, ...props 72 | }) => { 73 | let firstItem = hasFirst ? ( 74 | {first} 75 | ) : null; 76 | let previousItem = hasPrevious ? ( 77 | {previous} 78 | ) : null; 79 | 80 | return ( 81 |
    82 | {firstItem} 83 | {previousItem} 84 |
    85 | ); 86 | }; 87 | 88 | const RightLevel = ({ 89 | hasNext, hasLast, next, last, onChange, pageCount, currentPage, ...props 90 | }) => { 91 | let lastItem = hasLast ? ( 92 | {last} 93 | ) : null; 94 | let nextItem = hasNext ? ( 95 | {next} 96 | ) : null; 97 | 98 | return ( 99 |
    100 | {nextItem} 101 | {lastItem} 102 |
    103 | ); 104 | }; 105 | 106 | const Pagination = ({ 107 | currentPage, pageCount, hasFirst, first, hasPrevious, previous, 108 | hasNext, next, hasLast, last, className, onChange, pagesVisible, 109 | ...props 110 | }) => { 111 | let {classList, ...finalProps} = modifierClassList(props); 112 | classList = classnames('level', className, classList); 113 | 114 | const leftLevel = hasFirst || hasPrevious ? ( 115 | 123 | ) : null; 124 | 125 | const rightLevel = hasNext || hasLast ? ( 126 | 135 | ) : null; 136 | 137 | return ( 138 |
    139 | {leftLevel} 140 |
    141 | 149 |
    150 | {rightLevel} 151 |
    152 | ) 153 | }; 154 | 155 | Pagination.propTypes = { 156 | currentPage: PropTypes.number, 157 | pageCount: PropTypes.number, 158 | hasFirst: PropTypes.bool, 159 | first: PropTypes.node, 160 | hasPrevious: PropTypes.bool, 161 | previous: PropTypes.node, 162 | hasNext: PropTypes.bool, 163 | next: PropTypes.node, 164 | hasLast: PropTypes.bool, 165 | last: PropTypes.node, 166 | pagesVisible: PropTypes.number, 167 | 168 | onChange: PropTypes.func, 169 | ...defaultReactProps 170 | }; 171 | 172 | Pagination.defaultProps = { 173 | hasFirst: true, 174 | first: "First", 175 | hasPrevious: true, 176 | previous: "Previous", 177 | hasNext: true, 178 | next: "Next", 179 | hasLast: true, 180 | last: "Last", 181 | pagesVisible: 2, 182 | ...defaultReactPropsValues 183 | }; 184 | 185 | export default Pagination; 186 | -------------------------------------------------------------------------------- /components/Progress/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Progress = ({className, value, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames('progress', className, classList); 12 | return ( 13 | {value}% 14 | ) 15 | }; 16 | 17 | Progress.propTypes = { 18 | value: PropTypes.number, 19 | max: PropTypes.number, 20 | ...defaultReactProps 21 | }; 22 | 23 | Progress.defaultProps = { 24 | value: 0, 25 | max: 100, 26 | ...defaultReactPropsValues 27 | }; 28 | 29 | export default Progress; 30 | -------------------------------------------------------------------------------- /components/Radio/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import Label from '../Label'; 6 | import {defaultReactProps, defaultReactPropsValues} from '../utils'; 7 | 8 | const Radio = ({input, name, value, children, ...props}) => { 9 | const inputElement = input ? input : ; 10 | 11 | return ( 12 | 16 | ); 17 | }; 18 | 19 | Radio.propTypes = { 20 | input: PropTypes.node, 21 | name: PropTypes.string, 22 | value: PropTypes.string, 23 | children: PropTypes.node, 24 | ...defaultReactProps 25 | }; 26 | 27 | Radio.defaultProps = { 28 | ...defaultReactPropsValues 29 | }; 30 | 31 | export default Radio; 32 | -------------------------------------------------------------------------------- /components/Select/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const valueAtPath = (item, path) => { 10 | let value = item; 11 | for (let key of path) { 12 | value = value[key]; 13 | } 14 | return value; 15 | }; 16 | 17 | const placeholder = (name, value) => { 18 | if (!name) return null; 19 | return ( 27 | ); 28 | }; 29 | 30 | Option.propTypes = { 31 | item: PropTypes.object, 32 | valuePath: PropTypes.array, 33 | labelPath: PropTypes.array.isRequired 34 | }; 35 | 36 | Option.defaultProps = { 37 | labelPath: ['name'] 38 | }; 39 | 40 | const Select = ({ 41 | children, options, className, valuePath, labelPath, onChange, defaultValue, value, placeholderText, placeholderValue, ...props 42 | }) => { 43 | let {classList, ...finalProps} = modifierClassList(props); 44 | classList = classnames('select', className, classList); 45 | return ( 46 | 47 | 56 | 57 | ); 58 | }; 59 | 60 | Select.propTypes = { 61 | options: PropTypes.array.isRequired, 62 | valuePath: PropTypes.array, 63 | labelPath: PropTypes.array.isRequired, 64 | children: PropTypes.node, 65 | ...defaultReactProps 66 | }; 67 | 68 | Select.defaultProps = { 69 | labelPath: ['name'], 70 | ...defaultReactPropsValues 71 | }; 72 | 73 | export { 74 | Select as default, 75 | Option 76 | }; 77 | -------------------------------------------------------------------------------- /components/Tag/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const Tag = ({hasDelete, onDelete, isDark, children, className, ...props}) => { 10 | let {classList, ...finalProps} = modifierClassList(props); 11 | classList = classnames('tag', className, classList, { 12 | 'is-dark': isDark 13 | }); 14 | 15 | const deleteButton = hasDelete ? ( 16 | 17 | ) : null; 18 | 19 | return ( 20 | 21 | {children} 22 | {deleteButton} 23 | 24 | ); 25 | }; 26 | 27 | Tag.propTypes = { 28 | isDark: PropTypes.bool, 29 | hasDelete: PropTypes.bool, 30 | onDelete: PropTypes.func, 31 | ...defaultReactProps 32 | }; 33 | 34 | Tag.defaultProps = { 35 | isDark: false, 36 | hasDelete: false, 37 | ...defaultReactPropsValues 38 | }; 39 | 40 | export default Tag; 41 | -------------------------------------------------------------------------------- /components/Textarea/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | import { 5 | modifierClassList, defaultReactProps, defaultReactPropsValues 6 | } from '../utils'; 7 | 8 | class Textarea extends Component { 9 | render() { 10 | let {classList, className, ...finalProps} = modifierClassList(this.props); 11 | classList = classnames('textarea', className, classList); 12 | return ( 13 | 14 | ); 15 | } 16 | } 17 | 18 | Textarea.propTypes = { 19 | ...defaultReactProps 20 | }; 21 | 22 | Textarea.defaultProps = { 23 | ...defaultReactPropsValues 24 | }; 25 | 26 | export default Textarea; 27 | -------------------------------------------------------------------------------- /components/Title/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classnames from 'classnames'; 5 | import { 6 | modifierClassList, defaultReactProps, defaultReactPropsValues 7 | } from '../utils'; 8 | 9 | const getTitleSizeClass = (size) => { 10 | return classnames({ 11 | 'is-1': size === 1, 12 | 'is-2': size === 2, 13 | 'is-3': size === 3, 14 | 'is-4': size === 4, 15 | 'is-5': size === 5, 16 | 'is-6': size === 6 17 | }); 18 | }; 19 | 20 | const Title = ({className, children, size, ...props}) => { 21 | let {classList, ...finalProps} = modifierClassList(props); 22 | classList = classnames('title', className, getTitleSizeClass(size), classList); 23 | return React.cloneElement( 24 | children, 25 | { 26 | className: classList, 27 | ...finalProps 28 | } 29 | ); 30 | }; 31 | 32 | Title.propTypes = { 33 | size: PropTypes.oneOf([ 34 | 1, 2, 3, 4, 5, 6 35 | ]), 36 | children: PropTypes.element, 37 | ...defaultReactProps 38 | }; 39 | 40 | Title.defaultProps = { 41 | ...defaultReactPropsValues 42 | }; 43 | 44 | const Subtitle = ({className, children, size, ...props}) => { 45 | let {classList, ...finalProps} = modifierClassList(props); 46 | classList = classnames('subtitle', className, getTitleSizeClass(size), classList); 47 | return React.cloneElement( 48 | children, 49 | { 50 | className: classList, 51 | ...finalProps 52 | } 53 | ); 54 | }; 55 | 56 | Subtitle.propTypes = { 57 | size: PropTypes.oneOf([ 58 | 1, 2, 3, 4, 5, 6 59 | ]), 60 | children: PropTypes.element, 61 | ...defaultReactProps 62 | }; 63 | 64 | Subtitle.defaultProps = { 65 | ...defaultReactPropsValues 66 | }; 67 | 68 | export { 69 | Title, 70 | Subtitle 71 | }; 72 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | import Button from './Button'; 2 | import Content from './Content'; 3 | import Control, {HorizontalControl} from './Control'; 4 | import Icon from './Icon'; 5 | import Input from './Input'; 6 | import Label from './Label'; 7 | import Link from './Link'; 8 | import Checkbox from './Checkbox'; 9 | import Radio from './Radio'; 10 | import Textarea from './Textarea'; 11 | import Select, {Option} from './Select'; 12 | import Notification from './Notification'; 13 | import Progress from './Progress'; 14 | import Tag from './Tag'; 15 | import {Title, Subtitle} from './Title'; 16 | import Image from './Image'; 17 | import Card, {CardFooter} from './Card'; 18 | import Message from './Message'; 19 | import Pagination from './Pagination'; 20 | 21 | export default { 22 | Button, 23 | Content, 24 | Control, 25 | HorizontalControl, 26 | Icon, 27 | Input, 28 | Label, 29 | Link, 30 | Checkbox, 31 | Radio, 32 | Textarea, 33 | Select, 34 | Option, 35 | Notification, 36 | Progress, 37 | Tag, 38 | Title, 39 | Subtitle, 40 | Image, 41 | Card, 42 | CardFooter, 43 | Message, 44 | Pagination 45 | }; 46 | -------------------------------------------------------------------------------- /components/utils.js: -------------------------------------------------------------------------------- 1 | import {PropTypes} from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const defaultReactProps = { 5 | isPrimary: PropTypes.bool, 6 | isInfo: PropTypes.bool, 7 | isSuccess: PropTypes.bool, 8 | isWarning: PropTypes.bool, 9 | isDanger: PropTypes.bool, 10 | isSmall: PropTypes.bool, 11 | isMedium: PropTypes.bool, 12 | isLarge: PropTypes.bool, 13 | isOutlined: PropTypes.bool, 14 | isLoading: PropTypes.bool, 15 | isDisabled: PropTypes.bool, 16 | isMarginless: PropTypes.bool, 17 | isUnselectable: PropTypes.bool, 18 | hasTextCentered: PropTypes.bool, 19 | hasTextLeft: PropTypes.bool, 20 | hasTextRight: PropTypes.bool, 21 | isFullWidth: PropTypes.bool, 22 | isClearfix: PropTypes.bool, 23 | isPulledLeft: PropTypes.bool, 24 | isPulledRight: PropTypes.bool, 25 | isOverlay: PropTypes.bool 26 | }; 27 | 28 | const defaultReactPropsValues = { 29 | isPrimary: false, 30 | isInfo: false, 31 | isSuccess: false, 32 | isWarning: false, 33 | isDanger: false, 34 | isSmall: false, 35 | isMedium: false, 36 | isLarge: false, 37 | isOutlined: false, 38 | isLoading: false, 39 | isDisabled: false, 40 | isMarginless: false, 41 | isUnselectable: false, 42 | hasTextCentered: false, 43 | hasTextLeft: false, 44 | hasTextRight: false, 45 | isFullWidth: false, 46 | isClearfix: false, 47 | isPulledLeft: false, 48 | isPulledRight: false, 49 | isOverlay: false 50 | } 51 | 52 | const modifierClassList = ({ 53 | isPrimary, isInfo, isSuccess, isWarning, 54 | isDanger, isSmall, isMedium, isLarge, 55 | isOutlined, isLoading, isDisabled, 56 | isMarginless, isUnselectable, 57 | hasTextCentered, hasTextLeft, hasTextRight, 58 | isFullWidth, isClearfix, isPulledLeft, 59 | isPulledRight, isOverlay, 60 | ...props 61 | }) => { 62 | return { 63 | classList: classnames({ 64 | // Colors 65 | 'is-primary': isPrimary, 66 | 'is-info': isInfo, 67 | 'is-success': isSuccess, 68 | 'is-warning': isWarning, 69 | 'is-danger': isDanger, 70 | 71 | // Sizes 72 | 'is-small': isSmall, 73 | 'is-medium': isMedium, 74 | 'is-large': isLarge, 75 | 'is-fullwidth': isFullWidth, 76 | 77 | // State 78 | 'is-outlined': isOutlined, 79 | 'is-loading': isLoading, 80 | 'is-disabled': isDisabled, 81 | 82 | // Helpers 83 | 'is-marginless': isMarginless, 84 | 'is-unselectable': isUnselectable, 85 | 86 | // Text 87 | 'has-text-centered': hasTextCentered, 88 | 'has-text-left': hasTextLeft, 89 | 'has-text-right': hasTextRight, 90 | 91 | // Float 92 | 'is-clearfix': isClearfix, 93 | 'is-pulled-left': isPulledLeft, 94 | 'is-pulled-right': isPulledRight, 95 | 96 | // Overlay 97 | 'is-overlay': isOverlay 98 | }), 99 | ...props 100 | }; 101 | }; 102 | 103 | export { 104 | defaultReactProps, 105 | defaultReactPropsValues, 106 | modifierClassList 107 | }; 108 | -------------------------------------------------------------------------------- /docs/box.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Box from '../components/Box'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Box

    10 | 16 |
    17 | ); 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /docs/button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Button from '../components/Button'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Button

    10 | 29 |
    30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /docs/card.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Card, {CardFooter} from '../components/Card'; 4 | import Link from '../components/Link'; 5 | 6 | export default React.createClass({ 7 | render() { 8 | return ( 9 |
    10 |

    Card

    11 | "CLICKED"), 18 | children: P.string('This is a box area') 19 | }} 20 | > 21 | {props => { 22 | return ( 23 | 24 | ); 25 | }} 26 | 27 | 28 |

    Card with footer

    29 | "CLICKED"), 36 | children: P.string('This is a box area') 37 | }} 38 | > 39 | {props => { 40 | return ( 41 | 44 | Close 45 | 46 | } 47 | {...props} 48 | /> 49 | ); 50 | }} 51 | 52 | 53 |

    Card with complex footer

    54 | "CLICKED"), 61 | children: P.string('This is a box area') 62 | }} 63 | > 64 | {props => { 65 | return ( 66 | 69 |
    70 | Close 71 |
    72 |
    73 | Submit 74 |
    75 | 76 | } 77 | {...props} 78 | /> 79 | ); 80 | }} 81 |
    82 |
    83 | ); 84 | } 85 | }); 86 | -------------------------------------------------------------------------------- /docs/checkbox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Checkbox from '../components/Checkbox'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Checkbox

    10 | 16 | {props => { 17 | return ; 18 | }} 19 | 20 | 21 |

    Checkbox with custom input

    22 | 28 | {props => { 29 | return ( 30 | } {...props}> 31 | ); 32 | }} 33 | 34 |
    35 | ); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /docs/content.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Content from '../components/Content'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Content

    10 | 18 |
    19 | ); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /docs/control.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Control, {HorizontalControl} from '../components/Control'; 4 | import Input from '../components/Input'; 5 | import Link from '../components/Link'; 6 | 7 | export default React.createClass({ 8 | render() { 9 | return ( 10 |
    11 |

    Control

    12 | 22 | {props => { 23 | return ( 24 | 25 | 26 | 27 | ); 28 | }} 29 | 30 |

    Control with Addons

    31 | 41 | {props => { 42 | return ( 43 | Cancel} suffix={Login} {...props}> 44 | 45 | 46 | ); 47 | }} 48 | 49 |

    Grouped Control

    50 | 60 | {props => { 61 | return ( 62 | Cancel} suffix={Login} {...props}> 63 | 64 | 65 | ); 66 | }} 67 | 68 |

    Horizontal Controls

    69 | 75 | {props => { 76 | return ( 77 | 78 | 79 | 80 | 81 | 82 | ); 83 | }} 84 | 85 |
    86 | ); 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /docs/docs.css: -------------------------------------------------------------------------------- 1 | html { 2 | background: #fff; 3 | } 4 | -------------------------------------------------------------------------------- /docs/icon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Icon from '../components/Icon'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Icon

    10 | 20 |
    21 | ); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /docs/image.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Image from '../components/Image'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Image

    10 | 22 |
    23 | ); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/index.jsx: -------------------------------------------------------------------------------- 1 | require('bulma/css/bulma.css'); 2 | require('./docs.css'); 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | 6 | import ReactDOM from 'react-dom'; 7 | import { 8 | Router, Route, Link as ReactRouterLink, hashHistory 9 | } from 'react-router' 10 | 11 | import Button from './button'; 12 | import Link from './link'; 13 | import Content from './content'; 14 | import Icon from './icon'; 15 | import Input from './input'; 16 | import Label from './label'; 17 | import Control from './control'; 18 | import Checkbox from './checkbox'; 19 | import Radio from './radio'; 20 | import Textarea from './textarea'; 21 | import Select from './select'; 22 | import Box from './box'; 23 | import Progress from './progress'; 24 | import Notification from './notification'; 25 | import Tag from './tag'; 26 | import Title from './title'; 27 | import Image from './image'; 28 | import Card from './card'; 29 | import Message from './message'; 30 | import Pagination from './pagination'; 31 | import ModalCard from './modalcard'; 32 | 33 | const Description = React.createClass({ 34 | propTypes: { 35 | children: PropTypes.node.isRequired 36 | }, 37 | 38 | render() { 39 | return ( 40 |

    41 | {this.props.children} 42 |

    43 | ); 44 | } 45 | }); 46 | 47 | const App = React.createClass({ 48 | render() { 49 | return ( 50 |
    51 |
    52 |
    53 |
    54 |

    55 | Components 56 |

    57 |
      58 |
    • Button
    • 59 |
    • Link
    • 60 |
    • Icon
    • 61 |
    • Content
    • 62 |
    • Input
    • 63 |
    • Label
    • 64 |
    • Control
    • 65 |
    • Checkbox
    • 66 |
    • Radio
    • 67 |
    • Textarea
    • 68 |
    • Select
    • 69 |
    • Box
    • 70 |
    • Progress
    • 71 |
    • Notification
    • 72 |
    • Tag
    • 73 |
    • Title
    • 74 |
    • Image
    • 75 |
    • Card
    • 76 |
    • Message
    • 77 |
    • Pagination
    • 78 |
    • ModalCard
    • 79 |
    80 |
    81 |
    82 |
    83 | {this.props.children} 84 |
    85 |
    86 |
    87 | ); 88 | } 89 | }); 90 | 91 | ReactDOM.render( 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | , 117 | document.getElementById('app') 118 | ); 119 | -------------------------------------------------------------------------------- /docs/input.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Input from '../components/Input'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Input

    10 | 23 |
    24 | ); 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /docs/label.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Label from '../components/Label'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Label

    10 | 19 |
    20 | ); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /docs/link.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Link from '../components/Link'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Link

    10 | 29 |
    30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /docs/message.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Message from '../components/Message'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Message

    10 | 22 |
    23 | ); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /docs/modal.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Modal from '../components/Modal'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Modal

    10 | "OPENED"), 31 | onClose: P.callback.log(() => "CLOSED") 32 | }}/> 33 |
    34 | ); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /docs/modalcard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import ModalCard, { ModalCardFooter } from '../components/ModalCard'; 4 | import Button from '../components/Button'; 5 | 6 | export default React.createClass({ 7 | render() { 8 | return ( 9 |
    10 |

    ModalCard

    11 | "OPENED"), 32 | onClose: P.callback.log(() => "CLOSED") 33 | }}/> 34 |

    ModalCard with Footer

    35 | "OPENED"), 56 | onClose: P.callback.log(() => "CLOSED") 57 | }}> 58 | {props => { 59 | return ( 60 | } {...props}> 61 | ); 62 | }} 63 | 64 |
    65 | ); 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /docs/notification.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Notification from '../components/Notification'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Notification

    10 | "CLOSED!"), 20 | children: P.string('This is a notification') 21 | }}/> 22 |
    23 | ); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /docs/pagination.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Pagination from '../components/Pagination'; 4 | import Icon from '../components/Icon'; 5 | 6 | export default React.createClass({ 7 | render() { 8 | return ( 9 |
    10 |

    Pagination

    11 | `Page: ${index}`), 26 | pagesVisible: P.number(2) 27 | }}/> 28 | 29 |

    Pagination with Icons

    30 | `Page: ${index}`), 40 | pagesVisible: P.number(2) 41 | }} 42 | > 43 | {props => { 44 | return ( 45 | } 47 | previous={} 48 | next={} 49 | last={} 50 | {...props} 51 | /> 52 | ); 53 | }} 54 | 55 |
    56 | ); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /docs/progress.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Progress from '../components/Progress'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Progress

    10 | 25 |
    26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /docs/radio.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Radio from '../components/Radio'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Radio

    10 | 18 | {props => { 19 | return ( 20 |
    21 | 22 | This is a test 23 |
    24 | ); 25 | }} 26 |
    27 | 28 |

    Radio with custom input

    29 | 36 | {props => { 37 | return ( 38 | } {...props}> 39 | ); 40 | }} 41 | 42 |
    43 | ); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /docs/select.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Select from '../components/Select'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Select

    10 | { return "CHANGED"; }), 18 | defaultValue: P.string("2") 19 | }} 20 | > 21 | {props => { 22 | return ( 23 | 40 | ); 41 | }} 42 | 43 |
    44 | ); 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /docs/tag.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Tag from '../components/Tag'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Tag

    10 | "DELETED") 26 | }}/> 27 |
    28 | ); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /docs/textarea.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import Textarea from '../components/Textarea'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Textarea

    10 | 15 |
    16 | ); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /docs/title.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo, {props as P} from 'react-demo'; 3 | import {Title, Subtitle} from '../components/Title'; 4 | 5 | export default React.createClass({ 6 | render() { 7 | return ( 8 |
    9 |

    Title

    10 | 19 | {props => { 20 | return ( 21 | 22 | <h1>Title 1</h1> 23 | 24 | ); 25 | }} 26 | 27 |

    Subtitle

    28 | 37 | {props => { 38 | return ( 39 | 40 |

    Title 1

    41 |
    42 | ); 43 | }} 44 |
    45 |
    46 | ); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hiromi", 3 | "version": "0.4.0", 4 | "description": "React components for Bulma. http://bulma.io/", 5 | "main": "./lib", 6 | "scripts": { 7 | "babel": "babel ./components --out-dir ./lib", 8 | "build": "cross-env NODE_ENV=production npm run babel", 9 | "docs": "webpack-dev-server --hot --inline --history-api-fallback --content-base docs/", 10 | "prepublish": "npm run build", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/SimpleHQ/hiromi.git" 16 | }, 17 | "author": { 18 | "name": "SimpleHQ", 19 | "url": "http://github.com/SimpleHQ" 20 | }, 21 | "contributors": [ 22 | { 23 | "name": "Cameron Stitt", 24 | "email": "cameron.stitt@simplehq.co" 25 | } 26 | ], 27 | "license": "ISC", 28 | "bugs": { 29 | "url": "https://github.com/SimpleHQ/hiromi/issues" 30 | }, 31 | "homepage": "https://github.com/SimpleHQ/hiromi#readme", 32 | "keywords": [ 33 | "react", 34 | "react-component", 35 | "bulma" 36 | ], 37 | "dependencies": { 38 | "classnames": "^2.2.5", 39 | "prop-types": "^15.5.9", 40 | "react": "^15.0.2", 41 | "react-dom": "^15.0.2" 42 | }, 43 | "devDependencies": { 44 | "babel-cli": "^6.8.0", 45 | "babel-core": "^6.8.0", 46 | "babel-loader": "^6.2.4", 47 | "babel-plugin-transform-class-properties": "^6.8.0", 48 | "babel-preset-es2015": "^6.6.0", 49 | "babel-preset-react": "^6.5.0", 50 | "babel-preset-stage-1": "^6.5.0", 51 | "bulma": "0.0.26", 52 | "cross-env": "^1.0.7", 53 | "css-loader": "^0.23.1", 54 | "eslint": "^2.10.1", 55 | "eslint-plugin-react": "^5.1.1", 56 | "extract-text-webpack-plugin": "^1.0.1", 57 | "file-loader": "^0.8.5", 58 | "font-awesome": "^4.6.1", 59 | "html-webpack-plugin": "^2.17.0", 60 | "node-sass": "^3.7.0", 61 | "react-demo": "^1.4.1", 62 | "react-router": "^2.4.0", 63 | "sass-loader": "^3.2.0", 64 | "style-loader": "^0.13.1", 65 | "webpack": "^1.13.0", 66 | "webpack-dev-server": "^1.14.1" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // Used for running docs 2 | 3 | var webpack = require("webpack"); 4 | var path = require("path"); 5 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 6 | 7 | module.exports = { 8 | entry: { 9 | app: "./docs/index.jsx" 10 | }, 11 | output: { 12 | path: path.resolve(__dirname, "docs/build"), 13 | publicPath: "/assets/", 14 | filename: "bundle.js" 15 | }, 16 | devtool: 'source-map', 17 | module: { 18 | loaders: [ 19 | { 20 | test: /\.jsx?$/, 21 | loader: 'babel', 22 | include: [ 23 | path.resolve(__dirname, 'docs'), 24 | path.resolve(__dirname, 'components') 25 | ] 26 | }, 27 | { 28 | test: /\.css$/, 29 | loader: ExtractTextPlugin.extract('style-loader', 'css-loader'), 30 | } 31 | ] 32 | }, 33 | resolve: { 34 | extensions: ['', '.js', '.jsx'] 35 | }, 36 | plugins: [ 37 | new ExtractTextPlugin("[name].css") 38 | ] 39 | }; 40 | --------------------------------------------------------------------------------