Improve Bridge Flow types (#352)
* Updated local fork of react-window * Updated Fow 97 -> 103 * Lint ignore NPM dist * Improved Bridge Flow types
This commit is contained in:
parent
39ad101ea2
commit
4b34a77d29
|
@ -4,6 +4,7 @@ shells/browser/chrome/build
|
||||||
shells/browser/firefox/build
|
shells/browser/firefox/build
|
||||||
shells/browser/shared/build
|
shells/browser/shared/build
|
||||||
shells/dev/dist
|
shells/dev/dist
|
||||||
|
packages/react-devtools-core/dist
|
||||||
vendor
|
vendor
|
||||||
*.js.snap
|
*.js.snap
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
"test:chrome": "node ./shells/browser/chrome/test",
|
"test:chrome": "node ./shells/browser/chrome/test",
|
||||||
"test:firefox": "node ./shells/browser/firefox/test",
|
"test:firefox": "node ./shells/browser/firefox/test",
|
||||||
"test:standalone": "cd packages/react-devtools && yarn start",
|
"test:standalone": "cd packages/react-devtools && yarn start",
|
||||||
"typecheck": "flow check"
|
"typecheck": "flow check --show-all-errors"
|
||||||
},
|
},
|
||||||
"devEngines": {
|
"devEngines": {
|
||||||
"node": "10.x || 11.x"
|
"node": "10.x || 11.x"
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
"fbjs": "0.5.1",
|
"fbjs": "0.5.1",
|
||||||
"fbjs-scripts": "0.7.0",
|
"fbjs-scripts": "0.7.0",
|
||||||
"firefox-profile": "^1.0.2",
|
"firefox-profile": "^1.0.2",
|
||||||
"flow-bin": "^0.97.0",
|
"flow-bin": "^0.103.0",
|
||||||
"fs-extra": "^3.0.1",
|
"fs-extra": "^3.0.1",
|
||||||
"gh-pages": "^1.0.0",
|
"gh-pages": "^1.0.0",
|
||||||
"html2canvas": "^1.0.0-alpha.12",
|
"html2canvas": "^1.0.0-alpha.12",
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { __DEBUG__ } from 'src/constants';
|
||||||
import setupNativeStyleEditor from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
|
import setupNativeStyleEditor from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
|
||||||
import { getDefaultComponentFilters } from 'src/utils';
|
import { getDefaultComponentFilters } from 'src/utils';
|
||||||
|
|
||||||
|
import type { BackendBridge } from 'src/bridge';
|
||||||
import type { ComponentFilter } from 'src/types';
|
import type { ComponentFilter } from 'src/types';
|
||||||
import type { DevToolsHook } from 'src/backend/types';
|
import type { DevToolsHook } from 'src/backend/types';
|
||||||
import type { ResolveNativeStyle } from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
|
import type { ResolveNativeStyle } from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
|
||||||
|
@ -64,7 +65,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bridge: Bridge | null = null;
|
let bridge: BackendBridge | null = null;
|
||||||
|
|
||||||
const messageListeners = [];
|
const messageListeners = [];
|
||||||
const uri = 'ws://' + host + ':' + port;
|
const uri = 'ws://' + host + ':' + port;
|
||||||
|
|
|
@ -17,6 +17,7 @@ import DevTools from 'src/devtools/views/DevTools';
|
||||||
import launchEditor from './launchEditor';
|
import launchEditor from './launchEditor';
|
||||||
import { __DEBUG__ } from 'src/constants';
|
import { __DEBUG__ } from 'src/constants';
|
||||||
|
|
||||||
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type { InspectedElement } from 'src/devtools/views/Components/types';
|
import type { InspectedElement } from 'src/devtools/views/Components/types';
|
||||||
|
|
||||||
installHook(window);
|
installHook(window);
|
||||||
|
@ -46,7 +47,7 @@ function setStatusListener(value: StatusListener) {
|
||||||
return DevtoolsUI;
|
return DevtoolsUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bridge: Bridge | null = null;
|
let bridge: FrontendBridge | null = null;
|
||||||
let store: Store | null = null;
|
let store: Store | null = null;
|
||||||
let root = null;
|
let root = null;
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ function reload() {
|
||||||
root = createRoot(node);
|
root = createRoot(node);
|
||||||
root.render(
|
root.render(
|
||||||
createElement(DevTools, {
|
createElement(DevTools, {
|
||||||
bridge: ((bridge: any): Bridge),
|
bridge: ((bridge: any): FrontendBridge),
|
||||||
showTabBar: true,
|
showTabBar: true,
|
||||||
store: ((store: any): Store),
|
store: ((store: any): Store),
|
||||||
warnIfLegacyBackendDetected: true,
|
warnIfLegacyBackendDetected: true,
|
||||||
|
@ -166,7 +167,7 @@ function initialize(socket: WebSocket) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
((bridge: any): Bridge).addListener('shutdown', () => {
|
((bridge: any): FrontendBridge).addListener('shutdown', () => {
|
||||||
socket.close();
|
socket.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Suspense, useState } from 'react';
|
import React, { Fragment, Suspense, useState } from 'react';
|
||||||
|
|
||||||
function SuspenseTree() {
|
function SuspenseTree() {
|
||||||
return (
|
return (
|
||||||
<>
|
<Fragment>
|
||||||
<h1>Suspense</h1>
|
<h1>Suspense</h1>
|
||||||
<h4>Primary to Fallback Cycle</h4>
|
<h4>Primary to Fallback Cycle</h4>
|
||||||
<PrimaryFallbackTest initialSuspend={false} />
|
<PrimaryFallbackTest initialSuspend={false} />
|
||||||
<h4>Fallback to Primary Cycle</h4>
|
<h4>Fallback to Primary Cycle</h4>
|
||||||
<PrimaryFallbackTest initialSuspend={true} />
|
<PrimaryFallbackTest initialSuspend={true} />
|
||||||
<NestedSuspenseTest />
|
<NestedSuspenseTest />
|
||||||
</>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ function PrimaryFallbackTest({ initialSuspend }) {
|
||||||
const fallbackStep = useTestSequence('fallback', Fallback1, Fallback2);
|
const fallbackStep = useTestSequence('fallback', Fallback1, Fallback2);
|
||||||
const primaryStep = useTestSequence('primary', Primary1, Primary2);
|
const primaryStep = useTestSequence('primary', Primary1, Primary2);
|
||||||
return (
|
return (
|
||||||
<>
|
<Fragment>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
checked={suspend}
|
checked={suspend}
|
||||||
|
@ -33,7 +33,7 @@ function PrimaryFallbackTest({ initialSuspend }) {
|
||||||
<Suspense fallback={fallbackStep}>
|
<Suspense fallback={fallbackStep}>
|
||||||
{suspend ? <Never /> : primaryStep}
|
{suspend ? <Never /> : primaryStep}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,32 +45,32 @@ function useTestSequence(label, T1, T2) {
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
let allSteps = [
|
let allSteps = [
|
||||||
<>{next}</>,
|
<Fragment>{next}</Fragment>,
|
||||||
<>
|
<Fragment>
|
||||||
{next} <T1 prop={step}>mount</T1>
|
{next} <T1 prop={step}>mount</T1>
|
||||||
</>,
|
</Fragment>,
|
||||||
<>
|
<Fragment>
|
||||||
{next} <T1 prop={step}>update</T1>
|
{next} <T1 prop={step}>update</T1>
|
||||||
</>,
|
</Fragment>,
|
||||||
<>
|
<Fragment>
|
||||||
{next} <T2 prop={step}>several</T2> <T1 prop={step}>different</T1>{' '}
|
{next} <T2 prop={step}>several</T2> <T1 prop={step}>different</T1>{' '}
|
||||||
<T2 prop={step}>children</T2>
|
<T2 prop={step}>children</T2>
|
||||||
</>,
|
</Fragment>,
|
||||||
<>
|
<Fragment>
|
||||||
{next} <T2 prop={step}>goodbye</T2>
|
{next} <T2 prop={step}>goodbye</T2>
|
||||||
</>,
|
</Fragment>,
|
||||||
];
|
];
|
||||||
return allSteps[step];
|
return allSteps[step];
|
||||||
}
|
}
|
||||||
|
|
||||||
function NestedSuspenseTest() {
|
function NestedSuspenseTest() {
|
||||||
return (
|
return (
|
||||||
<>
|
<Fragment>
|
||||||
<h3>Nested Suspense</h3>
|
<h3>Nested Suspense</h3>
|
||||||
<Suspense fallback={<Fallback1>Loading outer</Fallback1>}>
|
<Suspense fallback={<Fallback1>Loading outer</Fallback1>}>
|
||||||
<Parent />
|
<Parent />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,19 +118,19 @@ function Never() {
|
||||||
throw new Promise(resolve => {});
|
throw new Promise(resolve => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function Fallback1({ prop, ...rest }) {
|
function Fallback1({ prop, ...rest }: any) {
|
||||||
return <span {...rest} />;
|
return <span {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Fallback2({ prop, ...rest }) {
|
function Fallback2({ prop, ...rest }: any) {
|
||||||
return <span {...rest} />;
|
return <span {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Primary1({ prop, ...rest }) {
|
function Primary1({ prop, ...rest }: any) {
|
||||||
return <span {...rest} />;
|
return <span {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Primary2({ prop, ...rest }) {
|
function Primary2({ prop, ...rest }: any) {
|
||||||
return <span {...rest} />;
|
return <span {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ describe('Bridge', () => {
|
||||||
const bridge = new Bridge(wall);
|
const bridge = new Bridge(wall);
|
||||||
|
|
||||||
// Check that we're wired up correctly.
|
// Check that we're wired up correctly.
|
||||||
bridge.send('init');
|
bridge.send('reloadAppForProfiling');
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(wall.send).toHaveBeenCalledWith('init', undefined, undefined);
|
expect(wall.send).toHaveBeenCalledWith('reloadAppForProfiling');
|
||||||
|
|
||||||
// Should flush pending messages and then shut down.
|
// Should flush pending messages and then shut down.
|
||||||
wall.send.mockClear();
|
wall.send.mockClear();
|
||||||
|
@ -25,9 +25,9 @@ describe('Bridge', () => {
|
||||||
bridge.send('update', '2');
|
bridge.send('update', '2');
|
||||||
bridge.shutdown();
|
bridge.shutdown();
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(wall.send).toHaveBeenCalledWith('update', '1', undefined);
|
expect(wall.send).toHaveBeenCalledWith('update', '1');
|
||||||
expect(wall.send).toHaveBeenCalledWith('update', '2', undefined);
|
expect(wall.send).toHaveBeenCalledWith('update', '2');
|
||||||
expect(wall.send).toHaveBeenCalledWith('shutdown', undefined, undefined);
|
expect(wall.send).toHaveBeenCalledWith('shutdown');
|
||||||
|
|
||||||
// Verify that the Bridge doesn't send messages after shutdown.
|
// Verify that the Bridge doesn't send messages after shutdown.
|
||||||
spyOn(console, 'warn');
|
spyOn(console, 'warn');
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
import type { GetInspectedElementPath } from 'src/devtools/views/Components/InspectedElementContext';
|
import type { GetInspectedElementPath } from 'src/devtools/views/Components/InspectedElementContext';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
|
||||||
describe('InspectedElementContext', () => {
|
describe('InspectedElementContext', () => {
|
||||||
let React;
|
let React;
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let TestRenderer: ReactTestRenderer;
|
let TestRenderer: ReactTestRenderer;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let meta;
|
let meta;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import type { InspectedElementPayload } from 'src/backend/types';
|
import type { InspectedElementPayload } from 'src/backend/types';
|
||||||
import type { DehydratedData } from 'src/devtools/views/Components/types';
|
import type { DehydratedData } from 'src/devtools/views/Components/types';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
|
||||||
describe('InspectedElementContext', () => {
|
describe('InspectedElementContext', () => {
|
||||||
|
@ -10,7 +10,7 @@ describe('InspectedElementContext', () => {
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let hydrate;
|
let hydrate;
|
||||||
let meta;
|
let meta;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
|
|
||||||
const act = (callback: Function) => {
|
const act = (callback: Function) => {
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
import type { Element } from 'src/devtools/views/Components/types';
|
import type { Element } from 'src/devtools/views/Components/types';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
|
||||||
describe('OwnersListContext', () => {
|
describe('OwnersListContext', () => {
|
||||||
let React;
|
let React;
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let TestRenderer: ReactTestRenderer;
|
let TestRenderer: ReactTestRenderer;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type { Context } from 'src/devtools/views/Profiler/ProfilerContext';
|
import type { Context } from 'src/devtools/views/Profiler/ProfilerContext';
|
||||||
import type { DispatcherContext } from 'src/devtools/views/Components/TreeContext';
|
import type { DispatcherContext } from 'src/devtools/views/Components/TreeContext';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
@ -10,7 +10,7 @@ describe('ProfilerContext', () => {
|
||||||
let React;
|
let React;
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let TestRenderer: ReactTestRenderer;
|
let TestRenderer: ReactTestRenderer;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
|
||||||
describe('ProfilingCache', () => {
|
describe('ProfilingCache', () => {
|
||||||
|
@ -11,7 +11,7 @@ describe('ProfilingCache', () => {
|
||||||
let Scheduler;
|
let Scheduler;
|
||||||
let SchedulerTracing;
|
let SchedulerTracing;
|
||||||
let TestRenderer: ReactTestRenderer;
|
let TestRenderer: ReactTestRenderer;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ describe('profiling charts', () => {
|
||||||
|
|
||||||
describe('flamegraph chart', () => {
|
describe('flamegraph chart', () => {
|
||||||
it('should contain valid data', () => {
|
it('should contain valid data', () => {
|
||||||
const Parent = ({ count }) => {
|
const Parent = (_: {||}) => {
|
||||||
Scheduler.unstable_advanceTime(10);
|
Scheduler.unstable_advanceTime(10);
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@ -105,7 +105,7 @@ describe('profiling charts', () => {
|
||||||
|
|
||||||
describe('ranked chart', () => {
|
describe('ranked chart', () => {
|
||||||
it('should contain valid data', () => {
|
it('should contain valid data', () => {
|
||||||
const Parent = ({ count }) => {
|
const Parent = (_: {||}) => {
|
||||||
Scheduler.unstable_advanceTime(10);
|
Scheduler.unstable_advanceTime(10);
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@ -177,7 +177,7 @@ describe('profiling charts', () => {
|
||||||
|
|
||||||
describe('interactions', () => {
|
describe('interactions', () => {
|
||||||
it('should contain valid data', () => {
|
it('should contain valid data', () => {
|
||||||
const Parent = ({ count }) => {
|
const Parent = (_: {||}) => {
|
||||||
Scheduler.unstable_advanceTime(10);
|
Scheduler.unstable_advanceTime(10);
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
import type { BackendBridge, FrontendBridge } from 'src/bridge';
|
||||||
|
|
||||||
const env = jasmine.getEnv();
|
const env = jasmine.getEnv();
|
||||||
env.beforeEach(() => {
|
env.beforeEach(() => {
|
||||||
// These files should be required (and re-reuired) before each test,
|
// These files should be required (and re-reuired) before each test,
|
||||||
|
@ -51,13 +53,13 @@ env.beforeEach(() => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const agent = new Agent(bridge);
|
const agent = new Agent(((bridge: any): BackendBridge));
|
||||||
|
|
||||||
const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||||
|
|
||||||
initBackend(hook, agent, global);
|
initBackend(hook, agent, global);
|
||||||
|
|
||||||
const store = new Store(bridge);
|
const store = new Store(((bridge: any): FrontendBridge));
|
||||||
|
|
||||||
global.agent = agent;
|
global.agent = agent;
|
||||||
global.bridge = bridge;
|
global.bridge = bridge;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
|
|
||||||
describe('Store component filters', () => {
|
describe('Store component filters', () => {
|
||||||
|
@ -8,7 +8,7 @@ describe('Store component filters', () => {
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let TestUtils;
|
let TestUtils;
|
||||||
let Types;
|
let Types;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
import type {
|
import type {
|
||||||
DispatcherContext,
|
DispatcherContext,
|
||||||
|
@ -12,7 +12,7 @@ describe('TreeListContext', () => {
|
||||||
let React;
|
let React;
|
||||||
let ReactDOM;
|
let ReactDOM;
|
||||||
let TestRenderer: ReactTestRenderer;
|
let TestRenderer: ReactTestRenderer;
|
||||||
let bridge: Bridge;
|
let bridge: FrontendBridge;
|
||||||
let store: Store;
|
let store: Store;
|
||||||
let utils;
|
let utils;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import typeof ReactTestRenderer from 'react-test-renderer';
|
import typeof ReactTestRenderer from 'react-test-renderer';
|
||||||
|
|
||||||
import type Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type Store from 'src/devtools/store';
|
import type Store from 'src/devtools/store';
|
||||||
import type { ProfilingDataFrontend } from 'src/devtools/views/Profiler/types';
|
import type { ProfilingDataFrontend } from 'src/devtools/views/Profiler/types';
|
||||||
import type { ElementType } from 'src/types';
|
import type { ElementType } from 'src/types';
|
||||||
|
@ -161,7 +161,7 @@ export function requireTestRenderer(): ReactTestRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exportImportHelper(bridge: Bridge, store: Store): void {
|
export function exportImportHelper(bridge: FrontendBridge, store: Store): void {
|
||||||
const { act } = require('./utils');
|
const { act } = require('./utils');
|
||||||
const {
|
const {
|
||||||
prepareProfilingDataExport,
|
prepareProfilingDataExport,
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import Agent from 'src/backend/agent';
|
import Agent from 'src/backend/agent';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import resolveBoxStyle from './resolveBoxStyle';
|
import resolveBoxStyle from './resolveBoxStyle';
|
||||||
|
|
||||||
|
import type { BackendBridge } from 'src/bridge';
|
||||||
import type { RendererID } from '../types';
|
import type { RendererID } from '../types';
|
||||||
import type { StyleAndLayout } from './types';
|
import type { StyleAndLayout } from './types';
|
||||||
|
|
||||||
export type ResolveNativeStyle = (stylesheetID: number) => ?Object;
|
export type ResolveNativeStyle = (stylesheetID: number) => ?Object;
|
||||||
|
|
||||||
export default function setupNativeStyleEditor(
|
export default function setupNativeStyleEditor(
|
||||||
bridge: Bridge,
|
bridge: BackendBridge,
|
||||||
agent: Agent,
|
agent: Agent,
|
||||||
resolveNativeStyle: ResolveNativeStyle,
|
resolveNativeStyle: ResolveNativeStyle,
|
||||||
validAttributes?: $ReadOnlyArray<string> | null
|
validAttributes?: $ReadOnlyArray<string> | null
|
||||||
|
@ -81,7 +81,7 @@ const componentIDToStyleOverrides: Map<number, Object> = new Map();
|
||||||
|
|
||||||
function measureStyle(
|
function measureStyle(
|
||||||
agent: Agent,
|
agent: Agent,
|
||||||
bridge: Bridge,
|
bridge: BackendBridge,
|
||||||
resolveNativeStyle: ResolveNativeStyle,
|
resolveNativeStyle: ResolveNativeStyle,
|
||||||
id: number,
|
id: number,
|
||||||
rendererID: RendererID
|
rendererID: RendererID
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import {
|
import {
|
||||||
SESSION_STORAGE_LAST_SELECTION_KEY,
|
SESSION_STORAGE_LAST_SELECTION_KEY,
|
||||||
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
|
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
|
||||||
|
@ -17,6 +16,7 @@ import {
|
||||||
import setupHighlighter from './views/Highlighter';
|
import setupHighlighter from './views/Highlighter';
|
||||||
import { patch as patchConsole, unpatch as unpatchConsole } from './console';
|
import { patch as patchConsole, unpatch as unpatchConsole } from './console';
|
||||||
|
|
||||||
|
import type { BackendBridge } from 'src/bridge';
|
||||||
import type {
|
import type {
|
||||||
InstanceAndStyle,
|
InstanceAndStyle,
|
||||||
NativeType,
|
NativeType,
|
||||||
|
@ -81,14 +81,14 @@ export default class Agent extends EventEmitter<{|
|
||||||
showNativeHighlight: [NativeType],
|
showNativeHighlight: [NativeType],
|
||||||
shutdown: [],
|
shutdown: [],
|
||||||
|}> {
|
|}> {
|
||||||
_bridge: Bridge;
|
_bridge: BackendBridge;
|
||||||
_isProfiling: boolean = false;
|
_isProfiling: boolean = false;
|
||||||
_recordChangeDescriptions: boolean = false;
|
_recordChangeDescriptions: boolean = false;
|
||||||
_rendererInterfaces: { [key: RendererID]: RendererInterface } = {};
|
_rendererInterfaces: { [key: RendererID]: RendererInterface } = {};
|
||||||
_persistedSelection: PersistedSelection | null = null;
|
_persistedSelection: PersistedSelection | null = null;
|
||||||
_persistedSelectionMatch: PathMatch | null = null;
|
_persistedSelectionMatch: PathMatch | null = null;
|
||||||
|
|
||||||
constructor(bridge: Bridge) {
|
constructor(bridge: BackendBridge) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -259,7 +259,7 @@ export default class Agent extends EventEmitter<{|
|
||||||
dataURL: string,
|
dataURL: string,
|
||||||
rootID: number,
|
rootID: number,
|
||||||
|}) => {
|
|}) => {
|
||||||
this._bridge.send('screenshotCaptured', { commitIndex, dataURL });
|
this._bridge.send('screenshotCaptured', { commitIndex, dataURL, rootID });
|
||||||
};
|
};
|
||||||
|
|
||||||
selectElement = ({ id, rendererID }: ElementAndRendererID) => {
|
selectElement = ({ id, rendererID }: ElementAndRendererID) => {
|
||||||
|
|
|
@ -11,6 +11,8 @@ type Rect = {
|
||||||
width: number,
|
width: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Box = {| top: number, left: number, width: number, height: number |};
|
||||||
|
|
||||||
// Note that the Overlay components are not affected by the active Theme,
|
// Note that the Overlay components are not affected by the active Theme,
|
||||||
// because they highlight elements in the main Chrome window (outside of devtools).
|
// because they highlight elements in the main Chrome window (outside of devtools).
|
||||||
// The colors below were chosen to roughly match those used by Chrome devtools.
|
// The colors below were chosen to roughly match those used by Chrome devtools.
|
||||||
|
@ -21,7 +23,7 @@ class OverlayRect {
|
||||||
padding: HTMLElement;
|
padding: HTMLElement;
|
||||||
content: HTMLElement;
|
content: HTMLElement;
|
||||||
|
|
||||||
constructor(doc, container) {
|
constructor(doc: Document, container: HTMLElement) {
|
||||||
this.node = doc.createElement('div');
|
this.node = doc.createElement('div');
|
||||||
this.border = doc.createElement('div');
|
this.border = doc.createElement('div');
|
||||||
this.padding = doc.createElement('div');
|
this.padding = doc.createElement('div');
|
||||||
|
@ -51,7 +53,7 @@ class OverlayRect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(box, dims) {
|
update(box: Rect, dims: any) {
|
||||||
boxWrap(dims, 'margin', this.node);
|
boxWrap(dims, 'margin', this.node);
|
||||||
boxWrap(dims, 'border', this.border);
|
boxWrap(dims, 'border', this.border);
|
||||||
boxWrap(dims, 'padding', this.padding);
|
boxWrap(dims, 'padding', this.padding);
|
||||||
|
@ -85,7 +87,7 @@ class OverlayTip {
|
||||||
nameSpan: HTMLElement;
|
nameSpan: HTMLElement;
|
||||||
dimSpan: HTMLElement;
|
dimSpan: HTMLElement;
|
||||||
|
|
||||||
constructor(doc, container) {
|
constructor(doc: Document, container: HTMLElement) {
|
||||||
this.tip = doc.createElement('div');
|
this.tip = doc.createElement('div');
|
||||||
assign(this.tip.style, {
|
assign(this.tip.style, {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -126,13 +128,13 @@ class OverlayTip {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateText(name, width, height) {
|
updateText(name: string, width: number, height: number) {
|
||||||
this.nameSpan.textContent = name;
|
this.nameSpan.textContent = name;
|
||||||
this.dimSpan.textContent =
|
this.dimSpan.textContent =
|
||||||
Math.round(width) + 'px × ' + Math.round(height) + 'px';
|
Math.round(width) + 'px × ' + Math.round(height) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePosition(dims, bounds) {
|
updatePosition(dims: Box, bounds: Box) {
|
||||||
const tipRect = this.tip.getBoundingClientRect();
|
const tipRect = this.tip.getBoundingClientRect();
|
||||||
const tipPos = findTipPos(dims, bounds, {
|
const tipPos = findTipPos(dims, bounds, {
|
||||||
width: tipRect.width,
|
width: tipRect.width,
|
||||||
|
@ -247,6 +249,7 @@ export default class Overlay {
|
||||||
this.tipBoundsWindow.document.documentElement,
|
this.tipBoundsWindow.document.documentElement,
|
||||||
this.window
|
this.window
|
||||||
);
|
);
|
||||||
|
|
||||||
this.tip.updatePosition(
|
this.tip.updatePosition(
|
||||||
{
|
{
|
||||||
top: outerBox.top,
|
top: outerBox.top,
|
||||||
|
|
|
@ -2,11 +2,15 @@
|
||||||
|
|
||||||
import memoize from 'memoize-one';
|
import memoize from 'memoize-one';
|
||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import Agent from 'src/backend/agent';
|
import Agent from 'src/backend/agent';
|
||||||
import { hideOverlay, showOverlay } from './Highlighter';
|
import { hideOverlay, showOverlay } from './Highlighter';
|
||||||
|
|
||||||
export default function setup(bridge: Bridge, agent: Agent): void {
|
import type { BackendBridge } from 'src/bridge';
|
||||||
|
|
||||||
|
export default function setupHighlighter(
|
||||||
|
bridge: BackendBridge,
|
||||||
|
agent: Agent
|
||||||
|
): void {
|
||||||
bridge.addListener(
|
bridge.addListener(
|
||||||
'clearNativeElementHighlight',
|
'clearNativeElementHighlight',
|
||||||
clearNativeElementHighlight
|
clearNativeElementHighlight
|
||||||
|
@ -50,7 +54,7 @@ export default function setup(bridge: Bridge, agent: Agent): void {
|
||||||
rendererID,
|
rendererID,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
}: {
|
}: {
|
||||||
displayName: string,
|
displayName: string | null,
|
||||||
hideAfterTimeout: boolean,
|
hideAfterTimeout: boolean,
|
||||||
id: number,
|
id: number,
|
||||||
openNativeElementsPanel: boolean,
|
openNativeElementsPanel: boolean,
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Message = {|
|
||||||
|
|
||||||
type HighlightElementInDOM = {|
|
type HighlightElementInDOM = {|
|
||||||
...ElementAndRendererID,
|
...ElementAndRendererID,
|
||||||
displayName: string,
|
displayName: string | null,
|
||||||
hideAfterTimeout: boolean,
|
hideAfterTimeout: boolean,
|
||||||
openNativeElementsPanel: boolean,
|
openNativeElementsPanel: boolean,
|
||||||
scrollIntoView: boolean,
|
scrollIntoView: boolean,
|
||||||
|
@ -62,33 +62,48 @@ type NativeStyleEditor_SetValueParams = {|
|
||||||
value: string,
|
value: string,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
export default class Bridge extends EventEmitter<{|
|
type BackendEvents = {|
|
||||||
|
captureScreenshot: [{| commitIndex: number, rootID: number |}],
|
||||||
|
inspectedElement: [InspectedElementPayload],
|
||||||
|
isBackendStorageAPISupported: [boolean],
|
||||||
|
operations: [Array<number>],
|
||||||
|
ownersList: [OwnersList],
|
||||||
|
overrideComponentFilters: [Array<ComponentFilter>],
|
||||||
|
profilingData: [ProfilingDataBackend],
|
||||||
|
profilingStatus: [boolean],
|
||||||
|
reloadAppForProfiling: [],
|
||||||
|
screenshotCaptured: [
|
||||||
|
{| commitIndex: number, dataURL: string, rootID: number |},
|
||||||
|
],
|
||||||
|
selectFiber: [number],
|
||||||
|
shutdown: [],
|
||||||
|
stopInspectingNative: [boolean],
|
||||||
|
syncSelectionFromNativeElementsPanel: [],
|
||||||
|
syncSelectionToNativeElementsPanel: [],
|
||||||
|
|
||||||
|
// React Native style editor plug-in.
|
||||||
|
isNativeStyleEditorSupported: [
|
||||||
|
{| isSupported: boolean, validAttributes: ?$ReadOnlyArray<string> |},
|
||||||
|
],
|
||||||
|
NativeStyleEditor_styleAndLayout: [StyleAndLayoutPayload],
|
||||||
|
|};
|
||||||
|
|
||||||
|
type FrontendEvents = {|
|
||||||
captureScreenshot: [{| commitIndex: number, rootID: number |}],
|
captureScreenshot: [{| commitIndex: number, rootID: number |}],
|
||||||
clearNativeElementHighlight: [],
|
clearNativeElementHighlight: [],
|
||||||
getOwnersList: [ElementAndRendererID],
|
getOwnersList: [ElementAndRendererID],
|
||||||
getProfilingData: [{| rendererID: RendererID |}],
|
getProfilingData: [{| rendererID: RendererID |}],
|
||||||
getProfilingStatus: [],
|
getProfilingStatus: [],
|
||||||
highlightNativeElement: [HighlightElementInDOM],
|
highlightNativeElement: [HighlightElementInDOM],
|
||||||
init: [],
|
|
||||||
inspectElement: [InspectElementParams],
|
inspectElement: [InspectElementParams],
|
||||||
inspectedElement: [InspectedElementPayload],
|
|
||||||
isBackendStorageAPISupported: [boolean],
|
|
||||||
logElementToConsole: [ElementAndRendererID],
|
logElementToConsole: [ElementAndRendererID],
|
||||||
operations: [Array<number>],
|
|
||||||
ownersList: [OwnersList],
|
|
||||||
overrideComponentFilters: [Array<ComponentFilter>],
|
|
||||||
overrideContext: [OverrideValue],
|
overrideContext: [OverrideValue],
|
||||||
overrideHookState: [OverrideHookState],
|
overrideHookState: [OverrideHookState],
|
||||||
overrideProps: [OverrideValue],
|
overrideProps: [OverrideValue],
|
||||||
overrideState: [OverrideValue],
|
overrideState: [OverrideValue],
|
||||||
overrideSuspense: [OverrideSuspense],
|
overrideSuspense: [OverrideSuspense],
|
||||||
profilingData: [ProfilingDataBackend],
|
profilingData: [ProfilingDataBackend],
|
||||||
profilingStatus: [boolean],
|
|
||||||
reloadAndProfile: [boolean],
|
reloadAndProfile: [boolean],
|
||||||
reloadAppForProfiling: [],
|
|
||||||
screenshotCaptured: [
|
|
||||||
{| commitIndex: number, dataURL: string, rootID: number |},
|
|
||||||
],
|
|
||||||
selectElement: [ElementAndRendererID],
|
selectElement: [ElementAndRendererID],
|
||||||
selectFiber: [number],
|
selectFiber: [number],
|
||||||
shutdown: [],
|
shutdown: [],
|
||||||
|
@ -96,20 +111,22 @@ export default class Bridge extends EventEmitter<{|
|
||||||
startProfiling: [boolean],
|
startProfiling: [boolean],
|
||||||
stopInspectingNative: [boolean],
|
stopInspectingNative: [boolean],
|
||||||
stopProfiling: [],
|
stopProfiling: [],
|
||||||
syncSelectionFromNativeElementsPanel: [],
|
|
||||||
syncSelectionToNativeElementsPanel: [],
|
|
||||||
updateAppendComponentStack: [boolean],
|
updateAppendComponentStack: [boolean],
|
||||||
updateComponentFilters: [Array<ComponentFilter>],
|
updateComponentFilters: [Array<ComponentFilter>],
|
||||||
viewElementSource: [ElementAndRendererID],
|
viewElementSource: [ElementAndRendererID],
|
||||||
|
|
||||||
// React Native style editor plug-in.
|
// React Native style editor plug-in.
|
||||||
isNativeStyleEditorSupported: [
|
|
||||||
{| isSupported: boolean, validAttributes: $ReadOnlyArray<string> |},
|
|
||||||
],
|
|
||||||
NativeStyleEditor_measure: [ElementAndRendererID],
|
NativeStyleEditor_measure: [ElementAndRendererID],
|
||||||
NativeStyleEditor_renameAttribute: [NativeStyleEditor_RenameAttributeParams],
|
NativeStyleEditor_renameAttribute: [NativeStyleEditor_RenameAttributeParams],
|
||||||
NativeStyleEditor_setValue: [NativeStyleEditor_SetValueParams],
|
NativeStyleEditor_setValue: [NativeStyleEditor_SetValueParams],
|
||||||
NativeStyleEditor_styleAndLayout: [StyleAndLayoutPayload],
|
|};
|
||||||
|
|
||||||
|
class Bridge<
|
||||||
|
OutgoingEvents: Object,
|
||||||
|
IncomingEvents: Object
|
||||||
|
> extends EventEmitter<{|
|
||||||
|
...IncomingEvents,
|
||||||
|
...OutgoingEvents,
|
||||||
|}> {
|
|}> {
|
||||||
_isShutdown: boolean = false;
|
_isShutdown: boolean = false;
|
||||||
_messageQueue: Array<any> = [];
|
_messageQueue: Array<any> = [];
|
||||||
|
@ -134,7 +151,10 @@ export default class Bridge extends EventEmitter<{|
|
||||||
return this._wall;
|
return this._wall;
|
||||||
}
|
}
|
||||||
|
|
||||||
send(event: string, payload: any, transferable?: Array<any>) {
|
send<EventName: $Keys<OutgoingEvents>>(
|
||||||
|
event: EventName,
|
||||||
|
...payload: $ElementType<OutgoingEvents, EventName>
|
||||||
|
) {
|
||||||
if (this._isShutdown) {
|
if (this._isShutdown) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Cannot send message "${event}" through a Bridge that has been shutdown.`
|
`Cannot send message "${event}" through a Bridge that has been shutdown.`
|
||||||
|
@ -150,7 +170,7 @@ export default class Bridge extends EventEmitter<{|
|
||||||
// - if there *has* been a message flushed in the last BATCH_DURATION ms
|
// - if there *has* been a message flushed in the last BATCH_DURATION ms
|
||||||
// (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
|
// (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
|
||||||
// be set, and we'll simply add to the queue and wait for that
|
// be set, and we'll simply add to the queue and wait for that
|
||||||
this._messageQueue.push(event, payload, transferable);
|
this._messageQueue.push(event, payload);
|
||||||
if (!this._timeoutID) {
|
if (!this._timeoutID) {
|
||||||
this._timeoutID = setTimeout(this._flush, 0);
|
this._timeoutID = setTimeout(this._flush, 0);
|
||||||
}
|
}
|
||||||
|
@ -204,12 +224,8 @@ export default class Bridge extends EventEmitter<{|
|
||||||
this._timeoutID = null;
|
this._timeoutID = null;
|
||||||
|
|
||||||
if (this._messageQueue.length) {
|
if (this._messageQueue.length) {
|
||||||
for (let i = 0; i < this._messageQueue.length; i += 3) {
|
for (let i = 0; i < this._messageQueue.length; i += 2) {
|
||||||
this._wall.send(
|
this._wall.send(this._messageQueue[i], ...this._messageQueue[i + 1]);
|
||||||
this._messageQueue[i],
|
|
||||||
this._messageQueue[i + 1],
|
|
||||||
this._messageQueue[i + 2]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this._messageQueue.length = 0;
|
this._messageQueue.length = 0;
|
||||||
|
|
||||||
|
@ -220,3 +236,8 @@ export default class Bridge extends EventEmitter<{|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BackendBridge = Bridge<BackendEvents, FrontendEvents>;
|
||||||
|
export type FrontendBridge = Bridge<FrontendEvents, BackendEvents>;
|
||||||
|
|
||||||
|
export default Bridge;
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import memoize from 'memoize-one';
|
import memoize from 'memoize-one';
|
||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import { prepareProfilingDataFrontendFromBackendAndStore } from './views/Profiler/utils';
|
import { prepareProfilingDataFrontendFromBackendAndStore } from './views/Profiler/utils';
|
||||||
import ProfilingCache from './ProfilingCache';
|
import ProfilingCache from './ProfilingCache';
|
||||||
import Store from './store';
|
import Store from './store';
|
||||||
|
|
||||||
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
import type { ProfilingDataBackend } from 'src/backend/types';
|
import type { ProfilingDataBackend } from 'src/backend/types';
|
||||||
import type {
|
import type {
|
||||||
CommitDataFrontend,
|
CommitDataFrontend,
|
||||||
|
@ -23,7 +23,7 @@ export default class ProfilerStore extends EventEmitter<{|
|
||||||
isProfiling: [],
|
isProfiling: [],
|
||||||
profilingData: [],
|
profilingData: [],
|
||||||
|}> {
|
|}> {
|
||||||
_bridge: Bridge;
|
_bridge: FrontendBridge;
|
||||||
|
|
||||||
// Suspense cache for lazily calculating derived profiling data.
|
// Suspense cache for lazily calculating derived profiling data.
|
||||||
_cache: ProfilingCache;
|
_cache: ProfilingCache;
|
||||||
|
@ -79,7 +79,11 @@ export default class ProfilerStore extends EventEmitter<{|
|
||||||
|
|
||||||
_store: Store;
|
_store: Store;
|
||||||
|
|
||||||
constructor(bridge: Bridge, store: Store, defaultIsProfiling: boolean) {
|
constructor(
|
||||||
|
bridge: FrontendBridge,
|
||||||
|
store: Store,
|
||||||
|
defaultIsProfiling: boolean
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._bridge = bridge;
|
this._bridge = bridge;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import Bridge from 'src/bridge';
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
|
|
||||||
type Shell = {|
|
type Shell = {|
|
||||||
connect: (callback: Function) => void,
|
connect: (callback: Function) => void,
|
||||||
|
@ -8,7 +8,7 @@ type Shell = {|
|
||||||
|};
|
|};
|
||||||
|
|
||||||
export function initDevTools(shell: Shell) {
|
export function initDevTools(shell: Shell) {
|
||||||
shell.connect((bridge: Bridge) => {
|
shell.connect((bridge: FrontendBridge) => {
|
||||||
// TODO ...
|
// TODO ...
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import { inspect } from 'util';
|
import { inspect } from 'util';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import {
|
import {
|
||||||
TREE_OPERATION_ADD,
|
TREE_OPERATION_ADD,
|
||||||
TREE_OPERATION_REMOVE,
|
TREE_OPERATION_REMOVE,
|
||||||
|
@ -24,6 +23,7 @@ import ProfilerStore from './ProfilerStore';
|
||||||
|
|
||||||
import type { Element } from './views/Components/types';
|
import type { Element } from './views/Components/types';
|
||||||
import type { ComponentFilter, ElementType } from '../types';
|
import type { ComponentFilter, ElementType } from '../types';
|
||||||
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
|
|
||||||
const debug = (methodName, ...args) => {
|
const debug = (methodName, ...args) => {
|
||||||
if (__DEBUG__) {
|
if (__DEBUG__) {
|
||||||
|
@ -71,7 +71,7 @@ export default class Store extends EventEmitter<{|
|
||||||
supportsProfiling: [],
|
supportsProfiling: [],
|
||||||
supportsReloadAndProfile: [],
|
supportsReloadAndProfile: [],
|
||||||
|}> {
|
|}> {
|
||||||
_bridge: Bridge;
|
_bridge: FrontendBridge;
|
||||||
|
|
||||||
_captureScreenshots: boolean = false;
|
_captureScreenshots: boolean = false;
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ export default class Store extends EventEmitter<{|
|
||||||
// Used for windowing purposes.
|
// Used for windowing purposes.
|
||||||
_weightAcrossRoots: number = 0;
|
_weightAcrossRoots: number = 0;
|
||||||
|
|
||||||
constructor(bridge: Bridge, config?: Config) {
|
constructor(bridge: FrontendBridge, config?: Config) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (__DEBUG__) {
|
if (__DEBUG__) {
|
||||||
|
@ -701,7 +701,7 @@ export default class Store extends EventEmitter<{|
|
||||||
validAttributes,
|
validAttributes,
|
||||||
}: {|
|
}: {|
|
||||||
isSupported: boolean,
|
isSupported: boolean,
|
||||||
validAttributes: $ReadOnlyArray<string>,
|
validAttributes: ?$ReadOnlyArray<string>,
|
||||||
|}) => {
|
|}) => {
|
||||||
this._isNativeStyleEditorSupported = isSupported;
|
this._isNativeStyleEditorSupported = isSupported;
|
||||||
this._nativeStyleEditorValidAttributes = validAttributes || null;
|
this._nativeStyleEditorValidAttributes = validAttributes || null;
|
||||||
|
|
|
@ -221,17 +221,19 @@ function HookView({
|
||||||
if (canEditHooks && isStateEditable) {
|
if (canEditHooks && isStateEditable) {
|
||||||
overrideValueFn = (absolutePath: Array<string | number>, value: any) => {
|
overrideValueFn = (absolutePath: Array<string | number>, value: any) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideHookState', {
|
if (rendererID !== null) {
|
||||||
id,
|
bridge.send('overrideHookState', {
|
||||||
hookID,
|
id,
|
||||||
// Hooks override function expects a relative path for the specified hook (id),
|
hookID,
|
||||||
// starting with its id within the (flat) hooks list structure.
|
// Hooks override function expects a relative path for the specified hook (id),
|
||||||
// This relative path does not include the fake tree structure DevTools uses for display,
|
// starting with its id within the (flat) hooks list structure.
|
||||||
// so it's important that we remove that part of the path before sending the update.
|
// This relative path does not include the fake tree structure DevTools uses for display,
|
||||||
path: absolutePath.slice(path.length + 1),
|
// so it's important that we remove that part of the path before sending the update.
|
||||||
rendererID,
|
path: absolutePath.slice(path.length + 1),
|
||||||
value,
|
rendererID,
|
||||||
});
|
value,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,9 @@ function InspectedElementContextController({ children }: Props) {
|
||||||
const getInspectedElementPath = useCallback<GetInspectedElementPath>(
|
const getInspectedElementPath = useCallback<GetInspectedElementPath>(
|
||||||
(id: number, path: Array<string | number>) => {
|
(id: number, path: Array<string | number>) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('inspectElement', { id, path, rendererID });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('inspectElement', { id, path, rendererID });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[bridge, store]
|
[bridge, store]
|
||||||
);
|
);
|
||||||
|
@ -232,7 +234,9 @@ function InspectedElementContextController({ children }: Props) {
|
||||||
const sendRequest = () => {
|
const sendRequest = () => {
|
||||||
timeoutID = null;
|
timeoutID = null;
|
||||||
|
|
||||||
bridge.send('inspectElement', { id: selectedElementID, rendererID });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('inspectElement', { id: selectedElementID, rendererID });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the initial inspection request.
|
// Send the initial inspection request.
|
||||||
|
@ -240,7 +244,9 @@ function InspectedElementContextController({ children }: Props) {
|
||||||
sendRequest();
|
sendRequest();
|
||||||
|
|
||||||
// Update the $r variable.
|
// Update the $r variable.
|
||||||
bridge.send('selectElement', { id: selectedElementID, rendererID });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('selectElement', { id: selectedElementID, rendererID });
|
||||||
|
}
|
||||||
|
|
||||||
const onInspectedElement = (data: InspectedElementPayload) => {
|
const onInspectedElement = (data: InspectedElementPayload) => {
|
||||||
// If this is the element we requested, wait a little bit and then ask for another update.
|
// If this is the element we requested, wait a little bit and then ask for another update.
|
||||||
|
|
|
@ -25,22 +25,28 @@ export default function StyleEditor({ id, style }: Props) {
|
||||||
const store = useContext(StoreContext);
|
const store = useContext(StoreContext);
|
||||||
|
|
||||||
const changeAttribute = (oldName: string, newName: string, value: any) => {
|
const changeAttribute = (oldName: string, newName: string, value: any) => {
|
||||||
bridge.send('NativeStyleEditor_renameAttribute', {
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
id,
|
if (rendererID !== null) {
|
||||||
rendererID: store.getRendererIDForElement(id),
|
bridge.send('NativeStyleEditor_renameAttribute', {
|
||||||
oldName,
|
id,
|
||||||
newName,
|
rendererID,
|
||||||
value,
|
oldName,
|
||||||
});
|
newName,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeValue = (name: string, value: any) => {
|
const changeValue = (name: string, value: any) => {
|
||||||
bridge.send('NativeStyleEditor_setValue', {
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
id,
|
if (rendererID !== null) {
|
||||||
rendererID: store.getRendererIDForElement(id),
|
bridge.send('NativeStyleEditor_setValue', {
|
||||||
name,
|
id,
|
||||||
value,
|
rendererID,
|
||||||
});
|
name,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const keys = useMemo(() => Array.from(Object.keys(style)), [style]);
|
const keys = useMemo(() => Array.from(Object.keys(style)), [style]);
|
||||||
|
|
|
@ -136,10 +136,12 @@ function NativeStyleContextController({ children }: Props) {
|
||||||
const sendRequest = () => {
|
const sendRequest = () => {
|
||||||
timeoutID = null;
|
timeoutID = null;
|
||||||
|
|
||||||
bridge.send('NativeStyleEditor_measure', {
|
if (rendererID !== null) {
|
||||||
id: selectedElementID,
|
bridge.send('NativeStyleEditor_measure', {
|
||||||
rendererID,
|
id: selectedElementID,
|
||||||
});
|
rendererID,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the initial measurement request.
|
// Send the initial measurement request.
|
||||||
|
|
|
@ -106,8 +106,9 @@ function OwnersListContextController({ children }: Props) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ownerID !== null) {
|
if (ownerID !== null) {
|
||||||
const rendererID = store.getRendererIDForElement(ownerID);
|
const rendererID = store.getRendererIDForElement(ownerID);
|
||||||
|
if (rendererID !== null) {
|
||||||
bridge.send('getOwnersList', { id: ownerID, rendererID });
|
bridge.send('getOwnersList', { id: ownerID, rendererID });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {};
|
return () => {};
|
||||||
|
|
|
@ -140,12 +140,18 @@ export default function SelectedElement(_: Props) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rendererID = store.getRendererIDForElement(
|
||||||
|
nearestSuspenseElementID
|
||||||
|
);
|
||||||
|
|
||||||
// Toggle suspended
|
// Toggle suspended
|
||||||
bridge.send('overrideSuspense', {
|
if (rendererID !== null) {
|
||||||
id: nearestSuspenseElementID,
|
bridge.send('overrideSuspense', {
|
||||||
rendererID: store.getRendererIDForElement(nearestSuspenseElementID),
|
id: nearestSuspenseElementID,
|
||||||
forceFallback: !isSuspended,
|
rendererID,
|
||||||
});
|
forceFallback: !isSuspended,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [bridge, dispatch, element, isSuspended, modalDialogDispatch, store]);
|
}, [bridge, dispatch, element, isSuspended, modalDialogDispatch, store]);
|
||||||
|
|
||||||
|
@ -280,15 +286,21 @@ function InspectedElementView({
|
||||||
if (type === ElementTypeClass) {
|
if (type === ElementTypeClass) {
|
||||||
overrideContextFn = (path: Array<string | number>, value: any) => {
|
overrideContextFn = (path: Array<string | number>, value: any) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideContext', { id, path, rendererID, value });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('overrideContext', { id, path, rendererID, value });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
overridePropsFn = (path: Array<string | number>, value: any) => {
|
overridePropsFn = (path: Array<string | number>, value: any) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideProps', { id, path, rendererID, value });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('overrideProps', { id, path, rendererID, value });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
overrideStateFn = (path: Array<string | number>, value: any) => {
|
overrideStateFn = (path: Array<string | number>, value: any) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideState', { id, path, rendererID, value });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('overrideState', { id, path, rendererID, value });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (
|
||||||
(type === ElementTypeFunction ||
|
(type === ElementTypeFunction ||
|
||||||
|
@ -298,7 +310,9 @@ function InspectedElementView({
|
||||||
) {
|
) {
|
||||||
overridePropsFn = (path: Array<string | number>, value: any) => {
|
overridePropsFn = (path: Array<string | number>, value: any) => {
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideProps', { id, path, rendererID, value });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('overrideProps', { id, path, rendererID, value });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (type === ElementTypeSuspense && canToggleSuspense) {
|
} else if (type === ElementTypeSuspense && canToggleSuspense) {
|
||||||
overrideSuspenseFn = (path: Array<string | number>, value: boolean) => {
|
overrideSuspenseFn = (path: Array<string | number>, value: boolean) => {
|
||||||
|
@ -306,7 +320,13 @@ function InspectedElementView({
|
||||||
throw new Error('Unexpected path.');
|
throw new Error('Unexpected path.');
|
||||||
}
|
}
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
bridge.send('overrideSuspense', { id, rendererID, forceFallback: value });
|
if (rendererID !== null) {
|
||||||
|
bridge.send('overrideSuspense', {
|
||||||
|
id,
|
||||||
|
rendererID,
|
||||||
|
forceFallback: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ export default function Tree(props: Props) {
|
||||||
(id: number) => {
|
(id: number) => {
|
||||||
const element = store.getElementByID(id);
|
const element = store.getElementByID(id);
|
||||||
const rendererID = store.getRendererIDForElement(id);
|
const rendererID = store.getRendererIDForElement(id);
|
||||||
if (element !== null) {
|
if (element !== null && rendererID !== null) {
|
||||||
bridge.send('highlightNativeElement', {
|
bridge.send('highlightNativeElement', {
|
||||||
displayName: element.displayName,
|
displayName: element.displayName,
|
||||||
hideAfterTimeout: false,
|
hideAfterTimeout: false,
|
||||||
|
|
|
@ -6,7 +6,6 @@ import '@reach/menu-button/styles.css';
|
||||||
import '@reach/tooltip/styles.css';
|
import '@reach/tooltip/styles.css';
|
||||||
|
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
import Store from '../store';
|
import Store from '../store';
|
||||||
import { BridgeContext, StoreContext } from './context';
|
import { BridgeContext, StoreContext } from './context';
|
||||||
import Components from './Components/Components';
|
import Components from './Components/Components';
|
||||||
|
@ -25,6 +24,7 @@ import styles from './DevTools.css';
|
||||||
import './root.css';
|
import './root.css';
|
||||||
|
|
||||||
import type { InspectedElement } from 'src/devtools/views/Components/types';
|
import type { InspectedElement } from 'src/devtools/views/Components/types';
|
||||||
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
|
|
||||||
export type BrowserTheme = 'dark' | 'light';
|
export type BrowserTheme = 'dark' | 'light';
|
||||||
export type TabID = 'components' | 'profiler' | 'settings';
|
export type TabID = 'components' | 'profiler' | 'settings';
|
||||||
|
@ -34,7 +34,7 @@ export type ViewElementSource = (
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export type Props = {|
|
export type Props = {|
|
||||||
bridge: Bridge,
|
bridge: FrontendBridge,
|
||||||
browserTheme?: BrowserTheme,
|
browserTheme?: BrowserTheme,
|
||||||
defaultTab?: TabID,
|
defaultTab?: TabID,
|
||||||
showTabBar?: boolean,
|
showTabBar?: boolean,
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import Bridge from 'src/bridge';
|
|
||||||
|
|
||||||
import Store from '../store';
|
import Store from '../store';
|
||||||
|
|
||||||
export const BridgeContext = createContext<Bridge>(((null: any): Bridge));
|
import type { FrontendBridge } from 'src/bridge';
|
||||||
|
|
||||||
|
export const BridgeContext = createContext<FrontendBridge>(
|
||||||
|
((null: any): FrontendBridge)
|
||||||
|
);
|
||||||
BridgeContext.displayName = 'BridgeContext';
|
BridgeContext.displayName = 'BridgeContext';
|
||||||
|
|
||||||
export const StoreContext = createContext<Store>(((null: any): Store));
|
export const StoreContext = createContext<Store>(((null: any): Store));
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -59,6 +59,50 @@ function getScrollbarSize(recalculate) {
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
var cachedRTLResult = null; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
||||||
|
// Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
|
||||||
|
// The safest way to check this is to intentionally set a negative offset,
|
||||||
|
// and then verify that the subsequent "scroll" event matches the negative offset.
|
||||||
|
// If it does not match, then we can assume a non-standard RTL scroll implementation.
|
||||||
|
|
||||||
|
function getRTLOffsetType(recalculate) {
|
||||||
|
if (recalculate === void 0) {
|
||||||
|
recalculate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedRTLResult === null || recalculate) {
|
||||||
|
var outerDiv = document.createElement('div');
|
||||||
|
var outerStyle = outerDiv.style;
|
||||||
|
outerStyle.width = '50px';
|
||||||
|
outerStyle.height = '50px';
|
||||||
|
outerStyle.overflow = 'scroll';
|
||||||
|
outerStyle.direction = 'rtl';
|
||||||
|
var innerDiv = document.createElement('div');
|
||||||
|
var innerStyle = innerDiv.style;
|
||||||
|
innerStyle.width = '100px';
|
||||||
|
innerStyle.height = '100px';
|
||||||
|
outerDiv.appendChild(innerDiv);
|
||||||
|
document.body.appendChild(outerDiv);
|
||||||
|
|
||||||
|
if (outerDiv.scrollLeft > 0) {
|
||||||
|
cachedRTLResult = 'positive-descending';
|
||||||
|
} else {
|
||||||
|
outerDiv.scrollLeft = 1;
|
||||||
|
|
||||||
|
if (outerDiv.scrollLeft === 0) {
|
||||||
|
cachedRTLResult = 'negative';
|
||||||
|
} else {
|
||||||
|
cachedRTLResult = 'positive-ascending';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(outerDiv);
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
||||||
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
|
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
|
||||||
|
|
||||||
|
@ -72,6 +116,7 @@ var defaultItemKey = function defaultItemKey(_ref) {
|
||||||
|
|
||||||
|
|
||||||
var devWarningsOverscanCount = null;
|
var devWarningsOverscanCount = null;
|
||||||
|
var devWarningsOverscanRowsColumnsCount = null;
|
||||||
var devWarningsTagName = null;
|
var devWarningsTagName = null;
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
@ -79,6 +124,9 @@ if (process.env.NODE_ENV !== 'production') {
|
||||||
devWarningsOverscanCount =
|
devWarningsOverscanCount =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
new WeakSet();
|
new WeakSet();
|
||||||
|
devWarningsOverscanRowsColumnsCount =
|
||||||
|
/*#__PURE__*/
|
||||||
|
new WeakSet();
|
||||||
devWarningsTagName =
|
devWarningsTagName =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
new WeakSet();
|
new WeakSet();
|
||||||
|
@ -183,9 +231,11 @@ function createGridComponent(_ref2) {
|
||||||
|
|
||||||
_this._onScroll = function (event) {
|
_this._onScroll = function (event) {
|
||||||
var _event$currentTarget = event.currentTarget,
|
var _event$currentTarget = event.currentTarget,
|
||||||
|
clientHeight = _event$currentTarget.clientHeight,
|
||||||
clientWidth = _event$currentTarget.clientWidth,
|
clientWidth = _event$currentTarget.clientWidth,
|
||||||
scrollLeft = _event$currentTarget.scrollLeft,
|
scrollLeft = _event$currentTarget.scrollLeft,
|
||||||
scrollTop = _event$currentTarget.scrollTop,
|
scrollTop = _event$currentTarget.scrollTop,
|
||||||
|
scrollHeight = _event$currentTarget.scrollHeight,
|
||||||
scrollWidth = _event$currentTarget.scrollWidth;
|
scrollWidth = _event$currentTarget.scrollWidth;
|
||||||
|
|
||||||
_this.setState(function (prevState) {
|
_this.setState(function (prevState) {
|
||||||
|
@ -196,25 +246,33 @@ function createGridComponent(_ref2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
var direction = _this.props.direction; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
|
|
||||||
var calculatedScrollLeft = scrollLeft;
|
var calculatedScrollLeft = scrollLeft;
|
||||||
|
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
switch (getRTLOffsetType()) {
|
||||||
calculatedScrollLeft = -scrollLeft;
|
case 'negative':
|
||||||
} else {
|
calculatedScrollLeft = -scrollLeft;
|
||||||
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case 'positive-descending':
|
||||||
|
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
calculatedScrollLeft = Math.max(0, Math.min(calculatedScrollLeft, scrollWidth - clientWidth));
|
||||||
|
var calculatedScrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
||||||
scrollLeft: calculatedScrollLeft,
|
scrollLeft: calculatedScrollLeft,
|
||||||
scrollTop: scrollTop,
|
scrollTop: calculatedScrollTop,
|
||||||
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
||||||
scrollUpdateWasRequested: false
|
scrollUpdateWasRequested: false
|
||||||
};
|
};
|
||||||
|
@ -339,26 +397,55 @@ function createGridComponent(_ref2) {
|
||||||
initialScrollLeft = _this$props3.initialScrollLeft,
|
initialScrollLeft = _this$props3.initialScrollLeft,
|
||||||
initialScrollTop = _this$props3.initialScrollTop;
|
initialScrollTop = _this$props3.initialScrollTop;
|
||||||
|
|
||||||
if (typeof initialScrollLeft === 'number' && this._outerRef != null) {
|
if (this._outerRef != null) {
|
||||||
this._outerRef.scrollLeft = initialScrollLeft;
|
var outerRef = this._outerRef;
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof initialScrollTop === 'number' && this._outerRef != null) {
|
if (typeof initialScrollLeft === 'number') {
|
||||||
this._outerRef.scrollTop = initialScrollTop;
|
outerRef.scrollLeft = initialScrollLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof initialScrollTop === 'number') {
|
||||||
|
outerRef.scrollTop = initialScrollTop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.componentDidUpdate = function componentDidUpdate() {
|
_proto.componentDidUpdate = function componentDidUpdate() {
|
||||||
|
var direction = this.props.direction;
|
||||||
var _this$state2 = this.state,
|
var _this$state2 = this.state,
|
||||||
scrollLeft = _this$state2.scrollLeft,
|
scrollLeft = _this$state2.scrollLeft,
|
||||||
scrollTop = _this$state2.scrollTop,
|
scrollTop = _this$state2.scrollTop,
|
||||||
scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
||||||
|
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
this._outerRef.scrollLeft = scrollLeft;
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
this._outerRef.scrollTop = scrollTop;
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
var outerRef = this._outerRef;
|
||||||
|
|
||||||
|
if (direction === 'rtl') {
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var clientWidth = outerRef.clientWidth,
|
||||||
|
scrollWidth = outerRef.scrollWidth;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = Math.max(0, scrollLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
outerRef.scrollTop = Math.max(0, scrollTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
|
@ -442,7 +529,7 @@ function createGridComponent(_ref2) {
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: estimatedTotalHeight,
|
height: estimatedTotalHeight,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: estimatedTotalWidth
|
width: estimatedTotalWidth
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -492,6 +579,7 @@ function createGridComponent(_ref2) {
|
||||||
_proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() {
|
_proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() {
|
||||||
var _this$props6 = this.props,
|
var _this$props6 = this.props,
|
||||||
columnCount = _this$props6.columnCount,
|
columnCount = _this$props6.columnCount,
|
||||||
|
overscanColumnCount = _this$props6.overscanColumnCount,
|
||||||
overscanColumnsCount = _this$props6.overscanColumnsCount,
|
overscanColumnsCount = _this$props6.overscanColumnsCount,
|
||||||
overscanCount = _this$props6.overscanCount,
|
overscanCount = _this$props6.overscanCount,
|
||||||
rowCount = _this$props6.rowCount;
|
rowCount = _this$props6.rowCount;
|
||||||
|
@ -499,7 +587,7 @@ function createGridComponent(_ref2) {
|
||||||
horizontalScrollDirection = _this$state4.horizontalScrollDirection,
|
horizontalScrollDirection = _this$state4.horizontalScrollDirection,
|
||||||
isScrolling = _this$state4.isScrolling,
|
isScrolling = _this$state4.isScrolling,
|
||||||
scrollLeft = _this$state4.scrollLeft;
|
scrollLeft = _this$state4.scrollLeft;
|
||||||
var overscanCountResolved = overscanColumnsCount || overscanCount || 1;
|
var overscanCountResolved = overscanColumnCount || overscanColumnsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -518,13 +606,14 @@ function createGridComponent(_ref2) {
|
||||||
var _this$props7 = this.props,
|
var _this$props7 = this.props,
|
||||||
columnCount = _this$props7.columnCount,
|
columnCount = _this$props7.columnCount,
|
||||||
overscanCount = _this$props7.overscanCount,
|
overscanCount = _this$props7.overscanCount,
|
||||||
|
overscanRowCount = _this$props7.overscanRowCount,
|
||||||
overscanRowsCount = _this$props7.overscanRowsCount,
|
overscanRowsCount = _this$props7.overscanRowsCount,
|
||||||
rowCount = _this$props7.rowCount;
|
rowCount = _this$props7.rowCount;
|
||||||
var _this$state5 = this.state,
|
var _this$state5 = this.state,
|
||||||
isScrolling = _this$state5.isScrolling,
|
isScrolling = _this$state5.isScrolling,
|
||||||
verticalScrollDirection = _this$state5.verticalScrollDirection,
|
verticalScrollDirection = _this$state5.verticalScrollDirection,
|
||||||
scrollTop = _this$state5.scrollTop;
|
scrollTop = _this$state5.scrollTop;
|
||||||
var overscanCountResolved = overscanRowsCount || overscanCount || 1;
|
var overscanCountResolved = overscanRowCount || overscanRowsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -553,7 +642,9 @@ var validateSharedProps = function validateSharedProps(_ref5, _ref6) {
|
||||||
height = _ref5.height,
|
height = _ref5.height,
|
||||||
innerTagName = _ref5.innerTagName,
|
innerTagName = _ref5.innerTagName,
|
||||||
outerTagName = _ref5.outerTagName,
|
outerTagName = _ref5.outerTagName,
|
||||||
|
overscanColumnsCount = _ref5.overscanColumnsCount,
|
||||||
overscanCount = _ref5.overscanCount,
|
overscanCount = _ref5.overscanCount,
|
||||||
|
overscanRowsCount = _ref5.overscanRowsCount,
|
||||||
width = _ref5.width;
|
width = _ref5.width;
|
||||||
var instance = _ref6.instance;
|
var instance = _ref6.instance;
|
||||||
|
|
||||||
|
@ -561,7 +652,14 @@ var validateSharedProps = function validateSharedProps(_ref5, _ref6) {
|
||||||
if (typeof overscanCount === 'number') {
|
if (typeof overscanCount === 'number') {
|
||||||
if (devWarningsOverscanCount && !devWarningsOverscanCount.has(instance)) {
|
if (devWarningsOverscanCount && !devWarningsOverscanCount.has(instance)) {
|
||||||
devWarningsOverscanCount.add(instance);
|
devWarningsOverscanCount.add(instance);
|
||||||
console.warn('The overscanCount prop has been deprecated. ' + 'Please use the overscanColumnsCount and overscanRowsCount props instead.');
|
console.warn('The overscanCount prop has been deprecated. ' + 'Please use the overscanColumnCount and overscanRowCount props instead.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof overscanColumnsCount === 'number' || typeof overscanRowsCount === 'number') {
|
||||||
|
if (devWarningsOverscanRowsColumnsCount && !devWarningsOverscanRowsColumnsCount.has(instance)) {
|
||||||
|
devWarningsOverscanRowsColumnsCount.add(instance);
|
||||||
|
console.warn('The overscanColumnsCount and overscanRowsCount props have been deprecated. ' + 'Please use the overscanColumnCount and overscanRowCount props instead.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,7 +868,11 @@ var getOffsetForIndexAndAlignment = function getOffsetForIndexAndAlignment(itemT
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1037,20 +1139,27 @@ function createListComponent(_ref) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
var direction = _this.props.direction;
|
||||||
// Chrome does not seem to adhere; its scrolLeft values are positive (measured relative to the left).
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
|
||||||
|
|
||||||
var scrollOffset = scrollLeft;
|
var scrollOffset = scrollLeft;
|
||||||
|
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
scrollOffset = -scrollOffset;
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
} else {
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
}
|
switch (getRTLOffsetType()) {
|
||||||
}
|
case 'negative':
|
||||||
|
scrollOffset = -scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-descending':
|
||||||
|
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
scrollOffset = Math.max(0, Math.min(scrollOffset, scrollWidth - clientWidth));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
||||||
|
@ -1061,7 +1170,10 @@ function createListComponent(_ref) {
|
||||||
};
|
};
|
||||||
|
|
||||||
_this._onScrollVertical = function (event) {
|
_this._onScrollVertical = function (event) {
|
||||||
var scrollTop = event.currentTarget.scrollTop;
|
var _event$currentTarget2 = event.currentTarget,
|
||||||
|
clientHeight = _event$currentTarget2.clientHeight,
|
||||||
|
scrollHeight = _event$currentTarget2.scrollHeight,
|
||||||
|
scrollTop = _event$currentTarget2.scrollTop;
|
||||||
|
|
||||||
_this.setState(function (prevState) {
|
_this.setState(function (prevState) {
|
||||||
if (prevState.scrollOffset === scrollTop) {
|
if (prevState.scrollOffset === scrollTop) {
|
||||||
|
@ -1069,12 +1181,14 @@ function createListComponent(_ref) {
|
||||||
// In which case we don't need to trigger another render,
|
// In which case we don't need to trigger another render,
|
||||||
// And we don't want to update state.isScrolling.
|
// And we don't want to update state.isScrolling.
|
||||||
return null;
|
return null;
|
||||||
}
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
var scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection: prevState.scrollOffset < scrollTop ? 'forward' : 'backward',
|
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
||||||
scrollOffset: scrollTop,
|
scrollOffset: scrollOffset,
|
||||||
scrollUpdateWasRequested: false
|
scrollUpdateWasRequested: false
|
||||||
};
|
};
|
||||||
}, _this._resetIsScrollingDebounced);
|
}, _this._resetIsScrollingDebounced);
|
||||||
|
@ -1154,12 +1268,13 @@ function createListComponent(_ref) {
|
||||||
initialScrollOffset = _this$props2.initialScrollOffset,
|
initialScrollOffset = _this$props2.initialScrollOffset,
|
||||||
layout = _this$props2.layout;
|
layout = _this$props2.layout;
|
||||||
|
|
||||||
if (typeof initialScrollOffset === 'number' && this._outerRef !== null) {
|
if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
|
||||||
// TODO Deprecate direction "horizontal"
|
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
||||||
|
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
this._outerRef.scrollLeft = initialScrollOffset;
|
outerRef.scrollLeft = initialScrollOffset;
|
||||||
} else {
|
} else {
|
||||||
this._outerRef.scrollTop = initialScrollOffset;
|
outerRef.scrollTop = initialScrollOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,12 +1289,34 @@ function createListComponent(_ref) {
|
||||||
scrollOffset = _this$state.scrollOffset,
|
scrollOffset = _this$state.scrollOffset,
|
||||||
scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
|
scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
|
||||||
|
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
// TODO Deprecate direction "horizontal"
|
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
||||||
|
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
this._outerRef.scrollLeft = scrollOffset;
|
if (direction === 'rtl') {
|
||||||
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var clientWidth = outerRef.clientWidth,
|
||||||
|
scrollWidth = outerRef.scrollWidth;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._outerRef.scrollTop = scrollOffset;
|
outerRef.scrollTop = scrollOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,7 +1392,7 @@ function createListComponent(_ref) {
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: isHorizontal ? '100%' : estimatedTotalSize,
|
height: isHorizontal ? '100%' : estimatedTotalSize,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: isHorizontal ? estimatedTotalSize : '100%'
|
width: isHorizontal ? estimatedTotalSize : '100%'
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -1537,7 +1674,7 @@ createListComponent({
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1642,7 +1779,8 @@ createGridComponent({
|
||||||
var columnCount = _ref7.columnCount,
|
var columnCount = _ref7.columnCount,
|
||||||
columnWidth = _ref7.columnWidth,
|
columnWidth = _ref7.columnWidth,
|
||||||
width = _ref7.width;
|
width = _ref7.width;
|
||||||
var maxOffset = Math.max(0, Math.min(columnCount * columnWidth - width, columnIndex * columnWidth));
|
var lastColumnOffset = Math.max(0, columnCount * columnWidth - width);
|
||||||
|
var maxOffset = Math.min(lastColumnOffset, columnIndex * columnWidth);
|
||||||
var minOffset = Math.max(0, columnIndex * columnWidth - width + scrollbarSize + columnWidth);
|
var minOffset = Math.max(0, columnIndex * columnWidth - width + scrollbarSize + columnWidth);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1661,13 +1799,27 @@ createGridComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(width / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastColumnOffset + Math.floor(width / 2)) {
|
||||||
|
return lastColumnOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
||||||
return scrollLeft;
|
return scrollLeft;
|
||||||
} else if (scrollLeft - minOffset < maxOffset - scrollLeft) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollLeft < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1679,7 +1831,8 @@ createGridComponent({
|
||||||
var rowHeight = _ref8.rowHeight,
|
var rowHeight = _ref8.rowHeight,
|
||||||
height = _ref8.height,
|
height = _ref8.height,
|
||||||
rowCount = _ref8.rowCount;
|
rowCount = _ref8.rowCount;
|
||||||
var maxOffset = Math.max(0, Math.min(rowCount * rowHeight - height, rowIndex * rowHeight));
|
var lastRowOffset = Math.max(0, rowCount * rowHeight - height);
|
||||||
|
var maxOffset = Math.min(lastRowOffset, rowIndex * rowHeight);
|
||||||
var minOffset = Math.max(0, rowIndex * rowHeight - height + scrollbarSize + rowHeight);
|
var minOffset = Math.max(0, rowIndex * rowHeight - height + scrollbarSize + rowHeight);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1698,13 +1851,27 @@ createGridComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(height / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastRowOffset + Math.floor(height / 2)) {
|
||||||
|
return lastRowOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
||||||
return scrollTop;
|
return scrollTop;
|
||||||
} else if (scrollTop - minOffset < maxOffset - scrollTop) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollTop < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1722,7 +1889,9 @@ createGridComponent({
|
||||||
columnCount = _ref10.columnCount,
|
columnCount = _ref10.columnCount,
|
||||||
width = _ref10.width;
|
width = _ref10.width;
|
||||||
var left = startIndex * columnWidth;
|
var left = startIndex * columnWidth;
|
||||||
return Math.max(0, Math.min(columnCount - 1, startIndex + Math.floor((width + (scrollLeft - left)) / columnWidth)));
|
var numVisibleColumns = Math.ceil((width + scrollLeft - left) / columnWidth);
|
||||||
|
return Math.max(0, Math.min(columnCount - 1, startIndex + numVisibleColumns - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
getRowStartIndexForOffset: function getRowStartIndexForOffset(_ref11, scrollTop) {
|
getRowStartIndexForOffset: function getRowStartIndexForOffset(_ref11, scrollTop) {
|
||||||
var rowHeight = _ref11.rowHeight,
|
var rowHeight = _ref11.rowHeight,
|
||||||
|
@ -1733,8 +1902,10 @@ createGridComponent({
|
||||||
var rowHeight = _ref12.rowHeight,
|
var rowHeight = _ref12.rowHeight,
|
||||||
rowCount = _ref12.rowCount,
|
rowCount = _ref12.rowCount,
|
||||||
height = _ref12.height;
|
height = _ref12.height;
|
||||||
var left = startIndex * rowHeight;
|
var top = startIndex * rowHeight;
|
||||||
return Math.max(0, Math.min(rowCount - 1, startIndex + Math.floor((height + (scrollTop - left)) / rowHeight)));
|
var numVisibleRows = Math.ceil((height + scrollTop - top) / rowHeight);
|
||||||
|
return Math.max(0, Math.min(rowCount - 1, startIndex + numVisibleRows - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
initInstanceProps: function initInstanceProps(props) {// Noop
|
initInstanceProps: function initInstanceProps(props) {// Noop
|
||||||
},
|
},
|
||||||
|
@ -1759,13 +1930,11 @@ var FixedSizeList =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
createListComponent({
|
createListComponent({
|
||||||
getItemOffset: function getItemOffset(_ref, index) {
|
getItemOffset: function getItemOffset(_ref, index) {
|
||||||
var itemSize = _ref.itemSize,
|
var itemSize = _ref.itemSize;
|
||||||
size = _ref.size;
|
|
||||||
return index * itemSize;
|
return index * itemSize;
|
||||||
},
|
},
|
||||||
getItemSize: function getItemSize(_ref2, index) {
|
getItemSize: function getItemSize(_ref2, index) {
|
||||||
var itemSize = _ref2.itemSize,
|
var itemSize = _ref2.itemSize;
|
||||||
size = _ref2.size;
|
|
||||||
return itemSize;
|
return itemSize;
|
||||||
},
|
},
|
||||||
getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
|
getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
|
||||||
|
@ -1783,7 +1952,8 @@ createListComponent({
|
||||||
// TODO Deprecate direction "horizontal"
|
// TODO Deprecate direction "horizontal"
|
||||||
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
var size = isHorizontal ? width : height;
|
var size = isHorizontal ? width : height;
|
||||||
var maxOffset = Math.max(0, Math.min(itemCount * itemSize - size, index * itemSize));
|
var lastItemOffset = Math.max(0, itemCount * itemSize - size);
|
||||||
|
var maxOffset = Math.min(lastItemOffset, index * itemSize);
|
||||||
var minOffset = Math.max(0, index * itemSize - size + itemSize);
|
var minOffset = Math.max(0, index * itemSize - size + itemSize);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1802,13 +1972,25 @@ createListComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
{
|
||||||
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(size / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastItemOffset + Math.floor(size / 2)) {
|
||||||
|
return lastItemOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1832,7 +2014,9 @@ createListComponent({
|
||||||
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
var offset = startIndex * itemSize;
|
var offset = startIndex * itemSize;
|
||||||
var size = isHorizontal ? width : height;
|
var size = isHorizontal ? width : height;
|
||||||
return Math.max(0, Math.min(itemCount - 1, startIndex + Math.floor((size + (scrollOffset - offset)) / itemSize)));
|
var numVisibleItems = Math.ceil((size + scrollOffset - offset) / itemSize);
|
||||||
|
return Math.max(0, Math.min(itemCount - 1, startIndex + numVisibleItems - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
initInstanceProps: function initInstanceProps(props) {// Noop
|
initInstanceProps: function initInstanceProps(props) {// Noop
|
||||||
},
|
},
|
||||||
|
@ -1892,3 +2076,4 @@ exports.FixedSizeGrid = FixedSizeGrid;
|
||||||
exports.FixedSizeList = FixedSizeList;
|
exports.FixedSizeList = FixedSizeList;
|
||||||
exports.areEqual = areEqual;
|
exports.areEqual = areEqual;
|
||||||
exports.shouldComponentUpdate = shouldComponentUpdate;
|
exports.shouldComponentUpdate = shouldComponentUpdate;
|
||||||
|
//# sourceMappingURL=index.cjs.js.map
|
||||||
|
|
|
@ -54,6 +54,50 @@ function getScrollbarSize(recalculate) {
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
var cachedRTLResult = null; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
||||||
|
// Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
|
||||||
|
// The safest way to check this is to intentionally set a negative offset,
|
||||||
|
// and then verify that the subsequent "scroll" event matches the negative offset.
|
||||||
|
// If it does not match, then we can assume a non-standard RTL scroll implementation.
|
||||||
|
|
||||||
|
function getRTLOffsetType(recalculate) {
|
||||||
|
if (recalculate === void 0) {
|
||||||
|
recalculate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedRTLResult === null || recalculate) {
|
||||||
|
var outerDiv = document.createElement('div');
|
||||||
|
var outerStyle = outerDiv.style;
|
||||||
|
outerStyle.width = '50px';
|
||||||
|
outerStyle.height = '50px';
|
||||||
|
outerStyle.overflow = 'scroll';
|
||||||
|
outerStyle.direction = 'rtl';
|
||||||
|
var innerDiv = document.createElement('div');
|
||||||
|
var innerStyle = innerDiv.style;
|
||||||
|
innerStyle.width = '100px';
|
||||||
|
innerStyle.height = '100px';
|
||||||
|
outerDiv.appendChild(innerDiv);
|
||||||
|
document.body.appendChild(outerDiv);
|
||||||
|
|
||||||
|
if (outerDiv.scrollLeft > 0) {
|
||||||
|
cachedRTLResult = 'positive-descending';
|
||||||
|
} else {
|
||||||
|
outerDiv.scrollLeft = 1;
|
||||||
|
|
||||||
|
if (outerDiv.scrollLeft === 0) {
|
||||||
|
cachedRTLResult = 'negative';
|
||||||
|
} else {
|
||||||
|
cachedRTLResult = 'positive-ascending';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(outerDiv);
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
||||||
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
|
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
|
||||||
|
|
||||||
|
@ -67,6 +111,7 @@ var defaultItemKey = function defaultItemKey(_ref) {
|
||||||
|
|
||||||
|
|
||||||
var devWarningsOverscanCount = null;
|
var devWarningsOverscanCount = null;
|
||||||
|
var devWarningsOverscanRowsColumnsCount = null;
|
||||||
var devWarningsTagName = null;
|
var devWarningsTagName = null;
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
@ -74,6 +119,9 @@ if (process.env.NODE_ENV !== 'production') {
|
||||||
devWarningsOverscanCount =
|
devWarningsOverscanCount =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
new WeakSet();
|
new WeakSet();
|
||||||
|
devWarningsOverscanRowsColumnsCount =
|
||||||
|
/*#__PURE__*/
|
||||||
|
new WeakSet();
|
||||||
devWarningsTagName =
|
devWarningsTagName =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
new WeakSet();
|
new WeakSet();
|
||||||
|
@ -178,9 +226,11 @@ function createGridComponent(_ref2) {
|
||||||
|
|
||||||
_this._onScroll = function (event) {
|
_this._onScroll = function (event) {
|
||||||
var _event$currentTarget = event.currentTarget,
|
var _event$currentTarget = event.currentTarget,
|
||||||
|
clientHeight = _event$currentTarget.clientHeight,
|
||||||
clientWidth = _event$currentTarget.clientWidth,
|
clientWidth = _event$currentTarget.clientWidth,
|
||||||
scrollLeft = _event$currentTarget.scrollLeft,
|
scrollLeft = _event$currentTarget.scrollLeft,
|
||||||
scrollTop = _event$currentTarget.scrollTop,
|
scrollTop = _event$currentTarget.scrollTop,
|
||||||
|
scrollHeight = _event$currentTarget.scrollHeight,
|
||||||
scrollWidth = _event$currentTarget.scrollWidth;
|
scrollWidth = _event$currentTarget.scrollWidth;
|
||||||
|
|
||||||
// Force flush sync for scroll updates to reduce visual checkerboarding.
|
// Force flush sync for scroll updates to reduce visual checkerboarding.
|
||||||
|
@ -193,25 +243,33 @@ function createGridComponent(_ref2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
var direction = _this.props.direction; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
|
|
||||||
var calculatedScrollLeft = scrollLeft;
|
var calculatedScrollLeft = scrollLeft;
|
||||||
|
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
switch (getRTLOffsetType()) {
|
||||||
calculatedScrollLeft = -scrollLeft;
|
case 'negative':
|
||||||
} else {
|
calculatedScrollLeft = -scrollLeft;
|
||||||
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case 'positive-descending':
|
||||||
|
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
calculatedScrollLeft = Math.max(0, Math.min(calculatedScrollLeft, scrollWidth - clientWidth));
|
||||||
|
var calculatedScrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
||||||
scrollLeft: calculatedScrollLeft,
|
scrollLeft: calculatedScrollLeft,
|
||||||
scrollTop: scrollTop,
|
scrollTop: calculatedScrollTop,
|
||||||
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
||||||
scrollUpdateWasRequested: false
|
scrollUpdateWasRequested: false
|
||||||
};
|
};
|
||||||
|
@ -337,26 +395,55 @@ function createGridComponent(_ref2) {
|
||||||
initialScrollLeft = _this$props3.initialScrollLeft,
|
initialScrollLeft = _this$props3.initialScrollLeft,
|
||||||
initialScrollTop = _this$props3.initialScrollTop;
|
initialScrollTop = _this$props3.initialScrollTop;
|
||||||
|
|
||||||
if (typeof initialScrollLeft === 'number' && this._outerRef != null) {
|
if (this._outerRef != null) {
|
||||||
this._outerRef.scrollLeft = initialScrollLeft;
|
var outerRef = this._outerRef;
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof initialScrollTop === 'number' && this._outerRef != null) {
|
if (typeof initialScrollLeft === 'number') {
|
||||||
this._outerRef.scrollTop = initialScrollTop;
|
outerRef.scrollLeft = initialScrollLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof initialScrollTop === 'number') {
|
||||||
|
outerRef.scrollTop = initialScrollTop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.componentDidUpdate = function componentDidUpdate() {
|
_proto.componentDidUpdate = function componentDidUpdate() {
|
||||||
|
var direction = this.props.direction;
|
||||||
var _this$state2 = this.state,
|
var _this$state2 = this.state,
|
||||||
scrollLeft = _this$state2.scrollLeft,
|
scrollLeft = _this$state2.scrollLeft,
|
||||||
scrollTop = _this$state2.scrollTop,
|
scrollTop = _this$state2.scrollTop,
|
||||||
scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
||||||
|
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
this._outerRef.scrollLeft = scrollLeft;
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
this._outerRef.scrollTop = scrollTop;
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
var outerRef = this._outerRef;
|
||||||
|
|
||||||
|
if (direction === 'rtl') {
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var clientWidth = outerRef.clientWidth,
|
||||||
|
scrollWidth = outerRef.scrollWidth;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = Math.max(0, scrollLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
outerRef.scrollTop = Math.max(0, scrollTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
|
@ -440,7 +527,7 @@ function createGridComponent(_ref2) {
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: estimatedTotalHeight,
|
height: estimatedTotalHeight,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: estimatedTotalWidth
|
width: estimatedTotalWidth
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -490,6 +577,7 @@ function createGridComponent(_ref2) {
|
||||||
_proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() {
|
_proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() {
|
||||||
var _this$props6 = this.props,
|
var _this$props6 = this.props,
|
||||||
columnCount = _this$props6.columnCount,
|
columnCount = _this$props6.columnCount,
|
||||||
|
overscanColumnCount = _this$props6.overscanColumnCount,
|
||||||
overscanColumnsCount = _this$props6.overscanColumnsCount,
|
overscanColumnsCount = _this$props6.overscanColumnsCount,
|
||||||
overscanCount = _this$props6.overscanCount,
|
overscanCount = _this$props6.overscanCount,
|
||||||
rowCount = _this$props6.rowCount;
|
rowCount = _this$props6.rowCount;
|
||||||
|
@ -497,7 +585,7 @@ function createGridComponent(_ref2) {
|
||||||
horizontalScrollDirection = _this$state4.horizontalScrollDirection,
|
horizontalScrollDirection = _this$state4.horizontalScrollDirection,
|
||||||
isScrolling = _this$state4.isScrolling,
|
isScrolling = _this$state4.isScrolling,
|
||||||
scrollLeft = _this$state4.scrollLeft;
|
scrollLeft = _this$state4.scrollLeft;
|
||||||
var overscanCountResolved = overscanColumnsCount || overscanCount || 1;
|
var overscanCountResolved = overscanColumnCount || overscanColumnsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -516,13 +604,14 @@ function createGridComponent(_ref2) {
|
||||||
var _this$props7 = this.props,
|
var _this$props7 = this.props,
|
||||||
columnCount = _this$props7.columnCount,
|
columnCount = _this$props7.columnCount,
|
||||||
overscanCount = _this$props7.overscanCount,
|
overscanCount = _this$props7.overscanCount,
|
||||||
|
overscanRowCount = _this$props7.overscanRowCount,
|
||||||
overscanRowsCount = _this$props7.overscanRowsCount,
|
overscanRowsCount = _this$props7.overscanRowsCount,
|
||||||
rowCount = _this$props7.rowCount;
|
rowCount = _this$props7.rowCount;
|
||||||
var _this$state5 = this.state,
|
var _this$state5 = this.state,
|
||||||
isScrolling = _this$state5.isScrolling,
|
isScrolling = _this$state5.isScrolling,
|
||||||
verticalScrollDirection = _this$state5.verticalScrollDirection,
|
verticalScrollDirection = _this$state5.verticalScrollDirection,
|
||||||
scrollTop = _this$state5.scrollTop;
|
scrollTop = _this$state5.scrollTop;
|
||||||
var overscanCountResolved = overscanRowsCount || overscanCount || 1;
|
var overscanCountResolved = overscanRowCount || overscanRowsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -551,7 +640,9 @@ var validateSharedProps = function validateSharedProps(_ref5, _ref6) {
|
||||||
height = _ref5.height,
|
height = _ref5.height,
|
||||||
innerTagName = _ref5.innerTagName,
|
innerTagName = _ref5.innerTagName,
|
||||||
outerTagName = _ref5.outerTagName,
|
outerTagName = _ref5.outerTagName,
|
||||||
|
overscanColumnsCount = _ref5.overscanColumnsCount,
|
||||||
overscanCount = _ref5.overscanCount,
|
overscanCount = _ref5.overscanCount,
|
||||||
|
overscanRowsCount = _ref5.overscanRowsCount,
|
||||||
width = _ref5.width;
|
width = _ref5.width;
|
||||||
var instance = _ref6.instance;
|
var instance = _ref6.instance;
|
||||||
|
|
||||||
|
@ -559,7 +650,14 @@ var validateSharedProps = function validateSharedProps(_ref5, _ref6) {
|
||||||
if (typeof overscanCount === 'number') {
|
if (typeof overscanCount === 'number') {
|
||||||
if (devWarningsOverscanCount && !devWarningsOverscanCount.has(instance)) {
|
if (devWarningsOverscanCount && !devWarningsOverscanCount.has(instance)) {
|
||||||
devWarningsOverscanCount.add(instance);
|
devWarningsOverscanCount.add(instance);
|
||||||
console.warn('The overscanCount prop has been deprecated. ' + 'Please use the overscanColumnsCount and overscanRowsCount props instead.');
|
console.warn('The overscanCount prop has been deprecated. ' + 'Please use the overscanColumnCount and overscanRowCount props instead.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof overscanColumnsCount === 'number' || typeof overscanRowsCount === 'number') {
|
||||||
|
if (devWarningsOverscanRowsColumnsCount && !devWarningsOverscanRowsColumnsCount.has(instance)) {
|
||||||
|
devWarningsOverscanRowsColumnsCount.add(instance);
|
||||||
|
console.warn('The overscanColumnsCount and overscanRowsCount props have been deprecated. ' + 'Please use the overscanColumnCount and overscanRowCount props instead.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,7 +866,11 @@ var getOffsetForIndexAndAlignment = function getOffsetForIndexAndAlignment(itemT
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1037,20 +1139,27 @@ function createListComponent(_ref) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
var direction = _this.props.direction;
|
||||||
// Chrome does not seem to adhere; its scrolLeft values are positive (measured relative to the left).
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
|
||||||
|
|
||||||
var scrollOffset = scrollLeft;
|
var scrollOffset = scrollLeft;
|
||||||
|
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
scrollOffset = -scrollOffset;
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
} else {
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
}
|
switch (getRTLOffsetType()) {
|
||||||
}
|
case 'negative':
|
||||||
|
scrollOffset = -scrollLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-descending':
|
||||||
|
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
scrollOffset = Math.max(0, Math.min(scrollOffset, scrollWidth - clientWidth));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
||||||
|
@ -1058,11 +1167,14 @@ function createListComponent(_ref) {
|
||||||
scrollUpdateWasRequested: false
|
scrollUpdateWasRequested: false
|
||||||
};
|
};
|
||||||
}, _this._resetIsScrollingDebounced);
|
}, _this._resetIsScrollingDebounced);
|
||||||
});
|
};
|
||||||
};
|
});
|
||||||
|
|
||||||
_this._onScrollVertical = function (event) {
|
_this._onScrollVertical = function (event) {
|
||||||
var scrollTop = event.currentTarget.scrollTop;
|
var _event$currentTarget2 = event.currentTarget,
|
||||||
|
clientHeight = _event$currentTarget2.clientHeight,
|
||||||
|
scrollHeight = _event$currentTarget2.scrollHeight,
|
||||||
|
scrollTop = _event$currentTarget2.scrollTop;
|
||||||
|
|
||||||
// Force flush sync for scroll updates to reduce visual checkerboarding.
|
// Force flush sync for scroll updates to reduce visual checkerboarding.
|
||||||
flushSync(() => {
|
flushSync(() => {
|
||||||
|
@ -1072,17 +1184,19 @@ function createListComponent(_ref) {
|
||||||
// In which case we don't need to trigger another render,
|
// In which case we don't need to trigger another render,
|
||||||
// And we don't want to update state.isScrolling.
|
// And we don't want to update state.isScrolling.
|
||||||
return null;
|
return null;
|
||||||
}
|
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
|
||||||
|
|
||||||
|
var scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection: prevState.scrollOffset < scrollTop ? 'forward' : 'backward',
|
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
||||||
scrollOffset: scrollTop,
|
scrollOffset: scrollOffset,
|
||||||
scrollUpdateWasRequested: false
|
scrollUpdateWasRequested: false
|
||||||
};
|
};
|
||||||
}, _this._resetIsScrollingDebounced);
|
}, _this._resetIsScrollingDebounced);
|
||||||
});
|
};
|
||||||
};
|
});
|
||||||
|
|
||||||
_this._outerRefSetter = function (ref) {
|
_this._outerRefSetter = function (ref) {
|
||||||
var outerRef = _this.props.outerRef;
|
var outerRef = _this.props.outerRef;
|
||||||
|
@ -1158,12 +1272,13 @@ function createListComponent(_ref) {
|
||||||
initialScrollOffset = _this$props2.initialScrollOffset,
|
initialScrollOffset = _this$props2.initialScrollOffset,
|
||||||
layout = _this$props2.layout;
|
layout = _this$props2.layout;
|
||||||
|
|
||||||
if (typeof initialScrollOffset === 'number' && this._outerRef !== null) {
|
if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
|
||||||
// TODO Deprecate direction "horizontal"
|
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
||||||
|
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
this._outerRef.scrollLeft = initialScrollOffset;
|
outerRef.scrollLeft = initialScrollOffset;
|
||||||
} else {
|
} else {
|
||||||
this._outerRef.scrollTop = initialScrollOffset;
|
outerRef.scrollTop = initialScrollOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,12 +1293,34 @@ function createListComponent(_ref) {
|
||||||
scrollOffset = _this$state.scrollOffset,
|
scrollOffset = _this$state.scrollOffset,
|
||||||
scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
|
scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
|
||||||
|
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
// TODO Deprecate direction "horizontal"
|
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
||||||
|
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
this._outerRef.scrollLeft = scrollOffset;
|
if (direction === 'rtl') {
|
||||||
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var clientWidth = outerRef.clientWidth,
|
||||||
|
scrollWidth = outerRef.scrollWidth;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._outerRef.scrollTop = scrollOffset;
|
outerRef.scrollTop = scrollOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1259,7 +1396,7 @@ function createListComponent(_ref) {
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: isHorizontal ? '100%' : estimatedTotalSize,
|
height: isHorizontal ? '100%' : estimatedTotalSize,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: isHorizontal ? estimatedTotalSize : '100%'
|
width: isHorizontal ? estimatedTotalSize : '100%'
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -1541,7 +1678,7 @@ createListComponent({
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1646,7 +1783,8 @@ createGridComponent({
|
||||||
var columnCount = _ref7.columnCount,
|
var columnCount = _ref7.columnCount,
|
||||||
columnWidth = _ref7.columnWidth,
|
columnWidth = _ref7.columnWidth,
|
||||||
width = _ref7.width;
|
width = _ref7.width;
|
||||||
var maxOffset = Math.max(0, Math.min(columnCount * columnWidth - width, columnIndex * columnWidth));
|
var lastColumnOffset = Math.max(0, columnCount * columnWidth - width);
|
||||||
|
var maxOffset = Math.min(lastColumnOffset, columnIndex * columnWidth);
|
||||||
var minOffset = Math.max(0, columnIndex * columnWidth - width + scrollbarSize + columnWidth);
|
var minOffset = Math.max(0, columnIndex * columnWidth - width + scrollbarSize + columnWidth);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1665,13 +1803,27 @@ createGridComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(width / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastColumnOffset + Math.floor(width / 2)) {
|
||||||
|
return lastColumnOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
||||||
return scrollLeft;
|
return scrollLeft;
|
||||||
} else if (scrollLeft - minOffset < maxOffset - scrollLeft) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollLeft < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1683,7 +1835,8 @@ createGridComponent({
|
||||||
var rowHeight = _ref8.rowHeight,
|
var rowHeight = _ref8.rowHeight,
|
||||||
height = _ref8.height,
|
height = _ref8.height,
|
||||||
rowCount = _ref8.rowCount;
|
rowCount = _ref8.rowCount;
|
||||||
var maxOffset = Math.max(0, Math.min(rowCount * rowHeight - height, rowIndex * rowHeight));
|
var lastRowOffset = Math.max(0, rowCount * rowHeight - height);
|
||||||
|
var maxOffset = Math.min(lastRowOffset, rowIndex * rowHeight);
|
||||||
var minOffset = Math.max(0, rowIndex * rowHeight - height + scrollbarSize + rowHeight);
|
var minOffset = Math.max(0, rowIndex * rowHeight - height + scrollbarSize + rowHeight);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1702,13 +1855,27 @@ createGridComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(height / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastRowOffset + Math.floor(height / 2)) {
|
||||||
|
return lastRowOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
||||||
return scrollTop;
|
return scrollTop;
|
||||||
} else if (scrollTop - minOffset < maxOffset - scrollTop) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollTop < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1726,7 +1893,9 @@ createGridComponent({
|
||||||
columnCount = _ref10.columnCount,
|
columnCount = _ref10.columnCount,
|
||||||
width = _ref10.width;
|
width = _ref10.width;
|
||||||
var left = startIndex * columnWidth;
|
var left = startIndex * columnWidth;
|
||||||
return Math.max(0, Math.min(columnCount - 1, startIndex + Math.floor((width + (scrollLeft - left)) / columnWidth)));
|
var numVisibleColumns = Math.ceil((width + scrollLeft - left) / columnWidth);
|
||||||
|
return Math.max(0, Math.min(columnCount - 1, startIndex + numVisibleColumns - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
getRowStartIndexForOffset: function getRowStartIndexForOffset(_ref11, scrollTop) {
|
getRowStartIndexForOffset: function getRowStartIndexForOffset(_ref11, scrollTop) {
|
||||||
var rowHeight = _ref11.rowHeight,
|
var rowHeight = _ref11.rowHeight,
|
||||||
|
@ -1737,8 +1906,10 @@ createGridComponent({
|
||||||
var rowHeight = _ref12.rowHeight,
|
var rowHeight = _ref12.rowHeight,
|
||||||
rowCount = _ref12.rowCount,
|
rowCount = _ref12.rowCount,
|
||||||
height = _ref12.height;
|
height = _ref12.height;
|
||||||
var left = startIndex * rowHeight;
|
var top = startIndex * rowHeight;
|
||||||
return Math.max(0, Math.min(rowCount - 1, startIndex + Math.floor((height + (scrollTop - left)) / rowHeight)));
|
var numVisibleRows = Math.ceil((height + scrollTop - top) / rowHeight);
|
||||||
|
return Math.max(0, Math.min(rowCount - 1, startIndex + numVisibleRows - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
initInstanceProps: function initInstanceProps(props) {// Noop
|
initInstanceProps: function initInstanceProps(props) {// Noop
|
||||||
},
|
},
|
||||||
|
@ -1763,13 +1934,11 @@ var FixedSizeList =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
createListComponent({
|
createListComponent({
|
||||||
getItemOffset: function getItemOffset(_ref, index) {
|
getItemOffset: function getItemOffset(_ref, index) {
|
||||||
var itemSize = _ref.itemSize,
|
var itemSize = _ref.itemSize;
|
||||||
size = _ref.size;
|
|
||||||
return index * itemSize;
|
return index * itemSize;
|
||||||
},
|
},
|
||||||
getItemSize: function getItemSize(_ref2, index) {
|
getItemSize: function getItemSize(_ref2, index) {
|
||||||
var itemSize = _ref2.itemSize,
|
var itemSize = _ref2.itemSize;
|
||||||
size = _ref2.size;
|
|
||||||
return itemSize;
|
return itemSize;
|
||||||
},
|
},
|
||||||
getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
|
getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
|
||||||
|
@ -1787,7 +1956,8 @@ createListComponent({
|
||||||
// TODO Deprecate direction "horizontal"
|
// TODO Deprecate direction "horizontal"
|
||||||
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
var size = isHorizontal ? width : height;
|
var size = isHorizontal ? width : height;
|
||||||
var maxOffset = Math.max(0, Math.min(itemCount * itemSize - size, index * itemSize));
|
var lastItemOffset = Math.max(0, itemCount * itemSize - size);
|
||||||
|
var maxOffset = Math.min(lastItemOffset, index * itemSize);
|
||||||
var minOffset = Math.max(0, index * itemSize - size + itemSize);
|
var minOffset = Math.max(0, index * itemSize - size + itemSize);
|
||||||
|
|
||||||
if (align === 'smart') {
|
if (align === 'smart') {
|
||||||
|
@ -1806,13 +1976,25 @@ createListComponent({
|
||||||
return minOffset;
|
return minOffset;
|
||||||
|
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
{
|
||||||
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
||||||
|
|
||||||
|
if (middleOffset < Math.ceil(size / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastItemOffset + Math.floor(size / 2)) {
|
||||||
|
return lastItemOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -1836,7 +2018,9 @@ createListComponent({
|
||||||
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
var offset = startIndex * itemSize;
|
var offset = startIndex * itemSize;
|
||||||
var size = isHorizontal ? width : height;
|
var size = isHorizontal ? width : height;
|
||||||
return Math.max(0, Math.min(itemCount - 1, startIndex + Math.floor((size + (scrollOffset - offset)) / itemSize)));
|
var numVisibleItems = Math.ceil((size + scrollOffset - offset) / itemSize);
|
||||||
|
return Math.max(0, Math.min(itemCount - 1, startIndex + numVisibleItems - 1 // -1 is because stop index is inclusive
|
||||||
|
));
|
||||||
},
|
},
|
||||||
initInstanceProps: function initInstanceProps(props) {// Noop
|
initInstanceProps: function initInstanceProps(props) {// Noop
|
||||||
},
|
},
|
||||||
|
@ -1891,3 +2075,4 @@ function shouldComponentUpdate(nextProps, nextState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export { VariableSizeGrid, VariableSizeList, FixedSizeGrid, FixedSizeList, areEqual, shouldComponentUpdate };
|
export { VariableSizeGrid, VariableSizeList, FixedSizeGrid, FixedSizeList, areEqual, shouldComponentUpdate };
|
||||||
|
//# sourceMappingURL=index.esm.js.map
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-window",
|
"name": "react-window",
|
||||||
"version": "1.8.0",
|
"version": "1.8.5",
|
||||||
"description":
|
"description":
|
||||||
"React components for efficiently rendering large, scrollable lists and tabular data",
|
"React components for efficiently rendering large, scrollable lists and tabular data",
|
||||||
"author":
|
"author":
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
"eslint-plugin-promise": "^3.7.0",
|
"eslint-plugin-promise": "^3.7.0",
|
||||||
"eslint-plugin-react": "^7.7.0",
|
"eslint-plugin-react": "^7.7.0",
|
||||||
"eslint-plugin-standard": "^3.0.1",
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"flow-bin": "^0.80.0",
|
"flow-bin": "^0.103.0",
|
||||||
"gh-pages": "^1.1.0",
|
"gh-pages": "^1.1.0",
|
||||||
"lint-staged": "^7.0.5",
|
"lint-staged": "^7.0.5",
|
||||||
"prettier": "^1.12.1",
|
"prettier": "^1.12.1",
|
||||||
|
@ -103,6 +103,8 @@
|
||||||
"rollup": "^1.4.1",
|
"rollup": "^1.4.1",
|
||||||
"rollup-plugin-babel": "^4.3.2",
|
"rollup-plugin-babel": "^4.3.2",
|
||||||
"rollup-plugin-commonjs": "^9.2.1",
|
"rollup-plugin-commonjs": "^9.2.1",
|
||||||
"rollup-plugin-node-resolve": "^4.0.1"
|
"rollup-plugin-node-resolve": "^4.0.1",
|
||||||
|
"rollup-plugin-replace": "^2.2.0",
|
||||||
|
"rollup-plugin-terser": "^5.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,13 @@ const FixedSizeGrid = createGridComponent({
|
||||||
instanceProps: typeof undefined,
|
instanceProps: typeof undefined,
|
||||||
scrollbarSize: number
|
scrollbarSize: number
|
||||||
): number => {
|
): number => {
|
||||||
const maxOffset = Math.max(
|
const lastColumnOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
columnCount * ((columnWidth: any): number) - width
|
||||||
columnCount * ((columnWidth: any): number) - width,
|
);
|
||||||
columnIndex * ((columnWidth: any): number)
|
const maxOffset = Math.min(
|
||||||
)
|
lastColumnOffset,
|
||||||
|
columnIndex * ((columnWidth: any): number)
|
||||||
);
|
);
|
||||||
const minOffset = Math.max(
|
const minOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
|
@ -60,12 +61,27 @@ const FixedSizeGrid = createGridComponent({
|
||||||
case 'end':
|
case 'end':
|
||||||
return minOffset;
|
return minOffset;
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
const middleOffset = Math.round(
|
||||||
|
minOffset + (maxOffset - minOffset) / 2
|
||||||
|
);
|
||||||
|
if (middleOffset < Math.ceil(width / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastColumnOffset + Math.floor(width / 2)) {
|
||||||
|
return lastColumnOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
||||||
return scrollLeft;
|
return scrollLeft;
|
||||||
} else if (scrollLeft - minOffset < maxOffset - scrollLeft) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollLeft < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -81,12 +97,13 @@ const FixedSizeGrid = createGridComponent({
|
||||||
instanceProps: typeof undefined,
|
instanceProps: typeof undefined,
|
||||||
scrollbarSize: number
|
scrollbarSize: number
|
||||||
): number => {
|
): number => {
|
||||||
const maxOffset = Math.max(
|
const lastRowOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
rowCount * ((rowHeight: any): number) - height
|
||||||
rowCount * ((rowHeight: any): number) - height,
|
);
|
||||||
rowIndex * ((rowHeight: any): number)
|
const maxOffset = Math.min(
|
||||||
)
|
lastRowOffset,
|
||||||
|
rowIndex * ((rowHeight: any): number)
|
||||||
);
|
);
|
||||||
const minOffset = Math.max(
|
const minOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
|
@ -110,12 +127,27 @@ const FixedSizeGrid = createGridComponent({
|
||||||
case 'end':
|
case 'end':
|
||||||
return minOffset;
|
return minOffset;
|
||||||
case 'center':
|
case 'center':
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
const middleOffset = Math.round(
|
||||||
|
minOffset + (maxOffset - minOffset) / 2
|
||||||
|
);
|
||||||
|
if (middleOffset < Math.ceil(height / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastRowOffset + Math.floor(height / 2)) {
|
||||||
|
return lastRowOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
||||||
return scrollTop;
|
return scrollTop;
|
||||||
} else if (scrollTop - minOffset < maxOffset - scrollTop) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollTop < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -141,14 +173,14 @@ const FixedSizeGrid = createGridComponent({
|
||||||
scrollLeft: number
|
scrollLeft: number
|
||||||
): number => {
|
): number => {
|
||||||
const left = startIndex * ((columnWidth: any): number);
|
const left = startIndex * ((columnWidth: any): number);
|
||||||
|
const numVisibleColumns = Math.ceil(
|
||||||
|
(width + scrollLeft - left) / ((columnWidth: any): number)
|
||||||
|
);
|
||||||
return Math.max(
|
return Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
Math.min(
|
||||||
columnCount - 1,
|
columnCount - 1,
|
||||||
startIndex +
|
startIndex + numVisibleColumns - 1 // -1 is because stop index is inclusive
|
||||||
Math.floor(
|
|
||||||
(width + (scrollLeft - left)) / ((columnWidth: any): number)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -167,13 +199,15 @@ const FixedSizeGrid = createGridComponent({
|
||||||
startIndex: number,
|
startIndex: number,
|
||||||
scrollTop: number
|
scrollTop: number
|
||||||
): number => {
|
): number => {
|
||||||
const left = startIndex * ((rowHeight: any): number);
|
const top = startIndex * ((rowHeight: any): number);
|
||||||
|
const numVisibleRows = Math.ceil(
|
||||||
|
(height + scrollTop - top) / ((rowHeight: any): number)
|
||||||
|
);
|
||||||
return Math.max(
|
return Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
Math.min(
|
||||||
rowCount - 1,
|
rowCount - 1,
|
||||||
startIndex +
|
startIndex + numVisibleRows - 1 // -1 is because stop index is inclusive
|
||||||
Math.floor((height + (scrollTop - left)) / ((rowHeight: any): number))
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,10 +5,10 @@ import createListComponent from './createListComponent';
|
||||||
import type { Props, ScrollToAlign } from './createListComponent';
|
import type { Props, ScrollToAlign } from './createListComponent';
|
||||||
|
|
||||||
const FixedSizeList = createListComponent({
|
const FixedSizeList = createListComponent({
|
||||||
getItemOffset: ({ itemSize, size }: Props<any>, index: number): number =>
|
getItemOffset: ({ itemSize }: Props<any>, index: number): number =>
|
||||||
index * ((itemSize: any): number),
|
index * ((itemSize: any): number),
|
||||||
|
|
||||||
getItemSize: ({ itemSize, size }: Props<any>, index: number): number =>
|
getItemSize: ({ itemSize }: Props<any>, index: number): number =>
|
||||||
((itemSize: any): number),
|
((itemSize: any): number),
|
||||||
|
|
||||||
getEstimatedTotalSize: ({ itemCount, itemSize }: Props<any>) =>
|
getEstimatedTotalSize: ({ itemCount, itemSize }: Props<any>) =>
|
||||||
|
@ -23,12 +23,13 @@ const FixedSizeList = createListComponent({
|
||||||
// TODO Deprecate direction "horizontal"
|
// TODO Deprecate direction "horizontal"
|
||||||
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
const size = (((isHorizontal ? width : height): any): number);
|
const size = (((isHorizontal ? width : height): any): number);
|
||||||
const maxOffset = Math.max(
|
const lastItemOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
itemCount * ((itemSize: any): number) - size
|
||||||
itemCount * ((itemSize: any): number) - size,
|
);
|
||||||
index * ((itemSize: any): number)
|
const maxOffset = Math.min(
|
||||||
)
|
lastItemOffset,
|
||||||
|
index * ((itemSize: any): number)
|
||||||
);
|
);
|
||||||
const minOffset = Math.max(
|
const minOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
|
@ -51,13 +52,25 @@ const FixedSizeList = createListComponent({
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
case 'end':
|
case 'end':
|
||||||
return minOffset;
|
return minOffset;
|
||||||
case 'center':
|
case 'center': {
|
||||||
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
// "Centered" offset is usually the average of the min and max.
|
||||||
|
// But near the edges of the list, this doesn't hold true.
|
||||||
|
const middleOffset = Math.round(
|
||||||
|
minOffset + (maxOffset - minOffset) / 2
|
||||||
|
);
|
||||||
|
if (middleOffset < Math.ceil(size / 2)) {
|
||||||
|
return 0; // near the beginning
|
||||||
|
} else if (middleOffset > lastItemOffset + Math.floor(size / 2)) {
|
||||||
|
return lastItemOffset; // near the end
|
||||||
|
} else {
|
||||||
|
return middleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
case 'auto':
|
case 'auto':
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
@ -83,14 +96,14 @@ const FixedSizeList = createListComponent({
|
||||||
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
||||||
const offset = startIndex * ((itemSize: any): number);
|
const offset = startIndex * ((itemSize: any): number);
|
||||||
const size = (((isHorizontal ? width : height): any): number);
|
const size = (((isHorizontal ? width : height): any): number);
|
||||||
|
const numVisibleItems = Math.ceil(
|
||||||
|
(size + scrollOffset - offset) / ((itemSize: any): number)
|
||||||
|
);
|
||||||
return Math.max(
|
return Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
Math.min(
|
||||||
itemCount - 1,
|
itemCount - 1,
|
||||||
startIndex +
|
startIndex + numVisibleItems - 1 // -1 is because stop index is inclusive
|
||||||
Math.floor(
|
|
||||||
(size + (scrollOffset - offset)) / ((itemSize: any): number)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -274,7 +274,11 @@ const getOffsetForIndexAndAlignment = (
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (minOffset > maxOffset) {
|
||||||
|
// Because we only take into account the scrollbar size when calculating minOffset
|
||||||
|
// this value can be larger than maxOffset when at the end of the list
|
||||||
|
return minOffset;
|
||||||
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
|
|
@ -227,7 +227,7 @@ const VariableSizeList = createListComponent({
|
||||||
default:
|
default:
|
||||||
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
||||||
return scrollOffset;
|
return scrollOffset;
|
||||||
} else if (scrollOffset - minOffset < maxOffset - scrollOffset) {
|
} else if (scrollOffset < minOffset) {
|
||||||
return minOffset;
|
return minOffset;
|
||||||
} else {
|
} else {
|
||||||
return maxOffset;
|
return maxOffset;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
import { createElement, PureComponent } from 'react';
|
import { createElement, PureComponent } from 'react';
|
||||||
import { cancelTimeout, requestTimeout } from './timer';
|
import { cancelTimeout, requestTimeout } from './timer';
|
||||||
import { getScrollbarSize } from './domHelpers';
|
import { getScrollbarSize, getRTLOffsetType } from './domHelpers';
|
||||||
|
|
||||||
import type { TimeoutID } from './timer';
|
import type { TimeoutID } from './timer';
|
||||||
|
|
||||||
|
@ -46,6 +46,22 @@ type OnScrollCallback = ({
|
||||||
type ScrollEvent = SyntheticEvent<HTMLDivElement>;
|
type ScrollEvent = SyntheticEvent<HTMLDivElement>;
|
||||||
type ItemStyleCache = { [key: string]: Object };
|
type ItemStyleCache = { [key: string]: Object };
|
||||||
|
|
||||||
|
type OuterProps = {|
|
||||||
|
children: React$Node,
|
||||||
|
className: string | void,
|
||||||
|
onScroll: ScrollEvent => void,
|
||||||
|
style: {
|
||||||
|
[string]: mixed,
|
||||||
|
},
|
||||||
|
|};
|
||||||
|
|
||||||
|
type InnerProps = {|
|
||||||
|
children: React$Node,
|
||||||
|
style: {
|
||||||
|
[string]: mixed,
|
||||||
|
},
|
||||||
|
|};
|
||||||
|
|
||||||
export type Props<T> = {|
|
export type Props<T> = {|
|
||||||
children: RenderComponent<T>,
|
children: RenderComponent<T>,
|
||||||
className?: string,
|
className?: string,
|
||||||
|
@ -56,7 +72,7 @@ export type Props<T> = {|
|
||||||
initialScrollLeft?: number,
|
initialScrollLeft?: number,
|
||||||
initialScrollTop?: number,
|
initialScrollTop?: number,
|
||||||
innerRef?: any,
|
innerRef?: any,
|
||||||
innerElementType?: React$ElementType,
|
innerElementType?: string | React$AbstractComponent<InnerProps, any>,
|
||||||
innerTagName?: string, // deprecated
|
innerTagName?: string, // deprecated
|
||||||
itemData: T,
|
itemData: T,
|
||||||
itemKey?: (params: {|
|
itemKey?: (params: {|
|
||||||
|
@ -67,11 +83,13 @@ export type Props<T> = {|
|
||||||
onItemsRendered?: OnItemsRenderedCallback,
|
onItemsRendered?: OnItemsRenderedCallback,
|
||||||
onScroll?: OnScrollCallback,
|
onScroll?: OnScrollCallback,
|
||||||
outerRef?: any,
|
outerRef?: any,
|
||||||
outerElementType?: React$ElementType,
|
outerElementType?: string | React$AbstractComponent<OuterProps, any>,
|
||||||
outerTagName?: string, // deprecated
|
outerTagName?: string, // deprecated
|
||||||
overscanColumnsCount?: number,
|
overscanColumnCount?: number,
|
||||||
|
overscanColumnsCount?: number, // deprecated
|
||||||
overscanCount?: number, // deprecated
|
overscanCount?: number, // deprecated
|
||||||
overscanRowsCount?: number,
|
overscanRowCount?: number,
|
||||||
|
overscanRowsCount?: number, // deprecated
|
||||||
rowCount: number,
|
rowCount: number,
|
||||||
rowHeight: itemSize,
|
rowHeight: itemSize,
|
||||||
style?: Object,
|
style?: Object,
|
||||||
|
@ -130,10 +148,12 @@ const defaultItemKey = ({ columnIndex, data, rowIndex }) =>
|
||||||
// In DEV mode, this Set helps us only log a warning once per component instance.
|
// In DEV mode, this Set helps us only log a warning once per component instance.
|
||||||
// This avoids spamming the console every time a render happens.
|
// This avoids spamming the console every time a render happens.
|
||||||
let devWarningsOverscanCount = null;
|
let devWarningsOverscanCount = null;
|
||||||
|
let devWarningsOverscanRowsColumnsCount = null;
|
||||||
let devWarningsTagName = null;
|
let devWarningsTagName = null;
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
if (typeof window !== 'undefined' && typeof window.WeakSet !== 'undefined') {
|
if (typeof window !== 'undefined' && typeof window.WeakSet !== 'undefined') {
|
||||||
devWarningsOverscanCount = new WeakSet();
|
devWarningsOverscanCount = new WeakSet();
|
||||||
|
devWarningsOverscanRowsColumnsCount = new WeakSet();
|
||||||
devWarningsTagName = new WeakSet();
|
devWarningsTagName = new WeakSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,21 +340,47 @@ export default function createGridComponent({
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { initialScrollLeft, initialScrollTop } = this.props;
|
const { initialScrollLeft, initialScrollTop } = this.props;
|
||||||
if (typeof initialScrollLeft === 'number' && this._outerRef != null) {
|
|
||||||
((this._outerRef: any): HTMLDivElement).scrollLeft = initialScrollLeft;
|
if (this._outerRef != null) {
|
||||||
}
|
const outerRef = ((this._outerRef: any): HTMLElement);
|
||||||
if (typeof initialScrollTop === 'number' && this._outerRef != null) {
|
if (typeof initialScrollLeft === 'number') {
|
||||||
((this._outerRef: any): HTMLDivElement).scrollTop = initialScrollTop;
|
outerRef.scrollLeft = initialScrollLeft;
|
||||||
|
}
|
||||||
|
if (typeof initialScrollTop === 'number') {
|
||||||
|
outerRef.scrollTop = initialScrollTop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
const { direction } = this.props;
|
||||||
const { scrollLeft, scrollTop, scrollUpdateWasRequested } = this.state;
|
const { scrollLeft, scrollTop, scrollUpdateWasRequested } = this.state;
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
|
||||||
((this._outerRef: any): HTMLDivElement).scrollLeft = scrollLeft;
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
((this._outerRef: any): HTMLDivElement).scrollTop = scrollTop;
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
const outerRef = ((this._outerRef: any): HTMLElement);
|
||||||
|
if (direction === 'rtl') {
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollLeft;
|
||||||
|
break;
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollLeft;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const { clientWidth, scrollWidth } = outerRef;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = Math.max(0, scrollLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
outerRef.scrollTop = Math.max(0, scrollTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._callPropsCallbacks();
|
this._callPropsCallbacks();
|
||||||
|
@ -432,7 +478,7 @@ export default function createGridComponent({
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: estimatedTotalHeight,
|
height: estimatedTotalHeight,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: estimatedTotalWidth,
|
width: estimatedTotalWidth,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -586,6 +632,7 @@ export default function createGridComponent({
|
||||||
_getHorizontalRangeToRender(): [number, number, number, number] {
|
_getHorizontalRangeToRender(): [number, number, number, number] {
|
||||||
const {
|
const {
|
||||||
columnCount,
|
columnCount,
|
||||||
|
overscanColumnCount,
|
||||||
overscanColumnsCount,
|
overscanColumnsCount,
|
||||||
overscanCount,
|
overscanCount,
|
||||||
rowCount,
|
rowCount,
|
||||||
|
@ -593,7 +640,7 @@ export default function createGridComponent({
|
||||||
const { horizontalScrollDirection, isScrolling, scrollLeft } = this.state;
|
const { horizontalScrollDirection, isScrolling, scrollLeft } = this.state;
|
||||||
|
|
||||||
const overscanCountResolved: number =
|
const overscanCountResolved: number =
|
||||||
overscanColumnsCount || overscanCount || 1;
|
overscanColumnCount || overscanColumnsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -634,13 +681,14 @@ export default function createGridComponent({
|
||||||
const {
|
const {
|
||||||
columnCount,
|
columnCount,
|
||||||
overscanCount,
|
overscanCount,
|
||||||
|
overscanRowCount,
|
||||||
overscanRowsCount,
|
overscanRowsCount,
|
||||||
rowCount,
|
rowCount,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { isScrolling, verticalScrollDirection, scrollTop } = this.state;
|
const { isScrolling, verticalScrollDirection, scrollTop } = this.state;
|
||||||
|
|
||||||
const overscanCountResolved: number =
|
const overscanCountResolved: number =
|
||||||
overscanRowsCount || overscanCount || 1;
|
overscanRowCount || overscanRowsCount || overscanCount || 1;
|
||||||
|
|
||||||
if (columnCount === 0 || rowCount === 0) {
|
if (columnCount === 0 || rowCount === 0) {
|
||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
|
@ -679,9 +727,11 @@ export default function createGridComponent({
|
||||||
|
|
||||||
_onScroll = (event: ScrollEvent): void => {
|
_onScroll = (event: ScrollEvent): void => {
|
||||||
const {
|
const {
|
||||||
|
clientHeight,
|
||||||
clientWidth,
|
clientWidth,
|
||||||
scrollLeft,
|
scrollLeft,
|
||||||
scrollTop,
|
scrollTop,
|
||||||
|
scrollHeight,
|
||||||
scrollWidth,
|
scrollWidth,
|
||||||
} = event.currentTarget;
|
} = event.currentTarget;
|
||||||
this.setState(prevState => {
|
this.setState(prevState => {
|
||||||
|
@ -697,24 +747,38 @@ export default function createGridComponent({
|
||||||
|
|
||||||
const { direction } = this.props;
|
const { direction } = this.props;
|
||||||
|
|
||||||
// HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
let calculatedScrollLeft = scrollLeft;
|
let calculatedScrollLeft = scrollLeft;
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
switch (getRTLOffsetType()) {
|
||||||
calculatedScrollLeft = -scrollLeft;
|
case 'negative':
|
||||||
} else {
|
calculatedScrollLeft = -scrollLeft;
|
||||||
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
break;
|
||||||
|
case 'positive-descending':
|
||||||
|
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
calculatedScrollLeft = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(calculatedScrollLeft, scrollWidth - clientWidth)
|
||||||
|
);
|
||||||
|
const calculatedScrollTop = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(scrollTop, scrollHeight - clientHeight)
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
horizontalScrollDirection:
|
horizontalScrollDirection:
|
||||||
prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
||||||
scrollLeft: calculatedScrollLeft,
|
scrollLeft: calculatedScrollLeft,
|
||||||
scrollTop,
|
scrollTop: calculatedScrollTop,
|
||||||
verticalScrollDirection:
|
verticalScrollDirection:
|
||||||
prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
||||||
scrollUpdateWasRequested: false,
|
scrollUpdateWasRequested: false,
|
||||||
|
@ -768,7 +832,9 @@ const validateSharedProps = (
|
||||||
height,
|
height,
|
||||||
innerTagName,
|
innerTagName,
|
||||||
outerTagName,
|
outerTagName,
|
||||||
|
overscanColumnsCount,
|
||||||
overscanCount,
|
overscanCount,
|
||||||
|
overscanRowsCount,
|
||||||
width,
|
width,
|
||||||
}: Props<any>,
|
}: Props<any>,
|
||||||
{ instance }: State
|
{ instance }: State
|
||||||
|
@ -779,7 +845,23 @@ const validateSharedProps = (
|
||||||
devWarningsOverscanCount.add(instance);
|
devWarningsOverscanCount.add(instance);
|
||||||
console.warn(
|
console.warn(
|
||||||
'The overscanCount prop has been deprecated. ' +
|
'The overscanCount prop has been deprecated. ' +
|
||||||
'Please use the overscanColumnsCount and overscanRowsCount props instead.'
|
'Please use the overscanColumnCount and overscanRowCount props instead.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof overscanColumnsCount === 'number' ||
|
||||||
|
typeof overscanRowsCount === 'number'
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
devWarningsOverscanRowsColumnsCount &&
|
||||||
|
!devWarningsOverscanRowsColumnsCount.has(instance)
|
||||||
|
) {
|
||||||
|
devWarningsOverscanRowsColumnsCount.add(instance);
|
||||||
|
console.warn(
|
||||||
|
'The overscanColumnsCount and overscanRowsCount props have been deprecated. ' +
|
||||||
|
'Please use the overscanColumnCount and overscanRowCount props instead.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
import { createElement, PureComponent } from 'react';
|
import { createElement, PureComponent } from 'react';
|
||||||
import { cancelTimeout, requestTimeout } from './timer';
|
import { cancelTimeout, requestTimeout } from './timer';
|
||||||
|
import { getRTLOffsetType } from './domHelpers';
|
||||||
|
|
||||||
import type { TimeoutID } from './timer';
|
import type { TimeoutID } from './timer';
|
||||||
|
|
||||||
|
@ -38,6 +39,22 @@ type onScrollCallback = ({
|
||||||
type ScrollEvent = SyntheticEvent<HTMLDivElement>;
|
type ScrollEvent = SyntheticEvent<HTMLDivElement>;
|
||||||
type ItemStyleCache = { [index: number]: Object };
|
type ItemStyleCache = { [index: number]: Object };
|
||||||
|
|
||||||
|
type OuterProps = {|
|
||||||
|
children: React$Node,
|
||||||
|
className: string | void,
|
||||||
|
onScroll: ScrollEvent => void,
|
||||||
|
style: {
|
||||||
|
[string]: mixed,
|
||||||
|
},
|
||||||
|
|};
|
||||||
|
|
||||||
|
type InnerProps = {|
|
||||||
|
children: React$Node,
|
||||||
|
style: {
|
||||||
|
[string]: mixed,
|
||||||
|
},
|
||||||
|
|};
|
||||||
|
|
||||||
export type Props<T> = {|
|
export type Props<T> = {|
|
||||||
children: RenderComponent<T>,
|
children: RenderComponent<T>,
|
||||||
className?: string,
|
className?: string,
|
||||||
|
@ -45,7 +62,7 @@ export type Props<T> = {|
|
||||||
height: number | string,
|
height: number | string,
|
||||||
initialScrollOffset?: number,
|
initialScrollOffset?: number,
|
||||||
innerRef?: any,
|
innerRef?: any,
|
||||||
innerElementType?: React$ElementType,
|
innerElementType?: string | React$AbstractComponent<InnerProps, any>,
|
||||||
innerTagName?: string, // deprecated
|
innerTagName?: string, // deprecated
|
||||||
itemCount: number,
|
itemCount: number,
|
||||||
itemData: T,
|
itemData: T,
|
||||||
|
@ -55,7 +72,7 @@ export type Props<T> = {|
|
||||||
onItemsRendered?: onItemsRenderedCallback,
|
onItemsRendered?: onItemsRenderedCallback,
|
||||||
onScroll?: onScrollCallback,
|
onScroll?: onScrollCallback,
|
||||||
outerRef?: any,
|
outerRef?: any,
|
||||||
outerElementType?: React$ElementType,
|
outerElementType?: string | React$AbstractComponent<OuterProps, any>,
|
||||||
outerTagName?: string, // deprecated
|
outerTagName?: string, // deprecated
|
||||||
overscanCount: number,
|
overscanCount: number,
|
||||||
style?: Object,
|
style?: Object,
|
||||||
|
@ -215,14 +232,13 @@ export default function createListComponent({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { direction, initialScrollOffset, layout } = this.props;
|
const { direction, initialScrollOffset, layout } = this.props;
|
||||||
|
|
||||||
if (typeof initialScrollOffset === 'number' && this._outerRef !== null) {
|
if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
|
||||||
|
const outerRef = ((this._outerRef: any): HTMLElement);
|
||||||
// TODO Deprecate direction "horizontal"
|
// TODO Deprecate direction "horizontal"
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
((this
|
outerRef.scrollLeft = initialScrollOffset;
|
||||||
._outerRef: any): HTMLDivElement).scrollLeft = initialScrollOffset;
|
|
||||||
} else {
|
} else {
|
||||||
((this
|
outerRef.scrollTop = initialScrollOffset;
|
||||||
._outerRef: any): HTMLDivElement).scrollTop = initialScrollOffset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,12 +249,32 @@ export default function createListComponent({
|
||||||
const { direction, layout } = this.props;
|
const { direction, layout } = this.props;
|
||||||
const { scrollOffset, scrollUpdateWasRequested } = this.state;
|
const { scrollOffset, scrollUpdateWasRequested } = this.state;
|
||||||
|
|
||||||
if (scrollUpdateWasRequested && this._outerRef !== null) {
|
if (scrollUpdateWasRequested && this._outerRef != null) {
|
||||||
|
const outerRef = ((this._outerRef: any): HTMLElement);
|
||||||
|
|
||||||
// TODO Deprecate direction "horizontal"
|
// TODO Deprecate direction "horizontal"
|
||||||
if (direction === 'horizontal' || layout === 'horizontal') {
|
if (direction === 'horizontal' || layout === 'horizontal') {
|
||||||
((this._outerRef: any): HTMLDivElement).scrollLeft = scrollOffset;
|
if (direction === 'rtl') {
|
||||||
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
|
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
outerRef.scrollLeft = -scrollOffset;
|
||||||
|
break;
|
||||||
|
case 'positive-ascending':
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const { clientWidth, scrollWidth } = outerRef;
|
||||||
|
outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outerRef.scrollLeft = scrollOffset;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
((this._outerRef: any): HTMLDivElement).scrollTop = scrollOffset;
|
outerRef.scrollTop = scrollOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +362,7 @@ export default function createListComponent({
|
||||||
ref: innerRef,
|
ref: innerRef,
|
||||||
style: {
|
style: {
|
||||||
height: isHorizontal ? '100%' : estimatedTotalSize,
|
height: isHorizontal ? '100%' : estimatedTotalSize,
|
||||||
pointerEvents: isScrolling ? 'none' : '',
|
pointerEvents: isScrolling ? 'none' : undefined,
|
||||||
width: isHorizontal ? estimatedTotalSize : '100%',
|
width: isHorizontal ? estimatedTotalSize : '100%',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -496,18 +532,28 @@ export default function createListComponent({
|
||||||
|
|
||||||
const { direction } = this.props;
|
const { direction } = this.props;
|
||||||
|
|
||||||
// HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
||||||
// Chrome does not seem to adhere; its scrolLeft values are positive (measured relative to the left).
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
|
|
||||||
let scrollOffset = scrollLeft;
|
let scrollOffset = scrollLeft;
|
||||||
if (direction === 'rtl') {
|
if (direction === 'rtl') {
|
||||||
if (scrollLeft <= 0) {
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
scrollOffset = -scrollOffset;
|
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
||||||
} else {
|
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
||||||
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
||||||
|
switch (getRTLOffsetType()) {
|
||||||
|
case 'negative':
|
||||||
|
scrollOffset = -scrollLeft;
|
||||||
|
break;
|
||||||
|
case 'positive-descending':
|
||||||
|
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
scrollOffset = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(scrollOffset, scrollWidth - clientWidth)
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection:
|
scrollDirection:
|
||||||
|
@ -519,7 +565,7 @@ export default function createListComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
_onScrollVertical = (event: ScrollEvent): void => {
|
_onScrollVertical = (event: ScrollEvent): void => {
|
||||||
const { scrollTop } = event.currentTarget;
|
const { clientHeight, scrollHeight, scrollTop } = event.currentTarget;
|
||||||
this.setState(prevState => {
|
this.setState(prevState => {
|
||||||
if (prevState.scrollOffset === scrollTop) {
|
if (prevState.scrollOffset === scrollTop) {
|
||||||
// Scroll position may have been updated by cDM/cDU,
|
// Scroll position may have been updated by cDM/cDU,
|
||||||
|
@ -528,11 +574,17 @@ export default function createListComponent({
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
||||||
|
const scrollOffset = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(scrollTop, scrollHeight - clientHeight)
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isScrolling: true,
|
isScrolling: true,
|
||||||
scrollDirection:
|
scrollDirection:
|
||||||
prevState.scrollOffset < scrollTop ? 'forward' : 'backward',
|
prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
||||||
scrollOffset: scrollTop,
|
scrollOffset,
|
||||||
scrollUpdateWasRequested: false,
|
scrollUpdateWasRequested: false,
|
||||||
};
|
};
|
||||||
}, this._resetIsScrollingDebounced);
|
}, this._resetIsScrollingDebounced);
|
||||||
|
|
|
@ -20,3 +20,53 @@ export function getScrollbarSize(recalculate?: boolean = false): number {
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RTLOffsetType =
|
||||||
|
| 'negative'
|
||||||
|
| 'positive-descending'
|
||||||
|
| 'positive-ascending';
|
||||||
|
|
||||||
|
let cachedRTLResult: RTLOffsetType | null = null;
|
||||||
|
|
||||||
|
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
||||||
|
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
||||||
|
// Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
|
||||||
|
// The safest way to check this is to intentionally set a negative offset,
|
||||||
|
// and then verify that the subsequent "scroll" event matches the negative offset.
|
||||||
|
// If it does not match, then we can assume a non-standard RTL scroll implementation.
|
||||||
|
export function getRTLOffsetType(recalculate?: boolean = false): RTLOffsetType {
|
||||||
|
if (cachedRTLResult === null || recalculate) {
|
||||||
|
const outerDiv = document.createElement('div');
|
||||||
|
const outerStyle = outerDiv.style;
|
||||||
|
outerStyle.width = '50px';
|
||||||
|
outerStyle.height = '50px';
|
||||||
|
outerStyle.overflow = 'scroll';
|
||||||
|
outerStyle.direction = 'rtl';
|
||||||
|
|
||||||
|
const innerDiv = document.createElement('div');
|
||||||
|
const innerStyle = innerDiv.style;
|
||||||
|
innerStyle.width = '100px';
|
||||||
|
innerStyle.height = '100px';
|
||||||
|
|
||||||
|
outerDiv.appendChild(innerDiv);
|
||||||
|
|
||||||
|
((document.body: any): HTMLBodyElement).appendChild(outerDiv);
|
||||||
|
|
||||||
|
if (outerDiv.scrollLeft > 0) {
|
||||||
|
cachedRTLResult = 'positive-descending';
|
||||||
|
} else {
|
||||||
|
outerDiv.scrollLeft = 1;
|
||||||
|
if (outerDiv.scrollLeft === 0) {
|
||||||
|
cachedRTLResult = 'negative';
|
||||||
|
} else {
|
||||||
|
cachedRTLResult = 'positive-ascending';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
((document.body: any): HTMLBodyElement).removeChild(outerDiv);
|
||||||
|
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedRTLResult;
|
||||||
|
}
|
||||||
|
|
26
yarn.lock
26
yarn.lock
|
@ -766,9 +766,9 @@
|
||||||
regenerator-runtime "^0.12.0"
|
regenerator-runtime "^0.12.0"
|
||||||
|
|
||||||
"@babel/runtime@^7.0.0":
|
"@babel/runtime@^7.0.0":
|
||||||
version "7.4.5"
|
version "7.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
||||||
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
|
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
|
@ -5522,10 +5522,10 @@ flatstr@^1.0.9:
|
||||||
resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.9.tgz#0950d56fec02de1030c1311847ecd58c25690eb9"
|
resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.9.tgz#0950d56fec02de1030c1311847ecd58c25690eb9"
|
||||||
integrity sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw==
|
integrity sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw==
|
||||||
|
|
||||||
flow-bin@^0.97.0:
|
flow-bin@^0.103.0:
|
||||||
version "0.97.0"
|
version "0.103.0"
|
||||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83"
|
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.103.0.tgz#7aec510d85e1c1b0f2b912bb988337d70035cb0f"
|
||||||
integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w==
|
integrity sha512-Y3yrnE5ICN1Kl/y10BwjA3JSuS+gt4jVPNyUNCZb0RqmkdssMrW8QNNysJYvhgAY/JBJH8Qv7NVUf11MiwfSlA==
|
||||||
|
|
||||||
fluent-syntax@0.10.0:
|
fluent-syntax@0.10.0:
|
||||||
version "0.10.0"
|
version "0.10.0"
|
||||||
|
@ -8250,9 +8250,9 @@ mem@^4.0.0:
|
||||||
p-is-promise "^2.0.0"
|
p-is-promise "^2.0.0"
|
||||||
|
|
||||||
"memoize-one@>=3.1.1 <6":
|
"memoize-one@>=3.1.1 <6":
|
||||||
version "5.0.4"
|
version "5.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc"
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e"
|
||||||
integrity sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA==
|
integrity sha512-ey6EpYv0tEaIbM/nTDOpHciXUvd+ackQrJgEzBwemhZZIWZjcyodqEcrmqDy2BKRTM3a65kKBV4WtLXJDt26SQ==
|
||||||
|
|
||||||
memoize-one@^3.1.1:
|
memoize-one@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
|
@ -10183,9 +10183,9 @@ regenerator-runtime@^0.12.0:
|
||||||
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
|
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
|
||||||
|
|
||||||
regenerator-runtime@^0.13.2:
|
regenerator-runtime@^0.13.2:
|
||||||
version "0.13.2"
|
version "0.13.3"
|
||||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
|
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
|
||||||
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
|
integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
|
||||||
|
|
||||||
regenerator-runtime@^0.9.5:
|
regenerator-runtime@^0.9.5:
|
||||||
version "0.9.6"
|
version "0.9.6"
|
||||||
|
|
Loading…
Reference in New Issue