1
1
import React from 'react' ;
2
2
import ReactDOM from 'react-dom' ;
3
+ import { HotEditorElement } from './types' ;
3
4
4
5
let bulkComponentContainer = null ;
5
6
@@ -9,6 +10,22 @@ let bulkComponentContainer = null;
9
10
export const AUTOSIZE_WARNING = 'Your `HotTable` configuration includes `autoRowSize`/`autoColumnSize` options, which are not compatible with ' +
10
11
' the component-based renderers`. Disable `autoRowSize` and `autoColumnSize` to prevent row and column misalignment.' ;
11
12
13
+ /**
14
+ * Default classname given to the wrapper container.
15
+ */
16
+ const DEFAULT_CLASSNAME = 'hot-wrapper-editor-container' ;
17
+
18
+ /**
19
+ * Logs warn to the console if the `console` object is exposed.
20
+ *
21
+ * @param {...* } args Values which will be logged.
22
+ */
23
+ export function warn ( ...args ) {
24
+ if ( typeof console !== 'undefined' ) {
25
+ console . warn ( ...args ) ;
26
+ }
27
+ }
28
+
12
29
/**
13
30
* Filter out and return elements of the provided `type` from the `HotColumn` component's children.
14
31
*
@@ -36,26 +53,27 @@ export function getChildElementByType(children: React.ReactNode, type: string):
36
53
}
37
54
38
55
/**
39
- * Get the component node name .
56
+ * Get the reference to the original editor class .
40
57
*
41
- * @param {React.ReactElement } componentNode
42
- * @returns {String } Provided component's name .
58
+ * @param {React.ReactElement } editorElement React element of the editor class.
59
+ * @returns {Function } Original class of the editor component .
43
60
*/
44
- export function getComponentNodeName ( componentNode : React . ReactElement ) : string {
45
- if ( ! componentNode ) {
61
+ export function getOriginalEditorClass ( editorElement : HotEditorElement ) {
62
+ if ( ! editorElement ) {
46
63
return null ;
47
64
}
48
65
49
- return ( componentNode . type as Function ) . name || ( ( componentNode . type as any ) . WrappedComponent as Function ) . name ;
66
+ return editorElement . type . WrappedComponent ? editorElement . type . WrappedComponent : editorElement . type ;
50
67
}
51
68
52
69
/**
53
70
* Remove editor containers from DOM.
54
71
*
55
- * @param [doc] Document to be used.
72
+ * @param {Document } [doc] Document to be used.
73
+ * @param {Map } editorCache The editor cache reference.
56
74
*/
57
75
export function removeEditorContainers ( doc = document ) : void {
58
- doc . querySelectorAll ( '[id ^="hot-wrapper-editor-container-"]' ) . forEach ( ( domNode ) => {
76
+ doc . querySelectorAll ( `[class ^="${ DEFAULT_CLASSNAME } "]` ) . forEach ( ( domNode ) => {
59
77
if ( domNode . parentNode ) {
60
78
domNode . parentNode . removeChild ( domNode ) ;
61
79
}
@@ -65,23 +83,31 @@ export function removeEditorContainers(doc = document): void {
65
83
/**
66
84
* Create an editor portal.
67
85
*
86
+ * @param {Document } [doc] Document to be used.
68
87
* @param {React.ReactElement } editorElement Editor's element.
88
+ * @param {Map } editorCache The editor cache reference.
69
89
* @returns {React.ReactPortal } The portal for the editor.
70
90
*/
71
- export function createEditorPortal ( editorElement : React . ReactElement ) : React . ReactPortal {
91
+ export function createEditorPortal ( doc = document , editorElement : HotEditorElement , editorCache : Map < Function , React . Component > ) : React . ReactPortal {
72
92
if ( editorElement === null ) {
73
93
return ;
74
94
}
75
95
76
- const componentName : string = getComponentNodeName ( editorElement ) ;
96
+ const editorContainer = doc . createElement ( 'DIV' ) ;
97
+ const { id, className, style} = getContainerAttributesProps ( editorElement . props , false ) ;
77
98
78
- let editorContainer = document . querySelector ( '#hot-wrapper-editor-container-' + componentName ) ;
79
- if ( ! document . querySelector ( '#hot-wrapper-editor-container-' + componentName ) ) {
80
- editorContainer = document . createElement ( 'DIV' ) ;
81
- editorContainer . id = 'hot-wrapper-editor-container-' + componentName ;
82
- document . body . appendChild ( editorContainer ) ;
99
+ if ( id ) {
100
+ editorContainer . id = id ;
83
101
}
84
102
103
+ editorContainer . className = [ DEFAULT_CLASSNAME , className ] . join ( ' ' ) ;
104
+
105
+ if ( style ) {
106
+ Object . assign ( editorContainer . style , style ) ;
107
+ }
108
+
109
+ doc . body . appendChild ( editorContainer ) ;
110
+
85
111
return ReactDOM . createPortal ( editorElement , editorContainer ) ;
86
112
}
87
113
@@ -92,21 +118,20 @@ export function createEditorPortal(editorElement: React.ReactElement): React.Rea
92
118
* @param {Map } editorCache Component's editor cache.
93
119
* @returns {React.ReactElement } An editor element containing the additional methods.
94
120
*/
95
- export function getExtendedEditorElement ( children : React . ReactNode , editorCache : Map < string , object > ) : React . ReactElement | null {
121
+ export function getExtendedEditorElement ( children : React . ReactNode , editorCache : Map < Function , object > ) : React . ReactElement | null {
96
122
const editorElement = getChildElementByType ( children , 'hot-editor' ) ;
123
+ const editorClass = getOriginalEditorClass ( editorElement ) ;
97
124
98
125
if ( ! editorElement ) {
99
126
return null ;
100
127
}
101
128
102
129
return React . cloneElement ( editorElement , {
103
- emitEditorInstance : ( editorName , editorInstance ) => {
104
- if ( ! editorCache . has ( editorName ) ) {
105
- editorCache . set ( editorName , editorInstance ) ;
106
- }
130
+ emitEditorInstance : ( editorInstance ) => {
131
+ editorCache . set ( editorClass , editorInstance ) ;
107
132
} ,
108
133
isEditor : true
109
- } ) ;
134
+ } as object ) ;
110
135
}
111
136
112
137
/**
@@ -144,23 +169,42 @@ export function createPortal(rElement: React.ReactElement, props, callback: Func
144
169
} ;
145
170
}
146
171
172
+ /**
173
+ * Get an object containing the `id`, `className` and `style` keys, representing the corresponding props passed to the
174
+ * component.
175
+ *
176
+ * @param {Object } props Object containing the react element props.
177
+ * @param {Boolean } randomizeId If set to `true`, the function will randomize the `id` property when no `id` was present in the `prop` object.
178
+ * @returns An object containing the `id`, `className` and `style` keys, representing the corresponding props passed to the
179
+ * component.
180
+ */
181
+ export function getContainerAttributesProps ( props , randomizeId : boolean = true ) : { id : string , className : string , style : object } {
182
+ return {
183
+ id : props . id || ( randomizeId ? 'hot-' + Math . random ( ) . toString ( 36 ) . substring ( 5 ) : void 0 ) ,
184
+ className : props . className || '' ,
185
+ style : props . style || { } ,
186
+ }
187
+ }
188
+
147
189
/**
148
190
* Add the `UNSAFE_` prefixes to the deprecated lifecycle methods for React >= 16.3.
149
191
*
150
- * @param {Function } Klass Class to have the methods renamed.
151
- * @returns {Function } Class with the renamed methods.
192
+ * @param {Object } instance Instance to have the methods renamed.
152
193
*/
153
- export function addUnsafePrefixes < T extends any > ( Klass : T ) : T {
194
+ export function addUnsafePrefixes ( instance : {
195
+ UNSAFE_componentWillUpdate ?: Function ,
196
+ componentWillUpdate : Function ,
197
+ UNSAFE_componentWillMount ?: Function ,
198
+ componentWillMount : Function
199
+ } ) : void {
154
200
const reactSemverArray = React . version . split ( '.' ) . map ( ( v ) => parseInt ( v ) ) ;
155
201
const shouldPrefix = reactSemverArray [ 0 ] >= 16 && reactSemverArray [ 1 ] >= 3 ;
156
202
157
203
if ( shouldPrefix ) {
158
- Klass . prototype . UNSAFE_componentWillUpdate = Klass . prototype . componentWillUpdate ;
159
- delete Klass . prototype . componentWillUpdate ;
204
+ instance . UNSAFE_componentWillUpdate = instance . componentWillUpdate ;
205
+ instance . componentWillUpdate = void 0 ;
160
206
161
- Klass . prototype . UNSAFE_componentWillMount = Klass . prototype . componentWillMount ;
162
- delete Klass . prototype . componentWillMount ;
207
+ instance . UNSAFE_componentWillMount = instance . componentWillMount ;
208
+ instance . componentWillMount = void 0 ;
163
209
}
164
-
165
- return Klass ;
166
210
}
0 commit comments