CHANGE core event names to uppercase && OPTIMISE app render

This commit is contained in:
Norbert de Langen 2018-12-30 00:15:55 +01:00
parent 1a271ba5f8
commit 7f5d1e843d
No known key found for this signature in database
GPG Key ID: 976651DA156C2825
16 changed files with 146 additions and 219 deletions

View File

@ -1,3 +1,3 @@
export const ADDON_ID = 'storybook/stories';
export const ADDON_ID = 'storybook/storysource';
export const PANEL_ID = `${ADDON_ID}/panel`;
export const EVENT_ID = `${ADDON_ID}/story-event`;

View File

@ -42,7 +42,7 @@ const Explorer = React.memo(({ stories, componentId, ...rest }) => {
<Placeholder key="empty">There have no stories been loaded yet</Placeholder>
);
});
Explorer.displayName = 'Explorer';
Explorer.propTypes = {
stories: PropTypes.shape({}).isRequired,
componentId: PropTypes.string,

View File

@ -64,10 +64,10 @@ class Preview extends Component {
}
componentDidUpdate(prevProps) {
const { channel, componentId } = this.props;
const { api, componentId } = this.props;
const { componentId: prevComponentId } = prevProps;
if (componentId && componentId !== prevComponentId) {
channel.emit(Events.SET_CURRENT_STORY, { componentId });
api.emit(Events.SET_CURRENT_STORY, { componentId });
}
}
@ -163,10 +163,10 @@ class Preview extends Component {
}
Preview.propTypes = {
id: PropTypes.string.isRequired,
channel: PropTypes.shape({
api: PropTypes.shape({
on: PropTypes.func,
off: PropTypes.func,
emit: PropTypes.func,
removeListener: PropTypes.func,
}).isRequired,
componentId: PropTypes.string,
path: PropTypes.string,

View File

@ -219,6 +219,7 @@ export const Tabs = React.memo(
);
}
);
Tabs.displayName = 'Tabs';
Tabs.propTypes = {
children: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.node, PropTypes.func])),
tools: PropTypes.node,

View File

@ -1,19 +1,19 @@
module.exports = {
CHANNEL_CREATED: 'channelCreated',
GET_CURRENT_STORY: 'getCurrentStory',
SET_CURRENT_STORY: 'setCurrentStory',
GET_STORIES: 'getStories',
SET_STORIES: 'setStories',
SELECT_STORY: 'selectStory',
APPLY_SHORTCUT: 'applyShortcut',
STORY_ADDED: 'storyAdded',
STORY_CHANGED: 'storyChanged',
FORCE_RE_RENDER: 'forceReRender',
REGISTER_SUBSCRIPTION: 'registerSubscription',
STORY_INIT: 'storyInit',
STORY_RENDER: 'storyRender',
STORY_RENDERED: 'storyRendered',
STORY_MISSING: 'storyMissing',
STORY_ERRORED: 'storyErrored',
STORY_THREW_EXCEPTION: 'storyThrewException',
CHANNEL_CREATED: 'CHANNEL_CREATED',
GET_CURRENT_STORY: 'GET_CURRENT_STORY',
SET_CURRENT_STORY: 'SET_CURRENT_STORY',
GET_STORIES: 'GET_STORIES',
SET_STORIES: 'SET_STORIES',
SELECT_STORY: 'SELECT_STORY',
APPLY_SHORTCUT: 'APPLY_SHORTCUT',
STORY_ADDED: 'STORY_ADDED',
STORY_CHANGED: 'STORY_CHANGED',
FORCE_RE_RENDER: 'FORCE_RE_RENDER',
REGISTER_SUBSCRIPTION: 'REGISTER_SUBSCRIPTION',
STORY_INIT: 'STORY_INIT',
STORY_RENDER: 'STORY_RENDER',
STORY_RENDERED: 'STORY_RENDERED',
STORY_MISSING: 'STORY_MISSING',
STORY_ERRORED: 'STORY_ERRORED',
STORY_THREW_EXCEPTION: 'STORY_THREW_EXCEPTION',
};

View File

@ -1,6 +1,7 @@
import React from 'react';
import styled from '@emotion/styled';
import ResizeDetector from 'react-resize-detector';
import memoize from 'memoizerific';
import { Router } from '@storybook/components';
@ -9,7 +10,6 @@ import { Desktop } from './components/layout/desktop';
import Nav from './containers/nav';
import Preview from './containers/preview';
import Panel from './containers/panel';
import { Consumer } from './core/context';
import SettingsPages from './settings';
@ -30,51 +30,43 @@ const Reset = styled.div(({ theme }) => ({
overflow: 'hidden',
}));
const App = () => (
<Consumer>
{({ state }) => {
const props = {
Nav,
Preview,
Panel,
pages: [
{
key: 'settings',
render: () => <SettingsPages />,
// eslint-disable-next-line react/prop-types
route: ({ children }) => (
<Router.Route path="/settings" startsWith>
{children}
</Router.Route>
),
},
],
options: {
...state.layout,
},
viewMode: state.viewMode,
componentId: state.componentId,
path: state.path,
location: state.location,
};
const createProps = memoize(1)(() => ({
Nav,
Preview,
Panel,
pages: [
{
key: 'settings',
render: () => <SettingsPages />,
// eslint-disable-next-line react/prop-types
route: ({ children }) => (
<Router.Route path="/settings" startsWith>
{children}
</Router.Route>
),
},
],
}));
return (
<Reset>
<ResizeDetector handleWidth>
{width => {
if (width === 0) {
return <div />;
}
if (width < 600) {
return <Mobile {...props} />;
}
return <Desktop {...props} />;
}}
</ResizeDetector>
</Reset>
);
}}
</Consumer>
);
const App = React.memo(({ viewMode, layout }) => {
const props = createProps();
return (
<Reset>
<ResizeDetector handleWidth>
{width => {
if (width === 0) {
return <div />;
}
if (width < 600) {
return <Mobile {...props} viewMode={viewMode} />;
}
return <Desktop {...props} viewMode={viewMode} options={layout} />;
}}
</ResizeDetector>
</Reset>
);
});
App.displayName = 'App';
export default App;

View File

@ -5,54 +5,48 @@ import ResizeDetector from 'react-resize-detector';
import * as S from './container';
const Desktop = React.memo(
({ Panel, Nav, Preview, pages, options, viewMode, location, path, componentId }) => (
<S.Root>
<ResizeDetector handleWidth handleHeight>
{(width, height) =>
width && height ? (
<S.Layout options={options} bounds={{ width, height }} viewMode={viewMode}>
{({ navProps, mainProps, panelProps, previewProps }) => (
<Fragment>
<S.Nav {...navProps}>
<Nav debug={navProps} />
</S.Nav>
<S.Main {...mainProps}>
<S.Preview
{...previewProps}
hidden={!(viewMode === 'components' || viewMode === 'info')}
>
<Preview
isFullscreen={previewProps.isFullscreen}
isToolshown={previewProps.isToolshown}
id="iframe"
path={path}
componentId={componentId}
location={location}
viewMode={viewMode}
debug={previewProps}
/>
</S.Preview>
const Desktop = React.memo(({ Panel, Nav, Preview, pages, options, viewMode }) => (
<S.Root>
<ResizeDetector handleWidth handleHeight>
{(width, height) =>
width && height ? (
<S.Layout options={options} bounds={{ width, height }} viewMode={viewMode}>
{({ navProps, mainProps, panelProps, previewProps }) => (
<Fragment>
<S.Nav {...navProps}>
<Nav debug={navProps} />
</S.Nav>
<S.Main {...mainProps}>
<S.Preview
{...previewProps}
hidden={!(viewMode === 'components' || viewMode === 'info')}
>
<Preview
isFullscreen={previewProps.isFullscreen}
isToolshown={previewProps.isToolshown}
id="iframe"
debug={previewProps}
/>
</S.Preview>
<S.Panel {...panelProps} hidden={viewMode !== 'components'}>
<Panel debug={panelProps} />
</S.Panel>
<S.Panel {...panelProps} hidden={viewMode !== 'components'}>
<Panel debug={panelProps} />
</S.Panel>
{pages.map(({ key, route: Route, render: content }) => (
<Route key={key}>{content()}</Route>
))}
</S.Main>
</Fragment>
)}
</S.Layout>
) : (
<div>0 width or height</div>
)
}
</ResizeDetector>
</S.Root>
)
);
{pages.map(({ key, route: Route, render: content }) => (
<Route key={key}>{content()}</Route>
))}
</S.Main>
</Fragment>
)}
</S.Layout>
) : (
<div>0 width or height</div>
)
}
</ResizeDetector>
</S.Root>
));
Desktop.displayName = 'DesktopLayout';
Desktop.propTypes = {

View File

@ -79,6 +79,7 @@ const Panels = React.memo(({ children, active }) => (
))}
</Panels.Container>
));
Panels.displayName = 'Panels';
Panels.propTypes = {
children: PropTypes.node.isRequired,
active: PropTypes.number.isRequired,

View File

@ -84,90 +84,6 @@ exports[`Storyshots UI|Nav/components components 1`] = `
</nav>
`;
exports[`Storyshots UI|Nav/settings with brand 1`] = `
<nav
class="css-12y23u7-Container ea9ueuv0"
>
<div
class="css-1w49w0r-Inner ea9ueuv1"
>
<div
class="css-vx98lc-Main ea9ueuv3"
>
<div
class="css-1l8ehjd-Head ea9ueuv2"
>
<div
class="css-1utbklm-HeadMain ea9ueuv6"
>
<div
class="css-12abwdn-BrandWrapper ezlaqq41"
>
<svg
class="css-1hafpwu-Svg e1jx9faa0"
height="30px"
viewBox="0 0 420 538"
>
<path
d="M 420,0 28,28 52,520 420,538 Z"
fill="#f1618c"
/>
<path
d="M 324.8652,6.79492 320,72 348.4004,50.5996 372,72 V 3.42774 Z"
fill="#fff"
/>
<path
d="m 230,96.80078 c 67.6,0 106.5996,37.19884 104.5996,111.79882 l -77.4004,2 v -0.1992 c 1.6,-40 -15.7984,-44 -25.3984,-44 -9,0 -24.4004,2.8004 -24.4004,24.4004 0,53.4 131.4004,50.4 131.4004,158 0,60.4 -46.8008,88.39844 -106.8008,88.39844 -62,0 -116.4,-21.19884 -110,-113.79884 h 81 c -1,37.4 7.2008,50.79884 27.8008,50.79884 16,0 23.1992,-8.99844 23.1992,-24.39844 0,-54.8 -129.5996,-56.6 -129.5996,-157 0,-57.6 37.5996,-96 105.5996,-96 z"
fill="#fff"
/>
<path
d="M 42,520 18,28 H 0 l 18,492 z"
fill="#b57ee5"
/>
</svg>
<span
class="css-1y8nbux-BrandText ezlaqq42"
>
<strong>
Title
</strong>
</span>
</div>
</div>
<span
class="css-1vfjj5t-Trigger e195q2qw0"
>
<button
class="css-16kkzcq-RoundButton eclugbz0"
id="storybook-explorer-menu"
>
<svg
class="css-1yaqr10-Svg e1vqr9v80"
height="14px"
viewBox="0 0 1024 1024"
width="14px"
>
<path
class="css-1xhbbdd-Path e1gl30fa0"
d="M184 393c66.274 0 120 53.73 120 120s-53.726 120-120 120c-66.286 0-120-53.73-120-120s53.714-120 120-120zM512 393c66.272 0 120 53.73 120 120s-53.728 120-120 120c-66.286 0-120-53.73-120-120s53.714-120 120-120zM840 393c66.272 0 120 53.73 120 120s-53.728 120-120 120c-66.286 0-120-53.73-120-120s53.714-120 120-120z"
/>
</svg>
</button>
</span>
</div>
<p
class="css-hftiue ejh6i270"
>
There have no stories been loaded yet
</p>
</div>
<div
class="css-1yt93tv-Foot ea9ueuv4"
/>
</div>
</nav>
`;
exports[`Storyshots UI|Nav/settings without brand 1`] = `
<nav
class="css-12y23u7-Container ea9ueuv0"

View File

@ -14,10 +14,11 @@ const StyledLink = React.memo(
textDecoration: 'none',
})
);
const LeafLink = React.memo(({ id, href, children, className, ...rest }) => (
StyledLink.displayName = 'StyledLink';
const LeafLink = React.memo(({ href, children, ...rest }) => (
<Router.Location>
{({ viewMode }) => (
<StyledLink id={id} className={className} to={strip(href, viewMode)} {...rest}>
<StyledLink to={strip(href, viewMode)} {...rest}>
{children}
</StyledLink>
)}
@ -27,6 +28,7 @@ const LeafLink = React.memo(({ id, href, children, className, ...rest }) => (
const StoriesPanel = React.memo(props => <Explorer allowClick {...props} Link={LeafLink} />);
StoriesPanel.propTypes = {
stories: PropTypes.shape({}).isRequired,
componentId: PropTypes.string.isRequired,
};
export { StoriesPanel as Explorer };
export { StoriesPanel as StoriesExplorer };

View File

@ -25,6 +25,7 @@ const Menu = React.memo(({ hide, items }) => (
))}
</List>
));
Menu.displayName = 'Menu';
Menu.propTypes = {
items: PropTypes.arrayOf(

View File

@ -13,7 +13,7 @@ import {
} from './notifications';
import { createMenu, MenuToggle } from './menu';
import { Explorer } from './explorer';
import { StoriesExplorer } from './explorer';
const Container = styled.nav(({ theme }) => ({
background: theme.asideFill,
@ -78,7 +78,7 @@ const Brand = withTheme(({ title, url, theme: { brand: UserBrand } }) => (
));
Brand.displayName = 'Brand';
const Nav = React.memo(({ title, url, componentId, notifications = [], stories, menu: items }) => (
const Nav = ({ title, url, componentId, notifications = [], stories, menu: items }) => (
<Container>
<Inner>
<Main>
@ -86,7 +86,7 @@ const Nav = React.memo(({ title, url, componentId, notifications = [], stories,
<Brand title={title} url={url} />
<MenuToggle id="storybook-explorer-menu">{createMenu(items)}</MenuToggle>
</Head>
<Explorer stories={stories} componentId={componentId} />
<StoriesExplorer stories={stories} componentId={componentId} />
</Main>
<Foot>
{notifications.map(({ id }) => (
@ -124,7 +124,7 @@ const Nav = React.memo(({ title, url, componentId, notifications = [], stories,
</Notifications>
) : null}
</Container>
));
);
Nav.propTypes = {
title: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
@ -141,6 +141,9 @@ Nav.propTypes = {
})
).isRequired,
};
Nav.defaultProps = {
componentId: undefined,
};
Nav.displayName = 'Nav';
export default Nav;

View File

@ -82,6 +82,7 @@ const AddonPanel = React.memo(({ panels, actions, selectedPanel, panelPosition }
))}
</Tabs>
));
AddonPanel.displayName = 'AddonPanel';
AddonPanel.propTypes = {
selectedPanel: PropTypes.string,
actions: PropTypes.shape({}).isRequired,

View File

@ -93,7 +93,7 @@ const createMenu = memoize(1)(
]
);
export const mapper = ({ state, api }) => {
export const mapper = (state, api) => {
const {
ui: { name, url },
notifications,
@ -116,5 +116,5 @@ export const mapper = ({ state, api }) => {
};
export default props => (
<Consumer>{({ state, api }) => <Nav {...props} {...mapper({ state, api })} />}</Consumer>
<Consumer>{({ state, api }) => <Nav {...props} {...mapper(state, api)} />}</Consumer>
);

View File

@ -7,17 +7,33 @@ import { Consumer } from '../core/context';
const createPreviewActions = memoize(1)(api => ({
toggleFullscreen: () => api.toggleFullscreen(),
}));
const createProps = (api, layout, location, path, componentId, viewMode) => ({
api,
getElements: api.getElements,
actions: createPreviewActions(api),
options: layout,
path,
componentId,
viewMode,
});
export default React.memo(props => (
const PreviewConnected = React.memo(props => (
<Consumer>
{({ state, api }) => {
const customProps = {
channel: api.getChannel(),
getElements: api.getElements,
actions: createPreviewActions(api),
options: state.layout,
};
return <Preview {...props} {...customProps} />;
}}
{({ state, api }) => (
<Preview
{...props}
{...createProps(
api,
state.layout,
state.location,
state.path,
state.componentId,
state.viewMode
)}
/>
)}
</Consumer>
));
PreviewConnected.displayName = 'PreviewConnected';
export default PreviewConnected;

View File

@ -22,7 +22,7 @@ const Root = ({ provider }) => (
<ManagerProvider key="manager" provider={provider} {...locationData}>
{({ state }) => (
<ThemeProvider key="theme.provider" theme={state.ui.theme}>
<App key="app" />
<App key="app" viewMode={state.viewMode} layout={state.layout} />
</ThemeProvider>
)}
</ManagerProvider>