@@ -15,7 +15,10 @@ import {
15
15
TemplateRef ,
16
16
Type ,
17
17
} from '@angular/core' ;
18
+ import classnames from 'classnames' ;
18
19
import toStyle from 'css-to-style' ;
20
+ import stylenames , { StyleObject } from 'stylenames' ;
21
+ import { Many } from '../declarations/many' ;
19
22
import { ReactContentProps } from '../renderer/react-content' ;
20
23
import { isReactNode } from '../renderer/react-node' ;
21
24
import { isReactRendererData } from '../renderer/renderer' ;
@@ -42,52 +45,57 @@ export type InputRendererOptions<TContext extends object> =
42
45
43
46
export type JsxRenderFunc < TContext > = ( context : TContext ) => JSX . Element ;
44
47
48
+ export type ContentClassValue = string [ ] | Set < string > | { [ klass : string ] : any } ;
49
+ export type ContentStyleValue = string | StyleObject ;
50
+
45
51
/**
46
52
* Base class for Angular @Components wrapping React Components.
47
- * Simplifies some of the handling around passing down props and setting CSS on the host component.
53
+ * Simplifies some of the handling around passing down props and CSS styling on the host component.
48
54
*/
49
55
// NOTE: TProps is not used at the moment, but a preparation for a potential future change.
50
56
export abstract class ReactWrapperComponent < TProps extends { } > implements AfterViewInit , OnChanges {
51
- private _contentClass : string ;
52
- private _contentStyle : string ;
57
+ private _contentClass : Many < ContentClassValue > ;
58
+ private _contentStyle : ContentStyleValue ;
53
59
54
60
protected abstract reactNodeRef : ElementRef < HTMLElement > ;
55
61
56
62
/**
57
- * Alternative to `class` using the same syntax.
63
+ * Alternative to `class` and `[ngClass]` using the same syntax.
58
64
*
59
- * @description Since this is a wrapper component, sticking to the virtual DOM concept, this should have any styling of its own.
60
- * Any value passes to `contentClass` will be passed to the root component's class.
65
+ * @description Since this is a wrapper component, sticking to the virtual DOM concept, its DOM element shouldn't have any styling of its own.
66
+ * Instead, any value passes to `contentClass` will be passed to the root component's class as `className` .
61
67
*/
62
68
@Input ( )
63
- set contentClass ( value : string ) {
69
+ set contentClass ( value : Many < ContentClassValue > ) {
64
70
this . _contentClass = value ;
65
71
if ( isReactNode ( this . reactNodeRef . nativeElement ) ) {
66
- this . reactNodeRef . nativeElement . setProperty ( 'className' , value ) ;
72
+ this . reactNodeRef . nativeElement . setProperty ( 'className' , classnames ( value ) ) ;
67
73
this . changeDetectorRef . detectChanges ( ) ;
68
74
}
69
75
}
70
76
71
- get contentClass ( ) : string {
77
+ get contentClass ( ) : Many < ContentClassValue > {
72
78
return this . _contentClass ;
73
79
}
74
80
75
81
/**
76
- * Alternative to `style` using the same syntax.
82
+ * Alternative to `style` and `[ngStyle]` using (almost) the same syntax.
83
+ * All syntax supports by `ngStyle` is supported, with the exception of specifying units in the key (`{ 'width.px': 12 }`).
77
84
*
78
85
* @description Since this is a wrapper component, sticking to the virtual DOM concept, this should have any styling of its own.
79
86
* Any value passes to `contentStyle` will be passed to the root component's style.
80
87
*/
81
88
@Input ( )
82
- set contentStyle ( value : string ) {
89
+ set contentStyle ( value : ContentStyleValue ) {
83
90
this . _contentStyle = value ;
84
91
if ( isReactNode ( this . reactNodeRef . nativeElement ) ) {
85
- this . reactNodeRef . nativeElement . setProperty ( 'style' , toStyle ( value ) ) ;
92
+ const stringValue = typeof value === 'string' ? value : stylenames ( value ) ;
93
+ this . reactNodeRef . nativeElement . setProperty ( 'style' , toStyle ( stringValue ) ) ;
86
94
this . changeDetectorRef . detectChanges ( ) ;
87
95
}
88
96
}
89
97
90
- get contentStyle ( ) : string {
98
+ get contentStyle ( ) : ContentStyleValue {
91
99
return this . _contentStyle ;
92
100
}
93
101
0 commit comments