From 69981986a84af020b826be9ff9e52d2c890073dd Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 10:26:09 +1100 Subject: [PATCH 01/22] Allow overriding WebView and UrlStore --- code/lib/preview-web/src/PreviewWeb.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/lib/preview-web/src/PreviewWeb.tsx b/code/lib/preview-web/src/PreviewWeb.tsx index ed0979a74bd6..6db52af25abd 100644 --- a/code/lib/preview-web/src/PreviewWeb.tsx +++ b/code/lib/preview-web/src/PreviewWeb.tsx @@ -71,11 +71,11 @@ export class PreviewWeb extends Preview; - constructor() { + constructor({ view = new WebView(), urlStore = new UrlStore() }) { super(); - this.view = new WebView(); - this.urlStore = new UrlStore(); + this.view = view; + this.urlStore = urlStore; } setupListeners() { From c4a69ab177931d8617c0078797fbe2e06504e50a Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 10:56:03 +1100 Subject: [PATCH 02/22] Create super classes for Selection/View --- code/lib/preview-web/src/Preview.tsx | 26 ++--- code/lib/preview-web/src/PreviewWeb.tsx | 98 ++++++++++++------- code/lib/preview-web/src/SelectionStore.ts | 12 +++ code/lib/preview-web/src/UrlStore.ts | 4 +- code/lib/preview-web/src/View.ts | 25 +++++ code/lib/preview-web/src/WebView.ts | 25 ++--- code/lib/preview-web/src/render/Render.ts | 6 +- .../src/render/StandaloneDocsRender.ts | 15 ++- .../lib/preview-web/src/render/StoryRender.ts | 17 ++-- .../src/render/TemplateDocsRender.ts | 15 ++- code/lib/types/src/modules/store.ts | 15 +-- 11 files changed, 174 insertions(+), 84 deletions(-) create mode 100644 code/lib/preview-web/src/SelectionStore.ts create mode 100644 code/lib/preview-web/src/View.ts diff --git a/code/lib/preview-web/src/Preview.tsx b/code/lib/preview-web/src/Preview.tsx index 76693eb5a4b8..9158d8d1ecf7 100644 --- a/code/lib/preview-web/src/Preview.tsx +++ b/code/lib/preview-web/src/Preview.tsx @@ -42,7 +42,7 @@ const STORY_INDEX_PATH = './index.json'; export type MaybePromise = Promise | T; -export class Preview { +export class Preview { serverChannel?: Channel; storyStore: StoryStore; @@ -51,9 +51,9 @@ export class Preview { importFn?: Store_ModuleImportFn; - renderToDOM?: Store_RenderToDOM; + renderToDOM?: Store_RenderToDOM; - storyRenders: StoryRender[] = []; + storyRenders: StoryRender[] = []; previewEntryError?: Error; @@ -81,7 +81,9 @@ export class Preview { // getProjectAnnotations has been run, thus this slightly awkward approach getStoryIndex?: () => Store_StoryIndex; importFn: Store_ModuleImportFn; - getProjectAnnotations: () => MaybePromise>; + getProjectAnnotations: () => MaybePromise< + Store_WebProjectAnnotations + >; }) { // We save these two on initialization in case `getProjectAnnotations` errors, // in which case we may need them later when we recover. @@ -106,7 +108,7 @@ export class Preview { } getProjectAnnotationsOrRenderError( - getProjectAnnotations: () => MaybePromise> + getProjectAnnotations: () => MaybePromise> ): Store_PromiseLike> { return SynchronousPromise.resolve() .then(getProjectAnnotations) @@ -132,7 +134,9 @@ export class Preview { } // If initialization gets as far as project annotations, this function runs. - initializeWithProjectAnnotations(projectAnnotations: Store_WebProjectAnnotations) { + initializeWithProjectAnnotations( + projectAnnotations: Store_WebProjectAnnotations + ) { this.storyStore.setProjectAnnotations(projectAnnotations); this.setInitialGlobals(); @@ -305,11 +309,11 @@ export class Preview { // main to be consistent with the previous behaviour. In the future, // we will change it to go ahead and load the story, which will end up being // "instant", although async. - renderStoryToElement(story: Store_Story, element: HTMLElement) { + renderStoryToElement(story: Store_Story, element: TRootElement) { if (!this.renderToDOM) throw new Error(`Cannot call renderStoryToElement before initialization`); - const render = new StoryRender( + const render = new StoryRender( this.channel, this.storyStore, this.renderToDOM, @@ -329,9 +333,9 @@ export class Preview { async teardownRender( render: - | StoryRender - | TemplateDocsRender - | StandaloneDocsRender, + | StoryRender + | TemplateDocsRender + | StandaloneDocsRender, { viewModeChanged }: { viewModeChanged?: boolean } = {} ) { this.storyRenders = this.storyRenders.filter((r) => r !== render); diff --git a/code/lib/preview-web/src/PreviewWeb.tsx b/code/lib/preview-web/src/PreviewWeb.tsx index 6db52af25abd..3b91cca9da56 100644 --- a/code/lib/preview-web/src/PreviewWeb.tsx +++ b/code/lib/preview-web/src/PreviewWeb.tsx @@ -41,6 +41,8 @@ import { PREPARE_ABORTED } from './render/Render'; import { StoryRender } from './render/StoryRender'; import { TemplateDocsRender } from './render/TemplateDocsRender'; import { StandaloneDocsRender } from './render/StandaloneDocsRender'; +import { SelectionStore } from './SelectionStore'; +import { View } from './View'; const { window: globalWindow } = global; @@ -49,33 +51,45 @@ function focusInInput(event: Event) { return /input|textarea/i.test(target.tagName) || target.getAttribute('contenteditable') !== null; } -type PossibleRender = - | StoryRender - | TemplateDocsRender - | StandaloneDocsRender; +type PossibleRender = + | StoryRender + | TemplateDocsRender + | StandaloneDocsRender; -function isStoryRender( - r: PossibleRender -): r is StoryRender { +function isStoryRender( + r: PossibleRender +): r is StoryRender { return r.type === 'story'; } -export class PreviewWeb extends Preview { - urlStore: UrlStore; +export class PreviewWeb< + TFramework extends AnyFramework, + TRootElement = HTMLElement +> extends Preview { + selectionStore: SelectionStore; - view: WebView; + view: View; previewEntryError?: Error; currentSelection?: Store_Selection; - currentRender?: PossibleRender; + currentRender?: PossibleRender; - constructor({ view = new WebView(), urlStore = new UrlStore() }) { + constructor({ + // I'm not quite sure how to express this -- if you don't pass a view, you need to ensure + // this is a PreviewWeb<..., HTMLElement>. If you pass one, it can be parameterized however you want, + // as long as it is consistent. + view = new WebView() as any, + selectionStore = new UrlStore(), + }: { + view: View; + selectionStore: SelectionStore; + }) { super(); this.view = view; - this.urlStore = urlStore; + this.selectionStore = selectionStore; } setupListeners() { @@ -88,7 +102,9 @@ export class PreviewWeb extends Preview) { + initializeWithProjectAnnotations( + projectAnnotations: Store_WebProjectAnnotations + ) { return super .initializeWithProjectAnnotations(projectAnnotations) .then(() => this.setInitialGlobals()); @@ -98,7 +114,7 @@ export class PreviewWeb extends Preview extends Preview extends Preview extends Preview extends Preview extends Preview extends Preview extends Preview; + let render: PossibleRender; if (entry.type === 'story') { - render = new StoryRender( + render = new StoryRender( this.channel, this.storyStore, - (...args) => { + (...args: Parameters) => { // At the start of renderToDOM we make the story visible (see note in WebView) this.view.showStoryDuringRender(); return renderToDOM(...args); @@ -304,9 +320,17 @@ export class PreviewWeb extends Preview(this.channel, this.storyStore, entry); + render = new StandaloneDocsRender( + this.channel, + this.storyStore, + entry + ); } else { - render = new TemplateDocsRender(this.channel, this.storyStore, entry); + render = new TemplateDocsRender( + this.channel, + this.storyStore, + entry + ); } // We need to store this right away, so if the story changes during @@ -385,20 +409,24 @@ export class PreviewWeb extends Preview); - (this.currentRender as StoryRender).renderToElement( + this.storyRenders.push(render as StoryRender); + (this.currentRender as StoryRender).renderToElement( this.view.prepareForStory(render.story) ); } else { this.currentRender.renderToElement( this.view.prepareForDocs(), - this.renderStoryToElement.bind(this) + // This argument is used for docs, which is currently only compatible with HTMLElements + this.renderStoryToElement.bind(this) as PreviewWeb< + TFramework, + HTMLElement + >['renderStoryToElement'] ); } } async teardownRender( - render: PossibleRender, + render: PossibleRender, { viewModeChanged = false }: { viewModeChanged?: boolean } = {} ) { this.storyRenders = this.storyRenders.filter((r) => r !== render); diff --git a/code/lib/preview-web/src/SelectionStore.ts b/code/lib/preview-web/src/SelectionStore.ts new file mode 100644 index 000000000000..a55cbad58138 --- /dev/null +++ b/code/lib/preview-web/src/SelectionStore.ts @@ -0,0 +1,12 @@ +/* eslint-disable camelcase */ +import type { Store_SelectionSpecifier, Store_Selection } from '@storybook/types'; + +export abstract class SelectionStore { + public selectionSpecifier: Store_SelectionSpecifier | null; + + public selection?: Store_Selection; + + abstract setSelection(selection: Store_Selection): void; + + abstract setQueryParams(queryParams: qs.ParsedQs): void; +} diff --git a/code/lib/preview-web/src/UrlStore.ts b/code/lib/preview-web/src/UrlStore.ts index 41eac2ae642d..4d505e702d93 100644 --- a/code/lib/preview-web/src/UrlStore.ts +++ b/code/lib/preview-web/src/UrlStore.ts @@ -4,6 +4,7 @@ import qs from 'qs'; import type { ViewMode, Store_SelectionSpecifier, Store_Selection } from '@storybook/types'; import { parseArgsParam } from './parseArgsParam'; +import { SelectionStore } from './SelectionStore'; const { history, document } = global; @@ -84,12 +85,13 @@ export const getSelectionSpecifierFromPath: () => Store_SelectionSpecifier | nul return null; }; -export class UrlStore { +export class UrlStore extends SelectionStore { selectionSpecifier: Store_SelectionSpecifier | null; selection?: Store_Selection; constructor() { + super(); this.selectionSpecifier = getSelectionSpecifierFromPath(); } diff --git a/code/lib/preview-web/src/View.ts b/code/lib/preview-web/src/View.ts new file mode 100644 index 000000000000..3c90a6dfdf94 --- /dev/null +++ b/code/lib/preview-web/src/View.ts @@ -0,0 +1,25 @@ +/* eslint-disable camelcase */ +import type { Store_Story } from '@storybook/types'; + +export abstract class View { + // Get ready to render a story, returning the element to render to + abstract prepareForStory(story: Store_Story): TRootElement; + + abstract prepareForDocs(): TRootElement; + + abstract showErrorDisplay({ message = '', stack = '' }): void; + + abstract showNoPreview(): void; + + abstract showPreparingStory({ immediate = false }): void; + + abstract showPreparingDocs(): void; + + abstract showMain(): void; + + abstract showDocs(): void; + + abstract showStory(): void; + + abstract showStoryDuringRender(): void; +} diff --git a/code/lib/preview-web/src/WebView.ts b/code/lib/preview-web/src/WebView.ts index 66d28b046d22..a48023881b06 100644 --- a/code/lib/preview-web/src/WebView.ts +++ b/code/lib/preview-web/src/WebView.ts @@ -6,18 +6,12 @@ import { dedent } from 'ts-dedent'; import qs from 'qs'; import type { Store_Story } from '@storybook/types'; +import { View } from './View'; const { document } = global; const PREPARING_DELAY = 100; -const layoutClassMap = { - centered: 'sb-main-centered', - fullscreen: 'sb-main-fullscreen', - padded: 'sb-main-padded', -} as const; -type Layout = keyof typeof layoutClassMap | 'none'; - enum Mode { 'MAIN' = 'MAIN', 'NOPREVIEW' = 'NOPREVIEW', @@ -33,18 +27,27 @@ const classes: Record = { ERROR: 'sb-show-errordisplay', }; +const layoutClassMap = { + centered: 'sb-main-centered', + fullscreen: 'sb-main-fullscreen', + padded: 'sb-main-padded', +} as const; +type Layout = keyof typeof layoutClassMap | 'none'; + const ansiConverter = new AnsiToHtml({ escapeXML: true, }); -export class WebView { - currentLayoutClass?: typeof layoutClassMap[keyof typeof layoutClassMap] | null; +export class WebView extends View { + private currentLayoutClass?: typeof layoutClassMap[keyof typeof layoutClassMap] | null; - testing = false; + private testing = false; - preparingTimeout?: ReturnType; + private preparingTimeout?: ReturnType; constructor() { + super(); + // Special code for testing situations const { __SPECIAL_TEST_PARAMETER__ } = qs.parse(document.location.search, { ignoreQueryPrefix: true, diff --git a/code/lib/preview-web/src/render/Render.ts b/code/lib/preview-web/src/render/Render.ts index 8e1b187c37b2..a96d097a7611 100644 --- a/code/lib/preview-web/src/render/Render.ts +++ b/code/lib/preview-web/src/render/Render.ts @@ -9,15 +9,15 @@ export type RenderType = 'story' | 'docs'; * - Tracking the state of the rendering as it moves between preparing, rendering and tearing down. * - Tracking what is rendered to know if a change requires re-rendering or teardown + recreation. */ -export interface Render { +export interface Render { type: RenderType; id: StoryId; isPreparing: () => boolean; - isEqual: (other: Render) => boolean; + isEqual: (other: Render) => boolean; disableKeyListeners: boolean; teardown?: (options: { viewModeChanged: boolean }) => Promise; torndown: boolean; - renderToElement: (canvasElement: HTMLElement, renderStoryToElement?: any) => Promise; + renderToElement: (canvasElement: TRootElement, renderStoryToElement?: any) => Promise; } export const PREPARE_ABORTED = new Error('prepareAborted'); diff --git a/code/lib/preview-web/src/render/StandaloneDocsRender.ts b/code/lib/preview-web/src/render/StandaloneDocsRender.ts index 56a32925a06b..f77b43822b15 100644 --- a/code/lib/preview-web/src/render/StandaloneDocsRender.ts +++ b/code/lib/preview-web/src/render/StandaloneDocsRender.ts @@ -24,7 +24,9 @@ import { DocsContext } from '../docs-context/DocsContext'; * - *.mdx file that may or may not reference a specific CSF file with `` */ -export class StandaloneDocsRender implements Render { +export class StandaloneDocsRender + implements Render +{ public readonly type: RenderType = 'docs'; public readonly id: StoryId; @@ -66,16 +68,16 @@ export class StandaloneDocsRender implements Re this.preparing = false; } - isEqual(other: Render): boolean { + isEqual(other: Render): boolean { return !!( this.id === other.id && this.exports && - this.exports === (other as StandaloneDocsRender).exports + this.exports === (other as StandaloneDocsRender).exports ); } async renderToElement( - canvasElement: HTMLElement, + canvasElement: TRootElement, renderStoryToElement: DocsContextProps['renderStoryToElement'] ) { if (!this.exports || !this.csfFiles || !this.store.projectAnnotations) @@ -100,7 +102,10 @@ export class StandaloneDocsRender implements Re const renderer = await docs.renderer(); const { render } = renderer as { render: DocsRenderFunction }; const renderDocs = async () => { - await new Promise((r) => render(docsContext, docsParameter, canvasElement, r)); + await new Promise((r) => + // NOTE: it isn't currently possible to use a docs renderer outside of "web" mode. + render(docsContext, docsParameter, canvasElement as HTMLElement, r) + ); this.channel.emit(DOCS_RENDERED, this.id); }; diff --git a/code/lib/preview-web/src/render/StoryRender.ts b/code/lib/preview-web/src/render/StoryRender.ts index 646917ea5ccf..eea0f9f6f53d 100644 --- a/code/lib/preview-web/src/render/StoryRender.ts +++ b/code/lib/preview-web/src/render/StoryRender.ts @@ -47,7 +47,9 @@ export type RenderContextCallbacks = Pick< 'showMain' | 'showError' | 'showException' >; -export class StoryRender implements Render { +export class StoryRender + implements Render +{ public type: RenderType = 'story'; public story?: Store_Story; @@ -56,7 +58,7 @@ export class StoryRender implements Render implements Render, - private renderToScreen: Store_RenderToDOM, + private renderToScreen: Store_RenderToDOM, private callbacks: RenderContextCallbacks, public id: StoryId, public viewMode: ViewMode, @@ -110,11 +112,11 @@ export class StoryRender implements Render): boolean { + isEqual(other: Render): boolean { return !!( this.id === other.id && this.story && - this.story === (other as StoryRender).story + this.story === (other as StoryRender).story ); } @@ -126,7 +128,7 @@ export class StoryRender implements Render implements Render = { componentId, diff --git a/code/lib/preview-web/src/render/TemplateDocsRender.ts b/code/lib/preview-web/src/render/TemplateDocsRender.ts index e095dd4e8670..e92d1977ecfe 100644 --- a/code/lib/preview-web/src/render/TemplateDocsRender.ts +++ b/code/lib/preview-web/src/render/TemplateDocsRender.ts @@ -27,7 +27,9 @@ import { DocsContext } from '../docs-context/DocsContext'; * - *.stories.mdx files, where the MDX compiler produces a CSF file with a `.parameter.docs.page` * parameter containing the compiled content of the MDX file. */ -export class TemplateDocsRender implements Render { +export class TemplateDocsRender + implements Render +{ public readonly type: RenderType = 'docs'; public readonly id: StoryId; @@ -83,16 +85,16 @@ export class TemplateDocsRender implements Rend this.preparing = false; } - isEqual(other: Render): boolean { + isEqual(other: Render): boolean { return !!( this.id === other.id && this.story && - this.story === (other as TemplateDocsRender).story + this.story === (other as TemplateDocsRender).story ); } async renderToElement( - canvasElement: HTMLElement, + canvasElement: TRootElement, renderStoryToElement: DocsContextProps['renderStoryToElement'] ) { if (!this.story || !this.csfFiles) throw new Error('Cannot render docs before preparing'); @@ -115,7 +117,10 @@ export class TemplateDocsRender implements Rend const renderer = await docsParameter.renderer(); const { render } = renderer as { render: DocsRenderFunction }; const renderDocs = async () => { - await new Promise((r) => render(docsContext, docsParameter, canvasElement, r)); + await new Promise((r) => + // NOTE: it isn't currently possible to use a docs renderer outside of "web" mode. + render(docsContext, docsParameter, canvasElement as HTMLElement, r) + ); this.channel.emit(DOCS_RENDERED, this.id); }; diff --git a/code/lib/types/src/modules/store.ts b/code/lib/types/src/modules/store.ts index 3bfd62a7eb65..1723f8d5a19b 100644 --- a/code/lib/types/src/modules/store.ts +++ b/code/lib/types/src/modules/store.ts @@ -35,15 +35,18 @@ export type Store_ModuleImportFn = (path: Store_Path) => Store_PromiseLike = Promise | T; export type Store_TeardownRenderToDOM = () => Store_MaybePromise; -export type Store_RenderToDOM = ( +// We should consider renaming this to `RenderToRootElement` or similar +export type Store_RenderToDOM = ( context: Store_RenderContext, - element: Element + element: TRootElement ) => Store_MaybePromise; -export type Store_WebProjectAnnotations = - ProjectAnnotations & { - renderToDOM?: Store_RenderToDOM; - }; +export type Store_WebProjectAnnotations< + TFramework extends AnyFramework, + TRootElement = HTMLElement +> = ProjectAnnotations & { + renderToDOM?: Store_RenderToDOM; +}; export type Store_NormalizedProjectAnnotations = ProjectAnnotations & { From 0f04209d868185a28f29f11ba021084f73a562ba Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 12:23:59 +1100 Subject: [PATCH 03/22] Default `PreviewWeb` --- code/lib/preview-web/src/PreviewWeb.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/lib/preview-web/src/PreviewWeb.tsx b/code/lib/preview-web/src/PreviewWeb.tsx index 3b91cca9da56..0ce6cf763517 100644 --- a/code/lib/preview-web/src/PreviewWeb.tsx +++ b/code/lib/preview-web/src/PreviewWeb.tsx @@ -83,9 +83,9 @@ export class PreviewWeb< view = new WebView() as any, selectionStore = new UrlStore(), }: { - view: View; - selectionStore: SelectionStore; - }) { + view?: View; + selectionStore?: SelectionStore; + } = {}) { super(); this.view = view; From 5ffdac21a596dfcf516b6a116003febcbe5bfb8f Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 12:28:03 +1100 Subject: [PATCH 04/22] Fix typing problems --- code/lib/preview-web/src/PreviewWeb.tsx | 5 +---- code/lib/preview-web/src/SelectionStore.ts | 2 +- code/lib/preview-web/src/View.ts | 4 ++-- code/lib/preview-web/src/render/StandaloneDocsRender.ts | 2 +- code/lib/preview-web/src/render/TemplateDocsRender.ts | 2 +- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/code/lib/preview-web/src/PreviewWeb.tsx b/code/lib/preview-web/src/PreviewWeb.tsx index 0ce6cf763517..9bb309690ea2 100644 --- a/code/lib/preview-web/src/PreviewWeb.tsx +++ b/code/lib/preview-web/src/PreviewWeb.tsx @@ -417,10 +417,7 @@ export class PreviewWeb< this.currentRender.renderToElement( this.view.prepareForDocs(), // This argument is used for docs, which is currently only compatible with HTMLElements - this.renderStoryToElement.bind(this) as PreviewWeb< - TFramework, - HTMLElement - >['renderStoryToElement'] + this.renderStoryToElement.bind(this) as any ); } } diff --git a/code/lib/preview-web/src/SelectionStore.ts b/code/lib/preview-web/src/SelectionStore.ts index a55cbad58138..f9b7b8d1693f 100644 --- a/code/lib/preview-web/src/SelectionStore.ts +++ b/code/lib/preview-web/src/SelectionStore.ts @@ -2,7 +2,7 @@ import type { Store_SelectionSpecifier, Store_Selection } from '@storybook/types'; export abstract class SelectionStore { - public selectionSpecifier: Store_SelectionSpecifier | null; + public selectionSpecifier: Store_SelectionSpecifier | null = null; public selection?: Store_Selection; diff --git a/code/lib/preview-web/src/View.ts b/code/lib/preview-web/src/View.ts index 3c90a6dfdf94..ac1003c94f6c 100644 --- a/code/lib/preview-web/src/View.ts +++ b/code/lib/preview-web/src/View.ts @@ -7,11 +7,11 @@ export abstract class View { abstract prepareForDocs(): TRootElement; - abstract showErrorDisplay({ message = '', stack = '' }): void; + abstract showErrorDisplay(err: { message: string; stack: string }): void; abstract showNoPreview(): void; - abstract showPreparingStory({ immediate = false }): void; + abstract showPreparingStory(options: { immediate: boolean }): void; abstract showPreparingDocs(): void; diff --git a/code/lib/preview-web/src/render/StandaloneDocsRender.ts b/code/lib/preview-web/src/render/StandaloneDocsRender.ts index f77b43822b15..06b204b7e490 100644 --- a/code/lib/preview-web/src/render/StandaloneDocsRender.ts +++ b/code/lib/preview-web/src/render/StandaloneDocsRender.ts @@ -104,7 +104,7 @@ export class StandaloneDocsRender { await new Promise((r) => // NOTE: it isn't currently possible to use a docs renderer outside of "web" mode. - render(docsContext, docsParameter, canvasElement as HTMLElement, r) + render(docsContext, docsParameter, canvasElement as any, r) ); this.channel.emit(DOCS_RENDERED, this.id); }; diff --git a/code/lib/preview-web/src/render/TemplateDocsRender.ts b/code/lib/preview-web/src/render/TemplateDocsRender.ts index e92d1977ecfe..f540cba07f88 100644 --- a/code/lib/preview-web/src/render/TemplateDocsRender.ts +++ b/code/lib/preview-web/src/render/TemplateDocsRender.ts @@ -119,7 +119,7 @@ export class TemplateDocsRender { await new Promise((r) => // NOTE: it isn't currently possible to use a docs renderer outside of "web" mode. - render(docsContext, docsParameter, canvasElement as HTMLElement, r) + render(docsContext, docsParameter, canvasElement as any, r) ); this.channel.emit(DOCS_RENDERED, this.id); }; From f286554cbd7391d9a63ad40a7b0246d018c638c1 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 12:31:08 +1100 Subject: [PATCH 05/22] One more fix --- code/lib/preview-web/src/View.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/preview-web/src/View.ts b/code/lib/preview-web/src/View.ts index ac1003c94f6c..af3f924885e4 100644 --- a/code/lib/preview-web/src/View.ts +++ b/code/lib/preview-web/src/View.ts @@ -7,7 +7,7 @@ export abstract class View { abstract prepareForDocs(): TRootElement; - abstract showErrorDisplay(err: { message: string; stack: string }): void; + abstract showErrorDisplay(err: { message?: string; stack?: string }): void; abstract showNoPreview(): void; From 3b962082a6f1218457803c361a1624f755e50fde Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 26 Oct 2022 13:16:12 +1100 Subject: [PATCH 06/22] Fix test --- code/lib/preview-web/src/PreviewWeb.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/preview-web/src/PreviewWeb.test.ts b/code/lib/preview-web/src/PreviewWeb.test.ts index aca47cbc3b21..baebcf9bd6c6 100644 --- a/code/lib/preview-web/src/PreviewWeb.test.ts +++ b/code/lib/preview-web/src/PreviewWeb.test.ts @@ -251,7 +251,7 @@ describe('PreviewWeb', () => { const preview = await createAndRenderPreview(); - expect(preview.urlStore.selection).toEqual({ + expect(preview.selectionStore.selection).toEqual({ storyId: 'component-one--a', viewMode: 'story', }); From 2c92e6e02b6f14fcddea26debba4e68f2a2ab2d6 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Mon, 31 Oct 2022 12:52:10 +1100 Subject: [PATCH 07/22] Rename `renderToDOM` -> `renderToRoot` --- MIGRATION.md | 5 + code/frameworks/angular/src/client/config.ts | 2 +- .../angular/src/client/public-api.ts | 4 +- code/frameworks/angular/src/client/render.ts | 2 +- .../ember/src/client/preview/config.ts | 2 +- .../ember/src/client/preview/index.ts | 4 +- .../ember/src/client/preview/render.ts | 2 +- .../builder-vite/src/codegen-iframe-script.ts | 3 +- .../templates/virtualModuleEntry.template.js | 3 +- code/lib/core-client/README.md | 4 +- .../core-client/src/PreviewWeb.mockdata.ts | 6 +- code/lib/core-client/src/start.test.ts | 88 +++---- code/lib/core-client/src/start.ts | 4 +- code/lib/preview-web/README.md | 2 +- code/lib/preview-web/src/Preview.tsx | 42 +-- .../src/PreviewWeb.integration.test.ts | 8 +- .../preview-web/src/PreviewWeb.mockdata.ts | 6 +- code/lib/preview-web/src/PreviewWeb.test.ts | 240 +++++++++--------- code/lib/preview-web/src/PreviewWeb.tsx | 54 ++-- code/lib/preview-web/src/View.ts | 7 +- code/lib/preview-web/src/render/Render.ts | 6 +- .../src/render/StandaloneDocsRender.ts | 10 +- .../lib/preview-web/src/render/StoryRender.ts | 22 +- .../src/render/TemplateDocsRender.ts | 10 +- code/lib/store/src/csf/composeConfigs.test.ts | 6 +- code/lib/store/src/csf/composeConfigs.ts | 3 +- code/lib/types/src/modules/store.ts | 15 +- code/renderers/html/src/config.ts | 2 +- code/renderers/html/src/public-api.ts | 4 +- code/renderers/html/src/render.ts | 2 +- code/renderers/preact/src/config.ts | 2 +- code/renderers/preact/src/public-api.ts | 4 +- code/renderers/preact/src/render.tsx | 2 +- code/renderers/react/src/config.ts | 2 +- code/renderers/react/src/public-api.tsx | 4 +- code/renderers/react/src/render.tsx | 2 +- code/renderers/server/src/config.ts | 2 +- code/renderers/server/src/public-api.ts | 4 +- code/renderers/server/src/render.ts | 2 +- code/renderers/svelte/src/config.ts | 2 +- code/renderers/svelte/src/public-api.ts | 4 +- code/renderers/svelte/src/render.ts | 2 +- code/renderers/vue/src/config.ts | 2 +- code/renderers/vue/src/public-api.ts | 4 +- code/renderers/vue/src/render.ts | 2 +- code/renderers/vue3/src/config.ts | 2 +- code/renderers/vue3/src/public-api.ts | 4 +- code/renderers/vue3/src/render.ts | 2 +- code/renderers/web-components/src/config.ts | 2 +- .../web-components/src/public-api.ts | 4 +- code/renderers/web-components/src/render.ts | 2 +- ...orybook-builder-api-preview-exports.ts.mdx | 4 +- 52 files changed, 323 insertions(+), 305 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 75baa360fcd5..98a2575939e1 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -41,6 +41,7 @@ - [7.0 Deprecations](#70-deprecations) - [`Story` type deprecated](#story-type-deprecated) - [`ComponentStory`, `ComponentStoryObj`, `ComponentStoryFn` and `ComponentMeta` types are deprecated](#componentstory-componentstoryobj-componentstoryfn-and-componentmeta-types-are-deprecated) + - [Renamed `renderToDOM` to `renderToRoot`](#renamed-rendertodom-to-rendertoroot) - [From version 6.4.x to 6.5.0](#from-version-64x-to-650) - [Vue 3 upgrade](#vue-3-upgrade) - [React18 new root API](#react18-new-root-api) @@ -790,6 +791,10 @@ export const CSF2Story: StoryFn = (args) =>