diff --git a/addons/backgrounds/src/Tool.js b/addons/backgrounds/src/Tool.js
index ca6268b34b70..dce93da22c6d 100644
--- a/addons/backgrounds/src/Tool.js
+++ b/addons/backgrounds/src/Tool.js
@@ -1,26 +1,25 @@
-import { document } from 'global';
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import memoize from 'memoizerific';
-import { logger } from '@storybook/client-logger';
import { SET_STORIES } from '@storybook/core-events';
+import { Global } from '@storybook/theming';
import { Popout, Item, Icons, Icon, IconButton, Title, Detail, List } from '@storybook/components';
import * as S from './components';
import { PARAM_KEY } from './constants';
-const getIframe = () => document.getElementById('storybook-preview-background');
+const iframeId = 'storybook-preview-background';
-const getState = (props, state) => {
+const getState = memoize(10)((props, state) => {
const data = props.api.getCurrentStoryData();
const list = data && data.parameters && data.parameters[PARAM_KEY];
return list && list.length
? list.reduce(
(acc, { name, value, default: isSelected }) => {
- acc.backgrounds.push({ name, value });
+ acc.items.push({ name, value });
if (isSelected && state.selected !== 'transparent') {
if (!list.find(i => i.value === state.selected)) {
@@ -30,23 +29,14 @@ const getState = (props, state) => {
return acc;
},
{
- backgrounds: [],
+ items: [],
selected: state.selected,
}
)
: {
- backgrounds: [],
+ items: [],
selected: 'transparent',
};
-};
-
-const apply = memoize(1)((value, iframe) => {
- if (iframe) {
- // eslint-disable-next-line no-param-reassign
- iframe.style.background = value;
- } else {
- logger.error('Cannot find Storybook iframe');
- }
});
export default class BackgroundTool extends Component {
@@ -54,69 +44,81 @@ export default class BackgroundTool extends Component {
super(props);
this.state = {
- backgrounds: [],
+ items: [],
selected: 'transparent',
};
+
+ this.listener = () => {
+ this.setState({ selected: null });
+ };
}
componentDidMount() {
const { api } = this.props;
+ api.on(SET_STORIES, this.listener);
+ }
- api.on(SET_STORIES, () => {
- const { state, props } = this;
- this.setState(getState(props, state));
- });
+ componentWillUnmount() {
+ const { api } = this.props;
+ api.off(SET_STORIES, this.listener);
}
change = selected => {
- this.setState({ selected }, this.apply);
+ this.setState({ selected });
};
render() {
- const { backgrounds, selected } = getState(this.props, this.state);
- const iframe = getIframe();
-
- apply(selected, iframe);
-
- return backgrounds.length ? (
-
-
-
-
- {({ hide }) => (
-
- {selected !== 'transparent' ? (
-
+ const { items, selected } = getState(this.props, this.state);
+
+ return items.length ? (
+
+
+
+
+
+
+
+ {({ hide }) => (
+
+ {selected !== 'transparent' ? (
+
+ - {
+ hide();
+ this.change('transparent');
+ }}
+ >
+
+ Clear
+ transparent
+
+
+ ) : null}
+
+ {items.map(({ name, value }) => (
- {
hide();
- this.change('transparent');
+ this.change(value);
}}
>
-
- Clear
- transparent
+ } />
+ {name}
+ {value}
-
- ) : null}
-
- {backgrounds.map(({ name, value }) => (
- - {
- hide();
- this.change(value);
- }}
- >
- } />
- {name}
- {value}
-
- ))}
-
- )}
-
+ ))}
+
+ )}
+
+
) : null;
}
}
diff --git a/addons/viewport/src/Tool.js b/addons/viewport/src/Tool.js
index c82cb6ecc280..d714ba46f20b 100644
--- a/addons/viewport/src/Tool.js
+++ b/addons/viewport/src/Tool.js
@@ -1,121 +1,120 @@
-import { document } from 'global';
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import memoize from 'memoizerific';
-import { Global, css } from '@storybook/theming';
+import { Global } from '@storybook/theming';
import { Popout, Item, Icons, Icon, IconButton, Title, List } from '@storybook/components';
-import { STORY_CHANGED } from '@storybook/core-events';
-import { logger } from '@storybook/client-logger';
+import { SET_STORIES } from '@storybook/core-events';
import { PARAM_KEY } from './constants';
-const toList = memoize(50)(viewports => Object.entries(viewports));
-const getIframe = memoize(1)(() => document.getElementById('storybook-preview-iframe'));
-const iframeClass = 'storybook-preview-iframe-viewport';
+const toList = memoize(50)(items =>
+ items ? Object.entries(items).map(([id, value]) => ({ ...value, id })) : []
+);
+const iframeId = 'storybook-preview-background';
+
+const getState = memoize(10)((props, state) => {
+ const data = props.api.getCurrentStoryData();
+ const list = toList(data && data.parameters && data.parameters[PARAM_KEY]);
+
+ return list && list.length
+ ? list.reduce(
+ (acc, { name, styles: value, id }) => {
+ acc.items.push({ name, value, id });
+
+ if (state.selected !== 'responsive') {
+ if (!list.find(i => i.id === state.selected)) {
+ acc.selected = id;
+ }
+ }
+ return acc;
+ },
+ {
+ isRotated: state.isRotated,
+ items: [],
+ selected: state.selected,
+ }
+ )
+ : {
+ isRotated: false,
+ items: [],
+ selected: 'responsive',
+ };
+});
+
+const flip = ({ width, height }) => ({ height: width, widht: height });
export default class ViewportTool extends Component {
constructor(props) {
super(props);
this.state = {
- viewports: {},
- selected: undefined,
isRotated: false,
+ items: [],
+ selected: 'responsive',
+ };
+
+ this.listener = () => {
+ this.setState({});
};
}
componentDidMount() {
const { api } = this.props;
- api.on(STORY_CHANGED, this.onStoryChange);
+ api.on(SET_STORIES, this.listener);
}
componentWillUnmount() {
const { api } = this.props;
- api.off(STORY_CHANGED, this.onStoryChange);
+ api.off(SET_STORIES, this.listener);
}
- onStoryChange = id => {
- const { api } = this.props;
- const viewports = api.getParameters(id, PARAM_KEY);
-
- if (viewports) {
- this.setState({ viewports });
- }
- };
-
- change = key => {
- this.setState({ selected: key }, () => {
- this.apply();
- });
+ change = selected => {
+ this.setState({ selected });
};
rotate = () => {
const { isRotated } = this.state;
- this.setState({ isRotated: !isRotated }, () => {
- this.apply();
- });
- };
-
- apply = () => {
- const iframe = getIframe();
- const { isRotated, selected, viewports } = this.state;
-
- if (iframe) {
- if (selected) {
- const {
- styles: { width: a, height: b },
- } = viewports[selected];
- iframe.style.width = isRotated ? b : a;
- iframe.style.height = isRotated ? a : b;
-
- if (!iframe.classList.item(iframeClass)) {
- iframe.classList.add(iframeClass);
- }
- } else {
- iframe.style.width = '100%';
- iframe.style.height = '100%';
- iframe.classList.remove(iframeClass);
- }
- } else {
- logger.error('Cannot find Storybook iframe');
- }
+ this.setState({ isRotated: !isRotated });
};
render() {
- const { viewports, selected } = this.state;
-
- const list = toList(viewports);
+ const { items, selected, isRotated } = getState(this.props, this.state);
+ const item = items.find(i => i.id === selected);
- if (!list.length) {
+ if (!items.length) {
return null;
}
return (
-
+ {item && item.value ? (
+
+ ) : null}
{({ hide }) => (
- {selected !== undefined ? (
+ {selected !== 'responsive' ? (
- {
hide();
- this.change(undefined);
+ this.change('responsive');
}}
>
@@ -134,12 +133,12 @@ export default class ViewportTool extends Component {
) : null}
- {list.map(([key, { name, type }]) => (
+ {items.map(({ id, name, type }) => (
- {
hide();
- this.change(key);
+ this.change(id);
}}
>
@@ -155,14 +154,7 @@ export default class ViewportTool extends Component {
}
ViewportTool.propTypes = {
- channel: PropTypes.shape({
- on: PropTypes.func,
- emit: PropTypes.func,
- removeListener: PropTypes.func,
- }).isRequired,
api: PropTypes.shape({
on: PropTypes.func,
- getQueryParam: PropTypes.func,
- setQueryParams: PropTypes.func,
}).isRequired,
};
diff --git a/addons/viewport/src/register.js b/addons/viewport/src/register.js
index 522cbb55de76..deb8bf839d2a 100644
--- a/addons/viewport/src/register.js
+++ b/addons/viewport/src/register.js
@@ -6,11 +6,10 @@ import { ADDON_ID } from './constants';
import Tool from './Tool';
addons.register(ADDON_ID, api => {
- const channel = addons.getChannel();
addons.add(ADDON_ID, {
- type: types.TOOL,
title: 'viewport / media-queries',
+ type: types.TOOL,
match: ({ viewMode }) => viewMode === 'story',
- render: () => ,
+ render: () => ,
});
});