Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-checkbox-tree

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-checkbox-tree - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0-rc.0

.editorconfig

79

gulpfile.js

@@ -1,44 +0,45 @@

var gulp = require('gulp');
var eslint = require('gulp-eslint');
var mocha = require('gulp-mocha-phantomjs');
var header = require('gulp-header');
var webpack = require('webpack-stream');
var scsslint = require('gulp-scss-lint');
var sass = require('gulp-sass');
var pkg = require('./package.json');
const gulp = require('gulp');
const eslint = require('gulp-eslint');
const mocha = require('gulp-mocha-phantomjs');
const header = require('gulp-header');
const webpack = require('webpack-stream');
const scsslint = require('gulp-scss-lint');
const sass = require('gulp-sass');
const pkg = require('./package.json');
var banner = '/*! <%= pkg.name %> - v<%= pkg.version %> | <%= new Date().getFullYear() %> */\n';
const webpackConfig = require('./webpack.config');
const testWebpackConfig = require('./webpack.test.config');
gulp.task('test-script-format', function () {
return gulp.src(['./src/js/**/*.js'])
const banner = '/*! <%= pkg.name %> - v<%= pkg.version %> | <%= new Date().getFullYear() %> */\n';
gulp.task('test-script-format', () =>
gulp.src(['./src/js/**/*.js'])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failOnError());
});
.pipe(eslint.failOnError())
);
gulp.task('compile-test-script', function () {
return gulp.src(['./test/index.js'])
gulp.task('compile-test-script', () =>
gulp.src(['./test/index.js'])
.pipe(webpack(require('./webpack.config.js')))
.pipe(gulp.dest('./test/compiled/'));
});
.pipe(gulp.dest('./test/compiled/'))
);
// Disabled for now
gulp.task('test-mocha', ['script-compile-test'], function () {
return gulp.src(['test/test.html'])
.pipe(mocha({ reporter: 'spec' }));
});
gulp.task('test-mocha', ['script-compile-test'], () =>
gulp.src(['test/test.html'])
.pipe(mocha({ reporter: 'spec' }))
);
gulp.task('test-script', ['test-script-format']);
gulp.task('build-script', ['test-script'], function () {
return gulp.src(['./src/index.js'])
.pipe(webpack(require('./webpack.config.js')))
.pipe(header(banner, {
pkg: pkg,
}))
.pipe(gulp.dest('./lib/'));
});
gulp.task('build-script', ['test-script'], () =>
gulp.src(['./src/index.js'])
.pipe(webpack(webpackConfig))
.pipe(header(banner, { pkg }))
.pipe(gulp.dest('./lib/'))
);
gulp.task('build-style', function () {
return gulp.src('./src/sass/**/*.scss')
gulp.task('build-style', () =>
gulp.src('./src/sass/**/*.scss')
.pipe(scsslint())

@@ -49,12 +50,12 @@ .pipe(scsslint.failReporter())

}).on('error', sass.logError))
.pipe(gulp.dest('./lib'));
});
.pipe(gulp.dest('./lib'))
);
gulp.task('build-examples', ['build-script', 'build-style'], function () {
return gulp.src(['./examples/index.js'])
.pipe(webpack(require('./webpack.test.config.js')))
.pipe(gulp.dest('./examples/compiled/'));
});
gulp.task('build-examples', ['build-script', 'build-style'], () =>
gulp.src(['./examples/index.js'])
.pipe(webpack(testWebpackConfig))
.pipe(gulp.dest('./examples/compiled/'))
);
gulp.task('watch', function () {
gulp.task('watch', () => {
gulp.watch(['./src/js/**/*.js'], ['build-script']);

@@ -61,0 +62,0 @@ gulp.watch(['./src/sass/**/*.scss'], ['build-style']);

@@ -1,2 +0,2 @@

/*! react-checkbox-tree - v0.2.0 | 2016 */
/*! react-checkbox-tree - v0.3.0-rc.0 | 2016 */
(function webpackUniversalModuleDefinition(root, factory) {

@@ -77,3 +77,3 @@ if(typeof exports === 'object' && typeof module === 'object')

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

@@ -104,10 +104,6 @@ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Tree).call(this, props));
var _this = _possibleConstructorReturn(this, (Tree.__proto__ || Object.getPrototypeOf(Tree)).call(this, props));
_this.state = {
checked: props.checked,
expanded: props.expanded
};
_this.handleCheck = _this.handleCheck.bind(_this);
_this.onCheck = _this.onCheck.bind(_this);
_this.onExpand = _this.onExpand.bind(_this);
return _this;

@@ -117,2 +113,30 @@ }

_createClass(Tree, [{
key: 'onCheck',
value: function onCheck(node) {
var checked = this.props.checked;
var isChecked = node.checked;
this.setCheckState(checked, node, isChecked);
this.props.onCheck(checked);
}
}, {
key: 'onExpand',
value: function onExpand(node) {
var isExpanded = node.expanded;
var expanded = this.props.expanded;
var nodeIndex = expanded.indexOf(node.value);
if (!isExpanded && nodeIndex > -1) {
// Node is now collapsed, remove from expanded list
expanded.splice(nodeIndex, 1);
} else if (isExpanded && nodeIndex === -1) {
// Add node to expanded list
expanded.push(node.value);
}
this.props.onExpand(expanded);
}
}, {
key: 'getFormattedNodes',

@@ -122,7 +146,12 @@ value: function getFormattedNodes(nodes) {

var _props = this.props;
var checked = _props.checked;
var expanded = _props.expanded;
return nodes.map(function (node) {
var formatted = Object.create(node);
formatted.checked = _this2.state.checked.indexOf(node.value) > -1;
formatted.collapsed = _this2.state.expanded.indexOf(node.value) === -1;
formatted.checked = checked.indexOf(node.value) > -1;
formatted.expanded = expanded.indexOf(node.value) > -1;

@@ -137,34 +166,2 @@ if (_this2.hasChildren(node)) {

}, {
key: 'getTreeNodes',
value: function getTreeNodes(nodes) {
var _this3 = this;
var treeNodes = nodes.map(function (node, index) {
var checked = _this3.getCheckState(node);
var children = _this3.getChildNodes(node);
return _react2.default.createElement(
_TreeNode2.default,
{
key: index,
name: _this3.props.name,
nameAsArray: _this3.props.nameAsArray,
value: node.value,
title: node.title,
checked: checked,
collapsed: node.collapsed,
rawChildren: node.children,
onCheck: _this3.handleCheck
},
children
);
});
return _react2.default.createElement(
'ol',
null,
treeNodes
);
}
}, {
key: 'getCheckState',

@@ -187,25 +184,5 @@ value: function getCheckState(node) {

}, {
key: 'getChildNodes',
value: function getChildNodes(node) {
if (this.hasChildren(node)) {
return this.getTreeNodes(node.children);
}
return null;
}
}, {
key: 'getHiddenInput',
value: function getHiddenInput() {
if (this.props.name === undefined || this.props.nameAsArray) {
return null;
}
var checked = this.state.checked.join(',');
return _react2.default.createElement('input', { name: this.props.name, value: checked, type: 'hidden' });
}
}, {
key: 'setCheckState',
value: function setCheckState(node, isChecked) {
var _this4 = this;
value: function setCheckState(checked, node, isChecked) {
var _this3 = this;

@@ -215,14 +192,14 @@ if (this.hasChildren(node)) {

node.children.forEach(function (child) {
_this4.setCheckState(child, isChecked);
_this3.setCheckState(checked, child, isChecked);
});
} else {
// Set leaf to check/unchecked state
var index = this.state.checked.indexOf(node.value);
var index = checked.indexOf(node.value);
if (index > -1) {
this.state.checked.splice(index, 1);
checked.splice(index, 1);
}
if (isChecked) {
this.state.checked.push(node.value);
checked.push(node.value);
}

@@ -234,7 +211,7 @@ }

value: function isEveryChildChecked(node) {
var _this5 = this;
var _this4 = this;
return node.children.every(function (child) {
if (_this5.hasChildren(child)) {
return _this5.isEveryChildChecked(child);
if (_this4.hasChildren(child)) {
return _this4.isEveryChildChecked(child);
}

@@ -248,7 +225,7 @@

value: function isSomeChildChecked(node) {
var _this6 = this;
var _this5 = this;
return node.children.some(function (child) {
if (_this6.hasChildren(child)) {
return _this6.isSomeChildChecked(child);
if (_this5.hasChildren(child)) {
return _this5.isSomeChildChecked(child);
}

@@ -269,17 +246,77 @@

}, {
key: 'handleCheck',
value: function handleCheck(node) {
var isChecked = node.checked;
key: 'renderTreeNodes',
value: function renderTreeNodes(nodes) {
var _this6 = this;
this.setCheckState(node, isChecked);
var treeNodes = nodes.map(function (node, index) {
var checked = _this6.getCheckState(node);
var children = _this6.renderChildNodes(node);
this.setState({
checked: this.state.checked
return _react2.default.createElement(
_TreeNode2.default,
{
key: index,
value: node.value,
title: node.title,
checked: checked,
expanded: node.expanded,
rawChildren: node.children,
onCheck: _this6.onCheck,
onExpand: _this6.onExpand
},
children
);
});
return _react2.default.createElement(
'ol',
null,
treeNodes
);
}
}, {
key: 'renderChildNodes',
value: function renderChildNodes(node) {
if (this.hasChildren(node)) {
return this.renderTreeNodes(node.children);
}
return null;
}
}, {
key: 'renderHiddenInput',
value: function renderHiddenInput() {
if (this.props.name === undefined) {
return null;
}
if (this.props.nameAsArray) {
return this.renderArrayHiddenInput();
}
return this.renderJoinedHiddenInput();
}
}, {
key: 'renderArrayHiddenInput',
value: function renderArrayHiddenInput() {
var _this7 = this;
return this.props.checked.map(function (value, index) {
var name = _this7.props.name + '[]';
return _react2.default.createElement('input', { key: index, name: name, type: 'hidden', value: value });
});
}
}, {
key: 'renderJoinedHiddenInput',
value: function renderJoinedHiddenInput() {
var checked = this.props.checked.join(',');
return _react2.default.createElement('input', { name: this.props.name, value: checked, type: 'hidden' });
}
}, {
key: 'render',
value: function render() {
var nodes = this.getFormattedNodes(this.props.nodes);
var treeNodes = this.getTreeNodes(nodes);
var treeNodes = this.renderTreeNodes(nodes);

@@ -289,3 +326,3 @@ return _react2.default.createElement(

{ className: 'react-checkbox-tree' },
this.getHiddenInput(),
this.renderHiddenInput(),
treeNodes

@@ -304,8 +341,6 @@ );

checked: _react2.default.PropTypes.array,
expanded: _react2.default.PropTypes.array
expanded: _react2.default.PropTypes.array,
onCheck: _react2.default.PropTypes.func,
onExpand: _react2.default.PropTypes.func
};
Tree.defaultProps = {
checked: [],
expanded: []
};
exports.default = Tree;

@@ -349,10 +384,6 @@

var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(TreeNode).call(this, props));
var _this = _possibleConstructorReturn(this, (TreeNode.__proto__ || Object.getPrototypeOf(TreeNode)).call(this, props));
_this.state = {
collapsed: props.collapsed
};
_this.handleCollapseClick = _this.handleCollapseClick.bind(_this);
_this.handleCheckboxClick = _this.handleCheckboxClick.bind(_this);
_this.onCheck = _this.onCheck.bind(_this);
_this.onExpand = _this.onExpand.bind(_this);
return _this;

@@ -362,4 +393,28 @@ }

_createClass(TreeNode, [{
key: "getCollapseIcon",
value: function getCollapseIcon() {
key: "onCheck",
value: function onCheck() {
var isChecked = 0;
// Toggle off/partial check state to checked
if (this.props.checked === 0 || this.props.checked === 2) {
isChecked = 1;
}
this.props.onCheck({
value: this.props.value,
checked: isChecked,
children: this.props.rawChildren
});
}
}, {
key: "onExpand",
value: function onExpand() {
this.props.onExpand({
value: this.props.value,
expanded: !this.props.expanded
});
}
}, {
key: "renderCollapseIcon",
value: function renderCollapseIcon() {
if (this.props.children === null) {

@@ -369,3 +424,3 @@ return _react2.default.createElement("i", { className: "fa" });

if (this.state.collapsed) {
if (!this.props.expanded) {
return _react2.default.createElement("i", { className: "fa fa-chevron-right" });

@@ -377,4 +432,4 @@ }

}, {
key: "getCheckboxIcon",
value: function getCheckboxIcon() {
key: "renderCheckboxIcon",
value: function renderCheckboxIcon() {
if (this.props.checked === 0) {

@@ -391,6 +446,6 @@ return _react2.default.createElement("i", { className: "fa fa-square-o" });

}, {
key: "getNodeIcon",
value: function getNodeIcon() {
key: "renderNodeIcon",
value: function renderNodeIcon() {
if (this.props.children !== null) {
if (this.state.collapsed) {
if (!this.props.expanded) {
return _react2.default.createElement("i", { className: "fa fa-folder-o" });

@@ -405,49 +460,11 @@ }

}, {
key: "getHiddenInput",
value: function getHiddenInput() {
if (this.props.name === undefined || !this.props.nameAsArray) {
key: "renderChildren",
value: function renderChildren() {
if (!this.props.expanded) {
return null;
}
var name = this.props.name + "[]";
if (this.props.checked === 1) {
return _react2.default.createElement("input", { name: name, value: this.props.value, type: "hidden" });
}
return null;
}
}, {
key: "getChildren",
value: function getChildren() {
if (this.state.collapsed) {
return null;
}
return this.props.children;
}
}, {
key: "handleCollapseClick",
value: function handleCollapseClick() {
this.setState({
collapsed: !this.state.collapsed
});
}
}, {
key: "handleCheckboxClick",
value: function handleCheckboxClick() {
var isChecked = 0;
// Toggle off/partial check state to checked
if (this.props.checked === 0 || this.props.checked === 2) {
isChecked = 1;
}
this.props.onCheck({
value: this.props.value,
checked: isChecked,
children: this.props.rawChildren
});
}
}, {
key: "render",

@@ -463,12 +480,12 @@ value: function render() {

"span",
{ className: "rct-collapse", onClick: this.handleCollapseClick, title: "toggle" },
this.getCollapseIcon()
{ className: "rct-collapse", onClick: this.onExpand, title: "Toggle" },
this.renderCollapseIcon()
),
_react2.default.createElement(
"label",
{ onClick: this.handleCheckboxClick },
{ onClick: this.onCheck },
_react2.default.createElement(
"span",
{ className: "rct-checkbox" },
this.getCheckboxIcon()
this.renderCheckboxIcon()
),

@@ -478,3 +495,3 @@ _react2.default.createElement(

{ className: "rct-icon" },
this.getNodeIcon()
this.renderNodeIcon()
),

@@ -485,7 +502,6 @@ _react2.default.createElement(

this.props.title
),
this.getHiddenInput()
)
)
),
this.getChildren()
this.renderChildren()
);

@@ -499,11 +515,10 @@ }

TreeNode.propTypes = {
name: _react2.default.PropTypes.string,
nameAsArray: _react2.default.PropTypes.bool,
value: _react2.default.PropTypes.string,
title: _react2.default.PropTypes.string,
children: _react2.default.PropTypes.node,
checked: _react2.default.PropTypes.number,
collapsed: _react2.default.PropTypes.bool,
expanded: _react2.default.PropTypes.bool,
rawChildren: _react2.default.PropTypes.any,
onCheck: _react2.default.PropTypes.func
onCheck: _react2.default.PropTypes.func,
onExpand: _react2.default.PropTypes.func,
title: _react2.default.PropTypes.string,
value: _react2.default.PropTypes.string
};

@@ -510,0 +525,0 @@ exports.default = TreeNode;

{
"name": "react-checkbox-tree",
"version": "0.2.0",
"version": "0.3.0-rc.0",
"description": "React component for checkbox trees.",
"author": "Jake Zatecky",
"license": "MIT",
"keywords": [
"react",
"checkbox",
"tree"
],
"repository": {

@@ -17,29 +22,30 @@ "type": "git",

"peerDependencies": {
"react": "^15.0.0"
"react": "^15.3.0"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-eslint": "^6.0.3",
"babel-loader": "^6.2.2",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
"babel-core": "^6.13.2",
"babel-eslint": "^7.0.0",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.13.2",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-0": "^6.5.0",
"chai": "^3.5.0",
"eslint": "^2.2.0",
"eslint-config-airbnb": "^7.0.0",
"eslint-plugin-react": "^5.0.1",
"eslint-plugin-jsx-a11y": "^0.6.2",
"gulp": "^3.9.0",
"gulp-eslint": "^2.0.0",
"gulp-header": "^1.7.1",
"eslint": "^3.2.2",
"eslint-config-airbnb": "^12.0.0",
"eslint-plugin-import": "^1.13.0",
"eslint-plugin-jsx-a11y": "^2.1.0",
"eslint-plugin-react": "^6.0.0",
"gulp": "^3.9.1",
"gulp-eslint": "^3.0.1",
"gulp-header": "^1.8.8",
"gulp-mocha-phantomjs": "^0.11.0",
"gulp-sass": "^2.1.1",
"gulp-scss-lint": "^0.3.9",
"gulp-sass": "^2.3.2",
"gulp-scss-lint": "^0.4.0",
"http-server": "^0.9.0",
"mocha": "^2.4.5",
"react": "^15.0.0",
"react-dom": "^15.0.1",
"webpack": "^1.12.12",
"webpack-stream": "^3.1.0"
"mocha": "^3.0.2",
"react": "^15.3.0",
"react-dom": "^15.3.0",
"webpack": "^1.13.1",
"webpack-stream": "^3.2.0"
}
}

@@ -8,34 +8,82 @@ # react-checkbox-tree

Checkbox treeview for React.
> Checkbox treeview for React.
# Usage
![Demo](demo.gif)
Install the library:
``` shell
## Installation
The easiest way to use react-checkbox-tree is to install from NPM and include it in your own React build process (e.g. using [Webpack](http://webpack.github.io/docs/what-is-webpack.html)):
```
npm install react-checkbox-tree --save
```
Then render the component:
## Usage
A quick usage example is included below. Note that the react-checkbox-tree component is [controlled](https://facebook.github.io/react/docs/forms.html#controlled-components). In other words, it is stateless. You must update its `checked` and `expanded` properties whenever a change occurs.
``` javascript
import CheckboxTree from 'react-checkbox-tree';
...
const nodes = [{
value: 'node-1',
title: 'Parent Node 1',
children: [{
value: 'node-1-1',
title: 'Leaf Node 1-1',
}, {
value: 'node-1-2',
title: 'Leaf Node 1-2'
}],
}];
render() {
const nodes = [{
value: 'node-1',
title: 'Parent Node 1',
children: [{
value: 'node-1-1',
title: 'Leaf Node 1-1',
}, {
value: 'node-1-2',
title: 'Leaf Node 1-2'
}],
}];
class Widget extends React.Component {
constructor() {
super();
return <CheckboxTree node={nodes} />;
this.state = {
checked: [],
expanded: [],
};
this.onCheck = this.onCheck.bind(this);
this.onExpand = this.onExpand.bind(this);
}
onCheck(checked) {
this.setState({ checked });
}
onExpand(expanded) {
this.setState({ expanded });
}
render() {
const { checked, expanded } = this.state;
return (
<Tree
name="tree_nodes"
nodes={nodes}
checked={checked}
expanded={expanded}
onCheck={this.onCheck}
onExpand={this.onExpand}
/>
);
}
}
```
### Properties
| Property | Type | Description |
| ------------- | -------- | --------------------------------------------------------------------------------------------- |
| `nodes` | array | **Required**. Specifies the tree nodes and their children. |
| `checked` | array | **Required**. An array of checked node values. |
| `expanded` | array | **Required**. An array of expanded node values. |
| `onCheck` | function | onCheck handler: `function(checked) {}` |
| `onExpand` | function | onExpand handler: `function(expanded) {}` |
| `name` | string | Optional name for the hidden `<input>` element. |
| `nameAsArray` | bool | If true, the hidden `<input>` will encode its values as an array rather than a joined string. |

@@ -6,2 +6,2 @@ // Use CommonJS export to trick Webpack into working around the issues that

module.exports = require('./js/Tree.js').default;
module.exports = require('./js/Tree').default;
import React from 'react';
import TreeNode from './TreeNode.js';
import TreeNode from './TreeNode';

@@ -12,26 +12,46 @@ class Tree extends React.Component {

expanded: React.PropTypes.array,
onCheck: React.PropTypes.func,
onExpand: React.PropTypes.func,
};
static defaultProps = {
checked: [],
expanded: [],
};
constructor(props) {
super(props);
this.state = {
checked: props.checked,
expanded: props.expanded,
};
this.onCheck = this.onCheck.bind(this);
this.onExpand = this.onExpand.bind(this);
}
this.handleCheck = this.handleCheck.bind(this);
onCheck(node) {
const { checked } = this.props;
const isChecked = node.checked;
this.setCheckState(checked, node, isChecked);
this.props.onCheck(checked);
}
onExpand(node) {
const isExpanded = node.expanded;
const expanded = this.props.expanded;
const nodeIndex = expanded.indexOf(node.value);
if (!isExpanded && nodeIndex > -1) {
// Node is now collapsed, remove from expanded list
expanded.splice(nodeIndex, 1);
} else if (isExpanded && nodeIndex === -1) {
// Add node to expanded list
expanded.push(node.value);
}
this.props.onExpand(expanded);
}
getFormattedNodes(nodes) {
const { checked, expanded } = this.props;
return nodes.map((node) => {
const formatted = Object.create(node);
formatted.checked = this.state.checked.indexOf(node.value) > -1;
formatted.collapsed = this.state.expanded.indexOf(node.value) === -1;
formatted.checked = checked.indexOf(node.value) > -1;
formatted.expanded = expanded.indexOf(node.value) > -1;

@@ -46,31 +66,2 @@ if (this.hasChildren(node)) {

getTreeNodes(nodes) {
const treeNodes = nodes.map((node, index) => {
const checked = this.getCheckState(node);
const children = this.getChildNodes(node);
return (
<TreeNode
key={index}
name={this.props.name}
nameAsArray={this.props.nameAsArray}
value={node.value}
title={node.title}
checked={checked}
collapsed={node.collapsed}
rawChildren={node.children}
onCheck={this.handleCheck}
>
{children}
</TreeNode>
);
});
return (
<ol>
{treeNodes}
</ol>
);
}
getCheckState(node) {

@@ -92,36 +83,18 @@ if (this.hasChildren(node) === false) {

getChildNodes(node) {
setCheckState(checked, node, isChecked) {
if (this.hasChildren(node)) {
return this.getTreeNodes(node.children);
}
return null;
}
getHiddenInput() {
if (this.props.name === undefined || this.props.nameAsArray) {
return null;
}
const checked = this.state.checked.join(',');
return <input name={this.props.name} value={checked} type="hidden" />;
}
setCheckState(node, isChecked) {
if (this.hasChildren(node)) {
// Percolate check status down to all children
node.children.forEach((child) => {
this.setCheckState(child, isChecked);
this.setCheckState(checked, child, isChecked);
});
} else {
// Set leaf to check/unchecked state
const index = this.state.checked.indexOf(node.value);
const index = checked.indexOf(node.value);
if (index > -1) {
this.state.checked.splice(index, 1);
checked.splice(index, 1);
}
if (isChecked) {
this.state.checked.push(node.value);
checked.push(node.value);
}

@@ -159,19 +132,71 @@ }

handleCheck(node) {
const isChecked = node.checked;
renderTreeNodes(nodes) {
const treeNodes = nodes.map((node, index) => {
const checked = this.getCheckState(node);
const children = this.renderChildNodes(node);
this.setCheckState(node, isChecked);
return (
<TreeNode
key={index}
value={node.value}
title={node.title}
checked={checked}
expanded={node.expanded}
rawChildren={node.children}
onCheck={this.onCheck}
onExpand={this.onExpand}
>
{children}
</TreeNode>
);
});
this.setState({
checked: this.state.checked,
return (
<ol>
{treeNodes}
</ol>
);
}
renderChildNodes(node) {
if (this.hasChildren(node)) {
return this.renderTreeNodes(node.children);
}
return null;
}
renderHiddenInput() {
if (this.props.name === undefined) {
return null;
}
if (this.props.nameAsArray) {
return this.renderArrayHiddenInput();
}
return this.renderJoinedHiddenInput();
}
renderArrayHiddenInput() {
return this.props.checked.map((value, index) => {
const name = `${this.props.name}[]`;
return <input key={index} name={name} type="hidden" value={value} />;
});
}
renderJoinedHiddenInput() {
const checked = this.props.checked.join(',');
return <input name={this.props.name} value={checked} type="hidden" />;
}
render() {
const nodes = this.getFormattedNodes(this.props.nodes);
const treeNodes = this.getTreeNodes(nodes);
const treeNodes = this.renderTreeNodes(nodes);
return (
<div className="react-checkbox-tree">
{this.getHiddenInput()}
{this.renderHiddenInput()}
{treeNodes}

@@ -178,0 +203,0 @@ </div>

@@ -5,11 +5,10 @@ import React from 'react';

static propTypes = {
name: React.PropTypes.string,
nameAsArray: React.PropTypes.bool,
value: React.PropTypes.string,
title: React.PropTypes.string,
children: React.PropTypes.node,
checked: React.PropTypes.number,
collapsed: React.PropTypes.bool,
expanded: React.PropTypes.bool,
rawChildren: React.PropTypes.any,
onCheck: React.PropTypes.func,
onExpand: React.PropTypes.func,
title: React.PropTypes.string,
value: React.PropTypes.string,
};

@@ -20,11 +19,29 @@

this.state = {
collapsed: props.collapsed,
};
this.onCheck = this.onCheck.bind(this);
this.onExpand = this.onExpand.bind(this);
}
this.handleCollapseClick = this.handleCollapseClick.bind(this);
this.handleCheckboxClick = this.handleCheckboxClick.bind(this);
onCheck() {
let isChecked = 0;
// Toggle off/partial check state to checked
if (this.props.checked === 0 || this.props.checked === 2) {
isChecked = 1;
}
this.props.onCheck({
value: this.props.value,
checked: isChecked,
children: this.props.rawChildren,
});
}
getCollapseIcon() {
onExpand() {
this.props.onExpand({
value: this.props.value,
expanded: !this.props.expanded,
});
}
renderCollapseIcon() {
if (this.props.children === null) {

@@ -34,3 +51,3 @@ return <i className="fa" />;

if (this.state.collapsed) {
if (!this.props.expanded) {
return <i className="fa fa-chevron-right" />;

@@ -42,3 +59,3 @@ }

getCheckboxIcon() {
renderCheckboxIcon() {
if (this.props.checked === 0) {

@@ -55,5 +72,5 @@ return <i className="fa fa-square-o" />;

getNodeIcon() {
renderNodeIcon() {
if (this.props.children !== null) {
if (this.state.collapsed) {
if (!this.props.expanded) {
return <i className="fa fa-folder-o" />;

@@ -68,45 +85,10 @@ }

getHiddenInput() {
if (this.props.name === undefined || !this.props.nameAsArray) {
renderChildren() {
if (!this.props.expanded) {
return null;
}
const name = `${this.props.name}[]`;
if (this.props.checked === 1) {
return <input name={name} value={this.props.value} type="hidden" />;
}
return null;
}
getChildren() {
if (this.state.collapsed) {
return null;
}
return this.props.children;
}
handleCollapseClick() {
this.setState({
collapsed: !this.state.collapsed,
});
}
handleCheckboxClick() {
let isChecked = 0;
// Toggle off/partial check state to checked
if (this.props.checked === 0 || this.props.checked === 2) {
isChecked = 1;
}
this.props.onCheck({
value: this.props.value,
checked: isChecked,
children: this.props.rawChildren,
});
}
render() {

@@ -116,11 +98,11 @@ return (

<span className="rct-text">
<span className="rct-collapse" onClick={this.handleCollapseClick} title="toggle">
{this.getCollapseIcon()}
<span className="rct-collapse" onClick={this.onExpand} title="Toggle">
{this.renderCollapseIcon()}
</span>
<label onClick={this.handleCheckboxClick}>
<label onClick={this.onCheck}>
<span className="rct-checkbox">
{this.getCheckboxIcon()}
{this.renderCheckboxIcon()}
</span>
<span className="rct-icon">
{this.getNodeIcon()}
{this.renderNodeIcon()}
</span>

@@ -130,6 +112,5 @@ <span className="rct-title">

</span>
{this.getHiddenInput()}
</label>
</span>
{this.getChildren()}
{this.renderChildren()}
</li>

@@ -136,0 +117,0 @@ );

@@ -1,3 +0,1 @@

/* eslint-disable */
module.exports = {

@@ -11,7 +9,7 @@ output: {

{
'react': {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
amd: 'react',
},

@@ -24,3 +22,3 @@ },

commonjs: 'react-dom',
amd: 'react-dom'
amd: 'react-dom',
},

@@ -36,3 +34,3 @@ },

query: {
presets: ['react', 'es2015', 'stage-0']
presets: ['react', 'es2015', 'stage-0'],
},

@@ -39,0 +37,0 @@ },

@@ -1,3 +0,1 @@

/* eslint-disable */
module.exports = {

@@ -16,3 +14,3 @@ output: {

query: {
presets: ['react', 'es2015', 'stage-0']
presets: ['react', 'es2015', 'stage-0'],
},

@@ -19,0 +17,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc