diff --git a/docs/components.json b/docs/components.json index 2dd9a770..b80befbd 100644 --- a/docs/components.json +++ b/docs/components.json @@ -900,9 +900,32 @@ "computed": false } }, + "uncheckedStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "Override the styles of the unchecked element", + "defaultValue": { + "value": "{}", + "computed": false + } + }, "value": { "type": { - "name": "string" + "name": "union", + "value": [ + { + "name": "string" + }, + { + "name": "number" + }, + { + "name": "bool" + } + ] }, "required": true, "description": "The checkbox' value" @@ -916,6 +939,118 @@ } } }, + "components/checkbox-group/component.jsx": { + "description": "", + "displayName": "CheckboxGroup", + "methods": [], + "props": { + "values": { + "type": { + "name": "arrayOf", + "value": { + "name": "union", + "value": [ + { + "name": "string" + }, + { + "name": "number" + }, + { + "name": "bool" + } + ] + } + }, + "required": false, + "description": "The CheckboxGroup's values", + "defaultValue": { + "value": "[]", + "computed": false + } + }, + "onChange": { + "type": { + "name": "func" + }, + "required": true, + "description": "Callback fired when Checkbox's value changes\n\nfunction(event: object) => void" + }, + "children": { + "type": { + "name": "node" + }, + "required": true, + "description": "The CheckboxGroup's content (Checkbox), each child must have a value prop" + }, + "label": { + "type": { + "name": "node" + }, + "required": true, + "description": "The CheckboxGroup's label" + }, + "labelStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "Override the styles of the label element", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "style": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "Override the styles of the root element", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "buttonStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "Override the styles of the button container", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "error": { + "type": { + "name": "node" + }, + "required": false, + "description": "Display an error message", + "defaultValue": { + "value": "null", + "computed": false + } + }, + "errorStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "Override the styles of the error element", + "defaultValue": { + "value": "{}", + "computed": false + } + } + } + }, "components/commands/component.jsx": { "description": "Used for displaying a list of commands", "displayName": "Commands", @@ -1637,197 +1772,7 @@ } } }, - "components/emoji-menu/emoji-categories.jsx": { - "description": "", - "methods": [], - "props": { - "changeCategory": { - "type": { - "name": "func" - }, - "required": true, - "description": "" - }, - "category": { - "type": { - "name": "string" - }, - "required": true, - "description": "" - }, - "activeColor": { - "type": { - "name": "string" - }, - "required": true, - "description": "" - }, - "recent": { - "type": { - "name": "bool" - }, - "required": true, - "description": "" - }, - "style": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - }, - "iconStyle": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - }, - "iconColor": { - "type": { - "name": "string" - }, - "required": true, - "description": "" - } - } - }, - "components/emoji-menu/emoji-category.jsx": { - "description": "", - "methods": [], - "props": { - "category": { - "type": { - "name": "string" - }, - "required": true, - "description": "" - }, - "emojis": { - "type": { - "name": "arrayOf", - "value": { - "name": "shape", - "value": { - "shortname": { - "name": "string", - "required": true - } - } - } - }, - "required": true, - "description": "" - }, - "sendEmoji": { - "type": { - "name": "func" - }, - "required": true, - "description": "" - }, - "style": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - }, - "emojiStyle": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - } - } - }, - "components/emoji-menu/emoji-modifiers.jsx": { - "description": "", - "displayName": "EmojiModifiers", - "methods": [], - "props": { - "modifiers": { - "type": { - "name": "arrayOf", - "value": { - "name": "shape", - "value": { - "shortname": { - "name": "string", - "required": true - }, - "title": { - "name": "string", - "required": true - } - } - } - }, - "required": true, - "description": "" - }, - "changeTone": { - "type": { - "name": "func" - }, - "required": true, - "description": "" - }, - "tone": { - "type": { - "name": "string" - }, - "required": true, - "description": "" - }, - "style": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - }, - "modifierStyle": { - "type": { - "name": "instanceOf", - "value": "Object" - }, - "required": false, - "description": "", - "defaultValue": { - "value": "{}", - "computed": false - } - } - } - }, - "components/emoji-menu/index.jsx": { + "components/emoji-menu/component.jsx": { "description": "Menu for sending messages with emoji", "displayName": "EmojiMenu", "methods": [ @@ -2026,7 +1971,197 @@ } } }, - "components/empty-state/index.jsx": { + "components/emoji-menu/emoji-categories.jsx": { + "description": "", + "methods": [], + "props": { + "changeCategory": { + "type": { + "name": "func" + }, + "required": true, + "description": "" + }, + "category": { + "type": { + "name": "string" + }, + "required": true, + "description": "" + }, + "activeColor": { + "type": { + "name": "string" + }, + "required": true, + "description": "" + }, + "recent": { + "type": { + "name": "bool" + }, + "required": true, + "description": "" + }, + "style": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "iconStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "iconColor": { + "type": { + "name": "string" + }, + "required": true, + "description": "" + } + } + }, + "components/emoji-menu/emoji-category.jsx": { + "description": "", + "methods": [], + "props": { + "category": { + "type": { + "name": "string" + }, + "required": true, + "description": "" + }, + "emojis": { + "type": { + "name": "arrayOf", + "value": { + "name": "shape", + "value": { + "shortname": { + "name": "string", + "required": true + } + } + } + }, + "required": true, + "description": "" + }, + "sendEmoji": { + "type": { + "name": "func" + }, + "required": true, + "description": "" + }, + "style": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "emojiStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + } + } + }, + "components/emoji-menu/emoji-modifiers.jsx": { + "description": "", + "displayName": "EmojiModifiers", + "methods": [], + "props": { + "modifiers": { + "type": { + "name": "arrayOf", + "value": { + "name": "shape", + "value": { + "shortname": { + "name": "string", + "required": true + }, + "title": { + "name": "string", + "required": true + } + } + } + }, + "required": true, + "description": "" + }, + "changeTone": { + "type": { + "name": "func" + }, + "required": true, + "description": "" + }, + "tone": { + "type": { + "name": "string" + }, + "required": true, + "description": "" + }, + "style": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + }, + "modifierStyle": { + "type": { + "name": "instanceOf", + "value": "Object" + }, + "required": false, + "description": "", + "defaultValue": { + "value": "{}", + "computed": false + } + } + } + }, + "components/empty-state/component.jsx": { "description": "Pretty placeholder for empty content", "displayName": "EmptyState", "methods": [], @@ -2105,7 +2240,7 @@ } } }, - "components/gallery/index.jsx": { + "components/gallery/component.jsx": { "description": "Justified grid layout for showcasing images.", "displayName": "Gallery", "methods": [ @@ -2225,7 +2360,7 @@ } } }, - "components/icon-menu/index.jsx": { + "components/icon-menu/component.jsx": { "description": "Open a menu from an Icon, give options related to the icon", "displayName": "IconMenu", "methods": [ @@ -3870,7 +4005,7 @@ } } }, - "components/input/index.jsx": { + "components/input/component.jsx": { "description": "General purpose form input", "displayName": "Input", "methods": [ @@ -4078,7 +4213,7 @@ } } }, - "components/lightbox/index.jsx": { + "components/lightbox/component.jsx": { "description": "Lightbox for images", "displayName": "Lightbox", "methods": [ @@ -4169,7 +4304,7 @@ } } }, - "components/list/index.jsx": { + "components/list/component.jsx": { "description": "A wrapper for ListItems", "displayName": "List", "methods": [], @@ -4251,7 +4386,7 @@ } } }, - "components/list-item/index.jsx": { + "components/list-item/component.jsx": { "description": "A list's item", "displayName": "ListItem", "methods": [ @@ -6842,7 +6977,7 @@ "value": { "type": { "name": "custom", - "raw": "propTypes.valueInRange" + "raw": "customPropTypes.valueInRange" }, "required": false, "description": "The slider's value. Must between min and max", @@ -6868,7 +7003,7 @@ "max": { "type": { "name": "custom", - "raw": "propTypes.minMax" + "raw": "customPropTypes.minMax" }, "required": false, "description": "The slider's max value. Cannot be equal to min.", @@ -6880,7 +7015,7 @@ "min": { "type": { "name": "custom", - "raw": "propTypes.minMax" + "raw": "customPropTypes.minMax" }, "required": false, "description": "The slider's min value. Cannot be equal to max.", diff --git a/docs/src/components/checkbox/example.js b/docs/src/components/checkbox/example.js index 3786dd82..f736c8f0 100644 --- a/docs/src/components/checkbox/example.js +++ b/docs/src/components/checkbox/example.js @@ -2,6 +2,7 @@ export default ` \`\`\`jsx import React, { Component } from 'react'; import Checkbox from 'anchor-ui/checkbox'; + import CheckboxGroup from 'anchor-ui/checkbox-group'; import Divider from 'anchor-ui/divider'; import _ from 'lodash'; @@ -30,20 +31,18 @@ export default ` return (
- - + + + +
    { diff --git a/docs/src/components/checkbox/index.jsx b/docs/src/components/checkbox/index.jsx index 3539f8ba..15bf4147 100644 --- a/docs/src/components/checkbox/index.jsx +++ b/docs/src/components/checkbox/index.jsx @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import _ from 'lodash'; import Checkbox from '../../../../dist/checkbox'; +import CheckboxGroup from '../../../../dist/checkbox-group'; import Divider from '../../../../dist/divider'; import Props from '../props'; import components from '../../../components.json'; @@ -31,13 +32,9 @@ class CheckboxDoc extends Component { render() { const { values } = this.state; - const componentData = _.find(components, component => component.displayName === 'Checkbox'); + const checkboxData = _.find(components, component => component.displayName === 'Checkbox'); + const checkboxGroupData = _.find(components, component => component.displayName === 'CheckboxGroup'); const style = { - checkboxWrapper: { - display: 'flex', - flexWrap: 'wrap', - alignItems: 'center' - }, paper: { margin: 0, padding: '20px' @@ -59,30 +56,26 @@ class CheckboxDoc extends Component {

    Checkbox

    Description

    -

    {componentData.description}

    +

    {checkboxData.description}

    Examples

    -
    + -
    +
      { @@ -93,7 +86,10 @@ class CheckboxDoc extends Component {
    - +

    Checkbox

    + +

    CheckboxGroup

    + ); } diff --git a/package.json b/package.json index df248b3f..6efea2f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anchor-ui", - "version": "5.0.6", + "version": "5.1.0", "description": "React Component UI Kit", "main": "dist/index.js", "files": [ @@ -40,10 +40,11 @@ "babel-cli": "^6.26.0", "babel-eslint": "^8.0.1", "babel-plugin-add-module-exports": "^0.2.1", - "babel-preset-es2015": "^6.18.0", + "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.16.0", "babel-preset-stage-0": "^6.16.0", "chai": "^3.5.0", + "chance": "^1.0.13", "codecov": "^3.0.0", "enzyme": "^3.1.0", "enzyme-adapter-react-16": "^1.0.3", @@ -60,13 +61,13 @@ "react-docgen": "^2.19.0", "react-test-renderer": "^15.5.4", "rimraf": "^2.6.2", - "sinon": "^1.17.7", + "sinon": "^4.1.3", "sinon-chai": "^2.9.0" }, "babel": { "presets": [ "react", - "es2015", + "env", "stage-0" ], "plugins": [ @@ -90,6 +91,7 @@ "react-event-listener": "^0.4.5", "react-onclickoutside": "^6.6.3", "recompose": "^0.22.0", + "store": "^2.0.12", "tlds": "^1.182.0" } } diff --git a/src/checkbox-group/component.jsx b/src/checkbox-group/component.jsx new file mode 100644 index 00000000..64a9dbb5 --- /dev/null +++ b/src/checkbox-group/component.jsx @@ -0,0 +1,76 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Radium from 'radium'; +import includes from 'lodash/includes'; +import getStyles from './get-styles'; + +const propTypes = { + /** The CheckboxGroup's values */ + values: PropTypes.arrayOf(PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.bool + ])), + /** + * Callback fired when Checkbox's value changes + * + * function(event: object) => void + */ + onChange: PropTypes.func.isRequired, + /** The CheckboxGroup's content (Checkbox), each child must have a value prop */ + children: PropTypes.node.isRequired, + /** The CheckboxGroup's label */ + label: PropTypes.node.isRequired, + /** Override the styles of the label element */ + labelStyle: PropTypes.instanceOf(Object), + /** Override the styles of the root element */ + style: PropTypes.instanceOf(Object), + /** Override the styles of the button container */ + buttonStyle: PropTypes.instanceOf(Object), + /** Display an error message */ + error: PropTypes.node, + /** Override the styles of the error element */ + errorStyle: PropTypes.instanceOf(Object) +}; + +const defaultProps = { + values: [], + labelStyle: {}, + style: {}, + error: null, + errorStyle: {}, + buttonStyle: {} +}; + +const displayName = 'CheckboxGroup'; + +const CheckboxGroup = ({ + values, onChange, children, buttonStyle, label, labelStyle, style, error, errorStyle, ...custom +}) => { + const childrenWithProps = React.Children.map( + children, + child => React.cloneElement( + child, + { + checked: includes(values, child.props.value), + onChange + } + ) + ); + + return ( +
    + {label} +
    + {childrenWithProps} +
    + {error ? {error} : null} +
    + ); +}; + +CheckboxGroup.propTypes = propTypes; +CheckboxGroup.defaultProps = defaultProps; +CheckboxGroup.displayName = displayName; + +export default Radium(CheckboxGroup); diff --git a/src/checkbox-group/get-styles.js b/src/checkbox-group/get-styles.js new file mode 100644 index 00000000..10cd077e --- /dev/null +++ b/src/checkbox-group/get-styles.js @@ -0,0 +1,12 @@ +import styles from './styles'; +import combineStyles from '../internal/combine-styles'; + +const buttons = overrideStyle => combineStyles(styles.buttons, overrideStyle); +const label = overrideStyle => combineStyles(styles.label, overrideStyle); +const error = overrideStyle => combineStyles(styles.error, overrideStyle); + +export default { + buttons, + label, + error +}; diff --git a/src/checkbox-group/index.js b/src/checkbox-group/index.js new file mode 100644 index 00000000..787141c9 --- /dev/null +++ b/src/checkbox-group/index.js @@ -0,0 +1,4 @@ +import Radium from 'radium'; +import CheckboxGroup from './component'; + +export default Radium(CheckboxGroup); diff --git a/src/checkbox-group/styles.js b/src/checkbox-group/styles.js new file mode 100644 index 00000000..1d0a3bf6 --- /dev/null +++ b/src/checkbox-group/styles.js @@ -0,0 +1,21 @@ +import colors from '../settings/colors'; + +export default { + buttons: { + display: 'flex', + flexWrap: 'wrap' + }, + label: { + fontSize: '16px', + color: colors.secondaryText, + fontWeight: 'bolder', + padding: '0 0 8px 8px', + display: 'inline-block' + }, + error: { + display: 'block', + paddingLeft: '10px', + color: colors.error, + fontSize: '14px' + } +}; diff --git a/src/checkbox/component.jsx b/src/checkbox/component.jsx index 5bede978..2d95390e 100644 --- a/src/checkbox/component.jsx +++ b/src/checkbox/component.jsx @@ -2,37 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import getStyles from './get-styles'; import IconCheckbox from '../icons/icon-checkbox'; -import styles from './styles'; -/** A checkbox is used to verify which options you want selected from a group. */ -const Checkbox = ({ - onChange, label, checked, name, style, inputStyle, iconStyle, labelStyle, value, color, ...custom -}) => ( -