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