diff --git a/src/__tests__/__snapshots__/store-test.js.snap b/src/__tests__/__snapshots__/store-test.js.snap index 102a328558..7f135dc641 100644 --- a/src/__tests__/__snapshots__/store-test.js.snap +++ b/src/__tests__/__snapshots__/store-test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Store should display Suspense nodes properly in various states: 1: loading 1`] = ` +exports[`Store collapseNodesByDefault:false should display Suspense nodes properly in various states: 1: loading 1`] = ` [root] ▾ @@ -8,7 +8,7 @@ exports[`Store should display Suspense nodes properly in various states: 1: load `; -exports[`Store should display Suspense nodes properly in various states: 2: resolved 1`] = ` +exports[`Store collapseNodesByDefault:false should display Suspense nodes properly in various states: 2: resolved 1`] = ` [root] ▾ @@ -16,7 +16,7 @@ exports[`Store should display Suspense nodes properly in various states: 2: reso `; -exports[`Store should filter DOM nodes from the store tree: 1: mount 1`] = ` +exports[`Store collapseNodesByDefault:false should filter DOM nodes from the store tree: 1: mount 1`] = ` [root] ▾ ▾ @@ -25,7 +25,7 @@ exports[`Store should filter DOM nodes from the store tree: 1: mount 1`] = ` `; -exports[`Store should support collapsing parts of the tree: 1: mount 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 1: mount 1`] = ` [root] ▾ ▾ @@ -36,7 +36,7 @@ exports[`Store should support collapsing parts of the tree: 1: mount 1`] = ` `; -exports[`Store should support collapsing parts of the tree: 2: collapse first Parent 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 2: collapse first Parent 1`] = ` [root] ▾ ▸ @@ -45,14 +45,14 @@ exports[`Store should support collapsing parts of the tree: 2: collapse first Pa `; -exports[`Store should support collapsing parts of the tree: 3: collapse second Parent 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 3: collapse second Parent 1`] = ` [root] ▾ ▸ ▸ `; -exports[`Store should support collapsing parts of the tree: 4: expand first Parent 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 4: expand first Parent 1`] = ` [root] ▾ ▾ @@ -61,12 +61,12 @@ exports[`Store should support collapsing parts of the tree: 4: expand first Pare ▸ `; -exports[`Store should support collapsing parts of the tree: 5: collapse Grandparent 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 5: collapse Grandparent 1`] = ` [root] ▸ `; -exports[`Store should support collapsing parts of the tree: 6: expand Grandparent 1`] = ` +exports[`Store collapseNodesByDefault:false should support collapsing parts of the tree: 6: expand Grandparent 1`] = ` [root] ▾ ▾ @@ -75,7 +75,7 @@ exports[`Store should support collapsing parts of the tree: 6: expand Grandparen ▸ `; -exports[`Store should support mount and update operations for multiple roots: 1: mount 1`] = ` +exports[`Store collapseNodesByDefault:false should support mount and update operations for multiple roots: 1: mount 1`] = ` [root] ▾ @@ -87,7 +87,7 @@ exports[`Store should support mount and update operations for multiple roots: 1: `; -exports[`Store should support mount and update operations for multiple roots: 2: update 1`] = ` +exports[`Store collapseNodesByDefault:false should support mount and update operations for multiple roots: 2: update 1`] = ` [root] ▾ @@ -99,7 +99,7 @@ exports[`Store should support mount and update operations for multiple roots: 2: `; -exports[`Store should support mount and update operations for multiple roots: 3: unmount B 1`] = ` +exports[`Store collapseNodesByDefault:false should support mount and update operations for multiple roots: 3: unmount B 1`] = ` [root] ▾ @@ -108,9 +108,9 @@ exports[`Store should support mount and update operations for multiple roots: 3: `; -exports[`Store should support mount and update operations for multiple roots: 4: unmount A 1`] = ``; +exports[`Store collapseNodesByDefault:false should support mount and update operations for multiple roots: 4: unmount A 1`] = ``; -exports[`Store should support mount and update operations: 1: mount 1`] = ` +exports[`Store collapseNodesByDefault:false should support mount and update operations: 1: mount 1`] = ` [root] ▾ ▾ @@ -125,7 +125,7 @@ exports[`Store should support mount and update operations: 1: mount 1`] = ` `; -exports[`Store should support mount and update operations: 2: update 1`] = ` +exports[`Store collapseNodesByDefault:false should support mount and update operations: 2: update 1`] = ` [root] ▾ ▾ @@ -136,4 +136,131 @@ exports[`Store should support mount and update operations: 2: update 1`] = ` `; -exports[`Store should support mount and update operations: 3: unmount 1`] = ``; +exports[`Store collapseNodesByDefault:false should support mount and update operations: 3: unmount 1`] = ``; + +exports[`Store collapseNodesByDefault:true should display Suspense nodes properly in various states: 1: loading 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should display Suspense nodes properly in various states: 2: expand Wrapper and Suspense 1`] = ` +[root] + ▾ + + ▾ + +`; + +exports[`Store collapseNodesByDefault:true should display Suspense nodes properly in various states: 2: resolved 1`] = ` +[root] + ▾ + + ▾ + +`; + +exports[`Store collapseNodesByDefault:true should filter DOM nodes from the store tree: 1: mount 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should filter DOM nodes from the store tree: 2: expand Grandparent 1`] = ` +[root] + ▾ + ▸ + ▸ +`; + +exports[`Store collapseNodesByDefault:true should filter DOM nodes from the store tree: 3: expand Parent 1`] = ` +[root] + ▾ + ▾ + + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 1: mount 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 2: expand Grandparent 1`] = ` +[root] + ▾ + ▸ + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 3: expand first Parent 1`] = ` +[root] + ▾ + ▾ + + + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 4: expand second Parent 1`] = ` +[root] + ▾ + ▾ + + + ▾ + + +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 5: collapse first Parent 1`] = ` +[root] + ▾ + ▸ + ▾ + + +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 6: collapse second Parent 1`] = ` +[root] + ▾ + ▸ + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support collapsing parts of the tree: 7: collapse Grandparent 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations for multiple roots: 1: mount 1`] = ` +[root] + ▸ +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations for multiple roots: 2: update 1`] = ` +[root] + ▸ +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations for multiple roots: 3: unmount B 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations for multiple roots: 4: unmount A 1`] = ``; + +exports[`Store collapseNodesByDefault:true should support mount and update operations: 1: mount 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations: 2: update 1`] = ` +[root] + ▸ +`; + +exports[`Store collapseNodesByDefault:true should support mount and update operations: 3: unmount 1`] = ``; diff --git a/src/__tests__/store-test.js b/src/__tests__/store-test.js index 82da076f0a..259984b74a 100644 --- a/src/__tests__/store-test.js +++ b/src/__tests__/store-test.js @@ -21,142 +21,324 @@ describe('Store', () => { TestUtils = require('react-dom/test-utils'); }); - it('should support mount and update operations', () => { - const Grandparent = ({ count }) => ( - - - - - ); - const Parent = ({ count }) => - new Array(count).fill(true).map((_, index) => ); - const Child = () =>
Hi!
; - - const container = document.createElement('div'); - - act(() => ReactDOM.render(, container)); - expect(store).toMatchSnapshot('1: mount'); - - act(() => ReactDOM.render(, container)); - expect(store).toMatchSnapshot('2: update'); - - act(() => ReactDOM.unmountComponentAtNode(container)); - expect(store).toMatchSnapshot('3: unmount'); + it('should not allow a root node to be collapsed', () => { + // TODO }); - it('should support mount and update operations for multiple roots', () => { - const Parent = ({ count }) => - new Array(count).fill(true).map((_, index) => ); - const Child = () =>
Hi!
; - - const containerA = document.createElement('div'); - const containerB = document.createElement('div'); - - act(() => { - ReactDOM.render(, containerA); - ReactDOM.render(, containerB); + describe('collapseNodesByDefault:false', () => { + beforeEach(() => { + store.collapseNodesByDefault = false; }); - expect(store).toMatchSnapshot('1: mount'); - act(() => { - ReactDOM.render(, containerA); - ReactDOM.render(, containerB); + it('should support mount and update operations', () => { + const Grandparent = ({ count }) => ( + + + + + ); + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; + + const container = document.createElement('div'); + + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('1: mount'); + + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('2: update'); + + act(() => ReactDOM.unmountComponentAtNode(container)); + expect(store).toMatchSnapshot('3: unmount'); }); - expect(store).toMatchSnapshot('2: update'); - act(() => ReactDOM.unmountComponentAtNode(containerB)); - expect(store).toMatchSnapshot('3: unmount B'); + it('should support mount and update operations for multiple roots', () => { + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; - act(() => ReactDOM.unmountComponentAtNode(containerA)); - expect(store).toMatchSnapshot('4: unmount A'); - }); + const containerA = document.createElement('div'); + const containerB = document.createElement('div'); - it('should filter DOM nodes from the store tree', () => { - const Grandparent = () => ( -
+ act(() => { + ReactDOM.render(, containerA); + ReactDOM.render(, containerB); + }); + expect(store).toMatchSnapshot('1: mount'); + + act(() => { + ReactDOM.render(, containerA); + ReactDOM.render(, containerB); + }); + expect(store).toMatchSnapshot('2: update'); + + act(() => ReactDOM.unmountComponentAtNode(containerB)); + expect(store).toMatchSnapshot('3: unmount B'); + + act(() => ReactDOM.unmountComponentAtNode(containerA)); + expect(store).toMatchSnapshot('4: unmount A'); + }); + + it('should filter DOM nodes from the store tree', () => { + const Grandparent = () => (
+
+ +
- -
- ); - const Parent = () => ( -
- -
- ); - const Child = () =>
Hi!
; + ); + const Parent = () => ( +
+ +
+ ); + const Child = () =>
Hi!
; - act(() => - ReactDOM.render(, document.createElement('div')) - ); - expect(store).toMatchSnapshot('1: mount'); - }); - - it('should display Suspense nodes properly in various states', () => { - const Loading = () =>
Loading...
; - const SuspendingComponent = () => { - throw new Promise(() => {}); - }; - const Component = () => { - return
Hello
; - }; - const Wrapper = ({ shouldSuspense }) => ( - - - }> - {shouldSuspense ? ( - - ) : ( - - )} - - - ); - - const container = document.createElement('div'); - act(() => ReactDOM.render(, container)); - expect(store).toMatchSnapshot('1: loading'); - - act(() => { - ReactDOM.render(, container); + act(() => + ReactDOM.render( + , + document.createElement('div') + ) + ); + expect(store).toMatchSnapshot('1: mount'); + }); + + it('should display Suspense nodes properly in various states', () => { + const Loading = () =>
Loading...
; + const SuspendingComponent = () => { + throw new Promise(() => {}); + }; + const Component = () => { + return
Hello
; + }; + const Wrapper = ({ shouldSuspense }) => ( + + + }> + {shouldSuspense ? ( + + ) : ( + + )} + + + ); + + const container = document.createElement('div'); + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('1: loading'); + + act(() => { + ReactDOM.render(, container); + }); + expect(store).toMatchSnapshot('2: resolved'); + }); + + it('should support collapsing parts of the tree', () => { + const Grandparent = ({ count }) => ( + + + + + ); + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; + + act(() => + ReactDOM.render( + , + document.createElement('div') + ) + ); + expect(store).toMatchSnapshot('1: mount'); + + const grandparentID = store.getElementIDAtIndex(0); + const parentOneID = store.getElementIDAtIndex(1); + const parentTwoID = store.getElementIDAtIndex(4); + + act(() => store.toggleIsCollapsed(parentOneID, true)); + expect(store).toMatchSnapshot('2: collapse first Parent'); + + act(() => store.toggleIsCollapsed(parentTwoID, true)); + expect(store).toMatchSnapshot('3: collapse second Parent'); + + act(() => store.toggleIsCollapsed(parentOneID, false)); + expect(store).toMatchSnapshot('4: expand first Parent'); + + act(() => store.toggleIsCollapsed(grandparentID, true)); + expect(store).toMatchSnapshot('5: collapse Grandparent'); + + act(() => store.toggleIsCollapsed(grandparentID, false)); + expect(store).toMatchSnapshot('6: expand Grandparent'); }); - expect(store).toMatchSnapshot('2: resolved'); }); - it('should support collapsing parts of the tree', () => { - const Grandparent = ({ count }) => ( - - - - - ); - const Parent = ({ count }) => - new Array(count).fill(true).map((_, index) => ); - const Child = () =>
Hi!
; + describe('collapseNodesByDefault:true', () => { + beforeEach(() => { + store.collapseNodesByDefault = true; + }); - act(() => - ReactDOM.render(, document.createElement('div')) - ); - expect(store).toMatchSnapshot('1: mount'); + it('should support mount and update operations', () => { + const Grandparent = ({ count }) => ( + + + + + ); + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; - const grandparentID = store.getElementIDAtIndex(0); - const parentOneID = store.getElementIDAtIndex(1); - const parentTwoID = store.getElementIDAtIndex(4); + const container = document.createElement('div'); - act(() => store.toggleIsCollapsed(parentOneID, true)); - expect(store).toMatchSnapshot('2: collapse first Parent'); + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('1: mount'); - act(() => store.toggleIsCollapsed(parentTwoID, true)); - expect(store).toMatchSnapshot('3: collapse second Parent'); + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('2: update'); - act(() => store.toggleIsCollapsed(parentOneID, false)); - expect(store).toMatchSnapshot('4: expand first Parent'); + act(() => ReactDOM.unmountComponentAtNode(container)); + expect(store).toMatchSnapshot('3: unmount'); + }); - act(() => store.toggleIsCollapsed(grandparentID, true)); - expect(store).toMatchSnapshot('5: collapse Grandparent'); + it('should support mount and update operations for multiple roots', () => { + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; - act(() => store.toggleIsCollapsed(grandparentID, false)); - expect(store).toMatchSnapshot('6: expand Grandparent'); + const containerA = document.createElement('div'); + const containerB = document.createElement('div'); + + act(() => { + ReactDOM.render(, containerA); + ReactDOM.render(, containerB); + }); + expect(store).toMatchSnapshot('1: mount'); + + act(() => { + ReactDOM.render(, containerA); + ReactDOM.render(, containerB); + }); + expect(store).toMatchSnapshot('2: update'); + + act(() => ReactDOM.unmountComponentAtNode(containerB)); + expect(store).toMatchSnapshot('3: unmount B'); + + act(() => ReactDOM.unmountComponentAtNode(containerA)); + expect(store).toMatchSnapshot('4: unmount A'); + }); + + it('should filter DOM nodes from the store tree', () => { + const Grandparent = () => ( +
+
+ +
+ +
+ ); + const Parent = () => ( +
+ +
+ ); + const Child = () =>
Hi!
; + + act(() => + ReactDOM.render( + , + document.createElement('div') + ) + ); + expect(store).toMatchSnapshot('1: mount'); + + act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false)); + expect(store).toMatchSnapshot('2: expand Grandparent'); + + act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false)); + expect(store).toMatchSnapshot('3: expand Parent'); + }); + + it('should display Suspense nodes properly in various states', () => { + const Loading = () =>
Loading...
; + const SuspendingComponent = () => { + throw new Promise(() => {}); + }; + const Component = () => { + return
Hello
; + }; + const Wrapper = ({ shouldSuspense }) => ( + + + }> + {shouldSuspense ? ( + + ) : ( + + )} + + + ); + + const container = document.createElement('div'); + act(() => ReactDOM.render(, container)); + expect(store).toMatchSnapshot('1: loading'); + + // This test isn't meaningful unless we expand the suspended tree + act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false)); + act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(2), false)); + expect(store).toMatchSnapshot('2: expand Wrapper and Suspense'); + + act(() => { + ReactDOM.render(, container); + }); + expect(store).toMatchSnapshot('2: resolved'); + }); + + it('should support collapsing parts of the tree', () => { + const Grandparent = ({ count }) => ( + + + + + ); + const Parent = ({ count }) => + new Array(count).fill(true).map((_, index) => ); + const Child = () =>
Hi!
; + + act(() => + ReactDOM.render( + , + document.createElement('div') + ) + ); + expect(store).toMatchSnapshot('1: mount'); + + const grandparentID = store.getElementIDAtIndex(0); + + act(() => store.toggleIsCollapsed(grandparentID, false)); + expect(store).toMatchSnapshot('2: expand Grandparent'); + + const parentOneID = store.getElementIDAtIndex(1); + const parentTwoID = store.getElementIDAtIndex(2); + + act(() => store.toggleIsCollapsed(parentOneID, false)); + expect(store).toMatchSnapshot('3: expand first Parent'); + + act(() => store.toggleIsCollapsed(parentTwoID, false)); + expect(store).toMatchSnapshot('4: expand second Parent'); + + act(() => store.toggleIsCollapsed(parentOneID, true)); + expect(store).toMatchSnapshot('5: collapse first Parent'); + + act(() => store.toggleIsCollapsed(parentTwoID, true)); + expect(store).toMatchSnapshot('6: collapse second Parent'); + + act(() => store.toggleIsCollapsed(grandparentID, true)); + expect(store).toMatchSnapshot('7: collapse Grandparent'); + }); }); }); diff --git a/src/__tests__/storeStress-test.js b/src/__tests__/storeStress-test.js index ae13007cca..12e111adf5 100644 --- a/src/__tests__/storeStress-test.js +++ b/src/__tests__/storeStress-test.js @@ -18,6 +18,7 @@ describe('StoreStress', () => { beforeEach(() => { bridge = global.bridge; store = global.store; + store.collapseNodesByDefault = false; React = require('react'); ReactDOM = require('react-dom'); diff --git a/src/devtools/store.js b/src/devtools/store.js index 63d87f2544..759e6bfc17 100644 --- a/src/devtools/store.js +++ b/src/devtools/store.js @@ -36,6 +36,8 @@ const debug = (methodName, ...args) => { const LOCAL_STORAGE_CAPTURE_SCREENSHOTS_KEY = 'React::DevTools::captureScreenshots'; +const LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY = + 'React::DevTools::collapseNodesByDefault'; const THROTTLE_CAPTURE_SCREENSHOT_DURATION = 500; @@ -61,6 +63,9 @@ export default class Store extends EventEmitter { _captureScreenshots: boolean = false; + // Should new nodes be collapsed by default when added to the tree? + _collapseNodesByDefault: boolean = true; + // At least one of the injected renderers contains (DEV only) owner metadata. _hasOwnerMetadata: boolean = false; @@ -123,6 +128,11 @@ export default class Store extends EventEmitter { debug('constructor', 'subscribing to Bridge'); } + // Default this setting to true unless otherwise specified. + this._collapseNodesByDefault = + localStorage.getItem(LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY) !== + 'false'; + if (config != null) { const { isProfiling, @@ -178,6 +188,20 @@ export default class Store extends EventEmitter { this.emit('captureScreenshots'); } + get collapseNodesByDefault(): boolean { + return this._collapseNodesByDefault; + } + set collapseNodesByDefault(value: boolean): void { + this._collapseNodesByDefault = value; + + localStorage.setItem( + LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY, + value ? 'true' : 'false' + ); + + this.emit('collapseNodesByDefault'); + } + get hasOwnerMetadata(): boolean { return this._hasOwnerMetadata; } @@ -552,7 +576,7 @@ export default class Store extends EventEmitter { depth: -1, displayName: null, id, - isCollapsed: false, + isCollapsed: false, // Never collapse roots key: null, ownerID: 0, parentID: 0, @@ -601,7 +625,7 @@ export default class Store extends EventEmitter { depth: parentElement.depth + 1, displayName, id, - isCollapsed: false, + isCollapsed: this._collapseNodesByDefault, key, ownerID, parentID: parentElement.id, diff --git a/src/devtools/views/Settings/Settings.css b/src/devtools/views/Settings/Settings.css index 01afd5a23d..7dc9755ca2 100644 --- a/src/devtools/views/Settings/Settings.css +++ b/src/devtools/views/Settings/Settings.css @@ -14,13 +14,14 @@ .Section { display: flex; - flex-direction: column; + flex-direction: row; + align-items: center; margin-right: 0.5rem; margin-bottom: 0.5rem; } .Header { - margin-bottom: 0.5rem; + margin-right: 0.5rem; font-size: var(--font-size-sans-large); } diff --git a/src/devtools/views/Settings/Settings.js b/src/devtools/views/Settings/Settings.js index 1725aa87d2..1c1ed43bcf 100644 --- a/src/devtools/views/Settings/Settings.js +++ b/src/devtools/views/Settings/Settings.js @@ -15,7 +15,7 @@ function Settings(_: {||}) { SettingsContext ); - const subscription = useMemo( + const captureScreenshotsSubscription = useMemo( () => ({ getCurrentValue: () => store.captureScreenshots, subscribe: (callback: Function) => { @@ -25,7 +25,23 @@ function Settings(_: {||}) { }), [store] ); - const captureScreenshots = useSubscription(subscription); + const captureScreenshots = useSubscription( + captureScreenshotsSubscription + ); + + const collapseNodesByDefaultSubscription = useMemo( + () => ({ + getCurrentValue: () => store.collapseNodesByDefault, + subscribe: (callback: Function) => { + store.addListener('collapseNodesByDefault', callback); + return () => store.removeListener('collapseNodesByDefault', callback); + }, + }), + [store] + ); + const collapseNodesByDefault = useSubscription( + collapseNodesByDefaultSubscription + ); const updateDisplayDensity = useCallback( ({ currentTarget }) => { @@ -47,6 +63,12 @@ function Settings(_: {||}) { }, [store] ); + const updateCollapseNodesByDefault = useCallback( + ({ currentTarget }) => { + store.collapseNodesByDefault = currentTarget.checked; + }, + [store] + ); return (
@@ -85,6 +107,17 @@ function Settings(_: {||}) {
+
+
Components tree
+ +
Display density
@@ -111,22 +144,24 @@ function Settings(_: {||}) {
{store.supportsCaptureScreenshots && ( -
-
Profiler
- +
+
+
Profiler
+ +
+ {captureScreenshots && ( +
+ Screenshots will be throttled in order to reduce the negative + impact on performance. +
+ )}
)}