import {Children, JSXElementConstructor, ReactNode} from 'react'; import styled from '@emotion/styled'; import {Flex} from 'sentry/components/profiling/flex'; import SideBySide from 'sentry/components/stories/sideBySide'; import {space} from 'sentry/styles/space'; type RenderFn = () => ReactNode | ReactNode[]; type StoryFn = (storyName: string, storyRender: RenderFn) => void; type SetupFn = (story: StoryFn) => void; type Context = { name: string; render: RenderFn; }; export default function storyBook( bookContext: string | JSXElementConstructor, setup: SetupFn ) { const contexts: Context[] = []; const storyFn: StoryFn = (name: string, render: RenderFn) => { contexts.push({name, render}); }; setup(storyFn); return function RenderStory() { return ( {contexts.map(({name, render}, i) => { const children = render(); const isOneChild = Children.count(children) === 1; const key = `${i}_${name}`; return ( {name} {isOneChild ? children : {children}} ); })} ); }; } function BookHeading({bookContext}) { if (typeof bookContext === 'string') { return {bookContext}; } const componentName = bookContext.displayName ?? bookContext.name ?? bookContext.constructor.name; if (!componentName) { return null; } return ( {`<${componentName}/>`} ); } const BookTitle = styled('h3')` margin: 0; `; const Story = styled('section')` & > p { margin: ${space(3)} 0; } `; const StoryTitle = styled('h4')` border-bottom: 1px solid ${p => p.theme.border}; `;