diff --git a/.github/workflows/deployWebSample.yml b/.github/workflows/deployWebSample.yml
new file mode 100644
index 0000000000..bb6c21fdfe
--- /dev/null
+++ b/.github/workflows/deployWebSample.yml
@@ -0,0 +1,63 @@
+# Simple workflow for deploying Web SDK Sample to GitHub Pages
+name: Deploy Web SDK Sample to Github Pages
+
+on:
+ pull_request:
+ branches:
+ - 'main'
+ paths:
+ - 'web/**'
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Sets the GITHUB_TOKEN permissions to allow comment on PRs
+permissions:
+ contents: read
+ pull-requests: write
+
+# Allow one concurrent deployment
+concurrency:
+ group: 'pages'
+ cancel-in-progress: true
+
+jobs:
+ # Single deploy job since we're just deploying
+ web-sdk-sample-deploy:
+ runs-on: ubuntu-latest
+ env:
+ SAMPLE_DIR: web/samples/WordWiz
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.14.0'
+
+ - name: Enable pnpm
+ run: |
+ corepack enable
+ corepack use pnpm@10.8.0
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+ working-directory: ${{ env.SAMPLE_DIR }}
+
+ - name: Build
+ run: pnpm run build
+ working-directory: ${{ env.SAMPLE_DIR }}
+
+ - name: Publish Web SDK Sample Build
+ run: ./build/bin/upload-web-sdk-sample-build.sh
+ env:
+ GITHUB_USERNAME: ${{ secrets.GIT_WEB_SDK_SAMPLE_USERNAME }}
+ GITHUB_PASSWORD: ${{ secrets.GIT_WEB_SDK_SAMPLE_PASSWORD }}
+ SAMPLE_DIR: ${{ env.SAMPLE_DIR }}
+
+ - uses: github-actions-up-and-running/pr-comment@v1.0.1
+ if: ${{ github.event_name == 'pull_request' }}
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ message: Web SDK Sample Build [link](https://beamable.github.io/web-sdk-sample/)
diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml
index 56206b45f3..cfd7202967 100644
--- a/.github/workflows/release-web.yml
+++ b/.github/workflows/release-web.yml
@@ -71,7 +71,7 @@ jobs:
# Install project dependencies using pnpm
- name: Install dependencies
- run: pnpm install
+ run: pnpm install --frozen-lockfile
# Run code linter
- name: Lint
diff --git a/build/bin/upload-web-sdk-sample-build.sh b/build/bin/upload-web-sdk-sample-build.sh
new file mode 100755
index 0000000000..8117fd2458
--- /dev/null
+++ b/build/bin/upload-web-sdk-sample-build.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Exit immediately if any command fails
+set -e
+
+# Use GitHub workspace if available, otherwise use current directory
+workspace="${GITHUB_WORKSPACE:-.}"
+
+# Set Up Paths
+build_directory="$workspace/web-sdk-sample-build"
+github_repo_url="https://$GITHUB_USERNAME:$GITHUB_PASSWORD@github.com/beamable/web-sdk-sample.git"
+source_dist_folder="$workspace/$SAMPLE_DIR/dist"
+
+# Validate Source Files Exist
+if [[ ! -d "$source_dist_folder" ]]; then
+ echo "Error: Expected dist folder not found at $source_dist_folder" >&2
+ exit 1
+fi
+
+echo "Preparing build directory..."
+
+# Create fresh build directory
+mkdir -p "$build_directory"
+
+# Move into build directory
+cd "$build_directory"
+
+echo "Setting up git repository..."
+
+git init
+git config user.email "github-actions[bot]@users.noreply.github.com"
+git config user.name "github-actions[bot]"
+git remote add origin "$github_repo_url"
+
+# Fetch existing main branch or create new one
+echo "Checking for existing repository..."
+if git ls-remote --exit-code origin main &>/dev/null; then
+ echo "Found existing main branch, fetching..."
+ git fetch origin main --depth=1
+ git checkout -B main origin/main
+else
+ echo "No existing main branch found, creating new one..."
+ git checkout -B main
+fi
+
+echo "Copying new files..."
+
+cp -a "$source_dist_folder"/. .
+
+echo "Checking for changes..."
+
+# Stage all changes
+git add --all
+git status
+
+# Check if there are any changes to commit
+if git diff --cached --quiet; then
+ echo "No changes detected - nothing to commit"
+else
+ echo "Changes detected, committing and pushing..."
+ git commit -m "Update web sdk sample build"
+ git push --set-upstream --force origin main
+ echo "Successfully deployed changes"
+fi
+
+echo "Done!"
\ No newline at end of file
diff --git a/web/samples/WordWiz/.eslintrc.cjs b/web/samples/WordWiz/.eslintrc.cjs
new file mode 100644
index 0000000000..ca385b7ba9
--- /dev/null
+++ b/web/samples/WordWiz/.eslintrc.cjs
@@ -0,0 +1,31 @@
+module.exports = {
+ env: {
+ browser: true,
+ es2021: true,
+ },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react/recommended',
+ ],
+ overrides: [
+ {
+ env: {
+ node: true,
+ },
+ files: ['.eslintrc.{js,cjs}'],
+ parserOptions: {
+ sourceType: 'script',
+ },
+ },
+ ],
+ parser: '@typescript-eslint/parser',
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ },
+ plugins: ['@typescript-eslint', 'react'],
+ rules: {
+ 'react/react-in-jsx-scope': 0,
+ },
+};
diff --git a/web/samples/WordWiz/.gitignore b/web/samples/WordWiz/.gitignore
new file mode 100644
index 0000000000..c74436aa16
--- /dev/null
+++ b/web/samples/WordWiz/.gitignore
@@ -0,0 +1,26 @@
+# 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?
+
+*.pem
diff --git a/web/samples/WordWiz/.prettierignore b/web/samples/WordWiz/.prettierignore
new file mode 100644
index 0000000000..40b878db5b
--- /dev/null
+++ b/web/samples/WordWiz/.prettierignore
@@ -0,0 +1 @@
+node_modules/
\ No newline at end of file
diff --git a/web/samples/WordWiz/.prettierrc b/web/samples/WordWiz/.prettierrc
new file mode 100644
index 0000000000..108b7935b9
--- /dev/null
+++ b/web/samples/WordWiz/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "printWidth": 80,
+ "bracketSpacing": true,
+ "semi": true,
+ "singleQuote": true
+}
diff --git a/web/samples/WordWiz/README.md b/web/samples/WordWiz/README.md
new file mode 100644
index 0000000000..2fd52689f7
--- /dev/null
+++ b/web/samples/WordWiz/README.md
@@ -0,0 +1,123 @@
+# Word Wiz
+
+This template demonstrates how developers can implement a single-page
+application on the Telegram Mini Apps platform using the following technologies
+and libraries:
+
+- [React](https://react.dev/)
+- [TypeScript](https://www.typescriptlang.org/)
+- [Vite](https://vitejs.dev/)
+
+> The template was created using [npm](https://www.npmjs.com/). Therefore, it is
+> required to use it for this project as well. Using other package managers, you
+> will receive a corresponding error.
+
+## Install Dependencies
+
+If you have just cloned this template, you should install the project
+dependencies using the command:
+
+```Bash
+pnpm install
+```
+
+## Scripts
+
+This project contains the following scripts:
+
+- `dev`. Runs the application in development mode.
+- `dev:https`. Runs the application in development mode using locally created valid SSL-certificates.
+- `build`. Builds the application for production.
+- `lint`. Runs [eslint](https://eslint.org/) to ensure the code quality meets
+ the required standards.
+- `deploy`. Deploys the application to GitHub Pages.
+
+To run a script, use the `pnpm run` command:
+
+```Bash
+pnpm run {script}
+# Example: pnpm run build
+```
+
+## Deploy
+
+This boilerplate uses GitHub Pages as the way to host the application
+externally. GitHub Pages provides a CDN which will let your users receive the
+application rapidly.
+
+### Manual Deployment
+
+This boilerplate uses the [gh-pages](https://www.npmjs.com/package/gh-pages)
+tool, which allows deploying the application right from the PC.
+
+#### Configuring
+
+Before running the deployment process, ensure that you have done the following:
+
+1. Replaced the `homepage` value in `package.json`. The GitHub Pages deploy tool
+ uses this value to
+ determine the related GitHub project.
+2. Replaced the `base` value in `vite.config.ts` and have set it to the name of
+ your GitHub
+ repository. Vite will use this value when creating paths to static assets.
+
+For instance, if your GitHub username is `telegram-mini-apps` and the repository
+name is `is-awesome`, the value in the `homepage` field should be the following:
+
+```json
+{
+ "homepage": "https://telegram-mini-apps.github.io/is-awesome"
+}
+```
+
+And `vite.config.ts` should have this content:
+
+```ts
+export default defineConfig({
+ base: '/is-awesome/',
+ // ...
+});
+```
+
+You can find more information on configuring the deployment in the `gh-pages`
+[docs](https://github.com/tschaub/gh-pages?tab=readme-ov-file#github-pages-project-sites).
+
+#### Before Deploying
+
+Before deploying the application, make sure that you've built it and going to
+deploy the fresh static files:
+
+```bash
+npm run build
+```
+
+Then, run the deployment process, using the `deploy` script:
+
+```Bash
+npm run deploy
+```
+
+### GitHub Workflow
+
+To simplify the deployment process, this template includes a
+pre-configured [GitHub workflow](.github/workflows/github-pages-deploy.yml) that
+automatically deploys the project when changes are pushed to the `master`
+branch.
+
+To enable this workflow, create a new environment (or edit the existing one) in
+the GitHub repository settings and name it `github-pages`. Then, add the
+`master` branch to the list of deployment branches.
+
+You can find the environment settings using this
+URL: `https://github.com/{username}/{repository}/settings/environments`.
+
+
+
+In case, you don't want to do it automatically, or you don't use GitHub as the
+project codebase, remove the `.github` directory.
+
+### GitHub Web Interface
+
+Alternatively, developers can configure automatic deployment using the GitHub
+web interface. To do this, follow the link:
+`https://github.com/{username}/{repository}/settings/pages`.
diff --git a/web/samples/WordWiz/eslint.config.js b/web/samples/WordWiz/eslint.config.js
new file mode 100644
index 0000000000..25715399b1
--- /dev/null
+++ b/web/samples/WordWiz/eslint.config.js
@@ -0,0 +1,41 @@
+// @ts-check
+
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import eslint from '@eslint/js';
+import tseslint from 'typescript-eslint';
+import react from 'eslint-plugin-react';
+import reactHooks from 'eslint-plugin-react-hooks';
+import globals from 'globals';
+
+const baseDir = path.dirname(fileURLToPath(import.meta.url));
+
+export default tseslint.config({
+ files: ['src/**/*.{js,jsx,mjs,cjs,ts,tsx}'],
+ extends: [
+ eslint.configs.recommended,
+ ...tseslint.configs.recommendedTypeChecked,
+ ],
+ plugins: {
+ react,
+ 'react-hooks': reactHooks,
+ },
+ languageOptions: {
+ parserOptions: {
+ project: './tsconfig.json',
+ tsconfigRootDir: baseDir,
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ globals: {
+ ...globals.browser,
+ },
+ },
+ rules: {
+ '@typescript-eslint/no-unused-expressions': 0,
+ },
+});
diff --git a/web/samples/WordWiz/index.html b/web/samples/WordWiz/index.html
new file mode 100644
index 0000000000..cfb8b7b7f3
--- /dev/null
+++ b/web/samples/WordWiz/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Word Wiz
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
diff --git a/web/samples/WordWiz/package.json b/web/samples/WordWiz/package.json
new file mode 100644
index 0000000000..2d11ee55aa
--- /dev/null
+++ b/web/samples/WordWiz/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "wordle-wiz",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "homepage": "https://BeamableProduct.github.io/BeamableProduct/WordWiz/",
+ "scripts": {
+ "deploy": "gh-pages -d dist",
+ "dev": "vite",
+ "dev:https": "cross-env HTTPS=true vite",
+ "build": "tsc --noEmit && vite build",
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
+ "preview": "vite preview",
+ "predeploy": "npm run build",
+ "test": "vitest",
+ "format": "prettier --write ."
+ },
+ "dependencies": {
+ "beamable-sdk": "file:../..",
+ "prettier": "^3.6.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.23.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.23.0",
+ "@types/node": "^20.12.11",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "@typescript-eslint/eslint-plugin": "^8.28.0",
+ "@typescript-eslint/parser": "^8.28.0",
+ "@vitejs/plugin-react-swc": "^3.8.1",
+ "cross-env": "^7.0.3",
+ "eslint": "^9.23.0",
+ "eslint-plugin-react": "^7.37.4",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "gh-pages": "^6.1.1",
+ "globals": "^15.2.0",
+ "typescript": "^5.8.2",
+ "typescript-eslint": "^8.28.0",
+ "vite": "^6.2.4",
+ "vite-plugin-mkcert": "^1.17.8",
+ "vite-tsconfig-paths": "^5.1.4",
+ "vitest": "^3.2.4"
+ }
+}
diff --git a/web/samples/WordWiz/pnpm-lock.yaml b/web/samples/WordWiz/pnpm-lock.yaml
new file mode 100644
index 0000000000..4857855df6
--- /dev/null
+++ b/web/samples/WordWiz/pnpm-lock.yaml
@@ -0,0 +1,4977 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+ .:
+ dependencies:
+ beamable-sdk:
+ specifier: file:../..
+ version: file:../..
+ prettier:
+ specifier: ^3.6.2
+ version: 3.6.2
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^6.23.0
+ version: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.23.0
+ version: 9.36.0
+ '@types/node':
+ specifier: ^20.12.11
+ version: 20.19.17
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.24
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.24)
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^8.28.0
+ version: 8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0)(typescript@5.9.2))(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/parser':
+ specifier: ^8.28.0
+ version: 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.8.1
+ version: 3.11.0(vite@6.3.6(@types/node@20.19.17))
+ cross-env:
+ specifier: ^7.0.3
+ version: 7.0.3
+ eslint:
+ specifier: ^9.23.0
+ version: 9.36.0
+ eslint-plugin-react:
+ specifier: ^7.37.4
+ version: 7.37.5(eslint@9.36.0)
+ eslint-plugin-react-hooks:
+ specifier: ^5.2.0
+ version: 5.2.0(eslint@9.36.0)
+ gh-pages:
+ specifier: ^6.1.1
+ version: 6.3.0
+ globals:
+ specifier: ^15.2.0
+ version: 15.15.0
+ typescript:
+ specifier: ^5.8.2
+ version: 5.9.2
+ typescript-eslint:
+ specifier: ^8.28.0
+ version: 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ vite:
+ specifier: ^6.2.4
+ version: 6.3.6(@types/node@20.19.17)
+ vite-plugin-mkcert:
+ specifier: ^1.17.8
+ version: 1.17.8(vite@6.3.6(@types/node@20.19.17))
+ vite-tsconfig-paths:
+ specifier: ^5.1.4
+ version: 5.1.4(typescript@5.9.2)(vite@6.3.6(@types/node@20.19.17))
+ vitest:
+ specifier: ^3.2.4
+ version: 3.2.4(@types/node@20.19.17)
+
+packages:
+ '@esbuild/aix-ppc64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.10':
+ resolution:
+ {
+ integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.10':
+ resolution:
+ {
+ integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.10':
+ resolution:
+ {
+ integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==,
+ }
+ engines: { node: '>=18' }
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==,
+ }
+ engines: { node: '>=18' }
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.10':
+ resolution:
+ {
+ integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.10':
+ resolution:
+ {
+ integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==,
+ }
+ engines: { node: '>=18' }
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.10':
+ resolution:
+ {
+ integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.10':
+ resolution:
+ {
+ integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==,
+ }
+ engines: { node: '>=18' }
+ cpu: [x64]
+ os: [win32]
+
+ '@eslint-community/eslint-utils@4.9.0':
+ resolution:
+ {
+ integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==,
+ }
+ 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.12.1':
+ resolution:
+ {
+ integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==,
+ }
+ engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 }
+
+ '@eslint/config-array@0.21.0':
+ resolution:
+ {
+ integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/config-helpers@0.3.1':
+ resolution:
+ {
+ integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/core@0.15.2':
+ resolution:
+ {
+ integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/eslintrc@3.3.1':
+ resolution:
+ {
+ integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/js@9.36.0':
+ resolution:
+ {
+ integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/object-schema@2.1.6':
+ resolution:
+ {
+ integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@eslint/plugin-kit@0.3.5':
+ resolution:
+ {
+ integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@humanfs/core@0.19.1':
+ resolution:
+ {
+ integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==,
+ }
+ engines: { node: '>=18.18.0' }
+
+ '@humanfs/node@0.16.7':
+ resolution:
+ {
+ integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==,
+ }
+ engines: { node: '>=18.18.0' }
+
+ '@humanwhocodes/module-importer@1.0.1':
+ resolution:
+ {
+ integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==,
+ }
+ engines: { node: '>=12.22' }
+
+ '@humanwhocodes/retry@0.4.3':
+ resolution:
+ {
+ integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==,
+ }
+ engines: { node: '>=18.18' }
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution:
+ {
+ integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==,
+ }
+
+ '@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' }
+
+ '@remix-run/router@1.23.0':
+ resolution:
+ {
+ integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==,
+ }
+ engines: { node: '>=14.0.0' }
+
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution:
+ {
+ integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==,
+ }
+
+ '@rollup/rollup-android-arm-eabi@4.52.2':
+ resolution:
+ {
+ integrity: sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==,
+ }
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==,
+ }
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==,
+ }
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==,
+ }
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==,
+ }
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==,
+ }
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.2':
+ resolution:
+ {
+ integrity: sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==,
+ }
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.2':
+ resolution:
+ {
+ integrity: sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==,
+ }
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==,
+ }
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.52.2':
+ resolution:
+ {
+ integrity: sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==,
+ }
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==,
+ }
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==,
+ }
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==,
+ }
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.2':
+ resolution:
+ {
+ integrity: sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==,
+ }
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==,
+ }
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==,
+ }
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.52.2':
+ resolution:
+ {
+ integrity: sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==,
+ }
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openharmony-arm64@4.52.2':
+ resolution:
+ {
+ integrity: sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==,
+ }
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.2':
+ resolution:
+ {
+ integrity: sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==,
+ }
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.2':
+ resolution:
+ {
+ integrity: sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==,
+ }
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.52.2':
+ resolution:
+ {
+ integrity: sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==,
+ }
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.52.2':
+ resolution:
+ {
+ integrity: sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==,
+ }
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core-darwin-arm64@1.13.19':
+ resolution:
+ {
+ integrity: sha512-NxDyte9tCJSJ8+R62WDtqwg8eI57lubD52sHyGOfezpJBOPr36bUSGGLyO3Vod9zTGlOu2CpkuzA/2iVw92u1g==,
+ }
+ engines: { node: '>=10' }
+ cpu: [arm64]
+ os: [darwin]
+
+ '@swc/core-darwin-x64@1.13.19':
+ resolution:
+ {
+ integrity: sha512-+w5DYrJndSygFFRDcuPYmx5BljD6oYnAohZ15K1L6SfORHp/BTSIbgSFRKPoyhjuIkDiq3W0um8RoMTOBAcQjQ==,
+ }
+ engines: { node: '>=10' }
+ cpu: [x64]
+ os: [darwin]
+
+ '@swc/core-linux-arm-gnueabihf@1.13.19':
+ resolution:
+ {
+ integrity: sha512-7LlfgpdwwYq2q7himNkAAFo4q6jysMLFNoBH6GRP7WL29NcSsl5mPMJjmYZymK+sYq/9MTVieDTQvChzYDsapw==,
+ }
+ engines: { node: '>=10' }
+ cpu: [arm]
+ os: [linux]
+
+ '@swc/core-linux-arm64-gnu@1.13.19':
+ resolution:
+ {
+ integrity: sha512-ml3I6Lm2marAQ3UC/TS9t/yILBh/eDSVHAdPpikp652xouWAVW1znUeV6bBSxe1sSZIenv+p55ubKAWq/u84sQ==,
+ }
+ engines: { node: '>=10' }
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-arm64-musl@1.13.19':
+ resolution:
+ {
+ integrity: sha512-M/otFc3/rWWkbF6VgbOXVzUKVoE7MFcphTaStxJp4bwb7oP5slYlxMZN51Dk/OTOfvCDo9pTAFDKNyixbkXMDQ==,
+ }
+ engines: { node: '>=10' }
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-x64-gnu@1.13.19':
+ resolution:
+ {
+ integrity: sha512-NoMUKaOJEdouU4tKF88ggdDHFiRRING+gYLxDqnTfm+sUXaizB5OGBRzvSVDYSXQb1SuUuChnXFPFzwTWbt3ZQ==,
+ }
+ engines: { node: '>=10' }
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-linux-x64-musl@1.13.19':
+ resolution:
+ {
+ integrity: sha512-r6krlZwyu8SBaw24QuS1lau2I9q8M+eJV6ITz0rpb6P1Bx0elf9ii5Bhh8ddmIqXXH8kOGSjC/dwcdHbZqAhgw==,
+ }
+ engines: { node: '>=10' }
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-win32-arm64-msvc@1.13.19':
+ resolution:
+ {
+ integrity: sha512-awcZSIuxyVn0Dw28VjMvgk1qiDJ6CeQwHkZNUjg2UxVlq23zE01NMMp+zkoGFypmLG9gaGmJSzuoqvk/WCQ5tw==,
+ }
+ engines: { node: '>=10' }
+ cpu: [arm64]
+ os: [win32]
+
+ '@swc/core-win32-ia32-msvc@1.13.19':
+ resolution:
+ {
+ integrity: sha512-H5d+KO7ISoLNgYvTbOcCQjJZNM3R7yaYlrMAF13lUr6GSiOUX+92xtM31B+HvzAWI7HtvVe74d29aC1b1TpXFA==,
+ }
+ engines: { node: '>=10' }
+ cpu: [ia32]
+ os: [win32]
+
+ '@swc/core-win32-x64-msvc@1.13.19':
+ resolution:
+ {
+ integrity: sha512-qNoyCpXvv2O3JqXKanRIeoMn03Fho/As+N4Fhe7u0FsYh4VYqGQah4DGDzEP/yjl4Gx1IElhqLGDhCCGMwWaDw==,
+ }
+ engines: { node: '>=10' }
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core@1.13.19':
+ resolution:
+ {
+ integrity: sha512-V1r4wFdjaZIUIZZrV2Mb/prEeu03xvSm6oatPxsvnXKF9lNh5Jtk9QvUdiVfD9rrvi7bXrAVhg9Wpbmv/2Fl1g==,
+ }
+ engines: { node: '>=10' }
+ peerDependencies:
+ '@swc/helpers': '>=0.5.17'
+ peerDependenciesMeta:
+ '@swc/helpers':
+ optional: true
+
+ '@swc/counter@0.1.3':
+ resolution:
+ {
+ integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==,
+ }
+
+ '@swc/types@0.1.25':
+ resolution:
+ {
+ integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==,
+ }
+
+ '@types/chai@5.2.2':
+ resolution:
+ {
+ integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==,
+ }
+
+ '@types/deep-eql@4.0.2':
+ resolution:
+ {
+ integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==,
+ }
+
+ '@types/estree@1.0.8':
+ resolution:
+ {
+ integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==,
+ }
+
+ '@types/json-schema@7.0.15':
+ resolution:
+ {
+ integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==,
+ }
+
+ '@types/node@20.19.17':
+ resolution:
+ {
+ integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==,
+ }
+
+ '@types/prop-types@15.7.15':
+ resolution:
+ {
+ integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==,
+ }
+
+ '@types/react-dom@18.3.7':
+ resolution:
+ {
+ integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==,
+ }
+ peerDependencies:
+ '@types/react': ^18.0.0
+
+ '@types/react@18.3.24':
+ resolution:
+ {
+ integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==,
+ }
+
+ '@typescript-eslint/eslint-plugin@8.44.1':
+ resolution:
+ {
+ integrity: sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.44.1
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/parser@8.44.1':
+ resolution:
+ {
+ integrity: sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/project-service@8.44.1':
+ resolution:
+ {
+ integrity: sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/scope-manager@8.44.1':
+ resolution:
+ {
+ integrity: sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@typescript-eslint/tsconfig-utils@8.44.1':
+ resolution:
+ {
+ integrity: sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/type-utils@8.44.1':
+ resolution:
+ {
+ integrity: sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/types@8.44.1':
+ resolution:
+ {
+ integrity: sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@typescript-eslint/typescript-estree@8.44.1':
+ resolution:
+ {
+ integrity: sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/utils@8.44.1':
+ resolution:
+ {
+ integrity: sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/visitor-keys@8.44.1':
+ resolution:
+ {
+ integrity: sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ '@vitejs/plugin-react-swc@3.11.0':
+ resolution:
+ {
+ integrity: sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==,
+ }
+ peerDependencies:
+ vite: ^4 || ^5 || ^6 || ^7
+
+ '@vitest/expect@3.2.4':
+ resolution:
+ {
+ integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==,
+ }
+
+ '@vitest/mocker@3.2.4':
+ resolution:
+ {
+ integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==,
+ }
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@3.2.4':
+ resolution:
+ {
+ integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==,
+ }
+
+ '@vitest/runner@3.2.4':
+ resolution:
+ {
+ integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==,
+ }
+
+ '@vitest/snapshot@3.2.4':
+ resolution:
+ {
+ integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==,
+ }
+
+ '@vitest/spy@3.2.4':
+ resolution:
+ {
+ integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==,
+ }
+
+ '@vitest/utils@3.2.4':
+ resolution:
+ {
+ integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==,
+ }
+
+ acorn-jsx@5.3.2:
+ resolution:
+ {
+ integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==,
+ }
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn@8.15.0:
+ resolution:
+ {
+ integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==,
+ }
+ engines: { node: '>=0.4.0' }
+ hasBin: true
+
+ ajv@6.12.6:
+ resolution:
+ {
+ integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==,
+ }
+
+ ansi-styles@4.3.0:
+ resolution:
+ {
+ integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==,
+ }
+ engines: { node: '>=8' }
+
+ argparse@2.0.1:
+ resolution:
+ {
+ integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==,
+ }
+
+ array-buffer-byte-length@1.0.2:
+ resolution:
+ {
+ integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ array-includes@3.1.9:
+ resolution:
+ {
+ integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ array-union@2.1.0:
+ resolution:
+ {
+ integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==,
+ }
+ engines: { node: '>=8' }
+
+ array.prototype.findlast@1.2.5:
+ resolution:
+ {
+ integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ array.prototype.flat@1.3.3:
+ resolution:
+ {
+ integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ array.prototype.flatmap@1.3.3:
+ resolution:
+ {
+ integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ array.prototype.tosorted@1.1.4:
+ resolution:
+ {
+ integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ arraybuffer.prototype.slice@1.0.4:
+ resolution:
+ {
+ integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ assertion-error@2.0.1:
+ resolution:
+ {
+ integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==,
+ }
+ engines: { node: '>=12' }
+
+ async-function@1.0.0:
+ resolution:
+ {
+ integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ async@3.2.6:
+ resolution:
+ {
+ integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==,
+ }
+
+ asynckit@0.4.0:
+ resolution:
+ {
+ integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==,
+ }
+
+ available-typed-arrays@1.0.7:
+ resolution:
+ {
+ integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ axios@1.12.2:
+ resolution:
+ {
+ integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==,
+ }
+
+ balanced-match@1.0.2:
+ resolution:
+ {
+ integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==,
+ }
+
+ beamable-sdk@file:../..:
+ resolution: { directory: ../.., type: directory }
+ engines: { node: '>=22.14.0' }
+
+ brace-expansion@1.1.12:
+ resolution:
+ {
+ integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==,
+ }
+
+ brace-expansion@2.0.2:
+ resolution:
+ {
+ integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==,
+ }
+
+ braces@3.0.3:
+ resolution:
+ {
+ integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==,
+ }
+ engines: { node: '>=8' }
+
+ cac@6.7.14:
+ resolution:
+ {
+ integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==,
+ }
+ engines: { node: '>=8' }
+
+ call-bind-apply-helpers@1.0.2:
+ resolution:
+ {
+ integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ call-bind@1.0.8:
+ resolution:
+ {
+ integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==,
+ }
+ engines: { node: '>= 0.4' }
+
+ call-bound@1.0.4:
+ resolution:
+ {
+ integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ callsites@3.1.0:
+ resolution:
+ {
+ integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==,
+ }
+ engines: { node: '>=6' }
+
+ chai@5.3.3:
+ resolution:
+ {
+ integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==,
+ }
+ engines: { node: '>=18' }
+
+ chalk@4.1.2:
+ resolution:
+ {
+ integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==,
+ }
+ engines: { node: '>=10' }
+
+ check-error@2.1.1:
+ resolution:
+ {
+ integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==,
+ }
+ engines: { node: '>= 16' }
+
+ color-convert@2.0.1:
+ resolution:
+ {
+ integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==,
+ }
+ engines: { node: '>=7.0.0' }
+
+ color-name@1.1.4:
+ resolution:
+ {
+ integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==,
+ }
+
+ combined-stream@1.0.8:
+ resolution:
+ {
+ integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==,
+ }
+ engines: { node: '>= 0.8' }
+
+ commander@13.1.0:
+ resolution:
+ {
+ integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==,
+ }
+ engines: { node: '>=18' }
+
+ commondir@1.0.1:
+ resolution:
+ {
+ integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==,
+ }
+
+ concat-map@0.0.1:
+ resolution:
+ {
+ integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==,
+ }
+
+ cross-env@7.0.3:
+ resolution:
+ {
+ integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==,
+ }
+ engines: { node: '>=10.14', npm: '>=6', yarn: '>=1' }
+ hasBin: true
+
+ cross-spawn@7.0.6:
+ resolution:
+ {
+ integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==,
+ }
+ engines: { node: '>= 8' }
+
+ csstype@3.1.3:
+ resolution:
+ {
+ integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==,
+ }
+
+ data-view-buffer@1.0.2:
+ resolution:
+ {
+ integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ data-view-byte-length@1.0.2:
+ resolution:
+ {
+ integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ data-view-byte-offset@1.0.1:
+ resolution:
+ {
+ integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ debug@4.4.3:
+ resolution:
+ {
+ integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==,
+ }
+ engines: { node: '>=6.0' }
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-eql@5.0.2:
+ resolution:
+ {
+ integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==,
+ }
+ engines: { node: '>=6' }
+
+ deep-is@0.1.4:
+ resolution:
+ {
+ integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==,
+ }
+
+ define-data-property@1.1.4:
+ resolution:
+ {
+ integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ define-properties@1.2.1:
+ resolution:
+ {
+ integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ delayed-stream@1.0.0:
+ resolution:
+ {
+ integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==,
+ }
+ engines: { node: '>=0.4.0' }
+
+ dir-glob@3.0.1:
+ resolution:
+ {
+ integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==,
+ }
+ engines: { node: '>=8' }
+
+ doctrine@2.1.0:
+ resolution:
+ {
+ integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ dunder-proto@1.0.1:
+ resolution:
+ {
+ integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ email-addresses@5.0.0:
+ resolution:
+ {
+ integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==,
+ }
+
+ es-abstract@1.24.0:
+ resolution:
+ {
+ integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-define-property@1.0.1:
+ resolution:
+ {
+ integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-errors@1.3.0:
+ resolution:
+ {
+ integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-iterator-helpers@1.2.1:
+ resolution:
+ {
+ integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-module-lexer@1.7.0:
+ resolution:
+ {
+ integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==,
+ }
+
+ es-object-atoms@1.1.1:
+ resolution:
+ {
+ integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-set-tostringtag@2.1.0:
+ resolution:
+ {
+ integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-shim-unscopables@1.1.0:
+ resolution:
+ {
+ integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ es-to-primitive@1.3.0:
+ resolution:
+ {
+ integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ esbuild@0.25.10:
+ resolution:
+ {
+ integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==,
+ }
+ engines: { node: '>=18' }
+ hasBin: true
+
+ 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@5.2.0:
+ resolution:
+ {
+ integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==,
+ }
+ engines: { node: '>=10' }
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
+ eslint-plugin-react@7.37.5:
+ resolution:
+ {
+ integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==,
+ }
+ engines: { node: '>=4' }
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+
+ eslint-scope@8.4.0:
+ resolution:
+ {
+ integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.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-visitor-keys@4.2.1:
+ resolution:
+ {
+ integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+
+ eslint@9.36.0:
+ resolution:
+ {
+ integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
+ espree@10.4.0:
+ resolution:
+ {
+ integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.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' }
+
+ estree-walker@3.0.3:
+ resolution:
+ {
+ integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==,
+ }
+
+ esutils@2.0.3:
+ resolution:
+ {
+ integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ expect-type@1.2.2:
+ resolution:
+ {
+ integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==,
+ }
+ engines: { node: '>=12.0.0' }
+
+ fast-deep-equal@3.1.3:
+ resolution:
+ {
+ integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==,
+ }
+
+ fast-glob@3.3.3:
+ resolution:
+ {
+ integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==,
+ }
+ 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==,
+ }
+
+ fastq@1.19.1:
+ resolution:
+ {
+ integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==,
+ }
+
+ fdir@6.5.0:
+ resolution:
+ {
+ integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==,
+ }
+ engines: { node: '>=12.0.0' }
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ file-entry-cache@8.0.0:
+ resolution:
+ {
+ integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==,
+ }
+ engines: { node: '>=16.0.0' }
+
+ filename-reserved-regex@2.0.0:
+ resolution:
+ {
+ integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==,
+ }
+ engines: { node: '>=4' }
+
+ filenamify@4.3.0:
+ resolution:
+ {
+ integrity: sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==,
+ }
+ engines: { node: '>=8' }
+
+ fill-range@7.1.1:
+ resolution:
+ {
+ integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==,
+ }
+ engines: { node: '>=8' }
+
+ find-cache-dir@3.3.2:
+ resolution:
+ {
+ integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==,
+ }
+ engines: { node: '>=8' }
+
+ find-up@4.1.0:
+ resolution:
+ {
+ integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==,
+ }
+ engines: { node: '>=8' }
+
+ find-up@5.0.0:
+ resolution:
+ {
+ integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==,
+ }
+ engines: { node: '>=10' }
+
+ flat-cache@4.0.1:
+ resolution:
+ {
+ integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==,
+ }
+ engines: { node: '>=16' }
+
+ flatted@3.3.3:
+ resolution:
+ {
+ integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==,
+ }
+
+ follow-redirects@1.15.11:
+ resolution:
+ {
+ integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==,
+ }
+ engines: { node: '>=4.0' }
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ for-each@0.3.5:
+ resolution:
+ {
+ integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ form-data@4.0.4:
+ resolution:
+ {
+ integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==,
+ }
+ engines: { node: '>= 6' }
+
+ fs-extra@11.3.2:
+ resolution:
+ {
+ integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==,
+ }
+ engines: { node: '>=14.14' }
+
+ 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==,
+ }
+
+ function.prototype.name@1.1.8:
+ resolution:
+ {
+ integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==,
+ }
+ engines: { node: '>= 0.4' }
+
+ functions-have-names@1.2.3:
+ resolution:
+ {
+ integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==,
+ }
+
+ get-intrinsic@1.3.0:
+ resolution:
+ {
+ integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ get-proto@1.0.1:
+ resolution:
+ {
+ integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ get-symbol-description@1.1.0:
+ resolution:
+ {
+ integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ gh-pages@6.3.0:
+ resolution:
+ {
+ integrity: sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==,
+ }
+ engines: { node: '>=10' }
+ hasBin: true
+
+ 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' }
+
+ globals@14.0.0:
+ resolution:
+ {
+ integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==,
+ }
+ engines: { node: '>=18' }
+
+ globals@15.15.0:
+ resolution:
+ {
+ integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==,
+ }
+ engines: { node: '>=18' }
+
+ globalthis@1.0.4:
+ resolution:
+ {
+ integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ globby@11.1.0:
+ resolution:
+ {
+ integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==,
+ }
+ engines: { node: '>=10' }
+
+ globrex@0.1.2:
+ resolution:
+ {
+ integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==,
+ }
+
+ gopd@1.2.0:
+ resolution:
+ {
+ integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ graceful-fs@4.2.11:
+ resolution:
+ {
+ integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==,
+ }
+
+ graphemer@1.4.0:
+ resolution:
+ {
+ integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==,
+ }
+
+ has-bigints@1.1.0:
+ resolution:
+ {
+ integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ has-flag@4.0.0:
+ resolution:
+ {
+ integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==,
+ }
+ engines: { node: '>=8' }
+
+ has-property-descriptors@1.0.2:
+ resolution:
+ {
+ integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==,
+ }
+
+ has-proto@1.2.0:
+ resolution:
+ {
+ integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ has-symbols@1.1.0:
+ resolution:
+ {
+ integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ has-tostringtag@1.0.2:
+ resolution:
+ {
+ integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ hasown@2.0.2:
+ resolution:
+ {
+ integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ ignore@5.3.2:
+ resolution:
+ {
+ integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==,
+ }
+ engines: { node: '>= 4' }
+
+ ignore@7.0.5:
+ resolution:
+ {
+ integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==,
+ }
+ engines: { node: '>= 4' }
+
+ import-fresh@3.3.1:
+ resolution:
+ {
+ integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==,
+ }
+ engines: { node: '>=6' }
+
+ imurmurhash@0.1.4:
+ resolution:
+ {
+ integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==,
+ }
+ engines: { node: '>=0.8.19' }
+
+ internal-slot@1.1.0:
+ resolution:
+ {
+ integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-array-buffer@3.0.5:
+ resolution:
+ {
+ integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-async-function@2.1.1:
+ resolution:
+ {
+ integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-bigint@1.1.0:
+ resolution:
+ {
+ integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-boolean-object@1.2.2:
+ resolution:
+ {
+ integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-callable@1.2.7:
+ resolution:
+ {
+ integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-core-module@2.16.1:
+ resolution:
+ {
+ integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-data-view@1.0.2:
+ resolution:
+ {
+ integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-date-object@1.1.0:
+ resolution:
+ {
+ integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-extglob@2.1.1:
+ resolution:
+ {
+ integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ is-finalizationregistry@1.1.1:
+ resolution:
+ {
+ integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-generator-function@1.1.0:
+ resolution:
+ {
+ integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-glob@4.0.3:
+ resolution:
+ {
+ integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ is-map@2.0.3:
+ resolution:
+ {
+ integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-negative-zero@2.0.3:
+ resolution:
+ {
+ integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-number-object@1.1.1:
+ resolution:
+ {
+ integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-number@7.0.0:
+ resolution:
+ {
+ integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==,
+ }
+ engines: { node: '>=0.12.0' }
+
+ is-regex@1.2.1:
+ resolution:
+ {
+ integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-set@2.0.3:
+ resolution:
+ {
+ integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-shared-array-buffer@1.0.4:
+ resolution:
+ {
+ integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-string@1.1.1:
+ resolution:
+ {
+ integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-symbol@1.1.1:
+ resolution:
+ {
+ integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-typed-array@1.1.15:
+ resolution:
+ {
+ integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-weakmap@2.0.2:
+ resolution:
+ {
+ integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-weakref@1.1.1:
+ resolution:
+ {
+ integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==,
+ }
+ engines: { node: '>= 0.4' }
+
+ is-weakset@2.0.4:
+ resolution:
+ {
+ integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ isarray@2.0.5:
+ resolution:
+ {
+ integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==,
+ }
+
+ isexe@2.0.0:
+ resolution:
+ {
+ integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==,
+ }
+
+ iterator.prototype@1.1.5:
+ resolution:
+ {
+ integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ js-tokens@4.0.0:
+ resolution:
+ {
+ integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==,
+ }
+
+ js-tokens@9.0.1:
+ resolution:
+ {
+ integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==,
+ }
+
+ js-yaml@4.1.0:
+ resolution:
+ {
+ integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==,
+ }
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution:
+ {
+ integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==,
+ }
+
+ 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==,
+ }
+
+ jsonfile@6.2.0:
+ resolution:
+ {
+ integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==,
+ }
+
+ jsx-ast-utils@3.3.5:
+ resolution:
+ {
+ integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==,
+ }
+ engines: { node: '>=4.0' }
+
+ 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' }
+
+ locate-path@5.0.0:
+ resolution:
+ {
+ integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==,
+ }
+ engines: { node: '>=8' }
+
+ locate-path@6.0.0:
+ resolution:
+ {
+ integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==,
+ }
+ engines: { node: '>=10' }
+
+ 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
+
+ loupe@3.2.1:
+ resolution:
+ {
+ integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==,
+ }
+
+ magic-string@0.30.19:
+ resolution:
+ {
+ integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==,
+ }
+
+ make-dir@3.1.0:
+ resolution:
+ {
+ integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==,
+ }
+ engines: { node: '>=8' }
+
+ math-intrinsics@1.1.0:
+ resolution:
+ {
+ integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==,
+ }
+ engines: { node: '>= 0.4' }
+
+ merge2@1.4.1:
+ resolution:
+ {
+ integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==,
+ }
+ engines: { node: '>= 8' }
+
+ micromatch@4.0.8:
+ resolution:
+ {
+ integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==,
+ }
+ engines: { node: '>=8.6' }
+
+ mime-db@1.52.0:
+ resolution:
+ {
+ integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==,
+ }
+ engines: { node: '>= 0.6' }
+
+ mime-types@2.1.35:
+ resolution:
+ {
+ integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==,
+ }
+ engines: { node: '>= 0.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' }
+
+ ms@2.1.3:
+ resolution:
+ {
+ integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==,
+ }
+
+ nanoid@3.3.11:
+ resolution:
+ {
+ integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==,
+ }
+ engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 }
+ hasBin: true
+
+ natural-compare@1.4.0:
+ resolution:
+ {
+ integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==,
+ }
+
+ object-assign@4.1.1:
+ resolution:
+ {
+ integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ object-inspect@1.13.4:
+ resolution:
+ {
+ integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==,
+ }
+ engines: { node: '>= 0.4' }
+
+ object-keys@1.1.1:
+ resolution:
+ {
+ integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ object.assign@4.1.7:
+ resolution:
+ {
+ integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ object.entries@1.1.9:
+ resolution:
+ {
+ integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ object.fromentries@2.0.8:
+ resolution:
+ {
+ integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ object.values@1.2.1:
+ resolution:
+ {
+ integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ optionator@0.9.4:
+ resolution:
+ {
+ integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==,
+ }
+ engines: { node: '>= 0.8.0' }
+
+ own-keys@1.0.1:
+ resolution:
+ {
+ integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ p-limit@2.3.0:
+ resolution:
+ {
+ integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==,
+ }
+ engines: { node: '>=6' }
+
+ p-limit@3.1.0:
+ resolution:
+ {
+ integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==,
+ }
+ engines: { node: '>=10' }
+
+ p-locate@4.1.0:
+ resolution:
+ {
+ integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==,
+ }
+ engines: { node: '>=8' }
+
+ p-locate@5.0.0:
+ resolution:
+ {
+ integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==,
+ }
+ engines: { node: '>=10' }
+
+ p-try@2.2.0:
+ resolution:
+ {
+ integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==,
+ }
+ engines: { node: '>=6' }
+
+ parent-module@1.0.1:
+ resolution:
+ {
+ integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==,
+ }
+ engines: { node: '>=6' }
+
+ path-exists@4.0.0:
+ resolution:
+ {
+ integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==,
+ }
+ engines: { node: '>=8' }
+
+ 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-type@4.0.0:
+ resolution:
+ {
+ integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==,
+ }
+ engines: { node: '>=8' }
+
+ pathe@2.0.3:
+ resolution:
+ {
+ integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==,
+ }
+
+ pathval@2.0.1:
+ resolution:
+ {
+ integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==,
+ }
+ engines: { node: '>= 14.16' }
+
+ picocolors@1.1.1:
+ resolution:
+ {
+ integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==,
+ }
+
+ picomatch@2.3.1:
+ resolution:
+ {
+ integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==,
+ }
+ engines: { node: '>=8.6' }
+
+ picomatch@4.0.3:
+ resolution:
+ {
+ integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==,
+ }
+ engines: { node: '>=12' }
+
+ pkg-dir@4.2.0:
+ resolution:
+ {
+ integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==,
+ }
+ engines: { node: '>=8' }
+
+ possible-typed-array-names@1.1.0:
+ resolution:
+ {
+ integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ postcss@8.5.6:
+ resolution:
+ {
+ integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==,
+ }
+ engines: { node: ^10 || ^12 || >=14 }
+
+ prelude-ls@1.2.1:
+ resolution:
+ {
+ integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==,
+ }
+ engines: { node: '>= 0.8.0' }
+
+ prettier@3.6.2:
+ resolution:
+ {
+ integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==,
+ }
+ engines: { node: '>=14' }
+ hasBin: true
+
+ prop-types@15.8.1:
+ resolution:
+ {
+ integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==,
+ }
+
+ proxy-from-env@1.1.0:
+ resolution:
+ {
+ integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==,
+ }
+
+ 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-is@16.13.1:
+ resolution:
+ {
+ integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==,
+ }
+
+ react-router-dom@6.30.1:
+ resolution:
+ {
+ integrity: sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==,
+ }
+ engines: { node: '>=14.0.0' }
+ peerDependencies:
+ react: '>=16.8'
+ react-dom: '>=16.8'
+
+ react-router@6.30.1:
+ resolution:
+ {
+ integrity: sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==,
+ }
+ 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' }
+
+ reflect.getprototypeof@1.0.10:
+ resolution:
+ {
+ integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ regexp.prototype.flags@1.5.4:
+ resolution:
+ {
+ integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ resolve-from@4.0.0:
+ resolution:
+ {
+ integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==,
+ }
+ engines: { node: '>=4' }
+
+ resolve@2.0.0-next.5:
+ resolution:
+ {
+ integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==,
+ }
+ hasBin: true
+
+ reusify@1.1.0:
+ resolution:
+ {
+ integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==,
+ }
+ engines: { iojs: '>=1.0.0', node: '>=0.10.0' }
+
+ rollup@4.52.2:
+ resolution:
+ {
+ integrity: sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==,
+ }
+ engines: { node: '>=18.0.0', npm: '>=8.0.0' }
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution:
+ {
+ integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==,
+ }
+
+ safe-array-concat@1.1.3:
+ resolution:
+ {
+ integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==,
+ }
+ engines: { node: '>=0.4' }
+
+ safe-push-apply@1.0.0:
+ resolution:
+ {
+ integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ safe-regex-test@1.1.0:
+ resolution:
+ {
+ integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ scheduler@0.23.2:
+ resolution:
+ {
+ integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==,
+ }
+
+ semver@6.3.1:
+ resolution:
+ {
+ integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==,
+ }
+ hasBin: true
+
+ semver@7.7.2:
+ resolution:
+ {
+ integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==,
+ }
+ engines: { node: '>=10' }
+ hasBin: true
+
+ set-function-length@1.2.2:
+ resolution:
+ {
+ integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ set-function-name@2.0.2:
+ resolution:
+ {
+ integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ set-proto@1.0.0:
+ resolution:
+ {
+ integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ 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' }
+
+ side-channel-list@1.0.0:
+ resolution:
+ {
+ integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ side-channel-map@1.0.1:
+ resolution:
+ {
+ integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ side-channel-weakmap@1.0.2:
+ resolution:
+ {
+ integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==,
+ }
+ engines: { node: '>= 0.4' }
+
+ side-channel@1.1.0:
+ resolution:
+ {
+ integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ siginfo@2.0.0:
+ resolution:
+ {
+ integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==,
+ }
+
+ slash@3.0.0:
+ resolution:
+ {
+ integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==,
+ }
+ engines: { node: '>=8' }
+
+ source-map-js@1.2.1:
+ resolution:
+ {
+ integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ stackback@0.0.2:
+ resolution:
+ {
+ integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==,
+ }
+
+ std-env@3.9.0:
+ resolution:
+ {
+ integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==,
+ }
+
+ stop-iteration-iterator@1.1.0:
+ resolution:
+ {
+ integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ string.prototype.matchall@4.0.12:
+ resolution:
+ {
+ integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ string.prototype.repeat@1.0.0:
+ resolution:
+ {
+ integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==,
+ }
+
+ string.prototype.trim@1.2.10:
+ resolution:
+ {
+ integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ string.prototype.trimend@1.0.9:
+ resolution:
+ {
+ integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ string.prototype.trimstart@1.0.8:
+ resolution:
+ {
+ integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ strip-json-comments@3.1.1:
+ resolution:
+ {
+ integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==,
+ }
+ engines: { node: '>=8' }
+
+ strip-literal@3.0.0:
+ resolution:
+ {
+ integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==,
+ }
+
+ strip-outer@1.0.1:
+ resolution:
+ {
+ integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ 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' }
+
+ tinybench@2.9.0:
+ resolution:
+ {
+ integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==,
+ }
+
+ tinyexec@0.3.2:
+ resolution:
+ {
+ integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==,
+ }
+
+ tinyglobby@0.2.15:
+ resolution:
+ {
+ integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==,
+ }
+ engines: { node: '>=12.0.0' }
+
+ tinypool@1.1.1:
+ resolution:
+ {
+ integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==,
+ }
+ engines: { node: ^18.0.0 || >=20.0.0 }
+
+ tinyrainbow@2.0.0:
+ resolution:
+ {
+ integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==,
+ }
+ engines: { node: '>=14.0.0' }
+
+ tinyspy@4.0.4:
+ resolution:
+ {
+ integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==,
+ }
+ engines: { node: '>=14.0.0' }
+
+ to-regex-range@5.0.1:
+ resolution:
+ {
+ integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==,
+ }
+ engines: { node: '>=8.0' }
+
+ trim-repeated@1.0.0:
+ resolution:
+ {
+ integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ ts-api-utils@2.1.0:
+ resolution:
+ {
+ integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==,
+ }
+ engines: { node: '>=18.12' }
+ peerDependencies:
+ typescript: '>=4.8.4'
+
+ tsconfck@3.1.6:
+ resolution:
+ {
+ integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==,
+ }
+ engines: { node: ^18 || >=20 }
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ type-check@0.4.0:
+ resolution:
+ {
+ integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==,
+ }
+ engines: { node: '>= 0.8.0' }
+
+ typed-array-buffer@1.0.3:
+ resolution:
+ {
+ integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ typed-array-byte-length@1.0.3:
+ resolution:
+ {
+ integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ typed-array-byte-offset@1.0.4:
+ resolution:
+ {
+ integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==,
+ }
+ engines: { node: '>= 0.4' }
+
+ typed-array-length@1.0.7:
+ resolution:
+ {
+ integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==,
+ }
+ engines: { node: '>= 0.4' }
+
+ typescript-eslint@8.44.1:
+ resolution:
+ {
+ integrity: sha512-0ws8uWGrUVTjEeN2OM4K1pLKHK/4NiNP/vz6ns+LjT/6sqpaYzIVFajZb1fj/IDwpsrrHb3Jy0Qm5u9CPcKaeg==,
+ }
+ engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ typescript@5.9.2:
+ resolution:
+ {
+ integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==,
+ }
+ engines: { node: '>=14.17' }
+ hasBin: true
+
+ unbox-primitive@1.1.0:
+ resolution:
+ {
+ integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ undici-types@6.21.0:
+ resolution:
+ {
+ integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==,
+ }
+
+ universalify@2.0.1:
+ resolution:
+ {
+ integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==,
+ }
+ engines: { node: '>= 10.0.0' }
+
+ uri-js@4.4.1:
+ resolution:
+ {
+ integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==,
+ }
+
+ vite-node@3.2.4:
+ resolution:
+ {
+ integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==,
+ }
+ engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 }
+ hasBin: true
+
+ vite-plugin-mkcert@1.17.8:
+ resolution:
+ {
+ integrity: sha512-S+4tNEyGqdZQ3RLAG54ETeO2qyURHWrVjUWKYikLAbmhh/iJ+36gDEja4OWwFyXNuvyXcZwNt5TZZR9itPeG5Q==,
+ }
+ engines: { node: '>=v16.7.0' }
+ peerDependencies:
+ vite: '>=3'
+
+ vite-tsconfig-paths@5.1.4:
+ resolution:
+ {
+ integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==,
+ }
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
+ vite@6.3.6:
+ resolution:
+ {
+ integrity: sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==,
+ }
+ engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 }
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@3.2.4:
+ resolution:
+ {
+ integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==,
+ }
+ engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 }
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ which-boxed-primitive@1.1.1:
+ resolution:
+ {
+ integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==,
+ }
+ engines: { node: '>= 0.4' }
+
+ which-builtin-type@1.2.1:
+ resolution:
+ {
+ integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==,
+ }
+ engines: { node: '>= 0.4' }
+
+ which-collection@1.0.2:
+ resolution:
+ {
+ integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ which-typed-array@1.1.19:
+ resolution:
+ {
+ integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==,
+ }
+ engines: { node: '>= 0.4' }
+
+ which@2.0.2:
+ resolution:
+ {
+ integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==,
+ }
+ engines: { node: '>= 8' }
+ hasBin: true
+
+ why-is-node-running@2.3.0:
+ resolution:
+ {
+ integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==,
+ }
+ engines: { node: '>=8' }
+ hasBin: true
+
+ word-wrap@1.2.5:
+ resolution:
+ {
+ integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==,
+ }
+ engines: { node: '>=0.10.0' }
+
+ yocto-queue@0.1.0:
+ resolution:
+ {
+ integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==,
+ }
+ engines: { node: '>=10' }
+
+snapshots:
+ '@esbuild/aix-ppc64@0.25.10':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/android-arm@0.25.10':
+ optional: true
+
+ '@esbuild/android-x64@0.25.10':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.10':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.10':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.10':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.10':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.10':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.10':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.10':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.10':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.10':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0)':
+ dependencies:
+ eslint: 9.36.0
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.12.1': {}
+
+ '@eslint/config-array@0.21.0':
+ dependencies:
+ '@eslint/object-schema': 2.1.6
+ debug: 4.4.3
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/config-helpers@0.3.1': {}
+
+ '@eslint/core@0.15.2':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
+ '@eslint/eslintrc@3.3.1':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.4.3
+ espree: 10.4.0
+ globals: 14.0.0
+ ignore: 5.3.2
+ import-fresh: 3.3.1
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@9.36.0': {}
+
+ '@eslint/object-schema@2.1.6': {}
+
+ '@eslint/plugin-kit@0.3.5':
+ dependencies:
+ '@eslint/core': 0.15.2
+ levn: 0.4.1
+
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.7':
+ dependencies:
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.4.3
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/retry@0.4.3': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@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.19.1
+
+ '@remix-run/router@1.23.0': {}
+
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
+
+ '@rollup/rollup-android-arm-eabi@4.52.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.52.2':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.52.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.52.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.52.2':
+ optional: true
+
+ '@swc/core-darwin-arm64@1.13.19':
+ optional: true
+
+ '@swc/core-darwin-x64@1.13.19':
+ optional: true
+
+ '@swc/core-linux-arm-gnueabihf@1.13.19':
+ optional: true
+
+ '@swc/core-linux-arm64-gnu@1.13.19':
+ optional: true
+
+ '@swc/core-linux-arm64-musl@1.13.19':
+ optional: true
+
+ '@swc/core-linux-x64-gnu@1.13.19':
+ optional: true
+
+ '@swc/core-linux-x64-musl@1.13.19':
+ optional: true
+
+ '@swc/core-win32-arm64-msvc@1.13.19':
+ optional: true
+
+ '@swc/core-win32-ia32-msvc@1.13.19':
+ optional: true
+
+ '@swc/core-win32-x64-msvc@1.13.19':
+ optional: true
+
+ '@swc/core@1.13.19':
+ dependencies:
+ '@swc/counter': 0.1.3
+ '@swc/types': 0.1.25
+ optionalDependencies:
+ '@swc/core-darwin-arm64': 1.13.19
+ '@swc/core-darwin-x64': 1.13.19
+ '@swc/core-linux-arm-gnueabihf': 1.13.19
+ '@swc/core-linux-arm64-gnu': 1.13.19
+ '@swc/core-linux-arm64-musl': 1.13.19
+ '@swc/core-linux-x64-gnu': 1.13.19
+ '@swc/core-linux-x64-musl': 1.13.19
+ '@swc/core-win32-arm64-msvc': 1.13.19
+ '@swc/core-win32-ia32-msvc': 1.13.19
+ '@swc/core-win32-x64-msvc': 1.13.19
+
+ '@swc/counter@0.1.3': {}
+
+ '@swc/types@0.1.25':
+ dependencies:
+ '@swc/counter': 0.1.3
+
+ '@types/chai@5.2.2':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+
+ '@types/deep-eql@4.0.2': {}
+
+ '@types/estree@1.0.8': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/node@20.19.17':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react-dom@18.3.7(@types/react@18.3.24)':
+ dependencies:
+ '@types/react': 18.3.24
+
+ '@types/react@18.3.24':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.1.3
+
+ '@typescript-eslint/eslint-plugin@8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0)(typescript@5.9.2))(eslint@9.36.0)(typescript@5.9.2)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.1
+ '@typescript-eslint/parser': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/scope-manager': 8.44.1
+ '@typescript-eslint/type-utils': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.44.1
+ eslint: 9.36.0
+ graphemer: 1.4.0
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.44.1(eslint@9.36.0)(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.44.1
+ '@typescript-eslint/types': 8.44.1
+ '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.44.1
+ debug: 4.4.3
+ eslint: 9.36.0
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/project-service@8.44.1(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/types': 8.44.1
+ debug: 4.4.3
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@8.44.1':
+ dependencies:
+ '@typescript-eslint/types': 8.44.1
+ '@typescript-eslint/visitor-keys': 8.44.1
+
+ '@typescript-eslint/tsconfig-utils@8.44.1(typescript@5.9.2)':
+ dependencies:
+ typescript: 5.9.2
+
+ '@typescript-eslint/type-utils@8.44.1(eslint@9.36.0)(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/types': 8.44.1
+ '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ debug: 4.4.3
+ eslint: 9.36.0
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@8.44.1': {}
+
+ '@typescript-eslint/typescript-estree@8.44.1(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/types': 8.44.1
+ '@typescript-eslint/visitor-keys': 8.44.1
+ debug: 4.4.3
+ fast-glob: 3.3.3
+ is-glob: 4.0.3
+ minimatch: 9.0.5
+ semver: 7.7.2
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.44.1(eslint@9.36.0)(typescript@5.9.2)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0)
+ '@typescript-eslint/scope-manager': 8.44.1
+ '@typescript-eslint/types': 8.44.1
+ '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2)
+ eslint: 9.36.0
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/visitor-keys@8.44.1':
+ dependencies:
+ '@typescript-eslint/types': 8.44.1
+ eslint-visitor-keys: 4.2.1
+
+ '@vitejs/plugin-react-swc@3.11.0(vite@6.3.6(@types/node@20.19.17))':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@swc/core': 1.13.19
+ vite: 6.3.6(@types/node@20.19.17)
+ transitivePeerDependencies:
+ - '@swc/helpers'
+
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@3.2.4(vite@6.3.6(@types/node@20.19.17))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.19
+ optionalDependencies:
+ vite: 6.3.6(@types/node@20.19.17)
+
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
+ '@vitest/runner@3.2.4':
+ dependencies:
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.0.0
+
+ '@vitest/snapshot@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.19
+ pathe: 2.0.3
+
+ '@vitest/spy@3.2.4':
+ dependencies:
+ tinyspy: 4.0.4
+
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
+
+ acorn-jsx@5.3.2(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
+ acorn@8.15.0: {}
+
+ 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-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ argparse@2.0.1: {}
+
+ array-buffer-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
+
+ array-includes@3.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ is-string: 1.1.1
+ math-intrinsics: 1.1.0
+
+ array-union@2.1.0: {}
+
+ array.prototype.findlast@1.2.5:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flat@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flatmap@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.tosorted@1.1.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-shim-unscopables: 1.1.0
+
+ arraybuffer.prototype.slice@1.0.4:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ is-array-buffer: 3.0.5
+
+ assertion-error@2.0.1: {}
+
+ async-function@1.0.0: {}
+
+ async@3.2.6: {}
+
+ asynckit@0.4.0: {}
+
+ available-typed-arrays@1.0.7:
+ dependencies:
+ possible-typed-array-names: 1.1.0
+
+ axios@1.12.2(debug@4.4.3):
+ dependencies:
+ follow-redirects: 1.15.11(debug@4.4.3)
+ form-data: 4.0.4
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ balanced-match@1.0.2: {}
+
+ beamable-sdk@file:../..: {}
+
+ brace-expansion@1.1.12:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.2:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ cac@6.7.14: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bind@1.0.8:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
+ set-function-length: 1.2.2
+
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ callsites@3.1.0: {}
+
+ chai@5.3.3:
+ dependencies:
+ assertion-error: 2.0.1
+ check-error: 2.1.1
+ deep-eql: 5.0.2
+ loupe: 3.2.1
+ pathval: 2.0.1
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ check-error@2.1.1: {}
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@13.1.0: {}
+
+ commondir@1.0.1: {}
+
+ concat-map@0.0.1: {}
+
+ cross-env@7.0.3:
+ dependencies:
+ cross-spawn: 7.0.6
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ csstype@3.1.3: {}
+
+ data-view-buffer@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-offset@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ deep-eql@5.0.2: {}
+
+ deep-is@0.1.4: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ define-properties@1.2.1:
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+
+ delayed-stream@1.0.0: {}
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ doctrine@2.1.0:
+ dependencies:
+ esutils: 2.0.3
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ email-addresses@5.0.0: {}
+
+ es-abstract@1.24.0:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ arraybuffer.prototype.slice: 1.0.4
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ data-view-buffer: 1.0.2
+ data-view-byte-length: 1.0.2
+ data-view-byte-offset: 1.0.1
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-set-tostringtag: 2.1.0
+ es-to-primitive: 1.3.0
+ function.prototype.name: 1.1.8
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ get-symbol-description: 1.1.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ internal-slot: 1.1.0
+ is-array-buffer: 3.0.5
+ is-callable: 1.2.7
+ is-data-view: 1.0.2
+ is-negative-zero: 2.0.3
+ is-regex: 1.2.1
+ is-set: 2.0.3
+ is-shared-array-buffer: 1.0.4
+ is-string: 1.1.1
+ is-typed-array: 1.1.15
+ is-weakref: 1.1.1
+ math-intrinsics: 1.1.0
+ object-inspect: 1.13.4
+ object-keys: 1.1.1
+ object.assign: 4.1.7
+ own-keys: 1.0.1
+ regexp.prototype.flags: 1.5.4
+ safe-array-concat: 1.1.3
+ safe-push-apply: 1.0.0
+ safe-regex-test: 1.1.0
+ set-proto: 1.0.0
+ stop-iteration-iterator: 1.1.0
+ string.prototype.trim: 1.2.10
+ string.prototype.trimend: 1.0.9
+ string.prototype.trimstart: 1.0.8
+ typed-array-buffer: 1.0.3
+ typed-array-byte-length: 1.0.3
+ typed-array-byte-offset: 1.0.4
+ typed-array-length: 1.0.7
+ unbox-primitive: 1.1.0
+ which-typed-array: 1.1.19
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-iterator-helpers@1.2.1:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-set-tostringtag: 2.1.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ iterator.prototype: 1.1.5
+ safe-array-concat: 1.1.3
+
+ es-module-lexer@1.7.0: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ es-shim-unscopables@1.1.0:
+ dependencies:
+ hasown: 2.0.2
+
+ es-to-primitive@1.3.0:
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
+
+ esbuild@0.25.10:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.10
+ '@esbuild/android-arm': 0.25.10
+ '@esbuild/android-arm64': 0.25.10
+ '@esbuild/android-x64': 0.25.10
+ '@esbuild/darwin-arm64': 0.25.10
+ '@esbuild/darwin-x64': 0.25.10
+ '@esbuild/freebsd-arm64': 0.25.10
+ '@esbuild/freebsd-x64': 0.25.10
+ '@esbuild/linux-arm': 0.25.10
+ '@esbuild/linux-arm64': 0.25.10
+ '@esbuild/linux-ia32': 0.25.10
+ '@esbuild/linux-loong64': 0.25.10
+ '@esbuild/linux-mips64el': 0.25.10
+ '@esbuild/linux-ppc64': 0.25.10
+ '@esbuild/linux-riscv64': 0.25.10
+ '@esbuild/linux-s390x': 0.25.10
+ '@esbuild/linux-x64': 0.25.10
+ '@esbuild/netbsd-arm64': 0.25.10
+ '@esbuild/netbsd-x64': 0.25.10
+ '@esbuild/openbsd-arm64': 0.25.10
+ '@esbuild/openbsd-x64': 0.25.10
+ '@esbuild/openharmony-arm64': 0.25.10
+ '@esbuild/sunos-x64': 0.25.10
+ '@esbuild/win32-arm64': 0.25.10
+ '@esbuild/win32-ia32': 0.25.10
+ '@esbuild/win32-x64': 0.25.10
+
+ escape-string-regexp@1.0.5: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ eslint-plugin-react-hooks@5.2.0(eslint@9.36.0):
+ dependencies:
+ eslint: 9.36.0
+
+ eslint-plugin-react@7.37.5(eslint@9.36.0):
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.1
+ eslint: 9.36.0
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
+
+ eslint-scope@8.4.0:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint-visitor-keys@4.2.1: {}
+
+ eslint@9.36.0:
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0)
+ '@eslint-community/regexpp': 4.12.1
+ '@eslint/config-array': 0.21.0
+ '@eslint/config-helpers': 0.3.1
+ '@eslint/core': 0.15.2
+ '@eslint/eslintrc': 3.3.1
+ '@eslint/js': 9.36.0
+ '@eslint/plugin-kit': 0.3.5
+ '@humanfs/node': 0.16.7
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.3
+ escape-string-regexp: 4.0.0
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.6.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@10.4.0:
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 4.2.1
+
+ esquery@1.6.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@5.3.0: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ esutils@2.0.3: {}
+
+ expect-type@1.2.2: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.3:
+ 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.8
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fastq@1.19.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ file-entry-cache@8.0.0:
+ dependencies:
+ flat-cache: 4.0.1
+
+ filename-reserved-regex@2.0.0: {}
+
+ filenamify@4.3.0:
+ dependencies:
+ filename-reserved-regex: 2.0.0
+ strip-outer: 1.0.1
+ trim-repeated: 1.0.0
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-cache-dir@3.3.2:
+ dependencies:
+ commondir: 1.0.1
+ make-dir: 3.1.0
+ pkg-dir: 4.2.0
+
+ find-up@4.1.0:
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@4.0.1:
+ dependencies:
+ flatted: 3.3.3
+ keyv: 4.5.4
+
+ flatted@3.3.3: {}
+
+ follow-redirects@1.15.11(debug@4.4.3):
+ optionalDependencies:
+ debug: 4.4.3
+
+ for-each@0.3.5:
+ dependencies:
+ is-callable: 1.2.7
+
+ form-data@4.0.4:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+
+ fs-extra@11.3.2:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.0
+ universalify: 2.0.1
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ function.prototype.name@1.1.8:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ functions-have-names: 1.2.3
+ hasown: 2.0.2
+ is-callable: 1.2.7
+
+ functions-have-names@1.2.3: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ get-symbol-description@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+
+ gh-pages@6.3.0:
+ dependencies:
+ async: 3.2.6
+ commander: 13.1.0
+ email-addresses: 5.0.0
+ filenamify: 4.3.0
+ find-cache-dir: 3.3.2
+ fs-extra: 11.3.2
+ globby: 11.1.0
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ globals@14.0.0: {}
+
+ globals@15.15.0: {}
+
+ globalthis@1.0.4:
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+
+ globby@11.1.0:
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.3
+ ignore: 5.3.2
+ merge2: 1.4.1
+ slash: 3.0.0
+
+ globrex@0.1.2: {}
+
+ gopd@1.2.0: {}
+
+ graceful-fs@4.2.11: {}
+
+ graphemer@1.4.0: {}
+
+ has-bigints@1.1.0: {}
+
+ has-flag@4.0.0: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.1
+
+ has-proto@1.2.0:
+ dependencies:
+ dunder-proto: 1.0.1
+
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ ignore@5.3.2: {}
+
+ ignore@7.0.5: {}
+
+ import-fresh@3.3.1:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
+ internal-slot@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ hasown: 2.0.2
+ side-channel: 1.1.0
+
+ is-array-buffer@3.0.5:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ is-async-function@2.1.1:
+ dependencies:
+ async-function: 1.0.0
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-bigint@1.1.0:
+ dependencies:
+ has-bigints: 1.1.0
+
+ is-boolean-object@1.2.2:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-callable@1.2.7: {}
+
+ is-core-module@2.16.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-data-view@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ is-typed-array: 1.1.15
+
+ is-date-object@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-extglob@2.1.1: {}
+
+ is-finalizationregistry@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-generator-function@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-map@2.0.3: {}
+
+ is-negative-zero@2.0.3: {}
+
+ is-number-object@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-number@7.0.0: {}
+
+ is-regex@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ is-set@2.0.3: {}
+
+ is-shared-array-buffer@1.0.4:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-string@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-symbol@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
+
+ is-typed-array@1.1.15:
+ dependencies:
+ which-typed-array: 1.1.19
+
+ is-weakmap@2.0.2: {}
+
+ is-weakref@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-weakset@2.0.4:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ isarray@2.0.5: {}
+
+ isexe@2.0.0: {}
+
+ iterator.prototype@1.1.5:
+ dependencies:
+ define-data-property: 1.1.4
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ has-symbols: 1.1.0
+ set-function-name: 2.0.2
+
+ js-tokens@4.0.0: {}
+
+ js-tokens@9.0.1: {}
+
+ js-yaml@4.1.0:
+ dependencies:
+ argparse: 2.0.1
+
+ json-buffer@3.0.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ jsonfile@6.2.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ jsx-ast-utils@3.3.5:
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.flat: 1.3.3
+ object.assign: 4.1.7
+ object.values: 1.2.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
+
+ locate-path@5.0.0:
+ dependencies:
+ p-locate: 4.1.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lodash.merge@4.6.2: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ loupe@3.2.1: {}
+
+ magic-string@0.30.19:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ make-dir@3.1.0:
+ dependencies:
+ semver: 6.3.1
+
+ math-intrinsics@1.1.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.12
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.11: {}
+
+ natural-compare@1.4.0: {}
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.4: {}
+
+ object-keys@1.1.1: {}
+
+ object.assign@4.1.7:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
+ object-keys: 1.1.1
+
+ object.entries@1.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ object.fromentries@2.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+
+ object.values@1.2.1:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ 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
+
+ own-keys@1.0.1:
+ dependencies:
+ get-intrinsic: 1.3.0
+ object-keys: 1.1.1
+ safe-push-apply: 1.0.0
+
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@4.1.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ p-try@2.2.0: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ path-exists@4.0.0: {}
+
+ path-key@3.1.1: {}
+
+ path-parse@1.0.7: {}
+
+ path-type@4.0.0: {}
+
+ pathe@2.0.3: {}
+
+ pathval@2.0.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ picomatch@4.0.3: {}
+
+ pkg-dir@4.2.0:
+ dependencies:
+ find-up: 4.1.0
+
+ possible-typed-array-names@1.1.0: {}
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ prelude-ls@1.2.1: {}
+
+ prettier@3.6.2: {}
+
+ prop-types@15.8.1:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ proxy-from-env@1.1.0: {}
+
+ 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-is@16.13.1: {}
+
+ react-router-dom@6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.23.0
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-router: 6.30.1(react@18.3.1)
+
+ react-router@6.30.1(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.23.0
+ react: 18.3.1
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ reflect.getprototypeof@1.0.10:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+
+ regexp.prototype.flags@1.5.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ set-function-name: 2.0.2
+
+ resolve-from@4.0.0: {}
+
+ resolve@2.0.0-next.5:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ reusify@1.1.0: {}
+
+ rollup@4.52.2:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.52.2
+ '@rollup/rollup-android-arm64': 4.52.2
+ '@rollup/rollup-darwin-arm64': 4.52.2
+ '@rollup/rollup-darwin-x64': 4.52.2
+ '@rollup/rollup-freebsd-arm64': 4.52.2
+ '@rollup/rollup-freebsd-x64': 4.52.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.52.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.52.2
+ '@rollup/rollup-linux-arm64-gnu': 4.52.2
+ '@rollup/rollup-linux-arm64-musl': 4.52.2
+ '@rollup/rollup-linux-loong64-gnu': 4.52.2
+ '@rollup/rollup-linux-ppc64-gnu': 4.52.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.52.2
+ '@rollup/rollup-linux-riscv64-musl': 4.52.2
+ '@rollup/rollup-linux-s390x-gnu': 4.52.2
+ '@rollup/rollup-linux-x64-gnu': 4.52.2
+ '@rollup/rollup-linux-x64-musl': 4.52.2
+ '@rollup/rollup-openharmony-arm64': 4.52.2
+ '@rollup/rollup-win32-arm64-msvc': 4.52.2
+ '@rollup/rollup-win32-ia32-msvc': 4.52.2
+ '@rollup/rollup-win32-x64-gnu': 4.52.2
+ '@rollup/rollup-win32-x64-msvc': 4.52.2
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-array-concat@1.1.3:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
+ isarray: 2.0.5
+
+ safe-push-apply@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ isarray: 2.0.5
+
+ safe-regex-test@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ semver@6.3.1: {}
+
+ semver@7.7.2: {}
+
+ set-function-length@1.2.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+
+ set-function-name@2.0.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.2
+
+ set-proto@1.0.0:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
+ siginfo@2.0.0: {}
+
+ slash@3.0.0: {}
+
+ source-map-js@1.2.1: {}
+
+ stackback@0.0.2: {}
+
+ std-env@3.9.0: {}
+
+ stop-iteration-iterator@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
+
+ string.prototype.matchall@4.0.12:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ regexp.prototype.flags: 1.5.4
+ set-function-name: 2.0.2
+ side-channel: 1.1.0
+
+ string.prototype.repeat@1.0.0:
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+
+ string.prototype.trim@1.2.10:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-data-property: 1.1.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ has-property-descriptors: 1.0.2
+
+ string.prototype.trimend@1.0.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ string.prototype.trimstart@1.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ strip-json-comments@3.1.1: {}
+
+ strip-literal@3.0.0:
+ dependencies:
+ js-tokens: 9.0.1
+
+ strip-outer@1.0.1:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@2.0.0: {}
+
+ tinyspy@4.0.4: {}
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ trim-repeated@1.0.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
+ ts-api-utils@2.1.0(typescript@5.9.2):
+ dependencies:
+ typescript: 5.9.2
+
+ tsconfck@3.1.6(typescript@5.9.2):
+ optionalDependencies:
+ typescript: 5.9.2
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ typed-array-buffer@1.0.3:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-length@1.0.3:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-offset@1.0.4:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ reflect.getprototypeof: 1.0.10
+
+ typed-array-length@1.0.7:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ is-typed-array: 1.1.15
+ possible-typed-array-names: 1.1.0
+ reflect.getprototypeof: 1.0.10
+
+ typescript-eslint@8.44.1(eslint@9.36.0)(typescript@5.9.2):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0)(typescript@5.9.2))(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.44.1(eslint@9.36.0)(typescript@5.9.2)
+ eslint: 9.36.0
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ typescript@5.9.2: {}
+
+ unbox-primitive@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-bigints: 1.1.0
+ has-symbols: 1.1.0
+ which-boxed-primitive: 1.1.1
+
+ undici-types@6.21.0: {}
+
+ universalify@2.0.1: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ vite-node@3.2.4(@types/node@20.19.17):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 6.3.6(@types/node@20.19.17)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite-plugin-mkcert@1.17.8(vite@6.3.6(@types/node@20.19.17)):
+ dependencies:
+ axios: 1.12.2(debug@4.4.3)
+ debug: 4.4.3
+ picocolors: 1.1.1
+ vite: 6.3.6(@types/node@20.19.17)
+ transitivePeerDependencies:
+ - supports-color
+
+ vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@6.3.6(@types/node@20.19.17)):
+ dependencies:
+ debug: 4.4.3
+ globrex: 0.1.2
+ tsconfck: 3.1.6(typescript@5.9.2)
+ optionalDependencies:
+ vite: 6.3.6(@types/node@20.19.17)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ vite@6.3.6(@types/node@20.19.17):
+ dependencies:
+ esbuild: 0.25.10
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.52.2
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 20.19.17
+ fsevents: 2.3.3
+
+ vitest@3.2.4(@types/node@20.19.17):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.3.6(@types/node@20.19.17))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.2.2
+ magic-string: 0.30.19
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 6.3.6(@types/node@20.19.17)
+ vite-node: 3.2.4(@types/node@20.19.17)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 20.19.17
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ which-boxed-primitive@1.1.1:
+ dependencies:
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
+
+ which-builtin-type@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ function.prototype.name: 1.1.8
+ has-tostringtag: 1.0.2
+ is-async-function: 2.1.1
+ is-date-object: 1.1.0
+ is-finalizationregistry: 1.1.1
+ is-generator-function: 1.1.0
+ is-regex: 1.2.1
+ is-weakref: 1.1.1
+ isarray: 2.0.5
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.19
+
+ which-collection@1.0.2:
+ dependencies:
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
+
+ which-typed-array@1.1.19:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ word-wrap@1.2.5: {}
+
+ yocto-queue@0.1.0: {}
diff --git a/web/samples/WordWiz/src/assets/EndlessIcon.tsx b/web/samples/WordWiz/src/assets/EndlessIcon.tsx
new file mode 100644
index 0000000000..c018bcf9cd
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/EndlessIcon.tsx
@@ -0,0 +1,25 @@
+export default function EndlessIcon() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/web/samples/WordWiz/src/assets/HomeIcon.tsx b/web/samples/WordWiz/src/assets/HomeIcon.tsx
new file mode 100644
index 0000000000..7d7d4058ad
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/HomeIcon.tsx
@@ -0,0 +1,18 @@
+export default function HomeIcon() {
+ return (
+
+
+
+
+ );
+}
diff --git a/web/samples/WordWiz/src/assets/NextIcon.tsx b/web/samples/WordWiz/src/assets/NextIcon.tsx
new file mode 100644
index 0000000000..3c1740aa2f
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/NextIcon.tsx
@@ -0,0 +1,19 @@
+export default function NextIcon() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/web/samples/WordWiz/src/assets/allowed.txt b/web/samples/WordWiz/src/assets/allowed.txt
new file mode 100644
index 0000000000..cc443a0688
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/allowed.txt
@@ -0,0 +1,10657 @@
+aahed
+aalii
+aargh
+aarti
+abaca
+abaci
+abacs
+abaft
+abaka
+abamp
+aband
+abash
+abask
+abaya
+abbas
+abbed
+abbes
+abcee
+abeam
+abear
+abele
+abers
+abets
+abies
+abler
+ables
+ablet
+ablow
+abmho
+abohm
+aboil
+aboma
+aboon
+abord
+abore
+abram
+abray
+abrim
+abrin
+abris
+absey
+absit
+abuna
+abune
+abuts
+abuzz
+abyes
+abysm
+acais
+acari
+accas
+accoy
+acerb
+acers
+aceta
+achar
+ached
+aches
+achoo
+acids
+acidy
+acing
+acini
+ackee
+acker
+acmes
+acmic
+acned
+acnes
+acock
+acold
+acred
+acres
+acros
+acted
+actin
+acton
+acyls
+adaws
+adays
+adbot
+addax
+added
+adder
+addio
+addle
+adeem
+adhan
+adieu
+adios
+adits
+adman
+admen
+admix
+adobo
+adown
+adoze
+adrad
+adred
+adsum
+aduki
+adunc
+adust
+advew
+adyta
+adzed
+adzes
+aecia
+aedes
+aegis
+aeons
+aerie
+aeros
+aesir
+afald
+afara
+afars
+afear
+aflaj
+afore
+afrit
+afros
+agama
+agami
+agars
+agast
+agave
+agaze
+agene
+agers
+agger
+aggie
+aggri
+aggro
+aggry
+aghas
+agila
+agios
+agism
+agist
+agita
+aglee
+aglet
+agley
+agloo
+aglus
+agmas
+agoge
+agone
+agons
+agood
+agria
+agrin
+agros
+agued
+agues
+aguna
+aguti
+aheap
+ahent
+ahigh
+ahind
+ahing
+ahint
+ahold
+ahull
+ahuru
+aidas
+aided
+aides
+aidoi
+aidos
+aiery
+aigas
+aight
+ailed
+aimed
+aimer
+ainee
+ainga
+aioli
+aired
+airer
+airns
+airth
+airts
+aitch
+aitus
+aiver
+aiyee
+aizle
+ajies
+ajiva
+ajuga
+ajwan
+akees
+akela
+akene
+aking
+akita
+akkas
+alaap
+alack
+alamo
+aland
+alane
+alang
+alans
+alant
+alapa
+alaps
+alary
+alate
+alays
+albas
+albee
+alcid
+alcos
+aldea
+alder
+aldol
+aleck
+alecs
+alefs
+aleft
+aleph
+alews
+aleye
+alfas
+algal
+algas
+algid
+algin
+algor
+algum
+alias
+alifs
+aline
+alist
+aliya
+alkie
+alkos
+alkyd
+alkyl
+allee
+allel
+allis
+allod
+allyl
+almah
+almas
+almeh
+almes
+almud
+almug
+alods
+aloed
+aloes
+aloha
+aloin
+aloos
+alowe
+altho
+altos
+alula
+alums
+alure
+alvar
+alway
+amahs
+amain
+amate
+amaut
+amban
+ambit
+ambos
+ambry
+ameba
+ameer
+amene
+amens
+ament
+amias
+amice
+amici
+amide
+amido
+amids
+amies
+amiga
+amigo
+amine
+amino
+amins
+amirs
+amlas
+amman
+ammon
+ammos
+amnia
+amnic
+amnio
+amoks
+amole
+amort
+amour
+amove
+amowt
+amped
+ampul
+amrit
+amuck
+amyls
+anana
+anata
+ancho
+ancle
+ancon
+andro
+anear
+anele
+anent
+angas
+anglo
+anigh
+anile
+anils
+anima
+animi
+anion
+anise
+anker
+ankhs
+ankus
+anlas
+annal
+annas
+annat
+anoas
+anole
+anomy
+ansae
+antae
+antar
+antas
+anted
+antes
+antis
+antra
+antre
+antsy
+anura
+anyon
+apace
+apage
+apaid
+apayd
+apays
+apeak
+apeek
+apers
+apert
+apery
+apgar
+aphis
+apian
+apiol
+apish
+apism
+apode
+apods
+apoop
+aport
+appal
+appay
+appel
+appro
+appui
+appuy
+apres
+apses
+apsis
+apsos
+apted
+apter
+aquae
+aquas
+araba
+araks
+arame
+arars
+arbas
+arced
+archi
+arcos
+arcus
+ardeb
+ardri
+aread
+areae
+areal
+arear
+areas
+areca
+aredd
+arede
+arefy
+areic
+arene
+arepa
+arere
+arete
+arets
+arett
+argal
+argan
+argil
+argle
+argol
+argon
+argot
+argus
+arhat
+arias
+ariel
+ariki
+arils
+ariot
+arish
+arked
+arled
+arles
+armed
+armer
+armet
+armil
+arnas
+arnut
+aroba
+aroha
+aroid
+arpas
+arpen
+arrah
+arras
+arret
+arris
+arroz
+arsed
+arses
+arsey
+arsis
+artal
+artel
+artic
+artis
+aruhe
+arums
+arval
+arvee
+arvos
+aryls
+asana
+ascon
+ascus
+asdic
+ashed
+ashes
+ashet
+asked
+asker
+askoi
+askos
+aspen
+asper
+aspic
+aspie
+aspis
+aspro
+assai
+assam
+asses
+assez
+assot
+aster
+astir
+astun
+asura
+asway
+aswim
+asyla
+ataps
+ataxy
+atigi
+atilt
+atimy
+atlas
+atman
+atmas
+atmos
+atocs
+atoke
+atoks
+atoms
+atomy
+atony
+atopy
+atria
+atrip
+attap
+attar
+atuas
+audad
+auger
+aught
+aulas
+aulic
+auloi
+aulos
+aumil
+aunes
+aunts
+aurae
+aural
+aurar
+auras
+aurei
+aures
+auric
+auris
+aurum
+autos
+auxin
+avale
+avant
+avast
+avels
+avens
+avers
+avgas
+avine
+avion
+avise
+aviso
+avize
+avows
+avyze
+awarn
+awato
+awave
+aways
+awdls
+aweel
+aweto
+awing
+awmry
+awned
+awner
+awols
+awork
+axels
+axile
+axils
+axing
+axite
+axled
+axles
+axman
+axmen
+axoid
+axone
+axons
+ayahs
+ayaya
+ayelp
+aygre
+ayins
+ayont
+ayres
+ayrie
+azans
+azide
+azido
+azine
+azlon
+azoic
+azole
+azons
+azote
+azoth
+azuki
+azurn
+azury
+azygy
+azyme
+azyms
+baaed
+baals
+babas
+babel
+babes
+babka
+baboo
+babul
+babus
+bacca
+bacco
+baccy
+bacha
+bachs
+backs
+baddy
+baels
+baffs
+baffy
+bafts
+baghs
+bagie
+bahts
+bahus
+bahut
+bails
+bairn
+baisa
+baith
+baits
+baiza
+baize
+bajan
+bajra
+bajri
+bajus
+baked
+baken
+bakes
+bakra
+balas
+balds
+baldy
+baled
+bales
+balks
+balky
+balls
+bally
+balms
+baloo
+balsa
+balti
+balun
+balus
+bambi
+banak
+banco
+bancs
+banda
+bandh
+bands
+bandy
+baned
+banes
+bangs
+bania
+banks
+banns
+bants
+bantu
+banty
+banya
+bapus
+barbe
+barbs
+barby
+barca
+barde
+bardo
+bards
+bardy
+bared
+barer
+bares
+barfi
+barfs
+baric
+barks
+barky
+barms
+barmy
+barns
+barny
+barps
+barra
+barre
+barro
+barry
+barye
+basan
+based
+basen
+baser
+bases
+basho
+basij
+basks
+bason
+basse
+bassi
+basso
+bassy
+basta
+basti
+basto
+basts
+bated
+bates
+baths
+batik
+batta
+batts
+battu
+bauds
+bauks
+baulk
+baurs
+bavin
+bawds
+bawks
+bawls
+bawns
+bawrs
+bawty
+bayed
+bayer
+bayes
+bayle
+bayts
+bazar
+bazoo
+beads
+beaks
+beaky
+beals
+beams
+beamy
+beano
+beans
+beany
+beare
+bears
+beath
+beats
+beaty
+beaus
+beaut
+beaux
+bebop
+becap
+becke
+becks
+bedad
+bedel
+bedes
+bedew
+bedim
+bedye
+beedi
+beefs
+beeps
+beers
+beery
+beets
+befog
+begad
+begar
+begem
+begot
+begum
+beige
+beigy
+beins
+bekah
+belah
+belar
+belay
+belee
+belga
+bells
+belon
+belts
+bemad
+bemas
+bemix
+bemud
+bends
+bendy
+benes
+benet
+benga
+benis
+benne
+benni
+benny
+bento
+bents
+benty
+bepat
+beray
+beres
+bergs
+berko
+berks
+berme
+berms
+berob
+beryl
+besat
+besaw
+besee
+beses
+besit
+besom
+besot
+besti
+bests
+betas
+beted
+betes
+beths
+betid
+beton
+betta
+betty
+bever
+bevor
+bevue
+bevvy
+bewet
+bewig
+bezes
+bezil
+bezzy
+bhais
+bhaji
+bhang
+bhats
+bhels
+bhoot
+bhuna
+bhuts
+biach
+biali
+bialy
+bibbs
+bibes
+biccy
+bices
+bided
+bider
+bides
+bidet
+bidis
+bidon
+bield
+biers
+biffo
+biffs
+biffy
+bifid
+bigae
+biggs
+biggy
+bigha
+bight
+bigly
+bigos
+bijou
+biked
+biker
+bikes
+bikie
+bilbo
+bilby
+biled
+biles
+bilgy
+bilks
+bills
+bimah
+bimas
+bimbo
+binal
+bindi
+binds
+biner
+bines
+bings
+bingy
+binit
+binks
+bints
+biogs
+biont
+biota
+biped
+bipod
+birds
+birks
+birle
+birls
+biros
+birrs
+birse
+birsy
+bises
+bisks
+bisom
+bitch
+biter
+bites
+bitos
+bitou
+bitsy
+bitte
+bitts
+bivia
+bivvy
+bizes
+bizzo
+bizzy
+blabs
+blads
+blady
+blaer
+blaes
+blaff
+blags
+blahs
+blain
+blams
+blart
+blase
+blash
+blate
+blats
+blatt
+blaud
+blawn
+blaws
+blays
+blear
+blebs
+blech
+blees
+blent
+blert
+blest
+blets
+bleys
+blimy
+bling
+blini
+blins
+bliny
+blips
+blist
+blite
+blits
+blive
+blobs
+blocs
+blogs
+blook
+bloop
+blore
+blots
+blows
+blowy
+blubs
+blude
+bluds
+bludy
+blued
+blues
+bluet
+bluey
+bluid
+blume
+blunk
+blurs
+blype
+boabs
+boaks
+boars
+boart
+boats
+bobac
+bobak
+bobas
+bobol
+bobos
+bocca
+bocce
+bocci
+boche
+bocks
+boded
+bodes
+bodge
+bodhi
+bodle
+boeps
+boets
+boeuf
+boffo
+boffs
+bogan
+bogey
+boggy
+bogie
+bogle
+bogue
+bogus
+bohea
+bohos
+boils
+boing
+boink
+boite
+boked
+bokeh
+bokes
+bokos
+bolar
+bolas
+bolds
+boles
+bolix
+bolls
+bolos
+bolts
+bolus
+bomas
+bombe
+bombo
+bombs
+bonce
+bonds
+boned
+boner
+bones
+bongs
+bonie
+bonks
+bonne
+bonny
+bonza
+bonze
+booai
+booay
+boobs
+boody
+booed
+boofy
+boogy
+boohs
+books
+booky
+bools
+booms
+boomy
+boong
+boons
+boord
+boors
+boose
+boots
+boppy
+borak
+boral
+boras
+borde
+bords
+bored
+boree
+borel
+borer
+bores
+borgo
+boric
+borks
+borms
+borna
+boron
+borts
+borty
+bortz
+bosie
+bosks
+bosky
+boson
+bosun
+botas
+botel
+botes
+bothy
+botte
+botts
+botty
+bouge
+bouks
+boult
+bouns
+bourd
+bourg
+bourn
+bouse
+bousy
+bouts
+bovid
+bowat
+bowed
+bower
+bowes
+bowet
+bowie
+bowls
+bowne
+bowrs
+bowse
+boxed
+boxen
+boxes
+boxla
+boxty
+boyar
+boyau
+boyed
+boyfs
+boygs
+boyla
+boyos
+boysy
+bozos
+braai
+brach
+brack
+bract
+brads
+braes
+brags
+brail
+braks
+braky
+brame
+brane
+brank
+brans
+brant
+brast
+brats
+brava
+bravi
+braws
+braxy
+brays
+braza
+braze
+bream
+brede
+breds
+breem
+breer
+brees
+breid
+breis
+breme
+brens
+brent
+brere
+brers
+breve
+brews
+breys
+brier
+bries
+brigs
+briki
+briks
+brill
+brims
+brins
+brios
+brise
+briss
+brith
+brits
+britt
+brize
+broch
+brock
+brods
+brogh
+brogs
+brome
+bromo
+bronc
+brond
+brool
+broos
+brose
+brosy
+brows
+brugh
+bruin
+bruit
+brule
+brume
+brung
+brusk
+brust
+bruts
+buats
+buaze
+bubal
+bubas
+bubba
+bubbe
+bubby
+bubus
+buchu
+bucko
+bucks
+bucku
+budas
+budis
+budos
+buffa
+buffe
+buffi
+buffo
+buffs
+buffy
+bufos
+bufty
+buhls
+buhrs
+buiks
+buist
+bukes
+bulbs
+bulgy
+bulks
+bulla
+bulls
+bulse
+bumbo
+bumfs
+bumph
+bumps
+bumpy
+bunas
+bunce
+bunco
+bunde
+bundh
+bunds
+bundt
+bundu
+bundy
+bungs
+bungy
+bunia
+bunje
+bunjy
+bunko
+bunks
+bunns
+bunts
+bunty
+bunya
+buoys
+buppy
+buran
+buras
+burbs
+burds
+buret
+burfi
+burgh
+burgs
+burin
+burka
+burke
+burks
+burls
+burns
+buroo
+burps
+burqa
+burro
+burrs
+burry
+bursa
+burse
+busby
+buses
+busks
+busky
+bussu
+busti
+busts
+busty
+buteo
+butes
+butle
+butoh
+butts
+butty
+butut
+butyl
+buzzy
+bwana
+bwazi
+byded
+bydes
+byked
+bykes
+byres
+byrls
+byssi
+bytes
+byway
+caaed
+cabas
+caber
+cabob
+caboc
+cabre
+cacas
+cacks
+cacky
+cadee
+cades
+cadge
+cadgy
+cadie
+cadis
+cadre
+caeca
+caese
+cafes
+caffs
+caged
+cager
+cages
+cagot
+cahow
+caids
+cains
+caird
+cajon
+cajun
+caked
+cakes
+cakey
+calfs
+calid
+calif
+calix
+calks
+calla
+calls
+calms
+calmy
+calos
+calpa
+calps
+calve
+calyx
+caman
+camas
+cames
+camis
+camos
+campi
+campo
+camps
+campy
+camus
+caned
+caneh
+caner
+canes
+cangs
+canid
+canna
+canns
+canso
+canst
+canto
+cants
+canty
+capas
+caped
+capes
+capex
+caphs
+capiz
+caple
+capon
+capos
+capot
+capri
+capul
+carap
+carbo
+carbs
+carby
+cardi
+cards
+cardy
+cared
+carer
+cares
+caret
+carex
+carks
+carle
+carls
+carns
+carny
+carob
+carom
+caron
+carpi
+carps
+carrs
+carse
+carta
+carte
+carts
+carvy
+casas
+casco
+cased
+cases
+casks
+casky
+casts
+casus
+cates
+cauda
+cauks
+cauld
+cauls
+caums
+caups
+cauri
+causa
+cavas
+caved
+cavel
+caver
+caves
+cavie
+cawed
+cawks
+caxon
+ceaze
+cebid
+cecal
+cecum
+ceded
+ceder
+cedes
+cedis
+ceiba
+ceili
+ceils
+celeb
+cella
+celli
+cells
+celom
+celts
+cense
+cento
+cents
+centu
+ceorl
+cepes
+cerci
+cered
+ceres
+cerge
+ceria
+ceric
+cerne
+ceroc
+ceros
+certs
+certy
+cesse
+cesta
+cesti
+cetes
+cetyl
+cezve
+chace
+chack
+chaco
+chado
+chads
+chaft
+chais
+chals
+chams
+chana
+chang
+chank
+chape
+chaps
+chapt
+chara
+chare
+chark
+charr
+chars
+chary
+chats
+chave
+chavs
+chawk
+chaws
+chaya
+chays
+cheep
+chefs
+cheka
+chela
+chelp
+chemo
+chems
+chere
+chert
+cheth
+chevy
+chews
+chewy
+chiao
+chias
+chibs
+chica
+chich
+chico
+chics
+chiel
+chiks
+chile
+chimb
+chimo
+chimp
+chine
+ching
+chink
+chino
+chins
+chips
+chirk
+chirl
+chirm
+chiro
+chirr
+chirt
+chiru
+chits
+chive
+chivs
+chivy
+chizz
+choco
+chocs
+chode
+chogs
+choil
+choko
+choky
+chola
+choli
+cholo
+chomp
+chons
+choof
+chook
+choom
+choon
+chops
+chota
+chott
+chout
+choux
+chowk
+chows
+chubs
+chufa
+chuff
+chugs
+chums
+churl
+churr
+chuse
+chuts
+chyle
+chyme
+chynd
+cibol
+cided
+cides
+ciels
+ciggy
+cilia
+cills
+cimar
+cimex
+cinct
+cines
+cinqs
+cions
+cippi
+circs
+cires
+cirls
+cirri
+cisco
+cissy
+cists
+cital
+cited
+citer
+cites
+cives
+civet
+civie
+civvy
+clach
+clade
+clads
+claes
+clags
+clame
+clams
+clans
+claps
+clapt
+claro
+clart
+clary
+clast
+clats
+claut
+clave
+clavi
+claws
+clays
+cleck
+cleek
+cleep
+clefs
+clegs
+cleik
+clems
+clepe
+clept
+cleve
+clews
+clied
+clies
+clift
+clime
+cline
+clint
+clipe
+clips
+clipt
+clits
+cloam
+clods
+cloff
+clogs
+cloke
+clomb
+clomp
+clonk
+clons
+cloop
+cloot
+clops
+clote
+clots
+clour
+clous
+clows
+cloye
+cloys
+cloze
+clubs
+clues
+cluey
+clunk
+clype
+cnida
+coact
+coady
+coala
+coals
+coaly
+coapt
+coarb
+coate
+coati
+coats
+cobbs
+cobby
+cobia
+coble
+cobza
+cocas
+cocci
+cocco
+cocks
+cocky
+cocos
+codas
+codec
+coded
+coden
+coder
+codes
+codex
+codon
+coeds
+coffs
+cogie
+cogon
+cogue
+cohab
+cohen
+cohoe
+cohog
+cohos
+coifs
+coign
+coils
+coins
+coirs
+coits
+coked
+cokes
+colas
+colby
+colds
+coled
+coles
+coley
+colic
+colin
+colls
+colly
+colog
+colts
+colza
+comae
+comal
+comas
+combe
+combi
+combo
+combs
+comby
+comer
+comes
+comix
+commo
+comms
+commy
+compo
+comps
+compt
+comte
+comus
+coned
+cones
+coney
+confs
+conga
+conge
+congo
+conia
+conin
+conks
+conky
+conne
+conns
+conte
+conto
+conus
+convo
+cooch
+cooed
+cooee
+cooer
+cooey
+coofs
+cooks
+cooky
+cools
+cooly
+coomb
+cooms
+coomy
+coons
+coops
+coopt
+coost
+coots
+cooze
+copal
+copay
+coped
+copen
+coper
+copes
+coppy
+copra
+copsy
+coqui
+coram
+corbe
+corby
+cords
+cored
+cores
+corey
+corgi
+coria
+corks
+corky
+corms
+corni
+corno
+corns
+cornu
+corps
+corse
+corso
+cosec
+cosed
+coses
+coset
+cosey
+cosie
+costa
+coste
+costs
+cotan
+coted
+cotes
+coths
+cotta
+cotts
+coude
+coups
+courb
+courd
+coure
+cours
+couta
+couth
+coved
+coves
+covin
+cowal
+cowan
+cowed
+cowks
+cowls
+cowps
+cowry
+coxae
+coxal
+coxed
+coxes
+coxib
+coyau
+coyed
+coyer
+coypu
+cozed
+cozen
+cozes
+cozey
+cozie
+craal
+crabs
+crags
+craic
+craig
+crake
+crame
+crams
+crans
+crape
+craps
+crapy
+crare
+craws
+crays
+creds
+creel
+crees
+crems
+crena
+creps
+crepy
+crewe
+crews
+crias
+cribs
+cries
+crims
+crine
+crios
+cripe
+crips
+crise
+crith
+crits
+croci
+crocs
+croft
+crogs
+cromb
+crome
+cronk
+crons
+crool
+croon
+crops
+crore
+crost
+crout
+crows
+croze
+cruck
+crudo
+cruds
+crudy
+crues
+cruet
+cruft
+crunk
+cruor
+crura
+cruse
+crusy
+cruve
+crwth
+cryer
+ctene
+cubby
+cubeb
+cubed
+cuber
+cubes
+cubit
+cuddy
+cuffo
+cuffs
+cuifs
+cuing
+cuish
+cuits
+cukes
+culch
+culet
+culex
+culls
+cully
+culms
+culpa
+culti
+cults
+culty
+cumec
+cundy
+cunei
+cunit
+cunts
+cupel
+cupid
+cuppa
+cuppy
+curat
+curbs
+curch
+curds
+curdy
+cured
+curer
+cures
+curet
+curfs
+curia
+curie
+curli
+curls
+curns
+curny
+currs
+cursi
+curst
+cusec
+cushy
+cusks
+cusps
+cuspy
+cusso
+cusum
+cutch
+cuter
+cutes
+cutey
+cutin
+cutis
+cutto
+cutty
+cutup
+cuvee
+cuzes
+cwtch
+cyano
+cyans
+cycad
+cycas
+cyclo
+cyder
+cylix
+cymae
+cymar
+cymas
+cymes
+cymol
+cysts
+cytes
+cyton
+czars
+daals
+dabba
+daces
+dacha
+dacks
+dadah
+dadas
+dados
+daffs
+daffy
+dagga
+daggy
+dagos
+dahls
+daiko
+daine
+daint
+daker
+daled
+dales
+dalis
+dalle
+dalts
+daman
+damar
+dames
+damme
+damns
+damps
+dampy
+dancy
+dangs
+danio
+danks
+danny
+dants
+daraf
+darbs
+darcy
+dared
+darer
+dares
+darga
+dargs
+daric
+daris
+darks
+darky
+darns
+darre
+darts
+darzi
+dashi
+dashy
+datal
+dated
+dater
+dates
+datos
+datto
+daube
+daubs
+dauby
+dauds
+dault
+daurs
+dauts
+daven
+davit
+dawah
+dawds
+dawed
+dawen
+dawks
+dawns
+dawts
+dayan
+daych
+daynt
+dazed
+dazer
+dazes
+deads
+deair
+deals
+deans
+deare
+dearn
+dears
+deary
+deash
+deave
+deaws
+deawy
+debag
+debby
+debel
+debes
+debts
+debud
+debur
+debus
+debye
+decad
+decaf
+decan
+decko
+decks
+decos
+dedal
+deeds
+deedy
+deely
+deems
+deens
+deeps
+deere
+deers
+deets
+deeve
+deevs
+defat
+deffo
+defis
+defog
+degas
+degum
+degus
+deice
+deids
+deify
+deils
+deism
+deist
+deked
+dekes
+dekko
+deled
+deles
+delfs
+delft
+delis
+dells
+delly
+delos
+delph
+delts
+deman
+demes
+demic
+demit
+demob
+demoi
+demos
+dempt
+denar
+denay
+dench
+denes
+denet
+denis
+dents
+deoxy
+derat
+deray
+dered
+deres
+derig
+derma
+derms
+derns
+derny
+deros
+derro
+derry
+derth
+dervs
+desex
+deshi
+desis
+desks
+desse
+devas
+devel
+devis
+devon
+devos
+devot
+dewan
+dewar
+dewax
+dewed
+dexes
+dexie
+dhaba
+dhaks
+dhals
+dhikr
+dhobi
+dhole
+dholl
+dhols
+dhoti
+dhows
+dhuti
+diact
+dials
+diane
+diazo
+dibbs
+diced
+dicer
+dices
+dicht
+dicks
+dicky
+dicot
+dicta
+dicts
+dicty
+diddy
+didie
+didos
+didst
+diebs
+diels
+diene
+diets
+diffs
+dight
+dikas
+diked
+diker
+dikes
+dikey
+dildo
+dilli
+dills
+dimbo
+dimer
+dimes
+dimps
+dinar
+dined
+dines
+dinge
+dings
+dinic
+dinks
+dinky
+dinna
+dinos
+dints
+diols
+diota
+dippy
+dipso
+diram
+direr
+dirke
+dirks
+dirls
+dirts
+disas
+disci
+discs
+dishy
+disks
+disme
+dital
+ditas
+dited
+dites
+ditsy
+ditts
+ditzy
+divan
+divas
+dived
+dives
+divis
+divna
+divos
+divot
+divvy
+diwan
+dixie
+dixit
+diyas
+dizen
+djinn
+djins
+doabs
+doats
+dobby
+dobes
+dobie
+dobla
+dobra
+dobro
+docht
+docks
+docos
+docus
+doddy
+dodos
+doeks
+doers
+doest
+doeth
+doffs
+dogan
+doges
+dogey
+doggo
+doggy
+dogie
+dohyo
+doilt
+doily
+doits
+dojos
+dolce
+dolci
+doled
+doles
+dolia
+dolls
+dolma
+dolor
+dolos
+dolts
+domal
+domed
+domes
+domic
+donah
+donas
+donee
+doner
+donga
+dongs
+donko
+donna
+donne
+donny
+donsy
+doobs
+dooce
+doody
+dooks
+doole
+dools
+dooly
+dooms
+doomy
+doona
+doorn
+doors
+doozy
+dopas
+doped
+doper
+dopes
+dorad
+dorba
+dorbs
+doree
+dores
+doric
+doris
+dorks
+dorky
+dorms
+dormy
+dorps
+dorrs
+dorsa
+dorse
+dorts
+dorty
+dosai
+dosas
+dosed
+doseh
+doser
+doses
+dosha
+dotal
+doted
+doter
+dotes
+dotty
+douar
+douce
+doucs
+douks
+doula
+douma
+doums
+doups
+doura
+douse
+douts
+doved
+doven
+dover
+doves
+dovie
+dowar
+dowds
+dowed
+dower
+dowie
+dowle
+dowls
+dowly
+downa
+downs
+dowps
+dowse
+dowts
+doxed
+doxes
+doxie
+doyen
+doyly
+dozed
+dozer
+dozes
+drabs
+drack
+draco
+draff
+drags
+drail
+drams
+drant
+draps
+drats
+drave
+draws
+drays
+drear
+dreck
+dreed
+dreer
+drees
+dregs
+dreks
+drent
+drere
+drest
+dreys
+dribs
+drice
+dries
+drily
+drips
+dript
+droid
+droil
+droke
+drole
+drome
+drony
+droob
+droog
+drook
+drops
+dropt
+drouk
+drows
+drubs
+drugs
+drums
+drupe
+druse
+drusy
+druxy
+dryad
+dryas
+dsobo
+dsomo
+duads
+duals
+duans
+duars
+dubbo
+ducal
+ducat
+duces
+ducks
+ducky
+ducts
+duddy
+duded
+dudes
+duels
+duets
+duett
+duffs
+dufus
+duing
+duits
+dukas
+duked
+dukes
+dukka
+dulce
+dules
+dulia
+dulls
+dulse
+dumas
+dumbo
+dumbs
+dumka
+dumky
+dumps
+dunam
+dunch
+dunes
+dungs
+dungy
+dunks
+dunno
+dunny
+dunsh
+dunts
+duomi
+duomo
+duped
+duper
+dupes
+duple
+duply
+duppy
+dural
+duras
+dured
+dures
+durgy
+durns
+duroc
+duros
+duroy
+durra
+durrs
+durry
+durst
+durum
+durzi
+dusks
+dusts
+duxes
+dwaal
+dwale
+dwalm
+dwams
+dwang
+dwaum
+dweeb
+dwile
+dwine
+dyads
+dyers
+dyked
+dykes
+dykey
+dykon
+dynel
+dynes
+dzhos
+eagre
+ealed
+eales
+eaned
+eards
+eared
+earls
+earns
+earnt
+earst
+eased
+easer
+eases
+easle
+easts
+eathe
+eaved
+eaves
+ebbed
+ebbet
+ebons
+ebook
+ecads
+eched
+eches
+echos
+ecrus
+edema
+edged
+edger
+edges
+edile
+edits
+educe
+educt
+eejit
+eensy
+eeven
+eevns
+effed
+egads
+egers
+egest
+eggar
+egged
+egger
+egmas
+ehing
+eider
+eidos
+eigne
+eiked
+eikon
+eilds
+eisel
+ejido
+ekkas
+elain
+eland
+elans
+elchi
+eldin
+elemi
+elfed
+eliad
+elint
+elmen
+eloge
+elogy
+eloin
+elops
+elpee
+elsin
+elute
+elvan
+elven
+elver
+elves
+emacs
+embar
+embay
+embog
+embow
+embox
+embus
+emeer
+emend
+emerg
+emery
+emeus
+emics
+emirs
+emits
+emmas
+emmer
+emmet
+emmew
+emmys
+emoji
+emong
+emote
+emove
+empts
+emule
+emure
+emyde
+emyds
+enarm
+enate
+ended
+ender
+endew
+endue
+enews
+enfix
+eniac
+enlit
+enmew
+ennog
+enoki
+enols
+enorm
+enows
+enrol
+ensew
+ensky
+entia
+enure
+enurn
+envoi
+enzym
+eorls
+eosin
+epact
+epees
+ephah
+ephas
+ephod
+ephor
+epics
+epode
+epopt
+epris
+eques
+equid
+erbia
+erevs
+ergon
+ergos
+ergot
+erhus
+erica
+erick
+erics
+ering
+erned
+ernes
+erose
+erred
+erses
+eruct
+erugo
+eruvs
+erven
+ervil
+escar
+escot
+esile
+eskar
+esker
+esnes
+esses
+estoc
+estop
+estro
+etage
+etape
+etats
+etens
+ethal
+ethne
+ethyl
+etics
+etnas
+ettin
+ettle
+etuis
+etwee
+etyma
+eughs
+euked
+eupad
+euros
+eusol
+evens
+evert
+evets
+evhoe
+evils
+evite
+evohe
+ewers
+ewest
+ewhow
+ewked
+exams
+exeat
+execs
+exeem
+exeme
+exfil
+exies
+exine
+exing
+exits
+exode
+exome
+exons
+expat
+expos
+exude
+exuls
+exurb
+eyass
+eyers
+eyots
+eyras
+eyres
+eyrie
+eyrir
+ezine
+fabby
+faced
+facer
+faces
+facia
+facta
+facts
+faddy
+faded
+fader
+fades
+fadge
+fados
+faena
+faery
+faffs
+faffy
+faggy
+fagin
+fagot
+faiks
+fails
+faine
+fains
+fairs
+faked
+faker
+fakes
+fakey
+fakie
+fakir
+falaj
+falls
+famed
+fames
+fanal
+fands
+fanes
+fanga
+fango
+fangs
+fanks
+fanon
+fanos
+fanum
+faqir
+farad
+farci
+farcy
+fards
+fared
+farer
+fares
+farle
+farls
+farms
+faros
+farro
+farse
+farts
+fasci
+fasti
+fasts
+fated
+fates
+fatly
+fatso
+fatwa
+faugh
+fauld
+fauns
+faurd
+fauts
+fauve
+favas
+favel
+faver
+faves
+favus
+fawns
+fawny
+faxed
+faxes
+fayed
+fayer
+fayne
+fayre
+fazed
+fazes
+feals
+feare
+fears
+feart
+fease
+feats
+feaze
+feces
+fecht
+fecit
+fecks
+fedex
+feebs
+feeds
+feels
+feens
+feers
+feese
+feeze
+fehme
+feint
+feist
+felch
+felid
+fells
+felly
+felts
+felty
+femal
+femes
+femmy
+fends
+fendy
+fenis
+fenks
+fenny
+fents
+feods
+feoff
+ferer
+feres
+feria
+ferly
+fermi
+ferms
+ferns
+ferny
+fesse
+festa
+fests
+festy
+fetas
+feted
+fetes
+fetor
+fetta
+fetts
+fetwa
+feuar
+feuds
+feued
+feyed
+feyer
+feyly
+fezes
+fezzy
+fiars
+fiats
+fibro
+fices
+fiche
+fichu
+ficin
+ficos
+fides
+fidge
+fidos
+fiefs
+fient
+fiere
+fiers
+fiest
+fifed
+fifer
+fifes
+fifis
+figgy
+figos
+fiked
+fikes
+filar
+filch
+filed
+files
+filii
+filks
+fille
+fillo
+fills
+filmi
+films
+filos
+filum
+finca
+finds
+fined
+fines
+finis
+finks
+finny
+finos
+fiord
+fiqhs
+fique
+fired
+firer
+fires
+firie
+firks
+firms
+firns
+firry
+firth
+fiscs
+fisks
+fists
+fisty
+fitch
+fitly
+fitna
+fitte
+fitts
+fiver
+fives
+fixed
+fixes
+fixit
+fjeld
+flabs
+flaff
+flags
+flaks
+flamm
+flams
+flamy
+flane
+flans
+flaps
+flary
+flats
+flava
+flawn
+flaws
+flawy
+flaxy
+flays
+fleam
+fleas
+fleek
+fleer
+flees
+flegs
+fleme
+fleur
+flews
+flexi
+flexo
+fleys
+flics
+flied
+flies
+flimp
+flims
+flips
+flirs
+flisk
+flite
+flits
+flitt
+flobs
+flocs
+floes
+flogs
+flong
+flops
+flors
+flory
+flosh
+flota
+flote
+flows
+flubs
+flued
+flues
+fluey
+fluky
+flump
+fluor
+flurr
+fluty
+fluyt
+flyby
+flype
+flyte
+foals
+foams
+foehn
+fogey
+fogie
+fogle
+fogou
+fohns
+foids
+foils
+foins
+folds
+foley
+folia
+folic
+folie
+folks
+folky
+fomes
+fonda
+fonds
+fondu
+fones
+fonly
+fonts
+foods
+foody
+fools
+foots
+footy
+foram
+forbs
+forby
+fordo
+fords
+forel
+fores
+forex
+forks
+forky
+forme
+forms
+forts
+forza
+forze
+fossa
+fosse
+fouat
+fouds
+fouer
+fouet
+foule
+fouls
+fount
+fours
+fouth
+fovea
+fowls
+fowth
+foxed
+foxes
+foxie
+foyle
+foyne
+frabs
+frack
+fract
+frags
+fraim
+franc
+frape
+fraps
+frass
+frate
+frati
+frats
+fraus
+frays
+frees
+freet
+freit
+fremd
+frena
+freon
+frere
+frets
+fribs
+frier
+fries
+frigs
+frise
+frist
+frith
+frits
+fritt
+frize
+frizz
+froes
+frogs
+frons
+frore
+frorn
+frory
+frosh
+frows
+frowy
+frugs
+frump
+frush
+frust
+fryer
+fubar
+fubby
+fubsy
+fucks
+fucus
+fuddy
+fudgy
+fuels
+fuero
+fuffs
+fuffy
+fugal
+fuggy
+fugie
+fugio
+fugle
+fugly
+fugus
+fujis
+fulls
+fumed
+fumer
+fumes
+fumet
+fundi
+funds
+fundy
+fungo
+fungs
+funks
+fural
+furan
+furca
+furls
+furol
+furrs
+furth
+furze
+furzy
+fused
+fusee
+fusel
+fuses
+fusil
+fusks
+fusts
+fusty
+futon
+fuzed
+fuzee
+fuzes
+fuzil
+fyces
+fyked
+fykes
+fyles
+fyrds
+fytte
+gabba
+gabby
+gable
+gaddi
+gades
+gadge
+gadid
+gadis
+gadje
+gadjo
+gadso
+gaffs
+gaged
+gager
+gages
+gaids
+gains
+gairs
+gaita
+gaits
+gaitt
+gajos
+galah
+galas
+galax
+galea
+galed
+gales
+galls
+gally
+galop
+galut
+galvo
+gamas
+gamay
+gamba
+gambe
+gambo
+gambs
+gamed
+games
+gamey
+gamic
+gamin
+gamme
+gammy
+gamps
+ganch
+gandy
+ganef
+ganev
+gangs
+ganja
+ganof
+gants
+gaols
+gaped
+gaper
+gapes
+gapos
+gappy
+garbe
+garbo
+garbs
+garda
+gares
+garis
+garms
+garni
+garre
+garth
+garum
+gases
+gasps
+gaspy
+gasts
+gatch
+gated
+gater
+gates
+gaths
+gator
+gauch
+gaucy
+gauds
+gauje
+gault
+gaums
+gaumy
+gaups
+gaurs
+gauss
+gauzy
+gavot
+gawcy
+gawds
+gawks
+gawps
+gawsy
+gayal
+gazal
+gazar
+gazed
+gazes
+gazon
+gazoo
+geals
+geans
+geare
+gears
+geats
+gebur
+gecks
+geeks
+geeps
+geest
+geist
+geits
+gelds
+gelee
+gelid
+gelly
+gelts
+gemel
+gemma
+gemmy
+gemot
+genal
+genas
+genes
+genet
+genic
+genii
+genip
+genny
+genoa
+genom
+genro
+gents
+genty
+genua
+genus
+geode
+geoid
+gerah
+gerbe
+geres
+gerle
+germs
+germy
+gerne
+gesse
+gesso
+geste
+gests
+getas
+getup
+geums
+geyan
+geyer
+ghast
+ghats
+ghaut
+ghazi
+ghees
+ghest
+ghyll
+gibed
+gibel
+giber
+gibes
+gibli
+gibus
+gifts
+gigas
+gighe
+gigot
+gigue
+gilas
+gilds
+gilet
+gills
+gilly
+gilpy
+gilts
+gimel
+gimme
+gimps
+gimpy
+ginch
+ginge
+gings
+ginks
+ginny
+ginzo
+gipon
+gippo
+gippy
+girds
+girls
+girns
+giron
+giros
+girrs
+girsh
+girts
+gismo
+gisms
+gists
+gitch
+gites
+giust
+gived
+gives
+gizmo
+glace
+glads
+glady
+glaik
+glair
+glams
+glans
+glary
+glaum
+glaur
+glazy
+gleba
+glebe
+gleby
+glede
+gleds
+gleed
+gleek
+glees
+gleet
+gleis
+glens
+glent
+gleys
+glial
+glias
+glibs
+gliff
+glift
+glike
+glime
+glims
+glisk
+glits
+glitz
+gloam
+globi
+globs
+globy
+glode
+glogg
+gloms
+gloop
+glops
+glost
+glout
+glows
+gloze
+glued
+gluer
+glues
+gluey
+glugs
+glume
+glums
+gluon
+glute
+gluts
+gnarl
+gnarr
+gnars
+gnats
+gnawn
+gnaws
+gnows
+goads
+goafs
+goals
+goary
+goats
+goaty
+goban
+gobar
+gobbi
+gobbo
+gobby
+gobis
+gobos
+godet
+godso
+goels
+goers
+goest
+goeth
+goety
+gofer
+goffs
+gogga
+gogos
+goier
+gojis
+golds
+goldy
+goles
+golfs
+golpe
+golps
+gombo
+gomer
+gompa
+gonch
+gonef
+gongs
+gonia
+gonif
+gonks
+gonna
+gonof
+gonys
+gonzo
+gooby
+goods
+goofs
+googs
+gooks
+gooky
+goold
+gools
+gooly
+goons
+goony
+goops
+goopy
+goors
+goory
+goosy
+gopak
+gopik
+goral
+goras
+gored
+gores
+goris
+gorms
+gormy
+gorps
+gorse
+gorsy
+gosht
+gosse
+gotch
+goths
+gothy
+gotta
+gouch
+gouks
+goura
+gouts
+gouty
+gowan
+gowds
+gowfs
+gowks
+gowls
+gowns
+goxes
+goyim
+goyle
+graal
+grabs
+grads
+graff
+graip
+grama
+grame
+gramp
+grams
+grana
+grans
+grapy
+gravs
+grays
+grebe
+grebo
+grece
+greek
+grees
+grege
+grego
+grein
+grens
+grese
+greve
+grews
+greys
+grice
+gride
+grids
+griff
+grift
+grigs
+grike
+grins
+griot
+grips
+gript
+gripy
+grise
+grist
+grisy
+grith
+grits
+grize
+groat
+grody
+grogs
+groks
+groma
+grone
+groof
+grosz
+grots
+grouf
+grovy
+grows
+grrls
+grrrl
+grubs
+grued
+grues
+grufe
+grume
+grump
+grund
+gryce
+gryde
+gryke
+grype
+grypt
+guaco
+guana
+guano
+guans
+guars
+gucks
+gucky
+gudes
+guffs
+gugas
+guids
+guimp
+guiro
+gulag
+gular
+gulas
+gules
+gulet
+gulfs
+gulfy
+gulls
+gulph
+gulps
+gulpy
+gumma
+gummi
+gumps
+gundy
+gunge
+gungy
+gunks
+gunky
+gunny
+guqin
+gurdy
+gurge
+gurls
+gurly
+gurns
+gurry
+gursh
+gurus
+gushy
+gusla
+gusle
+gusli
+gussy
+gusts
+gutsy
+gutta
+gutty
+guyed
+guyle
+guyot
+guyse
+gwine
+gyals
+gyans
+gybed
+gybes
+gyeld
+gymps
+gynae
+gynie
+gynny
+gynos
+gyoza
+gypos
+gyppo
+gyppy
+gyral
+gyred
+gyres
+gyron
+gyros
+gyrus
+gytes
+gyved
+gyves
+haafs
+haars
+hable
+habus
+hacek
+hacks
+hadal
+haded
+hades
+hadji
+hadst
+haems
+haets
+haffs
+hafiz
+hafts
+haggs
+hahas
+haick
+haika
+haiks
+haiku
+hails
+haily
+hains
+haint
+hairs
+haith
+hajes
+hajis
+hajji
+hakam
+hakas
+hakea
+hakes
+hakim
+hakus
+halal
+haled
+haler
+hales
+halfa
+halfs
+halid
+hallo
+halls
+halma
+halms
+halon
+halos
+halse
+halts
+halva
+halwa
+hamal
+hamba
+hamed
+hames
+hammy
+hamza
+hanap
+hance
+hanch
+hands
+hangi
+hangs
+hanks
+hanky
+hansa
+hanse
+hants
+haole
+haoma
+hapax
+haply
+happi
+hapus
+haram
+hards
+hared
+hares
+harim
+harks
+harls
+harms
+harns
+haros
+harps
+harts
+hashy
+hasks
+hasps
+hasta
+hated
+hates
+hatha
+hauds
+haufs
+haugh
+hauld
+haulm
+hauls
+hault
+hauns
+hause
+haver
+haves
+hawed
+hawks
+hawms
+hawse
+hayed
+hayer
+hayey
+hayle
+hazan
+hazed
+hazer
+hazes
+heads
+heald
+heals
+heame
+heaps
+heapy
+heare
+hears
+heast
+heats
+heben
+hebes
+hecht
+hecks
+heder
+hedgy
+heeds
+heedy
+heels
+heeze
+hefte
+hefts
+heids
+heigh
+heils
+heirs
+hejab
+hejra
+heled
+heles
+helio
+hells
+helms
+helos
+helot
+helps
+helve
+hemal
+hemes
+hemic
+hemin
+hemps
+hempy
+hench
+hends
+henge
+henna
+henny
+henry
+hents
+hepar
+herbs
+herby
+herds
+heres
+herls
+herma
+herms
+herns
+heros
+herry
+herse
+hertz
+herye
+hesps
+hests
+hetes
+heths
+heuch
+heugh
+hevea
+hewed
+hewer
+hewgh
+hexad
+hexed
+hexer
+hexes
+hexyl
+heyed
+hiant
+hicks
+hided
+hider
+hides
+hiems
+highs
+hight
+hijab
+hijra
+hiked
+hiker
+hikes
+hikoi
+hilar
+hilch
+hillo
+hills
+hilts
+hilum
+hilus
+himbo
+hinau
+hinds
+hings
+hinky
+hinny
+hints
+hiois
+hiply
+hired
+hiree
+hirer
+hires
+hissy
+hists
+hithe
+hived
+hiver
+hives
+hizen
+hoaed
+hoagy
+hoars
+hoary
+hoast
+hobos
+hocks
+hocus
+hodad
+hodja
+hoers
+hogan
+hogen
+hoggs
+hoghs
+hohed
+hoick
+hoied
+hoiks
+hoing
+hoise
+hokas
+hoked
+hokes
+hokey
+hokis
+hokku
+hokum
+holds
+holed
+holes
+holey
+holks
+holla
+hollo
+holme
+holms
+holon
+holos
+holts
+homas
+homed
+homes
+homey
+homie
+homme
+homos
+honan
+honda
+honds
+honed
+honer
+hones
+hongi
+hongs
+honks
+honky
+hooch
+hoods
+hoody
+hooey
+hoofs
+hooka
+hooks
+hooky
+hooly
+hoons
+hoops
+hoord
+hoors
+hoosh
+hoots
+hooty
+hoove
+hopak
+hoped
+hoper
+hopes
+hoppy
+horah
+horal
+horas
+horis
+horks
+horme
+horns
+horst
+horsy
+hosed
+hosel
+hosen
+hoser
+hoses
+hosey
+hosta
+hosts
+hotch
+hoten
+hotty
+houff
+houfs
+hough
+houri
+hours
+houts
+hovea
+hoved
+hoven
+hoves
+howbe
+howes
+howff
+howfs
+howks
+howls
+howre
+howso
+hoxed
+hoxes
+hoyas
+hoyed
+hoyle
+hubby
+hucks
+hudna
+hudud
+huers
+huffs
+huffy
+huger
+huggy
+huhus
+huias
+hulas
+hules
+hulks
+hulky
+hullo
+hulls
+hully
+humas
+humfs
+humic
+humps
+humpy
+hunks
+hunts
+hurds
+hurls
+hurly
+hurra
+hurst
+hurts
+hushy
+husks
+husos
+hutia
+huzza
+huzzy
+hwyls
+hydra
+hyens
+hygge
+hying
+hykes
+hylas
+hyleg
+hyles
+hylic
+hymns
+hynde
+hyoid
+hyped
+hypes
+hypha
+hyphy
+hypos
+hyrax
+hyson
+hythe
+iambi
+iambs
+ibrik
+icers
+iched
+iches
+ichor
+icier
+icker
+ickle
+icons
+ictal
+ictic
+ictus
+idant
+ideas
+idees
+ident
+idled
+idles
+idola
+idols
+idyls
+iftar
+igapo
+igged
+iglus
+ihram
+ikans
+ikats
+ikons
+ileac
+ileal
+ileum
+ileus
+iliad
+ilial
+ilium
+iller
+illth
+imago
+imams
+imari
+imaum
+imbar
+imbed
+imide
+imido
+imids
+imine
+imino
+immew
+immit
+immix
+imped
+impis
+impot
+impro
+imshi
+imshy
+inapt
+inarm
+inbye
+incel
+incle
+incog
+incus
+incut
+indew
+india
+indie
+indol
+indow
+indri
+indue
+inerm
+infix
+infos
+infra
+ingan
+ingle
+inion
+inked
+inker
+inkle
+inned
+innit
+inorb
+inrun
+inset
+inspo
+intel
+intil
+intis
+intra
+inula
+inure
+inurn
+inust
+invar
+inwit
+iodic
+iodid
+iodin
+iotas
+ippon
+irade
+irids
+iring
+irked
+iroko
+irone
+irons
+isbas
+ishes
+isled
+isles
+isnae
+issei
+istle
+items
+ither
+ivied
+ivies
+ixias
+ixnay
+ixora
+ixtle
+izard
+izars
+izzat
+jaaps
+jabot
+jacal
+jacks
+jacky
+jaded
+jades
+jafas
+jaffa
+jagas
+jager
+jaggs
+jaggy
+jagir
+jagra
+jails
+jaker
+jakes
+jakey
+jalap
+jalop
+jambe
+jambo
+jambs
+jambu
+james
+jammy
+jamon
+janes
+janns
+janny
+janty
+japan
+japed
+japer
+japes
+jarks
+jarls
+jarps
+jarta
+jarul
+jasey
+jaspe
+jasps
+jatos
+jauks
+jaups
+javas
+javel
+jawan
+jawed
+jaxie
+jeans
+jeats
+jebel
+jedis
+jeels
+jeely
+jeeps
+jeers
+jeeze
+jefes
+jeffs
+jehad
+jehus
+jelab
+jello
+jells
+jembe
+jemmy
+jenny
+jeons
+jerid
+jerks
+jerry
+jesse
+jests
+jesus
+jetes
+jeton
+jeune
+jewed
+jewie
+jhala
+jiaos
+jibba
+jibbs
+jibed
+jiber
+jibes
+jiffs
+jiggy
+jigot
+jihad
+jills
+jilts
+jimmy
+jimpy
+jingo
+jinks
+jinne
+jinni
+jinns
+jirds
+jirga
+jirre
+jisms
+jived
+jiver
+jives
+jivey
+jnana
+jobed
+jobes
+jocko
+jocks
+jocky
+jocos
+jodel
+joeys
+johns
+joins
+joked
+jokes
+jokey
+jokol
+joled
+joles
+jolls
+jolts
+jolty
+jomon
+jomos
+jones
+jongs
+jonty
+jooks
+joram
+jorum
+jotas
+jotty
+jotun
+joual
+jougs
+jouks
+joule
+jours
+jowar
+jowed
+jowls
+jowly
+joyed
+jubas
+jubes
+jucos
+judas
+judgy
+judos
+jugal
+jugum
+jujus
+juked
+jukes
+jukus
+julep
+jumar
+jumby
+jumps
+junco
+junks
+junky
+jupes
+jupon
+jural
+jurat
+jurel
+jures
+justs
+jutes
+jutty
+juves
+juvie
+kaama
+kabab
+kabar
+kabob
+kacha
+kacks
+kadai
+kades
+kadis
+kafir
+kagos
+kagus
+kahal
+kaiak
+kaids
+kaies
+kaifs
+kaika
+kaiks
+kails
+kaims
+kaing
+kains
+kakas
+kakis
+kalam
+kales
+kalif
+kalis
+kalpa
+kamas
+kames
+kamik
+kamis
+kamme
+kanae
+kanas
+kandy
+kaneh
+kanes
+kanga
+kangs
+kanji
+kants
+kanzu
+kaons
+kapas
+kaphs
+kapok
+kapow
+kapus
+kaput
+karas
+karat
+karks
+karns
+karoo
+karos
+karri
+karst
+karsy
+karts
+karzy
+kasha
+kasme
+katal
+katas
+katis
+katti
+kaugh
+kauri
+kauru
+kaury
+kaval
+kavas
+kawas
+kawau
+kawed
+kayle
+kayos
+kazis
+kazoo
+kbars
+kebar
+kebob
+kecks
+kedge
+kedgy
+keech
+keefs
+keeks
+keels
+keema
+keeno
+keens
+keeps
+keets
+keeve
+kefir
+kehua
+keirs
+kelep
+kelim
+kells
+kelly
+kelps
+kelpy
+kelts
+kelty
+kembo
+kembs
+kemps
+kempt
+kempy
+kenaf
+kench
+kendo
+kenos
+kente
+kents
+kepis
+kerbs
+kerel
+kerfs
+kerky
+kerma
+kerne
+kerns
+keros
+kerry
+kerve
+kesar
+kests
+ketas
+ketch
+ketes
+ketol
+kevel
+kevil
+kexes
+keyed
+keyer
+khadi
+khafs
+khans
+khaph
+khats
+khaya
+khazi
+kheda
+kheth
+khets
+khoja
+khors
+khoum
+khuds
+kiaat
+kiack
+kiang
+kibbe
+kibbi
+kibei
+kibes
+kibla
+kicks
+kicky
+kiddo
+kiddy
+kidel
+kidge
+kiefs
+kiers
+kieve
+kievs
+kight
+kikes
+kikoi
+kiley
+kilim
+kills
+kilns
+kilos
+kilps
+kilts
+kilty
+kimbo
+kinas
+kinda
+kinds
+kindy
+kines
+kings
+kinin
+kinks
+kinos
+kiore
+kipes
+kippa
+kipps
+kirby
+kirks
+kirns
+kirri
+kisan
+kissy
+kists
+kited
+kiter
+kites
+kithe
+kiths
+kitul
+kivas
+kiwis
+klang
+klaps
+klett
+klick
+klieg
+kliks
+klong
+kloof
+kluge
+klutz
+knags
+knaps
+knarl
+knars
+knaur
+knawe
+knees
+knell
+knish
+knits
+knive
+knobs
+knops
+knosp
+knots
+knout
+knowe
+knows
+knubs
+knurl
+knurr
+knurs
+knuts
+koans
+koaps
+koban
+kobos
+koels
+koffs
+kofta
+kogal
+kohas
+kohen
+kohls
+koine
+kojis
+kokam
+kokas
+koker
+kokra
+kokum
+kolas
+kolos
+kombu
+konbu
+kondo
+konks
+kooks
+kooky
+koori
+kopek
+kophs
+kopje
+koppa
+korai
+koras
+korat
+kores
+korma
+koros
+korun
+korus
+koses
+kotch
+kotos
+kotow
+koura
+kraal
+krabs
+kraft
+krais
+krait
+krang
+krans
+kranz
+kraut
+krays
+kreep
+kreng
+krewe
+krona
+krone
+kroon
+krubi
+krunk
+ksars
+kubie
+kudos
+kudus
+kudzu
+kufis
+kugel
+kuias
+kukri
+kukus
+kulak
+kulan
+kulas
+kulfi
+kumis
+kumys
+kuris
+kurre
+kurta
+kurus
+kusso
+kutas
+kutch
+kutis
+kutus
+kuzus
+kvass
+kvell
+kwela
+kyack
+kyaks
+kyang
+kyars
+kyats
+kybos
+kydst
+kyles
+kylie
+kylin
+kylix
+kyloe
+kynde
+kynds
+kypes
+kyrie
+kytes
+kythe
+laari
+labda
+labia
+labis
+labra
+laced
+lacer
+laces
+lacet
+lacey
+lacks
+laddy
+laded
+lader
+lades
+laers
+laevo
+lagan
+lahal
+lahar
+laich
+laics
+laids
+laigh
+laika
+laiks
+laird
+lairs
+lairy
+laith
+laity
+laked
+laker
+lakes
+lakhs
+lakin
+laksa
+laldy
+lalls
+lamas
+lambs
+lamby
+lamed
+lamer
+lames
+lamia
+lammy
+lamps
+lanai
+lanas
+lanch
+lande
+lands
+lanes
+lanks
+lants
+lapin
+lapis
+lapje
+larch
+lards
+lardy
+laree
+lares
+largo
+laris
+larks
+larky
+larns
+larnt
+larum
+lased
+laser
+lases
+lassi
+lassu
+lassy
+lasts
+latah
+lated
+laten
+latex
+lathi
+laths
+lathy
+latke
+latus
+lauan
+lauch
+lauds
+laufs
+laund
+laura
+laval
+lavas
+laved
+laver
+laves
+lavra
+lavvy
+lawed
+lawer
+lawin
+lawks
+lawns
+lawny
+laxed
+laxer
+laxes
+laxly
+layed
+layin
+layup
+lazar
+lazed
+lazes
+lazos
+lazzi
+lazzo
+leads
+leady
+leafs
+leaks
+leams
+leans
+leany
+leaps
+leare
+lears
+leary
+leats
+leavy
+leaze
+leben
+leccy
+ledes
+ledgy
+ledum
+leear
+leeks
+leeps
+leers
+leese
+leets
+leeze
+lefte
+lefts
+leger
+leges
+legge
+leggo
+legit
+lehrs
+lehua
+leirs
+leish
+leman
+lemed
+lemel
+lemes
+lemma
+lemme
+lends
+lenes
+lengs
+lenis
+lenos
+lense
+lenti
+lento
+leone
+lepid
+lepra
+lepta
+lered
+leres
+lerps
+lesbo
+leses
+lests
+letch
+lethe
+letup
+leuch
+leuco
+leuds
+leugh
+levas
+levee
+leves
+levin
+levis
+lewis
+lexes
+lexis
+lezes
+lezza
+lezzy
+liana
+liane
+liang
+liard
+liars
+liart
+liber
+libra
+libri
+lichi
+licht
+licit
+licks
+lidar
+lidos
+liefs
+liens
+liers
+lieus
+lieve
+lifer
+lifes
+lifts
+ligan
+liger
+ligge
+ligne
+liked
+liker
+likes
+likin
+lills
+lilos
+lilts
+liman
+limas
+limax
+limba
+limbi
+limbs
+limby
+limed
+limen
+limes
+limey
+limma
+limns
+limos
+limpa
+limps
+linac
+linch
+linds
+lindy
+lined
+lines
+liney
+linga
+lings
+lingy
+linin
+links
+linky
+linns
+linny
+linos
+lints
+linty
+linum
+linux
+lions
+lipas
+lipes
+lipin
+lipos
+lippy
+liras
+lirks
+lirot
+lisks
+lisle
+lisps
+lists
+litai
+litas
+lited
+liter
+lites
+litho
+liths
+litre
+lived
+liven
+lives
+livor
+livre
+llano
+loach
+loads
+loafs
+loams
+loans
+loast
+loave
+lobar
+lobed
+lobes
+lobos
+lobus
+loche
+lochs
+locie
+locis
+locks
+locos
+locum
+loden
+lodes
+loess
+lofts
+logan
+loges
+loggy
+logia
+logie
+logoi
+logon
+logos
+lohan
+loids
+loins
+loipe
+loirs
+lokes
+lolls
+lolly
+lolog
+lomas
+lomed
+lomes
+loner
+longa
+longe
+longs
+looby
+looed
+looey
+loofa
+loofs
+looie
+looks
+looky
+looms
+loons
+loony
+loops
+loord
+loots
+loped
+loper
+lopes
+loppy
+loral
+loran
+lords
+lordy
+lorel
+lores
+loric
+loris
+losed
+losel
+losen
+loses
+lossy
+lotah
+lotas
+lotes
+lotic
+lotos
+lotsa
+lotta
+lotte
+lotto
+lotus
+loued
+lough
+louie
+louis
+louma
+lound
+louns
+loupe
+loups
+loure
+lours
+loury
+louts
+lovat
+loved
+loves
+lovey
+lovie
+lowan
+lowed
+lowes
+lownd
+lowne
+lowns
+lowps
+lowry
+lowse
+lowts
+loxed
+loxes
+lozen
+luach
+luaus
+lubed
+lubes
+lubra
+luces
+lucks
+lucre
+ludes
+ludic
+ludos
+luffa
+luffs
+luged
+luger
+luges
+lulls
+lulus
+lumas
+lumbi
+lumme
+lummy
+lumps
+lunas
+lunes
+lunet
+lungi
+lungs
+lunks
+lunts
+lupin
+lured
+lurer
+lures
+lurex
+lurgi
+lurgy
+lurks
+lurry
+lurve
+luser
+lushy
+lusks
+lusts
+lusus
+lutea
+luted
+luter
+lutes
+luvvy
+luxed
+luxer
+luxes
+lweis
+lyams
+lyard
+lyart
+lyase
+lycea
+lycee
+lycra
+lymes
+lynes
+lyres
+lysed
+lyses
+lysin
+lysis
+lysol
+lyssa
+lyted
+lytes
+lythe
+lytic
+lytta
+maaed
+maare
+maars
+mabes
+macas
+maced
+macer
+maces
+mache
+machi
+machs
+macks
+macle
+macon
+madge
+madid
+madre
+maerl
+mafic
+mages
+maggs
+magot
+magus
+mahoe
+mahua
+mahwa
+maids
+maiko
+maiks
+maile
+maill
+mails
+maims
+mains
+maire
+mairs
+maise
+maist
+makar
+makes
+makis
+makos
+malam
+malar
+malas
+malax
+males
+malic
+malik
+malis
+malls
+malms
+malmy
+malts
+malty
+malus
+malva
+malwa
+mamas
+mamba
+mamee
+mamey
+mamie
+manas
+manat
+mandi
+maneb
+maned
+maneh
+manes
+manet
+mangs
+manis
+manky
+manna
+manos
+manse
+manta
+manto
+manty
+manul
+manus
+mapau
+maqui
+marae
+marah
+maras
+marcs
+mardy
+mares
+marge
+margs
+maria
+marid
+marka
+marks
+marle
+marls
+marly
+marms
+maron
+maror
+marra
+marri
+marse
+marts
+marvy
+masas
+mased
+maser
+mases
+mashy
+masks
+massa
+massy
+masts
+masty
+masus
+matai
+mated
+mater
+mates
+maths
+matin
+matlo
+matte
+matts
+matza
+matzo
+mauby
+mauds
+mauls
+maund
+mauri
+mausy
+mauts
+mauzy
+maven
+mavie
+mavin
+mavis
+mawed
+mawks
+mawky
+mawns
+mawrs
+maxed
+maxes
+maxis
+mayan
+mayas
+mayed
+mayos
+mayst
+mazed
+mazer
+mazes
+mazey
+mazut
+mbira
+meads
+meals
+meane
+means
+meany
+meare
+mease
+meath
+meats
+mebos
+mechs
+mecks
+medii
+medle
+meeds
+meers
+meets
+meffs
+meins
+meint
+meiny
+meith
+mekka
+melas
+melba
+melds
+melic
+melik
+mells
+melts
+melty
+memes
+memos
+menad
+mends
+mened
+menes
+menge
+mengs
+mensa
+mense
+mensh
+menta
+mento
+menus
+meous
+meows
+merch
+mercs
+merde
+mered
+merel
+merer
+meres
+meril
+meris
+merks
+merle
+merls
+merse
+mesal
+mesas
+mesel
+meses
+meshy
+mesic
+mesne
+meson
+messy
+mesto
+meted
+metes
+metho
+meths
+metic
+metif
+metis
+metol
+metre
+meuse
+meved
+meves
+mewed
+mewls
+meynt
+mezes
+mezze
+mezzo
+mhorr
+miaou
+miaow
+miasm
+miaul
+micas
+miche
+micht
+micks
+micky
+micos
+micra
+middy
+midgy
+midis
+miens
+mieve
+miffs
+miffy
+mifty
+miggs
+mihas
+mihis
+miked
+mikes
+mikra
+mikva
+milch
+milds
+miler
+miles
+milfs
+milia
+milko
+milks
+mille
+mills
+milor
+milos
+milpa
+milts
+milty
+miltz
+mimed
+mimeo
+mimer
+mimes
+mimsy
+minae
+minar
+minas
+mincy
+minds
+mined
+mines
+minge
+mings
+mingy
+minis
+minke
+minks
+minny
+minos
+mints
+mired
+mires
+mirex
+mirid
+mirin
+mirks
+mirky
+mirly
+miros
+mirvs
+mirza
+misch
+misdo
+mises
+misgo
+misos
+missa
+mists
+misty
+mitch
+miter
+mites
+mitis
+mitre
+mitts
+mixed
+mixen
+mixer
+mixes
+mixte
+mixup
+mizen
+mizzy
+mneme
+moans
+moats
+mobby
+mobes
+mobey
+mobie
+moble
+mochi
+mochs
+mochy
+mocks
+moder
+modes
+modge
+modii
+modus
+moers
+mofos
+moggy
+mohel
+mohos
+mohrs
+mohua
+mohur
+moile
+moils
+moira
+moire
+moits
+mojos
+mokes
+mokis
+mokos
+molal
+molas
+molds
+moled
+moles
+molla
+molls
+molly
+molto
+molts
+molys
+momes
+momma
+mommy
+momus
+monad
+monal
+monas
+monde
+mondo
+moner
+mongo
+mongs
+monic
+monie
+monks
+monos
+monte
+monty
+moobs
+mooch
+moods
+mooed
+mooks
+moola
+mooli
+mools
+mooly
+moong
+moons
+moony
+moops
+moors
+moory
+moots
+moove
+moped
+moper
+mopes
+mopey
+moppy
+mopsy
+mopus
+morae
+moras
+morat
+moray
+morel
+mores
+moria
+morne
+morns
+morra
+morro
+morse
+morts
+mosed
+moses
+mosey
+mosks
+mosso
+moste
+mosts
+moted
+moten
+motes
+motet
+motey
+moths
+mothy
+motis
+motte
+motts
+motty
+motus
+motza
+mouch
+moues
+mould
+mouls
+moups
+moust
+mousy
+moved
+moves
+mowas
+mowed
+mowra
+moxas
+moxie
+moyas
+moyle
+moyls
+mozed
+mozes
+mozos
+mpret
+mucho
+mucic
+mucid
+mucin
+mucks
+mucor
+mucro
+mudge
+mudir
+mudra
+muffs
+mufti
+mugga
+muggs
+muggy
+muhly
+muids
+muils
+muirs
+muist
+mujik
+mulct
+muled
+mules
+muley
+mulga
+mulie
+mulla
+mulls
+mulse
+mulsh
+mumms
+mumps
+mumsy
+mumus
+munga
+munge
+mungo
+mungs
+munis
+munts
+muntu
+muons
+muras
+mured
+mures
+murex
+murid
+murks
+murls
+murly
+murra
+murre
+murri
+murrs
+murry
+murti
+murva
+musar
+musca
+mused
+muser
+muses
+muset
+musha
+musit
+musks
+musos
+musse
+mussy
+musth
+musts
+mutch
+muted
+muter
+mutes
+mutha
+mutis
+muton
+mutts
+muxed
+muxes
+muzak
+muzzy
+mvule
+myall
+mylar
+mynah
+mynas
+myoid
+myoma
+myope
+myops
+myopy
+mysid
+mythi
+myths
+mythy
+myxos
+mzees
+naams
+naans
+nabes
+nabis
+nabks
+nabla
+nabob
+nache
+nacho
+nacre
+nadas
+naeve
+naevi
+naffs
+nagas
+naggy
+nagor
+nahal
+naiad
+naifs
+naiks
+nails
+naira
+nairu
+naked
+naker
+nakfa
+nalas
+naled
+nalla
+named
+namer
+names
+namma
+namus
+nanas
+nance
+nancy
+nandu
+nanna
+nanos
+nanua
+napas
+naped
+napes
+napoo
+nappa
+nappe
+nappy
+naras
+narco
+narcs
+nards
+nares
+naric
+naris
+narks
+narky
+narre
+nashi
+natch
+nates
+natis
+natty
+nauch
+naunt
+navar
+naves
+navew
+navvy
+nawab
+nazes
+nazir
+nazis
+nduja
+neafe
+neals
+neaps
+nears
+neath
+neats
+nebek
+nebel
+necks
+neddy
+needs
+neeld
+neele
+neemb
+neems
+neeps
+neese
+neeze
+negro
+negus
+neifs
+neist
+neive
+nelis
+nelly
+nemas
+nemns
+nempt
+nenes
+neons
+neper
+nepit
+neral
+nerds
+nerka
+nerks
+nerol
+nerts
+nertz
+nervy
+nests
+netes
+netop
+netts
+netty
+neuks
+neume
+neums
+nevel
+neves
+nevus
+newbs
+newed
+newel
+newie
+newsy
+newts
+nexts
+nexus
+ngaio
+ngana
+ngati
+ngoma
+ngwee
+nicad
+nicht
+nicks
+nicol
+nidal
+nided
+nides
+nidor
+nidus
+niefs
+nieve
+nifes
+niffs
+niffy
+nifty
+niger
+nighs
+nihil
+nikab
+nikah
+nikau
+nills
+nimbi
+nimbs
+nimps
+niner
+nines
+ninon
+nipas
+nippy
+niqab
+nirls
+nirly
+nisei
+nisse
+nisus
+niter
+nites
+nitid
+niton
+nitre
+nitro
+nitry
+nitty
+nival
+nixed
+nixer
+nixes
+nixie
+nizam
+nkosi
+noahs
+nobby
+nocks
+nodal
+noddy
+nodes
+nodus
+noels
+noggs
+nohow
+noils
+noily
+noint
+noirs
+noles
+nolls
+nolos
+nomas
+nomen
+nomes
+nomic
+nomoi
+nomos
+nonas
+nonce
+nones
+nonet
+nongs
+nonis
+nonny
+nonyl
+noobs
+nooit
+nooks
+nooky
+noons
+noops
+nopal
+noria
+noris
+norks
+norma
+norms
+nosed
+noser
+noses
+notal
+noted
+noter
+notes
+notum
+nould
+noule
+nouls
+nouns
+nouny
+noups
+novae
+novas
+novum
+noway
+nowed
+nowls
+nowts
+nowty
+noxal
+noxes
+noyau
+noyed
+noyes
+nubby
+nubia
+nucha
+nuddy
+nuder
+nudes
+nudie
+nudzh
+nuffs
+nugae
+nuked
+nukes
+nulla
+nulls
+numbs
+numen
+nummy
+nunny
+nurds
+nurdy
+nurls
+nurrs
+nutso
+nutsy
+nyaff
+nyala
+nying
+nyssa
+oaked
+oaker
+oakum
+oared
+oases
+oasis
+oasts
+oaten
+oater
+oaths
+oaves
+obang
+obeah
+obeli
+obeys
+obias
+obied
+obiit
+obits
+objet
+oboes
+obole
+oboli
+obols
+occam
+ocher
+oches
+ochre
+ochry
+ocker
+ocrea
+octad
+octan
+octas
+octyl
+oculi
+odahs
+odals
+odeon
+odeum
+odism
+odist
+odium
+odors
+odour
+odyle
+odyls
+ofays
+offed
+offie
+oflag
+ofter
+ogams
+ogeed
+ogees
+oggin
+ogham
+ogive
+ogled
+ogler
+ogles
+ogmic
+ogres
+ohias
+ohing
+ohmic
+ohone
+oidia
+oiled
+oiler
+oinks
+oints
+ojime
+okapi
+okays
+okehs
+okras
+oktas
+oldie
+oleic
+olein
+olent
+oleos
+oleum
+olios
+ollas
+ollav
+oller
+ollie
+ology
+olpae
+olpes
+omasa
+omber
+ombus
+omens
+omers
+omits
+omlah
+omovs
+omrah
+oncer
+onces
+oncet
+oncus
+onely
+oners
+onery
+onium
+onkus
+onlay
+onned
+ontic
+oobit
+oohed
+oomph
+oonts
+ooped
+oorie
+ooses
+ootid
+oozed
+oozes
+opahs
+opals
+opens
+opepe
+oping
+oppos
+opsin
+opted
+opter
+orach
+oracy
+orals
+orang
+orant
+orate
+orbed
+orcas
+orcin
+ordos
+oread
+orfes
+orgia
+orgic
+orgue
+oribi
+oriel
+orixa
+orles
+orlon
+orlop
+ormer
+ornis
+orpin
+orris
+ortho
+orval
+orzos
+oscar
+oshac
+osier
+osmic
+osmol
+ossia
+ostia
+otaku
+otary
+ottar
+ottos
+oubit
+oucht
+ouens
+ouija
+oulks
+oumas
+oundy
+oupas
+ouped
+ouphe
+ouphs
+ourie
+ousel
+ousts
+outby
+outed
+outre
+outro
+outta
+ouzel
+ouzos
+ovals
+ovels
+ovens
+overs
+ovist
+ovoli
+ovolo
+ovule
+owche
+owies
+owled
+owler
+owlet
+owned
+owres
+owrie
+owsen
+oxbow
+oxers
+oxeye
+oxids
+oxies
+oxime
+oxims
+oxlip
+oxter
+oyers
+ozeki
+ozzie
+paals
+paans
+pacas
+paced
+pacer
+paces
+pacey
+pacha
+packs
+pacos
+pacta
+pacts
+padis
+padle
+padma
+padre
+padri
+paean
+paedo
+paeon
+paged
+pager
+pages
+pagle
+pagod
+pagri
+paiks
+pails
+pains
+paire
+pairs
+paisa
+paise
+pakka
+palas
+palay
+palea
+paled
+pales
+palet
+palis
+palki
+palla
+palls
+pally
+palms
+palmy
+palpi
+palps
+palsa
+pampa
+panax
+pance
+panda
+pands
+pandy
+paned
+panes
+panga
+pangs
+panim
+panko
+panne
+panni
+panto
+pants
+panty
+paoli
+paolo
+papas
+papaw
+papes
+pappi
+pappy
+parae
+paras
+parch
+pardi
+pards
+pardy
+pared
+paren
+pareo
+pares
+pareu
+parev
+parge
+pargo
+paris
+parki
+parks
+parky
+parle
+parly
+parma
+parol
+parps
+parra
+parrs
+parti
+parts
+parve
+parvo
+paseo
+pases
+pasha
+pashm
+paska
+paspy
+passe
+pasts
+pated
+paten
+pater
+pates
+paths
+patin
+patka
+patly
+patte
+patus
+pauas
+pauls
+pavan
+paved
+paven
+paver
+paves
+pavid
+pavin
+pavis
+pawas
+pawaw
+pawed
+pawer
+pawks
+pawky
+pawls
+pawns
+paxes
+payed
+payor
+paysd
+peage
+peags
+peaks
+peaky
+peals
+peans
+peare
+pears
+peart
+pease
+peats
+peaty
+peavy
+peaze
+pebas
+pechs
+pecke
+pecks
+pecky
+pedes
+pedis
+pedro
+peece
+peeks
+peels
+peens
+peeoy
+peepe
+peeps
+peers
+peery
+peeve
+peggy
+peghs
+peins
+peise
+peize
+pekan
+pekes
+pekin
+pekoe
+pelas
+pelau
+peles
+pelfs
+pells
+pelma
+pelon
+pelta
+pelts
+pends
+pendu
+pened
+penes
+pengo
+penie
+penis
+penks
+penna
+penni
+pents
+peons
+peony
+pepla
+pepos
+peppy
+pepsi
+perai
+perce
+percs
+perdu
+perdy
+perea
+peres
+peris
+perks
+perms
+perns
+perog
+perps
+perry
+perse
+perst
+perts
+perve
+pervo
+pervs
+pervy
+pesos
+pests
+pesty
+petar
+peter
+petit
+petre
+petri
+petti
+petto
+pewee
+pewit
+peyse
+phage
+phang
+phare
+pharm
+pheer
+phene
+pheon
+phese
+phial
+phish
+phizz
+phlox
+phoca
+phono
+phons
+phots
+phpht
+phuts
+phyla
+phyle
+piani
+pians
+pibal
+pical
+picas
+piccy
+picks
+picot
+picra
+picul
+piend
+piers
+piert
+pieta
+piets
+piezo
+pight
+pigmy
+piing
+pikas
+pikau
+piked
+piker
+pikes
+pikey
+pikis
+pikul
+pilae
+pilaf
+pilao
+pilar
+pilau
+pilaw
+pilch
+pilea
+piled
+pilei
+piler
+piles
+pilis
+pills
+pilow
+pilum
+pilus
+pimas
+pimps
+pinas
+pined
+pines
+pingo
+pings
+pinko
+pinks
+pinna
+pinny
+pinon
+pinot
+pinta
+pints
+pinup
+pions
+piony
+pious
+pioye
+pioys
+pipal
+pipas
+piped
+pipes
+pipet
+pipis
+pipit
+pippy
+pipul
+pirai
+pirls
+pirns
+pirog
+pisco
+pises
+pisky
+pisos
+pissy
+piste
+pitas
+piths
+piton
+pitot
+pitta
+piums
+pixes
+pized
+pizes
+plaas
+plack
+plage
+plans
+plaps
+plash
+plasm
+plast
+plats
+platt
+platy
+playa
+plays
+pleas
+plebe
+plebs
+plena
+pleon
+plesh
+plews
+plica
+plies
+plims
+pling
+plink
+ploat
+plods
+plong
+plonk
+plook
+plops
+plots
+plotz
+plouk
+plows
+ploye
+ploys
+plues
+pluff
+plugs
+plums
+plumy
+pluot
+pluto
+plyer
+poach
+poaka
+poake
+poboy
+pocks
+pocky
+podal
+poddy
+podex
+podge
+podgy
+podia
+poems
+poeps
+poets
+pogey
+pogge
+pogos
+pohed
+poilu
+poind
+pokal
+poked
+pokes
+pokey
+pokie
+poled
+poler
+poles
+poley
+polio
+polis
+polje
+polks
+polls
+polly
+polos
+polts
+polys
+pombe
+pomes
+pommy
+pomos
+pomps
+ponce
+poncy
+ponds
+pones
+poney
+ponga
+pongo
+pongs
+pongy
+ponks
+ponts
+ponty
+ponzu
+poods
+pooed
+poofs
+poofy
+poohs
+pooja
+pooka
+pooks
+pools
+poons
+poops
+poopy
+poori
+poort
+poots
+poove
+poovy
+popes
+poppa
+popsy
+porae
+poral
+pored
+porer
+pores
+porge
+porgy
+porin
+porks
+porky
+porno
+porns
+porny
+porta
+ports
+porty
+posed
+poses
+posey
+posho
+posts
+potae
+potch
+poted
+potes
+potin
+potoo
+potsy
+potto
+potts
+potty
+pouff
+poufs
+pouke
+pouks
+poule
+poulp
+poult
+poupe
+poupt
+pours
+pouts
+powan
+powin
+pownd
+powns
+powny
+powre
+poxed
+poxes
+poynt
+poyou
+poyse
+pozzy
+praam
+prads
+prahu
+prams
+prana
+prang
+praos
+prase
+prate
+prats
+pratt
+praty
+praus
+prays
+predy
+preed
+prees
+preif
+prems
+premy
+prent
+preon
+preop
+preps
+presa
+prese
+prest
+preve
+prexy
+preys
+prial
+pricy
+prief
+prier
+pries
+prigs
+prill
+prima
+primi
+primp
+prims
+primy
+prink
+prion
+prise
+priss
+proas
+probs
+prods
+proem
+profs
+progs
+proin
+proke
+prole
+proll
+promo
+proms
+pronk
+props
+prore
+proso
+pross
+prost
+prosy
+proto
+proul
+prows
+proyn
+prunt
+pruta
+pryer
+pryse
+pseud
+pshaw
+psion
+psoae
+psoai
+psoas
+psora
+psych
+psyop
+pubco
+pubes
+pubis
+pucan
+pucer
+puces
+pucka
+pucks
+puddy
+pudge
+pudic
+pudor
+pudsy
+pudus
+puers
+puffa
+puffs
+puggy
+pugil
+puhas
+pujah
+pujas
+pukas
+puked
+puker
+pukes
+pukey
+pukka
+pukus
+pulao
+pulas
+puled
+puler
+pules
+pulik
+pulis
+pulka
+pulks
+pulli
+pulls
+pully
+pulmo
+pulps
+pulus
+pumas
+pumie
+pumps
+punas
+punce
+punga
+pungs
+punji
+punka
+punks
+punky
+punny
+punto
+punts
+punty
+pupae
+pupas
+pupus
+purda
+pured
+pures
+purin
+puris
+purls
+purpy
+purrs
+pursy
+purty
+puses
+pusle
+pussy
+putid
+puton
+putti
+putto
+putts
+puzel
+pwned
+pyats
+pyets
+pygal
+pyins
+pylon
+pyned
+pynes
+pyoid
+pyots
+pyral
+pyran
+pyres
+pyrex
+pyric
+pyros
+pyxed
+pyxes
+pyxie
+pyxis
+pzazz
+qadis
+qaids
+qajaq
+qanat
+qapik
+qibla
+qophs
+qorma
+quads
+quaff
+quags
+quair
+quais
+quaky
+quale
+quant
+quare
+quass
+quate
+quats
+quayd
+quays
+qubit
+quean
+queme
+quena
+quern
+queyn
+queys
+quich
+quids
+quiff
+quims
+quina
+quine
+quino
+quins
+quint
+quipo
+quips
+quipu
+quire
+quirt
+quist
+quits
+quoad
+quods
+quoif
+quoin
+quoit
+quoll
+quonk
+quops
+qursh
+quyte
+rabat
+rabic
+rabis
+raced
+races
+rache
+racks
+racon
+radge
+radix
+radon
+raffs
+rafts
+ragas
+ragde
+raged
+ragee
+rager
+rages
+ragga
+raggs
+raggy
+ragis
+ragus
+rahed
+rahui
+raias
+raids
+raiks
+raile
+rails
+raine
+rains
+raird
+raita
+raits
+rajas
+rajes
+raked
+rakee
+raker
+rakes
+rakia
+rakis
+rakus
+rales
+ramal
+ramee
+ramet
+ramie
+ramin
+ramis
+rammy
+ramps
+ramus
+ranas
+rance
+rands
+ranee
+ranga
+rangi
+rangs
+rangy
+ranid
+ranis
+ranke
+ranks
+rants
+raped
+raper
+rapes
+raphe
+rappe
+rared
+raree
+rares
+rarks
+rased
+raser
+rases
+rasps
+rasse
+rasta
+ratal
+ratan
+ratas
+ratch
+rated
+ratel
+rater
+rates
+ratha
+rathe
+raths
+ratoo
+ratos
+ratus
+rauns
+raupo
+raved
+ravel
+raver
+raves
+ravey
+ravin
+rawer
+rawin
+rawly
+rawns
+raxed
+raxes
+rayah
+rayas
+rayed
+rayle
+rayne
+razed
+razee
+razer
+razes
+razoo
+readd
+reads
+reais
+reaks
+realo
+reals
+reame
+reams
+reamy
+reans
+reaps
+rears
+reast
+reata
+reate
+reave
+rebbe
+rebec
+rebid
+rebit
+rebop
+rebuy
+recal
+recce
+recco
+reccy
+recit
+recks
+recon
+recta
+recti
+recto
+redan
+redds
+reddy
+reded
+redes
+redia
+redid
+redip
+redly
+redon
+redos
+redox
+redry
+redub
+redux
+redye
+reech
+reede
+reeds
+reefs
+reefy
+reeks
+reeky
+reels
+reens
+reest
+reeve
+refed
+refel
+reffo
+refis
+refix
+refly
+refry
+regar
+reges
+reggo
+regie
+regma
+regna
+regos
+regur
+rehem
+reifs
+reify
+reiki
+reiks
+reink
+reins
+reird
+reist
+reive
+rejig
+rejon
+reked
+rekes
+rekey
+relet
+relie
+relit
+rello
+reman
+remap
+remen
+remet
+remex
+remix
+renay
+rends
+reney
+renga
+renig
+renin
+renne
+renos
+rente
+rents
+reoil
+reorg
+repeg
+repin
+repla
+repos
+repot
+repps
+repro
+reran
+rerig
+resat
+resaw
+resay
+resee
+reses
+resew
+resid
+resit
+resod
+resow
+resto
+rests
+resty
+resus
+retag
+retax
+retem
+retia
+retie
+retox
+revet
+revie
+rewan
+rewax
+rewed
+rewet
+rewin
+rewon
+rewth
+rexes
+rezes
+rheas
+rheme
+rheum
+rhies
+rhime
+rhine
+rhody
+rhomb
+rhone
+rhumb
+rhyne
+rhyta
+riads
+rials
+riant
+riata
+ribas
+ribby
+ribes
+riced
+ricer
+rices
+ricey
+richt
+ricin
+ricks
+rides
+ridgy
+ridic
+riels
+riems
+rieve
+rifer
+riffs
+rifte
+rifts
+rifty
+riggs
+rigol
+riled
+riles
+riley
+rille
+rills
+rimae
+rimed
+rimer
+rimes
+rimus
+rinds
+rindy
+rines
+rings
+rinks
+rioja
+riots
+riped
+ripes
+ripps
+rises
+rishi
+risks
+risps
+risus
+rites
+ritts
+ritzy
+rivas
+rived
+rivel
+riven
+rives
+riyal
+rizas
+roads
+roams
+roans
+roars
+roary
+roate
+robed
+robes
+roble
+rocks
+roded
+rodes
+roguy
+rohes
+roids
+roils
+roily
+roins
+roist
+rojak
+rojis
+roked
+roker
+rokes
+rolag
+roles
+rolfs
+rolls
+romal
+roman
+romeo
+romps
+ronde
+rondo
+roneo
+rones
+ronin
+ronne
+ronte
+ronts
+roods
+roofs
+roofy
+rooks
+rooky
+rooms
+roons
+roops
+roopy
+roosa
+roose
+roots
+rooty
+roped
+roper
+ropes
+ropey
+roque
+roral
+rores
+roric
+rorid
+rorie
+rorts
+rorty
+rosed
+roses
+roset
+roshi
+rosin
+rosit
+rosti
+rosts
+rotal
+rotan
+rotas
+rotch
+roted
+rotes
+rotis
+rotls
+roton
+rotos
+rotte
+rouen
+roues
+roule
+rouls
+roums
+roups
+roupy
+roust
+routh
+routs
+roved
+roven
+roves
+rowan
+rowed
+rowel
+rowen
+rowie
+rowme
+rownd
+rowth
+rowts
+royne
+royst
+rozet
+rozit
+ruana
+rubai
+rubby
+rubel
+rubes
+rubin
+ruble
+rubli
+rubus
+ruche
+rucks
+rudas
+rudds
+rudes
+rudie
+rudis
+rueda
+ruers
+ruffe
+ruffs
+rugae
+rugal
+ruggy
+ruing
+ruins
+rukhs
+ruled
+rules
+rumal
+rumbo
+rumen
+rumes
+rumly
+rummy
+rumpo
+rumps
+rumpy
+runch
+runds
+runed
+runes
+rungs
+runic
+runny
+runts
+runty
+rupia
+rurps
+rurus
+rusas
+ruses
+rushy
+rusks
+rusma
+russe
+rusts
+ruths
+rutin
+rutty
+ryals
+rybat
+ryked
+rykes
+rymme
+rynds
+ryots
+ryper
+saags
+sabal
+sabed
+saber
+sabes
+sabha
+sabin
+sabir
+sable
+sabot
+sabra
+sabre
+sacks
+sacra
+saddo
+sades
+sadhe
+sadhu
+sadis
+sados
+sadza
+safed
+safes
+sagas
+sager
+sages
+saggy
+sagos
+sagum
+saheb
+sahib
+saice
+saick
+saics
+saids
+saiga
+sails
+saims
+saine
+sains
+sairs
+saist
+saith
+sajou
+sakai
+saker
+sakes
+sakia
+sakis
+sakti
+salal
+salat
+salep
+sales
+salet
+salic
+salix
+salle
+salmi
+salol
+salop
+salpa
+salps
+salse
+salto
+salts
+salue
+salut
+saman
+samas
+samba
+sambo
+samek
+samel
+samen
+sames
+samey
+samfu
+sammy
+sampi
+samps
+sands
+saned
+sanes
+sanga
+sangh
+sango
+sangs
+sanko
+sansa
+santo
+sants
+saola
+sapan
+sapid
+sapor
+saran
+sards
+sared
+saree
+sarge
+sargo
+sarin
+saris
+sarks
+sarky
+sarod
+saros
+sarus
+saser
+sasin
+sasse
+satai
+satay
+sated
+satem
+sates
+satis
+sauba
+sauch
+saugh
+sauls
+sault
+saunt
+saury
+sauts
+saved
+saver
+saves
+savey
+savin
+sawah
+sawed
+sawer
+saxes
+sayed
+sayer
+sayid
+sayne
+sayon
+sayst
+sazes
+scabs
+scads
+scaff
+scags
+scail
+scala
+scall
+scams
+scand
+scans
+scapa
+scape
+scapi
+scarp
+scars
+scart
+scath
+scats
+scatt
+scaud
+scaup
+scaur
+scaws
+sceat
+scena
+scend
+schav
+schmo
+schul
+schwa
+sclim
+scody
+scogs
+scoog
+scoot
+scopa
+scops
+scots
+scoug
+scoup
+scowp
+scows
+scrab
+scrae
+scrag
+scran
+scrat
+scraw
+scray
+scrim
+scrip
+scrob
+scrod
+scrog
+scrow
+scudi
+scudo
+scuds
+scuff
+scuft
+scugs
+sculk
+scull
+sculp
+sculs
+scums
+scups
+scurf
+scurs
+scuse
+scuta
+scute
+scuts
+scuzz
+scyes
+sdayn
+sdein
+seals
+seame
+seams
+seamy
+seans
+seare
+sears
+sease
+seats
+seaze
+sebum
+secco
+sechs
+sects
+seder
+sedes
+sedge
+sedgy
+sedum
+seeds
+seeks
+seeld
+seels
+seely
+seems
+seeps
+seepy
+seers
+sefer
+segar
+segni
+segno
+segol
+segos
+sehri
+seifs
+seils
+seine
+seirs
+seise
+seism
+seity
+seiza
+sekos
+sekts
+selah
+seles
+selfs
+sella
+selle
+sells
+selva
+semee
+semes
+semie
+semis
+senas
+sends
+senes
+sengi
+senna
+senor
+sensa
+sensi
+sente
+senti
+sents
+senvy
+senza
+sepad
+sepal
+sepic
+sepoy
+septa
+septs
+serac
+serai
+seral
+sered
+serer
+seres
+serfs
+serge
+seric
+serin
+serks
+seron
+serow
+serra
+serre
+serrs
+serry
+servo
+sesey
+sessa
+setae
+setal
+seton
+setts
+sewan
+sewar
+sewed
+sewel
+sewen
+sewin
+sexed
+sexer
+sexes
+sexto
+sexts
+seyen
+shads
+shags
+shahs
+shako
+shakt
+shalm
+shaly
+shama
+shams
+shand
+shans
+shaps
+sharn
+shash
+shaul
+shawm
+shawn
+shaws
+shaya
+shays
+shchi
+sheaf
+sheal
+sheas
+sheds
+sheel
+shend
+shent
+sheol
+sherd
+shere
+shero
+shets
+sheva
+shewn
+shews
+shiai
+shiel
+shier
+shies
+shill
+shily
+shims
+shins
+ships
+shirr
+shirs
+shish
+shiso
+shist
+shite
+shits
+shiur
+shiva
+shive
+shivs
+shlep
+shlub
+shmek
+shmoe
+shoat
+shoed
+shoer
+shoes
+shogi
+shogs
+shoji
+shojo
+shola
+shool
+shoon
+shoos
+shope
+shops
+shorl
+shote
+shots
+shott
+showd
+shows
+shoyu
+shred
+shris
+shrow
+shtik
+shtum
+shtup
+shule
+shuln
+shuls
+shuns
+shura
+shute
+shuts
+shwas
+shyer
+sials
+sibbs
+sibyl
+sices
+sicht
+sicko
+sicks
+sicky
+sidas
+sided
+sider
+sides
+sidha
+sidhe
+sidle
+sield
+siens
+sient
+sieth
+sieur
+sifts
+sighs
+sigil
+sigla
+signa
+signs
+sijos
+sikas
+siker
+sikes
+silds
+siled
+silen
+siler
+siles
+silex
+silks
+sills
+silos
+silts
+silty
+silva
+simar
+simas
+simba
+simis
+simps
+simul
+sinds
+sined
+sines
+sings
+sinhs
+sinks
+sinky
+sinus
+siped
+sipes
+sippy
+sired
+siree
+sires
+sirih
+siris
+siroc
+sirra
+sirup
+sisal
+sises
+sista
+sists
+sitar
+sited
+sites
+sithe
+sitka
+situp
+situs
+siver
+sixer
+sixes
+sixmo
+sixte
+sizar
+sized
+sizel
+sizer
+sizes
+skags
+skail
+skald
+skank
+skart
+skats
+skatt
+skaws
+skean
+skear
+skeds
+skeed
+skeef
+skeen
+skeer
+skees
+skeet
+skegg
+skegs
+skein
+skelf
+skell
+skelm
+skelp
+skene
+skens
+skeos
+skeps
+skers
+skets
+skews
+skids
+skied
+skies
+skiey
+skimo
+skims
+skink
+skins
+skint
+skios
+skips
+skirl
+skirr
+skite
+skits
+skive
+skivy
+sklim
+skoal
+skody
+skoff
+skogs
+skols
+skool
+skort
+skosh
+skran
+skrik
+skuas
+skugs
+skyed
+skyer
+skyey
+skyfs
+skyre
+skyrs
+skyte
+slabs
+slade
+slaes
+slags
+slaid
+slake
+slams
+slane
+slank
+slaps
+slart
+slats
+slaty
+slaws
+slays
+slebs
+sleds
+sleer
+slews
+sleys
+slier
+slily
+slims
+slipe
+slips
+slipt
+slish
+slits
+slive
+sloan
+slobs
+sloes
+slogs
+sloid
+slojd
+slomo
+sloom
+sloot
+slops
+slopy
+slorm
+slots
+slove
+slows
+sloyd
+slubb
+slubs
+slued
+slues
+sluff
+slugs
+sluit
+slums
+slurb
+slurs
+sluse
+sluts
+slyer
+slype
+smaak
+smaik
+smalm
+smalt
+smarm
+smaze
+smeek
+smees
+smeik
+smeke
+smerk
+smews
+smirr
+smirs
+smits
+smogs
+smoko
+smolt
+smoor
+smoot
+smore
+smorg
+smout
+smowt
+smugs
+smurs
+smush
+smuts
+snabs
+snafu
+snags
+snaps
+snarf
+snark
+snars
+snary
+snash
+snath
+snaws
+snead
+sneap
+snebs
+sneck
+sneds
+sneed
+snees
+snell
+snibs
+snick
+snies
+snift
+snigs
+snips
+snipy
+snirt
+snits
+snobs
+snods
+snoek
+snoep
+snogs
+snoke
+snood
+snook
+snool
+snoot
+snots
+snowk
+snows
+snubs
+snugs
+snush
+snyes
+soaks
+soaps
+soare
+soars
+soave
+sobas
+socas
+soces
+socko
+socks
+socle
+sodas
+soddy
+sodic
+sodom
+sofar
+sofas
+softa
+softs
+softy
+soger
+sohur
+soils
+soily
+sojas
+sojus
+sokah
+soken
+sokes
+sokol
+solah
+solan
+solas
+solde
+soldi
+soldo
+solds
+soled
+solei
+soler
+soles
+solon
+solos
+solum
+solus
+soman
+somas
+sonce
+sonde
+sones
+songs
+sonly
+sonne
+sonny
+sonse
+sonsy
+sooey
+sooks
+sooky
+soole
+sools
+sooms
+soops
+soote
+soots
+sophs
+sophy
+sopor
+soppy
+sopra
+soral
+soras
+sorbo
+sorbs
+sorda
+sordo
+sords
+sored
+soree
+sorel
+sorer
+sores
+sorex
+sorgo
+sorns
+sorra
+sorta
+sorts
+sorus
+soths
+sotol
+souce
+souct
+sough
+souks
+souls
+soums
+soups
+soupy
+sours
+souse
+souts
+sowar
+sowce
+sowed
+sowff
+sowfs
+sowle
+sowls
+sowms
+sownd
+sowne
+sowps
+sowse
+sowth
+soyas
+soyle
+soyuz
+sozin
+spacy
+spado
+spaed
+spaer
+spaes
+spags
+spahi
+spail
+spain
+spait
+spake
+spald
+spale
+spall
+spalt
+spams
+spane
+spang
+spans
+spard
+spars
+spart
+spate
+spats
+spaul
+spawl
+spaws
+spayd
+spays
+spaza
+spazz
+speal
+spean
+speat
+specs
+spect
+speel
+speer
+speil
+speir
+speks
+speld
+spelk
+speos
+spets
+speug
+spews
+spewy
+spial
+spica
+spick
+spics
+spide
+spier
+spies
+spiff
+spifs
+spiks
+spile
+spims
+spina
+spink
+spins
+spirt
+spiry
+spits
+spitz
+spivs
+splay
+splog
+spode
+spods
+spoom
+spoor
+spoot
+spork
+sposh
+spots
+sprad
+sprag
+sprat
+spred
+sprew
+sprit
+sprod
+sprog
+sprue
+sprug
+spuds
+spued
+spuer
+spues
+spugs
+spule
+spume
+spumy
+spurs
+sputa
+spyal
+spyre
+squab
+squaw
+squeg
+squid
+squit
+squiz
+stabs
+stade
+stags
+stagy
+staig
+stane
+stang
+staph
+staps
+starn
+starr
+stars
+stats
+staun
+staws
+stays
+stean
+stear
+stedd
+stede
+steds
+steek
+steem
+steen
+steil
+stela
+stele
+stell
+steme
+stems
+stend
+steno
+stens
+stent
+steps
+stept
+stere
+stets
+stews
+stewy
+steys
+stich
+stied
+sties
+stilb
+stile
+stime
+stims
+stimy
+stipa
+stipe
+stire
+stirk
+stirp
+stirs
+stive
+stivy
+stoae
+stoai
+stoas
+stoat
+stobs
+stoep
+stogy
+stoit
+stoln
+stoma
+stond
+stong
+stonk
+stonn
+stook
+stoor
+stope
+stops
+stopt
+stoss
+stots
+stott
+stoun
+stoup
+stour
+stown
+stowp
+stows
+strad
+strae
+strag
+strak
+strep
+strew
+stria
+strig
+strim
+strop
+strow
+stroy
+strum
+stubs
+stude
+studs
+stull
+stulm
+stumm
+stums
+stuns
+stupa
+stupe
+sture
+sturt
+styed
+styes
+styli
+stylo
+styme
+stymy
+styre
+styte
+subah
+subas
+subby
+suber
+subha
+succi
+sucks
+sucky
+sucre
+sudds
+sudor
+sudsy
+suede
+suent
+suers
+suete
+suets
+suety
+sugan
+sughs
+sugos
+suhur
+suids
+suint
+suits
+sujee
+sukhs
+sukuk
+sulci
+sulfa
+sulfo
+sulks
+sulph
+sulus
+sumis
+summa
+sumos
+sumph
+sumps
+sunis
+sunks
+sunna
+sunns
+sunup
+supes
+supra
+surah
+sural
+suras
+surat
+surds
+sured
+sures
+surfs
+surfy
+surgy
+surra
+sused
+suses
+susus
+sutor
+sutra
+sutta
+swabs
+swack
+swads
+swage
+swags
+swail
+swain
+swale
+swaly
+swamy
+swang
+swank
+swans
+swaps
+swapt
+sward
+sware
+swarf
+swart
+swats
+swayl
+sways
+sweal
+swede
+sweed
+sweel
+sweer
+swees
+sweir
+swelt
+swerf
+sweys
+swies
+swigs
+swile
+swims
+swink
+swipe
+swire
+swiss
+swith
+swits
+swive
+swizz
+swobs
+swole
+swoln
+swops
+swopt
+swots
+swoun
+sybbe
+sybil
+syboe
+sybow
+sycee
+syces
+sycon
+syens
+syker
+sykes
+sylis
+sylph
+sylva
+symar
+synch
+syncs
+synds
+syned
+synes
+synth
+syped
+sypes
+syphs
+syrah
+syren
+sysop
+sythe
+syver
+taals
+taata
+taber
+tabes
+tabid
+tabis
+tabla
+tabor
+tabun
+tabus
+tacan
+taces
+tacet
+tache
+tacho
+tachs
+tacks
+tacos
+tacts
+taels
+tafia
+taggy
+tagma
+tahas
+tahrs
+taiga
+taigs
+taiko
+tails
+tains
+taira
+taish
+taits
+tajes
+takas
+takes
+takhi
+takin
+takis
+takky
+talak
+talaq
+talar
+talas
+talcs
+talcy
+talea
+taler
+tales
+talks
+talky
+talls
+talma
+talpa
+taluk
+talus
+tamal
+tamed
+tames
+tamin
+tamis
+tammy
+tamps
+tanas
+tanga
+tangi
+tangs
+tanhs
+tanka
+tanks
+tanky
+tanna
+tansy
+tanti
+tanto
+tanty
+tapas
+taped
+tapen
+tapes
+tapet
+tapis
+tappa
+tapus
+taras
+tardo
+tared
+tares
+targa
+targe
+tarns
+taroc
+tarok
+taros
+tarps
+tarre
+tarry
+tarsi
+tarts
+tarty
+tasar
+tased
+taser
+tases
+tasks
+tassa
+tasse
+tasso
+tatar
+tater
+tates
+taths
+tatie
+tatou
+tatts
+tatus
+taube
+tauld
+tauon
+taupe
+tauts
+tavah
+tavas
+taver
+tawai
+tawas
+tawed
+tawer
+tawie
+tawse
+tawts
+taxed
+taxer
+taxes
+taxis
+taxol
+taxon
+taxor
+taxus
+tayra
+tazza
+tazze
+teade
+teads
+teaed
+teaks
+teals
+teams
+tears
+teats
+teaze
+techs
+techy
+tecta
+teels
+teems
+teend
+teene
+teens
+teeny
+teers
+teffs
+teggs
+tegua
+tegus
+tehrs
+teiid
+teils
+teind
+teins
+telae
+telco
+teles
+telex
+telia
+telic
+tells
+telly
+teloi
+telos
+temed
+temes
+tempi
+temps
+tempt
+temse
+tench
+tends
+tendu
+tenes
+tenge
+tenia
+tenne
+tenno
+tenny
+tenon
+tents
+tenty
+tenue
+tepal
+tepas
+tepoy
+terai
+teras
+terce
+terek
+teres
+terfe
+terfs
+terga
+terms
+terne
+terns
+terry
+terts
+tesla
+testa
+teste
+tests
+tetes
+teths
+tetra
+tetri
+teuch
+teugh
+tewed
+tewel
+tewit
+texas
+texes
+texts
+thack
+thagi
+thaim
+thale
+thali
+thana
+thane
+thang
+thans
+thanx
+tharm
+thars
+thaws
+thawy
+thebe
+theca
+theed
+theek
+thees
+thegn
+theic
+thein
+thelf
+thema
+thens
+theow
+therm
+thesp
+thete
+thews
+thewy
+thigs
+thilk
+thill
+thine
+thins
+thiol
+thirl
+thoft
+thole
+tholi
+thoro
+thorp
+thous
+thowl
+thrae
+thraw
+thrid
+thrip
+throe
+thuds
+thugs
+thuja
+thunk
+thurl
+thuya
+thymi
+thymy
+tians
+tiars
+tical
+ticca
+ticed
+tices
+tichy
+ticks
+ticky
+tiddy
+tided
+tides
+tiers
+tiffs
+tifos
+tifts
+tiges
+tigon
+tikas
+tikes
+tikis
+tikka
+tilak
+tiled
+tiler
+tiles
+tills
+tilly
+tilth
+tilts
+timbo
+timed
+times
+timon
+timps
+tinas
+tinct
+tinds
+tinea
+tined
+tines
+tinge
+tings
+tinks
+tinny
+tints
+tinty
+tipis
+tippy
+tired
+tires
+tirls
+tiros
+tirrs
+titch
+titer
+titis
+titre
+titty
+titup
+tiyin
+tiyns
+tizes
+tizzy
+toads
+toady
+toaze
+tocks
+tocky
+tocos
+todde
+toeas
+toffs
+toffy
+tofts
+tofus
+togae
+togas
+toged
+toges
+togue
+tohos
+toile
+toils
+toing
+toise
+toits
+tokay
+toked
+toker
+tokes
+tokos
+tolan
+tolar
+tolas
+toled
+toles
+tolls
+tolly
+tolts
+tolus
+tolyl
+toman
+tombs
+tomes
+tomia
+tommy
+tomos
+tondi
+tondo
+toned
+toner
+tones
+toney
+tongs
+tonka
+tonks
+tonne
+tonus
+tools
+tooms
+toons
+toots
+toped
+topee
+topek
+toper
+topes
+tophe
+tophi
+tophs
+topis
+topoi
+topos
+toppy
+toque
+torah
+toran
+toras
+torcs
+tores
+toric
+torii
+toros
+torot
+torrs
+torse
+torsi
+torsk
+torta
+torte
+torts
+tosas
+tosed
+toses
+toshy
+tossy
+toted
+toter
+totes
+totty
+touks
+touns
+tours
+touse
+tousy
+touts
+touze
+touzy
+towed
+towie
+towns
+towny
+towse
+towsy
+towts
+towze
+towzy
+toyed
+toyer
+toyon
+toyos
+tozed
+tozes
+tozie
+trabs
+trads
+tragi
+traik
+trams
+trank
+tranq
+trans
+trant
+trape
+traps
+trapt
+trass
+trats
+tratt
+trave
+trayf
+trays
+treck
+treed
+treen
+trees
+trefa
+treif
+treks
+trema
+trems
+tress
+trest
+trets
+trews
+treyf
+treys
+triac
+tride
+trier
+tries
+triff
+trigo
+trigs
+trike
+trild
+trill
+trims
+trine
+trins
+triol
+trior
+trios
+trips
+tripy
+trist
+troad
+troak
+troat
+trock
+trode
+trods
+trogs
+trois
+troke
+tromp
+trona
+tronc
+trone
+tronk
+trons
+trooz
+troth
+trots
+trows
+troys
+trued
+trues
+trugo
+trugs
+trull
+tryer
+tryke
+tryma
+tryps
+tsade
+tsadi
+tsars
+tsked
+tsuba
+tsubo
+tuans
+tuart
+tuath
+tubae
+tubar
+tubas
+tubby
+tubed
+tubes
+tucks
+tufas
+tuffe
+tuffs
+tufts
+tufty
+tugra
+tuile
+tuina
+tuism
+tuktu
+tules
+tulpa
+tulsi
+tumid
+tummy
+tumps
+tumpy
+tunas
+tunds
+tuned
+tuner
+tunes
+tungs
+tunny
+tupek
+tupik
+tuple
+tuque
+turds
+turfs
+turfy
+turks
+turme
+turms
+turns
+turnt
+turps
+turrs
+tushy
+tusks
+tusky
+tutee
+tutti
+tutty
+tutus
+tuxes
+tuyer
+twaes
+twain
+twals
+twank
+twats
+tways
+tweel
+tween
+tweep
+tweer
+twerk
+twerp
+twier
+twigs
+twill
+twilt
+twink
+twins
+twiny
+twire
+twirp
+twite
+twits
+twoer
+twyer
+tyees
+tyers
+tyiyn
+tykes
+tyler
+tymps
+tynde
+tyned
+tynes
+typal
+typed
+types
+typey
+typic
+typos
+typps
+typto
+tyran
+tyred
+tyres
+tyros
+tythe
+tzars
+udals
+udons
+ugali
+ugged
+uhlan
+uhuru
+ukase
+ulama
+ulans
+ulema
+ulmin
+ulnad
+ulnae
+ulnar
+ulnas
+ulpan
+ulvas
+ulyie
+ulzie
+umami
+umbel
+umber
+umble
+umbos
+umbre
+umiac
+umiak
+umiaq
+ummah
+ummas
+ummed
+umped
+umphs
+umpie
+umpty
+umrah
+umras
+unais
+unapt
+unarm
+unary
+unaus
+unbag
+unban
+unbar
+unbed
+unbid
+unbox
+uncap
+unces
+uncia
+uncos
+uncoy
+uncus
+undam
+undee
+undos
+undug
+uneth
+unfix
+ungag
+unget
+ungod
+ungot
+ungum
+unhat
+unhip
+unica
+units
+unjam
+unked
+unket
+unkid
+unlaw
+unlay
+unled
+unlet
+unlid
+unman
+unmew
+unmix
+unpay
+unpeg
+unpen
+unpin
+unred
+unrid
+unrig
+unrip
+unsaw
+unsay
+unsee
+unsew
+unsex
+unsod
+untax
+untin
+unwet
+unwit
+unwon
+upbow
+upbye
+updos
+updry
+upend
+upjet
+uplay
+upled
+uplit
+upped
+upran
+uprun
+upsee
+upsey
+uptak
+upter
+uptie
+uraei
+urali
+uraos
+urare
+urari
+urase
+urate
+urbex
+urbia
+urdee
+ureal
+ureas
+uredo
+ureic
+urena
+urent
+urged
+urger
+urges
+urial
+urite
+urman
+urnal
+urned
+urped
+ursae
+ursid
+urson
+urubu
+urvas
+users
+usnea
+usque
+usure
+usury
+uteri
+uveal
+uveas
+uvula
+vacua
+vaded
+vades
+vagal
+vagus
+vails
+vaire
+vairs
+vairy
+vakas
+vakil
+vales
+valis
+valse
+vamps
+vampy
+vanda
+vaned
+vanes
+vangs
+vants
+vaped
+vaper
+vapes
+varan
+varas
+vardy
+varec
+vares
+varia
+varix
+varna
+varus
+varve
+vasal
+vases
+vasts
+vasty
+vatic
+vatus
+vauch
+vaute
+vauts
+vawte
+vaxes
+veale
+veals
+vealy
+veena
+veeps
+veers
+veery
+vegas
+veges
+vegie
+vegos
+vehme
+veils
+veily
+veins
+veiny
+velar
+velds
+veldt
+veles
+vells
+velum
+venae
+venal
+vends
+vendu
+veney
+venge
+venin
+vents
+venus
+verbs
+verra
+verry
+verst
+verts
+vertu
+vespa
+vesta
+vests
+vetch
+vexed
+vexer
+vexes
+vexil
+vezir
+vials
+viand
+vibes
+vibex
+vibey
+viced
+vices
+vichy
+viers
+views
+viewy
+vifda
+viffs
+vigas
+vigia
+vilde
+viler
+villi
+vills
+vimen
+vinal
+vinas
+vinca
+vined
+viner
+vines
+vinew
+vinic
+vinos
+vints
+viold
+viols
+vired
+vireo
+vires
+virga
+virge
+virid
+virls
+virtu
+visas
+vised
+vises
+visie
+visne
+vison
+visto
+vitae
+vitas
+vitex
+vitro
+vitta
+vivas
+vivat
+vivda
+viver
+vives
+vizir
+vizor
+vleis
+vlies
+vlogs
+voars
+vocab
+voces
+voddy
+vodou
+vodun
+voema
+vogie
+voids
+voile
+voips
+volae
+volar
+voled
+voles
+volet
+volks
+volta
+volte
+volti
+volts
+volva
+volve
+vomer
+voted
+votes
+vouge
+voulu
+vowed
+vower
+voxel
+vozhd
+vraic
+vrils
+vroom
+vrous
+vrouw
+vrows
+vuggs
+vuggy
+vughs
+vughy
+vulgo
+vulns
+vulva
+vutty
+waacs
+wacke
+wacko
+wacks
+wadds
+waddy
+waded
+wader
+wades
+wadge
+wadis
+wadts
+waffs
+wafts
+waged
+wages
+wagga
+wagyu
+wahoo
+waide
+waifs
+waift
+wails
+wains
+wairs
+waite
+waits
+wakas
+waked
+waken
+waker
+wakes
+wakfs
+waldo
+walds
+waled
+waler
+wales
+walie
+walis
+walks
+walla
+walls
+wally
+walty
+wamed
+wames
+wamus
+wands
+waned
+wanes
+waney
+wangs
+wanks
+wanky
+wanle
+wanly
+wanna
+wants
+wanty
+wanze
+waqfs
+warbs
+warby
+wards
+wared
+wares
+warez
+warks
+warms
+warns
+warps
+warre
+warst
+warts
+wases
+washy
+wasms
+wasps
+waspy
+wasts
+watap
+watts
+wauff
+waugh
+wauks
+waulk
+wauls
+waurs
+waved
+waves
+wavey
+wawas
+wawes
+wawls
+waxed
+waxer
+waxes
+wayed
+wazir
+wazoo
+weald
+weals
+weamb
+weans
+wears
+webby
+weber
+wecht
+wedel
+wedgy
+weeds
+weeke
+weeks
+weels
+weems
+weens
+weeny
+weeps
+weepy
+weest
+weete
+weets
+wefte
+wefts
+weids
+weils
+weirs
+weise
+weize
+wekas
+welds
+welke
+welks
+welkt
+wells
+welly
+welts
+wembs
+wends
+wenge
+wenny
+wents
+weros
+wersh
+wests
+wetas
+wetly
+wexed
+wexes
+whamo
+whams
+whang
+whaps
+whare
+whata
+whats
+whaup
+whaur
+wheal
+whear
+wheen
+wheep
+wheft
+whelk
+whelm
+whens
+whets
+whews
+wheys
+whids
+whift
+whigs
+whilk
+whims
+whins
+whios
+whips
+whipt
+whirr
+whirs
+whish
+whiss
+whist
+whits
+whity
+whizz
+whomp
+whoof
+whoot
+whops
+whore
+whorl
+whort
+whoso
+whows
+whump
+whups
+whyda
+wicca
+wicks
+wicky
+widdy
+wides
+wiels
+wifed
+wifes
+wifey
+wifie
+wifty
+wigan
+wigga
+wiggy
+wikis
+wilco
+wilds
+wiled
+wiles
+wilga
+wilis
+wilja
+wills
+wilts
+wimps
+winds
+wined
+wines
+winey
+winge
+wings
+wingy
+winks
+winna
+winns
+winos
+winze
+wiped
+wiper
+wipes
+wired
+wirer
+wires
+wirra
+wised
+wises
+wisha
+wisht
+wisps
+wists
+witan
+wited
+wites
+withe
+withs
+withy
+wived
+wiver
+wives
+wizen
+wizes
+woads
+woald
+wocks
+wodge
+woful
+wojus
+woker
+wokka
+wolds
+wolfs
+wolly
+wolve
+wombs
+womby
+womyn
+wonga
+wongi
+wonks
+wonky
+wonts
+woods
+wooed
+woofs
+woofy
+woold
+wools
+woons
+woops
+woopy
+woose
+woosh
+wootz
+words
+works
+worms
+wormy
+worts
+wowed
+wowee
+woxen
+wrang
+wraps
+wrapt
+wrast
+wrate
+wrawl
+wrens
+wrick
+wried
+wrier
+wries
+writs
+wroke
+wroot
+wroth
+wryer
+wuddy
+wudus
+wulls
+wurst
+wuses
+wushu
+wussy
+wuxia
+wyled
+wyles
+wynds
+wynns
+wyted
+wytes
+xebec
+xenia
+xenic
+xenon
+xeric
+xerox
+xerus
+xoana
+xrays
+xylan
+xylem
+xylic
+xylol
+xylyl
+xysti
+xysts
+yaars
+yabas
+yabba
+yabby
+yacca
+yacka
+yacks
+yaffs
+yager
+yages
+yagis
+yahoo
+yaird
+yakka
+yakow
+yales
+yamen
+yampy
+yamun
+yangs
+yanks
+yapok
+yapon
+yapps
+yappy
+yarak
+yarco
+yards
+yarer
+yarfa
+yarks
+yarns
+yarrs
+yarta
+yarto
+yates
+yauds
+yauld
+yaups
+yawed
+yawey
+yawls
+yawns
+yawny
+yawps
+ybore
+yclad
+ycled
+ycond
+ydrad
+ydred
+yeads
+yeahs
+yealm
+yeans
+yeard
+years
+yecch
+yechs
+yechy
+yedes
+yeeds
+yeesh
+yeggs
+yelks
+yells
+yelms
+yelps
+yelts
+yenta
+yente
+yerba
+yerds
+yerks
+yeses
+yesks
+yests
+yesty
+yetis
+yetts
+yeuks
+yeuky
+yeven
+yeves
+yewen
+yexed
+yexes
+yfere
+yiked
+yikes
+yills
+yince
+yipes
+yippy
+yirds
+yirks
+yirrs
+yirth
+yites
+yitie
+ylems
+ylike
+ylkes
+ymolt
+ympes
+yobbo
+yobby
+yocks
+yodel
+yodhs
+yodle
+yogas
+yogee
+yoghs
+yogic
+yogin
+yogis
+yoick
+yojan
+yoked
+yokel
+yoker
+yokes
+yokul
+yolks
+yolky
+yomim
+yomps
+yonic
+yonis
+yonks
+yoofs
+yoops
+yores
+yorks
+yorps
+youks
+yourn
+yours
+yourt
+youse
+yowed
+yowes
+yowie
+yowls
+yowza
+yrapt
+yrent
+yrivd
+yrneh
+ysame
+ytost
+yuans
+yucas
+yucca
+yucch
+yucko
+yucks
+yucky
+yufts
+yugas
+yuked
+yukes
+yukky
+yukos
+yulan
+yules
+yummo
+yummy
+yumps
+yupon
+yuppy
+yurta
+yurts
+yuzus
+zabra
+zacks
+zaida
+zaidy
+zaire
+zakat
+zaman
+zambo
+zamia
+zanja
+zante
+zanza
+zanze
+zappy
+zarfs
+zaris
+zatis
+zaxes
+zayin
+zazen
+zeals
+zebec
+zebub
+zebus
+zedas
+zeins
+zendo
+zerda
+zerks
+zeros
+zests
+zetas
+zexes
+zezes
+zhomo
+zibet
+ziffs
+zigan
+zilas
+zilch
+zilla
+zills
+zimbi
+zimbs
+zinco
+zincs
+zincy
+zineb
+zines
+zings
+zingy
+zinke
+zinky
+zippo
+zippy
+ziram
+zitis
+zizel
+zizit
+zlote
+zloty
+zoaea
+zobos
+zobus
+zocco
+zoeae
+zoeal
+zoeas
+zoism
+zoist
+zombi
+zonae
+zonda
+zoned
+zoner
+zones
+zonks
+zooea
+zooey
+zooid
+zooks
+zooms
+zoons
+zooty
+zoppa
+zoppo
+zoril
+zoris
+zorro
+zouks
+zowee
+zowie
+zulus
+zupan
+zupas
+zuppa
+zurfs
+zuzim
+zygal
+zygon
+zymes
+zymic
\ No newline at end of file
diff --git a/web/samples/WordWiz/src/assets/allowedWords.ts b/web/samples/WordWiz/src/assets/allowedWords.ts
new file mode 100644
index 0000000000..dc074ea1fd
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/allowedWords.ts
@@ -0,0 +1,12 @@
+// Convert allowed.txt into an array of words for use across the app
+// The file is imported as raw text via Vite's ?raw import.
+import allowedRaw from '@app/assets/allowed.txt?raw';
+
+// Normalize: trim, filter empty, and lowercase (dictionary is case-insensitive)
+export const allowedWords: string[] = allowedRaw
+ .split(/\r?\n/)
+ .map((line) => line.trim())
+ .filter((line) => line.length > 0)
+ .map((line) => line.toLowerCase());
+
+export default allowedWords;
diff --git a/web/samples/WordWiz/src/assets/answers.ts b/web/samples/WordWiz/src/assets/answers.ts
new file mode 100644
index 0000000000..c52c91e1a6
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/answers.ts
@@ -0,0 +1,12 @@
+// Convert answers.txt into an array of words for use across the app
+// The file is imported as raw text via Vite's ?raw import.
+import answersRaw from '@app/assets/answers.txt?raw';
+
+// Normalize: trim, filter empty, and lowercase (dictionary is case-insensitive)
+export const answers: string[] = answersRaw
+ .split(/\r?\n/)
+ .map((line) => line.trim())
+ .filter((line) => line.length > 0)
+ .map((line) => line.toLowerCase());
+
+export default answers;
diff --git a/web/samples/WordWiz/src/assets/answers.txt b/web/samples/WordWiz/src/assets/answers.txt
new file mode 100644
index 0000000000..50838083dc
--- /dev/null
+++ b/web/samples/WordWiz/src/assets/answers.txt
@@ -0,0 +1,2315 @@
+aback
+abase
+abate
+abbey
+abbot
+abhor
+abide
+abled
+abode
+abort
+about
+above
+abuse
+abyss
+acorn
+acrid
+actor
+acute
+adage
+adapt
+adept
+admin
+admit
+adobe
+adopt
+adore
+adorn
+adult
+affix
+afire
+afoot
+afoul
+after
+again
+agape
+agate
+agent
+agile
+aging
+aglow
+agony
+agora
+agree
+ahead
+aider
+aisle
+alarm
+album
+alert
+algae
+alibi
+alien
+align
+alike
+alive
+allay
+alley
+allot
+allow
+alloy
+aloft
+alone
+along
+aloof
+aloud
+alpha
+altar
+alter
+amass
+amaze
+amber
+amble
+amend
+amiss
+amity
+among
+ample
+amply
+amuse
+angel
+anger
+angle
+angry
+angst
+anime
+ankle
+annex
+annoy
+annul
+anode
+antic
+anvil
+aorta
+apart
+aphid
+aping
+apnea
+apple
+apply
+apron
+aptly
+arbor
+ardor
+arena
+argue
+arise
+armor
+aroma
+arose
+array
+arrow
+arson
+artsy
+ascot
+ashen
+aside
+askew
+assay
+asset
+atoll
+atone
+attic
+audio
+audit
+augur
+aunty
+avail
+avert
+avian
+avoid
+await
+awake
+award
+aware
+awash
+awful
+awoke
+axial
+axiom
+axion
+azure
+bacon
+badge
+badly
+bagel
+baggy
+baker
+baler
+balmy
+banal
+banjo
+barge
+baron
+basal
+basic
+basil
+basin
+basis
+baste
+batch
+bathe
+baton
+batty
+bawdy
+bayou
+beach
+beady
+beard
+beast
+beech
+beefy
+befit
+began
+begat
+beget
+begin
+begun
+being
+belch
+belie
+belle
+belly
+below
+bench
+beret
+berry
+berth
+beset
+betel
+bevel
+bezel
+bible
+bicep
+biddy
+bigot
+bilge
+billy
+binge
+bingo
+biome
+birch
+birth
+bison
+bitty
+black
+blade
+blame
+bland
+blank
+blare
+blast
+blaze
+bleak
+bleat
+bleed
+bleep
+blend
+bless
+blimp
+blind
+blink
+bliss
+blitz
+bloat
+block
+bloke
+blond
+blood
+bloom
+blown
+bluer
+bluff
+blunt
+blurb
+blurt
+blush
+board
+boast
+bobby
+boney
+bongo
+bonus
+booby
+boost
+booth
+booty
+booze
+boozy
+borax
+borne
+bosom
+bossy
+botch
+bough
+boule
+bound
+bowel
+boxer
+brace
+braid
+brain
+brake
+brand
+brash
+brass
+brave
+bravo
+brawl
+brawn
+bread
+break
+breed
+briar
+bribe
+brick
+bride
+brief
+brine
+bring
+brink
+briny
+brisk
+broad
+broil
+broke
+brood
+brook
+broom
+broth
+brown
+brunt
+brush
+brute
+buddy
+budge
+buggy
+bugle
+build
+built
+bulge
+bulky
+bully
+bunch
+bunny
+burly
+burnt
+burst
+bused
+bushy
+butch
+butte
+buxom
+buyer
+bylaw
+cabal
+cabby
+cabin
+cable
+cacao
+cache
+cacti
+caddy
+cadet
+cagey
+cairn
+camel
+cameo
+canal
+candy
+canny
+canoe
+canon
+caper
+caput
+carat
+cargo
+carol
+carry
+carve
+caste
+catch
+cater
+catty
+caulk
+cause
+cavil
+cease
+cedar
+cello
+chafe
+chaff
+chain
+chair
+chalk
+champ
+chant
+chaos
+chard
+charm
+chart
+chase
+chasm
+cheap
+cheat
+check
+cheek
+cheer
+chess
+chest
+chick
+chide
+chief
+child
+chili
+chill
+chime
+china
+chirp
+chock
+choir
+choke
+chord
+chore
+chose
+chuck
+chump
+chunk
+churn
+chute
+cider
+cigar
+cinch
+circa
+civic
+civil
+clack
+claim
+clamp
+clang
+clank
+clash
+clasp
+class
+clean
+clear
+cleat
+cleft
+clerk
+click
+cliff
+climb
+cling
+clink
+cloak
+clock
+clone
+close
+cloth
+cloud
+clout
+clove
+clown
+cluck
+clued
+clump
+clung
+coach
+coast
+cobra
+cocoa
+colon
+color
+comet
+comfy
+comic
+comma
+conch
+condo
+conic
+copse
+coral
+corer
+corny
+couch
+cough
+could
+count
+coupe
+court
+coven
+cover
+covet
+covey
+cower
+coyly
+crack
+craft
+cramp
+crane
+crank
+crash
+crass
+crate
+crave
+crawl
+craze
+crazy
+creak
+cream
+credo
+creed
+creek
+creep
+creme
+crepe
+crept
+cress
+crest
+crick
+cried
+crier
+crime
+crimp
+crisp
+croak
+crock
+crone
+crony
+crook
+cross
+croup
+crowd
+crown
+crude
+cruel
+crumb
+crump
+crush
+crust
+crypt
+cubic
+cumin
+curio
+curly
+curry
+curse
+curve
+curvy
+cutie
+cyber
+cycle
+cynic
+daddy
+daily
+dairy
+daisy
+dally
+dance
+dandy
+datum
+daunt
+dealt
+death
+debar
+debit
+debug
+debut
+decal
+decay
+decor
+decoy
+decry
+defer
+deign
+deity
+delay
+delta
+delve
+demon
+demur
+denim
+dense
+depot
+depth
+derby
+deter
+detox
+deuce
+devil
+diary
+dicey
+digit
+dilly
+dimly
+diner
+dingo
+dingy
+diode
+dirge
+dirty
+disco
+ditch
+ditto
+ditty
+diver
+dizzy
+dodge
+dodgy
+dogma
+doing
+dolly
+donor
+donut
+dopey
+doubt
+dough
+dowdy
+dowel
+downy
+dowry
+dozen
+draft
+drain
+drake
+drama
+drank
+drape
+drawl
+drawn
+dread
+dream
+dress
+dried
+drier
+drift
+drill
+drink
+drive
+droit
+droll
+drone
+drool
+droop
+dross
+drove
+drown
+druid
+drunk
+dryer
+dryly
+duchy
+dully
+dummy
+dumpy
+dunce
+dusky
+dusty
+dutch
+duvet
+dwarf
+dwell
+dwelt
+dying
+eager
+eagle
+early
+earth
+easel
+eaten
+eater
+ebony
+eclat
+edict
+edify
+eerie
+egret
+eight
+eject
+eking
+elate
+elbow
+elder
+elect
+elegy
+elfin
+elide
+elite
+elope
+elude
+email
+embed
+ember
+emcee
+empty
+enact
+endow
+enema
+enemy
+enjoy
+ennui
+ensue
+enter
+entry
+envoy
+epoch
+epoxy
+equal
+equip
+erase
+erect
+erode
+error
+erupt
+essay
+ester
+ether
+ethic
+ethos
+etude
+evade
+event
+every
+evict
+evoke
+exact
+exalt
+excel
+exert
+exile
+exist
+expel
+extol
+extra
+exult
+eying
+fable
+facet
+faint
+fairy
+faith
+false
+fancy
+fanny
+farce
+fatal
+fatty
+fault
+fauna
+favor
+feast
+fecal
+feign
+fella
+felon
+femme
+femur
+fence
+feral
+ferry
+fetal
+fetch
+fetid
+fetus
+fever
+fewer
+fiber
+fibre
+ficus
+field
+fiend
+fiery
+fifth
+fifty
+fight
+filer
+filet
+filly
+filmy
+filth
+final
+finch
+finer
+first
+fishy
+fixer
+fizzy
+fjord
+flack
+flail
+flair
+flake
+flaky
+flame
+flank
+flare
+flash
+flask
+fleck
+fleet
+flesh
+flick
+flier
+fling
+flint
+flirt
+float
+flock
+flood
+floor
+flora
+floss
+flour
+flout
+flown
+fluff
+fluid
+fluke
+flume
+flung
+flunk
+flush
+flute
+flyer
+foamy
+focal
+focus
+foggy
+foist
+folio
+folly
+foray
+force
+forge
+forgo
+forte
+forth
+forty
+forum
+found
+foyer
+frail
+frame
+frank
+fraud
+freak
+freed
+freer
+fresh
+friar
+fried
+frill
+frisk
+fritz
+frock
+frond
+front
+frost
+froth
+frown
+froze
+fruit
+fudge
+fugue
+fully
+fungi
+funky
+funny
+furor
+furry
+fussy
+fuzzy
+gaffe
+gaily
+gamer
+gamma
+gamut
+gassy
+gaudy
+gauge
+gaunt
+gauze
+gavel
+gawky
+gayer
+gayly
+gazer
+gecko
+geeky
+geese
+genie
+genre
+ghost
+ghoul
+giant
+giddy
+gipsy
+girly
+girth
+given
+giver
+glade
+gland
+glare
+glass
+glaze
+gleam
+glean
+glide
+glint
+gloat
+globe
+gloom
+glory
+gloss
+glove
+glyph
+gnash
+gnome
+godly
+going
+golem
+golly
+gonad
+goner
+goody
+gooey
+goofy
+goose
+gorge
+gouge
+gourd
+grace
+grade
+graft
+grail
+grain
+grand
+grant
+grape
+graph
+grasp
+grass
+grate
+grave
+gravy
+graze
+great
+greed
+green
+greet
+grief
+grill
+grime
+grimy
+grind
+gripe
+groan
+groin
+groom
+grope
+gross
+group
+grout
+grove
+growl
+grown
+gruel
+gruff
+grunt
+guard
+guava
+guess
+guest
+guide
+guild
+guile
+guilt
+guise
+gulch
+gully
+gumbo
+gummy
+guppy
+gusto
+gusty
+gypsy
+habit
+hairy
+halve
+handy
+happy
+hardy
+harem
+harpy
+harry
+harsh
+haste
+hasty
+hatch
+hater
+haunt
+haute
+haven
+havoc
+hazel
+heady
+heard
+heart
+heath
+heave
+heavy
+hedge
+hefty
+heist
+helix
+hello
+hence
+heron
+hilly
+hinge
+hippo
+hippy
+hitch
+hoard
+hobby
+hoist
+holly
+homer
+honey
+honor
+horde
+horny
+horse
+hotel
+hotly
+hound
+house
+hovel
+hover
+howdy
+human
+humid
+humor
+humph
+humus
+hunch
+hunky
+hurry
+husky
+hussy
+hutch
+hydro
+hyena
+hymen
+hyper
+icily
+icing
+ideal
+idiom
+idiot
+idler
+idyll
+igloo
+iliac
+image
+imbue
+impel
+imply
+inane
+inbox
+incur
+index
+inept
+inert
+infer
+ingot
+inlay
+inlet
+inner
+input
+inter
+intro
+ionic
+irate
+irony
+islet
+issue
+itchy
+ivory
+jaunt
+jazzy
+jelly
+jerky
+jetty
+jewel
+jiffy
+joint
+joist
+joker
+jolly
+joust
+judge
+juice
+juicy
+jumbo
+jumpy
+junta
+junto
+juror
+kappa
+karma
+kayak
+kebab
+khaki
+kinky
+kiosk
+kitty
+knack
+knave
+knead
+kneed
+kneel
+knelt
+knife
+knock
+knoll
+known
+koala
+krill
+label
+labor
+laden
+ladle
+lager
+lance
+lanky
+lapel
+lapse
+large
+larva
+lasso
+latch
+later
+lathe
+latte
+laugh
+layer
+leach
+leafy
+leaky
+leant
+leapt
+learn
+lease
+leash
+least
+leave
+ledge
+leech
+leery
+lefty
+legal
+leggy
+lemon
+lemur
+leper
+level
+lever
+libel
+liege
+light
+liken
+lilac
+limbo
+limit
+linen
+liner
+lingo
+lipid
+lithe
+liver
+livid
+llama
+loamy
+loath
+lobby
+local
+locus
+lodge
+lofty
+logic
+login
+loopy
+loose
+lorry
+loser
+louse
+lousy
+lover
+lower
+lowly
+loyal
+lucid
+lucky
+lumen
+lumpy
+lunar
+lunch
+lunge
+lupus
+lurch
+lurid
+lusty
+lying
+lymph
+lynch
+lyric
+macaw
+macho
+macro
+madam
+madly
+mafia
+magic
+magma
+maize
+major
+maker
+mambo
+mamma
+mammy
+manga
+mange
+mango
+mangy
+mania
+manic
+manly
+manor
+maple
+march
+marry
+marsh
+mason
+masse
+match
+matey
+mauve
+maxim
+maybe
+mayor
+mealy
+meant
+meaty
+mecca
+medal
+media
+medic
+melee
+melon
+mercy
+merge
+merit
+merry
+metal
+meter
+metro
+micro
+midge
+midst
+might
+milky
+mimic
+mince
+miner
+minim
+minor
+minty
+minus
+mirth
+miser
+missy
+mocha
+modal
+model
+modem
+mogul
+moist
+molar
+moldy
+money
+month
+moody
+moose
+moral
+moron
+morph
+mossy
+motel
+motif
+motor
+motto
+moult
+mound
+mount
+mourn
+mouse
+mouth
+mover
+movie
+mower
+mucky
+mucus
+muddy
+mulch
+mummy
+munch
+mural
+murky
+mushy
+music
+musky
+musty
+myrrh
+nadir
+naive
+nanny
+nasal
+nasty
+natal
+naval
+navel
+needy
+neigh
+nerdy
+nerve
+never
+newer
+newly
+nicer
+niche
+niece
+night
+ninja
+ninny
+ninth
+noble
+nobly
+noise
+noisy
+nomad
+noose
+north
+nosey
+notch
+novel
+nudge
+nurse
+nutty
+nylon
+nymph
+oaken
+obese
+occur
+ocean
+octal
+octet
+odder
+oddly
+offal
+offer
+often
+olden
+older
+olive
+ombre
+omega
+onion
+onset
+opera
+opine
+opium
+optic
+orbit
+order
+organ
+other
+otter
+ought
+ounce
+outdo
+outer
+outgo
+ovary
+ovate
+overt
+ovine
+ovoid
+owing
+owner
+oxide
+ozone
+paddy
+pagan
+paint
+paler
+palsy
+panel
+panic
+pansy
+papal
+paper
+parer
+parka
+parry
+parse
+party
+pasta
+paste
+pasty
+patch
+patio
+patsy
+patty
+pause
+payee
+payer
+peace
+peach
+pearl
+pecan
+pedal
+penal
+pence
+penne
+penny
+perch
+peril
+perky
+pesky
+pesto
+petal
+petty
+phase
+phone
+phony
+photo
+piano
+picky
+piece
+piety
+piggy
+pilot
+pinch
+piney
+pinky
+pinto
+piper
+pique
+pitch
+pithy
+pivot
+pixel
+pixie
+pizza
+place
+plaid
+plain
+plait
+plane
+plank
+plant
+plate
+plaza
+plead
+pleat
+plied
+plier
+pluck
+plumb
+plume
+plump
+plunk
+plush
+poesy
+point
+poise
+poker
+polar
+polka
+polyp
+pooch
+poppy
+porch
+poser
+posit
+posse
+pouch
+pound
+pouty
+power
+prank
+prawn
+preen
+press
+price
+prick
+pride
+pried
+prime
+primo
+print
+prior
+prism
+privy
+prize
+probe
+prone
+prong
+proof
+prose
+proud
+prove
+prowl
+proxy
+prude
+prune
+psalm
+pubic
+pudgy
+puffy
+pulpy
+pulse
+punch
+pupal
+pupil
+puppy
+puree
+purer
+purge
+purse
+pushy
+putty
+pygmy
+quack
+quail
+quake
+qualm
+quark
+quart
+quash
+quasi
+queen
+queer
+quell
+query
+quest
+queue
+quick
+quiet
+quill
+quilt
+quirk
+quite
+quota
+quote
+quoth
+rabbi
+rabid
+racer
+radar
+radii
+radio
+rainy
+raise
+rajah
+rally
+ralph
+ramen
+ranch
+randy
+range
+rapid
+rarer
+raspy
+ratio
+ratty
+raven
+rayon
+razor
+reach
+react
+ready
+realm
+rearm
+rebar
+rebel
+rebus
+rebut
+recap
+recur
+recut
+reedy
+refer
+refit
+regal
+rehab
+reign
+relax
+relay
+relic
+remit
+renal
+renew
+repay
+repel
+reply
+rerun
+reset
+resin
+retch
+retro
+retry
+reuse
+revel
+revue
+rhino
+rhyme
+rider
+ridge
+rifle
+right
+rigid
+rigor
+rinse
+ripen
+riper
+risen
+riser
+risky
+rival
+river
+rivet
+roach
+roast
+robin
+robot
+rocky
+rodeo
+roger
+rogue
+roomy
+roost
+rotor
+rouge
+rough
+round
+rouse
+route
+rover
+rowdy
+rower
+royal
+ruddy
+ruder
+rugby
+ruler
+rumba
+rumor
+rupee
+rural
+rusty
+sadly
+safer
+saint
+salad
+sally
+salon
+salsa
+salty
+salve
+salvo
+sandy
+saner
+sappy
+sassy
+satin
+satyr
+sauce
+saucy
+sauna
+saute
+savor
+savoy
+savvy
+scald
+scale
+scalp
+scaly
+scamp
+scant
+scare
+scarf
+scary
+scene
+scent
+scion
+scoff
+scold
+scone
+scoop
+scope
+score
+scorn
+scour
+scout
+scowl
+scram
+scrap
+scree
+screw
+scrub
+scrum
+scuba
+sedan
+seedy
+segue
+seize
+semen
+sense
+sepia
+serif
+serum
+serve
+setup
+seven
+sever
+sewer
+shack
+shade
+shady
+shaft
+shake
+shaky
+shale
+shall
+shalt
+shame
+shank
+shape
+shard
+share
+shark
+sharp
+shave
+shawl
+shear
+sheen
+sheep
+sheer
+sheet
+sheik
+shelf
+shell
+shied
+shift
+shine
+shiny
+shire
+shirk
+shirt
+shoal
+shock
+shone
+shook
+shoot
+shore
+shorn
+short
+shout
+shove
+shown
+showy
+shrew
+shrub
+shrug
+shuck
+shunt
+shush
+shyly
+siege
+sieve
+sight
+sigma
+silky
+silly
+since
+sinew
+singe
+siren
+sissy
+sixth
+sixty
+skate
+skier
+skiff
+skill
+skimp
+skirt
+skulk
+skull
+skunk
+slack
+slain
+slang
+slant
+slash
+slate
+slave
+sleek
+sleep
+sleet
+slept
+slice
+slick
+slide
+slime
+slimy
+sling
+slink
+sloop
+slope
+slosh
+sloth
+slump
+slung
+slunk
+slurp
+slush
+slyly
+smack
+small
+smart
+smash
+smear
+smell
+smelt
+smile
+smirk
+smite
+smith
+smock
+smoke
+smoky
+smote
+snack
+snail
+snake
+snaky
+snare
+snarl
+sneak
+sneer
+snide
+sniff
+snipe
+snoop
+snore
+snort
+snout
+snowy
+snuck
+snuff
+soapy
+sober
+soggy
+solar
+solid
+solve
+sonar
+sonic
+sooth
+sooty
+sorry
+sound
+south
+sower
+space
+spade
+spank
+spare
+spark
+spasm
+spawn
+speak
+spear
+speck
+speed
+spell
+spelt
+spend
+spent
+sperm
+spice
+spicy
+spied
+spiel
+spike
+spiky
+spill
+spilt
+spine
+spiny
+spire
+spite
+splat
+split
+spoil
+spoke
+spoof
+spook
+spool
+spoon
+spore
+sport
+spout
+spray
+spree
+sprig
+spunk
+spurn
+spurt
+squad
+squat
+squib
+stack
+staff
+stage
+staid
+stain
+stair
+stake
+stale
+stalk
+stall
+stamp
+stand
+stank
+stare
+stark
+start
+stash
+state
+stave
+stead
+steak
+steal
+steam
+steed
+steel
+steep
+steer
+stein
+stern
+stick
+stiff
+still
+stilt
+sting
+stink
+stint
+stock
+stoic
+stoke
+stole
+stomp
+stone
+stony
+stood
+stool
+stoop
+store
+stork
+storm
+story
+stout
+stove
+strap
+straw
+stray
+strip
+strut
+stuck
+study
+stuff
+stump
+stung
+stunk
+stunt
+style
+suave
+sugar
+suing
+suite
+sulky
+sully
+sumac
+sunny
+super
+surer
+surge
+surly
+sushi
+swami
+swamp
+swarm
+swash
+swath
+swear
+sweat
+sweep
+sweet
+swell
+swept
+swift
+swill
+swine
+swing
+swirl
+swish
+swoon
+swoop
+sword
+swore
+sworn
+swung
+synod
+syrup
+tabby
+table
+taboo
+tacit
+tacky
+taffy
+taint
+taken
+taker
+tally
+talon
+tamer
+tango
+tangy
+taper
+tapir
+tardy
+tarot
+taste
+tasty
+tatty
+taunt
+tawny
+teach
+teary
+tease
+teddy
+teeth
+tempo
+tenet
+tenor
+tense
+tenth
+tepee
+tepid
+terra
+terse
+testy
+thank
+theft
+their
+theme
+there
+these
+theta
+thick
+thief
+thigh
+thing
+think
+third
+thong
+thorn
+those
+three
+threw
+throb
+throw
+thrum
+thumb
+thump
+thyme
+tiara
+tibia
+tidal
+tiger
+tight
+tilde
+timer
+timid
+tipsy
+titan
+tithe
+title
+toast
+today
+toddy
+token
+tonal
+tonga
+tonic
+tooth
+topaz
+topic
+torch
+torso
+torus
+total
+totem
+touch
+tough
+towel
+tower
+toxic
+toxin
+trace
+track
+tract
+trade
+trail
+train
+trait
+tramp
+trash
+trawl
+tread
+treat
+trend
+triad
+trial
+tribe
+trice
+trick
+tried
+tripe
+trite
+troll
+troop
+trope
+trout
+trove
+truce
+truck
+truer
+truly
+trump
+trunk
+truss
+trust
+truth
+tryst
+tubal
+tuber
+tulip
+tulle
+tumor
+tunic
+turbo
+tutor
+twang
+tweak
+tweed
+tweet
+twice
+twine
+twirl
+twist
+twixt
+tying
+udder
+ulcer
+ultra
+umbra
+uncle
+uncut
+under
+undid
+undue
+unfed
+unfit
+unify
+union
+unite
+unity
+unlit
+unmet
+unset
+untie
+until
+unwed
+unzip
+upper
+upset
+urban
+urine
+usage
+usher
+using
+usual
+usurp
+utile
+utter
+vague
+valet
+valid
+valor
+value
+valve
+vapid
+vapor
+vault
+vaunt
+vegan
+venom
+venue
+verge
+verse
+verso
+verve
+vicar
+video
+vigil
+vigor
+villa
+vinyl
+viola
+viper
+viral
+virus
+visit
+visor
+vista
+vital
+vivid
+vixen
+vocal
+vodka
+vogue
+voice
+voila
+vomit
+voter
+vouch
+vowel
+vying
+wacky
+wafer
+wager
+wagon
+waist
+waive
+waltz
+warty
+waste
+watch
+water
+waver
+waxen
+weary
+weave
+wedge
+weedy
+weigh
+weird
+welch
+welsh
+wench
+whack
+whale
+wharf
+wheat
+wheel
+whelp
+where
+which
+whiff
+while
+whine
+whiny
+whirl
+whisk
+white
+whole
+whoop
+whose
+widen
+wider
+widow
+width
+wield
+wight
+willy
+wimpy
+wince
+winch
+windy
+wiser
+wispy
+witch
+witty
+woken
+woman
+women
+woody
+wooer
+wooly
+woozy
+wordy
+world
+worry
+worse
+worst
+worth
+would
+wound
+woven
+wrack
+wrath
+wreak
+wreck
+wrest
+wring
+wrist
+write
+wrong
+wrote
+wrung
+wryly
+yacht
+yearn
+yeast
+yield
+young
+youth
+zebra
+zesty
+zonal
\ No newline at end of file
diff --git a/web/samples/WordWiz/src/assets/logo.png b/web/samples/WordWiz/src/assets/logo.png
new file mode 100644
index 0000000000..1251323791
Binary files /dev/null and b/web/samples/WordWiz/src/assets/logo.png differ
diff --git a/web/samples/WordWiz/src/beam.ts b/web/samples/WordWiz/src/beam.ts
new file mode 100644
index 0000000000..d7bd60f0c5
--- /dev/null
+++ b/web/samples/WordWiz/src/beam.ts
@@ -0,0 +1,53 @@
+import { AccountService, AuthService, Beam, StatsService } from 'beamable-sdk';
+import { DAILY_STREAK, ENDLESS_STREAK } from '@app/game/constants.ts';
+import { GameStore } from '@app/game/state/store.ts';
+
+/**
+ * Initializes Beamable SDK
+ * - Configures Beam with environment values.
+ * - Registers required Beam services.
+ *
+ * @returns {Promise} A fully initialized and authenticated Beam instance.
+ */
+export async function setupBeam(): Promise {
+ // Initialize Beamable SDK with project configuration
+ const beam: Beam = await Beam.init({
+ cid: '1639786776798208',
+ pid: 'DE_1912686680736768',
+ environment: 'dev',
+ });
+
+ try {
+ // Register required services with the Beam instance
+ beam.use(AuthService).use(AccountService).use(StatsService);
+ return beam;
+ } catch (error) {
+ console.error('Beam Error:', error);
+ return beam;
+ }
+}
+
+export async function getAndComputePlayerStats(
+ beam: Beam,
+ store: GameStore,
+): Promise {
+ try {
+ const stats = await beam.stats.get({
+ accessType: 'private',
+ stats: [DAILY_STREAK, ENDLESS_STREAK],
+ });
+
+ const dailyStreak = DAILY_STREAK in stats ? stats[DAILY_STREAK] : '0';
+ const endlessStreak =
+ ENDLESS_STREAK in stats ? stats[ENDLESS_STREAK] : '0';
+
+ store.stats = {
+ [DAILY_STREAK]: dailyStreak,
+ [ENDLESS_STREAK]: endlessStreak,
+ };
+
+ dispatchEvent(new CustomEvent('stats_updated'));
+ } catch (error) {
+ console.error('Failed to fetch player stats:', error);
+ }
+}
diff --git a/web/samples/WordWiz/src/components/App.tsx b/web/samples/WordWiz/src/components/App.tsx
new file mode 100644
index 0000000000..351574a493
--- /dev/null
+++ b/web/samples/WordWiz/src/components/App.tsx
@@ -0,0 +1,15 @@
+import { Navigate, Route, Routes, HashRouter } from 'react-router-dom';
+import { routes } from '@app/navigation/routes.tsx';
+
+export function App() {
+ return (
+
+
+ {routes.map((route) => (
+
+ ))}
+ } />
+
+
+ );
+}
diff --git a/web/samples/WordWiz/src/components/Avatar.tsx b/web/samples/WordWiz/src/components/Avatar.tsx
new file mode 100644
index 0000000000..d229a32b17
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Avatar.tsx
@@ -0,0 +1,40 @@
+type AvatarProps = {
+ name?: string;
+ picture?: string;
+ size?: number; // pixels
+ className?: string;
+};
+
+export const Avatar = ({
+ name = 'Guest',
+ picture = '',
+ size = 32,
+ className = '',
+}: AvatarProps) => {
+ const initial = (name?.trim?.() || 'G').charAt(0).toUpperCase();
+
+ const style: React.CSSProperties = {
+ width: size,
+ height: size,
+ fontSize: Math.round(size * 0.45),
+ };
+
+ return (
+
+ {picture ? (
+
+ ) : (
+ <>{initial}>
+ )}
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/ErrorBoundary.tsx b/web/samples/WordWiz/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000000..bcc3fa68b0
--- /dev/null
+++ b/web/samples/WordWiz/src/components/ErrorBoundary.tsx
@@ -0,0 +1,48 @@
+import {
+ Component,
+ type ComponentType,
+ type GetDerivedStateFromError,
+ type PropsWithChildren,
+ type ReactNode,
+} from 'react';
+
+export interface ErrorBoundaryProps extends PropsWithChildren {
+ fallback?: ReactNode | ComponentType<{ error: unknown }>;
+}
+
+interface ErrorBoundaryState {
+ error?: unknown;
+}
+
+export class ErrorBoundary extends Component<
+ ErrorBoundaryProps,
+ ErrorBoundaryState
+> {
+ state: ErrorBoundaryState = {};
+
+ static getDerivedStateFromError: GetDerivedStateFromError<
+ ErrorBoundaryProps,
+ ErrorBoundaryState
+ > = (error) => ({ error });
+
+ componentDidCatch(error: Error) {
+ this.setState({ error });
+ }
+
+ render() {
+ const {
+ state: { error },
+ props: { fallback: Fallback, children },
+ } = this;
+
+ return 'error' in this.state ? (
+ typeof Fallback === 'function' ? (
+
+ ) : (
+ Fallback
+ )
+ ) : (
+ children
+ );
+ }
+}
diff --git a/web/samples/WordWiz/src/components/Grid.tsx b/web/samples/WordWiz/src/components/Grid.tsx
new file mode 100644
index 0000000000..ede17ee508
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Grid.tsx
@@ -0,0 +1,35 @@
+import { MAX_ATTEMPTS, TIPS, WORD_LENGTH } from '@app/game/constants.ts';
+import { useGrid } from '@app/components/hooks/useGrid.ts';
+
+export const Grid = () => {
+ const { tipTextRef, setTilesRef, setGridRowsRef } = useGrid();
+
+ return (
+
+
+ {Array.from({ length: MAX_ATTEMPTS }, (_, row) => {
+ return (
+
+ {Array.from({ length: WORD_LENGTH }).map((_, col) => (
+
+ ))}
+
+ );
+ })}
+
+
+ {TIPS}
+
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/Header.tsx b/web/samples/WordWiz/src/components/Header.tsx
new file mode 100644
index 0000000000..4f17d462b4
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Header.tsx
@@ -0,0 +1,25 @@
+import { Avatar } from '@app/components/Avatar.tsx';
+import { useHeader } from '@app/components/hooks/useHeader.ts';
+import { DAILY_STREAK, ENDLESS_STREAK } from '@app/game/constants.ts';
+
+export const Header = () => {
+ const { state, stats } = useHeader();
+
+ return (
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/Keyboard.tsx b/web/samples/WordWiz/src/components/Keyboard.tsx
new file mode 100644
index 0000000000..eb3b2c4cfb
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Keyboard.tsx
@@ -0,0 +1,90 @@
+import { useKeyboard } from '@app/components/hooks/useKeyboard.ts';
+import { KEYBOARD_ROW } from '@app/game/constants.ts';
+
+export const Keyboard = () => {
+ const {
+ setKeyboardKeysRef,
+ handleOnScreenKeyboardKeyClick,
+ handleSubmit,
+ handleDeleteLetter,
+ } = useKeyboard();
+
+ return (
+
+
+
+ {KEYBOARD_ROW[0].map((key) => {
+ return (
+
+ {key}
+
+ );
+ })}
+
+
+
+
+ {KEYBOARD_ROW[1].map((key) => {
+ return (
+
+ {key}
+
+ );
+ })}
+
+
+
+
+
+ Enter
+
+ {KEYBOARD_ROW[2].map((key) => {
+ return (
+
+ {key}
+
+ );
+ })}
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/Page.tsx b/web/samples/WordWiz/src/components/Page.tsx
new file mode 100644
index 0000000000..45ce1e4e6f
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Page.tsx
@@ -0,0 +1,5 @@
+import { type PropsWithChildren } from 'react';
+
+export function Page({ children }: PropsWithChildren) {
+ return <>{children}>;
+}
diff --git a/web/samples/WordWiz/src/components/Profile.tsx b/web/samples/WordWiz/src/components/Profile.tsx
new file mode 100644
index 0000000000..b87671a33c
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Profile.tsx
@@ -0,0 +1,19 @@
+import { Avatar } from '@app/components/Avatar.tsx';
+
+interface ProfileProps {
+ name?: string;
+ picture?: string;
+}
+
+export const Profile = ({ name = 'Guest', picture = '' }: ProfileProps) => {
+ return (
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/Result.tsx b/web/samples/WordWiz/src/components/Result.tsx
new file mode 100644
index 0000000000..ffa2177639
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Result.tsx
@@ -0,0 +1,54 @@
+import logo from '@app/assets/logo.png';
+import { useResult } from '@app/components/hooks/useResult.ts';
+import HomeIcon from '@app/assets/HomeIcon.tsx';
+import NextIcon from '@app/assets/NextIcon.tsx';
+
+export const Result = () => {
+ const {
+ state,
+ didWin,
+ isOpen,
+ attemptsUsed,
+ answer,
+ handleHome,
+ handleContinue,
+ resultContainerRef,
+ } = useResult();
+
+ return (
+
+
+
+
+
+ {didWin ? 'You Win!' : 'Out of guesses'}
+
+ {didWin ? (
+
+ Solved in {attemptsUsed}/{state.maxAttempts}
+
+ ) : (
+
Answer
+ )}
+
{answer}
+
+
+
+
+ Home
+
+ {state.mode === 'endless' && (
+
+
+ Continue
+
+ )}
+
+
+
+ );
+};
diff --git a/web/samples/WordWiz/src/components/Root.tsx b/web/samples/WordWiz/src/components/Root.tsx
new file mode 100644
index 0000000000..c64a2fee84
--- /dev/null
+++ b/web/samples/WordWiz/src/components/Root.tsx
@@ -0,0 +1,27 @@
+import { App } from '@app/components/App.tsx';
+import { ErrorBoundary } from '@app/components/ErrorBoundary.tsx';
+
+function ErrorBoundaryError({ error }: { error: unknown }) {
+ return (
+
+
An unhandled error occurred:
+
+
+ {error instanceof Error
+ ? error.message
+ : typeof error === 'string'
+ ? error
+ : JSON.stringify(error)}
+
+
+
+ );
+}
+
+export function Root() {
+ return (
+
+
+
+ );
+}
diff --git a/web/samples/WordWiz/src/components/hooks/useGrid.ts b/web/samples/WordWiz/src/components/hooks/useGrid.ts
new file mode 100644
index 0000000000..73ed7d55b1
--- /dev/null
+++ b/web/samples/WordWiz/src/components/hooks/useGrid.ts
@@ -0,0 +1,135 @@
+import { MAX_ATTEMPTS, TIPS, WORD_LENGTH } from '@app/game/constants.ts';
+import { useCallback, useEffect, useRef } from 'react';
+import { GameState, LetterMark } from '@app/game/types.ts';
+import { useGameStore } from '@app/context/GameStoreContext.tsx';
+
+export const useGrid = () => {
+ const store = useGameStore();
+ const tipTextTimeoutRef = useRef(null);
+ const tipTextRef = useRef(null);
+ const gridRowsRef = useRef<(HTMLDivElement | null)[]>(
+ Array.from({ length: MAX_ATTEMPTS }, (): HTMLDivElement | null => null),
+ );
+ const tilesRef = useRef<(HTMLDivElement | null)[][]>(
+ Array.from({ length: MAX_ATTEMPTS }, () =>
+ Array.from({ length: WORD_LENGTH }, (): HTMLDivElement | null => null),
+ ),
+ );
+
+ const setTilesRef = useCallback(
+ (row: number, col: number) => (el: HTMLDivElement) => {
+ if (!el) return;
+ tilesRef.current[row][col] = el;
+ },
+ [],
+ );
+
+ const setGridRowsRef = useCallback(
+ (row: number) => (el: HTMLDivElement) => {
+ if (!el) return;
+ gridRowsRef.current[row] = el;
+ },
+ [],
+ );
+
+ const handleGridChange = useCallback((state: GameState) => {
+ if (state.status === 'revealing') return;
+
+ const grid = state.grid;
+ for (let row = 0; row < MAX_ATTEMPTS; row++) {
+ for (let col = 0; col < WORD_LENGTH; col++) {
+ const tile = grid[row][col];
+ const el = tilesRef.current[row][col];
+ if (!el) continue;
+
+ if (!tile) {
+ el.textContent = '';
+ el.dataset['animation'] = 'idle';
+ continue;
+ }
+
+ el.textContent = tile.letter;
+ el.dataset['animation'] = 'pulse';
+ }
+ }
+ }, []);
+
+ const handleFlipTile = useCallback(
+ (row: number, col: number, mark: LetterMark) => {
+ const el = tilesRef.current[row][col];
+ if (!el) return;
+
+ el.dataset['animation'] = 'flip';
+ el.addEventListener(
+ 'animationend',
+ () => {
+ el.classList.remove('tile--correct', 'tile--present', 'tile--absent');
+ el.classList.add(`tile--${mark}`);
+ },
+ { once: true },
+ );
+ },
+ [],
+ );
+
+ const handleShakeGridRow = useCallback((row: number, reason: string) => {
+ const el = gridRowsRef.current[row];
+ if (!el) return;
+
+ if (tipTextRef.current) {
+ const tipText = tipTextRef.current;
+ tipText.classList.add('notification');
+ tipText.textContent = reason;
+
+ if (tipTextTimeoutRef.current) {
+ clearTimeout(tipTextTimeoutRef.current);
+ tipTextTimeoutRef.current = null;
+ }
+
+ tipTextTimeoutRef.current = setTimeout(() => {
+ tipText.classList.remove('notification');
+ tipText.textContent = TIPS;
+ }, 2000);
+ }
+
+ el.dataset['animation'] = 'shake';
+ el.addEventListener(
+ 'animationend',
+ () => {
+ el.dataset['animation'] = 'idle';
+ },
+ { once: true },
+ );
+ }, []);
+
+ const reset = () => {
+ for (let row = 0; row < MAX_ATTEMPTS; row++) {
+ for (let col = 0; col < WORD_LENGTH; col++) {
+ const el = tilesRef.current[row][col];
+ if (!el) continue;
+
+ el.textContent = '';
+ el.dataset['animation'] = 'idle';
+ el.classList.remove('tile--correct', 'tile--present', 'tile--absent');
+ }
+ }
+ if (tipTextRef.current) {
+ tipTextRef.current.textContent = TIPS;
+ }
+ if (tipTextTimeoutRef.current) clearTimeout(tipTextTimeoutRef.current);
+ };
+
+ useEffect(() => {
+ store.subscribe(handleGridChange);
+ store.setCallback({
+ onShakeGridRow: handleShakeGridRow,
+ onFlipTile: handleFlipTile,
+ });
+ window.addEventListener('reset', reset);
+ return () => {
+ window.removeEventListener('reset', reset);
+ };
+ }, []);
+
+ return { tipTextRef, setTilesRef, setGridRowsRef };
+};
diff --git a/web/samples/WordWiz/src/components/hooks/useHeader.ts b/web/samples/WordWiz/src/components/hooks/useHeader.ts
new file mode 100644
index 0000000000..b3cd560eb5
--- /dev/null
+++ b/web/samples/WordWiz/src/components/hooks/useHeader.ts
@@ -0,0 +1,21 @@
+import { useGameStore } from '@app/context/GameStoreContext.tsx';
+import { useCallback, useEffect, useState } from 'react';
+
+export const useHeader = () => {
+ const store = useGameStore();
+ const state = store.getState();
+ const [stats, setStats] = useState(store.stats);
+
+ const handleStatUpdate = useCallback(() => {
+ setStats(store.stats);
+ }, []);
+
+ useEffect(() => {
+ window.addEventListener('stats_updated', handleStatUpdate);
+ return () => {
+ window.removeEventListener('stats_updated', handleStatUpdate);
+ };
+ }, []);
+
+ return { state, stats };
+};
diff --git a/web/samples/WordWiz/src/components/hooks/useKeyboard.ts b/web/samples/WordWiz/src/components/hooks/useKeyboard.ts
new file mode 100644
index 0000000000..0fd497059c
--- /dev/null
+++ b/web/samples/WordWiz/src/components/hooks/useKeyboard.ts
@@ -0,0 +1,101 @@
+import {
+ MouseEvent as ReactMouseEvent,
+ useCallback,
+ useEffect,
+ useRef,
+} from 'react';
+import { useGameStore } from '@app/context/GameStoreContext.tsx';
+import { GameState, Letter } from '@app/game/types.ts';
+
+export const useKeyboard = () => {
+ const store = useGameStore();
+ const keyboardKeysRef = useRef([]);
+
+ const setKeyboardKeysRef = useCallback((el: HTMLButtonElement) => {
+ keyboardKeysRef.current.push(el);
+ }, []);
+
+ const handleSubmit = () => {
+ store.submit();
+ };
+
+ const handleDeleteLetter = () => {
+ store.deleteLetter();
+ };
+
+ const handleOnScreenKeyboardKeyClick = (
+ event: ReactMouseEvent,
+ ) => {
+ const key = (event.target as HTMLButtonElement).dataset['key'];
+ if (!key) return;
+
+ store.inputLetter(key.toUpperCase() as Letter);
+ };
+
+ const handlePhysicalKeyboardKeyClick = (event: KeyboardEvent) => {
+ event.preventDefault();
+ const key = event.key;
+
+ if (key === 'Enter') {
+ handleSubmit();
+ } else if (key === 'Backspace') {
+ handleDeleteLetter();
+ } else if (/^[a-zA-Z]$/.test(key)) {
+ store.inputLetter(key.toUpperCase() as Letter);
+ }
+ };
+
+ const handleKeyboardChange = useCallback((state: GameState) => {
+ if (state.status === 'revealing') return;
+
+ const keyboardState = state.keyboard;
+ for (let i = 0; i < keyboardKeysRef.current.length; i++) {
+ const key = keyboardKeysRef.current[i];
+ if (!key) continue;
+
+ const keyLetter = key.dataset['key'];
+ if (!keyLetter) continue;
+
+ const keyLetterMark = keyboardState[keyLetter.toUpperCase() as Letter];
+ if (!keyLetterMark) continue;
+
+ key.classList.remove(
+ 'keyboard-key--correct',
+ 'keyboard-key--present',
+ 'keyboard-key--absent',
+ );
+ key.classList.add(`keyboard-key--${keyLetterMark}`);
+ }
+ }, []);
+
+ const reset = () => {
+ for (let i = 0; i < keyboardKeysRef.current.length; i++) {
+ const key = keyboardKeysRef.current[i];
+ if (!key) return;
+
+ key.classList.remove(
+ 'keyboard-key--correct',
+ 'keyboard-key--present',
+ 'keyboard-key--absent',
+ );
+ }
+ };
+
+ useEffect(() => {
+ store.subscribe(handleKeyboardChange);
+ window.addEventListener('keydown', handlePhysicalKeyboardKeyClick);
+ window.addEventListener('reset', reset);
+ return () => {
+ window.removeEventListener('keydown', handlePhysicalKeyboardKeyClick);
+ window.removeEventListener('reset', reset);
+ };
+ }, []);
+
+ return {
+ setKeyboardKeysRef,
+ handleOnScreenKeyboardKeyClick,
+ handleSubmit,
+ handleDeleteLetter,
+ handleKeyboardChange,
+ };
+};
diff --git a/web/samples/WordWiz/src/components/hooks/useResult.ts b/web/samples/WordWiz/src/components/hooks/useResult.ts
new file mode 100644
index 0000000000..3c4e9cabe8
--- /dev/null
+++ b/web/samples/WordWiz/src/components/hooks/useResult.ts
@@ -0,0 +1,89 @@
+import { useGameStore } from '@app/context/GameStoreContext.tsx';
+import { useNavigate } from 'react-router-dom';
+import { useEffect, useRef, useState } from 'react';
+import { GameState } from '@app/game/types.ts';
+import { getEndlessSeed } from '@app/game/engine/seed.ts';
+import { useBeam } from '@app/context/BeamContext.tsx';
+import { DAILY_STREAK, ENDLESS_STREAK } from '@app/game/constants.ts';
+import { getAndComputePlayerStats } from '@app/beam.ts';
+
+export const useResult = () => {
+ const beam = useBeam();
+ const store = useGameStore();
+ const navigate = useNavigate();
+ const resultContainerRef = useRef(null);
+ const [state, setState] = useState(store.getState());
+
+ const didWin = state.status === 'round_end_win';
+ const didLose = state.status === 'round_end_loss';
+ const isOpen = didWin || didLose;
+ const attemptsUsed = didWin ? state.row + 1 : state.maxAttempts;
+ const answer = state.currentAnswer.join('');
+
+ const handleGameEnd = async (gameState: GameState) => {
+ if (resultContainerRef.current) {
+ resultContainerRef.current.dataset['animation'] = 'reveal';
+ resultContainerRef.current.addEventListener(
+ 'animationend',
+ () => {
+ resultContainerRef.current!.dataset['animation'] = 'idle';
+ },
+ { once: true },
+ );
+ }
+
+ const newGameState = { ...gameState };
+ setState(newGameState);
+
+ const mode = gameState.mode;
+ const key = mode === 'daily' ? DAILY_STREAK : ENDLESS_STREAK;
+
+ const currentStreak = Number(store.stats[key] ?? '0');
+ if (currentStreak === 0 && gameState.status === 'round_end_loss') return;
+
+ const newStreak =
+ gameState.status === 'round_end_win' ? String(currentStreak + 1) : '0';
+
+ await beam.stats.set({
+ accessType: 'private',
+ stats: {
+ [key]: newStreak,
+ },
+ });
+
+ await getAndComputePlayerStats(beam, store);
+ };
+
+ const handleHome = () => {
+ store.reset();
+ dispatchEvent(new CustomEvent('reset'));
+ setState(store.getState());
+ navigate('/');
+ };
+
+ const handleContinue = () => {
+ const seed = getEndlessSeed();
+ store.nextRound(seed);
+ dispatchEvent(new CustomEvent('reset'));
+ setState(store.getState());
+ };
+
+ useEffect(() => {
+ store.setCallback({
+ onGameEnd: (gameState) => {
+ void handleGameEnd(gameState);
+ },
+ });
+ }, []);
+
+ return {
+ state,
+ didWin,
+ isOpen,
+ attemptsUsed,
+ answer,
+ handleHome,
+ handleContinue,
+ resultContainerRef,
+ };
+};
diff --git a/web/samples/WordWiz/src/context/BeamContext.tsx b/web/samples/WordWiz/src/context/BeamContext.tsx
new file mode 100644
index 0000000000..14c257003b
--- /dev/null
+++ b/web/samples/WordWiz/src/context/BeamContext.tsx
@@ -0,0 +1,23 @@
+import { createContext, useContext, type ReactNode } from 'react';
+import type { Beam } from 'beamable-sdk';
+
+// Holds the globally available Beam instance
+export const BeamContext = createContext(null);
+
+export function BeamProvider({
+ beam,
+ children,
+}: {
+ beam: Beam;
+ children: ReactNode;
+}) {
+ return {children} ;
+}
+
+export function useBeam(): Beam {
+ const ctx = useContext(BeamContext);
+ if (!ctx) {
+ throw new Error('useBeam must be used within a BeamProvider');
+ }
+ return ctx;
+}
diff --git a/web/samples/WordWiz/src/context/GameStoreContext.tsx b/web/samples/WordWiz/src/context/GameStoreContext.tsx
new file mode 100644
index 0000000000..7c2404b595
--- /dev/null
+++ b/web/samples/WordWiz/src/context/GameStoreContext.tsx
@@ -0,0 +1,26 @@
+import { createContext, useContext, type ReactNode } from 'react';
+import { GameStore } from '@app/game/state/store.ts';
+
+export const GameStoreContext = createContext(null);
+
+export function GameStoreProvider({
+ store,
+ children,
+}: {
+ store: GameStore;
+ children: ReactNode;
+}) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function useGameStore(): GameStore {
+ const ctx = useContext(GameStoreContext);
+ if (!ctx) {
+ throw new Error('useGameStore must be used within a GameStoreProvider');
+ }
+ return ctx;
+}
diff --git a/web/samples/WordWiz/src/game/constants.ts b/web/samples/WordWiz/src/game/constants.ts
new file mode 100644
index 0000000000..2487b31b0c
--- /dev/null
+++ b/web/samples/WordWiz/src/game/constants.ts
@@ -0,0 +1,16 @@
+export const WORD_LENGTH = 5;
+export const MAX_ATTEMPTS = 6;
+export const TILE_FLIP_DURATION = 250;
+export const FLIP_STAGGER = 100;
+export const RESULT_REVEAL_DELAY = 500;
+export const KEYBOARD_ROW = [
+ ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
+ ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
+ ['z', 'x', 'c', 'v', 'b', 'n', 'm'],
+];
+export const LETTERS = Array.from({ length: 26 }, (_, i) =>
+ String.fromCharCode(65 + i),
+);
+export const TIPS = 'Green = Correct • Amber = Present • Dark = Absent';
+export const DAILY_STREAK = 'DAILY_STREAK';
+export const ENDLESS_STREAK = 'ENDLESS_STREAK';
diff --git a/web/samples/WordWiz/src/game/engine/guessEvaluator.ts b/web/samples/WordWiz/src/game/engine/guessEvaluator.ts
new file mode 100644
index 0000000000..aba75cf39b
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/guessEvaluator.ts
@@ -0,0 +1,56 @@
+import { GuessResult, Letter, LetterMark, Tile } from '@app/game/types.ts';
+
+export function guessEvaluator(
+ answer: Letter[],
+ guess: Letter[],
+ wordLength = 5,
+): GuessResult {
+ const tiles: Tile[] = [];
+ const marks: LetterMark[] = [];
+
+ for (let i = 0; i <= wordLength - 1; i++) {
+ tiles.push({ letter: guess[i], mark: undefined });
+ marks.push('absent');
+ }
+
+ const answerCounts = answer.reduce(
+ (letterMap, currentLetter) => {
+ if (currentLetter in letterMap) {
+ letterMap[currentLetter] = letterMap[currentLetter] + 1;
+ } else {
+ letterMap[currentLetter] = 1;
+ }
+
+ return letterMap;
+ },
+ {} as Record,
+ );
+
+ // First pass (correct):
+ for (let i = 0; i <= wordLength - 1; i++) {
+ const guessLetter = guess[i];
+ const answerLetter = answer[i];
+ if (guessLetter === answerLetter) {
+ marks[i] = 'correct';
+ tiles[i].mark = marks[i];
+ answerCounts[guessLetter] = answerCounts[guessLetter] - 1;
+ }
+ }
+
+ // Second pass (present/absent):
+ for (let i = 0; i <= wordLength - 1; i++) {
+ if (marks[i] === 'correct') continue;
+
+ const guessLetter = guess[i];
+ if (answerCounts[guessLetter] > 0) {
+ marks[i] = 'present';
+ tiles[i].mark = marks[i];
+ answerCounts[guessLetter] = answerCounts[guessLetter] - 1;
+ } else {
+ marks[i] = 'absent';
+ tiles[i].mark = marks[i];
+ }
+ }
+
+ return { tiles, marks, isWin: marks.every((mark) => mark === 'correct') };
+}
diff --git a/web/samples/WordWiz/src/game/engine/seed.ts b/web/samples/WordWiz/src/game/engine/seed.ts
new file mode 100644
index 0000000000..9086b46baf
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/seed.ts
@@ -0,0 +1,6 @@
+import answers from '@app/assets/answers.ts';
+
+export function getEndlessSeed() {
+ // generate a random number between 0 and answersLength
+ return Math.floor(Math.random() * answers.length);
+}
diff --git a/web/samples/WordWiz/src/game/engine/tests/guessEvaluator.test.ts b/web/samples/WordWiz/src/game/engine/tests/guessEvaluator.test.ts
new file mode 100644
index 0000000000..97c589a487
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/tests/guessEvaluator.test.ts
@@ -0,0 +1,78 @@
+import { expect, test } from 'vitest';
+import { guessEvaluator } from '@app/game/engine/guessEvaluator.ts';
+import { Letter } from '@app/game/types.ts';
+
+test('answer=APPLE, guess=ALLEY', () => {
+ const answer = 'APPLE'.split('').map((ch) => ch as Letter);
+ const guess = 'ALLEY'.split('').map((ch) => ch as Letter);
+ const result = guessEvaluator(answer, guess);
+
+ expect(result.marks).toEqual([
+ 'correct',
+ 'present',
+ 'absent',
+ 'present',
+ 'absent',
+ ]);
+ expect(result.isWin).toBe(false);
+});
+
+test('answer=LEVEL, guess=LEMON', () => {
+ const answer = 'LEVEL'.split('').map((ch) => ch as Letter);
+ const guess = 'LEMON'.split('').map((ch) => ch as Letter);
+ const result = guessEvaluator(answer, guess);
+
+ expect(result.marks).toEqual([
+ 'correct',
+ 'correct',
+ 'absent',
+ 'absent',
+ 'absent',
+ ]);
+ expect(result.isWin).toBe(false);
+});
+
+test('answer=ABBEY, guess=BABES', () => {
+ const answer = 'ABBEY'.split('').map((ch) => ch as Letter);
+ const guess = 'BABES'.split('').map((ch) => ch as Letter);
+ const result = guessEvaluator(answer, guess);
+
+ expect(result.marks).toEqual([
+ 'present',
+ 'present',
+ 'correct',
+ 'correct',
+ 'absent',
+ ]);
+ expect(result.isWin).toBe(false);
+});
+
+test('answer=CRANE, guess=CRANE', () => {
+ const answer = 'CRANE'.split('').map((ch) => ch as Letter);
+ const guess = 'CRANE'.split('').map((ch) => ch as Letter);
+ const result = guessEvaluator(answer, guess);
+
+ expect(result.marks).toEqual([
+ 'correct',
+ 'correct',
+ 'correct',
+ 'correct',
+ 'correct',
+ ]);
+ expect(result.isWin).toBe(true);
+});
+
+test('answer=PLATE, guess=BRING', () => {
+ const answer = 'PLATE'.split('').map((ch) => ch as Letter);
+ const guess = 'BRING'.split('').map((ch) => ch as Letter);
+ const result = guessEvaluator(answer, guess);
+
+ expect(result.marks).toEqual([
+ 'absent',
+ 'absent',
+ 'absent',
+ 'absent',
+ 'absent',
+ ]);
+ expect(result.isWin).toBe(false);
+});
diff --git a/web/samples/WordWiz/src/game/engine/tests/seed.test.ts b/web/samples/WordWiz/src/game/engine/tests/seed.test.ts
new file mode 100644
index 0000000000..411dce4b14
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/tests/seed.test.ts
@@ -0,0 +1,13 @@
+import { expect, test, vi } from 'vitest';
+import { getEndlessSeed } from '@app/game/engine/seed.ts';
+import answers from '@app/assets/answers.ts';
+
+test('getEndlessSeed()', () => {
+ vi.doMock('@app/assets/answers.ts', () => {
+ return { default: new Array(answers.length).fill(0) };
+ });
+
+ const seed = getEndlessSeed();
+ expect(seed).toBeGreaterThanOrEqual(0);
+ expect(seed).toBeLessThan(answers.length);
+});
diff --git a/web/samples/WordWiz/src/game/engine/tests/validators.test.ts b/web/samples/WordWiz/src/game/engine/tests/validators.test.ts
new file mode 100644
index 0000000000..8af9d44cd5
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/tests/validators.test.ts
@@ -0,0 +1,40 @@
+import { expect, test } from 'vitest';
+import {
+ canSubmit,
+ isAllowedWord,
+ isAlphabetic,
+ isLengthOk,
+} from '@app/game/engine/validators.ts';
+import allowedWords from '@app/assets/allowedWords.ts';
+
+test('isLengthOk()', () => {
+ const correct = 'ALLEY';
+ const wrong = 'FOOD';
+
+ expect(isLengthOk(correct)).toBe(true);
+ expect(isLengthOk(wrong)).toBe(false);
+});
+
+test('isAlphabetic()', () => {
+ const correct = 'ALLEY';
+ const wrong = 'FOOD1';
+
+ expect(isAlphabetic(correct)).toBe(true);
+ expect(isAlphabetic(wrong)).toBe(false);
+});
+
+test('isAllowedWord()', () => {
+ const correct = 'ARGON';
+ const wrong = 'FOOD';
+
+ expect(isAllowedWord(correct, allowedWords)).toBe(true);
+ expect(isAllowedWord(wrong, allowedWords)).toBe(false);
+});
+
+test('canSubmit()', () => {
+ const correct = 'ALLEY';
+ const wrong = 'FOOD';
+
+ expect(canSubmit(correct)).toBe(true);
+ expect(canSubmit(wrong)).toBe(false);
+});
diff --git a/web/samples/WordWiz/src/game/engine/validators.ts b/web/samples/WordWiz/src/game/engine/validators.ts
new file mode 100644
index 0000000000..678b55eb99
--- /dev/null
+++ b/web/samples/WordWiz/src/game/engine/validators.ts
@@ -0,0 +1,21 @@
+import { WORD_LENGTH } from '@app/game/constants.ts';
+import allowedWordsDefault from '@app/assets/allowedWords.ts';
+import answersDefault from '@app/assets/answers.ts';
+
+export function isLengthOk(word: string) {
+ return word.length === WORD_LENGTH;
+}
+
+export function isAlphabetic(word: string) {
+ return /^[A-Z]+$/.test(word);
+}
+
+// If an explicit list is provided, use it. Otherwise, use the default allowed words loaded from allowed.txt
+export function isAllowedWord(word: string, allowedWords?: string[]) {
+ const list = allowedWords ?? allowedWordsDefault.concat(answersDefault);
+ return list.includes(word.toLowerCase());
+}
+
+export function canSubmit(word: string) {
+ return isLengthOk(word) && isAlphabetic(word);
+}
diff --git a/web/samples/WordWiz/src/game/state/machine.ts b/web/samples/WordWiz/src/game/state/machine.ts
new file mode 100644
index 0000000000..99c79da208
--- /dev/null
+++ b/web/samples/WordWiz/src/game/state/machine.ts
@@ -0,0 +1,91 @@
+import { GameEvent, GameState, Letter, LetterMark } from '@app/game/types.ts';
+import { LETTERS } from '@app/game/constants.ts';
+import { guessEvaluator } from '@app/game/engine/guessEvaluator.ts';
+
+export function stateMachine(state: GameState, event: GameEvent) {
+ const currentRow = state.row;
+ const maxAttempts = state.maxAttempts;
+ const gridRow = [...state.grid[currentRow]];
+
+ switch (event.type) {
+ case 'INPUT_LETTER': {
+ if (state.status === 'typing') {
+ if (gridRow.length < state.wordLength) {
+ state.grid[currentRow] = [...gridRow, { letter: event.letter }];
+ }
+ }
+ return state;
+ }
+ case 'DELETE': {
+ if (state.status === 'typing') {
+ if (gridRow.length > 0) {
+ gridRow.pop();
+ state.grid[currentRow] = [...gridRow];
+ }
+ }
+ return state;
+ }
+ case 'SUBMIT': {
+ if (state.status === 'typing') {
+ state.isSubmitting = true;
+ state.status = 'validating';
+ const lastResult = guessEvaluator(
+ state.currentAnswer,
+ gridRow.map((tile) => tile.letter),
+ );
+ state.lastResult = lastResult;
+ state.grid[currentRow] = state.grid[currentRow].map((tile, i) => ({
+ ...tile,
+ mark: lastResult.marks[i],
+ }));
+ state.status = 'revealing';
+ }
+ return state;
+ }
+ case 'REVEAL_DONE': {
+ state.isSubmitting = false;
+ const lastResult = state.lastResult;
+ if (!lastResult) return state;
+
+ if (lastResult.isWin) {
+ state.status = 'round_end_win';
+ } else if (currentRow === maxAttempts - 1) {
+ state.status = 'round_end_loss';
+ } else {
+ state.status = 'typing';
+ state.row += 1;
+ }
+ return state;
+ }
+ case 'NEXT_ROUND': {
+ state = {
+ ...state,
+ row: 0,
+ grid: Array.from({ length: state.maxAttempts }, () => []),
+ keyboard: LETTERS.reduce(
+ (acc, cur) => ({
+ ...acc,
+ [cur]: undefined,
+ }),
+ {} as Record,
+ ),
+ answerSeed: event.answerSeed,
+ currentAnswer: event.currentAnswer,
+ status: 'typing',
+ lastResult: undefined,
+ };
+ return state;
+ }
+ case 'MODE_CHANGE': {
+ if (state.status === 'idle' || state.status === 'typing') {
+ state.mode = event.mode;
+ state.status = 'typing';
+ state.answerSeed = event.answerSeed;
+ state.currentAnswer = event.currentAnswer;
+ }
+ return state;
+ }
+ default:
+ return state;
+ }
+}
diff --git a/web/samples/WordWiz/src/game/state/store.ts b/web/samples/WordWiz/src/game/state/store.ts
new file mode 100644
index 0000000000..8269101808
--- /dev/null
+++ b/web/samples/WordWiz/src/game/state/store.ts
@@ -0,0 +1,195 @@
+import {
+ GameEvent,
+ GameMode,
+ GameState,
+ GuessResult,
+ Letter,
+ LetterMark,
+} from '@app/game/types.ts';
+import {
+ FLIP_STAGGER,
+ LETTERS,
+ RESULT_REVEAL_DELAY,
+ TILE_FLIP_DURATION,
+} from '@app/game/constants.ts';
+import { canSubmit, isAllowedWord } from '@app/game/engine/validators.ts';
+import { stateMachine } from '@app/game/state/machine.ts';
+
+interface GameStoreOptions {
+ mode: GameMode;
+ answerSeed: number;
+ wordLength: number;
+ maxAttempts: number;
+ getAnswerBySeed(seed: number): Letter[];
+ onShakeGridRow?(this: void, row: number, reason: string): void;
+ onFlipTile?(this: void, row: number, col: number, mark: LetterMark): void;
+ onRowRevealStart?(this: void, row: number): void;
+ onRowRevealEnd?(this: void, row: number, result: GuessResult): void;
+ onGameEnd?(this: void, state: GameState): void;
+}
+
+export interface GameStoreCallbacks {
+ onShakeGridRow?(this: void, row: number, reason: string): void;
+ onFlipTile?(this: void, row: number, col: number, mark: LetterMark): void;
+ onRowRevealStart?(this: void, row: number): void;
+ onRowRevealEnd?(this: void, row: number, result: GuessResult): void;
+ onGameEnd?(this: void, state: GameState): void;
+}
+
+export interface GameStore {
+ stats: Record;
+ getState(): GameState;
+ dispatch(event: GameEvent): void;
+ subscribe(fn: (state: GameState) => void): void;
+ inputLetter(letter: Letter): void;
+ deleteLetter(): void;
+ submit(): void;
+ nextRound(answerSeed: number): void;
+ changeMode(mode: GameMode, answerSeed: number): void;
+ setCallback(callback: GameStoreCallbacks): void;
+ reset(): void;
+}
+
+function buildInitialState(options: GameStoreOptions): GameState {
+ return {
+ mode: options.mode,
+ row: 0,
+ grid: Array.from({ length: options.maxAttempts }, () => []),
+ keyboard: LETTERS.reduce(
+ (acc, cur) => ({ ...acc, [cur]: undefined }),
+ {} as Record,
+ ),
+ currentAnswer: options.getAnswerBySeed(options.answerSeed),
+ answerSeed: options.answerSeed,
+ wordLength: options.wordLength,
+ maxAttempts: options.maxAttempts,
+ isSubmitting: false,
+ status: 'idle',
+ lastResult: undefined,
+ };
+}
+
+export function createGameStore(options: GameStoreOptions): GameStore {
+ let state = buildInitialState(options);
+ let subscribers: ((state: GameState) => void)[] = [];
+
+ const store: GameStore = {
+ stats: {},
+ getState() {
+ return state;
+ },
+ dispatch(event: GameEvent) {
+ state = stateMachine(state, event);
+ subscribers.forEach((fn) => fn(state));
+ },
+ subscribe(fn: (state: GameState) => void) {
+ subscribers.push(fn);
+ },
+ inputLetter(letter: Letter) {
+ store.dispatch({ type: 'INPUT_LETTER', letter });
+ },
+ deleteLetter() {
+ store.dispatch({ type: 'DELETE' });
+ },
+ submit() {
+ if (state.isSubmitting) return;
+
+ const gridRow = state.grid[state.row];
+ const rowWord = gridRow.map((tile) => tile.letter).join('');
+
+ if (!canSubmit(rowWord)) {
+ options.onShakeGridRow?.(state.row, 'Not enough letters');
+ return;
+ }
+
+ if (!isAllowedWord(rowWord)) {
+ options.onShakeGridRow?.(state.row, 'Not in word list');
+ return;
+ }
+
+ store.dispatch({ type: 'SUBMIT' });
+
+ if (state.status !== 'revealing') return;
+
+ // Reveal tiles
+ const row = state.row;
+ options.onRowRevealStart?.(row);
+ for (let col = 0; col <= options.wordLength - 1; col++) {
+ setTimeout(() => {
+ const tileLetter = state.grid[row][col].letter;
+ const keyboardLetterMark = state.keyboard[tileLetter];
+ const tileLetterMark = state.grid[row][col].mark;
+
+ options.onFlipTile?.(state.row, col, tileLetterMark ?? 'absent');
+
+ // Update keyboard state with priority: correct > present > absent
+ state.keyboard = {
+ ...state.keyboard,
+ [state.grid[row][col].letter]:
+ keyboardLetterMark === 'correct'
+ ? keyboardLetterMark
+ : keyboardLetterMark === 'present' &&
+ tileLetterMark === 'absent'
+ ? keyboardLetterMark
+ : tileLetterMark,
+ };
+
+ if (col !== options.wordLength - 1) return;
+
+ // Last tile, schedule REVEAL_DONE event
+ setTimeout(() => {
+ options.onRowRevealEnd?.(row, state.lastResult!);
+ store.dispatch({ type: 'REVEAL_DONE' });
+
+ const isNotRoundEnd =
+ state.status !== 'round_end_win' &&
+ state.status !== 'round_end_loss';
+ if (isNotRoundEnd) return;
+
+ setTimeout(() => {
+ options.onGameEnd?.(state);
+ }, RESULT_REVEAL_DELAY);
+ }, TILE_FLIP_DURATION + FLIP_STAGGER); // FLIP_STAGGER as buffer
+ }, col * FLIP_STAGGER);
+ }
+ },
+ nextRound(answerSeed: number) {
+ store.dispatch({
+ type: 'NEXT_ROUND',
+ currentAnswer: options.getAnswerBySeed(answerSeed),
+ answerSeed,
+ });
+ },
+ changeMode(mode: GameMode, answerSeed: number) {
+ store.dispatch({
+ type: 'MODE_CHANGE',
+ currentAnswer: options.getAnswerBySeed(answerSeed),
+ mode,
+ answerSeed,
+ });
+ },
+ setCallback(callbacks: GameStoreCallbacks) {
+ if (callbacks.onShakeGridRow) {
+ options.onShakeGridRow = callbacks.onShakeGridRow;
+ }
+ if (callbacks.onFlipTile) {
+ options.onFlipTile = callbacks.onFlipTile;
+ }
+ if (callbacks.onRowRevealStart) {
+ options.onRowRevealStart = callbacks.onRowRevealStart;
+ }
+ if (callbacks.onRowRevealEnd) {
+ options.onRowRevealEnd = callbacks.onRowRevealEnd;
+ }
+ if (callbacks.onGameEnd) {
+ options.onGameEnd = callbacks.onGameEnd;
+ }
+ },
+ reset() {
+ state = buildInitialState(options);
+ subscribers = [];
+ },
+ };
+
+ return store;
+}
diff --git a/web/samples/WordWiz/src/game/state/tests/machine.test.ts b/web/samples/WordWiz/src/game/state/tests/machine.test.ts
new file mode 100644
index 0000000000..215881f91b
--- /dev/null
+++ b/web/samples/WordWiz/src/game/state/tests/machine.test.ts
@@ -0,0 +1,212 @@
+import { expect, test, vi, beforeEach, afterEach } from 'vitest';
+import { createGameStore } from '@app/game/state/store.ts';
+import { LETTERS, MAX_ATTEMPTS, WORD_LENGTH } from '@app/game/constants.ts';
+import { Letter, LetterMark } from '@app/game/types.ts';
+import answers from '@app/assets/answers.ts';
+
+beforeEach(() => {
+ vi.useFakeTimers();
+});
+
+afterEach(() => {
+ vi.useRealTimers();
+});
+
+test('Basic typing and guard rails', () => {
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+ store.nextRound(0);
+
+ const expected: Letter[] = ['A', 'P', 'P', 'L', 'E'];
+ const input: Letter[] = ['A', 'P', 'P', 'L', 'E', 'S'];
+ input.forEach((letter) => store.inputLetter(letter));
+
+ const state = store.getState();
+ const currentRow = state.row;
+ const gridRow = [...state.grid[currentRow]];
+
+ expect(gridRow.map((tile) => tile.letter)).toEqual(expected);
+
+ store.deleteLetter();
+ store.deleteLetter();
+ expect(state.grid[currentRow].length).toBe(3);
+
+ store.submit();
+ expect(state.status).not.toBe('validating');
+ expect(state.status).toBe('typing');
+});
+
+test('Valid submit → reveal → continue typing', () => {
+ const handleFlipTile = vi.fn();
+ const handleRevealStart = vi.fn();
+ const handleRevealEnd = vi.fn();
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ onFlipTile: handleFlipTile,
+ onRowRevealStart: handleRevealStart,
+ onRowRevealEnd: handleRevealEnd,
+ });
+ store.nextRound(0);
+
+ const input: Letter[] = ['A', 'B', 'A', 'C', 'K'];
+ const expectedKeyboard = LETTERS.reduce(
+ (acc, cur) => ({ ...acc, [cur]: undefined }),
+ {} as Record,
+ );
+
+ input.forEach((letter) => store.inputLetter(letter));
+ store.submit();
+
+ expect(store.getState().status).toBe('revealing');
+ expect(handleRevealStart).toBeCalledTimes(1);
+ expect(handleRevealStart).toBeCalledWith(store.getState().row);
+
+ vi.runAllTimers();
+ input.forEach((letter) => (expectedKeyboard[letter] = 'correct'));
+
+ expect(handleFlipTile).toBeCalledTimes(5);
+ expect(handleRevealEnd).toBeCalledTimes(1);
+ expect(handleRevealEnd).toBeCalledWith(
+ store.getState().row,
+ store.getState().lastResult,
+ );
+ expect(store.getState().status).toBe('round_end_win');
+ expect(store.getState().keyboard).toEqual(expectedKeyboard);
+});
+
+test('Loss after max attempts', () => {
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+ store.nextRound(0);
+
+ const input: Letter[] = ['A', 'P', 'P', 'L', 'E'];
+ for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
+ input.forEach((letter) => store.inputLetter(letter));
+ store.submit();
+ vi.runAllTimers();
+ }
+
+ expect(store.getState().status).toBe('round_end_loss');
+});
+
+test('Next round resets correctly', () => {
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+ store.nextRound(0);
+
+ const state = store.getState();
+ expect(state.status).toBe('typing');
+ expect(state.row).toBe(0);
+ expect(state.grid.every((row) => row.length === 0)).toBe(true);
+ expect(
+ Object.values(state.keyboard).every((mark) => mark === undefined),
+ ).toBe(true);
+});
+
+test('Re-entrancy locks', () => {
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+ store.nextRound(0);
+
+ const input: Letter[] = ['A', 'P', 'P', 'L', 'E'];
+ const currentRow = store.getState().row;
+ input.forEach((letter) => store.inputLetter(letter));
+ store.submit();
+
+ expect(store.getState().status).toBe('revealing');
+
+ // These should be no-ops:
+ store.inputLetter('A');
+ expect(store.getState().status).toBe('revealing');
+ expect(store.getState().grid[currentRow].length).toBe(5);
+
+ store.deleteLetter();
+ expect(store.getState().status).toBe('revealing');
+ expect(store.getState().grid[currentRow].length).toBe(5);
+
+ store.submit();
+ expect(store.getState().status).toBe('revealing');
+ expect(store.getState().grid[currentRow].length).toBe(5);
+
+ vi.runAllTimers();
+});
+
+test('Mode change while idle/typing', () => {
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+ expect(store.getState().mode).toBe('endless');
+
+ store.dispatch({
+ type: 'MODE_CHANGE',
+ mode: 'daily',
+ answerSeed: 0,
+ currentAnswer: ['A', 'P', 'P', 'L', 'E'],
+ });
+ expect(store.getState().mode).toBe('daily');
+ expect(store.getState().answerSeed).toBe(0);
+
+ store.nextRound(0);
+ expect(store.getState().status).toBe('typing');
+
+ store.dispatch({
+ type: 'MODE_CHANGE',
+ mode: 'endless',
+ answerSeed: 0,
+ currentAnswer: ['A', 'P', 'P', 'L', 'E'],
+ });
+ expect(store.getState().mode).toBe('endless');
+ expect(store.getState().answerSeed).toBe(0);
+});
diff --git a/web/samples/WordWiz/src/game/types.ts b/web/samples/WordWiz/src/game/types.ts
new file mode 100644
index 0000000000..db42184b17
--- /dev/null
+++ b/web/samples/WordWiz/src/game/types.ts
@@ -0,0 +1,69 @@
+export type GameMode = 'daily' | 'endless';
+export type LetterMark = 'correct' | 'present' | 'absent';
+export type Tile = { letter: Letter; mark?: LetterMark };
+export type GuessResult = {
+ tiles: Tile[];
+ marks: LetterMark[];
+ isWin: boolean;
+};
+export type KeyboardState = Record;
+export type GameState = {
+ mode: GameMode;
+ row: number;
+ grid: Tile[][];
+ keyboard: KeyboardState;
+ currentAnswer: Letter[];
+ answerSeed: number;
+ wordLength: number;
+ maxAttempts: number;
+ isSubmitting: boolean;
+ status: GameStateStatus;
+ lastResult?: GuessResult;
+};
+export type GameStateStatus =
+ | 'idle'
+ | 'typing'
+ | 'validating'
+ | 'revealing'
+ | 'round_end_win'
+ | 'round_end_loss'
+ | 'ready_next';
+export type GameEvent =
+ | { type: 'INPUT_LETTER'; letter: Letter }
+ | { type: 'DELETE' }
+ | { type: 'SUBMIT' }
+ | { type: 'REVEAL_DONE' }
+ | { type: 'NEXT_ROUND'; answerSeed: number; currentAnswer: Letter[] }
+ | {
+ type: 'MODE_CHANGE';
+ mode: GameMode;
+ answerSeed: number;
+ currentAnswer: Letter[];
+ };
+export type Letter =
+ | 'A'
+ | 'B'
+ | 'C'
+ | 'D'
+ | 'E'
+ | 'F'
+ | 'G'
+ | 'H'
+ | 'I'
+ | 'J'
+ | 'K'
+ | 'L'
+ | 'M'
+ | 'N'
+ | 'O'
+ | 'P'
+ | 'Q'
+ | 'R'
+ | 'S'
+ | 'T'
+ | 'U'
+ | 'V'
+ | 'W'
+ | 'X'
+ | 'Y'
+ | 'Z';
diff --git a/web/samples/WordWiz/src/index.css b/web/samples/WordWiz/src/index.css
new file mode 100644
index 0000000000..2300023096
--- /dev/null
+++ b/web/samples/WordWiz/src/index.css
@@ -0,0 +1,626 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
+
+:root {
+ /* Colors */
+ --color-bg-body: #2b2f36;
+ --color-surface: #2b2f36;
+ --color-app-bg: #1c1e22;
+ --color-landing-bg: #edede9;
+ --color-text: #ffffff;
+ --color-text-muted: #6b7280;
+ --color-footer-text: #6b7280;
+
+ --color-primary: #fff;
+ --color-primary-hover: #e6e6e6;
+
+ --color-key-bg: #434a54;
+ --color-key-bg-hover: #5a626e;
+ --color-key-border: rgba(255, 255, 255, 0.05);
+
+ --color-tile-bg: #434a54;
+ --color-tile-border: #5a626e;
+ --color-tile-correct-bg: #3e9f1c;
+ --color-tile-correct-border: #2f7a14;
+ --color-tile-present-bg: #c39318;
+ --color-tile-present-border: #947012;
+ --color-tile-absent-bg: #3a3a3c;
+ --color-tile-absent-border: #2a2a2b;
+
+ /* Radii */
+ --radius-sm: 4px;
+ --radius-md: 8px;
+
+ /* Spacing */
+ --space-1: 4px;
+ --space-2: 8px;
+ --space-3: 12px;
+ --space-4: 16px;
+ --space-5: 20px;
+ --space-6: 24px;
+
+ /* Typography sizes */
+ --text-xs: 12px;
+ --text-sm: 14px;
+ --text-md: 16px;
+ --text-lg: 20px;
+ --text-xl: 32px;
+}
+
+* {
+ box-sizing: border-box;
+ font-family: 'Inter', sans-serif;
+ font-optical-sizing: auto;
+ font-weight: 400;
+}
+
+body {
+ background-color: var(--color-bg-body);
+ padding: 0;
+ margin: 0;
+}
+
+p {
+ margin: 0;
+}
+
+header {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ padding: var(--space-2);
+ gap: var(--space-4);
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-key-border);
+ color: var(--color-text);
+ border-radius: var(--radius-md);
+}
+
+.header-container {
+ width: 100%;
+ padding: var(--space-2);
+}
+
+.profile-container {
+ margin-top: var(--space-6);
+}
+
+.profile-group {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ gap: 8px;
+ min-width: 0;
+}
+
+.username {
+ font-size: var(--text-md);
+ font-weight: 500;
+ color: var(--color-text);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ flex: 1 1 auto;
+ min-width: 0;
+ max-width: 100%;
+}
+
+.avatar {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ border-radius: 50%;
+ color: var(--color-text);
+ font-weight: 700;
+ text-transform: uppercase;
+ user-select: none;
+ border: 1px solid var(--color-key-border);
+ background: var(--color-key-bg);
+}
+
+.btn {
+ background-color: var(--color-primary);
+ box-shadow: 0 -4px inset rgba(0, 0, 0, 0.25);
+ transition:
+ transform 0.1s ease,
+ background 0.2s ease,
+ box-shadow 0.2s ease;
+ color: var(--color-surface);
+ padding: var(--space-2) 14px;
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ border-radius: var(--radius-md);
+ border: none;
+ outline: none;
+ cursor: pointer;
+ font-weight: 500;
+ font-size: var(--text-md);
+ height: 42px;
+}
+
+.btn:hover {
+ background-color: var(--color-primary-hover);
+}
+
+.btn:active {
+ transform: translateY(1px);
+}
+
+.btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ transform: none;
+ box-shadow: 0 -4px inset rgba(0, 0, 0, 0.15);
+}
+
+.btn--sm {
+ box-shadow: 0 -2px inset rgba(0, 0, 0, 0.25);
+ padding: 6px 12px;
+ font-size: 14px;
+ height: 36px;
+}
+
+.tips {
+ text-align: center;
+ font-size: var(--text-xs);
+ font-weight: 500;
+ color: var(--color-text-muted);
+ padding: var(--space-1);
+}
+
+.tips.notification {
+ background-color: var(--color-primary);
+ border-radius: var(--radius-sm);
+ color: var(--color-surface);
+}
+
+.grid-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.grid-group {
+ display: grid;
+ grid-template-rows: repeat(6, 1fr);
+ gap: 4px;
+ padding: 12px;
+ width: 100%;
+ height: 100%;
+ max-width: 280px;
+ max-height: 332px;
+}
+
+.grid-row {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 4px;
+}
+
+.tile {
+ background: var(--color-tile-bg);
+ border: 1px solid var(--color-tile-border);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: var(--text-xl);
+ font-weight: 700;
+ color: var(--color-text);
+ height: 48px;
+ width: 48px;
+ border-radius: var(--radius-md);
+}
+
+.tile--correct {
+ background: var(--color-tile-correct-bg);
+ border: 1px solid var(--color-tile-correct-border);
+ color: var(--color-text);
+}
+
+.tile--present {
+ background: var(--color-tile-present-bg);
+ border: 1px solid var(--color-tile-present-border);
+ color: var(--color-text);
+}
+
+.tile--absent {
+ background: var(--color-tile-absent-bg);
+ border: 1px solid var(--color-tile-absent-border);
+ color: var(--color-text);
+}
+
+.keyboard-container {
+ display: flex;
+ justify-content: center;
+ padding: var(--space-2);
+ width: 100%;
+}
+
+.keyboard-group {
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-key-border);
+ width: 100%;
+ padding: var(--space-2);
+ border-radius: var(--radius-md);
+}
+
+.keyboard-row {
+ display: flex;
+ justify-content: center;
+ gap: calc(4px * 1.5);
+ margin-bottom: var(--space-3);
+}
+
+.keyboard-row:last-child {
+ margin-bottom: 0;
+}
+
+.keyboard-key {
+ flex: 1;
+ background: var(--color-key-bg);
+ height: 42px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: var(--text-lg);
+ font-weight: 700;
+ color: var(--color-text);
+ cursor: pointer;
+ user-select: none;
+ text-transform: uppercase;
+ padding: 0;
+ border: 1px solid var(--color-key-border);
+ border-radius: var(--radius-md);
+ transition:
+ transform 0.1s ease,
+ background 0.2s ease,
+ box-shadow 0.2s ease;
+ box-shadow:
+ 0 1px 0 rgba(255, 255, 255, 0.05),
+ inset 0 -2px 0 rgba(0, 0, 0, 0.25);
+}
+
+.keyboard-key:hover {
+ background-color: var(--color-key-bg-hover);
+}
+
+.keyboard-key:active {
+ transform: translateY(1px);
+}
+
+.keyboard-key--large {
+ flex: 1.5;
+ font-size: var(--text-xs);
+}
+
+.keyboard-key--correct {
+ background: var(--color-tile-correct-bg);
+ border: 1px solid var(--color-tile-correct-border);
+ color: var(--color-text);
+}
+
+.keyboard-key--present {
+ background: var(--color-tile-present-bg);
+ border: 1px solid var(--color-tile-present-border);
+ color: var(--color-text);
+}
+
+.keyboard-key--absent {
+ background: var(--color-tile-absent-bg);
+ border: 1px solid var(--color-tile-absent-border);
+ color: var(--color-text);
+}
+
+.keyboard-edge {
+ flex: 0.5;
+}
+
+.landing-page {
+ align-items: center;
+ justify-items: center;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ background-color: var(--color-landing-bg);
+ max-width: 780px;
+ margin: 0 auto;
+}
+
+.flex-spacer {
+ flex: 1;
+}
+
+.landing-hero {
+ align-items: center;
+ justify-items: center;
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-6);
+}
+
+.logo-img {
+ width: 250px;
+ height: auto;
+}
+
+.button-row {
+ display: flex;
+ gap: var(--space-3);
+}
+
+.landing-footer {
+ flex: 1;
+ text-align: center;
+ color: var(--color-footer-text);
+ font-size: var(--text-xs);
+ margin-bottom: var(--space-6);
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+}
+
+.text-strong {
+ font-weight: 700;
+}
+
+.stack-vert {
+ display: flex;
+ flex-direction: column;
+ flex: 0 0 auto;
+ gap: 2px;
+}
+
+.stack-vert--right {
+ align-items: flex-end;
+}
+
+.caption {
+ font-size: var(--text-xs);
+ text-transform: capitalize;
+ margin: 0;
+}
+
+.caption--right {
+ text-align: right;
+}
+
+.data {
+ font-size: var(--text-sm);
+ font-weight: 500;
+ color: var(--color-text);
+}
+
+.data--right {
+ text-align: right;
+}
+
+.app-page {
+ align-items: center;
+ justify-items: center;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ min-height: 100vh;
+ margin: 0 auto;
+}
+
+.app-page--game {
+ background-color: var(--color-app-bg);
+ max-width: 500px;
+}
+
+.game-section {
+ width: 100%;
+ align-items: center;
+ justify-items: center;
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+.tg-sticker {
+ display: block;
+ width: 144px;
+ height: 144px;
+}
+
+.result-dialog {
+ width: 100%;
+ height: 100%;
+ max-width: 500px;
+ background: rgba(0, 0, 0, 0.4);
+ backdrop-filter: blur(2px);
+ -webkit-backdrop-filter: blur(2px);
+ border: none;
+ padding-top: 72px;
+}
+
+.result-container {
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-key-border);
+ width: 100%;
+ min-height: 350px;
+ border-radius: var(--radius-md);
+ display: flex;
+ flex-direction: column;
+}
+
+.result-container[data-animation='reveal'] {
+ animation: result_reveal 400ms ease-in;
+}
+
+@keyframes result_reveal {
+ 0% {
+ opacity: 0;
+ transform: translateY(12px) scale(0.98);
+ }
+ 60% {
+ opacity: 1;
+ transform: translateY(0) scale(1.01);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+.result-header {
+ padding: var(--space-6) var(--space-3);
+ text-align: center;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.result-title {
+ color: var(--color-text);
+ font-size: var(--text-xl);
+ font-weight: 800;
+ margin-bottom: var(--space-2);
+}
+
+.result-subtitle {
+ color: var(--color-tile-correct-bg);
+ font-size: var(--text-sm);
+ font-weight: 500;
+}
+
+.result-answer {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 12px;
+ border-radius: var(--radius-sm);
+ background: var(--color-key-bg);
+ border: 1px solid var(--color-key-border);
+ color: var(--color-text);
+ font-weight: 700;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+ margin-top: var(--space-3);
+}
+
+.result-actions {
+ display: flex;
+ justify-content: center;
+ gap: var(--space-4);
+ padding: var(--space-4);
+ border-top: 1px solid var(--color-key-border);
+}
+
+.brand-logo {
+ width: 100px;
+ height: auto;
+ margin-bottom: var(--space-4);
+}
+
+.loading-text {
+ color: var(--color-text);
+ font-size: var(--text-md);
+ font-weight: 500;
+ text-align: center;
+}
+
+.loading-text::after {
+ content: '.';
+ animation: dots 1s steps(5, start) infinite;
+}
+
+@keyframes dots {
+ 0%,
+ 20% {
+ color: rgba(0, 0, 0, 0);
+ text-shadow:
+ 0.25em 0 0 rgba(0, 0, 0, 0),
+ 0.5em 0 0 rgba(0, 0, 0, 0);
+ }
+ 40% {
+ color: var(--color-text);
+ text-shadow:
+ 0.25em 0 0 rgba(0, 0, 0, 0),
+ 0.5em 0 0 rgba(0, 0, 0, 0);
+ }
+ 60% {
+ text-shadow:
+ 0.25em 0 0 var(--color-text),
+ 0.5em 0 0 rgba(0, 0, 0, 0);
+ }
+ 80%,
+ 100% {
+ text-shadow:
+ 0.25em 0 0 var(--color-text),
+ 0.5em 0 0 var(--color-text);
+ }
+}
+
+.tile[data-animation='pulse'] {
+ animation-name: tile_pulse;
+ animation-duration: 100ms;
+}
+
+@keyframes tile_pulse {
+ 0% {
+ transform: scale(0.8);
+ }
+
+ 40% {
+ transform: scale(1.1);
+ border-width: 2px;
+ }
+}
+
+.tile[data-animation='flip'] {
+ animation-name: tile_flip;
+ animation-duration: 250ms;
+ animation-timing-function: ease-in;
+}
+
+@keyframes tile_flip {
+ 0% {
+ transform: rotateX(0);
+ }
+
+ 100% {
+ transform: rotateX(-90deg);
+ }
+}
+
+.grid-row[data-animation='shake'] {
+ animation-name: row_shake;
+ animation-duration: 600ms;
+}
+
+@keyframes row_shake {
+ 10%,
+ 90% {
+ transform: translateX(-1px);
+ }
+
+ 20%,
+ 80% {
+ transform: translateX(2px);
+ }
+
+ 30%,
+ 50%,
+ 70% {
+ transform: translateX(-4px);
+ }
+
+ 40%,
+ 60% {
+ transform: translateX(4px);
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ * {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
diff --git a/web/samples/WordWiz/src/index.tsx b/web/samples/WordWiz/src/index.tsx
new file mode 100644
index 0000000000..ae78fb5f21
--- /dev/null
+++ b/web/samples/WordWiz/src/index.tsx
@@ -0,0 +1,47 @@
+import ReactDOM from 'react-dom/client';
+import { StrictMode } from 'react';
+import { Root } from '@app/components/Root.tsx';
+import { init } from '@app/init.ts';
+import { BeamProvider } from '@app/context/BeamContext.tsx';
+import { createGameStore } from '@app/game/state/store.ts';
+import { GameStoreProvider } from '@app/context/GameStoreContext.tsx';
+import { MAX_ATTEMPTS, WORD_LENGTH } from '@app/game/constants.ts';
+import { Letter } from '@app/game/types.ts';
+import answers from '@app/assets/answers.ts';
+import { getAndComputePlayerStats } from '@app/beam.ts';
+import './index.css';
+import { ErrorBoundary } from './components/ErrorBoundary';
+
+const root = ReactDOM.createRoot(document.getElementById('root')!);
+
+try {
+ // Configure all application dependencies.
+ const beam = await init();
+
+ const store = createGameStore({
+ mode: 'endless',
+ answerSeed: 0,
+ wordLength: WORD_LENGTH,
+ maxAttempts: MAX_ATTEMPTS,
+ getAnswerBySeed(seed: number): Letter[] {
+ return answers[seed]
+ .split('')
+ .map((letter) => letter.toUpperCase() as Letter);
+ },
+ });
+
+ await getAndComputePlayerStats(beam, store);
+
+ root.render(
+
+
+
+
+
+
+ ,
+ );
+} catch (error) {
+ console.error('Failed to initialize WordWiz:', error);
+ root.render( );
+}
diff --git a/web/samples/WordWiz/src/init.ts b/web/samples/WordWiz/src/init.ts
new file mode 100644
index 0000000000..b22c42538d
--- /dev/null
+++ b/web/samples/WordWiz/src/init.ts
@@ -0,0 +1,9 @@
+import type { Beam } from 'beamable-sdk';
+import { setupBeam } from '@app/beam.ts';
+
+/**
+ * Initializes the application and configures its dependencies.
+ */
+export async function init(): Promise {
+ return await setupBeam();
+}
diff --git a/web/samples/WordWiz/src/navigation/routes.tsx b/web/samples/WordWiz/src/navigation/routes.tsx
new file mode 100644
index 0000000000..4589ec6c0b
--- /dev/null
+++ b/web/samples/WordWiz/src/navigation/routes.tsx
@@ -0,0 +1,16 @@
+import type { ComponentType, JSX } from 'react';
+
+import { IndexPage } from '@app/pages/IndexPage.tsx';
+import { GamePage } from '@app/pages/GamePage.tsx';
+
+interface Route {
+ path: string;
+ Component: ComponentType;
+ title?: string;
+ icon?: JSX.Element;
+}
+
+export const routes: Route[] = [
+ { path: '/', Component: IndexPage },
+ { path: '/game', Component: GamePage },
+];
diff --git a/web/samples/WordWiz/src/pages/GamePage.tsx b/web/samples/WordWiz/src/pages/GamePage.tsx
new file mode 100644
index 0000000000..88094f55ec
--- /dev/null
+++ b/web/samples/WordWiz/src/pages/GamePage.tsx
@@ -0,0 +1,21 @@
+import type { FC } from 'react';
+import { Page } from '@app/components/Page.tsx';
+import { Grid } from '@app/components/Grid.tsx';
+import { Keyboard } from '@app/components/Keyboard.tsx';
+import { Header } from '@app/components/Header.tsx';
+import { Result } from '@app/components/Result.tsx';
+
+export const GamePage: FC = () => {
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/web/samples/WordWiz/src/pages/IndexPage.tsx b/web/samples/WordWiz/src/pages/IndexPage.tsx
new file mode 100644
index 0000000000..e4a73eed4d
--- /dev/null
+++ b/web/samples/WordWiz/src/pages/IndexPage.tsx
@@ -0,0 +1,33 @@
+import type { FC } from 'react';
+import { Page } from '@app/components/Page.tsx';
+import logo from '@app/assets/logo.png';
+import EndlessIcon from '@app/assets/EndlessIcon.tsx';
+import { Profile } from '@app/components/Profile.tsx';
+import { useIndexPage } from '@app/pages/hooks/useIndexPage.ts';
+
+export const IndexPage: FC = () => {
+ const { handleEndlessButtonClick } = useIndexPage();
+
+ return (
+
+
+
+
+
+
+
+
+
+ Endless
+
+
+
+
+
+ powered by Beamable
+
+
+
+
+ );
+};
diff --git a/web/samples/WordWiz/src/pages/hooks/useIndexPage.ts b/web/samples/WordWiz/src/pages/hooks/useIndexPage.ts
new file mode 100644
index 0000000000..df52916881
--- /dev/null
+++ b/web/samples/WordWiz/src/pages/hooks/useIndexPage.ts
@@ -0,0 +1,16 @@
+import { getEndlessSeed } from '@app/game/engine/seed.ts';
+import { useGameStore } from '@app/context/GameStoreContext.tsx';
+import { useNavigate } from 'react-router-dom';
+
+export const useIndexPage = () => {
+ const store = useGameStore();
+ const navigate = useNavigate();
+
+ const handleEndlessButtonClick = () => {
+ const seed = getEndlessSeed();
+ store.changeMode('endless', seed);
+ navigate('/game');
+ };
+
+ return { handleEndlessButtonClick };
+};
diff --git a/web/samples/WordWiz/tsconfig.json b/web/samples/WordWiz/tsconfig.json
new file mode 100644
index 0000000000..2c3855c6a0
--- /dev/null
+++ b/web/samples/WordWiz/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "noEmit": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "paths": {
+ "@app/*": ["./src/*"],
+ "beamable-sdk": ["../../src/index.ts"],
+ "beamable-sdk/*": ["../../src/*"],
+ "@/defaults": ["../../src/defaults.browser.ts"],
+ "@/utils/createHash": ["../../src/utils/createHashStub.ts"],
+ "@/*": ["../../src/*"]
+ },
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "types": ["vite/client"]
+ },
+ "include": ["src"],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/web/samples/WordWiz/tsconfig.node.json b/web/samples/WordWiz/tsconfig.node.json
new file mode 100644
index 0000000000..42872c59f5
--- /dev/null
+++ b/web/samples/WordWiz/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/web/samples/WordWiz/vite.config.ts b/web/samples/WordWiz/vite.config.ts
new file mode 100644
index 0000000000..21d2a34a0c
--- /dev/null
+++ b/web/samples/WordWiz/vite.config.ts
@@ -0,0 +1,56 @@
+import { fileURLToPath } from 'node:url';
+import { dirname, resolve } from 'node:path';
+import { defineConfig } from 'vite';
+import tsconfigPaths from 'vite-tsconfig-paths';
+import react from '@vitejs/plugin-react-swc';
+import mkcert from 'vite-plugin-mkcert';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+const projectRoot = resolve(__dirname, '..', '..');
+const sdkSource = resolve(projectRoot, 'src');
+const sampleSource = resolve(__dirname, 'src');
+
+// https://vitejs.dev/config/
+export default defineConfig(({ mode }) => ({
+ base: mode === 'production' ? './' : '/',
+ css: {
+ preprocessorOptions: {
+ scss: {
+ api: 'modern',
+ },
+ },
+ },
+ plugins: [
+ // Allows using React dev server along with building a React application with Vite.
+ // https://npmjs.com/package/@vitejs/plugin-react-swc
+ react(),
+ // Allows using the compilerOptions.paths property in tsconfig.json.
+ // https://www.npmjs.com/package/vite-tsconfig-paths
+ tsconfigPaths(),
+ // Creates a custom SSL certificate valid for the local machine.
+ // Using this plugin requires admin rights on the first dev-mode launch.
+ // https://www.npmjs.com/package/vite-plugin-mkcert
+ process.env.HTTPS && mkcert(),
+ ],
+ build: {
+ target: 'esnext',
+ },
+ publicDir: './public',
+ resolve: {
+ alias: {
+ 'beamable-sdk': resolve(sdkSource, 'index.ts'),
+ '@/defaults': resolve(sdkSource, 'defaults.browser.ts'),
+ '@/utils/createHash': resolve(sdkSource, 'utils/createHashStub.ts'),
+ '@': sdkSource,
+ '@app': sampleSource,
+ },
+ },
+ server: {
+ // Exposes your dev server and makes it accessible for the devices in the same network.
+ host: true,
+ fs: {
+ allow: [projectRoot],
+ },
+ },
+}));
diff --git a/web/src/core/types/index.ts b/web/src/core/types/index.ts
index 77d851a674..d896598e7e 100644
--- a/web/src/core/types/index.ts
+++ b/web/src/core/types/index.ts
@@ -1,5 +1,5 @@
export * from './RefreshableServiceMap';
export * from './ServiceMap';
-export { Subscription } from './Subscription';
+export type { Subscription } from './Subscription';
export * from './SubscriptionMap';
export * from './ServerEventType';
diff --git a/web/src/utils/BeamJsonUtils.ts b/web/src/utils/BeamJsonUtils.ts
index 994fe25cf7..239e629df5 100644
--- a/web/src/utils/BeamJsonUtils.ts
+++ b/web/src/utils/BeamJsonUtils.ts
@@ -28,7 +28,7 @@ export class BeamJsonUtils {
* Usage:
* `JSON.parse(jsonString, BeamJsonUtils.reviver)`
*/
- static reviver(key: string, value: any): any {
+ static reviver(_key: string, value: any): any {
if (typeof value === 'string') {
if (BeamJsonUtils.ISO_DATE_REGEX.test(value)) return new Date(value);