react-cosmos-core 6.1.2-canary.db623aa.0 → 6.2.0

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.
@@ -1,3 +1,4 @@
1
- import { FixtureStateValue, FixtureStateValues, ObjectData } from './types.js';
1
+ import { ObjectData } from '../utils/data.js';
2
+ import { FixtureStateValue, FixtureStateValues } from './types.js';
2
3
  export declare function createValues(obj: ObjectData): FixtureStateValues;
3
4
  export declare function createValue(data: unknown): FixtureStateValue;
@@ -1,5 +1,5 @@
1
1
  import { isElement } from 'react-is';
2
- import { isArray, isObject, isPrimitiveData } from './shared.js';
2
+ import { isArray, isObject, isPrimitiveData, } from '../utils/data.js';
3
3
  export function createValues(obj) {
4
4
  const values = {};
5
5
  Object.keys(obj).forEach(key => {
@@ -32,8 +32,20 @@ export function createValue(data) {
32
32
  };
33
33
  }
34
34
  function stringifyUnserializableData(data) {
35
+ if (typeof data === 'function') {
36
+ return stringifyFunction(data);
37
+ }
35
38
  // NOTE: We used to use the react-element-to-jsx-string package but it added
36
39
  // bloat and complicated ESM support. We might go back to something similar
37
40
  // in the future. Or expose a plugin API for custom stringifiers.
38
41
  return isElement(data) ? '<React.Element />' : String(data);
39
42
  }
43
+ const emptyFnRegex = /^\(\) => \{.+\}$/s;
44
+ function stringifyFunction(data) {
45
+ // This clears space from empty function bodies. It originates as a fix for
46
+ // Vitest tests that needed to create deterministic fixture state values, but
47
+ // it cleans up how stringified functions look in the Cosmos UI as well.
48
+ // Potential improvement: Remove all extra indentation from function bodies
49
+ // to match the root-level function header indentation.
50
+ return String(data).replace(emptyFnRegex, '() => {}');
51
+ }
@@ -1,3 +1,4 @@
1
- import { FixtureStateValue, FixtureStateValues, ObjectData } from './types.js';
1
+ import { ObjectData } from '../utils/data.js';
2
+ import { FixtureStateValue, FixtureStateValues } from './types.js';
2
3
  export declare function extendWithValues(obj: ObjectData, values: FixtureStateValues): ObjectData;
3
4
  export declare function extendWithValue(data: unknown, value: FixtureStateValue): unknown;
@@ -1,4 +1,4 @@
1
- import { isArray, isObject } from './shared.js';
1
+ import { isArray, isObject } from '../utils/data.js';
2
2
  // Use fixture state for serializable values and fall back to base values
3
3
  export function extendWithValues(obj, values) {
4
4
  const extendedObj = {};
@@ -1,3 +1,4 @@
1
+ import { PrimitiveData } from '../utils/data.js';
1
2
  import { StateUpdater } from '../utils/state.js';
2
3
  export type FixtureDecoratorId = string;
3
4
  export type FixtureElementId = {
@@ -8,9 +9,6 @@ export type FixtureStateUnserializableValue = {
8
9
  type: 'unserializable';
9
10
  stringifiedData: string;
10
11
  };
11
- export type PrimitiveData = string | number | boolean | null | undefined;
12
- export type ObjectData = Record<string, unknown>;
13
- export type ArrayData = unknown[];
14
12
  export type FixtureStatePrimitiveValue = {
15
13
  type: 'primitive';
16
14
  data: PrimitiveData;
package/dist/index.d.ts CHANGED
@@ -30,13 +30,14 @@ export * from './userModules/getSortedDecoratorsForFixturePath.js';
30
30
  export * from './userModules/stringifyFixtureId.js';
31
31
  export * from './userModules/userModuleTypes.js';
32
32
  export * from './utils/array.js';
33
+ export * from './utils/data.js';
33
34
  export * from './utils/keys.js';
34
35
  export * from './utils/queryString.js';
35
- export * from './utils/react/ClassStateMock.js';
36
- export * from './utils/react/DelayRender.js';
37
36
  export * from './utils/react/areNodesEqual.js';
37
+ export * from './utils/react/DelayRender.js';
38
38
  export * from './utils/react/getComponentName.js';
39
39
  export * from './utils/react/isReactElement.js';
40
+ export * from './utils/serializable.js';
40
41
  export * from './utils/state.js';
41
42
  export * from './utils/string.js';
42
43
  export * from './utils/tree.js';
package/dist/index.js CHANGED
@@ -30,13 +30,14 @@ export * from './userModules/getSortedDecoratorsForFixturePath.js';
30
30
  export * from './userModules/stringifyFixtureId.js';
31
31
  export * from './userModules/userModuleTypes.js';
32
32
  export * from './utils/array.js';
33
+ export * from './utils/data.js';
33
34
  export * from './utils/keys.js';
34
35
  export * from './utils/queryString.js';
35
- export * from './utils/react/ClassStateMock.js';
36
- export * from './utils/react/DelayRender.js';
37
36
  export * from './utils/react/areNodesEqual.js';
37
+ export * from './utils/react/DelayRender.js';
38
38
  export * from './utils/react/getComponentName.js';
39
39
  export * from './utils/react/isReactElement.js';
40
+ export * from './utils/serializable.js';
40
41
  export * from './utils/state.js';
41
42
  export * from './utils/string.js';
42
43
  export * from './utils/tree.js';
@@ -58,6 +58,7 @@ export type FixtureLoadedResponse = {
58
58
  payload: {
59
59
  rendererId: RendererId;
60
60
  fixture: FixtureListItem;
61
+ fixtureOptions: {};
61
62
  };
62
63
  };
63
64
  export type FixtureStateChangeResponse = {
@@ -2,5 +2,11 @@ import { isElement } from 'react-is';
2
2
  export function isMultiFixture(fixtureExport) {
3
3
  return (fixtureExport !== null &&
4
4
  typeof fixtureExport === 'object' &&
5
- !isElement(fixtureExport));
5
+ !isElement(fixtureExport) &&
6
+ // With React Server Components, fixture exports of Client fixtures are
7
+ // wrapped in a Promise. The React ComponentType union does include
8
+ // PromiseLikeOfReactNode but for some reason it's impossible do type
9
+ // narrowing or use a type predicate function.
10
+ // @ts-ignore Sadly, we resort to the "cause I said so" type assertion
11
+ typeof fixtureExport.then !== 'function');
6
12
  }
@@ -1,10 +1,11 @@
1
- import { ComponentType, FunctionComponent, ReactNode } from 'react';
1
+ import { ComponentType, ReactNode } from 'react';
2
2
  type FixtureMap<FixtureType> = {
3
3
  [fixtureName: string]: FixtureType;
4
4
  };
5
5
  type FixtureExport<FixtureType> = FixtureType | FixtureMap<FixtureType>;
6
6
  type FixtureModule<FixtureType> = {
7
7
  default: FixtureExport<FixtureType>;
8
+ options?: {};
8
9
  };
9
10
  type ModuleWrapper<ModuleType> = {
10
11
  module: ModuleType;
@@ -12,18 +13,19 @@ type ModuleWrapper<ModuleType> = {
12
13
  type LazyModuleWrapper<ModuleType> = {
13
14
  getModule: () => Promise<ModuleType>;
14
15
  };
15
- export type ReactFixture = ReactNode | FunctionComponent;
16
+ export type ReactFixture = ReactNode | ComponentType;
16
17
  export type ReactFixtureMap = FixtureMap<ReactFixture>;
17
18
  export type ReactFixtureExport = FixtureExport<ReactFixture>;
18
19
  export type ReactFixtureModule = FixtureModule<ReactFixture>;
19
20
  export type ReactFixtureWrapper = ModuleWrapper<ReactFixtureModule>;
20
21
  export type LazyReactFixtureWrapper = LazyModuleWrapper<ReactFixtureModule>;
21
- export type ReactDecoratorProps = {
22
+ export type DecoratorProps<T = {}> = {
22
23
  children: ReactNode;
24
+ options: T;
23
25
  };
24
- export type ReactDecorator = ComponentType<ReactDecoratorProps>;
26
+ export type ReactDecorator<T = {}> = ComponentType<DecoratorProps<T>>;
25
27
  export type ReactDecoratorModule = {
26
- default: ReactDecorator;
28
+ default: ReactDecorator<any> | ReactDecorator<any>[];
27
29
  };
28
30
  export type ReactDecoratorWrapper = ModuleWrapper<ReactDecoratorModule>;
29
31
  export type LazyReactDecoratorWrapper = LazyModuleWrapper<ReactDecoratorModule>;
@@ -1,4 +1,6 @@
1
- import { ArrayData, ObjectData, PrimitiveData } from './types.js';
1
+ export type PrimitiveData = string | number | boolean | null | undefined;
2
+ export type ObjectData = Record<string, unknown>;
3
+ export type ArrayData = unknown[];
2
4
  export declare function isString(value: unknown): value is string;
3
5
  export declare function isNumber(value: unknown): value is number;
4
6
  export declare function isBoolean(value: unknown): value is boolean;
@@ -0,0 +1,4 @@
1
+ export declare function pickSerializableValues(object: Record<string, unknown>): {
2
+ [k: string]: unknown;
3
+ };
4
+ export declare function isSerializable(data: unknown): boolean;
@@ -0,0 +1,11 @@
1
+ import { isArray, isObject, isPrimitiveData } from './data.js';
2
+ export function pickSerializableValues(object) {
3
+ return Object.fromEntries(Object.entries(object).filter(([k, v]) => isSerializable(v)));
4
+ }
5
+ export function isSerializable(data) {
6
+ if (isObject(data))
7
+ return Object.values(data).every(isSerializable);
8
+ if (isArray(data))
9
+ return data.every(isSerializable);
10
+ return isPrimitiveData(data);
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-cosmos-core",
3
- "version": "6.1.2-canary.db623aa.0+db623aa",
3
+ "version": "6.2.0",
4
4
  "description": "React Cosmos Core",
5
5
  "repository": "https://github.com/react-cosmos/react-cosmos/tree/main/packages/react-cosmos-core",
6
6
  "license": "MIT",
@@ -10,7 +10,7 @@
10
10
  "dependencies": {
11
11
  "js-base64": "3.7.7",
12
12
  "lodash-es": "4.17.21",
13
- "react-is": "18.2.0"
13
+ "react-is": "18.3.1"
14
14
  },
15
- "gitHead": "db623aa4837dff16466b0cda1617fcda5d2f071d"
15
+ "gitHead": "965bf0e13230324699560be6eabb642c51c6d945"
16
16
  }
@@ -1,13 +0,0 @@
1
- import React from 'react';
2
- type Props = {
3
- children: React.ClassicElement<unknown>;
4
- state?: {};
5
- };
6
- export declare class ClassStateMock extends React.Component<Props> {
7
- static cosmosCapture: boolean;
8
- childRef: React.Component | null;
9
- render(): React.CElement<unknown, React.Component<{}, {}, any>>;
10
- componentDidUpdate(prevProps: Props): void;
11
- handleRef: (childRef: React.Component | null) => void;
12
- }
13
- export {};
@@ -1,72 +0,0 @@
1
- import { isEqual } from 'lodash-es';
2
- import React from 'react';
3
- // Compied from https://github.com/skidding/react-mock/blob/c33dfa1d6f0c9ce7b3eaba073618d61731a0e82e/packages/state/src/index.js
4
- export class ClassStateMock extends React.Component {
5
- static cosmosCapture = false;
6
- childRef = null;
7
- render() {
8
- const { children } = this.props;
9
- if (Array.isArray(children)) {
10
- throw new Error('ClassStateMock only accepts a single child element');
11
- }
12
- return React.cloneElement(children, { ref: this.handleRef });
13
- }
14
- componentDidUpdate(prevProps) {
15
- const { childRef } = this;
16
- const { state } = this.props;
17
- if (!childRef) {
18
- throw new Error('childRef missing in ClassStateMock.componentDidUpdate');
19
- }
20
- if (state && !isEqual(state, prevProps.state)) {
21
- replaceState(childRef, state);
22
- }
23
- }
24
- handleRef = (childRef) => {
25
- const prevRef = this.props.children.ref;
26
- this.childRef = childRef;
27
- if (!childRef) {
28
- if (prevRef)
29
- manuallyCallRef(prevRef, childRef);
30
- // Nothing else to do on the unmount branch (when refs are set to NULL)
31
- return;
32
- }
33
- if (this.props.state) {
34
- // Wait until state has been set to call prev ref. This will give the
35
- // impression that the mocked state is the initial state.
36
- replaceState(childRef, this.props.state, () => {
37
- manuallyCallRef(prevRef, childRef);
38
- });
39
- }
40
- else {
41
- manuallyCallRef(prevRef, childRef);
42
- }
43
- };
44
- }
45
- function replaceState(childRef, state, cb) {
46
- // We need to unset existing state keys because React doesn't provide a
47
- // replaceState method (anymore)
48
- // https://reactjs.org/docs/react-component.html#setstate
49
- const nextState = resetOriginalKeys(childRef.state, state);
50
- if (!isEqual(nextState, childRef.state)) {
51
- childRef.setState(nextState, cb);
52
- }
53
- }
54
- function resetOriginalKeys(original, current) {
55
- const { keys } = Object;
56
- return keys(original).reduce((result, key) => keys(result).indexOf(key) === -1
57
- ? { ...result, [key]: undefined }
58
- : result, current);
59
- }
60
- function manuallyCallRef(ref, elRef) {
61
- if (typeof ref === 'string') {
62
- throw new Error('StateMock does not support string refs');
63
- }
64
- // https://reactjs.org/docs/refs-and-the-dom.html#creating-refs
65
- if (typeof ref === 'function') {
66
- ref(elRef);
67
- }
68
- else if (ref && typeof ref === 'object') {
69
- // @ts-ignore
70
- ref.current = elRef;
71
- }
72
- }
File without changes