commit 9178ea08ac9bb95480e42831d51294c93babf82b Author: Khairul Hidayat <me@khairul.my.id> Date: Mon Sep 2 23:59:12 2024 +0700 initial commit diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs new file mode 100644 index 0000000..d6c9537 --- /dev/null +++ b/frontend/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..e1cdc89 --- /dev/null +++ b/frontend/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', './tsconfig.app.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/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..4a283d5 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <link rel="icon" type="image/svg+xml" href="/vite.svg" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Kidokoding</title> + </head> + <body> + <div id="root"></div> + <script type="module" src="/src/main.tsx"></script> + </body> +</html> diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..33cdf55 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,46 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@monaco-editor/react": "^4.6.0", + "@radix-ui/react-slot": "^1.1.0", + "clsx": "^2.1.1", + "console-feed": "^3.6.0", + "lucide-react": "^0.417.0", + "nanoid": "^5.0.7", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.25.1", + "tailwind-merge": "^2.4.0", + "tailwind-variants": "^0.2.1", + "zod": "^3.23.8", + "zustand": "^4.5.4" + }, + "devDependencies": { + "@tailwindcss/typography": "^0.5.13", + "@types/node": "^22.0.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "@vitejs/plugin-react-swc": "^3.5.0", + "autoprefixer": "^10.4.19", + "daisyui": "^4.12.10", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "monaco-editor": "^0.50.0", + "postcss": "^8.4.40", + "tailwindcss": "^3.4.7", + "typescript": "^5.2.2", + "vite": "^5.3.4" + } +} diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml new file mode 100644 index 0000000..71c2a7d --- /dev/null +++ b/frontend/pnpm-lock.yaml @@ -0,0 +1,3222 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@monaco-editor/react': + specifier: ^4.6.0 + version: 4.6.0(monaco-editor@0.50.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': + specifier: ^1.1.0 + version: 1.1.0(@types/react@18.3.3)(react@18.3.1) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + console-feed: + specifier: ^3.6.0 + version: 3.6.0(jquery@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + lucide-react: + specifier: ^0.417.0 + version: 0.417.0(react@18.3.1) + nanoid: + specifier: ^5.0.7 + version: 5.0.7 + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + react-router-dom: + specifier: ^6.25.1 + version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + tailwind-merge: + specifier: ^2.4.0 + version: 2.4.0 + tailwind-variants: + specifier: ^0.2.1 + version: 0.2.1(tailwindcss@3.4.7) + zod: + specifier: ^3.23.8 + version: 3.23.8 + zustand: + specifier: ^4.5.4 + version: 4.5.4(@types/react@18.3.3)(react@18.3.1) + devDependencies: + '@tailwindcss/typography': + specifier: ^0.5.13 + version: 0.5.13(tailwindcss@3.4.7) + '@types/node': + specifier: ^22.0.0 + version: 22.0.0 + '@types/react': + specifier: ^18.3.3 + version: 18.3.3 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.0 + '@typescript-eslint/eslint-plugin': + specifier: ^7.15.0 + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/parser': + specifier: ^7.15.0 + version: 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@vitejs/plugin-react-swc': + specifier: ^3.5.0 + version: 3.7.0(vite@5.3.5(@types/node@22.0.0)) + autoprefixer: + specifier: ^10.4.19 + version: 10.4.19(postcss@8.4.40) + daisyui: + specifier: ^4.12.10 + version: 4.12.10(postcss@8.4.40) + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-plugin-react-hooks: + specifier: ^4.6.2 + version: 4.6.2(eslint@8.57.0) + eslint-plugin-react-refresh: + specifier: ^0.4.7 + version: 0.4.9(eslint@8.57.0) + monaco-editor: + specifier: ^0.50.0 + version: 0.50.0 + postcss: + specifier: ^8.4.40 + version: 8.4.40 + tailwindcss: + specifier: ^3.4.7 + version: 3.4.7 + typescript: + specifier: ^5.2.2 + version: 5.5.4 + vite: + specifier: ^5.3.4 + version: 5.3.5(@types/node@22.0.0) + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.25.0': + resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.25.0': + resolution: {integrity: sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.25.0': + resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.25.0': + resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.2': + resolution: {integrity: sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.25.2': + resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} + engines: {node: '>=6.9.0'} + + '@emotion/cache@10.0.29': + resolution: {integrity: sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==} + + '@emotion/core@10.3.1': + resolution: {integrity: sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==} + peerDependencies: + react: '>=16.3.0' + + '@emotion/css@10.0.27': + resolution: {integrity: sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==} + + '@emotion/hash@0.8.0': + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + + '@emotion/is-prop-valid@0.8.8': + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + + '@emotion/memoize@0.7.4': + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + + '@emotion/serialize@0.11.16': + resolution: {integrity: sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==} + + '@emotion/sheet@0.9.4': + resolution: {integrity: sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==} + + '@emotion/styled-base@10.3.0': + resolution: {integrity: sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==} + peerDependencies: + '@emotion/core': ^10.0.28 + react: '>=16.3.0' + + '@emotion/styled@10.3.0': + resolution: {integrity: sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==} + peerDependencies: + '@emotion/core': ^10.0.27 + react: '>=16.3.0' + + '@emotion/stylis@0.8.5': + resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} + + '@emotion/unitless@0.7.5': + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + + '@emotion/utils@0.11.3': + resolution: {integrity: sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==} + + '@emotion/weak-memoize@0.2.5': + resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@monaco-editor/loader@1.4.0': + resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} + peerDependencies: + monaco-editor: '>= 0.21.0 < 1' + + '@monaco-editor/react@4.6.0': + resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@radix-ui/react-compose-refs@1.1.0': + resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-slot@1.1.0': + resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@remix-run/router@1.18.0': + resolution: {integrity: sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==} + engines: {node: '>=14.0.0'} + + '@rollup/rollup-android-arm-eabi@4.19.1': + resolution: {integrity: sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.19.1': + resolution: {integrity: sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.19.1': + resolution: {integrity: sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.19.1': + resolution: {integrity: sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.19.1': + resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.19.1': + resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.19.1': + resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.19.1': + resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.19.1': + resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.19.1': + resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.19.1': + resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.19.1': + resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.19.1': + resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.19.1': + resolution: {integrity: sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.19.1': + resolution: {integrity: sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.19.1': + resolution: {integrity: sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==} + cpu: [x64] + os: [win32] + + '@swc/core-darwin-arm64@1.7.3': + resolution: {integrity: sha512-CTkHa6MJdov9t41vuV2kmQIMu+Q19LrEHGIR/UiJYH06SC/sOu35ZZH8DyfLp9ZoaCn21gwgWd61ixOGQlwzTw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.7.3': + resolution: {integrity: sha512-mun623y6rCoZ2EFIYfIRqXYRFufJOopoYSJcxYhZUrfTpAvQ1zLngjQpWCUU1krggXR2U0PQj+ls0DfXUTraNg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.7.3': + resolution: {integrity: sha512-4Jz4UcIcvZNMp9qoHbBx35bo3rjt8hpYLPqnR4FFq6gkAsJIMFC56UhRZwdEQoDuYiOFMBnnrsg31Fyo6YQypA==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.7.3': + resolution: {integrity: sha512-p+U/M/oqV7HC4erQ5TVWHhJU1984QD+wQBPxslAYq751bOQGm0R/mXK42GjugqjnR6yYrAiwKKbpq4iWVXNePA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.7.3': + resolution: {integrity: sha512-s6VzyaJwaRGTi2mz2h6Ywxfmgpkc69IxhuMzl+sl34plH0V0RgnZDm14HoCGIKIzRk4+a2EcBV1ZLAfWmPACQg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.7.3': + resolution: {integrity: sha512-IrFY48C356Z2dU2pjYg080yvMXzmSV3Lmm/Wna4cfcB1nkVLjWsuYwwRAk9CY7E19c+q8N1sMNggubAUDYoX2g==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.7.3': + resolution: {integrity: sha512-qoLgxBlBnnyUEDu5vmRQqX90h9jldU1JXI96e6eh2d1gJyKRA0oSK7xXmTzorv1fGHiHulv9qiJOUG+g6uzJWg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.7.3': + resolution: {integrity: sha512-OAd7jVVJ7nb0Ev80VAa1aeK+FldPeC4eZ35H4Qn6EICzIz0iqJo2T33qLKkSZiZEBKSoF4KcwrqYfkjLOp5qWg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.7.3': + resolution: {integrity: sha512-31+Le1NyfSnILFV9+AhxfFOG0DK0272MNhbIlbcv4w/iqpjkhaOnNQnLsYJD1Ow7lTX1MtIZzTjOhRlzSviRWg==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.7.3': + resolution: {integrity: sha512-jVQPbYrwcuueI4QB0fHC29SVrkFOBcfIspYDlgSoHnEz6tmLMqUy+txZUypY/ZH/KaK0HEY74JkzgbRC1S6LFQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.7.3': + resolution: {integrity: sha512-HHAlbXjWI6Kl9JmmUW1LSygT1YbblXgj2UvvDzMkTBPRzYMhW6xchxdO8HbtMPtFYRt/EQq9u1z7j4ttRSrFsA==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '*' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.12': + resolution: {integrity: sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==} + + '@tailwindcss/typography@0.5.13': + resolution: {integrity: sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/node@22.0.0': + resolution: {integrity: sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/prop-types@15.7.12': + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + '@types/react-dom@18.3.0': + resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} + + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitejs/plugin-react-swc@3.7.0': + resolution: {integrity: sha512-yrknSb3Dci6svCd/qhHqhFPDSw0QtjumcqdKMoNNzmOl5lMXTTiqzjWtG4Qask2HdvvzaNgSunbQGet8/GrKdA==} + peerDependencies: + vite: ^4 || ^5 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + autoprefixer@10.4.19: + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + babel-plugin-emotion@10.2.2: + resolution: {integrity: sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==} + + babel-plugin-macros@2.8.0: + resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==} + + babel-plugin-syntax-jsx@6.18.0: + resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.2: + resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + caniuse-lite@1.0.30001645: + resolution: {integrity: sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + console-feed@3.6.0: + resolution: {integrity: sha512-eeMvRE2YkkLKhDJ16P5qEaM92tVLSI1DwqMBD5v7cmcvrU1WRGoKh4xpOAkzCqK3y/mAkqsMa8dDEafNi1uJ3w==} + peerDependencies: + react: ^15.x || ^16.x || ^17.x || ^18.x + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + cosmiconfig@6.0.0: + resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} + engines: {node: '>=8'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + css-selector-tokenizer@0.8.0: + resolution: {integrity: sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@2.6.21: + resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + culori@3.3.0: + resolution: {integrity: sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + daisyui@4.12.10: + resolution: {integrity: sha512-jp1RAuzbHhGdXmn957Z2XsTZStXGHzFfF0FgIOZj3Wv9sH7OZgLfXTRZNfKVYxltGUOBsG1kbWAdF5SrqjebvA==} + engines: {node: '>=16.9.0'} + + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.4: + resolution: {integrity: sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emotion-theming@10.3.0: + resolution: {integrity: sha512-mXiD2Oj7N9b6+h/dC6oLf9hwxbtKHQjoIqtodEyL8CpkN4F3V4IK/BT4D0C7zSs4BBFOu4UlPJbvvBLa88SGEA==} + peerDependencies: + '@emotion/core': ^10.0.27 + react: '>=16.3.0' + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + + eslint-plugin-react-refresh@0.4.9: + resolution: {integrity: sha512-QK49YrBAo5CLNLseZ7sZgvgTy21E6NEw22eZqc4teZfH8pxV3yXc9XXOYfUI6JNpw7mfHNkAeWtBxrTyykB6HA==} + peerDependencies: + eslint: '>=7' + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastparse@1.1.2: + resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + foreground-child@3.2.1: + resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} + engines: {node: '>=14'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.15.0: + resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} + engines: {node: '>= 0.4'} + + is-dom@1.1.0: + resolution: {integrity: sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-object@1.0.2: + resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-window@1.0.2: + resolution: {integrity: sha512-uj00kdXyZb9t9RcAUAwMZAnkBUwdYGhYlt7djMXhfyhUCzwNba50tIiBKR7q0l7tdoBtFVw/3JmLY6fI3rmZmg==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + jquery@3.7.1: + resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + linkifyjs@2.1.9: + resolution: {integrity: sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==} + peerDependencies: + jquery: '>= 1.11.0' + react: '>= 0.14.0' + react-dom: '>= 0.14.0' + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lucide-react@0.417.0: + resolution: {integrity: sha512-F/MDUHDter8YMZ7JKQpW/5/+v38tdaoShKX3e+opYsqfCnaHwn+5zz3+lBrMDFMNtSsvxtNpchLIaMpEfsi/4w==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + monaco-editor@0.50.0: + resolution: {integrity: sha512-8CclLCmrRRh+sul7C08BmPBP3P8wVWfBHomsTcndxg5NRCEPfu/mc2AGU8k37ajjDVXcXFc12ORAMUkmk+lkFA==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.0.7: + resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==} + engines: {node: ^18 || >=20} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + + postcss-selector-parser@6.1.1: + resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.40: + resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-inline-center@1.0.1: + resolution: {integrity: sha512-nMxG933OWuZET/CkvQTPBVEPNRI2zhfeeeiRqXKKzSdvIPHnHnDXZmh9KkRO2DDCjJFvZQ3KIe50lXaaxvnoNw==} + peerDependencies: + react: '*' + + react-inspector@5.1.1: + resolution: {integrity: sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==} + peerDependencies: + react: ^16.8.4 || ^17.0.0 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-router-dom@6.25.1: + resolution: {integrity: sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + react-router@6.25.1: + resolution: {integrity: sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rollup@4.19.1: + resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwind-merge@2.4.0: + resolution: {integrity: sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==} + + tailwind-variants@0.2.1: + resolution: {integrity: sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw==} + engines: {node: '>=16.x', pnpm: '>=7.x'} + peerDependencies: + tailwindcss: '*' + + tailwindcss@3.4.7: + resolution: {integrity: sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==} + engines: {node: '>=14.0.0'} + hasBin: true + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.11.1: + resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} + + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-sync-external-store@1.2.0: + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite@5.3.5: + resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.5.0: + resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zustand@4.5.4: + resolution: {integrity: sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + + '@babel/generator@7.25.0': + dependencies: + '@babel/types': 7.25.2 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.25.2 + '@babel/types': 7.25.2 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.24.8': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + + '@babel/parser@7.25.0': + dependencies: + '@babel/types': 7.25.2 + + '@babel/runtime@7.25.0': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.25.0': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.25.0 + '@babel/types': 7.25.2 + + '@babel/traverse@7.25.2': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.0 + '@babel/parser': 7.25.0 + '@babel/template': 7.25.0 + '@babel/types': 7.25.2 + debug: 4.3.6 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.25.2': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@emotion/cache@10.0.29': + dependencies: + '@emotion/sheet': 0.9.4 + '@emotion/stylis': 0.8.5 + '@emotion/utils': 0.11.3 + '@emotion/weak-memoize': 0.2.5 + + '@emotion/core@10.3.1(react@18.3.1)': + dependencies: + '@babel/runtime': 7.25.0 + '@emotion/cache': 10.0.29 + '@emotion/css': 10.0.27 + '@emotion/serialize': 0.11.16 + '@emotion/sheet': 0.9.4 + '@emotion/utils': 0.11.3 + react: 18.3.1 + transitivePeerDependencies: + - supports-color + + '@emotion/css@10.0.27': + dependencies: + '@emotion/serialize': 0.11.16 + '@emotion/utils': 0.11.3 + babel-plugin-emotion: 10.2.2 + transitivePeerDependencies: + - supports-color + + '@emotion/hash@0.8.0': {} + + '@emotion/is-prop-valid@0.8.8': + dependencies: + '@emotion/memoize': 0.7.4 + + '@emotion/memoize@0.7.4': {} + + '@emotion/serialize@0.11.16': + dependencies: + '@emotion/hash': 0.8.0 + '@emotion/memoize': 0.7.4 + '@emotion/unitless': 0.7.5 + '@emotion/utils': 0.11.3 + csstype: 2.6.21 + + '@emotion/sheet@0.9.4': {} + + '@emotion/styled-base@10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.25.0 + '@emotion/core': 10.3.1(react@18.3.1) + '@emotion/is-prop-valid': 0.8.8 + '@emotion/serialize': 0.11.16 + '@emotion/utils': 0.11.3 + react: 18.3.1 + + '@emotion/styled@10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@emotion/core': 10.3.1(react@18.3.1) + '@emotion/styled-base': 10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1) + babel-plugin-emotion: 10.2.2 + react: 18.3.1 + transitivePeerDependencies: + - supports-color + + '@emotion/stylis@0.8.5': {} + + '@emotion/unitless@0.7.5': {} + + '@emotion/utils@0.11.3': {} + + '@emotion/weak-memoize@0.2.5': {} + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.11.0': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.6 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.57.0': {} + + '@humanwhocodes/config-array@0.11.14': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.6 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@monaco-editor/loader@1.4.0(monaco-editor@0.50.0)': + dependencies: + monaco-editor: 0.50.0 + state-local: 1.0.7 + + '@monaco-editor/react@4.6.0(monaco-editor@0.50.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@monaco-editor/loader': 1.4.0(monaco-editor@0.50.0) + monaco-editor: 0.50.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.3)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-slot@1.1.0(@types/react@18.3.3)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.3 + + '@remix-run/router@1.18.0': {} + + '@rollup/rollup-android-arm-eabi@4.19.1': + optional: true + + '@rollup/rollup-android-arm64@4.19.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.19.1': + optional: true + + '@rollup/rollup-darwin-x64@4.19.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.19.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.19.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.19.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.19.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.19.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.19.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.19.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.19.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.19.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.19.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.19.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.19.1': + optional: true + + '@swc/core-darwin-arm64@1.7.3': + optional: true + + '@swc/core-darwin-x64@1.7.3': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.7.3': + optional: true + + '@swc/core-linux-arm64-gnu@1.7.3': + optional: true + + '@swc/core-linux-arm64-musl@1.7.3': + optional: true + + '@swc/core-linux-x64-gnu@1.7.3': + optional: true + + '@swc/core-linux-x64-musl@1.7.3': + optional: true + + '@swc/core-win32-arm64-msvc@1.7.3': + optional: true + + '@swc/core-win32-ia32-msvc@1.7.3': + optional: true + + '@swc/core-win32-x64-msvc@1.7.3': + optional: true + + '@swc/core@1.7.3': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.12 + optionalDependencies: + '@swc/core-darwin-arm64': 1.7.3 + '@swc/core-darwin-x64': 1.7.3 + '@swc/core-linux-arm-gnueabihf': 1.7.3 + '@swc/core-linux-arm64-gnu': 1.7.3 + '@swc/core-linux-arm64-musl': 1.7.3 + '@swc/core-linux-x64-gnu': 1.7.3 + '@swc/core-linux-x64-musl': 1.7.3 + '@swc/core-win32-arm64-msvc': 1.7.3 + '@swc/core-win32-ia32-msvc': 1.7.3 + '@swc/core-win32-x64-msvc': 1.7.3 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.12': + dependencies: + '@swc/counter': 0.1.3 + + '@tailwindcss/typography@0.5.13(tailwindcss@3.4.7)': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.7 + + '@types/estree@1.0.5': {} + + '@types/node@22.0.0': + dependencies: + undici-types: 6.11.1 + + '@types/parse-json@4.0.2': {} + + '@types/prop-types@15.7.12': {} + + '@types/react-dom@18.3.0': + dependencies: + '@types/react': 18.3.3 + + '@types/react@18.3.3': + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 + eslint: 8.57.0 + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + debug: 4.3.6 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + + '@ungap/structured-clone@1.2.0': {} + + '@vitejs/plugin-react-swc@3.7.0(vite@5.3.5(@types/node@22.0.0))': + dependencies: + '@swc/core': 1.7.3 + vite: 5.3.5(@types/node@22.0.0) + transitivePeerDependencies: + - '@swc/helpers' + + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn@8.12.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + array-union@2.1.0: {} + + autoprefixer@10.4.19(postcss@8.4.40): + dependencies: + browserslist: 4.23.2 + caniuse-lite: 1.0.30001645 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.1 + postcss: 8.4.40 + postcss-value-parser: 4.2.0 + + babel-plugin-emotion@10.2.2: + dependencies: + '@babel/helper-module-imports': 7.24.7 + '@emotion/hash': 0.8.0 + '@emotion/memoize': 0.7.4 + '@emotion/serialize': 0.11.16 + babel-plugin-macros: 2.8.0 + babel-plugin-syntax-jsx: 6.18.0 + convert-source-map: 1.9.0 + escape-string-regexp: 1.0.5 + find-root: 1.1.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + + babel-plugin-macros@2.8.0: + dependencies: + '@babel/runtime': 7.25.0 + cosmiconfig: 6.0.0 + resolve: 1.22.8 + + babel-plugin-syntax-jsx@6.18.0: {} + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.23.2: + dependencies: + caniuse-lite: 1.0.30001645 + electron-to-chromium: 1.5.4 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.2) + + callsites@3.1.0: {} + + camelcase-css@2.0.1: {} + + caniuse-lite@1.0.30001645: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + clsx@2.1.1: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + commander@4.1.1: {} + + concat-map@0.0.1: {} + + console-feed@3.6.0(jquery@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@emotion/core': 10.3.1(react@18.3.1) + '@emotion/styled': 10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1) + emotion-theming: 10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1) + linkifyjs: 2.1.9(jquery@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-inline-center: 1.0.1(react@18.3.1) + react-inspector: 5.1.1(react@18.3.1) + transitivePeerDependencies: + - jquery + - react-dom + - supports-color + + convert-source-map@1.9.0: {} + + cosmiconfig@6.0.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-selector-tokenizer@0.8.0: + dependencies: + cssesc: 3.0.0 + fastparse: 1.1.2 + + cssesc@3.0.0: {} + + csstype@2.6.21: {} + + csstype@3.1.3: {} + + culori@3.3.0: {} + + daisyui@4.12.10(postcss@8.4.40): + dependencies: + css-selector-tokenizer: 0.8.0 + culori: 3.3.0 + picocolors: 1.0.1 + postcss-js: 4.0.1(postcss@8.4.40) + transitivePeerDependencies: + - postcss + + debug@4.3.6: + dependencies: + ms: 2.1.2 + + deep-is@0.1.4: {} + + didyoumean@1.2.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.4: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emotion-theming@10.3.0(@emotion/core@10.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.25.0 + '@emotion/core': 10.3.1(react@18.3.1) + '@emotion/weak-memoize': 0.2.5 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.1.2: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-plugin-react-refresh@0.4.9(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint@8.57.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.6 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.6.1: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 3.4.3 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastparse@1.1.2: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-root@1.1.0: {} + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.3.1: {} + + foreground-child@3.2.1: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + fraction.js@4.3.7: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.2.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@11.12.0: {} + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + graphemer@1.4.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + ignore@5.3.1: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.15.0: + dependencies: + hasown: 2.0.2 + + is-dom@1.1.0: + dependencies: + is-object: 1.0.2 + is-window: 1.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-object@1.0.2: {} + + is-path-inside@3.0.3: {} + + is-window@1.0.2: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.6: {} + + jquery@3.7.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@2.5.2: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + linkifyjs@2.1.9(jquery@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + jquery: 3.7.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.castarray@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.merge@4.6.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} + + lucide-react@0.417.0(react@18.3.1): + dependencies: + react: 18.3.1 + + merge2@1.4.1: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + monaco-editor@0.50.0: {} + + ms@2.1.2: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.7: {} + + nanoid@5.0.7: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.18: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + package-json-from-dist@1.0.0: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-type@4.0.0: {} + + picocolors@1.0.1: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + + postcss-import@15.1.0(postcss@8.4.40): + dependencies: + postcss: 8.4.40 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.40): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.40 + + postcss-load-config@4.0.2(postcss@8.4.40): + dependencies: + lilconfig: 3.1.2 + yaml: 2.5.0 + optionalDependencies: + postcss: 8.4.40 + + postcss-nested@6.2.0(postcss@8.4.40): + dependencies: + postcss: 8.4.40 + postcss-selector-parser: 6.1.1 + + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@6.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.40: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + prelude-ls@1.2.1: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-inline-center@1.0.1(react@18.3.1): + dependencies: + react: 18.3.1 + + react-inspector@5.1.1(react@18.3.1): + dependencies: + '@babel/runtime': 7.25.0 + is-dom: 1.1.0 + prop-types: 15.8.1 + react: 18.3.1 + + react-is@16.13.1: {} + + react-router-dom@6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@remix-run/router': 1.18.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-router: 6.25.1(react@18.3.1) + + react-router@6.25.1(react@18.3.1): + dependencies: + '@remix-run/router': 1.18.0 + react: 18.3.1 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + regenerator-runtime@0.14.1: {} + + resolve-from@4.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup@4.19.1: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.19.1 + '@rollup/rollup-android-arm64': 4.19.1 + '@rollup/rollup-darwin-arm64': 4.19.1 + '@rollup/rollup-darwin-x64': 4.19.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.19.1 + '@rollup/rollup-linux-arm-musleabihf': 4.19.1 + '@rollup/rollup-linux-arm64-gnu': 4.19.1 + '@rollup/rollup-linux-arm64-musl': 4.19.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.19.1 + '@rollup/rollup-linux-riscv64-gnu': 4.19.1 + '@rollup/rollup-linux-s390x-gnu': 4.19.1 + '@rollup/rollup-linux-x64-gnu': 4.19.1 + '@rollup/rollup-linux-x64-musl': 4.19.1 + '@rollup/rollup-win32-arm64-msvc': 4.19.1 + '@rollup/rollup-win32-ia32-msvc': 4.19.1 + '@rollup/rollup-win32-x64-msvc': 4.19.1 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + semver@7.6.3: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + source-map-js@1.2.0: {} + + source-map@0.5.7: {} + + state-local@1.0.7: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-json-comments@3.1.1: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwind-merge@2.4.0: {} + + tailwind-variants@0.2.1(tailwindcss@3.4.7): + dependencies: + tailwind-merge: 2.4.0 + tailwindcss: 3.4.7 + + tailwindcss@3.4.7: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.7 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.1 + postcss: 8.4.40 + postcss-import: 15.1.0(postcss@8.4.40) + postcss-js: 4.0.1(postcss@8.4.40) + postcss-load-config: 4.0.2(postcss@8.4.40) + postcss-nested: 6.2.0(postcss@8.4.40) + postcss-selector-parser: 6.1.1 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + to-fast-properties@2.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@1.3.0(typescript@5.5.4): + dependencies: + typescript: 5.5.4 + + ts-interface-checker@0.1.13: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + typescript@5.5.4: {} + + undici-types@6.11.1: {} + + update-browserslist-db@1.1.0(browserslist@4.23.2): + dependencies: + browserslist: 4.23.2 + escalade: 3.1.2 + picocolors: 1.0.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-sync-external-store@1.2.0(react@18.3.1): + dependencies: + react: 18.3.1 + + util-deprecate@1.0.2: {} + + vite@5.3.5(@types/node@22.0.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.40 + rollup: 4.19.1 + optionalDependencies: + '@types/node': 22.0.0 + fsevents: 2.3.3 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + yaml@1.10.2: {} + + yaml@2.5.0: {} + + yocto-queue@0.1.0: {} + + zod@3.23.8: {} + + zustand@4.5.4(@types/react@18.3.3)(react@18.3.1): + dependencies: + use-sync-external-store: 1.2.0(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 + react: 18.3.1 diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> \ No newline at end of file diff --git a/frontend/src/app/app.tsx b/frontend/src/app/app.tsx new file mode 100644 index 0000000..8d8a30b --- /dev/null +++ b/frontend/src/app/app.tsx @@ -0,0 +1,12 @@ +import Providers from "./providers"; +import Router from "./router"; + +const App = () => { + return ( + <Providers> + <Router /> + </Providers> + ); +}; + +export default App; diff --git a/frontend/src/app/providers.tsx b/frontend/src/app/providers.tsx new file mode 100644 index 0000000..add1e44 --- /dev/null +++ b/frontend/src/app/providers.tsx @@ -0,0 +1,13 @@ +import { PropsWithChildren } from "react"; +import ThemeProvider from "./theme-provider"; + +const Providers = ({ children }: PropsWithChildren) => { + return ( + <> + {children} + <ThemeProvider /> + </> + ); +}; + +export default Providers; diff --git a/frontend/src/app/router.tsx b/frontend/src/app/router.tsx new file mode 100644 index 0000000..570769a --- /dev/null +++ b/frontend/src/app/router.tsx @@ -0,0 +1,35 @@ +import { useMemo } from "react"; +import { + createBrowserRouter, + Navigate, + RouterProvider, +} from "react-router-dom"; + +import LearnViewPage from "@/pages/learn/view/page"; + +const appRouter = createBrowserRouter([ + { + children: [ + { + index: true, + element: <Navigate to="/learn/123" />, + }, + { + path: "learn/:id", + Component: LearnViewPage, + }, + ], + }, +]); + +// const authRouter = createBrowserRouter([]); + +const Router = () => { + const router = useMemo(() => { + return appRouter; + }, []); + + return <RouterProvider router={router} />; +}; + +export default Router; diff --git a/frontend/src/app/styles.css b/frontend/src/app/styles.css new file mode 100644 index 0000000..d8d1017 --- /dev/null +++ b/frontend/src/app/styles.css @@ -0,0 +1,26 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + *, + ::before, + ::after { + @apply border-base-content/10; + } +} + +.console-feed > div { + @apply flex flex-col-reverse; +} +.console-feed > div > div { + @apply py-3; +} +.console-feed span, +.console-feed summary { + @apply text-base; +} + +.monaco-editor { + @apply outline-none; +} \ No newline at end of file diff --git a/frontend/src/app/theme-provider.tsx b/frontend/src/app/theme-provider.tsx new file mode 100644 index 0000000..2f6239a --- /dev/null +++ b/frontend/src/app/theme-provider.tsx @@ -0,0 +1,17 @@ +import { themeStore } from "@/stores/theme.store"; +import { useEffect } from "react"; +import { useStore } from "zustand"; + +const ThemeProvider = () => { + const theme = useStore(themeStore, (i) => i.theme); + const isDarkMode = useStore(themeStore, (i) => i.isDarkMode); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", theme); + document.documentElement.classList.toggle("dark", isDarkMode); + }, [theme, isDarkMode]); + + return null; +}; + +export default ThemeProvider; diff --git a/frontend/src/app/themes.ts b/frontend/src/app/themes.ts new file mode 100644 index 0000000..7cad07c --- /dev/null +++ b/frontend/src/app/themes.ts @@ -0,0 +1,38 @@ +// + +export const themes = [ + { + name: "light", + dark: false, + }, + { + name: "dark", + dark: true, + }, + { + name: "nord", + dark: false, + }, + { + name: "winter", + dark: false, + }, + { + name: "pastel", + dark: false, + }, + { + name: "dracula", + dark: true, + }, + { + name: "dim", + dark: true, + }, + { + name: "black", + dark: true, + }, +] as const; + +export type Themes = (typeof themes)[number]["name"]; diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/frontend/src/assets/react.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg> \ No newline at end of file diff --git a/frontend/src/components/containers/code-editor.tsx b/frontend/src/components/containers/code-editor.tsx new file mode 100644 index 0000000..dfa1bee --- /dev/null +++ b/frontend/src/components/containers/code-editor.tsx @@ -0,0 +1,220 @@ +import { Editor } from "@monaco-editor/react"; +import { editor } from "monaco-editor"; +import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; +import Tabs from "@ui/tabs"; +import { LucideIcon } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; +import { useStore } from "zustand"; +import { themeStore } from "@/stores/theme.store"; + +export type CodeEditorFile = { + uri: string; + title?: string; + icon?: LucideIcon; + lang: "html" | "javascript" | "css"; + content: string; + hidden?: boolean; + pinned?: boolean; +}; + +export type CodeEditorRef = { + editor: editor.IStandaloneCodeEditor; + monaco: typeof monaco; + getModels: () => editor.IModel[]; + loadFiles: (files: CodeEditorFile[]) => void; + getData: () => { + lang: string; + value: string; + fullUri: monaco.Uri; + uri: string; + }[]; + onSave: () => void; + onFormat: () => void; + clearPersistedData: () => void; +}; + +type CodeEditorProps = { + files?: CodeEditorFile[]; + persistId?: string; + onLoad?: (ref: CodeEditorRef) => void; + showHiddenFiles?: boolean; +}; + +const CodeEditor = ({ + persistId, + onLoad, + showHiddenFiles, + ...props +}: CodeEditorProps) => { + const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null); + const monacoRef = useRef<typeof monaco | null>(null); + + const [files, setCurrentFiles] = useState<CodeEditorFile[]>([]); + const [currentFile, setCurrentFile] = useState(""); + const [isEditorReady, setEditorReady] = useState(false); + const isDarkMode = useStore(themeStore, (i) => i.isDarkMode); + + useEffect(() => { + const editor = editorRef.current; + const monaco = monacoRef.current; + + if (!editor || !monaco || !isEditorReady || !props.files?.length) { + return; + } + + loadFiles(props.files); + onLoad?.({ + editor, + monaco, + getModels, + loadFiles, + getData, + onSave, + onFormat, + clearPersistedData, + }); + }, [isEditorReady, props.files, persistId]); + + useEffect(() => { + if (!currentFile?.length || !isEditorReady) { + return; + } + + if (!files.find((i) => i.uri === currentFile)) { + return; + } + + const uri = monaco.Uri.parse(currentFile); + const model = monacoRef.current?.editor.getModel(uri); + if (model) { + editorRef.current?.setModel(model); + } + }, [currentFile, isEditorReady, files]); + + const loadFiles = (files: CodeEditorFile[]) => { + const monaco = monacoRef.current; + if (!monaco) { + return; + } + + // Clear existing models + getModels().forEach((model) => { + model.dispose(); + }); + + files.forEach((file) => { + const uri = monaco.Uri.parse(file.uri); + const exist = monaco.editor.getModel(uri); + if (exist) { + return; + } + + let content = file.content; + if (persistId) { + content = localStorage.getItem(`${persistId}:${file.uri}`) || content; + } + + // Create model + monaco.editor.createModel(content, file.lang, uri); + }); + + const visibleFiles = files + .filter((i) => !i.hidden || showHiddenFiles) + .sort((a, b) => { + return a.pinned && b.pinned ? 0 : a.pinned ? -1 : b.pinned ? 1 : 0; + }); + setCurrentFiles(visibleFiles); + + // Open first model + setCurrentFile(visibleFiles[0]?.uri || ""); + }; + + const getModels = () => { + return monacoRef?.current?.editor.getModels() || []; + }; + + const getData = () => { + const models = getModels(); + + return models.map((model) => { + const lang = model.getLanguageId(); + const value = model.getValue(); + const fullUri = model.uri; + const uri = model.uri.path.slice(1); + + return { lang, value, fullUri, uri }; + }); + }; + + const onSave = () => { + const editor = editorRef.current; + if (!editor || !persistId) { + return; + } + + const data = getData(); + data.forEach((file) => { + localStorage.setItem(`${persistId}:${file.uri}`, file.value); + }); + return data; + }; + + const onFormat = () => { + const editor = editorRef.current; + if (editor) { + editor?.getAction("editor.action.formatDocument")?.run(); + } + }; + + const clearPersistedData = () => { + if (!persistId) { + return; + } + + const data = getData(); + data.forEach((file) => localStorage.removeItem(`${persistId}:${file.uri}`)); + loadFiles(props.files || []); + }; + + return ( + <> + <Tabs + hideIfOneTab + tabs={files.map((file) => ({ + title: file.title || file.uri, + icon: file.icon, + key: file.uri, + }))} + current={currentFile} + onChange={(key) => { + setCurrentFile(key); + }} + /> + + <div className="flex-1 overflow-hidden"> + <Editor + height="100%" + defaultLanguage="javascript" + theme={isDarkMode ? "vs-dark" : "light"} + onMount={(editor, monaco) => { + editorRef.current = editor; + monacoRef.current = monaco; + setEditorReady(true); + }} + options={{ + minimap: { enabled: false }, + scrollBeyondLastLine: false, + fontSize: 16, + lineNumbersMinChars: 3, + // lineNumbers: "off", + showFoldingControls: "never", + // codeLens: false, + wordWrap: "on", + }} + /> + </div> + </> + ); +}; + +export default CodeEditor; diff --git a/frontend/src/components/containers/console-logs.tsx b/frontend/src/components/containers/console-logs.tsx new file mode 100644 index 0000000..6a87495 --- /dev/null +++ b/frontend/src/components/containers/console-logs.tsx @@ -0,0 +1,32 @@ +import { cn } from "@/lib/utils"; +import { themeStore } from "@/stores/theme.store"; +import { Console } from "console-feed"; +import { Message } from "console-feed/lib/definitions/Component"; +import { useStore } from "zustand"; + +type ConsoleLogsProps = { + logs: Message[]; + className?: string; +}; + +const ConsoleLogs = ({ logs, className }: ConsoleLogsProps) => { + const colorScheme = useStore(themeStore, (i) => + i.isDarkMode ? "dark" : "light" + ); + + if (!logs?.length) { + return ( + <div className={cn("flex items-center justify-center p-4", className)}> + <p className="text-center">Tidak ada log.</p> + </div> + ); + } + + return ( + <div className={cn("console-feed overflow-y-auto", className)}> + <Console logs={logs} variant={colorScheme} /> + </div> + ); +}; + +export default ConsoleLogs; diff --git a/frontend/src/components/containers/playground-panels.tsx b/frontend/src/components/containers/playground-panels.tsx new file mode 100644 index 0000000..98d4550 --- /dev/null +++ b/frontend/src/components/containers/playground-panels.tsx @@ -0,0 +1,141 @@ +import { TestCase } from "@/lib/playground"; +import { Decode, Hook } from "console-feed"; +import { Message } from "console-feed/lib/definitions/Component"; +import { Bug, ClipboardCheck, PanelsTopLeft } from "lucide-react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import PlaygroundTests from "./playground-tests"; +import ConsoleLogs from "./console-logs"; +import { TabView, TabViewItem } from "@ui/tabs"; +import { useStore } from "zustand"; +import { themeStore } from "@/stores/theme.store"; + +export type PlaygroundPanelsRef = { + iframe: HTMLIFrameElement; + setFrameData: (data: string) => void; + clearLogs: () => void; +}; + +type PlaygroundPanelsProps = { + tests?: TestCase[]; + onTestResult?: (id: string, result: any) => void; + onLoad: (ctx: PlaygroundPanelsRef) => void; + showPreview?: boolean; + showLogs?: boolean; +}; + +const PlaygroundPanels = ({ + tests, + onTestResult, + onLoad, + showPreview, + showLogs, +}: PlaygroundPanelsProps) => { + const iframeRef = useRef<HTMLIFrameElement | null>(null); + const [frameLogs, setFrameLogs] = useState<Message[]>([]); + const colorScheme = useStore(themeStore, (i) => + i.isDarkMode ? "dark" : "light" + ); + + const onFrameLoad = useCallback( + (el: any) => { + if (el.contentWindow.consoleFn) { + Hook(el.contentWindow.consoleFn, (log) => { + const data = Decode(log) as never; + setFrameLogs((cur) => [...cur, data]); + }); + } + + if (typeof el.contentWindow.loadScript === "function") { + el.contentWindow.loadScript(); + } + + tests?.forEach((item) => { + let result; + try { + result = el.contentWindow.eval(item.test); + } catch (err) { + console.error(err); + } finally { + onTestResult?.(item.id!, result); + } + }); + + onLoad({ + iframe: el, + setFrameData: (data: string) => { + el.srcdoc = data; + }, + clearLogs: () => { + setFrameLogs([]); + }, + }); + }, + [setFrameLogs, tests, onLoad] + ); + + const frameElement = useMemo(() => { + return ( + <iframe + ref={iframeRef} + referrerPolicy="origin" + srcDoc="" + onLoad={() => { + const el = iframeRef.current as any; + if (el?.contentWindow) { + onFrameLoad(el); + } + }} + /> + ); + }, [onFrameLoad]); + + useEffect(() => { + const frameDoc = iframeRef.current?.contentWindow?.document; + if (frameDoc) { + frameDoc + .querySelector("meta[name='color-scheme']") + ?.setAttribute("content", colorScheme); + } + }, [colorScheme]); + + const tabs = useMemo(() => { + return [ + { + title: "Pratinjau", + key: "preview", + icon: PanelsTopLeft, + element: frameElement, + show: showPreview === true, + }, + { + title: "Hasil", + key: "tests", + icon: ClipboardCheck, + Component: ({ className }: any) => ( + <PlaygroundTests tests={tests || []} className={className} /> + ), + enabled: tests && tests?.length > 0, + }, + { + title: "Log", + key: "logs", + icon: Bug, + Component: ({ className }: any) => ( + <ConsoleLogs logs={frameLogs} className={className} /> + ), + enabled: showLogs !== false, + }, + ] satisfies TabViewItem[]; + }, [frameElement, frameLogs, tests, showPreview, showLogs]); + + return ( + <TabView + tabs={tabs} + className="rounded-none" + contentClassName="flex-1 shrink-0" + hideIfOneTab + /> + ); +}; + +export default PlaygroundPanels; diff --git a/frontend/src/components/containers/playground-tests.tsx b/frontend/src/components/containers/playground-tests.tsx new file mode 100644 index 0000000..5f37284 --- /dev/null +++ b/frontend/src/components/containers/playground-tests.tsx @@ -0,0 +1,39 @@ +import { cn } from "@/lib/utils"; +import { TestCase } from "../../lib/playground"; + +type PlaygroundTestsProps = { + tests: TestCase[]; + className?: string; +}; + +const PlaygroundTests = ({ tests, className }: PlaygroundTestsProps) => { + return ( + <div className={cn("p-4 flex flex-col gap-2 overflow-y-auto", className)}> + {tests.map((test) => ( + <div + key={test.id} + className={cn( + "flex flex-row gap-2 justify-between px-4 py-2 rounded-lg bg-base-200", + test.isFinished && test.expected !== test.result + ? "bg-error text-error-content" + : "", + test.isFinished && test.expected === test.result + ? "bg-success text-success-content" + : "" + )} + > + <p>{test.name}</p> + <p>Expect: {test.expected || "-"}</p> + <p> + Result:{" "} + {typeof test.result === "undefined" + ? "-" + : JSON.stringify(test.result)} + </p> + </div> + ))} + </div> + ); +}; + +export default PlaygroundTests; diff --git a/frontend/src/components/containers/playground.tsx b/frontend/src/components/containers/playground.tsx new file mode 100644 index 0000000..1b9702d --- /dev/null +++ b/frontend/src/components/containers/playground.tsx @@ -0,0 +1,300 @@ +import { Fragment } from "react"; +import { + Code, + PlayCircle, + Expand, + Shrink, + X, + EllipsisVertical, + RotateCw, +} from "lucide-react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import Button from "@ui/button"; +import { nanoid } from "nanoid"; +import { cn } from "@/lib/utils"; +import { frameTemplate, TestCase } from "../../lib/playground"; +import CodeEditor, { CodeEditorFile, CodeEditorRef } from "./code-editor"; +import PlaygroundPanels, { PlaygroundPanelsRef } from "./playground-panels"; +import Dropdown from "@ui/dropdown"; + +type PlaygroundProps = { + className?: string; + files?: CodeEditorFile[]; + tests?: TestCase[]; + persistId?: string; + showHiddenFiles?: boolean; + showLogs?: boolean; +}; + +const Playground = ({ + className, + files, + persistId, + showHiddenFiles, + showLogs, + ...props +}: PlaygroundProps) => { + const panelsRef = useRef<PlaygroundPanelsRef | null>(null); + const editorRef = useRef<CodeEditorRef | null>(null); + + const [tests, setTests] = useState<TestCase[]>([]); + const [hasRun, setHasRun] = useState(false); + + const onEditorLoad = useCallback((ctx: CodeEditorRef) => { + editorRef.current = ctx; + const { monaco, editor } = ctx; + + editor.addAction({ + id: "run", + label: "Run", + keybindings: [ + monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, + monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, + ], + run: onRun, + }); + + editor.addAction({ + id: "save", + label: "Save", + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS], + run: onRun, + }); + }, []); + + const onTestResult = useCallback( + (id: string, result: any) => { + const idx = tests.findIndex((i) => i.id === id); + if (idx < 0) { + return; + } + + setTests((cur) => { + const res = [...cur]; + res[idx] = { ...res[idx], result, isFinished: true }; + return res; + }); + }, + [tests, setTests] + ); + + const onRun = () => { + const panels = panelsRef.current; + const editor = editorRef.current; + + if (!panels || !editor) { + return; + } + + let body = "", + script = "", + style = ""; + + editor.getData().forEach((file) => { + const value = file.value + "\n"; + + switch (file.lang) { + case "html": + body += value; + break; + case "javascript": + script += value; + break; + case "css": + style += value; + break; + } + }); + + const newTests = props.tests?.map((i) => ({ ...i, id: nanoid() })) || []; + const doc = frameTemplate({ + body, + script, + style, + tests: newTests.map((i) => ({ id: i.id, test: i.test })), + }); + + setTests(newTests); + setHasRun(true); + panels.setFrameData(doc); + panels.clearLogs(); + editor.onFormat(); + setTimeout(() => editor.onSave(), 100); + }; + + const onResetFiles = () => { + if (window.confirm("Apakah anda yakin ingin mengembalikan data ke awal?")) { + editorRef.current?.clearPersistedData(); + } + }; + + if (!files?.length) { + return null; + } + + return ( + <PlaygroundContainer className={className}> + {(ctx) => ( + <Fragment> + <div className="p-2 flex flex-row items-center"> + <Code size={28} className="hidden lg:block ml-4 mr-3" /> + <Button + icon={X} + variant="ghost" + className="lg:hidden -ml-2 -mr-1" + onClick={() => ctx.setOpen(false)} + /> + + <p className="font-medium text-lg flex-1 truncate">Playground</p> + <Button + onClick={onRun} + icon={PlayCircle} + title="Ctrl + Enter to Run" + > + Mulai + </Button> + <Dropdown + trigger={ + <Button variant="ghost" size="icon" icon={EllipsisVertical} /> + } + > + <Dropdown.Item + icon={ctx.isExtended ? Shrink : Expand} + onClick={() => ctx.setExtended(!ctx.isExtended)} + className="hidden lg:block" + title="Ctrl + Alt + M" + > + Tampilan Penuh + </Dropdown.Item> + <Dropdown.Item icon={RotateCw} onClick={onResetFiles}> + Reset Files + </Dropdown.Item> + </Dropdown> + </div> + + <div + className={cn( + "flex-1 flex flex-col items-stretch overflow-hidden", + ctx.isExtended && "sm:grid sm:grid-cols-12" + )} + > + <div className="flex-1 flex flex-col overflow-hidden sm:col-span-6 lg:col-span-7"> + <CodeEditor + files={files} + persistId={persistId} + showHiddenFiles={showHiddenFiles} + onLoad={onEditorLoad} + /> + </div> + + <div + className={cn( + "flex-1 flex flex-col overflow-hidden sm:col-span-6 lg:col-span-5 transition-all duration-1000 ease-in-out opacity-100 border-t", + !hasRun && !ctx.isExtended + ? "max-h-0 opacity-0" + : "max-h-[100vh]", + ctx.isExtended && "border-l border-t-0 max-h-none" + )} + > + <PlaygroundPanels + onLoad={(ref) => { + panelsRef.current = ref; + }} + tests={tests} + onTestResult={onTestResult} + showPreview={files?.find((i) => i.lang === "html") != null} + showLogs={showLogs} + /> + </div> + </div> + </Fragment> + )} + </PlaygroundContainer> + ); +}; + +type IPlaygroundContext = { + isExtended: boolean; + setExtended: (isExtended: boolean) => void; + isOpen: boolean; + setOpen: (isOpen: boolean) => void; +}; + +type PlaygroundContainerProps = { + className?: string; + children?: (ctx: IPlaygroundContext) => React.ReactNode; +}; + +const PlaygroundContainer = ({ + className, + children, +}: PlaygroundContainerProps) => { + const [isExtended, setExtended] = useState(false); + const [isOpen, setOpen] = useState(false); + + useEffect(() => { + const onMouseDown = (e: MouseEvent) => { + if (!isOpen) { + return; + } + + const element = document.getElementById("playground"); + if (element && !element.contains(e.target as Node)) { + setOpen(false); + } + }; + + const onKeyUp = (e: KeyboardEvent) => { + if (e.key === "Escape" && (isOpen || isExtended)) { + setOpen(false); + setExtended(false); + } + + // ctrl+alt+m to go extended + if (e.ctrlKey && e.altKey && e.key === "m") { + setExtended(!isExtended); + } + }; + + window.addEventListener("mousedown", onMouseDown); + window.addEventListener("keyup", onKeyUp); + + return () => { + window.removeEventListener("mousedown", onMouseDown); + window.removeEventListener("keyup", onKeyUp); + }; + }, [isOpen, isExtended]); + + const contextValues = { + isExtended, + setExtended, + isOpen, + setOpen, + }; + + return ( + <Fragment> + <Button + className="fixed bottom-4 right-4 sm:bottom-8 sm:right-8 lg:hidden z-[39]" + onClick={() => setOpen(true)} + > + <Code /> + <p>Coba</p> + </Button> + + <div + id="playground" + className={cn( + "flex flex-col overflow-hidden playground bg-base-100 w-full max-w-[400px] h-full fixed right-0 border-l top-0 translate-x-full transition-transform z-40 lg:static lg:translate-x-0 lg:max-w-[33%] shadow-xl lg:shadow-none", + className, + isOpen && "translate-x-0", + isExtended && "!flex !max-w-none !fixed inset-0" + )} + > + {children?.(contextValues)} + </div> + </Fragment> + ); +}; + +export default Playground; diff --git a/frontend/src/components/containers/theme-selector.tsx b/frontend/src/components/containers/theme-selector.tsx new file mode 100644 index 0000000..7f74964 --- /dev/null +++ b/frontend/src/components/containers/theme-selector.tsx @@ -0,0 +1,29 @@ +import { themes } from "@/app/themes"; +import { ucfirst } from "@/lib/utils"; +import { setTheme, themeStore } from "@/stores/theme.store"; +import Button from "@ui/button"; +import Dropdown from "@ui/dropdown"; +import { Check, Palette } from "lucide-react"; +import { ComponentPropsWithoutRef } from "react"; +import { useStore } from "zustand"; + +type ThemeSelectorProps = ComponentPropsWithoutRef<typeof Dropdown>; + +const ThemeSelector = (props: ThemeSelectorProps) => { + const curTheme = useStore(themeStore, (i) => i.theme); + + return ( + <Dropdown trigger={<Button icon={Palette}>Tema</Button>} {...props}> + {themes.map((theme) => ( + <Dropdown.Item key={theme.name} onClick={() => setTheme(theme.name)}> + <div className="w-6"> + {curTheme === theme.name && <Check size={16} />} + </div> + {ucfirst(theme.name)} + </Dropdown.Item> + ))} + </Dropdown> + ); +}; + +export default ThemeSelector; diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx new file mode 100644 index 0000000..465cabf --- /dev/null +++ b/frontend/src/components/ui/button.tsx @@ -0,0 +1,75 @@ +import { cn } from "@/lib/utils"; +import { Slot } from "@radix-ui/react-slot"; +import { LucideIcon } from "lucide-react"; +import { ComponentPropsWithoutRef, forwardRef } from "react"; +import { tv, VariantProps } from "tailwind-variants"; + +const button = tv({ + base: "btn rounded-xl", + variants: { + color: { + none: "", + primary: "btn-primary", + secondary: "btn-secondary", + neutral: "btn-neutral", + accent: "btn-accent", + info: "btn-info", + success: "btn-success", + warning: "btn-warning", + error: "btn-error", + }, + variant: { + link: "btn-link", + outline: "btn-outline", + ghost: "btn-ghost", + }, + size: { + xs: "btn-xs", + sm: "btn-sm h-10", + lg: "btn-lg", + icon: "btn-square", + }, + }, + defaultVariants: { + color: "neutral", + }, +}); + +type ButtonVariants = VariantProps<typeof button>; + +type ButtonProps = ComponentPropsWithoutRef<"button"> & + ButtonVariants & { + as?: "a" | "button" | "div"; + asChild?: boolean; + href?: string; + isLoading?: boolean; + icon?: LucideIcon; + }; + +const Button = forwardRef<HTMLButtonElement, ButtonProps>( + ( + { as = "button", className, children, isLoading, icon: Icon, ...props }, + ref + ) => { + const Comp = props.asChild ? Slot : (as as any); + + return ( + <Comp + ref={ref} + role="button" + className={cn(button(props), className)} + {...props} + > + {isLoading ? ( + <span className="loading loading-spinner"></span> + ) : Icon ? ( + <Icon /> + ) : null} + + {children} + </Comp> + ); + } +); + +export default Button; diff --git a/frontend/src/components/ui/dropdown.tsx b/frontend/src/components/ui/dropdown.tsx new file mode 100644 index 0000000..e38e9db --- /dev/null +++ b/frontend/src/components/ui/dropdown.tsx @@ -0,0 +1,107 @@ +import { cn } from "@/lib/utils"; +import { Slot } from "@radix-ui/react-slot"; +import { LucideIcon } from "lucide-react"; +import { useMemo } from "react"; +import { tv, VariantProps } from "tailwind-variants"; + +const dropdown = tv({ + base: "dropdown", + variants: { + position: { + top: "dropdown-top", + bottom: "dropdown-bottom", + left: "dropdown-left", + right: "dropdown-right", + }, + align: { + default: "", + end: "dropdown-end", + }, + }, + defaultVariants: { + position: "bottom", + align: "end", + }, +}); + +type DropdownProps = VariantProps<typeof dropdown> & { + tabIndex?: number; + className?: string; + contentClassName?: string; + children?: React.ReactNode; + trigger?: React.ReactNode; +}; + +const Dropdown = ({ + tabIndex, + className, + contentClassName, + children, + trigger, + ...props +}: DropdownProps) => { + const tabIdx = useMemo( + () => tabIndex || Math.round(Math.random() * 10000), + [tabIndex] + ); + + return ( + <div className={cn(dropdown(props), className)}> + <Slot tabIndex={tabIdx} role="button" {...({ as: "div" } as any)}> + {trigger} + </Slot> + <ul + tabIndex={tabIdx} + className={cn( + "dropdown-content menu bg-base-200 rounded-box z-[1] w-52 p-2 shadow", + contentClassName + )} + > + {children} + </ul> + </div> + ); +}; + +type DropdownItemProps = { + className?: string; + btnClassName?: string; + children?: React.ReactNode; + href?: string; + onClick?: () => void; + icon?: LucideIcon; + title?: string; +}; + +export const DropdownItem = ({ + className, + btnClassName, + children, + href = "#", + onClick, + icon: Icon, + title, +}: DropdownItemProps) => { + return ( + <li className={className}> + <a + href={href} + onClick={(e) => { + if (onClick) { + e.preventDefault(); + onClick(); + } + }} + className={btnClassName} + title={title} + > + {Icon ? <Icon size={16} /> : null} + {children} + </a> + </li> + ); +}; + +Dropdown.Item = DropdownItem; + +export default Dropdown; diff --git a/frontend/src/components/ui/tabs.tsx b/frontend/src/components/ui/tabs.tsx new file mode 100644 index 0000000..077ee8b --- /dev/null +++ b/frontend/src/components/ui/tabs.tsx @@ -0,0 +1,118 @@ +import { cn } from "@/lib/utils"; +import { LucideIcon } from "lucide-react"; +import React, { useEffect, useMemo, useState } from "react"; +import { Slot } from "@radix-ui/react-slot"; + +export type Tab = { + title: string; + key: string; + icon?: LucideIcon; +}; + +type TabsProps = { + tabs?: Tab[]; + current?: string; + onChange?: (idx: string) => void; + hideIfOneTab?: boolean; + className?: string; + tabClassName?: string; +}; + +const Tabs = ({ + tabs = [], + current, + onChange, + hideIfOneTab, + className, + tabClassName, +}: TabsProps) => { + if (tabs.length < 2 && hideIfOneTab) { + return null; + } + + return ( + <div role="tablist" className={cn("tabs tabs-boxed p-2", className)}> + {tabs.map((tab) => ( + <button + key={tab.key} + type="button" + role="tab" + className={cn( + "tab h-10 text-sm gap-2", + tabClassName, + tab.key === current && "tab-active !border-b-primary text-primary" + )} + onClick={() => onChange?.(tab.key)} + > + {tab.icon ? <tab.icon size={18} /> : null} + {tab.title} + </button> + ))} + </div> + ); +}; + +export type TabViewItem = Tab & { + enabled?: boolean; + show?: boolean; + element?: React.ReactNode; + Component?: React.ComponentType<any>; +}; + +type TabViewProps = Omit<TabsProps, "tabs"> & { + tabs: TabViewItem[]; + contentClassName?: string; +}; + +export const TabView = ({ tabs, contentClassName, ...props }: TabViewProps) => { + const [curTab, setCurTab] = useState(""); + const tabList = useMemo(() => { + if (!tabs) { + return []; + } + + return tabs + .filter((tab) => tab.enabled !== false) + .map((tab) => { + const content = tab.element ? ( + tab.element + ) : tab.Component ? ( + <tab.Component /> + ) : null; + + return { ...tab, content }; + }); + }, [tabs]); + + const visibleTabs = tabList.filter((tab) => tab.show !== false); + + useEffect(() => { + setCurTab(visibleTabs[0]?.key || ""); + }, [visibleTabs.length]); + + return ( + <> + <Tabs + tabs={visibleTabs} + current={curTab} + onChange={setCurTab} + {...props} + /> + + {tabList.map((tab) => ( + <Slot + key={tab.key} + role="tabpanel" + className={cn( + contentClassName, + tab.key !== curTab ? "hidden" : undefined + )} + > + {tab.content} + </Slot> + ))} + </> + ); +}; + +export default Tabs; diff --git a/frontend/src/lib/playground.ts b/frontend/src/lib/playground.ts new file mode 100644 index 0000000..32b51c5 --- /dev/null +++ b/frontend/src/lib/playground.ts @@ -0,0 +1,60 @@ +import { themeStore } from "@/stores/theme.store"; + +export type TestCase = { + id?: string; + name: string; + test: string; + expected?: any; + result?: any; + isFinished?: boolean; +}; + +type FrameTemplateData = Partial<{ + body: string; + script: string; + style: string; + tests: Pick<TestCase, "id" | "test">[]; +}>; + +export const frameTemplate = (data: FrameTemplateData) => { + const colorScheme = themeStore.getState().isDarkMode ? "dark" : "light"; + + return `<!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="color-scheme" content="${colorScheme}"> + + <style> + html, + body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + } + + * { + box-sizing: border-box; + } + + pre { + margin: 0; + padding: 1rem; + font-size: 1.2rem; + } + + ${data.style} + </style> + </head> + <body id="body"> + ${data.body} + </body> + + <script> + window.consoleFn = {}; + Object.keys(console).forEach(key => { window.consoleFn[key] = function (){}; console[key] = function (...args){ setTimeout(() => window.consoleFn[key](...args), 100); }}); + ${data.script} + </script> + </html>`; +}; diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts new file mode 100644 index 0000000..6c3593f --- /dev/null +++ b/frontend/src/lib/utils.ts @@ -0,0 +1,10 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +export function ucfirst(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1); +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..1f7efca --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./app/app.tsx"; +import "./app/styles.css"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + <React.StrictMode> + <App /> + </React.StrictMode> +); diff --git a/frontend/src/pages/learn/view/page.tsx b/frontend/src/pages/learn/view/page.tsx new file mode 100644 index 0000000..351d2f9 --- /dev/null +++ b/frontend/src/pages/learn/view/page.tsx @@ -0,0 +1,183 @@ +import { useEffect, useMemo, useState } from "react"; +import Playground from "../../../components/containers/playground"; +import { Braces, Code, CodeXml, PencilRuler } from "lucide-react"; +import { TestCase } from "../../../lib/playground"; +import Button from "@ui/button"; +import { cn } from "@/lib/utils"; +import { CodeEditorFile } from "@/components/containers/code-editor"; +import ThemeSelector from "@/components/containers/theme-selector"; + +const initialBody = ` +<pre id="print-area"></pre> +`; + +const initialInitScript = ` +const printAreaEl = document.getElementById("print-area"); +function print(...args) { + printAreaEl.innerHTML += args.map(String).join(''); +} +`; + +const initialScript = ` +let a = 4; + +// Hasil dari 'a' dikali 2 +let b = a * 2; + +// Hasil dari penjumlahan a dan b +let c = // lengkapi disini + +// Fungsi untuk menambahkan dua bilangan +function tambah(a, b) { + // lengkapi disini +} + +for (let i=0; i<=5; i++) { + for (let j=0; j<=i; j++) { + print('*'); + } + print('\\n'); +} +`; + +const initialStyle = ` +body { + padding: 1rem; +} + +button { + background: #f5f5f5; + border: 1px solid #f5f5f5; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + cursor: pointer; + display: block; +} + +button:hover { + background: #e5e5e5; +} +`; + +const LearnViewPage = () => { + const files: CodeEditorFile[] = useMemo(() => { + return [ + { + uri: "body.html", + // title: "HTML", + // icon: CodeXml, + lang: "html", + content: initialBody, + hidden: true, + }, + { + uri: "init.js", + icon: Braces, + lang: "javascript", + content: initialInitScript, + hidden: true, + }, + { + uri: "script.js", + title: "Script", + icon: Braces, + lang: "javascript", + content: initialScript, + pinned: true, + }, + // { + // uri: "style.css", + // title: "Style", + // icon: PencilRuler, + // lang: "css", + // content: initialStyle, + // }, + ]; + }, []); + + const tests: TestCase[] = [ + { + name: "Hasil dari b = a x 2", + test: "b", + expected: 8, + }, + { + name: "Hasil dari c = a + b", + test: "c", + expected: 12, + }, + { + name: "Hasil 1 + 2", + test: "tambah(1, 2)", + expected: 3, + }, + ]; + + return ( + <div className="flex flex-row items-stretch h-screen overflow-hidden"> + <aside className="w-[250px] bg-base-100 fixed top-0 left-0 h-full z-10 -translate-x-full md:static md:translate-x-0"> + Sidebar + <ThemeSelector + className="absolute left-4 bottom-4" + position="top" + align="default" + /> + </aside> + + <main className="flex-1 bg-base-100 overflow-y-auto"> + <article className="p-4 md:p-8 prose"> + <h1>Lorem Ipsum</h1> + <p> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam + laoreet suscipit pretium. Nunc vehicula interdum condimentum. + Maecenas vitae enim dui. Vestibulum luctus tincidunt nisl et + molestie. Mauris sollicitudin velit consectetur ante porttitor, quis + commodo justo porta. Integer vestibulum ante urna, et fringilla + lorem faucibus egestas. Nunc laoreet mollis blandit. Fusce ut mauris + nibh. Sed orci dolor, fringilla a magna quis, aliquam imperdiet + purus. Nullam tellus sapien, luctus non volutpat non, venenatis eu + purus. Etiam elit arcu, dapibus nec pulvinar eu, blandit sed lacus. + Aliquam euismod id ligula in blandit. + </p> + + <p> + In vel vulputate dolor. Duis bibendum viverra ex, sit amet molestie + dui pulvinar quis. Donec varius dictum orci. Donec sollicitudin quam + eu massa ullamcorper porta. In sed ex mauris. Vestibulum ante ipsum + primis in faucibus orci luctus et ultrices posuere cubilia curae; + Nunc ultrices, enim a porttitor feugiat, leo nisl venenatis enim, in + pretium velit leo quis purus. Quisque eget sapien sem. Pellentesque + hendrerit, sapien ac sodales vestibulum, massa nulla sollicitudin + neque, vitae condimentum metus leo nec magna. Aliquam sit amet + porttitor leo. Morbi a massa nec magna ultrices efficitur et + vulputate nunc. Aliquam id convallis nisl. + </p> + + <p> + Praesent efficitur quis dui nec sagittis. Vestibulum finibus + vulputate nisi a ultricies. Quisque auctor nunc ut felis placerat, + eget scelerisque sapien rhoncus. Suspendisse sollicitudin sed lacus + in mattis. Duis ut egestas arcu. Integer convallis consequat dolor. + Nulla tincidunt sem nunc, rutrum congue eros ornare euismod. Quisque + vitae massa risus. Sed sodales facilisis iaculis. Etiam interdum + massa sit amet purus consequat finibus at sit amet mauris. + Vestibulum dapibus velit sit amet mauris lobortis, ut scelerisque + nulla lacinia. Donec quis dictum leo, id luctus mi. + </p> + </article> + </main> + + <Playground + className="flex-1" + files={files} + tests={tests} + persistId="test" + // showHiddenFiles + // showLogs={false} + // preview + /> + </div> + ); +}; + +export default LearnViewPage; diff --git a/frontend/src/stores/theme.store.ts b/frontend/src/stores/theme.store.ts new file mode 100644 index 0000000..b1ad112 --- /dev/null +++ b/frontend/src/stores/theme.store.ts @@ -0,0 +1,20 @@ +import { themes, Themes } from "@/app/themes"; +import { createStore } from "zustand"; +import { persist } from "zustand/middleware"; + +export const themeStore = createStore( + persist( + () => ({ + theme: "light" as Themes, + isDarkMode: false, + }), + { + name: "theme", + } + ) +); + +export const setTheme = (theme: Themes) => { + const isDarkMode = themes.find((t) => t.name === theme)?.dark ?? false; + themeStore.setState({ theme, isDarkMode }); +}; diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// <reference types="vite/client" /> diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 0000000..e846177 --- /dev/null +++ b/frontend/tailwind.config.js @@ -0,0 +1,13 @@ +const themes = require("./src/app/themes").themes; + +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: {}, + }, + plugins: [require("@tailwindcss/typography"), require("daisyui")], + daisyui: { + themes: themes.map((i) => i.name), + }, +}; diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json new file mode 100644 index 0000000..7fa2bc8 --- /dev/null +++ b/frontend/tsconfig.app.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "baseUrl": ".", + "paths": { + "@ui/*": ["./src/components/ui/*"], + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..ea9d0cd --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 0000000..3afdd6e --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true, + "noEmit": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..2594719 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,14 @@ +import path from "path"; +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@ui": path.resolve(__dirname, "./src/components/ui"), + "@": path.resolve(__dirname, "./src"), + }, + }, +});