react-cosmos-ui 6.0.0-alpha.20 → 6.0.0-alpha.21

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,5 +1,5 @@
1
1
  import React from 'react';
2
- import { buildRendererQueryString } from 'react-cosmos-core';
2
+ import { createRendererUrl } from 'react-cosmos-core';
3
3
  import { createPlugin } from 'react-plugin';
4
4
  import { FullScreenButton } from './FullScreenButton.js';
5
5
  const { namedPlug, register } = createPlugin({
@@ -10,15 +10,16 @@ namedPlug('rendererAction', 'fullScreen', ({ pluginContext, slotProps }) => {
10
10
  const { fixtureId } = slotProps;
11
11
  const core = getMethodsOf('core');
12
12
  const rendererCore = getMethodsOf('rendererCore');
13
- const rendererUrl = rendererCore.getWebRendererUrl();
13
+ const rendererUrl = rendererCore.getRendererUrl();
14
14
  const onSelect = React.useCallback(() => {
15
- const query = buildRendererQueryString({ fixtureId, locked: true });
16
- const fixtureUrl = `${rendererUrl}${query}`;
17
- // noopener is required to prevent reuse of sessionStorage from the
18
- // Playground window, thus making sure the remote renderer will generate
19
- // a different rendererId from the iframe renderer.
20
- // https://stackoverflow.com/a/73821739
21
- window.open(fixtureUrl, '_blank', 'noopener=true');
15
+ if (rendererUrl) {
16
+ const fixtureUrl = createRendererUrl(rendererUrl, fixtureId, true);
17
+ // noopener is required to prevent reuse of sessionStorage from the
18
+ // Playground window, thus making sure the remote renderer will generate
19
+ // a different rendererId from the iframe renderer.
20
+ // https://stackoverflow.com/a/73821739
21
+ window.open(fixtureUrl, '_blank', 'noopener=true');
22
+ }
22
23
  }, [fixtureId, rendererUrl]);
23
24
  React.useEffect(() => {
24
25
  return core.registerCommands({ goFullScreen: onSelect });
@@ -39,10 +39,7 @@ function useFixtureExpansion(context, fixtureId) {
39
39
  };
40
40
  }
41
41
  function shouldShowBlankState(fixtureState) {
42
- // Don't show blank state until props (empty or not) have been read
43
- if (!fixtureState.props)
44
- return false;
45
- const hasProps = fixtureState.props.some(hasFsValues);
42
+ const hasProps = fixtureState.props && fixtureState.props.some(hasFsValues);
46
43
  if (hasProps)
47
44
  return false;
48
45
  const hasClassState = fixtureState.classState && fixtureState.classState.some(hasFsValues);
@@ -2,8 +2,8 @@
2
2
  import { NotificationItem } from '../../Notifications/spec.js';
3
3
  type Props = {
4
4
  devServerOn: boolean;
5
- webRendererUrl: null | string;
5
+ rendererUrl: null | string;
6
6
  pushNotification: (notification: NotificationItem) => unknown;
7
7
  };
8
- export declare function RemoteButton({ devServerOn, webRendererUrl, pushNotification, }: Props): JSX.Element | null;
8
+ export declare function RemoteButton({ devServerOn, rendererUrl, pushNotification, }: Props): JSX.Element | null;
9
9
  export {};
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
+ import { createRendererUrl } from 'react-cosmos-core';
2
3
  import { IconButton32 } from '../../../components/buttons/index.js';
3
4
  import { CastIcon } from '../../../components/icons/index.js';
4
5
  import { copyToClipboard } from './copyToClipboard.js';
5
- export function RemoteButton({ devServerOn, webRendererUrl, pushNotification, }) {
6
- if (!devServerOn || !webRendererUrl) {
6
+ export function RemoteButton({ devServerOn, rendererUrl, pushNotification, }) {
7
+ if (!devServerOn || !rendererUrl) {
7
8
  return null;
8
9
  }
9
- return (React.createElement(IconButton32, { icon: React.createElement(CastIcon, null), title: "Copy remote renderer URL", onClick: () => copyRendererUrlToClipboard(webRendererUrl) }));
10
+ return (React.createElement(IconButton32, { icon: React.createElement(CastIcon, null), title: "Copy remote renderer URL", onClick: () => copyRendererUrlToClipboard(createRendererUrl(rendererUrl)) }));
10
11
  async function copyRendererUrlToClipboard(url) {
11
12
  const fullUrl = getFullUrl(url);
12
13
  try {
@@ -26,7 +26,7 @@ namedPlug('globalAction', 'remoteRenderer', ({ pluginContext }) => {
26
26
  const core = getMethodsOf('core');
27
27
  const rendererCore = getMethodsOf('rendererCore');
28
28
  const notifications = getMethodsOf('notifications');
29
- return (React.createElement(RemoteButton, { devServerOn: core.isDevServerOn(), webRendererUrl: rendererCore.getWebRendererUrl(), pushNotification: notifications.pushTimedNotification }));
29
+ return (React.createElement(RemoteButton, { devServerOn: core.isDevServerOn(), rendererUrl: rendererCore.getRendererUrl(), pushNotification: notifications.pushTimedNotification }));
30
30
  });
31
31
  export { register };
32
32
  if (process.env.NODE_ENV !== 'test')
@@ -1,5 +1,7 @@
1
1
  import { createPlugin } from 'react-plugin';
2
- import { onRouterFixtureChange } from './onRouterFixtureChange.js';
2
+ import { onRouterFixtureReselect } from './onRouterFixtureReselect.js';
3
+ import { onRouterFixtureSelect } from './onRouterFixtureSelect.js';
4
+ import { onRouterFixtureUnselect } from './onRouterFixtureUnselect.js';
3
5
  import { receiveResponse } from './receiveResponse/index.js';
4
6
  import { reloadRenderer } from './reloadRenderer.js';
5
7
  import { setFixtureState } from './setFixtureState.js';
@@ -7,7 +9,7 @@ const { on, register, onLoad } = createPlugin({
7
9
  name: 'rendererCore',
8
10
  defaultConfig: {
9
11
  fixtures: {},
10
- webRendererUrl: null,
12
+ rendererUrl: null,
11
13
  },
12
14
  initialState: {
13
15
  connectedRendererIds: [],
@@ -16,7 +18,7 @@ const { on, register, onLoad } = createPlugin({
16
18
  fixtureState: {},
17
19
  },
18
20
  methods: {
19
- getWebRendererUrl,
21
+ getRendererUrl,
20
22
  getConnectedRendererIds,
21
23
  getPrimaryRendererId,
22
24
  getFixtures,
@@ -32,12 +34,16 @@ onLoad(({ getConfig, setState }) => {
32
34
  const { fixtures } = getConfig();
33
35
  setState(prevState => ({ ...prevState, fixtures }));
34
36
  });
35
- on('router', { fixtureChange: onRouterFixtureChange });
37
+ on('router', {
38
+ fixtureSelect: onRouterFixtureSelect,
39
+ fixtureReselect: onRouterFixtureReselect,
40
+ fixtureUnselect: onRouterFixtureUnselect,
41
+ });
36
42
  export { register };
37
43
  if (process.env.NODE_ENV !== 'test')
38
44
  register();
39
- function getWebRendererUrl({ getConfig }) {
40
- return getConfig().webRendererUrl;
45
+ function getRendererUrl({ getConfig }) {
46
+ return getConfig().rendererUrl;
41
47
  }
42
48
  function getConnectedRendererIds({ getState }) {
43
49
  return getState().connectedRendererIds;
@@ -0,0 +1,3 @@
1
+ import { FixtureId } from 'react-cosmos-core';
2
+ import { RendererCoreContext } from './shared/index.js';
3
+ export declare function onRouterFixtureReselect(context: RendererCoreContext, fixtureId: FixtureId): void;
@@ -0,0 +1,7 @@
1
+ import { postSelectFixtureRequest } from './shared/postRequest.js';
2
+ export function onRouterFixtureReselect(context, fixtureId) {
3
+ const { connectedRendererIds } = context.getState();
4
+ connectedRendererIds.forEach(rendererId => {
5
+ postSelectFixtureRequest(context, rendererId, fixtureId, {});
6
+ });
7
+ }
@@ -0,0 +1,3 @@
1
+ import { FixtureId } from 'react-cosmos-core';
2
+ import { RendererCoreContext } from './shared/index.js';
3
+ export declare function onRouterFixtureSelect(context: RendererCoreContext, fixtureId: FixtureId): void;
@@ -0,0 +1,9 @@
1
+ import { postSelectFixtureRequest } from './shared/postRequest.js';
2
+ export function onRouterFixtureSelect(context, fixtureId) {
3
+ context.setState(prevState => ({ ...prevState, fixtureState: {} }), () => {
4
+ const { connectedRendererIds } = context.getState();
5
+ connectedRendererIds.forEach(rendererId => {
6
+ postSelectFixtureRequest(context, rendererId, fixtureId, {});
7
+ });
8
+ });
9
+ }
@@ -0,0 +1,2 @@
1
+ import { RendererCoreContext } from './shared/index.js';
2
+ export declare function onRouterFixtureUnselect(context: RendererCoreContext): void;
@@ -0,0 +1,9 @@
1
+ import { postUnselectFixtureRequest } from './shared/postRequest.js';
2
+ export function onRouterFixtureUnselect(context) {
3
+ context.setState(prevState => ({ ...prevState, fixtureState: {} }), () => {
4
+ const { connectedRendererIds } = context.getState();
5
+ connectedRendererIds.forEach(rendererId => {
6
+ postUnselectFixtureRequest(context, rendererId);
7
+ });
8
+ });
9
+ }
@@ -3,7 +3,7 @@ export type RendererCoreSpec = {
3
3
  name: 'rendererCore';
4
4
  config: {
5
5
  fixtures: FixtureList;
6
- webRendererUrl: null | string;
6
+ rendererUrl: null | string;
7
7
  };
8
8
  state: {
9
9
  connectedRendererIds: RendererId[];
@@ -12,7 +12,7 @@ export type RendererCoreSpec = {
12
12
  fixtureState: FixtureState;
13
13
  };
14
14
  methods: {
15
- getWebRendererUrl(): null | string;
15
+ getRendererUrl(): null | string;
16
16
  getConnectedRendererIds(): RendererId[];
17
17
  getPrimaryRendererId(): null | RendererId;
18
18
  getFixtures(): FixtureList;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { createRendererUrl } from 'react-cosmos-core';
2
3
  import { Slot } from 'react-plugin';
3
4
  import styled from 'styled-components';
4
5
  import { RemoteRendererOverlay } from './RendererOverlay/RemoteRendererOverlay.js';
@@ -11,7 +12,7 @@ export const RendererPreview = React.memo(function RendererPreview({ rendererUrl
11
12
  }
12
13
  return (React.createElement(Slot, { name: "rendererPreviewOuter" },
13
14
  React.createElement(Container, null,
14
- React.createElement(Iframe, { "data-testid": "previewIframe", ref: onIframeRef, src: rendererUrl, frameBorder: 0, allow: "clipboard-write *" }),
15
+ React.createElement(Iframe, { "data-testid": "previewIframe", ref: onIframeRef, src: createRendererUrl(rendererUrl), frameBorder: 0, allow: "clipboard-write *" }),
15
16
  React.createElement(RendererOverlay, { runtimeStatus: runtimeStatus }))));
16
17
  });
17
18
  const Container = styled.div `
@@ -36,7 +36,7 @@ function getRuntimeStatus({ getState }) {
36
36
  return getState().runtimeStatus;
37
37
  }
38
38
  function getRendererUrl({ getMethodsOf }) {
39
- return getMethodsOf('rendererCore').getWebRendererUrl();
39
+ return getMethodsOf('rendererCore').getRendererUrl();
40
40
  }
41
41
  function getRendererConnected({ getMethodsOf }) {
42
42
  return getMethodsOf('rendererCore').isRendererConnected();
@@ -22,7 +22,7 @@ namedPlug('rendererAction', 'responsivePreview', ({ pluginContext }) => {
22
22
  const rendererCore = getMethodsOf('rendererCore');
23
23
  const viewportState = getViewportState(pluginContext);
24
24
  const { enabled, viewport } = viewportState;
25
- if (!rendererCore.getWebRendererUrl())
25
+ if (!rendererCore.getRendererUrl())
26
26
  return null;
27
27
  return (React.createElement(ToggleButton, { selected: enabled, onToggle: () => {
28
28
  if (enabled) {
@@ -20,7 +20,7 @@ onLoad(context => {
20
20
  const fixtureChanged = !isEqual(urlParams.fixtureId, fixtureId);
21
21
  setState({ urlParams }, () => {
22
22
  if (fixtureChanged) {
23
- emitFixtureChangeEvent(context);
23
+ emitFixtureChangeEvent(context, true);
24
24
  }
25
25
  });
26
26
  });
@@ -41,16 +41,28 @@ function setUrlParams(context, nextUrlParams) {
41
41
  const { urlParams } = context.getState();
42
42
  const fixtureChanged = !isEqual(nextUrlParams.fixtureId, urlParams.fixtureId);
43
43
  const urlParamsEqual = isEqual(nextUrlParams, urlParams);
44
- context.setState({ urlParams: nextUrlParams }, () => {
45
- // Setting identical url params is considered a "reset" request
46
- if (fixtureChanged || urlParamsEqual) {
47
- emitFixtureChangeEvent(context);
48
- }
49
- if (!urlParamsEqual) {
44
+ if (urlParamsEqual) {
45
+ // Setting identical URL params can be considered a "reset" request, but
46
+ // this will only re-render the fixture if the renderer implements an
47
+ // auto-incrementing render key in its state
48
+ emitFixtureChangeEvent(context, false);
49
+ }
50
+ else {
51
+ context.setState({ urlParams: nextUrlParams }, () => {
50
52
  pushUrlParams(context.getState().urlParams);
51
- }
52
- });
53
+ emitFixtureChangeEvent(context, fixtureChanged);
54
+ });
55
+ }
53
56
  }
54
- function emitFixtureChangeEvent(context) {
55
- context.emit('fixtureChange', getSelectedFixtureId(context));
57
+ function emitFixtureChangeEvent(context, fixtureChanged) {
58
+ const fixtureId = getSelectedFixtureId(context);
59
+ if (!fixtureId) {
60
+ context.emit('fixtureUnselect');
61
+ }
62
+ else if (fixtureChanged) {
63
+ context.emit('fixtureSelect', fixtureId);
64
+ }
65
+ else {
66
+ context.emit('fixtureReselect', fixtureId);
67
+ }
56
68
  }
@@ -10,6 +10,8 @@ export type RouterSpec = {
10
10
  unselectFixture(): void;
11
11
  };
12
12
  events: {
13
- fixtureChange(fixtureId: null | FixtureId): void;
13
+ fixtureSelect(fixtureId: FixtureId): void;
14
+ fixtureReselect(fixtureId: FixtureId): void;
15
+ fixtureUnselect(): void;
14
16
  };
15
17
  };
@@ -32,7 +32,7 @@ export declare function getCoreMethods(): {
32
32
  isDevServerOn(): boolean;
33
33
  };
34
34
  export declare function getRendererCoreMethods(): {
35
- getWebRendererUrl(): string | null;
35
+ getRendererUrl(): string | null;
36
36
  getConnectedRendererIds(): string[];
37
37
  getPrimaryRendererId(): string | null;
38
38
  getFixtures(): import("react-cosmos-core").FixtureList;
@@ -75,7 +75,7 @@ export declare function mockMessageHandler(methods?: MethodsOf<MessageHandlerSpe
75
75
  postRendererRequest: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<MessageHandlerSpec>, msg: import("react-cosmos-core").MessageType) => unknown);
76
76
  };
77
77
  export declare function mockRendererCore(methods?: MethodsOf<RendererCoreSpec>): {
78
- getWebRendererUrl: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<RendererCoreSpec>) => string | null);
78
+ getRendererUrl: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<RendererCoreSpec>) => string | null);
79
79
  getConnectedRendererIds: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<RendererCoreSpec>) => string[]);
80
80
  getPrimaryRendererId: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<RendererCoreSpec>) => string | null);
81
81
  getFixtures: jest.Mock<any, any, any> | ((context: import("react-plugin").PluginContext<RendererCoreSpec>) => import("react-cosmos-core").FixtureList);
@@ -102,7 +102,9 @@ export declare function mockFixtureTree(methods?: MethodsOf<FixtureTreeSpec>): {
102
102
  }, fixtureId: import("react-cosmos-core").FixtureId) => unknown);
103
103
  };
104
104
  export declare function onRouter(events?: EventsOf<RouterSpec>): {
105
- fixtureChange: jest.Mock<any, any, any> | import("ui-plugin/dist/types/PluginContextHandlers.js").PluginEventHandler<any, [fixtureId: import("react-cosmos-core").FixtureId | null]>;
105
+ fixtureSelect: jest.Mock<any, any, any> | import("ui-plugin/dist/types/PluginContextHandlers.js").PluginEventHandler<any, [fixtureId: import("react-cosmos-core").FixtureId]>;
106
+ fixtureReselect: jest.Mock<any, any, any> | import("ui-plugin/dist/types/PluginContextHandlers.js").PluginEventHandler<any, [fixtureId: import("react-cosmos-core").FixtureId]>;
107
+ fixtureUnselect: jest.Mock<any, any, any> | import("ui-plugin/dist/types/PluginContextHandlers.js").PluginEventHandler<any, []>;
106
108
  };
107
109
  export declare function onMessageHandler(events?: EventsOf<MessageHandlerSpec>): {
108
110
  serverMessage: jest.Mock<any, any, any> | import("ui-plugin/dist/types/PluginContextHandlers.js").PluginEventHandler<any, [msg: import("react-cosmos-core").MessageType]>;
@@ -69,7 +69,7 @@ export function mockMessageHandler(methods = {}) {
69
69
  }
70
70
  export function mockRendererCore(methods = {}) {
71
71
  const allMethods = {
72
- getWebRendererUrl: jest.fn(),
72
+ getRendererUrl: jest.fn(),
73
73
  getConnectedRendererIds: jest.fn(),
74
74
  getPrimaryRendererId: jest.fn(),
75
75
  getFixtures: jest.fn(),
@@ -113,7 +113,9 @@ export function mockFixtureTree(methods = {}) {
113
113
  }
114
114
  export function onRouter(events = {}) {
115
115
  const allEvents = {
116
- fixtureChange: jest.fn(),
116
+ fixtureSelect: jest.fn(),
117
+ fixtureReselect: jest.fn(),
118
+ fixtureUnselect: jest.fn(),
117
119
  ...events,
118
120
  };
119
121
  on('router', allEvents);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-cosmos-ui",
3
- "version": "6.0.0-alpha.20",
3
+ "version": "6.0.0-alpha.21",
4
4
  "description": "React Cosmos UI",
5
5
  "repository": "https://github.com/react-cosmos/react-cosmos/tree/main/packages/react-cosmos-ui",
6
6
  "license": "MIT",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "lodash-es": "^4.17.21",
18
- "react-cosmos-core": "6.0.0-alpha.20"
18
+ "react-cosmos-core": "6.0.0-alpha.21"
19
19
  },
20
20
  "devDependencies": {
21
21
  "fuzzaldrin-plus": "^0.6.0",
@@ -23,5 +23,5 @@
23
23
  "react-plugin": "^3.0.0-alpha.4",
24
24
  "styled-components": "^5.3.10"
25
25
  },
26
- "gitHead": "31201ce4185919b054f42b8f15b3e87033af4e69"
26
+ "gitHead": "1b7472f75075853e5eaf9a427a4c3138818fbcd0"
27
27
  }
@@ -1,3 +0,0 @@
1
- import { FixtureId } from 'react-cosmos-core';
2
- import { RendererCoreContext } from './shared/index.js';
3
- export declare function onRouterFixtureChange(context: RendererCoreContext, fixtureId: null | FixtureId): void;
@@ -1,18 +0,0 @@
1
- import { postSelectFixtureRequest, postUnselectFixtureRequest, } from './shared/postRequest.js';
2
- export function onRouterFixtureChange(context, fixtureId) {
3
- if (fixtureId === null) {
4
- return context.setState(emptyFixtureState, () => {
5
- getConnectedRendererIds(context).forEach(rendererId => postUnselectFixtureRequest(context, rendererId));
6
- });
7
- }
8
- // Clear fixture state between fixtures
9
- context.setState(emptyFixtureState, () => {
10
- getConnectedRendererIds(context).forEach(rendererId => postSelectFixtureRequest(context, rendererId, fixtureId, {}));
11
- });
12
- }
13
- function getConnectedRendererIds(context) {
14
- return context.getState().connectedRendererIds;
15
- }
16
- function emptyFixtureState(prevState) {
17
- return { ...prevState, fixtureState: {} };
18
- }