@storybook/addon-docs 7.0.0-alpha.4 → 7.0.0-alpha.7

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 (39) hide show
  1. package/dist/cjs/blocks/ArgsTable.js +2 -2
  2. package/dist/cjs/blocks/Canvas.js +12 -2
  3. package/dist/cjs/blocks/Description.js +1 -1
  4. package/dist/cjs/blocks/DocsContainer.js +18 -11
  5. package/dist/cjs/blocks/DocsContext.js +2 -2
  6. package/dist/cjs/blocks/DocsRenderer.js +48 -0
  7. package/dist/cjs/blocks/DocsStory.js +1 -3
  8. package/dist/cjs/blocks/ExternalDocsContainer.js +64 -0
  9. package/dist/cjs/blocks/ExternalPreview.js +99 -0
  10. package/dist/cjs/blocks/Meta.js +17 -3
  11. package/dist/cjs/blocks/Source.js +16 -20
  12. package/dist/cjs/blocks/Stories.js +1 -5
  13. package/dist/cjs/blocks/Story.js +15 -6
  14. package/dist/cjs/blocks/Subtitle.js +1 -1
  15. package/dist/cjs/blocks/enhanceSource.js +1 -3
  16. package/dist/cjs/blocks/index.js +28 -0
  17. package/dist/cjs/blocks/useStory.js +13 -6
  18. package/dist/cjs/preset.js +5 -13
  19. package/dist/cjs/preview.js +6 -2
  20. package/dist/esm/blocks/Canvas.js +12 -2
  21. package/dist/esm/blocks/DocsContainer.js +18 -11
  22. package/dist/esm/blocks/DocsContext.js +2 -2
  23. package/dist/esm/blocks/DocsRenderer.js +32 -0
  24. package/dist/esm/blocks/ExternalDocsContainer.js +48 -0
  25. package/dist/esm/blocks/ExternalPreview.js +89 -0
  26. package/dist/esm/blocks/Meta.js +17 -3
  27. package/dist/esm/blocks/Source.js +9 -3
  28. package/dist/esm/blocks/Story.js +15 -6
  29. package/dist/esm/blocks/index.js +3 -0
  30. package/dist/esm/blocks/useStory.js +13 -6
  31. package/dist/esm/preview.js +6 -2
  32. package/dist/types/blocks/DocsRenderer.d.ts +7 -0
  33. package/dist/types/blocks/ExternalDocsContainer.d.ts +4 -0
  34. package/dist/types/blocks/ExternalPreview.d.ts +19 -0
  35. package/dist/types/blocks/Meta.d.ts +4 -1
  36. package/dist/types/blocks/Story.d.ts +3 -1
  37. package/dist/types/blocks/index.d.ts +2 -0
  38. package/dist/types/preview.d.ts +1 -2
  39. package/package.json +15 -15
@@ -205,7 +205,7 @@ const StoryTable = props => {
205
205
  }
206
206
  }; // Use the dynamically generated component tabs if there are no controls
207
207
 
208
- const storyHasArgsWithControls = argTypes && Object.values(argTypes).find(v => !!(v !== null && v !== void 0 && v.control));
208
+ const storyHasArgsWithControls = argTypes && Object.values(argTypes).find(v => !!v?.control);
209
209
 
210
210
  if (!storyHasArgsWithControls) {
211
211
  updateArgs = null;
@@ -278,7 +278,7 @@ const ArgsTable = props => {
278
278
  const {
279
279
  story: storyName
280
280
  } = props;
281
- const sort = sortProp || (controls === null || controls === void 0 ? void 0 : controls.sort);
281
+ const sort = sortProp || controls?.sort;
282
282
  const main = getComponent(props, context);
283
283
 
284
284
  if (storyName) {
@@ -71,8 +71,18 @@ const getPreviewProps = (_ref, docsContext, sourceContext) => {
71
71
  }
72
72
 
73
73
  const childArray = Array.isArray(children) ? children : [children];
74
- const storyChildren = childArray.filter(c => c.props && (c.props.id || c.props.name));
75
- const targetIds = storyChildren.map(s => s.props.id || (0, _csf.toId)(mdxComponentAnnotations.id || mdxComponentAnnotations.title, (0, _csf.storyNameFromExport)(mdxStoryNameToKey[s.props.name])));
74
+ const storyChildren = childArray.filter(c => c.props && (c.props.id || c.props.name || c.props.of));
75
+ const targetIds = storyChildren.map(({
76
+ props: {
77
+ id,
78
+ of,
79
+ name
80
+ }
81
+ }) => {
82
+ if (id) return id;
83
+ if (of) return docsContext.storyIdByModuleExport(of);
84
+ return (0, _csf.toId)(mdxComponentAnnotations.id || mdxComponentAnnotations.title, (0, _csf.storyNameFromExport)(mdxStoryNameToKey[name]));
85
+ });
76
86
  const sourceProps = (0, _Source.getSourceProps)({
77
87
  ids: targetIds
78
88
  }, docsContext, sourceContext);
@@ -67,7 +67,7 @@ const getDescriptionProps = ({
67
67
  } = docs || {};
68
68
  const target = of === _types.CURRENT_SELECTION ? component : of; // override component description
69
69
 
70
- const componentDescriptionParameter = description === null || description === void 0 ? void 0 : description.component;
70
+ const componentDescriptionParameter = description?.component;
71
71
 
72
72
  if (componentDescriptionParameter) {
73
73
  return {
@@ -57,23 +57,30 @@ const DocsContainer = ({
57
57
  }) => {
58
58
  const {
59
59
  id: storyId,
60
+ type,
60
61
  storyById
61
62
  } = context;
62
- const {
63
- parameters: {
64
- options = {},
65
- docs = {}
63
+ const allComponents = Object.assign({}, defaultComponents);
64
+ let theme = (0, _theming.ensure)(null);
65
+
66
+ if (type === 'legacy') {
67
+ const {
68
+ parameters: {
69
+ options = {},
70
+ docs = {}
71
+ }
72
+ } = storyById(storyId);
73
+ let themeVars = docs.theme;
74
+
75
+ if (!themeVars && options.theme) {
76
+ warnOptionsTheme();
77
+ themeVars = options.theme;
66
78
  }
67
- } = storyById(storyId);
68
- let themeVars = docs.theme;
69
79
 
70
- if (!themeVars && options.theme) {
71
- warnOptionsTheme();
72
- themeVars = options.theme;
80
+ theme = (0, _theming.ensure)(themeVars);
81
+ Object.assign(allComponents, docs.components);
73
82
  }
74
83
 
75
- const theme = (0, _theming.ensure)(themeVars);
76
- const allComponents = Object.assign({}, defaultComponents, docs.components);
77
84
  (0, _react.useEffect)(() => {
78
85
  let url;
79
86
 
@@ -17,9 +17,9 @@ var _global = require("global");
17
17
 
18
18
  /* eslint-disable no-underscore-dangle */
19
19
  if (_global.window && _global.window.__DOCS_CONTEXT__ === undefined) {
20
- _global.window.__DOCS_CONTEXT__ = /*#__PURE__*/(0, _react.createContext)({});
20
+ _global.window.__DOCS_CONTEXT__ = /*#__PURE__*/(0, _react.createContext)(null);
21
21
  _global.window.__DOCS_CONTEXT__.displayName = 'DocsContext';
22
22
  }
23
23
 
24
- const DocsContext = _global.window ? _global.window.__DOCS_CONTEXT__ : /*#__PURE__*/(0, _react.createContext)({});
24
+ const DocsContext = _global.window ? _global.window.__DOCS_CONTEXT__ : /*#__PURE__*/(0, _react.createContext)(null);
25
25
  exports.DocsContext = DocsContext;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DocsRenderer = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _reactDom = _interopRequireDefault(require("react-dom"));
11
+
12
+ var _DocsContainer = require("./DocsContainer");
13
+
14
+ var _DocsPage = require("./DocsPage");
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ class DocsRenderer {
19
+ constructor() {
20
+ this.render = void 0;
21
+ this.unmount = void 0;
22
+
23
+ this.render = (docsContext, docsParameters, element, callback) => {
24
+ renderDocsAsync(docsContext, docsParameters, element).then(callback);
25
+ };
26
+
27
+ this.unmount = element => {
28
+ _reactDom.default.unmountComponentAtNode(element);
29
+ };
30
+ }
31
+
32
+ }
33
+
34
+ exports.DocsRenderer = DocsRenderer;
35
+
36
+ async function renderDocsAsync(docsContext, docsParameters, element) {
37
+ const Container = docsParameters.container || (await docsParameters.getContainer?.()) || _DocsContainer.DocsContainer;
38
+ const Page = docsParameters.page || (await docsParameters.getPage?.()) || _DocsPage.DocsPage; // Use `title` as a key so that we force a re-render every time we switch components
39
+
40
+ const docsElement = /*#__PURE__*/_react.default.createElement(Container, {
41
+ key: docsContext.title,
42
+ context: docsContext
43
+ }, /*#__PURE__*/_react.default.createElement(Page, null));
44
+
45
+ await new Promise(resolve => {
46
+ _reactDom.default.render(docsElement, element, resolve);
47
+ });
48
+ }
@@ -42,9 +42,7 @@ const DocsStory = ({
42
42
  } = parameters;
43
43
 
44
44
  if (expanded && docs) {
45
- var _docs$description;
46
-
47
- description = (_docs$description = docs.description) === null || _docs$description === void 0 ? void 0 : _docs$description.story;
45
+ description = docs.description?.story;
48
46
 
49
47
  if (!description) {
50
48
  description = docs.storyDescription;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ExternalDocsContainer = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _theming = require("@storybook/theming");
11
+
12
+ var _DocsContext = require("./DocsContext");
13
+
14
+ var _ExternalPreview = require("./ExternalPreview");
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ let preview;
19
+
20
+ const ExternalDocsContainer = ({
21
+ projectAnnotations,
22
+ children
23
+ }) => {
24
+ if (!preview) preview = new _ExternalPreview.ExternalPreview(projectAnnotations);
25
+ let pageMeta;
26
+
27
+ const setMeta = m => {
28
+ pageMeta = m;
29
+ };
30
+
31
+ const docsContext = {
32
+ type: 'external',
33
+ id: 'external-docs',
34
+ title: 'External',
35
+ name: 'Docs',
36
+ storyIdByModuleExport: (storyExport, metaExport) => {
37
+ return preview.storyIdByModuleExport(storyExport, metaExport || pageMeta);
38
+ },
39
+ storyById: id => {
40
+ return preview.storyById(id);
41
+ },
42
+ getStoryContext: () => {
43
+ throw new Error('not implemented');
44
+ },
45
+ componentStories: () => {
46
+ // TODO: could implement in a very similar way to in DocsRender. (TODO: How to share code?)
47
+ throw new Error('not implemented');
48
+ },
49
+ loadStory: async id => {
50
+ return preview.storyById(id);
51
+ },
52
+ renderStoryToElement: (story, element) => {
53
+ return preview.renderStoryToElement(story, element);
54
+ },
55
+ setMeta
56
+ };
57
+ return /*#__PURE__*/_react.default.createElement(_DocsContext.DocsContext.Provider, {
58
+ value: docsContext
59
+ }, /*#__PURE__*/_react.default.createElement(_theming.ThemeProvider, {
60
+ theme: (0, _theming.ensure)(_theming.themes.normal)
61
+ }, children));
62
+ };
63
+
64
+ exports.ExternalDocsContainer = ExternalDocsContainer;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ExternalPreview = void 0;
7
+
8
+ var _previewWeb = require("@storybook/preview-web");
9
+
10
+ var _csf = require("@storybook/csf");
11
+
12
+ class ConstantMap {
13
+ // eslint-disable-next-line no-useless-constructor
14
+ constructor(prefix) {
15
+ this.prefix = prefix;
16
+ this.entries = new Map();
17
+ }
18
+
19
+ get(key) {
20
+ if (!this.entries.has(key)) {
21
+ this.entries.set(key, `${this.prefix}${this.entries.size}`);
22
+ }
23
+
24
+ return this.entries.get(key);
25
+ }
26
+
27
+ }
28
+
29
+ class ExternalPreview extends _previewWeb.Preview {
30
+ constructor(projectAnnotations) {
31
+ super();
32
+ this.projectAnnotations = projectAnnotations;
33
+ this.initialized = false;
34
+ this.importPaths = new ConstantMap('./importPath/');
35
+ this.titles = new ConstantMap('title-');
36
+ this.storyIds = new Map();
37
+ this.storyIndex = {
38
+ v: 4,
39
+ entries: {}
40
+ };
41
+ this.moduleExportsByImportPath = {};
42
+ }
43
+
44
+ storyIdByModuleExport(storyExport, meta) {
45
+ if (!this.storyIds.has(storyExport)) this.addStoryFromExports(storyExport, meta);
46
+ return this.storyIds.get(storyExport);
47
+ }
48
+
49
+ addStoryFromExports(storyExport, meta) {
50
+ const importPath = this.importPaths.get(meta);
51
+ this.moduleExportsByImportPath[importPath] = meta;
52
+ const title = meta.default.title || this.titles.get(meta);
53
+ const exportEntry = Object.entries(meta).find(([_, moduleExport]) => moduleExport === storyExport);
54
+ if (!exportEntry) throw new Error(`Didn't find \`of\` used in Story block in the provided CSF exports`);
55
+ const storyId = (0, _csf.toId)(title, exportEntry[0]);
56
+ this.storyIds.set(storyExport, storyId);
57
+ this.storyIndex.entries[storyId] = {
58
+ id: storyId,
59
+ importPath,
60
+ title,
61
+ name: 'Name',
62
+ type: 'story'
63
+ };
64
+
65
+ if (!this.initialized) {
66
+ this.initialized = true;
67
+ return this.initialize({
68
+ getStoryIndex: () => this.storyIndex,
69
+ importFn: path => {
70
+ return Promise.resolve(this.moduleExportsByImportPath[path]);
71
+ },
72
+ getProjectAnnotations: () => this.projectAnnotations
73
+ });
74
+ } // else
75
+
76
+
77
+ return this.onStoriesChanged({
78
+ storyIndex: this.storyIndex
79
+ });
80
+ }
81
+
82
+ storyById(storyId) {
83
+ const entry = this.storyIndex.entries[storyId];
84
+ if (!entry) throw new Error(`Unknown storyId ${storyId}`);
85
+ const {
86
+ importPath,
87
+ title
88
+ } = entry;
89
+ const moduleExports = this.moduleExportsByImportPath[importPath];
90
+ const csfFile = this.storyStore.processCSFFileWithCache(moduleExports, importPath, title);
91
+ return this.storyStore.storyFromCSFFile({
92
+ storyId,
93
+ csfFile
94
+ });
95
+ }
96
+
97
+ }
98
+
99
+ exports.ExternalPreview = ExternalPreview;
@@ -30,6 +30,11 @@ function getFirstStoryId(docsContext) {
30
30
 
31
31
  function renderAnchor() {
32
32
  const context = (0, _react.useContext)(_DocsContext.DocsContext);
33
+
34
+ if (context.type !== 'legacy') {
35
+ return null;
36
+ }
37
+
33
38
  const anchorId = getFirstStoryId(context) || context.id;
34
39
  return /*#__PURE__*/_react.default.createElement(_Anchor.Anchor, {
35
40
  storyId: anchorId
@@ -41,9 +46,18 @@ function renderAnchor() {
41
46
  */
42
47
 
43
48
 
44
- const Meta = () => {
45
- const params = new URL(document.location).searchParams;
46
- const isDocs = params.get('viewMode') === 'docs';
49
+ const Meta = ({
50
+ of
51
+ }) => {
52
+ let isDocs = true;
53
+
54
+ if (document) {
55
+ const params = new URL(document.location).searchParams;
56
+ isDocs = params.get('viewMode') === 'docs';
57
+ }
58
+
59
+ const context = (0, _react.useContext)(_DocsContext.DocsContext);
60
+ if (of) context.setMeta(of);
47
61
  return isDocs ? renderAnchor() : null;
48
62
  };
49
63
 
@@ -35,11 +35,7 @@ exports.SourceState = SourceState;
35
35
  })(SourceState || (exports.SourceState = SourceState = {}));
36
36
 
37
37
  const getSourceState = stories => {
38
- const states = stories.map(story => {
39
- var _story$parameters$doc, _story$parameters$doc2;
40
-
41
- return (_story$parameters$doc = story.parameters.docs) === null || _story$parameters$doc === void 0 ? void 0 : (_story$parameters$doc2 = _story$parameters$doc.source) === null || _story$parameters$doc2 === void 0 ? void 0 : _story$parameters$doc2.state;
42
- }).filter(Boolean);
38
+ const states = stories.map(story => story.parameters.docs?.source?.state).filter(Boolean);
43
39
  if (states.length === 0) return SourceState.CLOSED; // FIXME: handling multiple stories is a pain
44
40
 
45
41
  return states[0];
@@ -51,15 +47,13 @@ const getStorySource = (storyId, sourceContext) => {
51
47
  } = sourceContext; // source rendering is async so source is unavailable at the start of the render cycle,
52
48
  // so we fail gracefully here without warning
53
49
 
54
- return (sources === null || sources === void 0 ? void 0 : sources[storyId]) || {
50
+ return sources?.[storyId] || {
55
51
  code: '',
56
52
  format: false
57
53
  };
58
54
  };
59
55
 
60
56
  const getSnippet = (snippet, story) => {
61
- var _parameters$docs, _parameters$docs$sour, _parameters$docs2, _parameters$docs2$sou, _enhanced$docs, _enhanced$docs$source;
62
-
63
57
  if (!story) {
64
58
  return snippet;
65
59
  }
@@ -69,9 +63,9 @@ const getSnippet = (snippet, story) => {
69
63
  } = story; // eslint-disable-next-line no-underscore-dangle
70
64
 
71
65
  const isArgsStory = parameters.__isArgsStory;
72
- const type = ((_parameters$docs = parameters.docs) === null || _parameters$docs === void 0 ? void 0 : (_parameters$docs$sour = _parameters$docs.source) === null || _parameters$docs$sour === void 0 ? void 0 : _parameters$docs$sour.type) || _shared.SourceType.AUTO; // if user has hard-coded the snippet, that takes precedence
66
+ const type = parameters.docs?.source?.type || _shared.SourceType.AUTO; // if user has hard-coded the snippet, that takes precedence
73
67
 
74
- const userCode = (_parameters$docs2 = parameters.docs) === null || _parameters$docs2 === void 0 ? void 0 : (_parameters$docs2$sou = _parameters$docs2.source) === null || _parameters$docs2$sou === void 0 ? void 0 : _parameters$docs2$sou.code;
68
+ const userCode = parameters.docs?.source?.code;
75
69
 
76
70
  if (userCode !== undefined) {
77
71
  return userCode;
@@ -79,21 +73,17 @@ const getSnippet = (snippet, story) => {
79
73
 
80
74
 
81
75
  if (type === _shared.SourceType.DYNAMIC) {
82
- var _parameters$docs3, _parameters$docs3$tra;
83
-
84
- return ((_parameters$docs3 = parameters.docs) === null || _parameters$docs3 === void 0 ? void 0 : (_parameters$docs3$tra = _parameters$docs3.transformSource) === null || _parameters$docs3$tra === void 0 ? void 0 : _parameters$docs3$tra.call(_parameters$docs3, snippet, story)) || snippet;
76
+ return parameters.docs?.transformSource?.(snippet, story) || snippet;
85
77
  } // if this is an args story and there's a snippet
86
78
 
87
79
 
88
80
  if (type === _shared.SourceType.AUTO && snippet && isArgsStory) {
89
- var _parameters$docs4, _parameters$docs4$tra;
90
-
91
- return ((_parameters$docs4 = parameters.docs) === null || _parameters$docs4 === void 0 ? void 0 : (_parameters$docs4$tra = _parameters$docs4.transformSource) === null || _parameters$docs4$tra === void 0 ? void 0 : _parameters$docs4$tra.call(_parameters$docs4, snippet, story)) || snippet;
81
+ return parameters.docs?.transformSource?.(snippet, story) || snippet;
92
82
  } // otherwise, use the source code logic
93
83
 
94
84
 
95
85
  const enhanced = (0, _enhanceSource.enhanceSource)(story) || parameters;
96
- return (enhanced === null || enhanced === void 0 ? void 0 : (_enhanced$docs = enhanced.docs) === null || _enhanced$docs === void 0 ? void 0 : (_enhanced$docs$source = _enhanced$docs.source) === null || _enhanced$docs$source === void 0 ? void 0 : _enhanced$docs$source.code) || '';
86
+ return enhanced?.docs?.source?.code || '';
97
87
  };
98
88
 
99
89
  const getSourceProps = (props, docsContext, sourceContext) => {
@@ -101,9 +91,15 @@ const getSourceProps = (props, docsContext, sourceContext) => {
101
91
  id: currentId,
102
92
  storyById
103
93
  } = docsContext;
104
- const {
105
- parameters
106
- } = storyById(currentId);
94
+ let parameters = {};
95
+
96
+ try {
97
+ ({
98
+ parameters
99
+ } = storyById(currentId));
100
+ } catch (err) {// TODO: in external mode, there is no "current"
101
+ }
102
+
107
103
  const codeProps = props;
108
104
  const singleProps = props;
109
105
  const multiProps = props;
@@ -27,11 +27,7 @@ const Stories = ({
27
27
  componentStories
28
28
  } = (0, _react.useContext)(_DocsContext.DocsContext);
29
29
  let stories = componentStories();
30
- stories = stories.filter(story => {
31
- var _story$parameters, _story$parameters$doc;
32
-
33
- return !((_story$parameters = story.parameters) !== null && _story$parameters !== void 0 && (_story$parameters$doc = _story$parameters.docs) !== null && _story$parameters$doc !== void 0 && _story$parameters$doc.disable);
34
- });
30
+ stories = stories.filter(story => !story.parameters?.docs?.disable);
35
31
  if (!includePrimary) stories = stories.slice(1);
36
32
 
37
33
  if (!stories || stories.length === 0) {
@@ -36,8 +36,15 @@ exports.lookupStoryId = lookupStoryId;
36
36
 
37
37
  const getStoryId = (props, context) => {
38
38
  const {
39
- id
39
+ id,
40
+ of,
41
+ meta
40
42
  } = props;
43
+
44
+ if (of) {
45
+ return context.storyIdByModuleExport(of, meta);
46
+ }
47
+
41
48
  const {
42
49
  name
43
50
  } = props;
@@ -53,8 +60,8 @@ const getStoryProps = ({
53
60
  }, story) => {
54
61
  const {
55
62
  name: storyName,
56
- parameters
57
- } = story;
63
+ parameters = {}
64
+ } = story || {};
58
65
  const {
59
66
  docs = {}
60
67
  } = parameters;
@@ -71,7 +78,7 @@ const getStoryProps = ({
71
78
  const storyIsInline = typeof inline === 'boolean' ? inline : inlineStories;
72
79
  return Object.assign({
73
80
  inline: storyIsInline,
74
- id: story.id,
81
+ id: story?.id,
75
82
  height: height || (storyIsInline ? undefined : iframeHeight),
76
83
  title: storyName
77
84
  }, storyIsInline && {
@@ -109,7 +116,9 @@ const Story = props => {
109
116
  return null;
110
117
  }
111
118
 
112
- if (storyProps.inline) {
119
+ const inline = context.type === 'external' || storyProps.inline;
120
+
121
+ if (inline) {
113
122
  // We do this so React doesn't complain when we replace the span in a secondary render
114
123
  const htmlContents = `<span></span>`; // FIXME: height/style/etc. lifted from PureStory
115
124
 
@@ -120,7 +129,7 @@ const Story = props => {
120
129
  id: storyBlockIdFromId(story.id)
121
130
  }, /*#__PURE__*/_react.default.createElement(_react2.MDXProvider, {
122
131
  components: _components.resetComponents
123
- }, height ? /*#__PURE__*/_react.default.createElement("style", null, `#story--${story.id} { min-height: ${height}; transform: translateZ(0); overflow: auto }`) : null, showLoader && /*#__PURE__*/_react.default.createElement(_components.StorySkeleton, null), /*#__PURE__*/_react.default.createElement("div", {
132
+ }, height ? /*#__PURE__*/_react.default.createElement("style", null, `#story--${story.id} { min-height: ${height}px; transform: translateZ(0); overflow: auto }`) : null, showLoader && /*#__PURE__*/_react.default.createElement(_components.StorySkeleton, null), /*#__PURE__*/_react.default.createElement("div", {
124
133
  ref: storyRef,
125
134
  "data-name": story.name,
126
135
  dangerouslySetInnerHTML: {
@@ -28,7 +28,7 @@ const Subtitle = ({
28
28
  let text = children;
29
29
 
30
30
  if (!text) {
31
- text = parameters === null || parameters === void 0 ? void 0 : parameters.componentSubtitle;
31
+ text = parameters?.componentSubtitle;
32
32
  }
33
33
 
34
34
  return text ? /*#__PURE__*/_react.default.createElement(_components.Subtitle, {
@@ -60,8 +60,6 @@ const extract = (targetId, {
60
60
  };
61
61
 
62
62
  const enhanceSource = story => {
63
- var _docs$source;
64
-
65
63
  const {
66
64
  id,
67
65
  parameters
@@ -74,7 +72,7 @@ const enhanceSource = story => {
74
72
  transformSource
75
73
  } = docs; // no input or user has manually overridden the output
76
74
 
77
- if (!(storySource !== null && storySource !== void 0 && storySource.source) || (_docs$source = docs.source) !== null && _docs$source !== void 0 && _docs$source.code) {
75
+ if (!storySource?.source || docs.source?.code) {
78
76
  return null;
79
77
  }
80
78
 
@@ -141,6 +141,34 @@ Object.keys(_DocsContainer).forEach(function (key) {
141
141
  });
142
142
  });
143
143
 
144
+ var _DocsRenderer = require("./DocsRenderer");
145
+
146
+ Object.keys(_DocsRenderer).forEach(function (key) {
147
+ if (key === "default" || key === "__esModule") return;
148
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
149
+ if (key in exports && exports[key] === _DocsRenderer[key]) return;
150
+ Object.defineProperty(exports, key, {
151
+ enumerable: true,
152
+ get: function () {
153
+ return _DocsRenderer[key];
154
+ }
155
+ });
156
+ });
157
+
158
+ var _ExternalDocsContainer = require("./ExternalDocsContainer");
159
+
160
+ Object.keys(_ExternalDocsContainer).forEach(function (key) {
161
+ if (key === "default" || key === "__esModule") return;
162
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
163
+ if (key in exports && exports[key] === _ExternalDocsContainer[key]) return;
164
+ Object.defineProperty(exports, key, {
165
+ enumerable: true,
166
+ get: function () {
167
+ return _ExternalDocsContainer[key];
168
+ }
169
+ });
170
+ });
171
+
144
172
  var _DocsStory = require("./DocsStory");
145
173
 
146
174
  Object.keys(_DocsStory).forEach(function (key) {
@@ -14,11 +14,9 @@ function useStory(storyId, context) {
14
14
  }
15
15
 
16
16
  function useStories(storyIds, context) {
17
- const initialStoriesById = context.componentStories().reduce((acc, story) => {
18
- acc[story.id] = story;
19
- return acc;
20
- }, {});
21
- const [storiesById, setStories] = (0, _react.useState)(initialStoriesById);
17
+ // Legacy docs pages can reference any story by id. Those stories will need to be
18
+ // asyncronously loaded; we use the state for this
19
+ const [storiesById, setStories] = (0, _react.useState)({});
22
20
  (0, _react.useEffect)(() => {
23
21
  Promise.all(storyIds.map(async storyId => {
24
22
  // loadStory will be called every single time useStory is called
@@ -33,5 +31,14 @@ function useStories(storyIds, context) {
33
31
  }));
34
32
  }));
35
33
  });
36
- return storyIds.map(storyId => storiesById[storyId]);
34
+ return storyIds.map(storyId => {
35
+ if (storiesById[storyId]) return storiesById[storyId];
36
+
37
+ try {
38
+ // If we are allowed to load this story id synchonously, this will work
39
+ return context.storyById(storyId);
40
+ } catch (err) {
41
+ return null;
42
+ }
43
+ });
37
44
  }
@@ -29,7 +29,7 @@ function createBabelOptions({
29
29
  mdxBabelOptions,
30
30
  configureJSX
31
31
  }) {
32
- const babelPlugins = (mdxBabelOptions === null || mdxBabelOptions === void 0 ? void 0 : mdxBabelOptions.plugins) || (babelOptions === null || babelOptions === void 0 ? void 0 : babelOptions.plugins) || [];
32
+ const babelPlugins = mdxBabelOptions?.plugins || babelOptions?.plugins || [];
33
33
  const jsxPlugin = [require.resolve('@babel/plugin-transform-react-jsx'), {
34
34
  pragma: 'React.createElement',
35
35
  pragmaFrag: 'React.Fragment'
@@ -45,8 +45,6 @@ function createBabelOptions({
45
45
  }
46
46
 
47
47
  async function webpack(webpackConfig = {}, options) {
48
- var _global$FEATURES, _global$FEATURES2;
49
-
50
48
  const resolvedBabelLoader = require.resolve('babel-loader');
51
49
 
52
50
  const {
@@ -67,11 +65,11 @@ async function webpack(webpackConfig = {}, options) {
67
65
  skipCsf: true,
68
66
  remarkPlugins: [_remarkSlug.default, _remarkExternalLinks.default]
69
67
  };
70
- const mdxVersion = (_global$FEATURES = _global.default.FEATURES) !== null && _global$FEATURES !== void 0 && _global$FEATURES.previewMdx2 ? 'MDX2' : 'MDX1';
68
+ const mdxVersion = _global.default.FEATURES?.previewMdx2 ? 'MDX2' : 'MDX1';
71
69
 
72
70
  _nodeLogger.logger.info(`Addon-docs: using ${mdxVersion}`);
73
71
 
74
- const mdxLoader = (_global$FEATURES2 = _global.default.FEATURES) !== null && _global$FEATURES2 !== void 0 && _global$FEATURES2.previewMdx2 ? require.resolve('@storybook/mdx2-csf/loader') : require.resolve('@storybook/mdx1-csf/loader'); // set `sourceLoaderOptions` to `null` to disable for manual configuration
72
+ const mdxLoader = _global.default.FEATURES?.previewMdx2 ? require.resolve('@storybook/mdx2-csf/loader') : require.resolve('@storybook/mdx1-csf/loader'); // set `sourceLoaderOptions` to `null` to disable for manual configuration
75
73
 
76
74
  const sourceLoader = sourceLoaderOptions ? [{
77
75
  test: /\.(stories|story)\.[tj]sx?$/,
@@ -84,11 +82,7 @@ async function webpack(webpackConfig = {}, options) {
84
82
  let rules = module.rules || [];
85
83
 
86
84
  if (transcludeMarkdown) {
87
- rules = [...rules.filter(rule => {
88
- var _rule$test;
89
-
90
- return ((_rule$test = rule.test) === null || _rule$test === void 0 ? void 0 : _rule$test.toString()) !== '/\\.md$/';
91
- }), {
85
+ rules = [...rules.filter(rule => rule.test?.toString() !== '/\\.md$/'), {
92
86
  test: /\.md$/,
93
87
  use: [{
94
88
  loader: resolvedBabelLoader,
@@ -140,13 +134,11 @@ async function webpack(webpackConfig = {}, options) {
140
134
 
141
135
  const storyIndexers = async indexers => {
142
136
  const mdxIndexer = async (fileName, opts) => {
143
- var _global$FEATURES3;
144
-
145
137
  let code = (await _fsExtra.default.readFile(fileName, 'utf-8')).toString(); // @ts-ignore
146
138
 
147
139
  const {
148
140
  compile
149
- } = (_global$FEATURES3 = _global.default.FEATURES) !== null && _global$FEATURES3 !== void 0 && _global$FEATURES3.previewMdx2 ? await Promise.resolve().then(() => _interopRequireWildcard(require('@storybook/mdx2-csf'))) : await Promise.resolve().then(() => _interopRequireWildcard(require('@storybook/mdx1-csf')));
141
+ } = _global.default.FEATURES?.previewMdx2 ? await Promise.resolve().then(() => _interopRequireWildcard(require('@storybook/mdx2-csf'))) : await Promise.resolve().then(() => _interopRequireWildcard(require('@storybook/mdx1-csf')));
150
142
  code = await compile(code, {});
151
143
  return (0, _csfTools.loadCsf)(code, Object.assign({}, opts, {
152
144
  fileName
@@ -11,8 +11,12 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
11
11
 
12
12
  const parameters = {
13
13
  docs: {
14
- getContainer: async () => (await Promise.resolve().then(() => _interopRequireWildcard(require('./blocks')))).DocsContainer,
15
- getPage: async () => (await Promise.resolve().then(() => _interopRequireWildcard(require('./blocks')))).DocsPage
14
+ renderer: async () => {
15
+ const {
16
+ DocsRenderer
17
+ } = await Promise.resolve().then(() => _interopRequireWildcard(require('./blocks/DocsRenderer')));
18
+ return new DocsRenderer();
19
+ }
16
20
  }
17
21
  };
18
22
  exports.parameters = parameters;
@@ -47,8 +47,18 @@ const getPreviewProps = (_ref, docsContext, sourceContext) => {
47
47
  }
48
48
 
49
49
  const childArray = Array.isArray(children) ? children : [children];
50
- const storyChildren = childArray.filter(c => c.props && (c.props.id || c.props.name));
51
- const targetIds = storyChildren.map(s => s.props.id || toId(mdxComponentAnnotations.id || mdxComponentAnnotations.title, storyNameFromExport(mdxStoryNameToKey[s.props.name])));
50
+ const storyChildren = childArray.filter(c => c.props && (c.props.id || c.props.name || c.props.of));
51
+ const targetIds = storyChildren.map(({
52
+ props: {
53
+ id,
54
+ of,
55
+ name
56
+ }
57
+ }) => {
58
+ if (id) return id;
59
+ if (of) return docsContext.storyIdByModuleExport(of);
60
+ return toId(mdxComponentAnnotations.id || mdxComponentAnnotations.title, storyNameFromExport(mdxStoryNameToKey[name]));
61
+ });
52
62
  const sourceProps = getSourceProps({
53
63
  ids: targetIds
54
64
  }, docsContext, sourceContext);
@@ -30,23 +30,30 @@ export const DocsContainer = ({
30
30
  }) => {
31
31
  const {
32
32
  id: storyId,
33
+ type,
33
34
  storyById
34
35
  } = context;
35
- const {
36
- parameters: {
37
- options = {},
38
- docs = {}
36
+ const allComponents = Object.assign({}, defaultComponents);
37
+ let theme = ensureTheme(null);
38
+
39
+ if (type === 'legacy') {
40
+ const {
41
+ parameters: {
42
+ options = {},
43
+ docs = {}
44
+ }
45
+ } = storyById(storyId);
46
+ let themeVars = docs.theme;
47
+
48
+ if (!themeVars && options.theme) {
49
+ warnOptionsTheme();
50
+ themeVars = options.theme;
39
51
  }
40
- } = storyById(storyId);
41
- let themeVars = docs.theme;
42
52
 
43
- if (!themeVars && options.theme) {
44
- warnOptionsTheme();
45
- themeVars = options.theme;
53
+ theme = ensureTheme(themeVars);
54
+ Object.assign(allComponents, docs.components);
46
55
  }
47
56
 
48
- const theme = ensureTheme(themeVars);
49
- const allComponents = Object.assign({}, defaultComponents, docs.components);
50
57
  useEffect(() => {
51
58
  let url;
52
59
 
@@ -9,8 +9,8 @@ import { window as globalWindow } from 'global';
9
9
 
10
10
  /* eslint-disable no-underscore-dangle */
11
11
  if (globalWindow && globalWindow.__DOCS_CONTEXT__ === undefined) {
12
- globalWindow.__DOCS_CONTEXT__ = /*#__PURE__*/createContext({});
12
+ globalWindow.__DOCS_CONTEXT__ = /*#__PURE__*/createContext(null);
13
13
  globalWindow.__DOCS_CONTEXT__.displayName = 'DocsContext';
14
14
  }
15
15
 
16
- export const DocsContext = globalWindow ? globalWindow.__DOCS_CONTEXT__ : /*#__PURE__*/createContext({});
16
+ export const DocsContext = globalWindow ? globalWindow.__DOCS_CONTEXT__ : /*#__PURE__*/createContext(null);
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { DocsContainer } from './DocsContainer';
4
+ import { DocsPage } from './DocsPage';
5
+ export class DocsRenderer {
6
+ constructor() {
7
+ this.render = void 0;
8
+ this.unmount = void 0;
9
+
10
+ this.render = (docsContext, docsParameters, element, callback) => {
11
+ renderDocsAsync(docsContext, docsParameters, element).then(callback);
12
+ };
13
+
14
+ this.unmount = element => {
15
+ ReactDOM.unmountComponentAtNode(element);
16
+ };
17
+ }
18
+
19
+ }
20
+
21
+ async function renderDocsAsync(docsContext, docsParameters, element) {
22
+ const Container = docsParameters.container || (await docsParameters.getContainer?.()) || DocsContainer;
23
+ const Page = docsParameters.page || (await docsParameters.getPage?.()) || DocsPage; // Use `title` as a key so that we force a re-render every time we switch components
24
+
25
+ const docsElement = /*#__PURE__*/React.createElement(Container, {
26
+ key: docsContext.title,
27
+ context: docsContext
28
+ }, /*#__PURE__*/React.createElement(Page, null));
29
+ await new Promise(resolve => {
30
+ ReactDOM.render(docsElement, element, resolve);
31
+ });
32
+ }
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { ThemeProvider, themes, ensure } from '@storybook/theming';
3
+ import { DocsContext } from './DocsContext';
4
+ import { ExternalPreview } from './ExternalPreview';
5
+ let preview;
6
+ export const ExternalDocsContainer = ({
7
+ projectAnnotations,
8
+ children
9
+ }) => {
10
+ if (!preview) preview = new ExternalPreview(projectAnnotations);
11
+ let pageMeta;
12
+
13
+ const setMeta = m => {
14
+ pageMeta = m;
15
+ };
16
+
17
+ const docsContext = {
18
+ type: 'external',
19
+ id: 'external-docs',
20
+ title: 'External',
21
+ name: 'Docs',
22
+ storyIdByModuleExport: (storyExport, metaExport) => {
23
+ return preview.storyIdByModuleExport(storyExport, metaExport || pageMeta);
24
+ },
25
+ storyById: id => {
26
+ return preview.storyById(id);
27
+ },
28
+ getStoryContext: () => {
29
+ throw new Error('not implemented');
30
+ },
31
+ componentStories: () => {
32
+ // TODO: could implement in a very similar way to in DocsRender. (TODO: How to share code?)
33
+ throw new Error('not implemented');
34
+ },
35
+ loadStory: async id => {
36
+ return preview.storyById(id);
37
+ },
38
+ renderStoryToElement: (story, element) => {
39
+ return preview.renderStoryToElement(story, element);
40
+ },
41
+ setMeta
42
+ };
43
+ return /*#__PURE__*/React.createElement(DocsContext.Provider, {
44
+ value: docsContext
45
+ }, /*#__PURE__*/React.createElement(ThemeProvider, {
46
+ theme: ensure(themes.normal)
47
+ }, children));
48
+ };
@@ -0,0 +1,89 @@
1
+ import { Preview } from '@storybook/preview-web';
2
+ import { toId } from '@storybook/csf';
3
+
4
+ class ConstantMap {
5
+ // eslint-disable-next-line no-useless-constructor
6
+ constructor(prefix) {
7
+ this.prefix = prefix;
8
+ this.entries = new Map();
9
+ }
10
+
11
+ get(key) {
12
+ if (!this.entries.has(key)) {
13
+ this.entries.set(key, `${this.prefix}${this.entries.size}`);
14
+ }
15
+
16
+ return this.entries.get(key);
17
+ }
18
+
19
+ }
20
+
21
+ export class ExternalPreview extends Preview {
22
+ constructor(projectAnnotations) {
23
+ super();
24
+ this.projectAnnotations = projectAnnotations;
25
+ this.initialized = false;
26
+ this.importPaths = new ConstantMap('./importPath/');
27
+ this.titles = new ConstantMap('title-');
28
+ this.storyIds = new Map();
29
+ this.storyIndex = {
30
+ v: 4,
31
+ entries: {}
32
+ };
33
+ this.moduleExportsByImportPath = {};
34
+ }
35
+
36
+ storyIdByModuleExport(storyExport, meta) {
37
+ if (!this.storyIds.has(storyExport)) this.addStoryFromExports(storyExport, meta);
38
+ return this.storyIds.get(storyExport);
39
+ }
40
+
41
+ addStoryFromExports(storyExport, meta) {
42
+ const importPath = this.importPaths.get(meta);
43
+ this.moduleExportsByImportPath[importPath] = meta;
44
+ const title = meta.default.title || this.titles.get(meta);
45
+ const exportEntry = Object.entries(meta).find(([_, moduleExport]) => moduleExport === storyExport);
46
+ if (!exportEntry) throw new Error(`Didn't find \`of\` used in Story block in the provided CSF exports`);
47
+ const storyId = toId(title, exportEntry[0]);
48
+ this.storyIds.set(storyExport, storyId);
49
+ this.storyIndex.entries[storyId] = {
50
+ id: storyId,
51
+ importPath,
52
+ title,
53
+ name: 'Name',
54
+ type: 'story'
55
+ };
56
+
57
+ if (!this.initialized) {
58
+ this.initialized = true;
59
+ return this.initialize({
60
+ getStoryIndex: () => this.storyIndex,
61
+ importFn: path => {
62
+ return Promise.resolve(this.moduleExportsByImportPath[path]);
63
+ },
64
+ getProjectAnnotations: () => this.projectAnnotations
65
+ });
66
+ } // else
67
+
68
+
69
+ return this.onStoriesChanged({
70
+ storyIndex: this.storyIndex
71
+ });
72
+ }
73
+
74
+ storyById(storyId) {
75
+ const entry = this.storyIndex.entries[storyId];
76
+ if (!entry) throw new Error(`Unknown storyId ${storyId}`);
77
+ const {
78
+ importPath,
79
+ title
80
+ } = entry;
81
+ const moduleExports = this.moduleExportsByImportPath[importPath];
82
+ const csfFile = this.storyStore.processCSFFileWithCache(moduleExports, importPath, title);
83
+ return this.storyStore.storyFromCSFFile({
84
+ storyId,
85
+ csfFile
86
+ });
87
+ }
88
+
89
+ }
@@ -13,6 +13,11 @@ function getFirstStoryId(docsContext) {
13
13
 
14
14
  function renderAnchor() {
15
15
  const context = useContext(DocsContext);
16
+
17
+ if (context.type !== 'legacy') {
18
+ return null;
19
+ }
20
+
16
21
  const anchorId = getFirstStoryId(context) || context.id;
17
22
  return /*#__PURE__*/React.createElement(Anchor, {
18
23
  storyId: anchorId
@@ -24,8 +29,17 @@ function renderAnchor() {
24
29
  */
25
30
 
26
31
 
27
- export const Meta = () => {
28
- const params = new URL(document.location).searchParams;
29
- const isDocs = params.get('viewMode') === 'docs';
32
+ export const Meta = ({
33
+ of
34
+ }) => {
35
+ let isDocs = true;
36
+
37
+ if (document) {
38
+ const params = new URL(document.location).searchParams;
39
+ isDocs = params.get('viewMode') === 'docs';
40
+ }
41
+
42
+ const context = useContext(DocsContext);
43
+ if (of) context.setMeta(of);
30
44
  return isDocs ? renderAnchor() : null;
31
45
  };
@@ -71,9 +71,15 @@ export const getSourceProps = (props, docsContext, sourceContext) => {
71
71
  id: currentId,
72
72
  storyById
73
73
  } = docsContext;
74
- const {
75
- parameters
76
- } = storyById(currentId);
74
+ let parameters = {};
75
+
76
+ try {
77
+ ({
78
+ parameters
79
+ } = storyById(currentId));
80
+ } catch (err) {// TODO: in external mode, there is no "current"
81
+ }
82
+
77
83
  const codeProps = props;
78
84
  const singleProps = props;
79
85
  const multiProps = props;
@@ -12,8 +12,15 @@ export const lookupStoryId = (storyName, {
12
12
  }) => toId(mdxComponentAnnotations.id || mdxComponentAnnotations.title, storyNameFromExport(mdxStoryNameToKey[storyName]));
13
13
  export const getStoryId = (props, context) => {
14
14
  const {
15
- id
15
+ id,
16
+ of,
17
+ meta
16
18
  } = props;
19
+
20
+ if (of) {
21
+ return context.storyIdByModuleExport(of, meta);
22
+ }
23
+
17
24
  const {
18
25
  name
19
26
  } = props;
@@ -26,8 +33,8 @@ export const getStoryProps = ({
26
33
  }, story) => {
27
34
  const {
28
35
  name: storyName,
29
- parameters
30
- } = story;
36
+ parameters = {}
37
+ } = story || {};
31
38
  const {
32
39
  docs = {}
33
40
  } = parameters;
@@ -44,7 +51,7 @@ export const getStoryProps = ({
44
51
  const storyIsInline = typeof inline === 'boolean' ? inline : inlineStories;
45
52
  return Object.assign({
46
53
  inline: storyIsInline,
47
- id: story.id,
54
+ id: story?.id,
48
55
  height: height || (storyIsInline ? undefined : iframeHeight),
49
56
  title: storyName
50
57
  }, storyIsInline && {
@@ -80,7 +87,9 @@ const Story = props => {
80
87
  return null;
81
88
  }
82
89
 
83
- if (storyProps.inline) {
90
+ const inline = context.type === 'external' || storyProps.inline;
91
+
92
+ if (inline) {
84
93
  // We do this so React doesn't complain when we replace the span in a secondary render
85
94
  const htmlContents = `<span></span>`; // FIXME: height/style/etc. lifted from PureStory
86
95
 
@@ -91,7 +100,7 @@ const Story = props => {
91
100
  id: storyBlockIdFromId(story.id)
92
101
  }, /*#__PURE__*/React.createElement(MDXProvider, {
93
102
  components: resetComponents
94
- }, height ? /*#__PURE__*/React.createElement("style", null, `#story--${story.id} { min-height: ${height}; transform: translateZ(0); overflow: auto }`) : null, showLoader && /*#__PURE__*/React.createElement(StorySkeleton, null), /*#__PURE__*/React.createElement("div", {
103
+ }, height ? /*#__PURE__*/React.createElement("style", null, `#story--${story.id} { min-height: ${height}px; transform: translateZ(0); overflow: auto }`) : null, showLoader && /*#__PURE__*/React.createElement(StorySkeleton, null), /*#__PURE__*/React.createElement("div", {
95
104
  ref: storyRef,
96
105
  "data-name": story.name,
97
106
  dangerouslySetInnerHTML: {
@@ -6,6 +6,9 @@ export * from './Description';
6
6
  export * from './DocsContext';
7
7
  export * from './DocsPage';
8
8
  export * from './DocsContainer';
9
+ export * from './DocsRenderer'; // For testing
10
+
11
+ export * from './ExternalDocsContainer';
9
12
  export * from './DocsStory';
10
13
  export * from './Heading';
11
14
  export * from './Meta';
@@ -4,11 +4,9 @@ export function useStory(storyId, context) {
4
4
  return stories && stories[0];
5
5
  }
6
6
  export function useStories(storyIds, context) {
7
- const initialStoriesById = context.componentStories().reduce((acc, story) => {
8
- acc[story.id] = story;
9
- return acc;
10
- }, {});
11
- const [storiesById, setStories] = useState(initialStoriesById);
7
+ // Legacy docs pages can reference any story by id. Those stories will need to be
8
+ // asyncronously loaded; we use the state for this
9
+ const [storiesById, setStories] = useState({});
12
10
  useEffect(() => {
13
11
  Promise.all(storyIds.map(async storyId => {
14
12
  // loadStory will be called every single time useStory is called
@@ -23,5 +21,14 @@ export function useStories(storyIds, context) {
23
21
  }));
24
22
  }));
25
23
  });
26
- return storyIds.map(storyId => storiesById[storyId]);
24
+ return storyIds.map(storyId => {
25
+ if (storiesById[storyId]) return storiesById[storyId];
26
+
27
+ try {
28
+ // If we are allowed to load this story id synchonously, this will work
29
+ return context.storyById(storyId);
30
+ } catch (err) {
31
+ return null;
32
+ }
33
+ });
27
34
  }
@@ -1,6 +1,10 @@
1
1
  export const parameters = {
2
2
  docs: {
3
- getContainer: async () => (await import('./blocks')).DocsContainer,
4
- getPage: async () => (await import('./blocks')).DocsPage
3
+ renderer: async () => {
4
+ const {
5
+ DocsRenderer
6
+ } = await import('./blocks/DocsRenderer');
7
+ return new DocsRenderer();
8
+ }
5
9
  }
6
10
  };
@@ -0,0 +1,7 @@
1
+ import { AnyFramework } from '@storybook/csf';
2
+ import { DocsRenderFunction } from '@storybook/preview-web';
3
+ export declare class DocsRenderer<TFramework extends AnyFramework> {
4
+ render: DocsRenderFunction<TFramework>;
5
+ unmount: (element: HTMLElement) => void;
6
+ constructor();
7
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const ExternalDocsContainer: React.FC<{
3
+ projectAnnotations: any;
4
+ }>;
@@ -0,0 +1,19 @@
1
+ import { Preview } from '@storybook/preview-web';
2
+ import { ModuleExports, ModuleExport } from '@storybook/store';
3
+ import { AnyFramework, StoryId, ProjectAnnotations } from '@storybook/csf';
4
+ declare type StoryExport = ModuleExport;
5
+ declare type MetaExport = ModuleExports;
6
+ export declare class ExternalPreview<TFramework extends AnyFramework> extends Preview<TFramework> {
7
+ projectAnnotations: ProjectAnnotations;
8
+ private initialized;
9
+ private importPaths;
10
+ private titles;
11
+ storyIds: Map<any, string>;
12
+ private storyIndex;
13
+ private moduleExportsByImportPath;
14
+ constructor(projectAnnotations: ProjectAnnotations);
15
+ storyIdByModuleExport(storyExport: StoryExport, meta: MetaExport): string;
16
+ addStoryFromExports(storyExport: StoryExport, meta: MetaExport): Promise<void>;
17
+ storyById(storyId: StoryId): import("@storybook/store").Story<TFramework>;
18
+ }
19
+ export {};
@@ -1,6 +1,9 @@
1
1
  import { FC } from 'react';
2
2
  import { BaseAnnotations } from '@storybook/csf';
3
- declare type MetaProps = BaseAnnotations;
3
+ import type { ModuleExports } from '@storybook/store';
4
+ declare type MetaProps = BaseAnnotations & {
5
+ of?: ModuleExports;
6
+ };
4
7
  /**
5
8
  * This component is used to declare component metadata in docs
6
9
  * and gets transformed into a default export underneath the hood.
@@ -1,7 +1,7 @@
1
1
  import { FunctionComponent, ReactNode, ElementType, ComponentProps } from 'react';
2
2
  import { Story as PureStory } from '@storybook/components';
3
3
  import { StoryId, StoryAnnotations, AnyFramework } from '@storybook/csf';
4
- import type { Story as StoryType } from '@storybook/store';
4
+ import type { ModuleExport, ModuleExports, Story as StoryType } from '@storybook/store';
5
5
  import { DocsContextProps } from './DocsContext';
6
6
  export declare const storyBlockIdFromId: (storyId: string) => string;
7
7
  declare type PureStoryProps = ComponentProps<typeof PureStory>;
@@ -15,6 +15,8 @@ declare type StoryDefProps = {
15
15
  };
16
16
  declare type StoryRefProps = {
17
17
  id?: string;
18
+ of?: ModuleExport;
19
+ meta?: ModuleExports;
18
20
  };
19
21
  declare type StoryImportProps = {
20
22
  name: string;
@@ -6,6 +6,8 @@ export * from './Description';
6
6
  export * from './DocsContext';
7
7
  export * from './DocsPage';
8
8
  export * from './DocsContainer';
9
+ export * from './DocsRenderer';
10
+ export * from './ExternalDocsContainer';
9
11
  export * from './DocsStory';
10
12
  export * from './Heading';
11
13
  export * from './Meta';
@@ -1,6 +1,5 @@
1
1
  export declare const parameters: {
2
2
  docs: {
3
- getContainer: () => Promise<import("react").FunctionComponent<import("./blocks").DocsContainerProps<import("@storybook/csf").AnyFramework>>>;
4
- getPage: () => Promise<import("react").FC<{}>>;
3
+ renderer: () => Promise<import("./blocks/DocsRenderer").DocsRenderer<import("@storybook/csf").AnyFramework>>;
5
4
  };
6
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/addon-docs",
3
- "version": "7.0.0-alpha.4",
3
+ "version": "7.0.0-alpha.7",
4
4
  "description": "Document component usage and properties in Markdown",
5
5
  "keywords": [
6
6
  "addon",
@@ -52,21 +52,21 @@
52
52
  "@babel/preset-env": "^7.12.11",
53
53
  "@jest/transform": "^26.6.2",
54
54
  "@mdx-js/react": "^1.6.22",
55
- "@storybook/addons": "7.0.0-alpha.4",
56
- "@storybook/api": "7.0.0-alpha.4",
57
- "@storybook/components": "7.0.0-alpha.4",
58
- "@storybook/core-common": "7.0.0-alpha.4",
59
- "@storybook/core-events": "7.0.0-alpha.4",
55
+ "@storybook/addons": "7.0.0-alpha.7",
56
+ "@storybook/api": "7.0.0-alpha.7",
57
+ "@storybook/components": "7.0.0-alpha.7",
58
+ "@storybook/core-common": "7.0.0-alpha.7",
59
+ "@storybook/core-events": "7.0.0-alpha.7",
60
60
  "@storybook/csf": "0.0.2--canary.4566f4d.1",
61
- "@storybook/csf-tools": "7.0.0-alpha.4",
62
- "@storybook/docs-tools": "7.0.0-alpha.4",
61
+ "@storybook/csf-tools": "7.0.0-alpha.7",
62
+ "@storybook/docs-tools": "7.0.0-alpha.7",
63
63
  "@storybook/mdx1-csf": "^0.0.1",
64
- "@storybook/node-logger": "7.0.0-alpha.4",
65
- "@storybook/postinstall": "7.0.0-alpha.4",
66
- "@storybook/preview-web": "7.0.0-alpha.4",
67
- "@storybook/source-loader": "7.0.0-alpha.4",
68
- "@storybook/store": "7.0.0-alpha.4",
69
- "@storybook/theming": "7.0.0-alpha.4",
64
+ "@storybook/node-logger": "7.0.0-alpha.7",
65
+ "@storybook/postinstall": "7.0.0-alpha.7",
66
+ "@storybook/preview-web": "7.0.0-alpha.7",
67
+ "@storybook/source-loader": "7.0.0-alpha.7",
68
+ "@storybook/store": "7.0.0-alpha.7",
69
+ "@storybook/theming": "7.0.0-alpha.7",
70
70
  "babel-loader": "^8.2.5",
71
71
  "core-js": "^3.8.2",
72
72
  "fast-deep-equal": "^3.1.3",
@@ -101,7 +101,7 @@
101
101
  "publishConfig": {
102
102
  "access": "public"
103
103
  },
104
- "gitHead": "006ed54452dd7c37a8cbe91a84f5312182f7ca00",
104
+ "gitHead": "d334cabd251cd0ed8b845a87707dc84f007d4074",
105
105
  "storybook": {
106
106
  "displayName": "Docs",
107
107
  "icon": "https://user-images.githubusercontent.com/263385/101991672-48355c80-3c7c-11eb-82d9-95fa12438f64.png",