mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 07:52:07 +08:00
# 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
84 lines
2.7 KiB
TypeScript
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();
|
|
}
|