diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 3db2e79..57f0231 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -12,9 +12,6 @@ module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["react-refresh"],
rules: {
- "react-refresh/only-export-components": [
- "warn",
- { allowConstantExport: true },
- ],
+ "react-refresh/only-export-components": 0,
},
};
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index de92157..c3c753a 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -14,11 +14,14 @@ jobs:
with:
fetch-depth: 2
- run: pnpm install
- - run: pnpm test
- run: pnpm lint
- run: pnpm format:check
+ - run: pnpm test
+ working-directory: packages/zod-error-viewer
- run: pnpm build
+ working-directory: packages/zod-error-viewer
- name: Publish package
+ working-directory: packages/zod-error-viewer
run: |
if [ $GITHUB_REF != "refs/heads/main" ]; then
echo "Branch is not main, skipping publish step"
@@ -27,7 +30,7 @@ jobs:
echo "Branch is main, proceeding..."
- prev_version=$(git show HEAD~1:package.json | jq -r '.version')
+ prev_version=$(git show HEAD~1:packages/zod-error-viewer/package.json | jq -r '.version')
new_version=$(cat package.json | jq -r '.version')
if [ $prev_version = $new_version ]; then
@@ -43,11 +46,24 @@ jobs:
echo "Publishing package..."
pnpm publish
- - name: Build documentation
+ - name: Build storybook
+ working-directory: packages/zod-error-viewer
run: pnpm build-storybook
+ - name: Build docs site
+ working-directory: packages/docs-site
+ run: pnpm build
+ - name: Move storybook to under docs site
+ run: mv ./packages/zod-error-viewer/storybook-static ./packages/docs-site/dist/storybook-static
+ # Workaround since github pages does not support routing all requests to index.html
+ - name: Create fake pages
+ run: |
+ mkdir ./packages/docs-site/dist/docs
+ cp ./packages/docs-site/dist/index.html ./packages/docs-site/dist/docs/index.html
+ mkdir ./packages/docs-site/dist/playground
+ cp ./packages/docs-site/dist/index.html ./packages/docs-site/dist/playground/index.html
- name: Upload documentation artifact
uses: actions/upload-pages-artifact@v3
with:
- path: storybook-static
+ path: packages/docs-site/dist
- name: Publish documentation
uses: actions/deploy-pages@v4
diff --git a/img/logo-wide.png b/img/logo-wide.png
deleted file mode 100644
index 9fb2bb3..0000000
Binary files a/img/logo-wide.png and /dev/null differ
diff --git a/package.json b/package.json
index 2abfcf8..a4e3f66 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
{
- "name": "zod-error-viewer",
- "version": "1.2.1",
+ "name": "zod-error-viewer-monorepo",
+ "private": true,
+ "version": "1.0.0",
"license": "MIT",
"author": {
"name": "Ben Lorantfy",
@@ -10,42 +11,10 @@
"type": "git",
"url": "https://github.com/BenLorantfy/zod-error-viewer"
},
- "keywords": [
- "zod",
- "visualization",
- "viewer"
- ],
- "files": [
- "dist"
- ],
- "type": "module",
- "module": "dist/esm/ZodErrorViewer.js",
- "main": "dist/cjs/ZodErrorViewer.js",
- "types": "dist/types/ZodErrorViewer.d.ts",
- "sideEffects": false,
- "exports": {
- ".": {
- "import": "./dist/esm/ZodErrorViewer.js",
- "require": "./dist/cjs/ZodErrorViewer.js",
- "types": "./dist/types/ZodErrorViewer.d.ts"
- }
- },
"scripts": {
- "dev": "storybook dev -p 6006",
- "storybook": "pnpm run dev",
- "build": "tsc -p ./tsconfig.cjs.json && tsc -p ./tsconfig.esm.json",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"format:check": "prettier --check .",
- "build-storybook": "storybook build",
- "prepare": "husky",
- "test": "vitest"
- },
- "dependencies": {
- "zod": ">=3"
- },
- "peerDependencies": {
- "react": ">=16",
- "react-dom": ">=16"
+ "prepare": "husky"
},
"lint-staged": {
"**/*.{js,ts,tsx,jsx}": [
@@ -55,19 +24,6 @@
"**/*.json": "prettier --check --ignore-unknown"
},
"devDependencies": {
- "@chromatic-com/storybook": "^1.5.0",
- "@storybook/addon-essentials": "^8.1.5",
- "@storybook/addon-interactions": "^8.1.5",
- "@storybook/addon-links": "^8.1.5",
- "@storybook/blocks": "^8.1.5",
- "@storybook/react": "^8.1.5",
- "@storybook/react-vite": "^8.1.5",
- "@storybook/test": "^8.1.5",
- "@storybook/theming": "^8.1.5",
- "@testing-library/react": "^15.0.7",
- "@testing-library/user-event": "^14.5.2",
- "@types/react": "^18.2.66",
- "@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
@@ -76,16 +32,8 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"eslint-plugin-storybook": "^0.8.0",
- "happy-dom": "^14.12.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
- "prettier": "3.3.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "storybook": "^8.1.5",
- "typescript": "^5.2.2",
- "vite": "^5.2.0",
- "vitest": "^1.6.0",
- "zod": "^3.23.8"
+ "prettier": "3.3.0"
}
}
diff --git a/packages/docs-site/README.md b/packages/docs-site/README.md
new file mode 100644
index 0000000..bb15685
--- /dev/null
+++ b/packages/docs-site/README.md
@@ -0,0 +1,30 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default {
+ // other rules...
+ parserOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ project: ["./tsconfig.json", "./tsconfig.node.json"],
+ tsconfigRootDir: __dirname,
+ },
+};
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/index.html b/packages/docs-site/index.html
similarity index 72%
rename from index.html
rename to packages/docs-site/index.html
index e4b78ea..842afe5 100644
--- a/index.html
+++ b/packages/docs-site/index.html
@@ -2,9 +2,9 @@
-
+
- Vite + React + TS
+ zod-error-viewer
diff --git a/packages/docs-site/package.json b/packages/docs-site/package.json
new file mode 100644
index 0000000..a1597e7
--- /dev/null
+++ b/packages/docs-site/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "docs-site",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@codemirror/lang-javascript": "^6.2.2",
+ "@uiw/react-codemirror": "^4.22.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "zod": ">=3",
+ "zod-error-viewer": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@vitejs/plugin-react": "^4.2.1",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0"
+ }
+}
diff --git a/packages/docs-site/public/favicon.svg b/packages/docs-site/public/favicon.svg
new file mode 100644
index 0000000..7be4ed1
--- /dev/null
+++ b/packages/docs-site/public/favicon.svg
@@ -0,0 +1,67 @@
+
\ No newline at end of file
diff --git a/packages/docs-site/src/App.tsx b/packages/docs-site/src/App.tsx
new file mode 100644
index 0000000..9d50e8e
--- /dev/null
+++ b/packages/docs-site/src/App.tsx
@@ -0,0 +1,25 @@
+import { PlaygroundPage } from "./pages/PlaygroundPage";
+import { Route, Router } from "./components/Router";
+import { HomePage } from "./pages/HomePage";
+import { Layout } from "./components/Layout";
+
+export function App() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/docs-site/src/assets/logo.png b/packages/docs-site/src/assets/logo.png
new file mode 100644
index 0000000..e45b162
Binary files /dev/null and b/packages/docs-site/src/assets/logo.png differ
diff --git a/packages/docs-site/src/components/Layout.css b/packages/docs-site/src/components/Layout.css
new file mode 100644
index 0000000..4e6a4d5
--- /dev/null
+++ b/packages/docs-site/src/components/Layout.css
@@ -0,0 +1,53 @@
+.content {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+main {
+ flex-grow: 1;
+ flex-basis: 0;
+}
+
+nav {
+ background-color: rgb(247, 249, 252);
+ flex-grow: 0;
+ display: flex;
+ border-bottom: 1px solid rgb(220, 220, 220);
+
+ ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+
+ li {
+ height: 100%;
+
+ a {
+ padding: 16px;
+ display: flex;
+ align-items: center;
+ text-decoration: none;
+ color: #595959;
+ transition: all 0.1s;
+ }
+
+ a:hover {
+ background-color: #e7e7e7;
+ }
+
+ a:focus {
+ background-color: #e7e7e7;
+ }
+
+ a:active {
+ background-color: #dddddd;
+ }
+
+ a[aria-current="page"] {
+ background-color: #dddddd;
+ }
+ }
+ }
+}
diff --git a/packages/docs-site/src/components/Layout.tsx b/packages/docs-site/src/components/Layout.tsx
new file mode 100644
index 0000000..a4353d9
--- /dev/null
+++ b/packages/docs-site/src/components/Layout.tsx
@@ -0,0 +1,59 @@
+import { Link, usePathname } from "./Router";
+import logo from "../assets/logo.png";
+import "./Layout.css";
+
+function Nav() {
+ const pathname = usePathname();
+ return (
+
+ );
+}
+
+export function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/packages/docs-site/src/components/Router.tsx b/packages/docs-site/src/components/Router.tsx
new file mode 100644
index 0000000..c020e1a
--- /dev/null
+++ b/packages/docs-site/src/components/Router.tsx
@@ -0,0 +1,91 @@
+import { createContext, useContext, useEffect, useState } from "react";
+
+const CounterContext = createContext(0);
+const SetCounterContext = createContext<
+ React.Dispatch>
+>(() => {});
+
+export function Router({ children }: { children: React.ReactNode }) {
+ const [count, setCount] = useState(0);
+
+ useEffect(() => {
+ const listener = () => {
+ setCount((c) => c + 1);
+ };
+
+ window.addEventListener("popstate", listener);
+ }, []);
+
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+export function usePathname() {
+ useContext(CounterContext);
+ const pathname = window.location.pathname;
+ if (pathname === "/") {
+ return pathname;
+ }
+
+ if (pathname.endsWith("/")) {
+ return pathname.substring(0, pathname.length - 1);
+ }
+
+ return pathname;
+}
+
+export function Route({
+ path,
+ children,
+}: {
+ path: string;
+ children: React.ReactNode;
+}) {
+ const pathname = usePathname();
+ if (path !== pathname) {
+ return null;
+ }
+
+ return <>{children}>;
+}
+
+export function Link({
+ href,
+ children,
+ "aria-current": ariaCurrent,
+}: {
+ href: string;
+ children: React.ReactNode;
+ "aria-current"?: "page";
+}) {
+ const setCount = useContext(SetCounterContext);
+ return (
+ {
+ if (event.ctrlKey || event.metaKey) {
+ return;
+ }
+
+ if (
+ href.indexOf("http") === 0 &&
+ window.location.host !== new URL(href).host
+ ) {
+ return;
+ }
+
+ event.preventDefault();
+ window.history.pushState({}, "", href);
+ setCount((c) => c + 1);
+ }}
+ aria-current={ariaCurrent}
+ >
+ {children}
+
+ );
+}
diff --git a/packages/docs-site/src/index.css b/packages/docs-site/src/index.css
new file mode 100644
index 0000000..4631a5b
--- /dev/null
+++ b/packages/docs-site/src/index.css
@@ -0,0 +1,15 @@
+html,
+body {
+ height: 100%;
+ padding: 0;
+ margin: 0;
+ font-family: sans-serif;
+}
+
+#root {
+ height: 100%;
+}
+
+* {
+ box-sizing: border-box;
+}
diff --git a/packages/docs-site/src/main.tsx b/packages/docs-site/src/main.tsx
new file mode 100644
index 0000000..71675c4
--- /dev/null
+++ b/packages/docs-site/src/main.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { App } from "./App.tsx";
+import "./index.css";
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+ ,
+);
diff --git a/packages/docs-site/src/pages/HomePage.css b/packages/docs-site/src/pages/HomePage.css
new file mode 100644
index 0000000..9dc1a58
--- /dev/null
+++ b/packages/docs-site/src/pages/HomePage.css
@@ -0,0 +1,28 @@
+.buttonLink {
+ background-color: rgb(24, 38, 63);
+ color: white;
+ text-decoration: none;
+ padding-left: 16px;
+ padding-right: 16px;
+ padding-top: 14px;
+ padding-bottom: 14px;
+ border-radius: 8px;
+ font-size: large;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ outline-offset: 2px;
+ margin-top: 8px;
+}
+
+.buttonLink:hover {
+ background-color: rgb(55, 73, 105);
+}
+
+.buttonLink:focus {
+ background-color: rgb(55, 73, 105);
+}
+
+p {
+ font-size: large;
+}
diff --git a/packages/docs-site/src/pages/HomePage.tsx b/packages/docs-site/src/pages/HomePage.tsx
new file mode 100644
index 0000000..f310ce7
--- /dev/null
+++ b/packages/docs-site/src/pages/HomePage.tsx
@@ -0,0 +1,49 @@
+import { ZodErrorViewer } from "zod-error-viewer";
+import logo from "../assets/logo.png";
+import { z } from "zod";
+import "./HomePage.css";
+
+export function HomePage() {
+ const data = {
+ name: "Han Solo",
+ age: "35",
+ shotFirst: false,
+ sideKicks: ["Lando", "Obi-wan"],
+ };
+ const error = z
+ .object({
+ name: z.string(),
+ age: z.number(),
+ shotFirst: z.literal(true),
+ sideKicks: z.array(z.union([z.literal("Chewbacca"), z.literal("Lando")])),
+ })
+ .safeParse(data).error!;
+
+ return (
+
+ );
+}
diff --git a/packages/docs-site/src/pages/PlaygroundPage.css b/packages/docs-site/src/pages/PlaygroundPage.css
new file mode 100644
index 0000000..9c5b89f
--- /dev/null
+++ b/packages/docs-site/src/pages/PlaygroundPage.css
@@ -0,0 +1,70 @@
+.playground {
+ font-family: sans-serif;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ padding: 16px;
+
+ h1,
+ h2 {
+ margin: 0;
+ font-weight: 400;
+ color: #595959;
+ }
+
+ h1 {
+ font-size: 1.5rem;
+ margin-bottom: 8px;
+ }
+
+ h2 {
+ padding: 8px;
+ font-size: 1.2rem;
+ background-color: rgb(245, 245, 245);
+ }
+
+ main {
+ padding: 16px;
+ flex-grow: 1;
+ overflow: auto;
+ }
+
+ .error {
+ color: red;
+ min-height: 30px;
+ padding-top: 4px;
+ }
+
+ .editor-column {
+ flex-basis: 33.33%;
+ }
+
+ .editor {
+ border: 1px solid rgb(221, 221, 221);
+ }
+
+ .error-viewer-container {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .error-viewer {
+ flex-grow: 1;
+ flex-basis: 0;
+ overflow: hidden;
+ }
+
+ .tag {
+ display: inline-block;
+ border-radius: 8px;
+ background-color: #dedede;
+ padding: 8px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ vertical-align: middle;
+ font-size: 0.9rem;
+ }
+}
diff --git a/packages/docs-site/src/pages/PlaygroundPage.tsx b/packages/docs-site/src/pages/PlaygroundPage.tsx
new file mode 100644
index 0000000..9981a40
--- /dev/null
+++ b/packages/docs-site/src/pages/PlaygroundPage.tsx
@@ -0,0 +1,169 @@
+import { useMemo, useState } from "react";
+import CodeMirror from "@uiw/react-codemirror";
+import { javascript } from "@codemirror/lang-javascript";
+import { ZodErrorViewer } from "zod-error-viewer";
+import { z } from "zod";
+import "./PlaygroundPage.css";
+
+export function PlaygroundPage() {
+ const [dataStr, setDataStr] = useState("");
+ const [errorStr, setErrorStr] = useState("");
+ const [schemaStr, setSchemaStr] = useState("");
+
+ const { data, dataParseError } = useMemo(() => {
+ if (dataStr.trim().length === 0) {
+ return {
+ data: null,
+ };
+ }
+ try {
+ return { data: JSON.parse(dataStr) };
+ } catch (err) {
+ return {
+ data: null,
+ dataParseError: err instanceof Error ? err : new Error("Unknown error"),
+ };
+ }
+ }, [dataStr]);
+
+ const { schema, schemaEvalError } = useMemo(() => {
+ try {
+ Object.assign(window, { z });
+ const schema = eval(`const z = window.z; ${schemaStr}`);
+ if (!schema || !("_def" in schema)) {
+ return {
+ schema: null,
+ schemaEvalError:
+ (schemaStr || "").trim().length > 0
+ ? new Error("Missing schema")
+ : null,
+ };
+ }
+ return {
+ schema,
+ schemaEvalError: null,
+ };
+ } catch (err) {
+ return {
+ schema: null,
+ schemaEvalError:
+ err instanceof Error ? err : new Error("Unknown error"),
+ };
+ }
+ }, [schemaStr]);
+
+ const { error, errorParseError, schemaExecuteError } = useMemo(() => {
+ if (errorStr.trim().length !== 0) {
+ try {
+ return { error: JSON.parse(errorStr) };
+ } catch (err) {
+ return {
+ error: undefined,
+ errorParseError:
+ err instanceof Error ? err : new Error("Unknown error"),
+ };
+ }
+ }
+
+ if (!schema) {
+ return {
+ error: undefined,
+ };
+ }
+
+ try {
+ return { error: schema.safeParse(data).error };
+ } catch (err) {
+ return {
+ error: undefined,
+ schemaExecuteError:
+ err instanceof Error ? err : new Error("Unknown error"),
+ };
+ }
+ }, [errorStr, schema, data]);
+
+ return (
+
+
Playground
+
+
+
+
DATA
+
+
+
+ {dataParseError?.message
+ ? `Failed to parse error: ${dataParseError.message}`
+ : ""}
+
+
+
+
+
+ ERROR{" "}
+ Optional
+
+
+
+
+ {errorParseError?.message
+ ? `Failed to parse error: ${errorParseError.message}`
+ : ""}
+
+
+
+
+
+
+ SCHEMA{" "}
+ Optional
+
+
+
+
+ {schemaExecuteError?.message
+ ? `Failed to execute schema: ${schemaExecuteError}`
+ : schemaEvalError?.message
+ ? `Failed to parse schema: ${schemaEvalError.message}`
+ : ""}
+
+
+
+
+
+ );
+}
diff --git a/packages/docs-site/src/vite-env.d.ts b/packages/docs-site/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/packages/docs-site/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/docs-site/tsconfig.json b/packages/docs-site/tsconfig.json
new file mode 100644
index 0000000..a7fc6fb
--- /dev/null
+++ b/packages/docs-site/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/packages/docs-site/tsconfig.node.json b/packages/docs-site/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/packages/docs-site/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/vite.config.ts b/packages/docs-site/vite.config.ts
similarity index 100%
rename from vite.config.ts
rename to packages/docs-site/vite.config.ts
diff --git a/.storybook/main.ts b/packages/zod-error-viewer/.storybook/main.ts
similarity index 100%
rename from .storybook/main.ts
rename to packages/zod-error-viewer/.storybook/main.ts
diff --git a/.storybook/manager-head.html b/packages/zod-error-viewer/.storybook/manager-head.html
similarity index 100%
rename from .storybook/manager-head.html
rename to packages/zod-error-viewer/.storybook/manager-head.html
diff --git a/.storybook/manager.ts b/packages/zod-error-viewer/.storybook/manager.ts
similarity index 72%
rename from .storybook/manager.ts
rename to packages/zod-error-viewer/.storybook/manager.ts
index 798a4cc..45943a1 100644
--- a/.storybook/manager.ts
+++ b/packages/zod-error-viewer/.storybook/manager.ts
@@ -1,13 +1,9 @@
import { addons } from "@storybook/manager-api";
import { create } from "@storybook/theming/create";
-// @ts-expect-error
-import logo from "../img/logo-wide.png";
-
const theme = create({
base: "light",
brandTitle: "zod-error-viewer",
- brandImage: logo,
});
addons.setConfig({
diff --git a/packages/zod-error-viewer/package.json b/packages/zod-error-viewer/package.json
new file mode 100644
index 0000000..e86e4e4
--- /dev/null
+++ b/packages/zod-error-viewer/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "zod-error-viewer",
+ "version": "1.2.1",
+ "license": "MIT",
+ "author": {
+ "name": "Ben Lorantfy",
+ "url": "https://www.benlorantfy.com/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/BenLorantfy/zod-error-viewer"
+ },
+ "keywords": [
+ "zod",
+ "visualization",
+ "viewer"
+ ],
+ "files": [
+ "dist"
+ ],
+ "type": "module",
+ "module": "dist/esm/ZodErrorViewer.js",
+ "main": "dist/cjs/ZodErrorViewer.js",
+ "types": "dist/types/ZodErrorViewer.d.ts",
+ "sideEffects": false,
+ "exports": {
+ ".": {
+ "import": "./dist/esm/ZodErrorViewer.js",
+ "require": "./dist/cjs/ZodErrorViewer.js",
+ "types": "./dist/types/ZodErrorViewer.d.ts"
+ }
+ },
+ "scripts": {
+ "dev": "storybook dev -p 6006",
+ "storybook": "pnpm run dev",
+ "build": "tsc -p ./tsconfig.cjs.json && tsc -p ./tsconfig.esm.json",
+ "build-storybook": "storybook build",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "zod": ">=3"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ },
+ "devDependencies": {
+ "@chromatic-com/storybook": "^1.5.0",
+ "@codemirror/lang-javascript": "^6.2.2",
+ "@storybook/addon-essentials": "^8.1.5",
+ "@storybook/addon-interactions": "^8.1.5",
+ "@storybook/addon-links": "^8.1.5",
+ "@storybook/blocks": "^8.1.5",
+ "@storybook/manager-api": "^8.1.6",
+ "@storybook/react": "^8.1.5",
+ "@storybook/react-vite": "^8.1.5",
+ "@storybook/test": "^8.1.5",
+ "@storybook/theming": "^8.1.5",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@uiw/react-codemirror": "^4.22.2",
+ "@vitejs/plugin-react": "^4.2.1",
+ "happy-dom": "^14.12.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "storybook": "^8.1.5",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0",
+ "vitest": "^1.6.0",
+ "zod": "^3.23.8"
+ }
+}
diff --git a/src/ZodErrorViewer.stories.tsx b/packages/zod-error-viewer/src/ZodErrorViewer.stories.tsx
similarity index 100%
rename from src/ZodErrorViewer.stories.tsx
rename to packages/zod-error-viewer/src/ZodErrorViewer.stories.tsx
diff --git a/src/ZodErrorViewer.test.tsx b/packages/zod-error-viewer/src/ZodErrorViewer.test.tsx
similarity index 95%
rename from src/ZodErrorViewer.test.tsx
rename to packages/zod-error-viewer/src/ZodErrorViewer.test.tsx
index 170054d..89fcbf1 100644
--- a/src/ZodErrorViewer.test.tsx
+++ b/packages/zod-error-viewer/src/ZodErrorViewer.test.tsx
@@ -244,6 +244,30 @@ test("renders correctly for missing keys", () => {
`);
});
+test("renders correctly for missing key that is a discriminator", () => {
+ const data = {};
+ render(
+ ,
+ );
+
+ expect(`\n${document.body.innerText}\n`).toMatchInlineSnapshot(`
+ "
+ 1{ // Error: Object missing required key: 'type'
+ 2}
+ "
+ `);
+});
+
test("renders correctly for unreconizged keys", () => {
render();
expect(`\n${document.body.innerText}\n`).toMatchInlineSnapshot(`
diff --git a/src/ZodErrorViewer.tsx b/packages/zod-error-viewer/src/ZodErrorViewer.tsx
similarity index 87%
rename from src/ZodErrorViewer.tsx
rename to packages/zod-error-viewer/src/ZodErrorViewer.tsx
index bc32461..54b94da 100644
--- a/src/ZodErrorViewer.tsx
+++ b/packages/zod-error-viewer/src/ZodErrorViewer.tsx
@@ -54,8 +54,9 @@ const srOnly: CSSProperties = {
*/
export function ZodErrorViewer({
data,
- error,
+ error = new ZodError([]),
theme = defaultTheme,
+ height,
}: {
/**
* The data that was parsed when the error occurred
@@ -64,11 +65,16 @@ export function ZodErrorViewer({
/**
* The zod error that was thrown when parsing the data
*/
- error: z.ZodError;
+ error?: z.ZodError;
/**
* A custom theme to apply to the component
*/
theme?: Partial;
+
+ /**
+ * Set to `fill` to fill the parent container
+ */
+ height?: "fill";
}) {
const mergedTheme = {
...defaultTheme,
@@ -83,15 +89,36 @@ export function ZodErrorViewer({
fontSize: "1rem",
whiteSpace: "nowrap",
background: mergedTheme.background,
+ position: "relative",
+ height: height === "fill" ? "100%" : undefined,
}}
>
-
+
+
+
);
}
@@ -109,6 +136,7 @@ function RecursiveViewer({
onToggleTruncate,
toggleButtonRef,
truncated,
+ rootData,
}: {
propertyKey?: string;
data: unknown;
@@ -122,6 +150,7 @@ function RecursiveViewer({
onToggleTruncate?: () => void;
toggleButtonRef?: React.RefObject;
truncated?: boolean;
+ rootData?: unknown;
}) {
const [unionErrorIndex, setSelectedUnionErrorIndex] = useState(0);
const [truncateStart, setTruncateStart] = useState(true);
@@ -152,6 +181,7 @@ function RecursiveViewer({
onToggleTruncate={onToggleTruncate}
toggleButtonRef={toggleButtonRef}
truncated={truncated}
+ rootData={rootData}
/>
);
}
@@ -198,6 +228,7 @@ function RecursiveViewer({
onToggleTruncate={onToggleTruncate}
toggleButtonRef={toggleButtonRef}
truncated={truncated}
+ rootData={rootData}
/>
{firstPart.length > 5 && truncateStart ? (
) : (
firstPart.map((value, i) => {
@@ -243,6 +275,7 @@ function RecursiveViewer({
: undefined
}
toggleButtonRef={startToggleButtonRef}
+ rootData={rootData}
/>
);
})
@@ -261,6 +294,7 @@ function RecursiveViewer({
path={[...path, i + firstPart.length]}
theme={theme}
countLines={countLines}
+ rootData={rootData}
/>
);
})}
@@ -281,6 +315,7 @@ function RecursiveViewer({
truncated
indentation={indentation + 1}
theme={theme}
+ rootData={rootData}
/>
) : (
thirdPart.map((value, i) => {
@@ -308,6 +343,7 @@ function RecursiveViewer({
: undefined
}
toggleButtonRef={endToggleButtonRef}
+ rootData={rootData}
/>
);
})
@@ -318,6 +354,7 @@ function RecursiveViewer({
comma={comma}
num={runningLineNum++}
theme={theme}
+ rootData={rootData}
/>
>
);
@@ -339,6 +376,7 @@ function RecursiveViewer({
onToggleTruncate={onToggleTruncate}
toggleButtonRef={toggleButtonRef}
truncated={truncated}
+ rootData={rootData}
/>
{entries.map(([key, value], i) => {
runningLineNum += i === 0 ? 1 : countLines(entries[i - 1]?.[1]);
@@ -354,6 +392,7 @@ function RecursiveViewer({
path={[...path, key]}
theme={theme}
countLines={countLines}
+ rootData={rootData}
/>
);
})}
@@ -369,6 +408,7 @@ function RecursiveViewer({
comma={comma}
path={path}
theme={theme}
+ rootData={rootData}
/>
>
);
@@ -394,19 +434,29 @@ function getUnionError({
return unionIssue ? unionIssue.unionErrors[index] : undefined;
}
-function getRelevantIssues(error: ZodError, path: Array) {
+function getRelevantIssues({
+ error,
+ path = [],
+ rootData,
+}: {
+ error: ZodError;
+ path?: Array;
+ rootData: unknown;
+}) {
const relevantIssues =
error.issues.filter((issue) => issue.path.join(".") === path?.join(".")) ||
[];
const missingKeys = [];
for (const issue of error.issues) {
- if (isMissing(issue, path)) {
+ if (isMissing({ issue, objPath: path, rootData })) {
missingKeys.push(issue.path[issue.path.length - 1]);
} else if (
issue.code === ZodIssueCode.invalid_union &&
issue.unionErrors.every((err) =>
- err.issues.some((iss) => isMissing(iss, path)),
+ err.issues.some((iss) =>
+ isMissing({ issue: iss, objPath: path, rootData }),
+ ),
)
) {
missingKeys.push(issue.path[issue.path.length - 1]);
@@ -427,11 +477,19 @@ function getRelevantIssues(error: ZodError, path: Array) {
return relevantIssues;
}
-function isMissing(issue: ZodIssue, path: Array) {
+function isMissing({
+ issue,
+ objPath,
+ rootData,
+}: {
+ issue: ZodIssue;
+ objPath: Array;
+ rootData: unknown;
+}) {
if (
issue.code === ZodIssueCode.invalid_type &&
issue.received === "undefined" &&
- issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
+ issue.path.slice(0, issue.path.length - 1).join(".") === objPath.join(".")
) {
return true;
}
@@ -439,7 +497,16 @@ function isMissing(issue: ZodIssue, path: Array) {
if (
issue.code === ZodIssueCode.invalid_literal &&
typeof issue.received === "undefined" &&
- issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
+ issue.path.slice(0, issue.path.length - 1).join(".") === objPath.join(".")
+ ) {
+ return true;
+ }
+
+ if (
+ issue.code === ZodIssueCode.invalid_union_discriminator &&
+ issue.path.slice(0, issue.path.length - 1).join(".") ===
+ objPath.join(".") &&
+ typeof getValueAtPath(rootData, issue.path) === "undefined"
) {
return true;
}
@@ -462,6 +529,7 @@ function Line({
onToggleTruncate,
toggleButtonRef,
truncated,
+ rootData,
}: {
num: number;
value?: unknown;
@@ -477,8 +545,9 @@ function Line({
onToggleTruncate?: () => void;
toggleButtonRef?: React.RefObject;
truncated?: boolean;
+ rootData: unknown;
}) {
- const issues = error ? getRelevantIssues(error, path || []) : [];
+ const issues = error ? getRelevantIssues({ error, path, rootData }) : [];
const issue = issues[0];
const unionError =
error &&
@@ -499,13 +568,14 @@ function Line({
style={{
padding: "4px",
paddingRight: "8px",
+ width: "52px",
backgroundColor: theme.lineNumberBackground,
- width: "40px",
display: "inline-block",
textAlign: "right",
fontFamily: "monospace",
userSelect: "none",
color: theme.lineNumber,
+ boxSizing: "border-box",
}}
>
{num}
@@ -518,6 +588,7 @@ function Line({
fontFamily: "monospace",
tabSize: "24px",
margin: 0,
+ boxSizing: "border-box",
}}
>
{/* INDENTATION */}
@@ -558,6 +629,7 @@ function Line({
ref={toggleButtonRef}
aria-label={truncated ? "Expand" : "Collapse"}
style={{
+ boxSizing: "border-box",
appearance: "none",
background: "none",
border: "none",
@@ -575,7 +647,12 @@ function Line({
}}
>
{/* Only show // when copying / pasting text. This is so the JSON can still be parsed (if using jsonc) */}
@@ -621,7 +698,11 @@ function Line({
/>
{`: `}
{unionError
- ? getRelevantIssues(unionError, path)[0]?.message
+ ? getRelevantIssues({
+ error: unionError,
+ path,
+ rootData,
+ })[0]?.message
: undefined}
>
)}
@@ -801,3 +882,18 @@ function findLastIndex(
return -1;
}
+
+function getValueAtPath(data: unknown, path: Array) {
+ let value = data;
+ for (const pathPart of path) {
+ if (typeof value === "object" && value) {
+ if (pathPart in value) {
+ // @ts-expect-error Not sure how to narrow this so TS is okay
+ value = value[pathPart];
+ } else {
+ return undefined;
+ }
+ }
+ }
+ return value;
+}
diff --git a/tsconfig.cjs.json b/packages/zod-error-viewer/tsconfig.cjs.json
similarity index 100%
rename from tsconfig.cjs.json
rename to packages/zod-error-viewer/tsconfig.cjs.json
diff --git a/tsconfig.esm.json b/packages/zod-error-viewer/tsconfig.esm.json
similarity index 100%
rename from tsconfig.esm.json
rename to packages/zod-error-viewer/tsconfig.esm.json
diff --git a/tsconfig.json b/packages/zod-error-viewer/tsconfig.json
similarity index 100%
rename from tsconfig.json
rename to packages/zod-error-viewer/tsconfig.json
diff --git a/packages/zod-error-viewer/vite.config.ts b/packages/zod-error-viewer/vite.config.ts
new file mode 100644
index 0000000..9cc50ea
--- /dev/null
+++ b/packages/zod-error-viewer/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 25eebe5..b46737e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,105 +4,193 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
-dependencies:
- zod:
- specifier: '>=3'
- version: 3.23.8
-
-devDependencies:
- '@chromatic-com/storybook':
- specifier: ^1.5.0
- version: 1.5.0(react@18.3.1)
- '@storybook/addon-essentials':
- specifier: ^8.1.5
- version: 8.1.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)
- '@storybook/addon-interactions':
- specifier: ^8.1.5
- version: 8.1.5(vitest@1.6.0)
- '@storybook/addon-links':
- specifier: ^8.1.5
- version: 8.1.5(react@18.3.1)
- '@storybook/blocks':
- specifier: ^8.1.5
- version: 8.1.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)
- '@storybook/react':
- specifier: ^8.1.5
- version: 8.1.5(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5)
- '@storybook/react-vite':
- specifier: ^8.1.5
- version: 8.1.5(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5)(vite@5.2.12)
- '@storybook/test':
- specifier: ^8.1.5
- version: 8.1.5(vitest@1.6.0)
- '@storybook/theming':
- specifier: ^8.1.5
- version: 8.1.5(react-dom@18.3.1)(react@18.3.1)
- '@testing-library/react':
- specifier: ^15.0.7
- version: 15.0.7(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)
- '@testing-library/user-event':
- specifier: ^14.5.2
- version: 14.5.2(@testing-library/dom@10.1.0)
- '@types/react':
- specifier: ^18.2.66
- version: 18.3.3
- '@types/react-dom':
- specifier: ^18.2.22
- version: 18.3.0
- '@typescript-eslint/eslint-plugin':
- specifier: ^7.2.0
- version: 7.11.0(@typescript-eslint/parser@7.11.0)(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser':
- specifier: ^7.2.0
- version: 7.11.0(eslint@8.57.0)(typescript@5.4.5)
- '@vitejs/plugin-react':
- specifier: ^4.2.1
- version: 4.3.0(vite@5.2.12)
- eslint:
- specifier: ^8.57.0
- version: 8.57.0
- eslint-config-prettier:
- specifier: ^9.1.0
- version: 9.1.0(eslint@8.57.0)
- eslint-plugin-react-hooks:
- specifier: ^4.6.0
- version: 4.6.2(eslint@8.57.0)
- eslint-plugin-react-refresh:
- specifier: ^0.4.6
- version: 0.4.7(eslint@8.57.0)
- eslint-plugin-storybook:
- specifier: ^0.8.0
- version: 0.8.0(eslint@8.57.0)(typescript@5.4.5)
- happy-dom:
- specifier: ^14.12.0
- version: 14.12.0
- husky:
- specifier: ^9.0.11
- version: 9.0.11
- lint-staged:
- specifier: ^15.2.5
- version: 15.2.5
- prettier:
- specifier: 3.3.0
- version: 3.3.0
- react:
- specifier: ^18.2.0
- version: 18.3.1
- react-dom:
- specifier: ^18.2.0
- version: 18.3.1(react@18.3.1)
- storybook:
- specifier: ^8.1.5
- version: 8.1.5(react-dom@18.3.1)(react@18.3.1)
- typescript:
- specifier: ^5.2.2
- version: 5.4.5
- vite:
- specifier: ^5.2.0
- version: 5.2.12
- vitest:
- specifier: ^1.6.0
- version: 1.6.0(happy-dom@14.12.0)
+importers:
+
+ .:
+ devDependencies:
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^7.2.0
+ version: 7.11.0(@typescript-eslint/parser@7.11.0)(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/parser':
+ specifier: ^7.2.0
+ version: 7.11.0(eslint@8.57.0)(typescript@5.4.5)
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.3.0(vite@5.2.12)
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.0(eslint@8.57.0)
+ eslint-plugin-react-hooks:
+ specifier: ^4.6.0
+ version: 4.6.2(eslint@8.57.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.6
+ version: 0.4.7(eslint@8.57.0)
+ eslint-plugin-storybook:
+ specifier: ^0.8.0
+ version: 0.8.0(eslint@8.57.0)(typescript@5.4.5)
+ husky:
+ specifier: ^9.0.11
+ version: 9.0.11
+ lint-staged:
+ specifier: ^15.2.5
+ version: 15.2.5
+ prettier:
+ specifier: 3.3.0
+ version: 3.3.0
+
+ packages/docs-site:
+ dependencies:
+ '@codemirror/lang-javascript':
+ specifier: ^6.2.2
+ version: 6.2.2
+ '@uiw/react-codemirror':
+ specifier: ^4.22.2
+ version: 4.22.2(@babel/runtime@7.24.6)(@codemirror/autocomplete@6.16.2)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.27.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ zod:
+ specifier: '>=3'
+ version: 3.23.8
+ zod-error-viewer:
+ specifier: workspace:*
+ version: link:../zod-error-viewer
+ devDependencies:
+ '@types/react':
+ specifier: ^18.2.66
+ version: 18.3.3
+ '@types/react-dom':
+ specifier: ^18.2.22
+ version: 18.3.0
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.3.0(vite@5.2.12)
+ typescript:
+ specifier: ^5.2.2
+ version: 5.4.5
+ vite:
+ specifier: ^5.2.0
+ version: 5.2.12
+
+ packages/docs-site-js:
+ dependencies:
+ '@codemirror/lang-javascript':
+ specifier: ^6.2.2
+ version: 6.2.2
+ '@uiw/react-codemirror':
+ specifier: ^4.22.2
+ version: 4.22.2(@babel/runtime@7.24.6)(@codemirror/autocomplete@6.16.2)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.27.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ zod:
+ specifier: '>=3'
+ version: 3.23.8
+ zod-error-viewer:
+ specifier: workspace:*
+ version: link:../zod-error-viewer
+ devDependencies:
+ '@types/react':
+ specifier: ^18.2.66
+ version: 18.3.3
+ '@types/react-dom':
+ specifier: ^18.2.22
+ version: 18.3.0
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.3.0(vite@5.2.12)
+ vite:
+ specifier: ^5.2.0
+ version: 5.2.12
+
+ packages/zod-error-viewer:
+ dependencies:
+ zod:
+ specifier: '>=3'
+ version: 3.23.8
+ devDependencies:
+ '@chromatic-com/storybook':
+ specifier: ^1.5.0
+ version: 1.5.0(react@18.3.1)
+ '@codemirror/lang-javascript':
+ specifier: ^6.2.2
+ version: 6.2.2
+ '@storybook/addon-essentials':
+ specifier: ^8.1.5
+ version: 8.1.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)
+ '@storybook/addon-interactions':
+ specifier: ^8.1.5
+ version: 8.1.5(vitest@1.6.0)
+ '@storybook/addon-links':
+ specifier: ^8.1.5
+ version: 8.1.5(react@18.3.1)
+ '@storybook/blocks':
+ specifier: ^8.1.5
+ version: 8.1.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)
+ '@storybook/manager-api':
+ specifier: ^8.1.6
+ version: 8.1.6(react-dom@18.3.1)(react@18.3.1)
+ '@storybook/react':
+ specifier: ^8.1.5
+ version: 8.1.5(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5)
+ '@storybook/react-vite':
+ specifier: ^8.1.5
+ version: 8.1.5(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5)(vite@5.2.12)
+ '@storybook/test':
+ specifier: ^8.1.5
+ version: 8.1.5(vitest@1.6.0)
+ '@storybook/theming':
+ specifier: ^8.1.5
+ version: 8.1.5(react-dom@18.3.1)(react@18.3.1)
+ '@testing-library/react':
+ specifier: ^15.0.7
+ version: 15.0.7(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)
+ '@testing-library/user-event':
+ specifier: ^14.5.2
+ version: 14.5.2(@testing-library/dom@10.1.0)
+ '@types/react':
+ specifier: ^18.2.66
+ version: 18.3.3
+ '@types/react-dom':
+ specifier: ^18.2.22
+ version: 18.3.0
+ '@uiw/react-codemirror':
+ specifier: ^4.22.2
+ version: 4.22.2(@babel/runtime@7.24.6)(@codemirror/autocomplete@6.16.2)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.27.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1)
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.3.0(vite@5.2.12)
+ happy-dom:
+ specifier: ^14.12.0
+ version: 14.12.0
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ storybook:
+ specifier: ^8.1.5
+ version: 8.1.5(react-dom@18.3.1)(react@18.3.1)
+ typescript:
+ specifier: ^5.2.2
+ version: 5.4.5
+ vite:
+ specifier: ^5.2.0
+ version: 5.2.12
+ vitest:
+ specifier: ^1.6.0
+ version: 1.6.0(happy-dom@14.12.0)
packages:
@@ -1375,7 +1463,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.14.1
- dev: true
/@babel/template@7.24.6:
resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==}
@@ -1432,6 +1519,80 @@ packages:
- react
dev: true
+ /@codemirror/autocomplete@6.16.2(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0)(@lezer/common@1.2.1):
+ resolution: {integrity: sha512-MjfDrHy0gHKlPWsvSsikhO1+BOh+eBHNgfH1OXs1+DAf30IonQldgMM3kxLDTG9ktE7kDLaA1j/l7KMPA4KNfw==}
+ peerDependencies:
+ '@codemirror/language': ^6.0.0
+ '@codemirror/state': ^6.0.0
+ '@codemirror/view': ^6.0.0
+ '@lezer/common': ^1.0.0
+ dependencies:
+ '@codemirror/language': 6.10.2
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ '@lezer/common': 1.2.1
+
+ /@codemirror/commands@6.6.0:
+ resolution: {integrity: sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==}
+ dependencies:
+ '@codemirror/language': 6.10.2
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ '@lezer/common': 1.2.1
+
+ /@codemirror/lang-javascript@6.2.2:
+ resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==}
+ dependencies:
+ '@codemirror/autocomplete': 6.16.2(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0)(@lezer/common@1.2.1)
+ '@codemirror/language': 6.10.2
+ '@codemirror/lint': 6.8.0
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ '@lezer/common': 1.2.1
+ '@lezer/javascript': 1.4.16
+
+ /@codemirror/language@6.10.2:
+ resolution: {integrity: sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==}
+ dependencies:
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ '@lezer/common': 1.2.1
+ '@lezer/highlight': 1.2.0
+ '@lezer/lr': 1.4.1
+ style-mod: 4.1.2
+
+ /@codemirror/lint@6.8.0:
+ resolution: {integrity: sha512-lsFofvaw0lnPRJlQylNsC4IRt/1lI4OD/yYslrSGVndOJfStc58v+8p9dgGiD90ktOfL7OhBWns1ZETYgz0EJA==}
+ dependencies:
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ crelt: 1.0.6
+
+ /@codemirror/search@6.5.6:
+ resolution: {integrity: sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==}
+ dependencies:
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ crelt: 1.0.6
+
+ /@codemirror/state@6.4.1:
+ resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==}
+
+ /@codemirror/theme-one-dark@6.1.2:
+ resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
+ dependencies:
+ '@codemirror/language': 6.10.2
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ '@lezer/highlight': 1.2.0
+
+ /@codemirror/view@6.27.0:
+ resolution: {integrity: sha512-8kqX1sHbVW1lVzWwrjAbh4dR7eKhV8eIQ952JKaBXOoXE04WncoqCy4DMU701LSrPZ3N2Q4zsTawz7GQ+2mrUw==}
+ dependencies:
+ '@codemirror/state': 6.4.1
+ style-mod: 4.1.2
+ w3c-keyname: 2.2.8
+
/@colors/colors@1.5.0:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
@@ -1786,6 +1947,26 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
+ /@lezer/common@1.2.1:
+ resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
+
+ /@lezer/highlight@1.2.0:
+ resolution: {integrity: sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==}
+ dependencies:
+ '@lezer/common': 1.2.1
+
+ /@lezer/javascript@1.4.16:
+ resolution: {integrity: sha512-84UXR3N7s11MPQHWgMnjb9571fr19MmXnr5zTv2XX0gHXXUvW3uPJ8GCjKrfTXmSdfktjRK0ayKklw+A13rk4g==}
+ dependencies:
+ '@lezer/common': 1.2.1
+ '@lezer/highlight': 1.2.0
+ '@lezer/lr': 1.4.1
+
+ /@lezer/lr@1.4.1:
+ resolution: {integrity: sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==}
+ dependencies:
+ '@lezer/common': 1.2.1
+
/@mdx-js/react@3.0.1(@types/react@18.3.3)(react@18.3.1):
resolution: {integrity: sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==}
peerDependencies:
@@ -2538,6 +2719,16 @@ packages:
tiny-invariant: 1.3.3
dev: true
+ /@storybook/channels@8.1.6:
+ resolution: {integrity: sha512-CzDnP6qfI8OC8pGUk+wPUzLPYcKhX8XbriF2gBtwl6qVM8YfkHP2mLTiDYDwBIi0rLuUbSm/SpILXQ/ouOHOGw==}
+ dependencies:
+ '@storybook/client-logger': 8.1.6
+ '@storybook/core-events': 8.1.6
+ '@storybook/global': 5.0.0
+ telejson: 7.2.0
+ tiny-invariant: 1.3.3
+ dev: true
+
/@storybook/cli@8.1.5(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-VEYluZEMleNEnD5wTD90KTh03pwjvQwEEmzHAJQJdLbWTAcgBxZ3Gb45nbUPauSqBL+HdJx0QXF8Ielk+iBttw==}
hasBin: true
@@ -2594,6 +2785,12 @@ packages:
'@storybook/global': 5.0.0
dev: true
+ /@storybook/client-logger@8.1.6:
+ resolution: {integrity: sha512-QfSoUxS1rmrBzO7o99og9g+Gkm7sTmU5ZOpTkjszjlRqfV6/77eUnUOzUikej4LqPLmlJV5fqGuvoP0aNVksDw==}
+ dependencies:
+ '@storybook/global': 5.0.0
+ dev: true
+
/@storybook/codemod@8.1.5:
resolution: {integrity: sha512-eGoYozT2XPfsIFrzm4cJo9tRTX0yuK1y4uTYmKvnomezHu5kiY8qo2fUzQa5DHxiAzRDTpGlQTzb0PsxHOxYoA==}
dependencies:
@@ -2689,6 +2886,13 @@ packages:
ts-dedent: 2.2.0
dev: true
+ /@storybook/core-events@8.1.6:
+ resolution: {integrity: sha512-DaIVe4TUp/7uQdSJYGmJv9S/S364tSgZ3S3dZ1vsf1rgoUbCp5kTBtcd/fcqgukMPREgCgO9oDhmemI3SLAqzw==}
+ dependencies:
+ '@storybook/csf': 0.1.7
+ ts-dedent: 2.2.0
+ dev: true
+
/@storybook/core-server@8.1.5(prettier@3.3.0)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-y16W2sg5KIHG6qgbd+a0nBUYHAgiUpPDFF7cdcIpbeOIoqFn+6ECp93MVefukumiSj3sQiJFU/tSm2A8apGltw==}
dependencies:
@@ -2856,6 +3060,29 @@ packages:
- react-dom
dev: true
+ /@storybook/manager-api@8.1.6(react-dom@18.3.1)(react@18.3.1):
+ resolution: {integrity: sha512-L/s1FdFh/P+eFmQwLtFtJHwFJrGD9H7nauaQlKJOrU3GeXfjBjtlAZQF0Q6B4ZTGxwZjQrzShpt/0yKc6gymtw==}
+ dependencies:
+ '@storybook/channels': 8.1.6
+ '@storybook/client-logger': 8.1.6
+ '@storybook/core-events': 8.1.6
+ '@storybook/csf': 0.1.7
+ '@storybook/global': 5.0.0
+ '@storybook/icons': 1.2.9(react-dom@18.3.1)(react@18.3.1)
+ '@storybook/router': 8.1.6
+ '@storybook/theming': 8.1.6(react-dom@18.3.1)(react@18.3.1)
+ '@storybook/types': 8.1.6
+ dequal: 2.0.3
+ lodash: 4.17.21
+ memoizerific: 1.11.3
+ store2: 2.14.3
+ telejson: 7.2.0
+ ts-dedent: 2.2.0
+ transitivePeerDependencies:
+ - react
+ - react-dom
+ dev: true
+
/@storybook/manager@8.1.5:
resolution: {integrity: sha512-qMYwD1cXW0hJ3pMmdMlbsqktVBlsjsqwMH5PBzAN4FoWiCQ/yHeAnDXRUgFFaLcORS72h9H/cQuJ+p//RdeURg==}
dev: true
@@ -2978,6 +3205,14 @@ packages:
qs: 6.12.1
dev: true
+ /@storybook/router@8.1.6:
+ resolution: {integrity: sha512-tvuhB2uXHEKK640Epm1SqVzPhQ9lXYfF7FX6FleJgVYEvZpJpNTD4RojedQoLI6SUUSXNy1Vs2QV26VM0XIPHQ==}
+ dependencies:
+ '@storybook/client-logger': 8.1.6
+ memoizerific: 1.11.3
+ qs: 6.12.1
+ dev: true
+
/@storybook/telemetry@8.1.5(prettier@3.3.0):
resolution: {integrity: sha512-QbB1Ox7oBaCvIF2TacFjPLi1XYeHxSPeZUuFXeE+tSMdvvWZzYLnXfj/oISmV6Q+X5VZfyJVMrZ2LfeW9CuFNg==}
dependencies:
@@ -3035,6 +3270,25 @@ packages:
react-dom: 18.3.1(react@18.3.1)
dev: true
+ /@storybook/theming@8.1.6(react-dom@18.3.1)(react@18.3.1):
+ resolution: {integrity: sha512-0Cl/7/0z2WSfXhZ9XSw6rgEjb0fXac7jfktieX0vYo1YckrNpWFRQP9NCpVPAcYZaFLlRSOqYark6CLoutEsIg==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ dependencies:
+ '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1)
+ '@storybook/client-logger': 8.1.6
+ '@storybook/global': 5.0.0
+ memoizerific: 1.11.3
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ dev: true
+
/@storybook/types@8.1.5:
resolution: {integrity: sha512-/PfAZh1xtXN2MvAZZKpiL/nPkC3bZj8BQ7P7z5a/aQarP+y7qdXuoitYQ6oOH3rkaiYywmkWzA/y4iW70KXLKg==}
dependencies:
@@ -3043,6 +3297,14 @@ packages:
file-system-cache: 2.3.0
dev: true
+ /@storybook/types@8.1.6:
+ resolution: {integrity: sha512-cWpS9+x1pxCO39spR8QmumMK2ub2p5cvMtrRvWaIjBFPbCwm2CvjBXFWIra2veBCZTxUKJ9VWxvi7pzRHjN/nw==}
+ dependencies:
+ '@storybook/channels': 8.1.6
+ '@types/express': 4.17.21
+ file-system-cache: 2.3.0
+ dev: true
+
/@testing-library/dom@10.1.0:
resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==}
engines: {node: '>=18'}
@@ -3552,6 +3814,51 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
+ /@uiw/codemirror-extensions-basic-setup@4.22.2(@codemirror/autocomplete@6.16.2)(@codemirror/commands@6.6.0)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0):
+ resolution: {integrity: sha512-zcHGkldLFN3cGoI5XdOGAkeW24yaAgrDEYoyPyWHODmPiNwybQQoZGnH3qUdzZwUaXtAcLWoAeOPzfNRW2yGww==}
+ peerDependencies:
+ '@codemirror/autocomplete': '>=6.0.0'
+ '@codemirror/commands': '>=6.0.0'
+ '@codemirror/language': '>=6.0.0'
+ '@codemirror/lint': '>=6.0.0'
+ '@codemirror/search': '>=6.0.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+ dependencies:
+ '@codemirror/autocomplete': 6.16.2(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0)(@lezer/common@1.2.1)
+ '@codemirror/commands': 6.6.0
+ '@codemirror/language': 6.10.2
+ '@codemirror/lint': 6.8.0
+ '@codemirror/search': 6.5.6
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+
+ /@uiw/react-codemirror@4.22.2(@babel/runtime@7.24.6)(@codemirror/autocomplete@6.16.2)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.27.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1):
+ resolution: {integrity: sha512-okCSl+WJG63gRx8Fdz7v0C6RakBQnbb3pHhuzIgDB+fwhipgFodSnu2n9oOsQesJ5YQ7mSOcKMgX0JEsu4nnfQ==}
+ peerDependencies:
+ '@babel/runtime': '>=7.11.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/theme-one-dark': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+ codemirror: '>=6.0.0'
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+ dependencies:
+ '@babel/runtime': 7.24.6
+ '@codemirror/commands': 6.6.0
+ '@codemirror/state': 6.4.1
+ '@codemirror/theme-one-dark': 6.1.2
+ '@codemirror/view': 6.27.0
+ '@uiw/codemirror-extensions-basic-setup': 4.22.2(@codemirror/autocomplete@6.16.2)(@codemirror/commands@6.6.0)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0)
+ codemirror: 6.0.1(@lezer/common@1.2.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ transitivePeerDependencies:
+ - '@codemirror/autocomplete'
+ - '@codemirror/language'
+ - '@codemirror/lint'
+ - '@codemirror/search'
+
/@ungap/structured-clone@1.2.0:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
@@ -4176,6 +4483,19 @@ packages:
engines: {node: '>=0.8'}
dev: true
+ /codemirror@6.0.1(@lezer/common@1.2.1):
+ resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
+ dependencies:
+ '@codemirror/autocomplete': 6.16.2(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.27.0)(@lezer/common@1.2.1)
+ '@codemirror/commands': 6.6.0
+ '@codemirror/language': 6.10.2
+ '@codemirror/lint': 6.8.0
+ '@codemirror/search': 6.5.6
+ '@codemirror/state': 6.4.1
+ '@codemirror/view': 6.27.0
+ transitivePeerDependencies:
+ - '@lezer/common'
+
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@@ -4285,6 +4605,9 @@ packages:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: true
+ /crelt@1.0.6:
+ resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
+
/cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
@@ -5766,7 +6089,6 @@ packages:
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
- dev: true
/js-tokens@9.0.0:
resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
@@ -5998,7 +6320,6 @@ packages:
hasBin: true
dependencies:
js-tokens: 4.0.0
- dev: true
/loupe@2.3.7:
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
@@ -6803,7 +7124,6 @@ packages:
loose-envify: 1.4.0
react: 18.3.1
scheduler: 0.23.2
- dev: true
/react-element-to-jsx-string@15.0.0(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==}
@@ -6896,7 +7216,6 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
loose-envify: 1.4.0
- dev: true
/read-pkg-up@7.0.1:
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
@@ -6977,7 +7296,6 @@ packages:
/regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
- dev: true
/regenerator-transform@0.15.2:
resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
@@ -7148,7 +7466,6 @@ packages:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
dependencies:
loose-envify: 1.4.0
- dev: true
/semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
@@ -7481,6 +7798,9 @@ packages:
js-tokens: 9.0.0
dev: true
+ /style-mod@4.1.2:
+ resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
+
/supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@@ -8003,6 +8323,9 @@ packages:
- terser
dev: true
+ /w3c-keyname@2.2.8:
+ resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
+
/watchpack@2.4.1:
resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==}
engines: {node: '>=10.13.0'}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..dee51e9
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+packages:
+ - "packages/*"