From bd1e940f5f9403004676040ae9d3f85bb20ee9ee Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 19 Mar 2024 12:14:24 +0100 Subject: [PATCH] Merge pull request #26566 from storybookjs/yann/fix-docs-jsx-decorator Addon Docs: Fix [Object object] displayName in some JSX components (cherry picked from commit 79abc6ce91602baf842e1744555cdfd1500dfdac) --- .../react/src/docs/jsxDecorator.test.tsx | 34 ++++++++++++++---- .../renderers/react/src/docs/jsxDecorator.tsx | 35 +++++++++++++------ 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/code/renderers/react/src/docs/jsxDecorator.test.tsx b/code/renderers/react/src/docs/jsxDecorator.test.tsx index 6ed0f0eda179..b8868265333e 100644 --- a/code/renderers/react/src/docs/jsxDecorator.test.tsx +++ b/code/renderers/react/src/docs/jsxDecorator.test.tsx @@ -130,11 +130,22 @@ describe('renderJsx', () => { } ); - expect(renderJsx(createElement(MyExoticComponentRef, {}, 'I am forwardRef!'), {})) + expect(renderJsx(I am forwardRef!)) .toMatchInlineSnapshot(` - + I am forwardRef! - + + `); + + // if docgenInfo is present, it should use the displayName from there + (MyExoticComponentRef as any).__docgenInfo = { + displayName: 'ExoticComponent', + }; + expect(renderJsx(I am forwardRef!)) + .toMatchInlineSnapshot(` + + I am forwardRef! + `); }); @@ -143,11 +154,20 @@ describe('renderJsx', () => { return
{props.children}
; }); - expect(renderJsx(createElement(MyMemoComponentRef, {}, 'I am memo!'), {})) - .toMatchInlineSnapshot(` - + expect(renderJsx(I am memo!)).toMatchInlineSnapshot(` + + I am memo! + + `); + + // if docgenInfo is present, it should use the displayName from there + (MyMemoComponentRef as any).__docgenInfo = { + displayName: 'MyMemoComponentRef', + }; + expect(renderJsx(I am memo!)).toMatchInlineSnapshot(` + I am memo! - + `); }); diff --git a/code/renderers/react/src/docs/jsxDecorator.tsx b/code/renderers/react/src/docs/jsxDecorator.tsx index 5b1391246c9d..e6b1934c2e6e 100644 --- a/code/renderers/react/src/docs/jsxDecorator.tsx +++ b/code/renderers/react/src/docs/jsxDecorator.tsx @@ -29,7 +29,8 @@ const toPascalCase = (str: string) => str.charAt(0).toUpperCase() + str.slice(1) * @returns {string | null} A displayName for the Symbol in case elementType is a Symbol; otherwise, null. */ export const getReactSymbolName = (elementType: any): string => { - const symbolDescription: string = elementType.toString().replace(/^Symbol\((.*)\)$/, '$1'); + const elementName = elementType.$$typeof || elementType; + const symbolDescription: string = elementName.toString().replace(/^Symbol\((.*)\)$/, '$1'); const reactComponentName = symbolDescription .split('.') @@ -124,16 +125,28 @@ export const renderJsx = (code: React.ReactElement, options?: JSXOptions) => { } else { displayNameDefaults = { // To get exotic component names resolving properly - displayName: (el: any): string => - el.type.displayName || typeof el.type === 'symbol' - ? getReactSymbolName(el.type) - : null || - getDocgenSection(el.type, 'displayName') || - (el.type.name !== '_default' ? el.type.name : null) || - (typeof el.type === 'function' ? 'No Display Name' : null) || - (isForwardRef(el.type) ? el.type.render.name : null) || - (isMemo(el.type) ? el.type.type.name : null) || - el.type, + displayName: (el: any): string => { + if (el.type.displayName) { + return el.type.displayName; + } else if (getDocgenSection(el.type, 'displayName')) { + return getDocgenSection(el.type, 'displayName'); + } else if ( + typeof el.type === 'symbol' || + (el.type.$$typeof && typeof el.type.$$typeof === 'symbol') + ) { + return getReactSymbolName(el.type); + } else if (el.type.name && el.type.name !== '_default') { + return el.type.name; + } else if (typeof el.type === 'function') { + return 'No Display Name'; + } else if (isForwardRef(el.type)) { + return el.type.render.name; + } else if (isMemo(el.type)) { + return el.type.type.name; + } else { + return el.type; + } + }, }; }