1+ const React = require ( "react" ) ;
2+ const findDOMNode = require ( "react-dom" ) . findDOMNode ;
3+ import { matchAnd } from "./utils/match-props" ;
4+ export default class ToggleAndDisplayPattern extends React . Component {
5+ constructor ( ...args ) {
6+ super ( ...args ) ;
7+ this . wrapper = null ;
8+ this . _activeChidlren = [ ] ;
9+ this . _hiddenChildren = [ ] ;
10+ }
11+
12+ getFlagNames ( ) {
13+ return Object . keys ( this . props ) . filter ( key => {
14+ return key !== "children" ;
15+ } ) ;
16+ }
17+
18+ /**
19+ * get components from `children` that matches key and value with own props.
20+ * @returns {ReactComponent[] }
21+ */
22+ mapComponents ( ) {
23+ const children = [ ] . concat ( this . props . children ) ;
24+ const flagKeyNames = this . getFlagNames ( ) ;
25+ return children . map ( ( child , index ) => {
26+ if ( ! child . props ) {
27+ return null ;
28+ }
29+ // all match
30+ if ( matchAnd ( flagKeyNames , this . props , child . props ) ) {
31+ const newProps = {
32+ key : index
33+ } ;
34+ newProps . ref = ( c ) => {
35+ if ( typeof child . ref === 'function' ) {
36+ child . ref ( c ) ;
37+ }
38+ if ( c ) {
39+ this . _activeChidlren . push ( c ) ;
40+ }
41+ } ;
42+ return React . cloneElement ( child , newProps ) ;
43+ } else {
44+ const newProps = {
45+ key : index
46+ } ;
47+ newProps . ref = ( c ) => {
48+ if ( typeof child . ref === 'function' ) {
49+ child . ref ( c ) ;
50+ }
51+ if ( c ) {
52+ this . _hiddenChildren . push ( c ) ;
53+ }
54+ } ;
55+ return React . cloneElement ( child , newProps ) ;
56+ }
57+ } ) ;
58+ }
59+
60+ componentWillUpdate ( ) {
61+ this . _activeChidlren = [ ] ;
62+ this . _hiddenChildren = [ ] ;
63+ }
64+
65+ componentDidMount ( ) {
66+ this . _updatePattens ( ) ;
67+ }
68+
69+ componentDidUpdate ( ) {
70+ this . _updatePattens ( )
71+ }
72+
73+ render ( ) {
74+ const components = this . mapComponents ( ) ;
75+ if ( components . length === 0 ) {
76+ return null ;
77+ }
78+ return < span
79+ className = "TogglePattern ToggleAndDisplayPattern"
80+ ref = { ( c ) => this . wrapper = c } >
81+ { components }
82+ </ span > ;
83+ }
84+
85+ _updatePattens ( ) {
86+ const wrapper = findDOMNode ( this . wrapper ) ;
87+ let isActiveWrapper = false ;
88+ // include focus element?
89+ if ( wrapper ) {
90+ const activeElement = document . activeElement ;
91+ isActiveWrapper = wrapper . contains ( activeElement ) ;
92+ }
93+ this . _activeChidlren . forEach ( child => {
94+ const childDOM = findDOMNode ( child ) ;
95+ if ( childDOM ) {
96+ childDOM . hidden = false ;
97+ }
98+ } ) ;
99+ this . _hiddenChildren . forEach ( child => {
100+ const childDOM = findDOMNode ( child ) ;
101+ if ( childDOM ) {
102+ childDOM . hidden = true ;
103+ }
104+ } ) ;
105+ // move to focus
106+ if ( isActiveWrapper && this . _activeChidlren . length === 1 ) {
107+ const activeDOM = findDOMNode ( this . _activeChidlren [ 0 ] ) ;
108+ if ( activeDOM ) {
109+ activeDOM . focus ( ) ;
110+ }
111+ }
112+ }
113+ }
0 commit comments