react-cosmos-ui 6.0.0-alpha.9 → 6.0.0-beta.2

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.
Files changed (175) hide show
  1. package/dist/components/Icon.d.ts +7 -3
  2. package/dist/components/Icon.js +2 -2
  3. package/dist/components/Illustration.d.ts +1 -0
  4. package/dist/components/KeyBox.d.ts +1 -0
  5. package/dist/components/SidePanel.d.ts +1 -0
  6. package/dist/components/SidePanel.js +1 -1
  7. package/dist/components/Space.d.ts +1 -0
  8. package/dist/components/ValueInputTree/ExpandCollapseValues.d.ts +1 -0
  9. package/dist/components/ValueInputTree/ValueInput/BooleanValueInput.d.ts +1 -0
  10. package/dist/components/ValueInputTree/ValueInput/NullValueInput.d.ts +1 -0
  11. package/dist/components/ValueInputTree/ValueInput/NumberValueInput.d.ts +1 -0
  12. package/dist/components/ValueInputTree/ValueInput/StringValueInput.d.ts +1 -0
  13. package/dist/components/ValueInputTree/ValueInput/UndefinedValueInput.d.ts +1 -0
  14. package/dist/components/ValueInputTree/ValueInput/UnserializableValueInput.d.ts +1 -0
  15. package/dist/components/ValueInputTree/ValueInput/ValueInput.d.ts +1 -0
  16. package/dist/components/ValueInputTree/ValueInput/ValueInput.js +1 -1
  17. package/dist/components/ValueInputTree/ValueInputDir.d.ts +1 -0
  18. package/dist/components/ValueInputTree/index.d.ts +3 -3
  19. package/dist/components/ValueInputTree/index.js +2 -2
  20. package/dist/components/ValueInputTree/shared.d.ts +1 -2
  21. package/dist/components/ValueInputTree/shared.js +0 -4
  22. package/dist/components/ValueInputTree/valueTreeExpansion.js +2 -1
  23. package/dist/components/icons/index.d.ts +4 -6
  24. package/dist/components/icons/index.js +1 -1
  25. package/dist/components/illustrations/ArtificialIntelligence.d.ts +1 -0
  26. package/dist/components/illustrations/Astronaut.d.ts +1 -0
  27. package/dist/components/illustrations/BlankCanvas.d.ts +1 -0
  28. package/dist/components/inputs/NumberInput.d.ts +1 -0
  29. package/dist/components/inputs/Select.d.ts +1 -0
  30. package/dist/cosmos.loadPlugins.js +14 -10
  31. package/dist/index.d.ts +0 -1
  32. package/dist/index.js +0 -1
  33. package/dist/playground.bundle.js +602 -599
  34. package/dist/playground.bundle.js.map +1 -1
  35. package/dist/playground.js +13 -2
  36. package/dist/playgroundConfig.d.ts +2 -0
  37. package/dist/plugins/ClassStatePanel/ClassStatePanel/ComponentClassState.d.ts +1 -0
  38. package/dist/plugins/ClassStatePanel/ClassStatePanel/ComponentClassState.js +3 -3
  39. package/dist/plugins/ControlPanel/ControlPanel.d.ts +1 -0
  40. package/dist/plugins/ControlPanel/ControlPanel.js +1 -1
  41. package/dist/plugins/ControlSelect/SelectValueInput.d.ts +1 -0
  42. package/dist/plugins/ControlSelect/SelectValueInput.js +1 -1
  43. package/dist/plugins/Core/index.js +0 -5
  44. package/dist/plugins/Core/spec.d.ts +0 -2
  45. package/dist/plugins/FixtureBookmark/BookmarkFixtureButton.d.ts +1 -0
  46. package/dist/plugins/FixtureBookmark/FixtureBookmarks.d.ts +5 -5
  47. package/dist/plugins/FixtureBookmark/FixtureBookmarks.js +10 -7
  48. package/dist/plugins/FixtureBookmark/index.js +7 -17
  49. package/dist/plugins/FixtureSearch/FixtureSearchHeader.d.ts +3 -2
  50. package/dist/plugins/FixtureSearch/FixtureSearchHeader.js +3 -3
  51. package/dist/plugins/FixtureSearch/FixtureSearchOverlay.d.ts +1 -0
  52. package/dist/plugins/FixtureSearch/FixtureSearchOverlay.js +2 -2
  53. package/dist/plugins/FixtureSearch/FixtureSearchResult.d.ts +1 -0
  54. package/dist/plugins/FixtureSearch/FixtureSearchShortcuts.d.ts +1 -0
  55. package/dist/plugins/FixtureSearch/index.js +2 -1
  56. package/dist/plugins/FixtureTree/BlankState.d.ts +1 -0
  57. package/dist/plugins/FixtureTree/BlankState.js +23 -24
  58. package/dist/plugins/FixtureTree/FixtureTree/FixtureButton.d.ts +2 -2
  59. package/dist/plugins/FixtureTree/FixtureTree/FixtureButton.js +2 -2
  60. package/dist/plugins/FixtureTree/FixtureTree/FixtureDir.d.ts +1 -0
  61. package/dist/plugins/FixtureTree/FixtureTree/FixtureTree.js +6 -8
  62. package/dist/plugins/FixtureTree/FixtureTree/MultiFixtureButton.d.ts +3 -2
  63. package/dist/plugins/FixtureTree/FixtureTree/MultiFixtureButton.js +16 -11
  64. package/dist/plugins/FixtureTree/FixtureTreeContainer.d.ts +2 -2
  65. package/dist/plugins/FixtureTree/FixtureTreeContainer.js +1 -3
  66. package/dist/plugins/FixtureTree/FixtureTreeHeader.d.ts +1 -0
  67. package/dist/plugins/FixtureTree/index.js +1 -1
  68. package/dist/plugins/FixtureTree/revealFixture.js +2 -2
  69. package/dist/plugins/FixtureTree/shared.d.ts +1 -1
  70. package/dist/plugins/FullScreenButton/FullScreenButton.d.ts +1 -0
  71. package/dist/plugins/FullScreenButton/index.js +11 -5
  72. package/dist/plugins/Notifications/Notifications.d.ts +1 -0
  73. package/dist/plugins/PluginList/PluginList.d.ts +1 -0
  74. package/dist/plugins/PropsPanel/BlankState.d.ts +1 -0
  75. package/dist/plugins/PropsPanel/BlankState.js +14 -12
  76. package/dist/plugins/PropsPanel/PropsPanel/ComponentProps.d.ts +1 -0
  77. package/dist/plugins/PropsPanel/index.js +1 -4
  78. package/dist/plugins/RemoteRenderer/RemoteButton/index.d.ts +3 -2
  79. package/dist/plugins/RemoteRenderer/RemoteButton/index.js +5 -4
  80. package/dist/plugins/RemoteRenderer/index.js +2 -1
  81. package/dist/plugins/RendererCore/index.js +23 -5
  82. package/dist/plugins/RendererCore/onRouterFixtureReselect.d.ts +3 -0
  83. package/dist/plugins/RendererCore/onRouterFixtureReselect.js +7 -0
  84. package/dist/plugins/RendererCore/onRouterFixtureSelect.d.ts +3 -0
  85. package/dist/plugins/RendererCore/onRouterFixtureSelect.js +9 -0
  86. package/dist/plugins/RendererCore/onRouterFixtureUnselect.d.ts +2 -0
  87. package/dist/plugins/RendererCore/onRouterFixtureUnselect.js +9 -0
  88. package/dist/plugins/RendererCore/receiveResponse/fixtureStateChange.js +4 -4
  89. package/dist/plugins/RendererCore/receiveResponse/rendererReady.js +15 -21
  90. package/dist/plugins/RendererCore/reloadRenderer.d.ts +2 -0
  91. package/dist/plugins/RendererCore/reloadRenderer.js +5 -0
  92. package/dist/plugins/RendererCore/shared/postRequest.d.ts +1 -0
  93. package/dist/plugins/RendererCore/shared/postRequest.js +8 -0
  94. package/dist/plugins/RendererCore/spec.d.ts +6 -1
  95. package/dist/plugins/RendererPreview/RendererOverlay/RemoteRendererConnected.d.ts +2 -0
  96. package/dist/plugins/RendererPreview/RendererOverlay/RemoteRendererConnected.js +19 -0
  97. package/dist/plugins/RendererPreview/RendererOverlay/RemoteRendererOverlay.d.ts +6 -0
  98. package/dist/plugins/RendererPreview/RendererOverlay/RemoteRendererOverlay.js +6 -0
  99. package/dist/plugins/RendererPreview/RendererOverlay/RendererOverlay.d.ts +7 -0
  100. package/dist/plugins/RendererPreview/RendererOverlay/RendererOverlay.js +11 -0
  101. package/dist/plugins/RendererPreview/RendererOverlay/WaitingForRenderer.d.ts +2 -0
  102. package/dist/plugins/RendererPreview/RendererOverlay/WaitingForRenderer.js +65 -0
  103. package/dist/plugins/RendererPreview/RendererOverlay/rendererOverlayShared.d.ts +3 -0
  104. package/dist/plugins/RendererPreview/RendererOverlay/rendererOverlayShared.js +27 -0
  105. package/dist/plugins/RendererPreview/RendererPreview.d.ts +3 -0
  106. package/dist/plugins/RendererPreview/RendererPreview.js +10 -3
  107. package/dist/plugins/RendererPreview/handleRendererRequests.js +7 -6
  108. package/dist/plugins/RendererPreview/handleWindowMessages.js +10 -1
  109. package/dist/plugins/RendererPreview/index.js +7 -13
  110. package/dist/plugins/RendererPreview/shared.d.ts +0 -6
  111. package/dist/plugins/RendererPreview/spec.d.ts +0 -3
  112. package/dist/plugins/ResponsivePreview/ResponsivePreview/{Header.d.ts → ResponsiveHeader.d.ts} +1 -1
  113. package/dist/plugins/ResponsivePreview/ResponsivePreview/{Header.js → ResponsiveHeader.js} +2 -2
  114. package/dist/plugins/ResponsivePreview/ResponsivePreview/ResponsivePreview.d.ts +1 -2
  115. package/dist/plugins/ResponsivePreview/ResponsivePreview/ResponsivePreview.js +4 -4
  116. package/dist/plugins/ResponsivePreview/ToggleButton/index.d.ts +1 -0
  117. package/dist/plugins/ResponsivePreview/index.js +5 -6
  118. package/dist/plugins/ResponsivePreview/shared.js +13 -10
  119. package/dist/plugins/Root/GlobalHeader.d.ts +2 -4
  120. package/dist/plugins/Root/GlobalHeader.js +2 -23
  121. package/dist/plugins/{ContentOverlay/shared.d.ts → Root/HomeOverlay/ContentOverlay.d.ts} +1 -4
  122. package/dist/plugins/{ContentOverlay/shared.js → Root/HomeOverlay/ContentOverlay.js} +3 -3
  123. package/dist/plugins/Root/HomeOverlay/HomeOverlay.d.ts +8 -0
  124. package/dist/plugins/Root/HomeOverlay/HomeOverlay.js +6 -0
  125. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/KeyShortcut.d.ts +1 -0
  126. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/KeyShortcut.js +2 -2
  127. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/NoFixtureSelected.d.ts +1 -0
  128. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/NoFixtureSelected.js +5 -5
  129. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/WelcomeCosmos.d.ts +1 -0
  130. package/dist/plugins/Root/HomeOverlay/WelcomeCosmos.js +159 -0
  131. package/dist/plugins/Root/HomeOverlay/welcomeDismiss.d.ts +7 -0
  132. package/dist/plugins/{ContentOverlay → Root/HomeOverlay}/welcomeDismiss.js +6 -4
  133. package/dist/plugins/Root/RendererHeader.d.ts +1 -1
  134. package/dist/plugins/Root/RendererHeader.js +13 -5
  135. package/dist/plugins/Root/Root.d.ts +7 -5
  136. package/dist/plugins/Root/Root.js +9 -10
  137. package/dist/plugins/Root/ToggleNavButton.d.ts +1 -0
  138. package/dist/plugins/Root/index.js +6 -5
  139. package/dist/plugins/Root/panelOpen.js +0 -5
  140. package/dist/plugins/Router/index.js +23 -11
  141. package/dist/plugins/Router/spec.d.ts +5 -3
  142. package/dist/plugins/StandardControl/storage.d.ts +1 -1
  143. package/dist/plugins/pluginEntry.d.ts +0 -1
  144. package/dist/plugins/pluginEntry.js +0 -1
  145. package/dist/shared/fixtureTree.d.ts +1 -2
  146. package/dist/shared/fixtureTree.js +5 -10
  147. package/dist/shared/url.d.ts +6 -5
  148. package/dist/shared/url.js +6 -6
  149. package/dist/slots/ControlActionSlot.d.ts +1 -0
  150. package/dist/slots/ControlSlot.d.ts +1 -0
  151. package/dist/slots/FixtureActionSlot.d.ts +3 -2
  152. package/dist/slots/NavRowSlot.d.ts +1 -0
  153. package/dist/slots/RendererActionSlot.d.ts +1 -0
  154. package/dist/slots/SidePanelRowSlot.d.ts +1 -0
  155. package/dist/testHelpers/pluginMocks.d.ts +8 -7
  156. package/dist/testHelpers/pluginMocks.js +5 -3
  157. package/package.json +4 -4
  158. package/dist/plugins/ContentOverlay/ContentOverlay.d.ts +0 -13
  159. package/dist/plugins/ContentOverlay/ContentOverlay.js +0 -34
  160. package/dist/plugins/ContentOverlay/RendererNotResponding.d.ts +0 -1
  161. package/dist/plugins/ContentOverlay/RendererNotResponding.js +0 -109
  162. package/dist/plugins/ContentOverlay/WelcomeCosmos.js +0 -158
  163. package/dist/plugins/ContentOverlay/cosmos.decorator.d.ts +0 -5
  164. package/dist/plugins/ContentOverlay/cosmos.decorator.js +0 -13
  165. package/dist/plugins/ContentOverlay/index.d.ts +0 -2
  166. package/dist/plugins/ContentOverlay/index.js +0 -19
  167. package/dist/plugins/ContentOverlay/spec.d.ts +0 -3
  168. package/dist/plugins/ContentOverlay/spec.js +0 -1
  169. package/dist/plugins/ContentOverlay/welcomeDismiss.d.ts +0 -7
  170. package/dist/plugins/RendererCore/isValidFixtureSelected.d.ts +0 -2
  171. package/dist/plugins/RendererCore/isValidFixtureSelected.js +0 -16
  172. package/dist/plugins/RendererCore/onRouterFixtureChange.d.ts +0 -3
  173. package/dist/plugins/RendererCore/onRouterFixtureChange.js +0 -18
  174. package/dist/plugins/RendererPreview/checkRendererStatus.d.ts +0 -2
  175. package/dist/plugins/RendererPreview/checkRendererStatus.js +0 -31
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
+ import { createRendererUrl } from 'react-cosmos-core';
2
3
  import { createPlugin } from 'react-plugin';
3
- import { stringifyRendererUrlQuery } from 'react-cosmos-core';
4
4
  import { FullScreenButton } from './FullScreenButton.js';
5
5
  const { namedPlug, register } = createPlugin({
6
6
  name: 'fullScreenButton',
@@ -9,11 +9,17 @@ namedPlug('rendererAction', 'fullScreen', ({ pluginContext, slotProps }) => {
9
9
  const { getMethodsOf } = pluginContext;
10
10
  const { fixtureId } = slotProps;
11
11
  const core = getMethodsOf('core');
12
- const rendererUrl = core.getWebRendererUrl();
12
+ const rendererCore = getMethodsOf('rendererCore');
13
+ const rendererUrl = rendererCore.getRendererUrl();
13
14
  const onSelect = React.useCallback(() => {
14
- const query = stringifyRendererUrlQuery({ _fixtureId: fixtureId });
15
- const fixtureUrl = `${rendererUrl}?${query}`;
16
- window.open(fixtureUrl, '_blank');
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
+ }
17
23
  }, [fixtureId, rendererUrl]);
18
24
  React.useEffect(() => {
19
25
  return core.registerCommands({ goFullScreen: onSelect });
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { NotificationItem } from './spec.js';
2
3
  type Props = {
3
4
  notifications: NotificationItem[];
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  export type SimplePlugin = {
2
3
  name: string;
3
4
  enabled: boolean;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  export declare function BlankState(): JSX.Element;
2
3
  export declare const IconContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
3
4
  export declare const NoWrap: import("styled-components").StyledComponent<"span", any, {}, never>;
@@ -1,20 +1,22 @@
1
1
  import React from 'react';
2
+ import { DelayRender } from 'react-cosmos-core';
2
3
  import styled from 'styled-components';
3
4
  import { SlidersIcon } from '../../components/icons/index.js';
4
5
  import { grey160, grey224, grey32, grey64 } from '../../style/colors.js';
5
6
  export function BlankState() {
6
- return (React.createElement(Container, null,
7
- React.createElement(IconContainer, null,
8
- React.createElement(SlidersIcon, null)),
9
- React.createElement(Title, null,
10
- "No visible props in ",
11
- React.createElement(NoWrap, null, "selected fixture")),
12
- React.createElement(Description, null,
13
- "Props of exported JSX ",
14
- React.createElement(NoWrap, null, "elements from"),
15
- " your fixtures",
16
- ' ',
17
- React.createElement(NoWrap, null, "will appear here."))));
7
+ return (React.createElement(DelayRender, { delay: 500 },
8
+ React.createElement(Container, null,
9
+ React.createElement(IconContainer, null,
10
+ React.createElement(SlidersIcon, null)),
11
+ React.createElement(Title, null,
12
+ "No visible props in ",
13
+ React.createElement(NoWrap, null, "selected fixture")),
14
+ React.createElement(Description, null,
15
+ "Props of exported JSX ",
16
+ React.createElement(NoWrap, null, "elements from"),
17
+ " your fixtures",
18
+ ' ',
19
+ React.createElement(NoWrap, null, "will appear here.")))));
18
20
  }
19
21
  const Container = styled.div `
20
22
  padding: 16px 24px;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { FixtureState, FixtureStateProps, StateUpdater } from 'react-cosmos-core';
2
3
  import { FixtureExpansion, OnElementExpansionChange } from '../../../components/ValueInputTree/index.js';
3
4
  type Props = {
@@ -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);
@@ -1,8 +1,9 @@
1
+ /// <reference types="react" />
1
2
  import { NotificationItem } from '../../Notifications/spec.js';
2
3
  type Props = {
3
4
  devServerOn: boolean;
4
- webRendererUrl: null | string;
5
+ rendererUrl: null | string;
5
6
  pushNotification: (notification: NotificationItem) => unknown;
6
7
  };
7
- export declare function RemoteButton({ devServerOn, webRendererUrl, pushNotification, }: Props): JSX.Element | null;
8
+ export declare function RemoteButton({ devServerOn, rendererUrl, pushNotification, }: Props): JSX.Element | null;
8
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 {
@@ -33,5 +34,5 @@ function getFullUrl(rendererUrl) {
33
34
  // is running on the same host/port as the playground
34
35
  if (rendererUrl.startsWith('http'))
35
36
  return rendererUrl;
36
- return `${location.origin}${rendererUrl}`;
37
+ return new URL(rendererUrl, location.origin).toString();
37
38
  }
@@ -24,8 +24,9 @@ onLoad(context => {
24
24
  namedPlug('globalAction', 'remoteRenderer', ({ pluginContext }) => {
25
25
  const { getMethodsOf } = pluginContext;
26
26
  const core = getMethodsOf('core');
27
+ const rendererCore = getMethodsOf('rendererCore');
27
28
  const notifications = getMethodsOf('notifications');
28
- return (React.createElement(RemoteButton, { devServerOn: core.isDevServerOn(), webRendererUrl: core.getWebRendererUrl(), pushNotification: notifications.pushTimedNotification }));
29
+ return (React.createElement(RemoteButton, { devServerOn: core.isDevServerOn(), rendererUrl: rendererCore.getRendererUrl(), pushNotification: notifications.pushTimedNotification }));
29
30
  });
30
31
  export { register };
31
32
  if (process.env.NODE_ENV !== 'test')
@@ -1,10 +1,16 @@
1
1
  import { createPlugin } from 'react-plugin';
2
- import { isValidFixtureSelected } from './isValidFixtureSelected.js';
3
- import { onRouterFixtureChange } from './onRouterFixtureChange.js';
2
+ import { onRouterFixtureReselect } from './onRouterFixtureReselect.js';
3
+ import { onRouterFixtureSelect } from './onRouterFixtureSelect.js';
4
+ import { onRouterFixtureUnselect } from './onRouterFixtureUnselect.js';
4
5
  import { receiveResponse } from './receiveResponse/index.js';
6
+ import { reloadRenderer } from './reloadRenderer.js';
5
7
  import { setFixtureState } from './setFixtureState.js';
6
- const { on, register } = createPlugin({
8
+ const { on, register, onLoad } = createPlugin({
7
9
  name: 'rendererCore',
10
+ defaultConfig: {
11
+ fixtures: {},
12
+ rendererUrl: null,
13
+ },
8
14
  initialState: {
9
15
  connectedRendererIds: [],
10
16
  primaryRendererId: null,
@@ -12,21 +18,33 @@ const { on, register } = createPlugin({
12
18
  fixtureState: {},
13
19
  },
14
20
  methods: {
21
+ getRendererUrl,
15
22
  getConnectedRendererIds,
16
23
  getPrimaryRendererId,
17
24
  getFixtures,
18
25
  getFixtureState,
19
26
  isRendererConnected,
20
- isValidFixtureSelected,
27
+ reloadRenderer,
21
28
  setFixtureState,
22
29
  selectPrimaryRenderer,
23
30
  receiveResponse,
24
31
  },
25
32
  });
26
- on('router', { fixtureChange: onRouterFixtureChange });
33
+ onLoad(({ getConfig, setState }) => {
34
+ const { fixtures } = getConfig();
35
+ setState(prevState => ({ ...prevState, fixtures }));
36
+ });
37
+ on('router', {
38
+ fixtureSelect: onRouterFixtureSelect,
39
+ fixtureReselect: onRouterFixtureReselect,
40
+ fixtureUnselect: onRouterFixtureUnselect,
41
+ });
27
42
  export { register };
28
43
  if (process.env.NODE_ENV !== 'test')
29
44
  register();
45
+ function getRendererUrl({ getConfig }) {
46
+ return getConfig().rendererUrl;
47
+ }
30
48
  function getConnectedRendererIds({ getState }) {
31
49
  return getState().connectedRendererIds;
32
50
  }
@@ -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
+ }
@@ -5,15 +5,15 @@ export function receiveFixtureStateChangeResponse(context, { payload }) {
5
5
  const { rendererId, fixtureId, fixtureState } = payload;
6
6
  const selectedFixtureId = getSelectedFixtureId(context);
7
7
  const { primaryRendererId, fixtureState: prevFixtureState } = context.getState();
8
+ // Discard updates from secondary renderers
9
+ if (rendererId !== primaryRendererId) {
10
+ return;
11
+ }
8
12
  if (!isEqual(fixtureId, selectedFixtureId)) {
9
13
  console.warn('[Renderer] fixtureStateChange response ignored ' +
10
14
  `because it doesn't match the selected fixture`);
11
15
  return;
12
16
  }
13
- // Discard updates from secondary renderers
14
- if (rendererId !== primaryRendererId) {
15
- return;
16
- }
17
17
  if (isEqual(fixtureState, prevFixtureState)) {
18
18
  return;
19
19
  }
@@ -1,38 +1,32 @@
1
+ import { isEqual } from 'lodash-es';
1
2
  import { postSelectFixtureRequest } from '../shared/postRequest.js';
2
- import { getSelectedFixtureId } from '../shared/router.js';
3
3
  export function receiveRendererReadyResponse(context, { payload }) {
4
- const { rendererId, fixtures, initialFixtureId } = payload;
4
+ const { rendererId } = payload;
5
+ const { connectedRendererIds: prevRendererIds } = context.getState();
5
6
  context.setState(stateUpdater, afterStateChanged);
6
7
  function stateUpdater(prevState) {
7
8
  // The first announced renderer becomes the primary one
8
9
  const primaryRendererId = prevState.primaryRendererId || rendererId;
9
- const isPrimaryRenderer = rendererId === primaryRendererId;
10
10
  const { connectedRendererIds, fixtureState } = prevState;
11
11
  return {
12
12
  ...prevState,
13
13
  connectedRendererIds: addToSet(connectedRendererIds, rendererId),
14
14
  primaryRendererId,
15
- fixtures,
16
- fixtureState: isPrimaryRenderer ? {} : fixtureState,
15
+ fixtureState: rendererId === primaryRendererId ? {} : fixtureState,
17
16
  };
18
17
  }
19
18
  function afterStateChanged() {
20
- if (initialFixtureId)
21
- selectInitialFixture(context, initialFixtureId);
22
- else
23
- selectFixtureFromUrlParams(context, rendererId);
24
- notifyRendererConnection(context, rendererId);
25
- }
26
- }
27
- function selectInitialFixture({ getMethodsOf }, fixtureId) {
28
- const router = getMethodsOf('router');
29
- router.selectFixture(fixtureId);
30
- }
31
- function selectFixtureFromUrlParams(context, rendererId) {
32
- const fixtureId = getSelectedFixtureId(context);
33
- if (fixtureId) {
34
- const { fixtureState } = context.getState();
35
- postSelectFixtureRequest(context, rendererId, fixtureId, fixtureState);
19
+ const router = context.getMethodsOf('router');
20
+ const rendererFixtureId = payload.selectedFixtureId;
21
+ const routerFixtureId = router.getSelectedFixtureId();
22
+ if (routerFixtureId && !isEqual(routerFixtureId, rendererFixtureId)) {
23
+ const { fixtureState } = context.getState();
24
+ postSelectFixtureRequest(context, rendererId, routerFixtureId, fixtureState);
25
+ }
26
+ // Notify about connected renderers that weren't connected before
27
+ if (!prevRendererIds.includes(rendererId)) {
28
+ notifyRendererConnection(context, rendererId);
29
+ }
36
30
  }
37
31
  }
38
32
  function notifyRendererConnection({ getMethodsOf }, rendererId) {
@@ -0,0 +1,2 @@
1
+ import { RendererCoreContext } from './shared/index.js';
2
+ export declare function reloadRenderer(context: RendererCoreContext): void;
@@ -0,0 +1,5 @@
1
+ import { postReloadRendererRequest } from './shared/postRequest.js';
2
+ export function reloadRenderer(context) {
3
+ const { connectedRendererIds } = context.getState();
4
+ connectedRendererIds.forEach(rendererId => postReloadRendererRequest(context, rendererId));
5
+ }
@@ -1,5 +1,6 @@
1
1
  import { FixtureId, FixtureState, RendererId } from 'react-cosmos-core';
2
2
  import { RendererCoreContext } from '../shared/index.js';
3
+ export declare function postReloadRendererRequest(context: RendererCoreContext, rendererId: RendererId): void;
3
4
  export declare function postSelectFixtureRequest(context: RendererCoreContext, rendererId: RendererId, fixtureId: FixtureId, fixtureState: FixtureState): void;
4
5
  export declare function postUnselectFixtureRequest(context: RendererCoreContext, rendererId: RendererId): void;
5
6
  export declare function postSetFixtureStateRequest(context: RendererCoreContext, rendererId: RendererId, fixtureId: FixtureId, fixtureState: FixtureState): void;
@@ -1,3 +1,11 @@
1
+ export function postReloadRendererRequest(context, rendererId) {
2
+ postRendererRequest(context, {
3
+ type: 'reloadRenderer',
4
+ payload: {
5
+ rendererId,
6
+ },
7
+ });
8
+ }
1
9
  export function postSelectFixtureRequest(context, rendererId, fixtureId, fixtureState) {
2
10
  postRendererRequest(context, {
3
11
  type: 'selectFixture',
@@ -1,6 +1,10 @@
1
1
  import { FixtureList, FixtureState, MessageType, RendererId, StateUpdater } from 'react-cosmos-core';
2
2
  export type RendererCoreSpec = {
3
3
  name: 'rendererCore';
4
+ config: {
5
+ fixtures: FixtureList;
6
+ rendererUrl: null | string;
7
+ };
4
8
  state: {
5
9
  connectedRendererIds: RendererId[];
6
10
  primaryRendererId: null | RendererId;
@@ -8,12 +12,13 @@ export type RendererCoreSpec = {
8
12
  fixtureState: FixtureState;
9
13
  };
10
14
  methods: {
15
+ getRendererUrl(): null | string;
11
16
  getConnectedRendererIds(): RendererId[];
12
17
  getPrimaryRendererId(): null | RendererId;
13
18
  getFixtures(): FixtureList;
14
19
  getFixtureState(): FixtureState;
15
20
  isRendererConnected(): boolean;
16
- isValidFixtureSelected(): boolean;
21
+ reloadRenderer(): void;
17
22
  setFixtureState(stateUpdater: StateUpdater<FixtureState>): void;
18
23
  selectPrimaryRenderer(primaryRendererId: RendererId): void;
19
24
  receiveResponse(msg: MessageType): void;
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare function RemoteRendererConnected(): JSX.Element;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { CheckCircleIcon } from '../../../components/icons/index.js';
4
+ import { grey144 } from '../../../style/colors.js';
5
+ import { RendererOverlayContainer, RendererOverlayIconWrapper, RendererOverlayMessage, } from './rendererOverlayShared.js';
6
+ export function RemoteRendererConnected() {
7
+ return (React.createElement(RendererOverlayContainer, null,
8
+ React.createElement(RendererOverlayIconWrapper, null,
9
+ React.createElement(IconContainer, null, React.createElement(CheckCircleIcon, { strokeWidth: 0.55 }))),
10
+ React.createElement(RendererOverlayMessage, null, "Remote renderer connected")));
11
+ }
12
+ const svgRingRatio = 26.667 / 32;
13
+ const ringSize = 34;
14
+ const iconSize = ringSize / svgRingRatio;
15
+ const IconContainer = styled.span `
16
+ width: ${iconSize}px;
17
+ height: ${iconSize}px;
18
+ color: ${grey144};
19
+ `;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ type Props = {
3
+ rendererConnected: boolean;
4
+ };
5
+ export declare function RemoteRendererOverlay({ rendererConnected }: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { RemoteRendererConnected } from './RemoteRendererConnected.js';
3
+ import { WaitingForRenderer } from './WaitingForRenderer.js';
4
+ export function RemoteRendererOverlay({ rendererConnected }) {
5
+ return rendererConnected ? (React.createElement(RemoteRendererConnected, null)) : (React.createElement(WaitingForRenderer, null));
6
+ }
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { RuntimeStatus } from '../spec.js';
3
+ type Props = {
4
+ runtimeStatus: RuntimeStatus;
5
+ };
6
+ export declare function RendererOverlay({ runtimeStatus }: Props): JSX.Element | null;
7
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { WaitingForRenderer } from './WaitingForRenderer.js';
3
+ export function RendererOverlay({ runtimeStatus }) {
4
+ if (runtimeStatus === 'pending') {
5
+ return React.createElement(WaitingForRenderer, null);
6
+ }
7
+ // No render overlay is shown in both "connected" and "error" states. In the
8
+ // latter case, the renderer will communicate the error using its own
9
+ // framework-specific UI.
10
+ return null;
11
+ }
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare function WaitingForRenderer(): JSX.Element;
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import { DelayRender } from 'react-cosmos-core';
3
+ import styled from 'styled-components';
4
+ import { grey144 } from '../../../style/colors.js';
5
+ import { RendererOverlayContainer, RendererOverlayIconWrapper, RendererOverlayMessage, } from './rendererOverlayShared.js';
6
+ export function WaitingForRenderer() {
7
+ return (React.createElement(DelayRender, { delay: 500 },
8
+ React.createElement(RendererOverlayContainer, null,
9
+ React.createElement(RendererOverlayIconWrapper, null,
10
+ React.createElement(Loader, null)),
11
+ React.createElement(RendererOverlayMessage, null, "Waiting for renderer..."))));
12
+ }
13
+ // Copied from https://codepen.io/bernethe/pen/dorozd
14
+ const Loader = styled.div `
15
+ width: 34px;
16
+ height: 34px;
17
+ border-radius: 50%;
18
+ position: relative;
19
+
20
+ :before,
21
+ :after {
22
+ content: '';
23
+ box-sizing: border-box;
24
+ border: 1px ${grey144} solid;
25
+ border-radius: 50%;
26
+ width: 100%;
27
+ height: 100%;
28
+ position: absolute;
29
+ left: 0px;
30
+ }
31
+
32
+ :before {
33
+ transform: scale(1, 1);
34
+ opacity: 1;
35
+ animation: waveOuter 1.5s infinite linear;
36
+ }
37
+
38
+ :after {
39
+ transform: scale(0, 0);
40
+ opacity: 0;
41
+ animation: waveInner 1.5s infinite linear;
42
+ }
43
+
44
+ @keyframes waveOuter {
45
+ from {
46
+ -webkit-transform: scale(1, 1);
47
+ opacity: 1;
48
+ }
49
+ to {
50
+ -webkit-transform: scale(1.5, 1.5);
51
+ opacity: 0;
52
+ }
53
+ }
54
+
55
+ @keyframes waveInner {
56
+ from {
57
+ transform: scale(0.5, 0.5);
58
+ opacity: 0;
59
+ }
60
+ to {
61
+ transform: scale(1, 1);
62
+ opacity: 1;
63
+ }
64
+ }
65
+ `;
@@ -0,0 +1,3 @@
1
+ export declare const RendererOverlayContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ export declare const RendererOverlayIconWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
3
+ export declare const RendererOverlayMessage: import("styled-components").StyledComponent<"p", any, {}, never>;
@@ -0,0 +1,27 @@
1
+ import styled from 'styled-components';
2
+ import { createGreyColor, grey192 } from '../../../style/colors.js';
3
+ export const RendererOverlayContainer = styled.div `
4
+ position: absolute;
5
+ top: 50%;
6
+ left: 50%;
7
+ transform: translate(-50%, -50%);
8
+ background: ${createGreyColor(8, 0.9)};
9
+ border-radius: 3px;
10
+ height: 116px;
11
+ padding: 0 24px;
12
+ display: flex;
13
+ flex-direction: column;
14
+ align-items: center;
15
+ justify-content: flex-end;
16
+ `;
17
+ export const RendererOverlayIconWrapper = styled.div `
18
+ height: 76px;
19
+ display: flex;
20
+ align-items: center;
21
+ `;
22
+ export const RendererOverlayMessage = styled.p `
23
+ margin-bottom: 16px;
24
+ color: ${grey192};
25
+ text-transform: uppercase;
26
+ white-space: nowrap;
27
+ `;
@@ -1,7 +1,10 @@
1
1
  import React from 'react';
2
+ import { RuntimeStatus } from './spec.js';
2
3
  export type OnIframeRef = (elRef: null | HTMLIFrameElement) => void;
3
4
  type Props = {
4
5
  rendererUrl: null | string;
6
+ rendererConnected: boolean;
7
+ runtimeStatus: RuntimeStatus;
5
8
  onIframeRef: OnIframeRef;
6
9
  };
7
10
  export declare const RendererPreview: React.NamedExoticComponent<Props>;
@@ -1,15 +1,22 @@
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
- export const RendererPreview = React.memo(function RendererPreview({ rendererUrl, onIframeRef, }) {
5
+ import { RemoteRendererOverlay } from './RendererOverlay/RemoteRendererOverlay.js';
6
+ import { RendererOverlay } from './RendererOverlay/RendererOverlay.js';
7
+ export const RendererPreview = React.memo(function RendererPreview({ rendererUrl, rendererConnected, runtimeStatus, onIframeRef, }) {
5
8
  if (!rendererUrl) {
6
- return null;
9
+ // This code path is used when Cosmos is in React Native mode
10
+ return (React.createElement(Container, null,
11
+ React.createElement(RemoteRendererOverlay, { rendererConnected: rendererConnected })));
7
12
  }
8
13
  return (React.createElement(Slot, { name: "rendererPreviewOuter" },
9
14
  React.createElement(Container, null,
10
- 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 *" }),
16
+ React.createElement(RendererOverlay, { runtimeStatus: runtimeStatus }))));
11
17
  });
12
18
  const Container = styled.div `
19
+ position: relative;
13
20
  width: 100%;
14
21
  height: 100%;
15
22
  background-color: #fff;
@@ -34,7 +34,7 @@ export function createRendererRequestHandler() {
34
34
  id: notificationId,
35
35
  type: 'info',
36
36
  title: 'Renderer iframe location changed',
37
- info: `Reload or select another fixture to reset your preview.`,
37
+ info: `Select a fixture to reset your preview.`,
38
38
  });
39
39
  }
40
40
  else {
@@ -59,11 +59,12 @@ function iframeLocationChanged(iframeWindow, iframeSrc) {
59
59
  return false;
60
60
  try {
61
61
  const { href } = iframeWindow.location;
62
- const locationWithoutHash = href.split('#')[0];
63
- return (locationWithoutHash !== iframeSrc &&
64
- // Some static servers strip .html extensions automatically
65
- // https://github.com/zeit/serve-handler/tree/ce35fcd4e1c67356348f4735eed88fb084af9b43#cleanurls-booleanarray
66
- locationWithoutHash !== iframeSrc.replace(/\.html$/, ''));
62
+ return (
63
+ // Don't register a location change when renderer searchParams change
64
+ !href.startsWith(
65
+ // Some static servers strip .html extensions automatically
66
+ // https://github.com/zeit/serve-handler/tree/ce35fcd4e1c67356348f4735eed88fb084af9b43#cleanurls-booleanarray
67
+ iframeSrc.replace(/\.html$/, '')));
67
68
  }
68
69
  catch (err) {
69
70
  // An exception is thrown when trying to access the location of a