Rearranged some DevTools Components code
Brian Vaughn committed
Feb 26, 2020 at 11:33 UTC
71418fda3b449d36b81ec8f12e076b81cd816534
4 files changed
+238
-258
packages/react-devtools-shared/src/devtools/views/Components/Components.css
+15
@@ -1,3 +1,14 @@
1
+.Components {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ display: flex;
6
+ flex-direction: row;
7
+ background-color: var(--color-background);
8
+ color: var(--color-text);
9
+ font-family: var(--font-family-sans);
10
+}
11
+
12
.TreeWrapper {
13
flex: 0 0 var(--horizontal-resize-percentage);
14
overflow: auto;
@@ -23,6 +34,10 @@
34
}
35
36
@media screen and (max-width: 600px) {
37
+ .Components {
38
+ flex-direction: column;
39
+ }
40
+
41
.TreeWrapper {
42
flex: 0 0 var(--vertical-resize-percentage);
43
}
packages/react-devtools-shared/src/devtools/views/Components/Components.js
+223
-29
@@ -8,49 +8,155 @@
8
*/
9
10
import * as React from 'react';
11
-import {Suspense, Fragment} from 'react';
11
+import {
12
+ Fragment,
13
+ Suspense,
14
+ useEffect,
15
+ useLayoutEffect,
16
+ useReducer,
17
+ useRef,
18
+} from 'react';
19
import Tree from './Tree';
13
-import SelectedElement from './SelectedElement';
20
import {InspectedElementContextController} from './InspectedElementContext';
15
-import {NativeStyleContextController} from './NativeStyleEditor/context';
21
import {OwnersListContextController} from './OwnersListContext';
17
-import ComponentsResizer from './ComponentsResizer';
22
import portaledContent from '../portaledContent';
23
+import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
24
+import {
25
+ localStorageGetItem,
26
+ localStorageSetItem,
27
+} from 'react-devtools-shared/src/storage';
28
+import SelectedElement from './SelectedElement';
29
import {ModalDialog} from '../ModalDialog';
30
import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';
21
-import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
31
+import {NativeStyleContextController} from './NativeStyleEditor/context';
32
33
import styles from './Components.css';
34
35
function Components(_: {||}) {
36
+ const wrapperElementRef = useRef<HTMLElement>(null);
37
+ const resizeElementRef = useRef<HTMLElement>(null);
38
+
39
+ const [state, dispatch] = useReducer<ResizeState, ResizeAction>(
40
+ resizeReducer,
41
+ null,
42
+ initResizeState,
43
+ );
44
+
45
+ const {horizontalPercentage, verticalPercentage} = state;
46
+
47
+ useLayoutEffect(() => {
48
+ const resizeElement = resizeElementRef.current;
49
+
50
+ setResizeCSSVariable(
51
+ resizeElement,
52
+ 'horizontal',
53
+ horizontalPercentage * 100,
54
+ );
55
+ setResizeCSSVariable(resizeElement, 'vertical', verticalPercentage * 100);
56
+ }, []);
57
+
58
+ useEffect(() => {
59
+ const timeoutID = setTimeout(() => {
60
+ localStorageSetItem(
61
+ LOCAL_STORAGE_KEY,
62
+ JSON.stringify({
63
+ horizontalPercentage,
64
+ verticalPercentage,
65
+ }),
66
+ );
67
+ }, 500);
68
+
69
+ return () => clearTimeout(timeoutID);
70
+ }, [horizontalPercentage, verticalPercentage]);
71
+
72
+ const {isResizing} = state;
73
+
74
+ const onResizeStart = () =>
75
+ dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true});
76
+
77
+ let onResize;
78
+ let onResizeEnd;
79
+ if (isResizing) {
80
+ onResizeEnd = () =>
81
+ dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false});
82
+
83
+ onResize = event => {
84
+ const resizeElement = resizeElementRef.current;
85
+ const wrapperElement = wrapperElementRef.current;
86
+
87
+ if (!isResizing || wrapperElement === null || resizeElement === null) {
88
+ return;
89
+ }
90
+
91
+ event.preventDefault();
92
+
93
+ const orientation = getOrientation(wrapperElement);
94
+
95
+ const {height, width, left, top} = wrapperElement.getBoundingClientRect();
96
+
97
+ const currentMousePosition =
98
+ orientation === 'horizontal'
99
+ ? event.clientX - left
100
+ : event.clientY - top;
101
+
102
+ const boundaryMin = MINIMUM_SIZE;
103
+ const boundaryMax =
104
+ orientation === 'horizontal'
105
+ ? width - MINIMUM_SIZE
106
+ : height - MINIMUM_SIZE;
107
+
108
+ const isMousePositionInBounds =
109
+ currentMousePosition > boundaryMin &&
110
+ currentMousePosition < boundaryMax;
111
+
112
+ if (isMousePositionInBounds) {
113
+ const resizedElementDimension =
114
+ orientation === 'horizontal' ? width : height;
115
+ const actionType =
116
+ orientation === 'horizontal'
117
+ ? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
118
+ : 'ACTION_SET_VERTICAL_PERCENTAGE';
119
+ const percentage =
120
+ (currentMousePosition / resizedElementDimension) * 100;
121
+
122
+ setResizeCSSVariable(resizeElement, orientation, percentage);
123
+
124
+ dispatch({
125
+ type: actionType,
126
+ payload: currentMousePosition / resizedElementDimension,
127
+ });
128
+ }
129
+ };
130
+ }
131
+
132
return (
133
<SettingsModalContextController>
134
<OwnersListContextController>
135
<InspectedElementContextController>
30
- <ComponentsResizer>
31
- {({resizeElementRef, onResizeStart}) => (
32
- <Fragment>
33
- <div ref={resizeElementRef} className={styles.TreeWrapper}>
34
- <Tree />
35
- </div>
36
- <div className={styles.ResizeBarWrapper}>
37
- <div
38
- onMouseDown={onResizeStart}
39
- className={styles.ResizeBar}
40
- />
41
- </div>
42
- <div className={styles.SelectedElementWrapper}>
43
- <NativeStyleContextController>
44
- <Suspense fallback={<Loading />}>
45
- <SelectedElement />
46
- </Suspense>
47
- </NativeStyleContextController>
48
- </div>
49
- <ModalDialog />
50
- <SettingsModal />
51
- </Fragment>
52
- )}
53
- </ComponentsResizer>
136
+ <div
137
+ ref={wrapperElementRef}
138
+ className={styles.Components}
139
+ onMouseMove={onResize}
140
+ onMouseLeave={onResizeEnd}
141
+ onMouseUp={onResizeEnd}>
142
+ <Fragment>
143
+ <div ref={resizeElementRef} className={styles.TreeWrapper}>
144
+ <Tree />
145
+ </div>
146
+ <div className={styles.ResizeBarWrapper}>
147
+ <div onMouseDown={onResizeStart} className={styles.ResizeBar} />
148
+ </div>
149
+ <div className={styles.SelectedElementWrapper}>
150
+ <NativeStyleContextController>
151
+ <Suspense fallback={<Loading />}>
152
+ <SelectedElement />
153
+ </Suspense>
154
+ </NativeStyleContextController>
155
+ </div>
156
+ <ModalDialog />
157
+ <SettingsModal />
158
+ </Fragment>
159
+ </div>
160
</InspectedElementContextController>
161
</OwnersListContextController>
162
</SettingsModalContextController>
@@ -61,4 +167,92 @@ function Loading() {
167
return <div className={styles.Loading}>Loading...</div>;
168
}
169
170
+const LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer';
171
+const VERTICAL_MODE_MAX_WIDTH = 600;
172
+const MINIMUM_SIZE = 50;
173
+
174
+type Orientation = 'horizontal' | 'vertical';
175
+
176
+type ResizeActionType =
177
+ | 'ACTION_SET_DID_MOUNT'
178
+ | 'ACTION_SET_IS_RESIZING'
179
+ | 'ACTION_SET_HORIZONTAL_PERCENTAGE'
180
+ | 'ACTION_SET_VERTICAL_PERCENTAGE';
181
+
182
+type ResizeAction = {|
183
+ type: ResizeActionType,
184
+ payload: any,
185
+|};
186
+
187
+type ResizeState = {|
188
+ horizontalPercentage: number,
189
+ isResizing: boolean,
190
+ verticalPercentage: number,
191
+|};
192
+
193
+function initResizeState(): ResizeState {
194
+ let horizontalPercentage = 0.65;
195
+ let verticalPercentage = 0.5;
196
+
197
+ try {
198
+ let data = localStorageGetItem(LOCAL_STORAGE_KEY);
199
+ if (data != null) {
200
+ data = JSON.parse(data);
201
+ horizontalPercentage = data.horizontalPercentage;
202
+ verticalPercentage = data.verticalPercentage;
203
+ }
204
+ } catch (error) {}
205
+
206
+ return {
207
+ horizontalPercentage,
208
+ isResizing: false,
209
+ verticalPercentage,
210
+ };
211
+}
212
+
213
+function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {
214
+ switch (action.type) {
215
+ case 'ACTION_SET_IS_RESIZING':
216
+ return {
217
+ ...state,
218
+ isResizing: action.payload,
219
+ };
220
+ case 'ACTION_SET_HORIZONTAL_PERCENTAGE':
221
+ return {
222
+ ...state,
223
+ horizontalPercentage: action.payload,
224
+ };
225
+ case 'ACTION_SET_VERTICAL_PERCENTAGE':
226
+ return {
227
+ ...state,
228
+ verticalPercentage: action.payload,
229
+ };
230
+ default:
231
+ return state;
232
+ }
233
+}
234
+
235
+function getOrientation(
236
+ wrapperElement: null | HTMLElement,
237
+): null | Orientation {
238
+ if (wrapperElement != null) {
239
+ const {width} = wrapperElement.getBoundingClientRect();
240
+ return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical';
241
+ }
242
+ return null;
243
+}
244
+
245
+function setResizeCSSVariable(
246
+ resizeElement: null | HTMLElement,
247
+ orientation: null | Orientation,
248
+ percentage: number,
249
+): void {
250
+ if (resizeElement !== null && orientation !== null) {
251
+ resizeElement.style.setProperty(
252
+ `--${orientation}-resize-percentage`,
253
+ `${percentage}%`,
254
+ );
255
+ }
256
+}
257
+
258
export default portaledContent(Components);
packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.css
deleted
-16
@@ -1,16 +0,0 @@
1
-.ComponentsWrapper {
2
- position: relative;
3
- width: 100%;
4
- height: 100%;
5
- display: flex;
6
- flex-direction: row;
7
- background-color: var(--color-background);
8
- color: var(--color-text);
9
- font-family: var(--font-family-sans);
10
-}
11
-
12
-@media screen and (max-width: 600px) {
13
- .ComponentsWrapper {
14
- flex-direction: column;
15
- }
16
-}
packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js
deleted
-213
@@ -1,213 +0,0 @@
1
-/**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import * as React from 'react';
11
-import {useEffect, useLayoutEffect, useReducer, useRef} from 'react';
12
-import {
13
- localStorageGetItem,
14
- localStorageSetItem,
15
-} from 'react-devtools-shared/src/storage';
16
-import styles from './ComponentsResizer.css';
17
-
18
-const LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer';
19
-const VERTICAL_MODE_MAX_WIDTH = 600;
20
-const MINIMUM_SIZE = 50;
21
-
22
-type Orientation = 'horizontal' | 'vertical';
23
-
24
-type ResizeActionType =
25
- | 'ACTION_SET_DID_MOUNT'
26
- | 'ACTION_SET_IS_RESIZING'
27
- | 'ACTION_SET_HORIZONTAL_PERCENTAGE'
28
- | 'ACTION_SET_VERTICAL_PERCENTAGE';
29
-
30
-type ResizeAction = {|
31
- type: ResizeActionType,
32
- payload: any,
33
-|};
34
-
35
-type ResizeState = {|
36
- horizontalPercentage: number,
37
- isResizing: boolean,
38
- verticalPercentage: number,
39
-|};
40
-
41
-function initResizeState(): ResizeState {
42
- let horizontalPercentage = 0.65;
43
- let verticalPercentage = 0.5;
44
-
45
- try {
46
- let data = localStorageGetItem(LOCAL_STORAGE_KEY);
47
- if (data != null) {
48
- data = JSON.parse(data);
49
- horizontalPercentage = data.horizontalPercentage;
50
- verticalPercentage = data.verticalPercentage;
51
- }
52
- } catch (error) {}
53
-
54
- return {
55
- horizontalPercentage,
56
- isResizing: false,
57
- verticalPercentage,
58
- };
59
-}
60
-
61
-function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {
62
- switch (action.type) {
63
- case 'ACTION_SET_IS_RESIZING':
64
- return {
65
- ...state,
66
- isResizing: action.payload,
67
- };
68
- case 'ACTION_SET_HORIZONTAL_PERCENTAGE':
69
- return {
70
- ...state,
71
- horizontalPercentage: action.payload,
72
- };
73
- case 'ACTION_SET_VERTICAL_PERCENTAGE':
74
- return {
75
- ...state,
76
- verticalPercentage: action.payload,
77
- };
78
- default:
79
- return state;
80
- }
81
-}
82
-
83
-type Props = {|
84
- children: ({
85
- resizeElementRef: React$Ref<HTMLElement>,
86
- onResizeStart: () => void,
87
- }) => React$Node,
88
-|};
89
-
90
-export default function ComponentsResizer({children}: Props) {
91
- const wrapperElementRef = useRef<HTMLElement>(null);
92
- const resizeElementRef = useRef<HTMLElement>(null);
93
-
94
- const [state, dispatch] = useReducer<ResizeState, ResizeAction>(
95
- resizeReducer,
96
- null,
97
- initResizeState,
98
- );
99
-
100
- const {horizontalPercentage, verticalPercentage} = state;
101
-
102
- useLayoutEffect(() => {
103
- const resizeElement = resizeElementRef.current;
104
-
105
- setResizeCSSVariable(
106
- resizeElement,
107
- 'horizontal',
108
- horizontalPercentage * 100,
109
- );
110
- setResizeCSSVariable(resizeElement, 'vertical', verticalPercentage * 100);
111
- }, []);
112
-
113
- useEffect(() => {
114
- const timeoutID = setTimeout(() => {
115
- localStorageSetItem(
116
- LOCAL_STORAGE_KEY,
117
- JSON.stringify({
118
- horizontalPercentage,
119
- verticalPercentage,
120
- }),
121
- );
122
- }, 500);
123
-
124
- return () => clearTimeout(timeoutID);
125
- }, [horizontalPercentage, verticalPercentage]);
126
-
127
- const {isResizing} = state;
128
-
129
- const onResizeStart = () =>
130
- dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true});
131
- const onResizeEnd = () =>
132
- dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false});
133
-
134
- const onResize = event => {
135
- const resizeElement = resizeElementRef.current;
136
- const wrapperElement = wrapperElementRef.current;
137
-
138
- if (!isResizing || wrapperElement === null || resizeElement === null) {
139
- return;
140
- }
141
-
142
- event.preventDefault();
143
-
144
- const orientation = getOrientation(wrapperElement);
145
-
146
- const {height, width, left, top} = wrapperElement.getBoundingClientRect();
147
-
148
- const currentMousePosition =
149
- orientation === 'horizontal' ? event.clientX - left : event.clientY - top;
150
-
151
- const boundaryMin = MINIMUM_SIZE;
152
- const boundaryMax =
153
- orientation === 'horizontal'
154
- ? width - MINIMUM_SIZE
155
- : height - MINIMUM_SIZE;
156
-
157
- const isMousePositionInBounds =
158
- currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;
159
-
160
- if (isMousePositionInBounds) {
161
- const resizedElementDimension =
162
- orientation === 'horizontal' ? width : height;
163
- const actionType =
164
- orientation === 'horizontal'
165
- ? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
166
- : 'ACTION_SET_VERTICAL_PERCENTAGE';
167
- const percentage = (currentMousePosition / resizedElementDimension) * 100;
168
-
169
- setResizeCSSVariable(resizeElement, orientation, percentage);
170
-
171
- dispatch({
172
- type: actionType,
173
- payload: currentMousePosition / resizedElementDimension,
174
- });
175
- }
176
- };
177
-
178
- return (
179
- <div
180
- ref={wrapperElementRef}
181
- className={styles.ComponentsWrapper}
182
- {...(isResizing && {
183
- onMouseMove: onResize,
184
- onMouseLeave: onResizeEnd,
185
- onMouseUp: onResizeEnd,
186
- })}>
187
- {children({resizeElementRef, onResizeStart})}
188
- </div>
189
- );
190
-}
191
-
192
-function getOrientation(
193
- wrapperElement: null | HTMLElement,
194
-): null | Orientation {
195
- if (wrapperElement != null) {
196
- const {width} = wrapperElement.getBoundingClientRect();
197
- return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical';
198
- }
199
- return null;
200
-}
201
-
202
-function setResizeCSSVariable(
203
- resizeElement: null | HTMLElement,
204
- orientation: null | Orientation,
205
- percentage: number,
206
-): void {
207
- if (resizeElement !== null && orientation !== null) {
208
- resizeElement.style.setProperty(
209
- `--${orientation}-resize-percentage`,
210
- `${percentage}%`,
211
- );
212
- }
213
-}