File tree Expand file tree Collapse file tree 4 files changed +145
-0
lines changed Expand file tree Collapse file tree 4 files changed +145
-0
lines changed Original file line number Diff line number Diff line change 38
38
]
39
39
},
40
40
"dependencies" : {
41
+ "classnames" : " ^2.5.1" ,
42
+ "is-plain-object" : " ^5.0.0" ,
41
43
"react-is" : " ^18.2.0"
42
44
},
43
45
"devDependencies" : {
Original file line number Diff line number Diff line change 1
1
export { default as useEvent } from './hooks/useEvent' ;
2
2
export { default as useMergedState } from './hooks/useMergedState' ;
3
+ export { default as mergeProps } from './mergeProps' ;
3
4
export { supportNodeRef , supportRef , useComposeRef } from './ref' ;
4
5
export { default as get } from './utils/get' ;
5
6
export { default as set } from './utils/set' ;
Original file line number Diff line number Diff line change
1
+ import classNames from 'classnames' ;
2
+ import { isPlainObject } from 'is-plain-object' ;
3
+
4
+ function mergeClassNames < T > ( classNamesA : T , classNamesB : T ) : T {
5
+ const result = { ...classNamesA } ;
6
+ Object . keys ( classNamesB ) . forEach ( key => {
7
+ result [ key ] = mergeClassName ( classNamesA [ key ] , classNamesB [ key ] ) ;
8
+ } ) ;
9
+ return result ;
10
+ }
11
+
12
+ function mergeClassName ( classNameA ?: any , classNameB ?: any ) : string {
13
+ if ( typeof classNameA === 'object' || typeof classNameB === 'object' ) {
14
+ return mergeClassNames ( classNameA , classNameB ) ;
15
+ }
16
+
17
+ return classNames ( classNameA , classNameB ) ;
18
+ }
19
+
20
+ export default function mergeProps < T > ( ...list : T [ ] ) : T {
21
+ if ( list . length > 2 ) {
22
+ return mergeProps ( list [ 0 ] , mergeProps ( ...list . slice ( 1 ) ) ) ;
23
+ }
24
+ const result : T = { ...list [ 0 ] } ;
25
+ list [ 1 ] &&
26
+ Object . keys ( list [ 1 ] ) . forEach ( key => {
27
+ if ( key === 'className' ) {
28
+ result [ key ] = classNames ( result [ key ] , list [ 1 ] [ key ] ) ;
29
+ } else if ( key === 'classNames' ) {
30
+ result [ key ] = mergeClassNames ( result [ key ] , list [ 1 ] [ key ] ) ;
31
+ } else if ( isPlainObject ( list [ 1 ] [ key ] ) ) {
32
+ result [ key ] = mergeProps ( result [ key ] , list [ 1 ] [ key ] ) ;
33
+ } else {
34
+ result [ key ] = list [ 1 ] [ key ] ?? result [ key ] ;
35
+ }
36
+ } ) ;
37
+ return result ;
38
+ }
Original file line number Diff line number Diff line change
1
+ import mergeProps from '../src/mergeProps' ;
2
+
3
+ test ( 'merge className' , ( ) => {
4
+ expect ( mergeProps ( { className : 'foo' } , { className : 'bar' } ) ) . toEqual ( {
5
+ className : 'foo bar' ,
6
+ } ) ;
7
+ } ) ;
8
+
9
+ test ( 'merge classNames' , ( ) => {
10
+ expect (
11
+ mergeProps (
12
+ {
13
+ classNames : {
14
+ body : 'bam' ,
15
+ footer : 'foo' ,
16
+ } ,
17
+ } ,
18
+ {
19
+ classNames : {
20
+ footer : 'bar' ,
21
+ header : 'boo' ,
22
+ } ,
23
+ } ,
24
+ ) ,
25
+ ) . toEqual ( {
26
+ classNames : {
27
+ body : 'bam' ,
28
+ footer : 'foo bar' ,
29
+ header : 'boo' ,
30
+ } ,
31
+ } ) ;
32
+ } ) ;
33
+
34
+ test ( 'merge style' , ( ) => {
35
+ expect (
36
+ mergeProps (
37
+ {
38
+ style : {
39
+ background : '#000' ,
40
+ color : '#666' ,
41
+ } ,
42
+ } ,
43
+ {
44
+ style : {
45
+ background : '#fff' ,
46
+ } ,
47
+ } ,
48
+ ) ,
49
+ ) . toEqual ( {
50
+ style : {
51
+ background : '#fff' ,
52
+ color : '#666' ,
53
+ } ,
54
+ } ) ;
55
+ } ) ;
56
+
57
+ test ( 'merge boolean prop' , ( ) => {
58
+ expect (
59
+ mergeProps (
60
+ {
61
+ disabled : true ,
62
+ loading : false ,
63
+ } ,
64
+ {
65
+ disabled : false ,
66
+ } ,
67
+ ) ,
68
+ ) . toEqual ( {
69
+ disabled : false ,
70
+ loading : false ,
71
+ } ) ;
72
+ } ) ;
73
+
74
+ test ( 'merge number prop' , ( ) => {
75
+ expect (
76
+ mergeProps (
77
+ {
78
+ value : 1 ,
79
+ } ,
80
+ {
81
+ value : 2 ,
82
+ } ,
83
+ ) ,
84
+ ) . toEqual ( {
85
+ value : 2 ,
86
+ } ) ;
87
+ } ) ;
88
+
89
+ test ( 'merge non-plain object prop' , ( ) => {
90
+ const dateObj = new Date ( ) ;
91
+ const urlObj = new URL ( 'https://example.com/' ) ;
92
+ expect (
93
+ mergeProps (
94
+ {
95
+ value : dateObj ,
96
+ } ,
97
+ {
98
+ value : urlObj ,
99
+ } ,
100
+ ) ,
101
+ ) . toEqual ( {
102
+ value : urlObj ,
103
+ } ) ;
104
+ } ) ;
You can’t perform that action at this time.
0 commit comments