adding monkeytype
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled

This commit is contained in:
Benjamin Falch
2026-04-23 13:53:44 +02:00
parent e214a2fd35
commit 2bc741fb78
1930 changed files with 7590652 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
import type { ThemeName } from "@monkeytype/schemas/configs";
import type { JSXElement } from "solid-js";
import { ThemesList, ThemeWithName } from "../../src/ts/constants/themes";
type StoryContext = {
globals: { theme?: string };
};
const themeMap = new Map(ThemesList.map((t) => [t.name, t]));
let currentThemeLink: HTMLLinkElement | null = null;
export function ThemeDecorator(
Story: () => JSXElement,
context: StoryContext,
): JSXElement {
const themeName = (context.globals.theme ?? "serika_dark") as ThemeName;
const theme =
themeMap.get(themeName) ?? (themeMap.get("serika_dark") as ThemeWithName);
const root = document.documentElement;
root.style.setProperty("--bg-color", theme.bg);
root.style.setProperty("--main-color", theme.main);
root.style.setProperty("--caret-color", theme.caret);
root.style.setProperty("--sub-color", theme.sub);
root.style.setProperty("--sub-alt-color", theme.subAlt);
root.style.setProperty("--text-color", theme.text);
root.style.setProperty("--error-color", theme.error);
root.style.setProperty("--error-extra-color", theme.errorExtra);
root.style.setProperty("--colorful-error-color", theme.colorfulError);
root.style.setProperty(
"--colorful-error-extra-color",
theme.colorfulErrorExtra,
);
// Load/unload theme CSS file
if (currentThemeLink) {
currentThemeLink.remove();
currentThemeLink = null;
}
if (theme.hasCss) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `/themes/${themeName}.css`;
document.head.appendChild(link);
currentThemeLink = link;
}
return Story();
}

View File

@@ -0,0 +1,153 @@
import { defineMain } from "storybook-solidjs-vite";
import tailwindcss from "@tailwindcss/vite";
import type { Plugin } from "vite";
function stubVirtualEnvConfig(): Plugin {
const id = "virtual:env-config";
const resolved = "\0" + id;
return {
name: "stub-virtual-env-config",
resolveId(source) {
if (source === id) return resolved;
},
load(loadId) {
if (loadId === resolved) {
return `export const envConfig = ${JSON.stringify({
isDevelopment: true,
backendUrl: "http://localhost:5005",
clientVersion: "storybook",
recaptchaSiteKey: "",
quickLoginEmail: undefined,
quickLoginPassword: undefined,
})};`;
}
},
};
}
function patchQsrToNotThrow(): Plugin {
return {
name: "patch-qsr-not-throw",
enforce: "pre",
transform(code, id) {
if (!id.includes("utils/dom")) return;
// Replace the throw in qsr with creating a dummy element
return code.replaceAll(
`throw new Error(\`Required element not found: \${selector}\`);`,
`console.warn(\`[storybook] qsr: element not found: \${selector}, returning dummy\`);
return new ElementWithUtils(document.createElement("div") as T);`,
);
},
};
}
function patchAnimatedModalToNotThrow(): Plugin {
return {
name: "patch-animated-modal-not-throw",
enforce: "pre",
transform(code, id) {
if (!id.includes("utils/animated-modal")) return;
return code
.replaceAll(
`throw new Error(
\`Dialog element with id \${constructorParams.dialogId} not found\`,
);`,
`console.warn(\`[storybook] AnimatedModal: dialog #\${constructorParams.dialogId} not found\`); return;`,
)
.replace(
`throw new Error("Animated dialog must be an HTMLDialogElement");`,
`console.warn("[storybook] AnimatedModal: element is not a dialog"); return;`,
);
},
};
}
function stubChartController(): Plugin {
const stubId = "\0stub-chart-controller";
const stubCode = `
const noop = () => {};
const fakeScale = new Proxy({}, { get: () => "" , set: () => true });
const fakeDataset = new Proxy({}, { get: () => [], set: () => true });
const fakeChart = {
data: { labels: [] },
options: { plugins: {} },
getDataset: () => fakeDataset,
getScale: () => fakeScale,
update: noop,
resize: noop,
};
export class ChartWithUpdateColors {}
export const result = fakeChart;
export const accountHistory = fakeChart;
export const accountActivity = fakeChart;
export const accountHistogram = fakeChart;
export const miniResult = fakeChart;
export let accountHistoryActiveIndex = 0;
export function updateAccountChartButtons() {}
`;
return {
name: "stub-chart-controller",
enforce: "pre",
resolveId(source, _importer) {
if (
source.endsWith("controllers/chart-controller") ||
source.endsWith("controllers/chart-controller.ts")
) {
return stubId;
}
},
load(id) {
if (id === stubId) return stubCode;
if (id.includes("controllers/chart-controller")) return stubCode;
},
};
}
function stubVirtualLanguageHashes(): Plugin {
const id = "virtual:language-hashes";
const resolved = "\0" + id;
return {
name: "stub-virtual-language-hashes",
resolveId(source) {
if (source === id) return resolved;
},
load(loadId) {
if (loadId === resolved) {
return `export const languageHashes = {};`;
}
},
};
}
export default defineMain({
staticDirs: ["../../static"],
framework: {
name: "storybook-solidjs-vite",
options: {
// docgen: {
// Enabled by default, but you can configure or disable it:
// see https://github.com/styleguidist/react-docgen-typescript#options
// },
},
},
addons: [
"@storybook/addon-docs",
"@storybook/addon-a11y",
"@storybook/addon-links",
"@storybook/addon-vitest",
],
stories: [
"../stories/**/*.mdx",
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
],
viteFinal(config) {
config.plugins ??= [];
config.plugins.push(tailwindcss());
config.plugins.push(stubVirtualEnvConfig());
config.plugins.push(stubVirtualLanguageHashes());
config.plugins.push(patchQsrToNotThrow());
config.plugins.push(patchAnimatedModalToNotThrow());
config.plugins.push(stubChartController());
return config;
},
});

View File

@@ -0,0 +1,6 @@
<!-- Stub elements needed by components with module-level DOM query calls -->
<body>
<div style="display: none">
<input id="wordsInput" />
</div>
</body>

View File

@@ -0,0 +1,74 @@
import addonA11y from "@storybook/addon-a11y";
import addonDocs from "@storybook/addon-docs";
import { definePreview } from "storybook-solidjs-vite";
import "../stories/tailwind.css";
import "../stories/storybook-theme.css";
import "@fortawesome/fontawesome-free/css/all.min.css";
import "balloon-css/balloon.min.css";
//@ts-expect-error this works i think
import "slim-select/styles";
import { ThemesList } from "../../src/ts/constants/themes";
import { ThemeDecorator } from "./ThemeDecorator";
const tailwindViewports = {
xxs: { name: "xxs (331px)", styles: { width: "331px", height: "900px" } },
xs: { name: "xs (426px)", styles: { width: "426px", height: "900px" } },
sm: { name: "sm (640px)", styles: { width: "640px", height: "900px" } },
md: { name: "md (768px)", styles: { width: "768px", height: "900px" } },
lg: { name: "lg (1024px)", styles: { width: "1024px", height: "900px" } },
xl: { name: "xl (1280px)", styles: { width: "1280px", height: "900px" } },
"2xl": {
name: "2xl (1536px)",
styles: { width: "1536px", height: "900px" },
},
};
export default definePreview({
addons: [addonDocs(), addonA11y()],
globalTypes: {
theme: {
description: "Global theme for components",
toolbar: {
title: "Theme",
icon: "paintbrush",
items: ThemesList.sort((a, b) => a.name.localeCompare(b.name)).map(
(t) => ({
value: t.name,
title: t.name.replace(/_/g, " "),
}),
),
dynamicTitle: true,
},
},
},
initialGlobals: {
theme: "serika_dark",
},
decorators: [ThemeDecorator],
parameters: {
layout: "centered",
// automatically create action args for all props that start with 'on'
actions: {
argTypesRegex: "^on.*",
},
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
viewport: {
options: tailwindViewports,
},
a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: "todo",
},
},
// All components will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
// tags: ['autodocs'],
});