Norbert de Langen f9abc6a986
Merge branch 'next' into tech/remove-deprecations-6
# Conflicts:
#	addons/events/src/deprecated.js
#	addons/options/src/register.ts
#	examples/official-storybook/stories/core/decorators.stories.js
#	examples/official-storybook/stories/deprecated/addon-events.stories.js
#	lib/addons/src/make-decorator.test.ts
#	lib/api/src/modules/layout.ts
#	lib/cli/src/generate.js
#	lib/core/package.json
2020-03-31 09:40:58 +02:00

84 lines
2.7 KiB
TypeScript

import { document } from 'global';
import { addons, makeDecorator } from '@storybook/addons';
import { EVENTS, PARAM_KEY } from './constants';
const changeMediaAttribute = (element: HTMLElement, enabled: boolean) => {
const current = element.getAttribute('media');
if ((enabled && !current) || (!enabled && current === 'max-width: 1px')) {
// don't do anything
} else if (enabled && current === 'max-width: 1px') {
// remove the attribute
element.removeAttribute('media');
} else if (enabled) {
// add the disable attribute
const value = current.replace(' and max-width: 1px', '');
element.setAttribute('media', value);
} else {
// modify the existing attribute so it disables
const value = current ? `${current} and max-width: 1px` : 'max-width: 1px';
element.setAttribute('media', value);
}
};
const createElement = (id: string, code: string): HTMLDivElement => {
const element: HTMLDivElement = document.createElement('div');
element.setAttribute('id', `storybook-addon-resource_${id}`);
element.innerHTML = code;
return element;
};
const getElement = (id: string, code: string) => {
const found: Element = document.querySelector(`[id="storybook-addon-resource_${id}"]`);
return { element: found || createElement(id, code), created: !found };
};
const updateElement = (id: string, code: string, value: boolean) => {
const { element, created } = getElement(id, code);
element.querySelectorAll('link').forEach((child) => changeMediaAttribute(child, value));
element.querySelectorAll('style').forEach((child) => changeMediaAttribute(child, value));
if (created) {
document.body.appendChild(element);
}
};
const list: any[] = [];
const setResources = (resources: { code: string; id: string }[]) => {
const added = resources.filter((i) => !list.find((r) => r.code === i.code));
const removed = list.filter((i) => !resources.find((r) => r.code === i.code));
added.forEach((r) => list.push(r));
resources.forEach((r) => {
const { id, code } = r;
updateElement(id, code, true);
});
removed.forEach((r) => {
const { id, code } = r;
updateElement(id, code, false);
});
};
export const withCssResources = makeDecorator({
name: 'withCssResources',
parameterName: PARAM_KEY,
skipIfNoParametersOrOptions: true,
wrapper: (getStory, context, { options, parameters }) => {
const storyOptions = parameters || options;
addons.getChannel().on(EVENTS.SET, setResources);
if (!Array.isArray(storyOptions) && !Array.isArray(storyOptions.cssresources)) {
throw new Error('The `cssresources` parameter needs to be an Array');
}
return getStory(context);
},
});
if (module && module.hot && module.hot.decline) {
module.hot.decline();
}