diff --git a/demo/Demo.react.js b/demo/Demo.react.js
index d34e24c05..385c733ec 100644
--- a/demo/Demo.react.js
+++ b/demo/Demo.react.js
@@ -268,7 +268,6 @@ const ChecklistExample = `
const properties = {
id: 'my checklist',
labelStyle: {'display': 'block'},
- disabled: false,
options: [
{'label': 'Melons', 'value': 'melons', 'disabled': false},
{'label': 'Apples', 'value': 'apples'},
@@ -299,6 +298,54 @@ class Controller extends Component {
ReactDOM.render(, mountNode);`
+const ChecklistContainerExample = `
+const applesDescription = (
+

+
This option selects the best and most fancy apples in the world
+
);
+
+const orangesDescription = (There is no oranges available. Please come back in oranges season.
);
+
+const properties = {
+ id: 'my container checklist',
+ labelStyle: {'display': 'block'},
+ options: [
+ {'label': 'Melons', 'value': 'melons', 'disabled': false},
+ {'label': 'Apples', 'value': 'apples',
+ 'children': applesDescription,
+ 'collapseChildrenButton': true,
+ 'initiallyExpanded': false
+ },
+ {'label': 'Oranges', 'value': 'oranges', 'disabled': true,
+ 'children': orangesDescription,
+ 'collapseChildrenButton': true,
+ 'initiallyExpanded': true}
+ ]
+};
+
+class Controller extends Component {
+ constructor() {
+ super();
+ this.state = {
+ values: ['melons', 'apples']
+ };
+ }
+
+ render() {
+ return ( {
+ this.setState(props);
+ }}
+ fireEvent={event => console.warn(event)}
+ values={this.state.values}
+ {...properties}
+ />);
+ }
+}
+
+ReactDOM.render(, mountNode);`
+
+
const examples = [
{name: 'Upload', code: UploadExample},
@@ -308,6 +355,7 @@ const examples = [
{name: 'SyntaxHighlighter', code: SyntaxHighlighterExample},
{name: 'Radio', code: RadioExample},
{name: 'Checklist', code: ChecklistExample},
+ {name: 'Checklist with containers options', code: ChecklistContainerExample},
{name: 'Dropdown', code: DropdownExample},
{name: 'Slider', code: SliderExample},
{name: 'RangeSlider', code: RangeSliderExample},
diff --git a/src/components/Checklist.react.js b/src/components/Checklist.react.js
index 1c921ac4b..246f06b1d 100644
--- a/src/components/Checklist.react.js
+++ b/src/components/Checklist.react.js
@@ -1,6 +1,135 @@
-import {append, contains, without} from 'ramda';
+import {append, contains, without} from 'ramda';
import React, {Component, PropTypes} from 'react';
+class Checkbox extends Component {
+
+ constructor(props) {
+ super(props);
+
+ if (props.collapsable) {
+ this.state = {
+ collapsed: props.initiallyExpanded
+ };
+ this.handleCollapseClick = this.handleCollapseClick.bind(this);
+ }
+ }
+
+ handleCollapseClick() {
+ this.setState({ collapsed: !this.state.collapsed });
+ }
+
+ render() {
+
+ const {
+ children,
+ collapsable,
+ disabled,
+ inputClassName,
+ inputStyle,
+ isChecked,
+ label,
+ labelClassName,
+ labelStyle,
+ value
+ } = this.props;
+
+
+ let arrow;
+ let CollapsableChildren;
+
+ if (collapsable) {
+ const collapsed = this.state.collapsed;
+ arrow = (
+
+ {collapsed? '▾' : '▴'}
+
+ );
+
+ CollapsableChildren = (
+
+ {collapsed ? null : children}
+
+ );
+ }
+
+ return (
+
+
+
+ {collapsable? arrow : null}
+
+
+ {collapsable? CollapsableChildren : children}
+
+ );
+ }
+}
+
+Checkbox.propTypes = {
+ /**
+ * The checkbox's label
+ */
+ label: PropTypes.string,
+
+ /**
+ * The value of the checkbox. This value
+ * corresponds to the items specified in the
+ * `values` property.
+ */
+ value: PropTypes.string,
+
+ /**
+ * If true, this checkbox is disabled and can't be clicked on.
+ */
+ disabled: PropTypes.bool,
+
+
+ /**
+ * Optinal wrapped components within this option
+ */
+ children: PropTypes.node,
+
+ /**
+ * Show a button to show/hide children components of this option
+ */
+ collapsable: PropTypes.bool,
+
+ /**
+ * Change default for the initiallyExpanded to be initially collapsed (hidden)
+ */
+ initiallyExpanded: PropTypes.bool,
+
+ /**
+ * Mark if the input is checked or not
+ */
+ checked: PropTypes.bool,
+
+ /**
+ * Callback to the parent to add or remove this option from the Checklist
+ */
+ handleOnChange: PropTypes.func
+}
+
+Checkbox.defaultProps = {
+ initiallyExpanded: true
+}
+
/**
* Checklist is a component that encapsulates several checkboxes.
* The values and labels of the checklist is specified in the `options`
@@ -11,56 +140,56 @@ export default class Checklist extends Component {
constructor(props) {
super(props);
this.state = {values: props.values};
+
+ this.handleOnChange = this.handleOnChange.bind(this);
}
componentWillReceiveProps(newProps) {
this.setState({values: newProps.values});
}
+ handleOnChange(value) {
+ const values = this.state.values;
+ let newValues;
+ if (contains(value, values)) {
+ newValues = without([value], values);
+ } else {
+ newValues = append(value, values);
+ }
+ this.setState({values: newValues});
+
+ const {fireEvent, setProps} = this.props;
+ if (setProps) setProps({values: newValues});
+ if (fireEvent) fireEvent({event: 'change'});
+ }
+
render() {
const {
className,
- fireEvent,
id,
- inputClassName,
- inputStyle,
- labelClassName,
- labelStyle,
options,
- setProps,
- style
+ style,
+ values,
+ ...rest
} = this.props;
- const {values} = this.state;
return (
{options.map(option => (
-
- ))}
+
+ )
+ )}
);
}
@@ -72,24 +201,42 @@ Checklist.propTypes = {
/**
* An array of options
*/
- options: PropTypes.shape({
- /**
- * The checkbox's label
- */
- label: PropTypes.string,
-
- /**
- * The value of the checkbox. This value
- * corresponds to the items specified in the
- * `values` property.
- */
- value: PropTypes.string,
-
- /**
- * If true, this checkbox is disabled and can't be clicked on.
- */
- disabled: PropTypes.bool
- }),
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ /**
+ * The checkbox's label
+ */
+ label: PropTypes.string,
+
+ /**
+ * The value of the checkbox. This value
+ * corresponds to the items specified in the
+ * `values` property.
+ */
+ value: PropTypes.string,
+
+ /**
+ * If true, this checkbox is disabled and can't be clicked on.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * Optinal wrapped components within this option
+ */
+ children: PropTypes.node,
+
+ /**
+ * Show a button to show/hide children components of this option
+ */
+ collapseChildrenButton: PropTypes.bool,
+
+ /**
+ * Change default for the collapseChildrenButton to be initially hidden
+ */
+ initiallyExpanded: PropTypes.bool
+
+ })
+ ),
/**
* The currently selected value
diff --git a/src/components/__tests__/Checklist.test.js b/src/components/__tests__/Checklist.test.js
new file mode 100644
index 000000000..fcbc7c57f
--- /dev/null
+++ b/src/components/__tests__/Checklist.test.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import CheckListComponent from '../Checklist.react';
+
+describe('Checklist component', () => {
+
+ it('renders', () => {
+ const component = shallow();
+ expect(component).to.be.ok;
+ });
+
+ describe('options', () => {
+ it('renders passed-in options');
+ });
+});