@samitouri / QOS-React-2 / commits / 71418fda3b

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 -}