misskey/packages/frontend/.storybook/preview.ts

114 lines
2.8 KiB
TypeScript
Raw Normal View History

2023-03-20 17:05:00 +00:00
import { addons } from '@storybook/addons';
import { FORCE_REMOUNT } from '@storybook/core-events';
2023-03-23 07:44:41 +00:00
import { type Preview, setup } from '@storybook/vue3';
2023-04-02 12:30:43 +00:00
import isChromatic from 'chromatic/isChromatic';
import { initialize, mswDecorator } from 'msw-storybook-addon';
import locale from './locale';
2023-03-20 13:12:11 +00:00
import { commonHandlers, onUnhandledRequest } from './mocks';
2023-03-20 17:05:00 +00:00
import themes from './themes';
2023-03-19 13:22:14 +00:00
import '../src/style.scss';
2023-03-23 07:44:41 +00:00
const appInitialized = Symbol();
let moduleInitialized = false;
2023-03-20 17:05:00 +00:00
let unobserve = () => {};
2023-03-25 03:21:16 +00:00
let misskeyOS = null;
2023-03-20 17:05:00 +00:00
function loadTheme(applyTheme: typeof import('../src/scripts/theme')['applyTheme']) {
unobserve();
const theme = themes[document.documentElement.dataset.misskeyTheme];
if (theme) {
applyTheme(themes[document.documentElement.dataset.misskeyTheme]);
2023-04-02 12:30:43 +00:00
} else if (isChromatic()) {
applyTheme(themes['l-light']);
2023-03-20 17:05:00 +00:00
}
const observer = new MutationObserver((entries) => {
for (const entry of entries) {
if (entry.attributeName === 'data-misskey-theme') {
const target = entry.target as HTMLElement;
const theme = themes[target.dataset.misskeyTheme];
if (theme) {
applyTheme(themes[target.dataset.misskeyTheme]);
} else {
target.removeAttribute('style');
}
}
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-misskey-theme'],
});
unobserve = () => observer.disconnect();
}
2023-03-20 13:12:11 +00:00
initialize({
onUnhandledRequest,
});
localStorage.setItem("locale", JSON.stringify(locale));
2023-03-20 17:05:00 +00:00
queueMicrotask(() => {
Promise.all([
import('../src/components'),
import('../src/directives'),
import('../src/widgets'),
import('../src/scripts/theme'),
import('../src/store'),
2023-03-25 03:21:16 +00:00
import('../src/os'),
]).then(([{ default: components }, { default: directives }, { default: widgets }, { applyTheme }, { defaultStore }, os]) => {
2023-03-20 17:05:00 +00:00
setup((app) => {
2023-03-23 07:44:41 +00:00
moduleInitialized = true;
if (app[appInitialized]) {
return;
}
app[appInitialized] = true;
2023-03-20 17:05:00 +00:00
loadTheme(applyTheme);
components(app);
directives(app);
widgets(app);
2023-03-25 03:21:16 +00:00
misskeyOS = os;
if (isChromatic()) {
defaultStore.set('animation', false);
}
2023-03-20 17:05:00 +00:00
});
});
});
2023-03-19 13:22:14 +00:00
const preview = {
decorators: [
2023-03-20 17:05:00 +00:00
(Story, context) => {
const story = Story();
2023-03-23 07:44:41 +00:00
if (!moduleInitialized) {
2023-03-20 17:05:00 +00:00
const channel = addons.getChannel();
2023-03-21 02:58:58 +00:00
(globalThis.requestIdleCallback || setTimeout)(() => {
2023-03-20 17:05:00 +00:00
channel.emit(FORCE_REMOUNT, { storyId: context.id });
});
}
return story;
2023-03-23 07:44:41 +00:00
},
mswDecorator,
2023-03-25 03:21:16 +00:00
(Story, context) => {
return {
setup() {
return {
context,
popups: misskeyOS.popups,
};
},
2023-03-25 14:32:47 +00:00
template:
'<component :is="popup.component" v-for="popup in popups" :key="popup.id" v-bind="popup.props" v-on="popup.events"/>' +
'<story />',
2023-03-25 03:21:16 +00:00
};
},
],
2023-03-20 13:12:11 +00:00
parameters: {
2023-04-01 03:18:42 +00:00
controls: {
exclude: /^__/,
},
2023-03-20 13:12:11 +00:00
msw: {
handlers: commonHandlers,
},
},
2023-03-19 13:22:14 +00:00
} satisfies Preview;
export default preview;