Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions example/src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, {Component} from 'react';
import {TogglePattern} from "react-toggle-pattern";
import {ToggleAndDisplayPattern as TogglePattern} from "react-toggle-pattern";
import ActiveElement from "./ActiveElement";
import './App.css';

class App extends Component {
constructor() {
super();
this.state = {
pattern: "A"
pattern: "A",
patternCorD: "C"
}
}

Expand All @@ -22,21 +23,40 @@ class App extends Component {
pattern: "A"
});
};
const onClickC = () => {
this.setState({
patternCorD: "D"
});
};
const onClickD = () => {
this.setState({
patternCorD: "C"
});
};
return (
<div className="App">
<TogglePattern pattern={this.state.pattern}>
<div pattern={"A"} onClick={onClickA}>
<button><p>
A
</p></button>
</div>
<div pattern={"B"} onClick={onClickB}>
<span>BBB</span>
<button>
<span>B</span>
<div>
<h2>Pattern A or B</h2>
<TogglePattern pattern={this.state.pattern}>
<button pattern={"A"} onClick={onClickA}>
AAAAAA
</button>
<button pattern={"B"} onClick={onClickB}>
BBBBBB
</button>
</TogglePattern>
</div>
<div>
<h2>Pattern C or D</h2>
<TogglePattern pattern={this.state.patternCorD}>
<button key="C" pattern={"C"} onClick={onClickC}>
CCCCCCC
</button>
<button key="D" pattern={"D"} onClick={onClickD}>
DDDDDDD
</button>
</div>
</TogglePattern>
</TogglePattern>
</div>
<ActiveElement />
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"src/",
"lib/"
],
"version": "1.2.1",
"version": "1.3.1",
"description": "React Component that provide toggle pattern",
"main": "lib/index.js",
"directories": {
Expand All @@ -38,18 +38,20 @@
"devDependencies": {
"babel-cli": "^6.8.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-jsdoc-to-assert": "^1.0.1",
"babel-preset-jsdoc-to-assert": "^4.0.0",
"babel-preset-power-assert": "^1.0.0",
"babel-preset-react": "^6.5.0",
"babel-register": "^6.8.0",
"enzyme": "^2.3.0",
"mocha": "^2.4.5",
"mocha": "^3.1.0",
"power-assert": "^1.4.1",
"react": "^15.0.2",
"react-addons-test-utils": "^15.0.2",
"react-dom": "^15.0.2"
},
"peerDependencies": {
"react": ">=15.0.2"
},
"dependencies": {
}
}
113 changes: 113 additions & 0 deletions src/ToggleAndDisplayPattern.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const React = require("react");
const findDOMNode = require("react-dom").findDOMNode;
import {matchAnd} from "./utils/match-props";
export default class ToggleAndDisplayPattern extends React.Component {
constructor(...args) {
super(...args);
this.wrapper = null;
this._activeChidlren = [];
this._hiddenChildren = [];
}

getFlagNames() {
return Object.keys(this.props).filter(key => {
return key !== "children";
});
}

/**
* get components from `children` that matches key and value with own props.
* @returns {ReactComponent[]}
*/
mapComponents() {
const children = [].concat(this.props.children);
const flagKeyNames = this.getFlagNames();
return children.map((child, index) => {
if (!child.props) {
return null;
}
// all match
if (matchAnd(flagKeyNames, this.props, child.props)) {
const newProps = {
key: index
};
newProps.ref = (c) => {
if (typeof child.ref === 'function') {
child.ref(c);
}
if (c) {
this._activeChidlren.push(c);
}
};
return React.cloneElement(child, newProps);
} else {
const newProps = {
key: index
};
newProps.ref = (c) => {
if (typeof child.ref === 'function') {
child.ref(c);
}
if (c) {
this._hiddenChildren.push(c);
}
};
return React.cloneElement(child, newProps);
}
});
}

componentWillUpdate() {
this._activeChidlren = [];
this._hiddenChildren = [];
}

componentDidMount() {
this._updatePattens();
}

componentDidUpdate() {
this._updatePattens()
}

render() {
const components = this.mapComponents();
if (components.length === 0) {
return null;
}
return <span
className="TogglePattern ToggleAndDisplayPattern"
ref={(c) => this.wrapper = c}>
{components}
</span>;
}

_updatePattens() {
const wrapper = findDOMNode(this.wrapper);
let isActiveWrapper = false;
// include focus element?
if (wrapper) {
const activeElement = document.activeElement;
isActiveWrapper = wrapper.contains(activeElement);
}
this._activeChidlren.forEach(child => {
const childDOM = findDOMNode(child);
if (childDOM) {
childDOM.hidden = false;
}
});
this._hiddenChildren.forEach(child => {
const childDOM = findDOMNode(child);
if (childDOM) {
childDOM.hidden = true;
}
});
// move to focus
if (isActiveWrapper && this._activeChidlren.length === 1) {
const activeDOM = findDOMNode(this._activeChidlren[0]);
if (activeDOM) {
activeDOM.focus();
}
}
}
}
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// LICENSE : MIT
"use strict";
import ToggleAndDisplayPattern from "./ToggleAndDisplayPattern";
import ToggleAndPattern from "./ToggleAndPattern";
import ToggleOrPattern from "./ToggleOrPattern";
module.exports = {
// default: or pattern
TogglePattern: ToggleOrPattern,
ToggleAndDisplayPattern,
ToggleOrPattern,
ToggleAndPattern
};
6 changes: 3 additions & 3 deletions src/utils/match-props.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// LICENSE : MIT
"use strict";
export function matchAnd(keys, parentProps, childProps) {
const childKeys = Object.keys(childProps);
const childKeys = childProps ? Object.keys(childProps) : [];
// all match
return keys.every(parentKey => {
return childKeys.some(childKey => {
Expand All @@ -11,7 +11,7 @@ export function matchAnd(keys, parentProps, childProps) {
const parentValue = parentProps[parentKey];
const childValue = childProps[childKey];
if (childValue === parentValue) {
return true
return true;
} else if (childValue === undefined && parentKey === true) {
// <X attr />
return true;
Expand All @@ -21,7 +21,7 @@ export function matchAnd(keys, parentProps, childProps) {
});
}
export function matchOr(keys, parentProps, childProps) {
const childKeys = Object.keys(childProps);
const childKeys = childProps ? Object.keys(childProps) : [];
// some match
return keys.some(parentKey => {
return childKeys.some(childKey => {
Expand Down
24 changes: 24 additions & 0 deletions test/ToggleAndDisplayPattern-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const assert = require("power-assert");
import React from "react";
import {shallow} from 'enzyme';
import ToggleAndDisplayPattern from "../src/ToggleAndDisplayPattern";
class ComponentY extends React.Component {
render() {
return <div>Hidden</div>
}
}
class ComponentX extends React.Component {
render() {
return <div>Visible</div>
}
}
describe('<ToggleAndDisplayPattern />', () => {
it('renders 1 <ComponentX /> components', () => {
const result = shallow(<ToggleAndDisplayPattern isEditing={true}>
<ComponentX isEditing/>
<ComponentY/>
</ToggleAndDisplayPattern>);
assert.equal(result.html(), `<span class="TogglePattern ToggleAndDisplayPattern"><div>Visible</div><div>Hidden</div></span>`)
;
});
});