react-cosmos-core 6.0.0-alpha.17 → 6.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fixtureTree/createFixtureTree/createRawFixtureTree.d.ts +1 -1
- package/dist/fixtureTree/createFixtureTree/index.d.ts +1 -1
- package/dist/fixtureTree/flattenFixtureTree.d.ts +1 -1
- package/dist/index.d.ts +20 -18
- package/dist/index.js +20 -18
- package/dist/playground/playgroundParams.d.ts +4 -0
- package/dist/playground/playgroundQueryString.d.ts +3 -0
- package/dist/playground/playgroundQueryString.js +21 -0
- package/dist/renderer/{rendererConnectTypes.d.ts → rendererConnect.d.ts} +11 -14
- package/dist/renderer/rendererParams.d.ts +6 -0
- package/dist/renderer/rendererQueryString.d.ts +10 -0
- package/dist/renderer/rendererQueryString.js +33 -0
- package/dist/userModules/getFixtureFromExport.d.ts +2 -0
- package/dist/{renderer/getFixture.js → userModules/getFixtureFromExport.js} +1 -1
- package/dist/{renderer → userModules}/getFixtureList.d.ts +1 -1
- package/dist/{renderer → userModules}/userModuleTypes.d.ts +0 -5
- package/dist/userModules/userModuleTypes.js +1 -0
- package/dist/utils/queryString.d.ts +2 -0
- package/dist/utils/queryString.js +7 -0
- package/dist/utils/react/ClassStateMock.d.ts +2 -1
- package/dist/utils/react/DelayRender.d.ts +7 -0
- package/dist/utils/react/DelayRender.js +10 -0
- package/dist/utils/window.d.ts +1 -0
- package/dist/utils/window.js +8 -0
- package/package.json +3 -3
- package/dist/fixture/FixtureContext.d.ts +0 -7
- package/dist/fixture/FixtureContext.js +0 -5
- package/dist/fixture/Viewport.d.ts +0 -8
- package/dist/fixture/Viewport.js +0 -19
- package/dist/fixture/useSelect/index.d.ts +0 -2
- package/dist/fixture/useSelect/index.js +0 -11
- package/dist/fixture/useSelect/shared.d.ts +0 -6
- package/dist/fixture/useSelect/shared.js +0 -3
- package/dist/fixture/useSelect/useCreateFixtureState.d.ts +0 -2
- package/dist/fixture/useSelect/useCreateFixtureState.js +0 -32
- package/dist/fixture/useSelect/useCurrentValue.d.ts +0 -2
- package/dist/fixture/useSelect/useCurrentValue.js +0 -11
- package/dist/fixture/useSelect/useSetValue.d.ts +0 -2
- package/dist/fixture/useSelect/useSetValue.js +0 -25
- package/dist/fixture/useValue/index.d.ts +0 -7
- package/dist/fixture/useValue/index.js +0 -9
- package/dist/fixture/useValue/shared.d.ts +0 -3
- package/dist/fixture/useValue/useCreateFixtureState.d.ts +0 -2
- package/dist/fixture/useValue/useCreateFixtureState.js +0 -35
- package/dist/fixture/useValue/useCurrentValue.d.ts +0 -2
- package/dist/fixture/useValue/useCurrentValue.js +0 -13
- package/dist/fixture/useValue/useSetValue.d.ts +0 -3
- package/dist/fixture/useValue/useSetValue.js +0 -36
- package/dist/playground/playgroundUrl.d.ts +0 -13
- package/dist/playground/playgroundUrl.js +0 -36
- package/dist/renderer/DecoratedFixture.d.ts +0 -14
- package/dist/renderer/DecoratedFixture.js +0 -33
- package/dist/renderer/FixtureCapture/classState/decorateFixtureRefs/index.d.ts +0 -5
- package/dist/renderer/FixtureCapture/classState/decorateFixtureRefs/index.js +0 -46
- package/dist/renderer/FixtureCapture/classState/decorateFixtureRefs/isRefSupported.d.ts +0 -4
- package/dist/renderer/FixtureCapture/classState/decorateFixtureRefs/isRefSupported.js +0 -19
- package/dist/renderer/FixtureCapture/classState/index.d.ts +0 -3
- package/dist/renderer/FixtureCapture/classState/index.js +0 -13
- package/dist/renderer/FixtureCapture/classState/shared.d.ts +0 -18
- package/dist/renderer/FixtureCapture/classState/shared.js +0 -14
- package/dist/renderer/FixtureCapture/classState/useFixtureState.d.ts +0 -4
- package/dist/renderer/FixtureCapture/classState/useFixtureState.js +0 -156
- package/dist/renderer/FixtureCapture/classState/useReadClassState.d.ts +0 -4
- package/dist/renderer/FixtureCapture/classState/useReadClassState.js +0 -60
- package/dist/renderer/FixtureCapture/index.d.ts +0 -7
- package/dist/renderer/FixtureCapture/index.js +0 -9
- package/dist/renderer/FixtureCapture/props/index.d.ts +0 -3
- package/dist/renderer/FixtureCapture/props/index.js +0 -77
- package/dist/renderer/FixtureCapture/props/useFixtureProps.d.ts +0 -3
- package/dist/renderer/FixtureCapture/props/useFixtureProps.js +0 -70
- package/dist/renderer/FixtureCapture/shared/findRelevantElementPaths.d.ts +0 -2
- package/dist/renderer/FixtureCapture/shared/findRelevantElementPaths.js +0 -23
- package/dist/renderer/FixtureCapture/shared/nodeTree/findElementPaths.d.ts +0 -2
- package/dist/renderer/FixtureCapture/shared/nodeTree/findElementPaths.js +0 -22
- package/dist/renderer/FixtureCapture/shared/nodeTree/getElementAtPath.d.ts +0 -3
- package/dist/renderer/FixtureCapture/shared/nodeTree/getElementAtPath.js +0 -26
- package/dist/renderer/FixtureCapture/shared/nodeTree/index.d.ts +0 -11
- package/dist/renderer/FixtureCapture/shared/nodeTree/index.js +0 -11
- package/dist/renderer/FixtureCapture/shared/nodeTree/setElementAtPath.d.ts +0 -2
- package/dist/renderer/FixtureCapture/shared/nodeTree/setElementAtPath.js +0 -35
- package/dist/renderer/FixtureCapture/shared/nodeTree/shared.d.ts +0 -2
- package/dist/renderer/FixtureCapture/shared/nodeTree/shared.js +0 -6
- package/dist/renderer/FixtureConnect.d.ts +0 -17
- package/dist/renderer/FixtureConnect.js +0 -27
- package/dist/renderer/FixtureLoader.d.ts +0 -17
- package/dist/renderer/FixtureLoader.js +0 -16
- package/dist/renderer/FixtureStateChangeResponse.d.ts +0 -11
- package/dist/renderer/FixtureStateChangeResponse.js +0 -34
- package/dist/renderer/LazyFixtureListItemUpdate.d.ts +0 -10
- package/dist/renderer/LazyFixtureListItemUpdate.js +0 -15
- package/dist/renderer/LazyFixtureLoader.d.ts +0 -20
- package/dist/renderer/LazyFixtureLoader.js +0 -22
- package/dist/renderer/createPostMessageConnect.d.ts +0 -2
- package/dist/renderer/createPostMessageConnect.js +0 -22
- package/dist/renderer/createWebSocketsConnect.d.ts +0 -2
- package/dist/renderer/createWebSocketsConnect.js +0 -32
- package/dist/renderer/getDecoratedFixtureElement/FixtureElement.d.ts +0 -9
- package/dist/renderer/getDecoratedFixtureElement/FixtureElement.js +0 -5
- package/dist/renderer/getDecoratedFixtureElement/index.d.ts +0 -3
- package/dist/renderer/getDecoratedFixtureElement/index.js +0 -15
- package/dist/renderer/getFixture.d.ts +0 -2
- package/dist/renderer/useFixtureModules.d.ts +0 -2
- package/dist/renderer/useFixtureModules.js +0 -10
- package/dist/renderer/useLazyFixtureModules.d.ts +0 -2
- package/dist/renderer/useLazyFixtureModules.js +0 -24
- package/dist/renderer/useRendererRequest.d.ts +0 -5
- package/dist/renderer/useRendererRequest.js +0 -81
- package/dist/renderer/useRendererResponse.d.ts +0 -4
- package/dist/renderer/useRendererResponse.js +0 -23
- package/dist/renderer/useSelectedFixture.d.ts +0 -14
- package/dist/renderer/useSelectedFixture.js +0 -31
- /package/dist/{server → message}/serverMessage.d.ts +0 -0
- /package/dist/{server → message}/serverMessage.js +0 -0
- /package/dist/{server → message}/socketMessage.d.ts +0 -0
- /package/dist/{server → message}/socketMessage.js +0 -0
- /package/dist/{fixture/types.js → playground/playgroundParams.js} +0 -0
- /package/dist/{renderer → playground}/registerPlaygroundShortcuts.d.ts +0 -0
- /package/dist/{renderer → playground}/registerPlaygroundShortcuts.js +0 -0
- /package/dist/{server → plugin}/cosmosPluginConfig.d.ts +0 -0
- /package/dist/{server → plugin}/cosmosPluginConfig.js +0 -0
- /package/dist/{fixture/useValue/shared.js → renderer/rendererConnect.js} +0 -0
- /package/dist/renderer/{rendererConnectTypes.js → rendererParams.js} +0 -0
- /package/dist/{fixture/types.d.ts → userModules/fixtureTypes.d.ts} +0 -0
- /package/dist/{renderer/userModuleTypes.js → userModules/fixtureTypes.js} +0 -0
- /package/dist/{renderer → userModules}/getFixtureList.js +0 -0
- /package/dist/{renderer → userModules}/getSortedDecoratorsForFixturePath.d.ts +0 -0
- /package/dist/{renderer → userModules}/getSortedDecoratorsForFixturePath.js +0 -0
- /package/dist/{renderer → userModules}/isMultiFixture.d.ts +0 -0
- /package/dist/{renderer → userModules}/isMultiFixture.js +0 -0
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { findFixtureStateControl } from '../../fixtureState/controls.js';
|
|
3
|
-
import { extendWithValue } from '../../fixtureState/extendWithValues.js';
|
|
4
|
-
import { FixtureContext } from '../FixtureContext.js';
|
|
5
|
-
export function useCurrentValue(inputName, defaultValue) {
|
|
6
|
-
const { fixtureState } = React.useContext(FixtureContext);
|
|
7
|
-
const fsControl = findFixtureStateControl(fixtureState, inputName);
|
|
8
|
-
return fsControl && fsControl.type === 'standard'
|
|
9
|
-
? // Types of fixture state values cannot be guaranteed at read time, which
|
|
10
|
-
// means that tampering with the fixture state can cause runtime errors
|
|
11
|
-
extendWithValue(defaultValue, fsControl.currentValue)
|
|
12
|
-
: defaultValue;
|
|
13
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { findFixtureStateControl } from '../../fixtureState/controls.js';
|
|
3
|
-
import { createValue } from '../../fixtureState/createValues.js';
|
|
4
|
-
import { extendWithValue } from '../../fixtureState/extendWithValues.js';
|
|
5
|
-
import { FixtureContext } from '../FixtureContext.js';
|
|
6
|
-
export function useSetValue(inputName, defaultValue) {
|
|
7
|
-
const { setFixtureState } = React.useContext(FixtureContext);
|
|
8
|
-
return React.useCallback(stateChange => {
|
|
9
|
-
setFixtureState(prevFs => {
|
|
10
|
-
const currentValue = typeof stateChange === 'function'
|
|
11
|
-
? stateChange(
|
|
12
|
-
// Types of fixture state values cannot be guaranteed at read
|
|
13
|
-
// time, which means that tampering with the fixture state can
|
|
14
|
-
// cause runtime errors
|
|
15
|
-
getCurrentValueFromFixtureState(prevFs, inputName, defaultValue))
|
|
16
|
-
: stateChange;
|
|
17
|
-
return {
|
|
18
|
-
...prevFs,
|
|
19
|
-
controls: {
|
|
20
|
-
...prevFs.controls,
|
|
21
|
-
[inputName]: {
|
|
22
|
-
type: 'standard',
|
|
23
|
-
defaultValue: createValue(defaultValue),
|
|
24
|
-
currentValue: createValue(currentValue),
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
});
|
|
29
|
-
}, [setFixtureState, defaultValue, inputName]);
|
|
30
|
-
}
|
|
31
|
-
function getCurrentValueFromFixtureState(fixtureState, inputName, defaultValue) {
|
|
32
|
-
const fsControl = findFixtureStateControl(fixtureState, inputName);
|
|
33
|
-
return fsControl && fsControl.type === 'standard'
|
|
34
|
-
? extendWithValue(defaultValue, fsControl.currentValue)
|
|
35
|
-
: defaultValue;
|
|
36
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FixtureId } from '../fixture/types.js';
|
|
2
|
-
export type PlaygroundUrlParams = {
|
|
3
|
-
fixtureId?: FixtureId;
|
|
4
|
-
};
|
|
5
|
-
export type RendererUrlParams = {
|
|
6
|
-
_fixtureId?: FixtureId;
|
|
7
|
-
};
|
|
8
|
-
export declare function stringifyPlaygroundUrlQuery(urlParams: PlaygroundUrlParams): string;
|
|
9
|
-
export declare function parsePlaygroundUrlQuery(query: string): PlaygroundUrlParams;
|
|
10
|
-
export declare function stringifyRendererUrlQuery(urlParams: RendererUrlParams): string;
|
|
11
|
-
export declare function parseRendererUrlQuery(query: string): RendererUrlParams;
|
|
12
|
-
export declare function parseUrlQuery<T extends {}>(query: string): T;
|
|
13
|
-
export declare function stringifyUrlQuery(params: {}): string;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export function stringifyPlaygroundUrlQuery(urlParams) {
|
|
2
|
-
const encodedUrlParams = {};
|
|
3
|
-
if (urlParams.fixtureId) {
|
|
4
|
-
encodedUrlParams.fixtureId = JSON.stringify(urlParams.fixtureId);
|
|
5
|
-
}
|
|
6
|
-
return stringifyUrlQuery(encodedUrlParams);
|
|
7
|
-
}
|
|
8
|
-
export function parsePlaygroundUrlQuery(query) {
|
|
9
|
-
const encodedUrlParams = parseUrlQuery(query);
|
|
10
|
-
const decoded = {};
|
|
11
|
-
if (encodedUrlParams.fixtureId) {
|
|
12
|
-
decoded.fixtureId = JSON.parse(encodedUrlParams.fixtureId);
|
|
13
|
-
}
|
|
14
|
-
return decoded;
|
|
15
|
-
}
|
|
16
|
-
export function stringifyRendererUrlQuery(urlParams) {
|
|
17
|
-
const encodedUrlParams = {};
|
|
18
|
-
if (urlParams._fixtureId) {
|
|
19
|
-
encodedUrlParams._fixtureId = JSON.stringify(urlParams._fixtureId);
|
|
20
|
-
}
|
|
21
|
-
return stringifyUrlQuery(encodedUrlParams);
|
|
22
|
-
}
|
|
23
|
-
export function parseRendererUrlQuery(query) {
|
|
24
|
-
const encodedUrlParams = parseUrlQuery(query);
|
|
25
|
-
const decoded = {};
|
|
26
|
-
if (encodedUrlParams._fixtureId) {
|
|
27
|
-
decoded._fixtureId = JSON.parse(encodedUrlParams._fixtureId);
|
|
28
|
-
}
|
|
29
|
-
return decoded;
|
|
30
|
-
}
|
|
31
|
-
export function parseUrlQuery(query) {
|
|
32
|
-
return Object.fromEntries(new URLSearchParams(query));
|
|
33
|
-
}
|
|
34
|
-
export function stringifyUrlQuery(params) {
|
|
35
|
-
return new URLSearchParams(params).toString();
|
|
36
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
import { FixtureState, SetFixtureState } from '../fixtureState/types.js';
|
|
3
|
-
import { ReactDecorator, ReactDecoratorModule, ReactFixture } from './userModuleTypes.js';
|
|
4
|
-
type Props = {
|
|
5
|
-
fixture: ReactFixture;
|
|
6
|
-
systemDecorators: ReactDecorator[];
|
|
7
|
-
userDecoratorModules: ReactDecoratorModule[];
|
|
8
|
-
fixtureState: FixtureState;
|
|
9
|
-
setFixtureState: SetFixtureState;
|
|
10
|
-
renderKey: number;
|
|
11
|
-
onErrorReset?: () => unknown;
|
|
12
|
-
};
|
|
13
|
-
export declare function DecoratedFixture({ fixture, systemDecorators, userDecoratorModules, fixtureState, setFixtureState, renderKey, onErrorReset, }: Props): JSX.Element;
|
|
14
|
-
export {};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
2
|
-
import { FixtureContext } from '../fixture/FixtureContext.js';
|
|
3
|
-
import { getDecoratedFixtureElement } from './getDecoratedFixtureElement/index.js';
|
|
4
|
-
export function DecoratedFixture({ fixture, systemDecorators, userDecoratorModules, fixtureState, setFixtureState, renderKey, onErrorReset = noop, }) {
|
|
5
|
-
// Prevent unintentional renders https://reactjs.org/docs/context.html#caveats
|
|
6
|
-
const contextValue = useMemo(() => ({ fixtureState, setFixtureState }), [fixtureState, setFixtureState]);
|
|
7
|
-
const decoratedFixture = useMemo(() => {
|
|
8
|
-
const decorators = [
|
|
9
|
-
...systemDecorators,
|
|
10
|
-
...userDecoratorModules.map(m => m.default),
|
|
11
|
-
];
|
|
12
|
-
return getDecoratedFixtureElement(fixture, decorators, {
|
|
13
|
-
fixtureState,
|
|
14
|
-
setFixtureState,
|
|
15
|
-
onErrorReset,
|
|
16
|
-
});
|
|
17
|
-
}, [
|
|
18
|
-
fixture,
|
|
19
|
-
fixtureState,
|
|
20
|
-
onErrorReset,
|
|
21
|
-
setFixtureState,
|
|
22
|
-
systemDecorators,
|
|
23
|
-
userDecoratorModules,
|
|
24
|
-
]);
|
|
25
|
-
return (React.createElement(FixtureContext.Provider
|
|
26
|
-
// renderKey controls whether to reuse previous instances (and
|
|
27
|
-
// transition props) or rebuild render tree from scratch
|
|
28
|
-
, {
|
|
29
|
-
// renderKey controls whether to reuse previous instances (and
|
|
30
|
-
// transition props) or rebuild render tree from scratch
|
|
31
|
-
key: renderKey, value: contextValue }, decoratedFixture));
|
|
32
|
-
}
|
|
33
|
-
function noop() { }
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { Component, ReactNode } from 'react';
|
|
2
|
-
import { CachedRefHandlers } from '../shared.js';
|
|
3
|
-
type SpyRef = (elPath: string, elRef: null | Component) => unknown;
|
|
4
|
-
export declare function decorateFixtureRefs(fixture: ReactNode, spyRef: SpyRef, cachedRefHandlers: CachedRefHandlers): ReactNode;
|
|
5
|
-
export {};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { cloneElement, } from 'react';
|
|
2
|
-
import { findRelevantElementPaths } from '../../shared/findRelevantElementPaths.js';
|
|
3
|
-
import { setElementAtPath } from '../../shared/nodeTree/index.js';
|
|
4
|
-
import { isRefSupported } from './isRefSupported.js';
|
|
5
|
-
export function decorateFixtureRefs(fixture, spyRef, cachedRefHandlers) {
|
|
6
|
-
const elPaths = findRelevantElementPaths(fixture);
|
|
7
|
-
return elPaths.reduce((decoratedFixture, elPath) => {
|
|
8
|
-
return setElementAtPath(decoratedFixture, elPath, element => {
|
|
9
|
-
if (!isRefSupported(element.type)) {
|
|
10
|
-
return element;
|
|
11
|
-
}
|
|
12
|
-
return cloneElement(element, {
|
|
13
|
-
ref: getDecoratedRef(element.ref, spyRef, elPath, cachedRefHandlers),
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
}, fixture);
|
|
17
|
-
}
|
|
18
|
-
function getDecoratedRef(origRef, spyRef, elPath, cachedRefHandlers) {
|
|
19
|
-
const found = cachedRefHandlers[elPath];
|
|
20
|
-
if (found && found.origRef === origRef) {
|
|
21
|
-
return found.handler;
|
|
22
|
-
}
|
|
23
|
-
const handler = decorateRefWithSpy(origRef, spyRef, elPath);
|
|
24
|
-
cachedRefHandlers[elPath] = { origRef, handler };
|
|
25
|
-
return handler;
|
|
26
|
-
}
|
|
27
|
-
function decorateRefWithSpy(origRef, spyRef, elPath) {
|
|
28
|
-
return (elRef) => {
|
|
29
|
-
if (origRef) {
|
|
30
|
-
callOriginalRef(origRef, elRef);
|
|
31
|
-
}
|
|
32
|
-
spyRef(elPath, elRef);
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function callOriginalRef(ref, elRef) {
|
|
36
|
-
if (typeof ref === 'string') {
|
|
37
|
-
console.warn('[decorateFixtureRefs] String refs are not supported');
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (typeof ref === 'function') {
|
|
41
|
-
ref(elRef);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const refObj = ref;
|
|
45
|
-
refObj.current = elRef;
|
|
46
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ForwardRef } from 'react-is';
|
|
3
|
-
export function isRefSupported(elementType) {
|
|
4
|
-
if (typeof elementType === 'string') {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
const { $$typeof, prototype } = elementType;
|
|
8
|
-
return ($$typeof === ForwardRef ||
|
|
9
|
-
// Warning: Some functions don't have the .prototype property
|
|
10
|
-
(prototype &&
|
|
11
|
-
// ES6 Class
|
|
12
|
-
// Warning: This will return false is the component is extending a
|
|
13
|
-
// different copy of React than the one used by Cosmos. This is relevant
|
|
14
|
-
// when running Cosmos from an external location instead of node_modules.
|
|
15
|
-
(prototype instanceof React.Component ||
|
|
16
|
-
// React.createClass
|
|
17
|
-
prototype.getInitialState !== undefined) &&
|
|
18
|
-
true));
|
|
19
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useFixtureState } from './useFixtureState.js';
|
|
3
|
-
import { useReadClassState } from './useReadClassState.js';
|
|
4
|
-
export function useClassStateCapture(fixture, decoratorId) {
|
|
5
|
-
const elRefs = React.useRef({});
|
|
6
|
-
React.useEffect(() => {
|
|
7
|
-
return () => {
|
|
8
|
-
elRefs.current = {};
|
|
9
|
-
};
|
|
10
|
-
}, []);
|
|
11
|
-
useReadClassState(fixture, decoratorId, elRefs);
|
|
12
|
-
return useFixtureState(fixture, decoratorId, elRefs);
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export type ElRefs = {
|
|
3
|
-
[elPath: string]: React.Component;
|
|
4
|
-
};
|
|
5
|
-
export type InitialStates = {
|
|
6
|
-
[elPath: string]: {
|
|
7
|
-
type: React.ComponentClass<any>;
|
|
8
|
-
state: {};
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
export type CachedRefHandler = {
|
|
12
|
-
origRef: null | React.Ref<any>;
|
|
13
|
-
handler: (elRef: null | React.Component) => unknown;
|
|
14
|
-
};
|
|
15
|
-
export type CachedRefHandlers = {
|
|
16
|
-
[elPath: string]: CachedRefHandler;
|
|
17
|
-
};
|
|
18
|
-
export declare function replaceState(elRef: React.Component, nextState: {}): void;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { isEqual } from 'lodash-es';
|
|
2
|
-
// We need to do this because React doesn't provide a replaceState method
|
|
3
|
-
// (anymore) https://reactjs.org/docs/react-component.html#setstate
|
|
4
|
-
export function replaceState(elRef, nextState) {
|
|
5
|
-
const fullState = resetOriginalKeys(elRef.state, nextState);
|
|
6
|
-
if (!isEqual(fullState, elRef.state)) {
|
|
7
|
-
elRef.setState(fullState);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
function resetOriginalKeys(original, current) {
|
|
11
|
-
return Object.keys(original).reduce((result, key) => Object.keys(result).indexOf(key) === -1
|
|
12
|
-
? { ...result, [key]: undefined }
|
|
13
|
-
: result, current);
|
|
14
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { MutableRefObject, ReactNode } from 'react';
|
|
2
|
-
import { FixtureDecoratorId } from '../../../fixtureState/types.js';
|
|
3
|
-
import { ElRefs } from './shared.js';
|
|
4
|
-
export declare function useFixtureState(fixture: ReactNode, decoratorId: FixtureDecoratorId, elRefs: MutableRefObject<ElRefs>): ReactNode;
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { isEqual } from 'lodash-es';
|
|
2
|
-
import { useContext, useEffect, useRef, } from 'react';
|
|
3
|
-
import { FixtureContext } from '../../../fixture/FixtureContext.js';
|
|
4
|
-
import { createFixtureStateClassState, findFixtureStateClassState, getFixtureStateClassState, removeFixtureStateClassState, } from '../../../fixtureState/classState.js';
|
|
5
|
-
import { createValues } from '../../../fixtureState/createValues.js';
|
|
6
|
-
import { extendWithValues } from '../../../fixtureState/extendWithValues.js';
|
|
7
|
-
import { getComponentName } from '../../../utils/react/getComponentName.js';
|
|
8
|
-
import { findRelevantElementPaths } from '../shared/findRelevantElementPaths.js';
|
|
9
|
-
import { decorateFixtureRefs } from './decorateFixtureRefs/index.js';
|
|
10
|
-
import { replaceState, } from './shared.js';
|
|
11
|
-
export function useFixtureState(fixture, decoratorId, elRefs) {
|
|
12
|
-
const elPaths = findRelevantElementPaths(fixture);
|
|
13
|
-
const { fixtureState, setFixtureState } = useContext(FixtureContext);
|
|
14
|
-
const lastFixtureState = useFixtureStateRef(fixtureState);
|
|
15
|
-
// Keep a copy of the previous fixture state to observe changes
|
|
16
|
-
const prevFixtureState = useRef(fixtureState);
|
|
17
|
-
// Remember initial state of child components to use as a default when
|
|
18
|
-
// resetting fixture state
|
|
19
|
-
const initialStates = useRef({});
|
|
20
|
-
// Ref handlers are reused because every time we pass a new ref handler to
|
|
21
|
-
// a React element it gets called in the next render loop, even when the
|
|
22
|
-
// associated element instance has been preserved. Having ref handlers fire
|
|
23
|
-
// on every render loop results in unwanted operations and race conditions.
|
|
24
|
-
const cachedRefHandlers = useRef({});
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
return () => {
|
|
27
|
-
initialStates.current = {};
|
|
28
|
-
cachedRefHandlers.current = {};
|
|
29
|
-
};
|
|
30
|
-
}, []);
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
// Remove fixture state for removed child elements (likely via HMR)
|
|
33
|
-
// FIXME: Also invalidate fixture state at this element path if the
|
|
34
|
-
// component type of the corresponding element changed
|
|
35
|
-
const fsProps = getFixtureStateClassState(fixtureState, decoratorId);
|
|
36
|
-
fsProps.forEach(({ elementId }) => {
|
|
37
|
-
const { elPath } = elementId;
|
|
38
|
-
if (elPaths.indexOf(elementId.elPath) === -1) {
|
|
39
|
-
setFixtureState(prevFs => ({
|
|
40
|
-
...prevFs,
|
|
41
|
-
classState: removeFixtureStateClassState(fixtureState, elementId),
|
|
42
|
-
}));
|
|
43
|
-
if (elRefs.current[elPath]) {
|
|
44
|
-
delete elRefs.current[elPath];
|
|
45
|
-
delete initialStates.current[elPath];
|
|
46
|
-
delete cachedRefHandlers.current[elPath];
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
elPaths.forEach(elPath => {
|
|
51
|
-
const elementId = { decoratorId, elPath };
|
|
52
|
-
// Component fixture state can be provided before the fixture mounts (eg.
|
|
53
|
-
// a previous snapshot of a fixture state or the current fixture state
|
|
54
|
-
// from another renderer)
|
|
55
|
-
const fsClassState = findFixtureStateClassState(fixtureState, elementId);
|
|
56
|
-
if (!fsClassState) {
|
|
57
|
-
if (initialStates.current[elPath]) {
|
|
58
|
-
const { state } = initialStates.current[elPath];
|
|
59
|
-
const elRef = elRefs.current[elPath];
|
|
60
|
-
if (!isEqual(elRef.state, state)) {
|
|
61
|
-
replaceState(elRef, state);
|
|
62
|
-
}
|
|
63
|
-
setFixtureState(prevFs => ({
|
|
64
|
-
...prevFs,
|
|
65
|
-
classState: createFixtureStateClassState({
|
|
66
|
-
fixtureState: prevFs,
|
|
67
|
-
elementId,
|
|
68
|
-
values: createValues(state),
|
|
69
|
-
componentName: getComponentName(elRef.constructor),
|
|
70
|
-
}),
|
|
71
|
-
}));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
const elRef = elRefs.current[elPath];
|
|
76
|
-
// The el ref can be missing for three reasons:
|
|
77
|
-
// 1. Element type is stateless
|
|
78
|
-
// 2. Element type is a class, but doesn't have state. An instance exists
|
|
79
|
-
// but has been discarded because of its lack of state.
|
|
80
|
-
// 3. Element instance unmounted and is about to remount. When this
|
|
81
|
-
// happens, the new instance will be handled when its ref fires again.
|
|
82
|
-
if (!elRef) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
// The child's state can be out of sync with the fixture state for two
|
|
86
|
-
// reasons:
|
|
87
|
-
// 1. The child's state changed internally
|
|
88
|
-
// 2. The fixture state changed
|
|
89
|
-
// Here we're interested in the second scenario. In the first scenario
|
|
90
|
-
// we want to let the component state override the fixture state.
|
|
91
|
-
const prevFsClassState = findFixtureStateClassState(prevFixtureState.current, elementId);
|
|
92
|
-
if (prevFsClassState && !isEqual(prevFsClassState, fsClassState)) {
|
|
93
|
-
return replaceState(elRef, extendWithValues(elRef.state, fsClassState.values));
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}, [
|
|
98
|
-
decoratorId,
|
|
99
|
-
elPaths,
|
|
100
|
-
elRefs,
|
|
101
|
-
fixtureState,
|
|
102
|
-
fixtureState.classState,
|
|
103
|
-
setFixtureState,
|
|
104
|
-
]);
|
|
105
|
-
// Update prev fixture state ref *after* running effects that reference it
|
|
106
|
-
useEffect(() => {
|
|
107
|
-
prevFixtureState.current = fixtureState;
|
|
108
|
-
});
|
|
109
|
-
return decorateFixtureRefs(fixture, handleRef, cachedRefHandlers.current);
|
|
110
|
-
function handleRef(elPath, elRef) {
|
|
111
|
-
if (!elRef) {
|
|
112
|
-
delete elRefs.current[elPath];
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
// Only track instances with state
|
|
116
|
-
const { state } = elRef;
|
|
117
|
-
if (!state) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
elRefs.current[elPath] = elRef;
|
|
121
|
-
setInitialState(initialStates.current, elPath, elRef);
|
|
122
|
-
const elementId = { decoratorId, elPath };
|
|
123
|
-
const fsClassState = findFixtureStateClassState(lastFixtureState.current, elementId);
|
|
124
|
-
if (!fsClassState) {
|
|
125
|
-
setFixtureState(prevFs => ({
|
|
126
|
-
...prevFs,
|
|
127
|
-
classState: createFixtureStateClassState({
|
|
128
|
-
fixtureState: prevFs,
|
|
129
|
-
elementId,
|
|
130
|
-
values: createValues(state),
|
|
131
|
-
componentName: getComponentName(elRef.constructor),
|
|
132
|
-
}),
|
|
133
|
-
}));
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
replaceState(elRef, extendWithValues(state, fsClassState.values));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Make latest fixture state accessible in ref callback
|
|
141
|
-
function useFixtureStateRef(fixtureState) {
|
|
142
|
-
const ref = useRef(fixtureState);
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
ref.current = fixtureState;
|
|
145
|
-
});
|
|
146
|
-
return ref;
|
|
147
|
-
}
|
|
148
|
-
function setInitialState(initialStates, elPath, elRef) {
|
|
149
|
-
const found = initialStates[elPath];
|
|
150
|
-
const type = elRef.constructor;
|
|
151
|
-
// Keep the first state recevied for this type
|
|
152
|
-
const initialStateExists = found && found.type === type;
|
|
153
|
-
if (!initialStateExists && elRef.state) {
|
|
154
|
-
initialStates[elPath] = { type, state: elRef.state };
|
|
155
|
-
}
|
|
156
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { MutableRefObject, ReactNode } from 'react';
|
|
2
|
-
import { FixtureDecoratorId } from '../../../fixtureState/types.js';
|
|
3
|
-
import { ElRefs } from './shared.js';
|
|
4
|
-
export declare function useReadClassState(fixture: ReactNode, decoratorId: FixtureDecoratorId, elRefs: MutableRefObject<ElRefs>): void;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { isEqual } from 'lodash-es';
|
|
2
|
-
import { useContext, useEffect, useRef, } from 'react';
|
|
3
|
-
import { FixtureContext } from '../../../fixture/FixtureContext.js';
|
|
4
|
-
import { findFixtureStateClassState, updateFixtureStateClassState, } from '../../../fixtureState/classState.js';
|
|
5
|
-
import { createValues } from '../../../fixtureState/createValues.js';
|
|
6
|
-
import { extendWithValues } from '../../../fixtureState/extendWithValues.js';
|
|
7
|
-
import { findRelevantElementPaths } from '../shared/findRelevantElementPaths.js';
|
|
8
|
-
// How often to check the state of the loaded component and update the fixture
|
|
9
|
-
// state if it changed
|
|
10
|
-
const REFRESH_INTERVAL = 200;
|
|
11
|
-
export function useReadClassState(fixture, decoratorId, elRefs) {
|
|
12
|
-
const elPaths = findRelevantElementPaths(fixture);
|
|
13
|
-
const { fixtureState, setFixtureState } = useContext(FixtureContext);
|
|
14
|
-
const timeoutId = useRef(null);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
// The check should run even if no element paths are found at mount, because
|
|
17
|
-
// the fixture can change during the lifecycle of a FixtureCapture instance
|
|
18
|
-
// and the updated fixture might contain elements of stateful components
|
|
19
|
-
scheduleStateCheck();
|
|
20
|
-
return () => {
|
|
21
|
-
if (timeoutId.current) {
|
|
22
|
-
clearTimeout(timeoutId.current);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
function scheduleStateCheck() {
|
|
27
|
-
// Is there a better way to listen to component state changes?
|
|
28
|
-
timeoutId.current = window.setTimeout(checkState, REFRESH_INTERVAL);
|
|
29
|
-
}
|
|
30
|
-
function checkState() {
|
|
31
|
-
let fixtureStateChangeScheduled = false;
|
|
32
|
-
Object.keys(elRefs.current).map(async (elPath) => {
|
|
33
|
-
if (elPaths.indexOf(elPath) === -1) {
|
|
34
|
-
throw new Error(`[FixtureCapture] Child ref exists for missing element path "${elPath}"`);
|
|
35
|
-
}
|
|
36
|
-
const { state } = elRefs.current[elPath];
|
|
37
|
-
const elementId = { decoratorId, elPath };
|
|
38
|
-
const fsClassState = findFixtureStateClassState(fixtureState, elementId);
|
|
39
|
-
if (fsClassState &&
|
|
40
|
-
state &&
|
|
41
|
-
!doesFixtureStateMatchClassState(fsClassState, state)) {
|
|
42
|
-
fixtureStateChangeScheduled = true;
|
|
43
|
-
setFixtureState(prevFs => ({
|
|
44
|
-
...prevFs,
|
|
45
|
-
classState: updateFixtureStateClassState({
|
|
46
|
-
fixtureState: prevFs,
|
|
47
|
-
elementId,
|
|
48
|
-
values: createValues(state),
|
|
49
|
-
}),
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
if (!fixtureStateChangeScheduled) {
|
|
54
|
-
scheduleStateCheck();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function doesFixtureStateMatchClassState(fsClassState, state) {
|
|
59
|
-
return isEqual(state, extendWithValues(state, fsClassState.values));
|
|
60
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { FixtureDecoratorId } from '../../fixtureState/types.js';
|
|
3
|
-
export type Props = {
|
|
4
|
-
children: React.ReactNode;
|
|
5
|
-
decoratorId: FixtureDecoratorId;
|
|
6
|
-
};
|
|
7
|
-
export declare function FixtureCapture({ children, decoratorId }: Props): JSX.Element;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useClassStateCapture } from './classState/index.js';
|
|
3
|
-
import { usePropsCapture } from './props/index.js';
|
|
4
|
-
export function FixtureCapture({ children, decoratorId }) {
|
|
5
|
-
let fixture = usePropsCapture(children, decoratorId);
|
|
6
|
-
fixture = useClassStateCapture(fixture, decoratorId);
|
|
7
|
-
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
|
|
8
|
-
return React.createElement(React.Fragment, null, fixture);
|
|
9
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { useContext, useEffect, useRef } from 'react';
|
|
2
|
-
import { FixtureContext } from '../../../fixture/FixtureContext.js';
|
|
3
|
-
import { createValues } from '../../../fixtureState/createValues.js';
|
|
4
|
-
import { createFixtureStateProps, findFixtureStateProps, getFixtureStateProps, removeFixtureStateProps, updateFixtureStateProps, } from '../../../fixtureState/props.js';
|
|
5
|
-
import { areNodesEqual } from '../../../utils/react/areNodesEqual.js';
|
|
6
|
-
import { getComponentName } from '../../../utils/react/getComponentName.js';
|
|
7
|
-
import { findRelevantElementPaths } from '../shared/findRelevantElementPaths.js';
|
|
8
|
-
import { getElementAtPath, getExpectedElementAtPath, } from '../shared/nodeTree/index.js';
|
|
9
|
-
import { useFixtureProps } from './useFixtureProps.js';
|
|
10
|
-
export function usePropsCapture(fixture, decoratorId) {
|
|
11
|
-
const { fixtureState, setFixtureState } = useContext(FixtureContext);
|
|
12
|
-
const prevFixtureRef = useRef(fixture);
|
|
13
|
-
const elPaths = findRelevantElementPaths(fixture);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
// Create empty fixture state
|
|
16
|
-
if (!fixtureState.props && elPaths.length === 0) {
|
|
17
|
-
// Make sure not to override any (currently pending) fixture state props
|
|
18
|
-
setFixtureState(prevFs => ({ ...prevFs, props: prevFs.props || [] }));
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
// Remove fixture state for removed child elements (likely via HMR)
|
|
22
|
-
// FIXME: Also invalidate fixture state at this element path if the
|
|
23
|
-
// component type of the corresponding element changed
|
|
24
|
-
const fsProps = getFixtureStateProps(fixtureState, decoratorId);
|
|
25
|
-
fsProps.forEach(({ elementId }) => {
|
|
26
|
-
if (elPaths.indexOf(elementId.elPath) === -1) {
|
|
27
|
-
setFixtureState(prevFs => ({
|
|
28
|
-
...prevFs,
|
|
29
|
-
props: removeFixtureStateProps(fixtureState, elementId),
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
elPaths.forEach(elPath => {
|
|
34
|
-
const childEl = getExpectedElementAtPath(fixture, elPath);
|
|
35
|
-
const elementId = { decoratorId, elPath };
|
|
36
|
-
// Component fixture state can be provided before the fixture mounts (eg.
|
|
37
|
-
// a previous snapshot of a fixture state or the current fixture state
|
|
38
|
-
// from another renderer)
|
|
39
|
-
if (!findFixtureStateProps(fixtureState, elementId)) {
|
|
40
|
-
const componentName = getComponentName(childEl.type);
|
|
41
|
-
setFixtureState(prevFs => ({
|
|
42
|
-
...prevFs,
|
|
43
|
-
props: createFixtureStateProps({
|
|
44
|
-
fixtureState: prevFs,
|
|
45
|
-
elementId,
|
|
46
|
-
values: createValues(childEl.props),
|
|
47
|
-
componentName,
|
|
48
|
-
}),
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
const prevChildEl = getElementAtPath(prevFixtureRef.current, elPath);
|
|
53
|
-
if (!areNodesEqual(prevChildEl, childEl, false)) {
|
|
54
|
-
setFixtureState(prevFs => ({
|
|
55
|
-
...prevFs,
|
|
56
|
-
props: updateFixtureStateProps({
|
|
57
|
-
fixtureState,
|
|
58
|
-
elementId,
|
|
59
|
-
values: createValues(childEl.props),
|
|
60
|
-
}),
|
|
61
|
-
}));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}, [
|
|
66
|
-
fixture,
|
|
67
|
-
decoratorId,
|
|
68
|
-
elPaths,
|
|
69
|
-
fixtureState,
|
|
70
|
-
fixtureState.props,
|
|
71
|
-
setFixtureState,
|
|
72
|
-
]);
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
prevFixtureRef.current = fixture;
|
|
75
|
-
});
|
|
76
|
-
return useFixtureProps(fixture, fixtureState, decoratorId);
|
|
77
|
-
}
|