build(#10336): control themes
This commit is contained in:
parent
bdbbb92ff6
commit
0ac4d744fd
7 changed files with 843 additions and 195 deletions
8
packages/frontend/.storybook/.gitignore
vendored
8
packages/frontend/.storybook/.gitignore
vendored
|
@ -1,8 +1,8 @@
|
||||||
# (cd .; pnpm tsc --jsx react --jsxFactory h ./generate.tsx && node ./generate.js)
|
# (cd path/to/frontend; pnpm tsc --jsx react --jsxFactory h .storybook/generate.tsx && node .storybook/generate.js)
|
||||||
/generate.js
|
/generate.js
|
||||||
# (cd .; pnpm tsc ./preload-locale.ts && node ./preload-locale.js)
|
# (cd path/to/frontend; pnpm tsc .storybook/preload-locale.ts && node .storybook/preload-locale.js)
|
||||||
/preload-locale.js
|
/preload-locale.js
|
||||||
/locale.ts
|
/locale.ts
|
||||||
# (cd .; pnpm tsc ./preload-theme.ts && node ./preload-theme.js)
|
# (cd path/to/frontend; pnpm tsc .storybook/preload-theme.ts && node .storybook/preload-theme.js)
|
||||||
/preload-theme.js
|
/preload-theme.js
|
||||||
/theme.ts
|
/themes.ts
|
||||||
|
|
|
@ -8,6 +8,7 @@ const config = {
|
||||||
'@storybook/addon-links',
|
'@storybook/addon-links',
|
||||||
'@storybook/addon-essentials',
|
'@storybook/addon-essentials',
|
||||||
'@storybook/addon-interactions',
|
'@storybook/addon-interactions',
|
||||||
|
'../node_modules/storybook-addon-misskey-theme',
|
||||||
],
|
],
|
||||||
framework: {
|
framework: {
|
||||||
name: '@storybook/vue3-vite',
|
name: '@storybook/vue3-vite',
|
||||||
|
|
|
@ -2,19 +2,35 @@ import { readFile, writeFile } from 'node:fs/promises';
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
import * as JSON5 from 'json5';
|
import * as JSON5 from 'json5';
|
||||||
|
|
||||||
Promise.all([
|
const keys = [
|
||||||
readFile(resolve(__dirname, '../src/themes/_light.json5'), 'utf8'),
|
'_dark',
|
||||||
readFile(resolve(__dirname, '../src/themes/l-light.json5'), 'utf8'),
|
'_light',
|
||||||
]).then((sources) => {
|
'l-light',
|
||||||
const base = JSON5.parse(sources[0]);
|
'l-coffee',
|
||||||
const theme = JSON5.parse(sources[1]);
|
'l-apricot',
|
||||||
|
'l-rainy',
|
||||||
|
'l-botanical',
|
||||||
|
'l-vivid',
|
||||||
|
'l-cherry',
|
||||||
|
'l-sushi',
|
||||||
|
'l-u0',
|
||||||
|
'd-dark',
|
||||||
|
'd-persimmon',
|
||||||
|
'd-astro',
|
||||||
|
'd-future',
|
||||||
|
'd-botanical',
|
||||||
|
'd-green-lime',
|
||||||
|
'd-green-orange',
|
||||||
|
'd-cherry',
|
||||||
|
'd-ice',
|
||||||
|
'd-u0',
|
||||||
|
]
|
||||||
|
|
||||||
|
Promise.all(keys.map((key) => readFile(resolve(__dirname, `../src/themes/${key}.json5`), 'utf8'))).then((sources) => {
|
||||||
writeFile(
|
writeFile(
|
||||||
resolve(__dirname, './theme.ts'),
|
resolve(__dirname, './themes.ts'),
|
||||||
`export default ${JSON.stringify(
|
`export default ${JSON.stringify(
|
||||||
Object.assign(theme, {
|
Object.fromEntries(sources.map((source, i) => [keys[i], JSON5.parse(source)])),
|
||||||
base: undefined,
|
|
||||||
props: Object.assign(base.props, theme.props),
|
|
||||||
}),
|
|
||||||
undefined,
|
undefined,
|
||||||
2,
|
2,
|
||||||
)} as const;`,
|
)} as const;`,
|
||||||
|
|
|
@ -1,30 +1,75 @@
|
||||||
import { type Preview, setup } from '@storybook/vue3';
|
import { addons } from '@storybook/addons';
|
||||||
|
import { FORCE_REMOUNT } from '@storybook/core-events';
|
||||||
|
import { type Preview, forceReRender, setup } from '@storybook/vue3';
|
||||||
import { initialize, mswDecorator } from 'msw-storybook-addon';
|
import { initialize, mswDecorator } from 'msw-storybook-addon';
|
||||||
import locale from './locale';
|
import locale from './locale';
|
||||||
import { commonHandlers, onUnhandledRequest } from './mocks';
|
import { commonHandlers, onUnhandledRequest } from './mocks';
|
||||||
import theme from './theme';
|
import themes from './themes';
|
||||||
import '../src/style.scss';
|
import '../src/style.scss';
|
||||||
|
|
||||||
|
let initialized = false;
|
||||||
|
let unobserve = () => {};
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
initialize({
|
initialize({
|
||||||
onUnhandledRequest,
|
onUnhandledRequest,
|
||||||
});
|
});
|
||||||
localStorage.setItem("locale", JSON.stringify(locale));
|
localStorage.setItem("locale", JSON.stringify(locale));
|
||||||
Promise.all([
|
queueMicrotask(() => {
|
||||||
import('../src/components'),
|
Promise.all([
|
||||||
import('../src/directives'),
|
import('../src/components'),
|
||||||
import('../src/widgets'),
|
import('../src/directives'),
|
||||||
import('../src/scripts/theme').then(({ applyTheme }) => applyTheme(theme)),
|
import('../src/widgets'),
|
||||||
]).then(([{ default: components }, { default: directives }, { default: widgets }]) => {
|
import('../src/scripts/theme'),
|
||||||
setup((app) => {
|
]).then(([{ default: components }, { default: directives }, { default: widgets }, { applyTheme }]) => {
|
||||||
components(app);
|
setup((app) => {
|
||||||
directives(app);
|
initialized = true;
|
||||||
widgets(app);
|
loadTheme(applyTheme);
|
||||||
|
components(app);
|
||||||
|
directives(app);
|
||||||
|
widgets(app);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const preview = {
|
const preview = {
|
||||||
decorators: [
|
decorators: [
|
||||||
mswDecorator,
|
mswDecorator,
|
||||||
|
(Story, context) => {
|
||||||
|
const story = Story();
|
||||||
|
if (!initialized) {
|
||||||
|
const channel = addons.getChannel();
|
||||||
|
requestIdleCallback(() => {
|
||||||
|
channel.emit(FORCE_REMOUNT, { storyId: context.id });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return story;
|
||||||
|
}
|
||||||
],
|
],
|
||||||
parameters: {
|
parameters: {
|
||||||
msw: {
|
msw: {
|
||||||
|
|
|
@ -75,10 +75,16 @@
|
||||||
"@storybook/addon-essentials": "^7.0.0-rc.4",
|
"@storybook/addon-essentials": "^7.0.0-rc.4",
|
||||||
"@storybook/addon-interactions": "^7.0.0-rc.4",
|
"@storybook/addon-interactions": "^7.0.0-rc.4",
|
||||||
"@storybook/addon-links": "^7.0.0-rc.4",
|
"@storybook/addon-links": "^7.0.0-rc.4",
|
||||||
|
"@storybook/addons": "7.0.0-rc.5",
|
||||||
"@storybook/blocks": "^7.0.0-rc.4",
|
"@storybook/blocks": "^7.0.0-rc.4",
|
||||||
"@storybook/manager-api": "7.0.0-rc.4",
|
"@storybook/core-events": "^7.0.0-rc.4",
|
||||||
|
"@storybook/manager-api": "^7.0.0-rc.4",
|
||||||
|
"@storybook/preview-api": "^7.0.0-rc.4",
|
||||||
|
"@storybook/react": "^7.0.0-rc.4",
|
||||||
|
"@storybook/react-vite": "^7.0.0-rc.4",
|
||||||
"@storybook/testing-library": "^0.0.14-next.1",
|
"@storybook/testing-library": "^0.0.14-next.1",
|
||||||
"@storybook/theming": "7.0.0-rc.4",
|
"@storybook/theming": "^7.0.0-rc.4",
|
||||||
|
"@storybook/types": "^7.0.0-rc.4",
|
||||||
"@storybook/vue3": "^7.0.0-rc.4",
|
"@storybook/vue3": "^7.0.0-rc.4",
|
||||||
"@storybook/vue3-vite": "^7.0.0-rc.4",
|
"@storybook/vue3-vite": "^7.0.0-rc.4",
|
||||||
"@testing-library/vue": "^6.6.1",
|
"@testing-library/vue": "^6.6.1",
|
||||||
|
@ -114,6 +120,7 @@
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"start-server-and-test": "2.0.0",
|
"start-server-and-test": "2.0.0",
|
||||||
"storybook": "^7.0.0-rc.4",
|
"storybook": "^7.0.0-rc.4",
|
||||||
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"summaly": "github:misskey-dev/summaly",
|
"summaly": "github:misskey-dev/summaly",
|
||||||
"vitest": "^0.29.2",
|
"vitest": "^0.29.2",
|
||||||
"vitest-fetch-mock": "^0.2.2",
|
"vitest-fetch-mock": "^0.2.2",
|
||||||
|
|
|
@ -3,7 +3,6 @@ export class I18n<T extends Record<string, any>> {
|
||||||
|
|
||||||
constructor(locale: T) {
|
constructor(locale: T) {
|
||||||
this.ts = locale;
|
this.ts = locale;
|
||||||
console.log(this);
|
|
||||||
|
|
||||||
//#region BIND
|
//#region BIND
|
||||||
this.t = this.t.bind(this);
|
this.t = this.t.bind(this);
|
||||||
|
|
910
pnpm-lock.yaml
910
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue