diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..09b8f4e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,19 @@ +name: Lint and Unit Tests +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm install -g pnpm && pnpm install + - name: Run linting + run: pnpm lint diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..520eebb --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,29 @@ +name: Playwright Tests +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + e2e: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm install -g pnpm && pnpm install + - name: Install Playwright Browsers + working-directory: ./test-harness + run: pnpm install && pnpm exec playwright install --with-deps + - name: Run Playwright tests + working-directory: ./test-harness + run: pnpm e2e + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: test-harness/playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 28f1ba7..508b03a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ node_modules -.DS_Store \ No newline at end of file +.DS_Store +/test-harness/test-results/ +/test-harness/playwright-report/ +/blob-report/ +/playwright/.cache/ +/dist/ diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 016efd8..0000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v20.10.0 \ No newline at end of file diff --git a/docs/ai-journey.md b/docs/ai-journey.md deleted file mode 100644 index e69de29..0000000 diff --git a/eslint.config.mjs b/eslint.config.mjs index e779c9d..8fcef51 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -17,5 +17,6 @@ export default [ "react/react-in-jsx-scope": "off", "react/prop-types": "off", } - } + }, + { settings: { react: { version: "detect" } } }, ]; diff --git a/main.tsx b/main.tsx deleted file mode 100644 index c97e2cb..0000000 --- a/main.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React, { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import { Backgammon } from "./src/components/Backgammon"; - -createRoot(document.getElementById("root")!).render( - - - , -); diff --git a/package.json b/package.json index 9eee5fd..faf4228 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,22 @@ "name": "backgammon-board-react", "version": "1.0.0", "description": "Simplistic backgammon board in react", - "main": "dist/bundle.js", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/index.umd.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "require": "./dist/index.umd.cjs", + "types": "./dist/index.d.ts" + } + }, "scripts": { "build": "vite build", - "dev": "vite --host", - "test": "echo \"Error: no test specified\" && exit 1", "lint": "eslint .", "format": "prettier --write --ignore-unknown .", "prepare": "husky", @@ -28,8 +39,8 @@ }, "homepage": "https://github.com/Backgammonist/backgammon-board#readme", "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0. || ^18.0.0 || ^19.0.0" }, "resolutions": { "typescript-eslint": "^8.15.0" @@ -45,10 +56,15 @@ "eslint --fix" ] }, + "dependencies": { + "styled-components": "^6.1.13", + "vite-plugin-dts": "^4.5.0" + }, "devDependencies": { "@commitlint/cli": "^19.6.1", "@commitlint/config-conventional": "^19.6.0", "@eslint/js": "^9.17.0", + "@types/node": "^22.10.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", @@ -59,7 +75,6 @@ "husky": "^9.1.7", "lint-staged": "^15.2.11", "prettier": "3.4.2", - "styled-components": "^6.1.13", "typescript": "~5.6.2", "typescript-eslint": "^8.13.0", "vite": "^5.4.10" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 057d88f..7b2e3c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,21 +12,30 @@ importers: .: dependencies: react: - specifier: ^18.0.0 + specifier: ^17.0.0 || ^18.0.0 || ^19.0.0 version: 18.3.1 react-dom: - specifier: ^18.0.0 + specifier: ^17.0.0. || ^18.0.0 || ^19.0.0 version: 18.3.1(react@18.3.1) + styled-components: + specifier: ^6.1.13 + version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + vite-plugin-dts: + specifier: ^4.5.0 + version: 4.5.0(@types/node@22.10.2)(rollup@4.24.4)(typescript@5.6.3)(vite@5.4.11(@types/node@22.10.2)(terser@5.36.0)) devDependencies: '@commitlint/cli': specifier: ^19.6.1 - version: 19.6.1(@types/node@22.9.0)(typescript@5.6.3) + version: 19.6.1(@types/node@22.10.2)(typescript@5.6.3) '@commitlint/config-conventional': specifier: ^19.6.0 version: 19.6.0 '@eslint/js': specifier: ^9.17.0 version: 9.17.0 + '@types/node': + specifier: ^22.10.2 + version: 22.10.2 '@types/react': specifier: ^18.3.12 version: 18.3.12 @@ -35,7 +44,7 @@ importers: version: 18.3.1 '@vitejs/plugin-react': specifier: ^4.3.3 - version: 4.3.3(vite@5.4.10(@types/node@22.9.0)(terser@5.36.0)) + version: 4.3.3(vite@5.4.11(@types/node@22.10.2)(terser@5.36.0)) eslint: specifier: ^9.17.0 version: 9.17.0(jiti@2.4.2) @@ -57,9 +66,6 @@ importers: prettier: specifier: 3.4.2 version: 3.4.2 - styled-components: - specifier: ^6.1.13 - version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) typescript: specifier: ~5.6.2 version: 5.6.3 @@ -68,7 +74,7 @@ importers: version: 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.6.3) vite: specifier: ^5.4.10 - version: 5.4.10(@types/node@22.9.0)(terser@5.36.0) + version: 5.4.11(@types/node@22.10.2)(terser@5.36.0) packages: @@ -446,6 +452,19 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@microsoft/api-extractor-model@7.30.2': + resolution: {integrity: sha512-3/t2F+WhkJgBzSNwlkTIL0tBgUoBqDqL66pT+nh2mPbM0NIDGVGtpqbGWPgHIzn/mn7kGS/Ep8D8po58e8UUIw==} + + '@microsoft/api-extractor@7.49.1': + resolution: {integrity: sha512-jRTR/XbQF2kb+dYn8hfYSicOGA99+Fo00GrsdMwdfE3eIgLtKdH6Qa2M3wZV9S2XmbgCaGX1OdPtYctbfu5jQg==} + hasBin: true + + '@microsoft/tsdoc-config@0.17.1': + resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==} + + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -458,6 +477,15 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.24.4': resolution: {integrity: sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==} cpu: [arm] @@ -548,6 +576,31 @@ packages: cpu: [x64] os: [win32] + '@rushstack/node-core-library@5.10.2': + resolution: {integrity: sha512-xOF/2gVJZTfjTxbo4BDj9RtQq/HFnrrKdtem4JkyRLnwsRz2UDTg8gA1/et10fBx5RxmZD9bYVGST69W8ME5OQ==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.3': + resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==} + + '@rushstack/terminal@0.14.5': + resolution: {integrity: sha512-TEOpNwwmsZVrkp0omnuTUTGZRJKTr6n6m4OITiNjkqzLAkcazVpwR1SOtBg6uzpkIBLgrcNHETqI8rbw3uiUfw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.23.3': + resolution: {integrity: sha512-HazKL8fv4HMQMzrKJCrOrhyBPPdzk7iajUXgsASwjQ8ROo1cmgyqxt/k9+SdmrNLGE1zATgRqMUH3s/6smbRMA==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -569,8 +622,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.9.0': - resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} + '@types/node@22.10.2': + resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} '@types/prop-types@15.7.13': resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} @@ -637,6 +690,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 + '@volar/language-core@2.4.11': + resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} + + '@volar/source-map@2.4.11': + resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==} + + '@volar/typescript@2.4.11': + resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==} + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -651,12 +733,37 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ajv@8.13.0: + resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + ansi-escapes@7.0.0: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} @@ -677,6 +784,9 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -798,9 +908,15 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + conventional-changelog-angular@7.0.0: resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} engines: {node: '>=16'} @@ -864,6 +980,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -914,6 +1033,10 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -1019,6 +1142,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1075,6 +1201,10 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1151,6 +1281,9 @@ packages: 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==} @@ -1181,6 +1314,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -1198,6 +1335,10 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} @@ -1354,6 +1495,9 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1386,6 +1530,9 @@ packages: engines: {node: '>=6'} hasBin: true + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} @@ -1397,6 +1544,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1417,6 +1567,10 @@ packages: resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} engines: {node: '>=18.0.0'} + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1452,6 +1606,9 @@ packages: lodash.upperfirst@4.3.1: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} @@ -1463,6 +1620,13 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -1490,6 +1654,9 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1500,9 +1667,15 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1582,6 +1755,9 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1601,6 +1777,12 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.1: + resolution: {integrity: sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1608,11 +1790,18 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true + pkg-types@1.3.0: + resolution: {integrity: sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -1624,8 +1813,8 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -1687,6 +1876,11 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + resolve@2.0.0-next.5: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true @@ -1725,6 +1919,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} @@ -1792,6 +1991,9 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -1853,6 +2055,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -1917,17 +2123,29 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true @@ -1937,8 +2155,17 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - vite@5.4.10: - resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} + vite-plugin-dts@4.5.0: + resolution: {integrity: sha512-M1lrPTdi7gilLYRZoLmGYnl4fbPryVYsehPN9JgaxjJKTs8/f7tuAlvCCvOLB5gRDQTTKnptBcB0ACsaw2wNLw==} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -1968,6 +2195,9 @@ packages: terser: optional: true + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -2008,6 +2238,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.6.1: resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} engines: {node: '>= 14'} @@ -2057,7 +2290,7 @@ snapshots: '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.3.7 + debug: 4.4.0 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -2136,7 +2369,7 @@ snapshots: '@babel/parser': 7.26.2 '@babel/template': 7.25.9 '@babel/types': 7.26.0 - debug: 4.3.7 + debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -2146,11 +2379,11 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@commitlint/cli@19.6.1(@types/node@22.9.0)(typescript@5.6.3)': + '@commitlint/cli@19.6.1(@types/node@22.10.2)(typescript@5.6.3)': dependencies: '@commitlint/format': 19.5.0 '@commitlint/lint': 19.6.0 - '@commitlint/load': 19.6.1(@types/node@22.9.0)(typescript@5.6.3) + '@commitlint/load': 19.6.1(@types/node@22.10.2)(typescript@5.6.3) '@commitlint/read': 19.5.0 '@commitlint/types': 19.5.0 tinyexec: 0.3.1 @@ -2197,7 +2430,7 @@ snapshots: '@commitlint/rules': 19.6.0 '@commitlint/types': 19.5.0 - '@commitlint/load@19.6.1(@types/node@22.9.0)(typescript@5.6.3)': + '@commitlint/load@19.6.1(@types/node@22.10.2)(typescript@5.6.3)': dependencies: '@commitlint/config-validator': 19.5.0 '@commitlint/execute-rule': 19.5.0 @@ -2205,7 +2438,7 @@ snapshots: '@commitlint/types': 19.5.0 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.6.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.9.0)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.10.2)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -2410,6 +2643,41 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@microsoft/api-extractor-model@7.30.2(@types/node@22.10.2)': + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.10.2(@types/node@22.10.2) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.49.1(@types/node@22.10.2)': + dependencies: + '@microsoft/api-extractor-model': 7.30.2(@types/node@22.10.2) + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + '@rushstack/node-core-library': 5.10.2(@types/node@22.10.2) + '@rushstack/rig-package': 0.5.3 + '@rushstack/terminal': 0.14.5(@types/node@22.10.2) + '@rushstack/ts-command-line': 4.23.3(@types/node@22.10.2) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.10 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.7.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.17.1': + dependencies: + '@microsoft/tsdoc': 0.15.1 + ajv: 8.12.0 + jju: 1.4.0 + resolve: 1.22.10 + + '@microsoft/tsdoc@0.15.1': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2422,6 +2690,14 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@rollup/pluginutils@5.1.4(rollup@4.24.4)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.24.4 + '@rollup/rollup-android-arm-eabi@4.24.4': optional: true @@ -2476,6 +2752,42 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.24.4': optional: true + '@rushstack/node-core-library@5.10.2(@types/node@22.10.2)': + dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.10 + semver: 7.5.4 + optionalDependencies: + '@types/node': 22.10.2 + + '@rushstack/rig-package@0.5.3': + dependencies: + resolve: 1.22.10 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.14.5(@types/node@22.10.2)': + dependencies: + '@rushstack/node-core-library': 5.10.2(@types/node@22.10.2) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 22.10.2 + + '@rushstack/ts-command-line@4.23.3(@types/node@22.10.2)': + dependencies: + '@rushstack/terminal': 0.14.5(@types/node@22.10.2) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@types/argparse@1.0.38': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.26.2 @@ -2499,15 +2811,15 @@ snapshots: '@types/conventional-commits-parser@5.0.1': dependencies: - '@types/node': 22.9.0 + '@types/node': 22.10.2 '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} - '@types/node@22.9.0': + '@types/node@22.10.2': dependencies: - undici-types: 6.19.8 + undici-types: 6.20.0 '@types/prop-types@15.7.13': {} @@ -2599,17 +2911,62 @@ snapshots: '@typescript-eslint/types': 8.18.1 eslint-visitor-keys: 4.2.0 - '@vitejs/plugin-react@4.3.3(vite@5.4.10(@types/node@22.9.0)(terser@5.36.0))': + '@vitejs/plugin-react@4.3.3(vite@5.4.11(@types/node@22.10.2)(terser@5.36.0))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.10(@types/node@22.9.0)(terser@5.36.0) + vite: 5.4.11(@types/node@22.10.2)(terser@5.36.0) transitivePeerDependencies: - supports-color + '@volar/language-core@2.4.11': + dependencies: + '@volar/source-map': 2.4.11 + + '@volar/source-map@2.4.11': {} + + '@volar/typescript@2.4.11': + dependencies: + '@volar/language-core': 2.4.11 + path-browserify: 1.0.1 + vscode-uri: 3.0.8 + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.26.2 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/language-core@2.2.0(typescript@5.6.3)': + dependencies: + '@volar/language-core': 2.4.11 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 0.4.14 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.6.3 + + '@vue/shared@3.5.13': {} + JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 @@ -2621,6 +2978,14 @@ snapshots: acorn@8.14.0: {} + ajv-draft-04@1.0.0(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@3.0.1(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -2628,6 +2993,20 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.13.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 @@ -2635,6 +3014,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + alien-signals@0.4.14: {} + ansi-escapes@7.0.0: dependencies: environment: 1.1.0 @@ -2649,6 +3030,10 @@ snapshots: ansi-styles@6.2.1: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} array-buffer-byte-length@1.0.2: @@ -2800,8 +3185,12 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 + compare-versions@6.1.1: {} + concat-map@0.0.1: {} + confbox@0.1.8: {} + conventional-changelog-angular@7.0.0: dependencies: compare-func: 2.0.0 @@ -2819,9 +3208,9 @@ snapshots: convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@22.9.0)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.10.2)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): dependencies: - '@types/node': 22.9.0 + '@types/node': 22.10.2 cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 2.4.2 typescript: 5.6.3 @@ -2871,6 +3260,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + de-indent@1.0.2: {} + debug@4.3.7: dependencies: ms: 2.1.3 @@ -2913,6 +3304,8 @@ snapshots: emoji-regex@8.0.0: {} + entities@4.5.0: {} + env-paths@2.2.1: {} environment@1.1.0: {} @@ -3137,6 +3530,8 @@ snapshots: estraverse@5.3.0: {} + estree-walker@2.0.2: {} + esutils@2.0.3: {} eventemitter3@5.0.1: {} @@ -3203,6 +3598,12 @@ snapshots: dependencies: is-callable: 1.2.7 + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fsevents@2.3.3: optional: true @@ -3277,6 +3678,8 @@ snapshots: gopd@1.2.0: {} + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} has-bigints@1.1.0: {} @@ -3301,6 +3704,8 @@ snapshots: dependencies: function-bind: 1.1.2 + he@1.2.0: {} + human-signals@5.0.0: {} husky@9.1.7: {} @@ -3312,6 +3717,8 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-lazy@4.0.0: {} + import-meta-resolve@4.1.0: {} imurmurhash@0.1.4: {} @@ -3457,6 +3864,8 @@ snapshots: jiti@2.4.2: {} + jju@1.4.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -3477,6 +3886,10 @@ snapshots: json5@2.2.3: {} + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + jsonparse@1.3.1: {} jsx-ast-utils@3.3.5: @@ -3490,6 +3903,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kolorist@1.8.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -3523,6 +3938,11 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.0 + local-pkg@0.5.1: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3549,6 +3969,8 @@ snapshots: lodash.upperfirst@4.3.1: {} + lodash@4.17.21: {} + log-update@6.1.0: dependencies: ansi-escapes: 7.0.0 @@ -3565,6 +3987,14 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + math-intrinsics@1.1.0: {} meow@12.1.1: {} @@ -3582,6 +4012,10 @@ snapshots: mimic-function@5.0.1: {} + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.11 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -3592,8 +4026,17 @@ snapshots: minimist@1.2.8: {} + mlly@1.7.4: + dependencies: + acorn: 8.14.0 + pathe: 2.0.1 + pkg-types: 1.3.0 + ufo: 1.5.4 + ms@2.1.3: {} + muggle-string@0.4.1: {} + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -3683,6 +4126,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + path-browserify@1.0.1: {} + path-exists@4.0.0: {} path-exists@5.0.0: {} @@ -3693,12 +4138,24 @@ snapshots: path-parse@1.0.7: {} + pathe@1.1.2: {} + + pathe@2.0.1: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pidtree@0.6.0: {} + pkg-types@1.3.0: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 1.1.2 + possible-typed-array-names@1.0.0: {} postcss-value-parser@4.2.0: {} @@ -3709,7 +4166,7 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.4.47: + postcss@8.4.49: dependencies: nanoid: 3.3.7 picocolors: 1.1.1 @@ -3769,6 +4226,12 @@ snapshots: resolve-from@5.0.0: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + resolve@2.0.0-next.5: dependencies: is-core-module: 2.16.0 @@ -3832,6 +4295,10 @@ snapshots: semver@6.3.1: {} + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + semver@7.6.3: {} set-function-length@1.2.2: @@ -3906,11 +4373,12 @@ snapshots: source-map: 0.6.1 optional: true - source-map@0.6.1: - optional: true + source-map@0.6.1: {} split2@4.2.0: {} + sprintf-js@1.0.3: {} + string-argv@0.3.2: {} string-width@4.2.3: @@ -4001,6 +4469,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} terser@5.36.0: @@ -4076,6 +4548,10 @@ snapshots: typescript@5.6.3: {} + typescript@5.7.2: {} + + ufo@1.5.4: {} + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.3 @@ -4083,10 +4559,12 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 - undici-types@6.19.8: {} + undici-types@6.20.0: {} unicorn-magic@0.1.0: {} + universalify@0.1.2: {} + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: browserslist: 4.24.2 @@ -4097,16 +4575,37 @@ snapshots: dependencies: punycode: 2.3.1 - vite@5.4.10(@types/node@22.9.0)(terser@5.36.0): + vite-plugin-dts@4.5.0(@types/node@22.10.2)(rollup@4.24.4)(typescript@5.6.3)(vite@5.4.11(@types/node@22.10.2)(terser@5.36.0)): + dependencies: + '@microsoft/api-extractor': 7.49.1(@types/node@22.10.2) + '@rollup/pluginutils': 5.1.4(rollup@4.24.4) + '@volar/typescript': 2.4.11 + '@vue/language-core': 2.2.0(typescript@5.6.3) + compare-versions: 6.1.1 + debug: 4.4.0 + kolorist: 1.8.0 + local-pkg: 0.5.1 + magic-string: 0.30.17 + typescript: 5.6.3 + optionalDependencies: + vite: 5.4.11(@types/node@22.10.2)(terser@5.36.0) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite@5.4.11(@types/node@22.10.2)(terser@5.36.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 + postcss: 8.4.49 rollup: 4.24.4 optionalDependencies: - '@types/node': 22.9.0 + '@types/node': 22.10.2 fsevents: 2.3.3 terser: 5.36.0 + vscode-uri@3.0.8: {} + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -4169,6 +4668,8 @@ snapshots: yallist@3.1.1: {} + yallist@4.0.0: {} + yaml@2.6.1: {} yargs-parser@21.1.1: {} diff --git a/src/components/Backgammon.tsx b/src/components/Backgammon.tsx index 4bd6fc6..37869cb 100644 --- a/src/components/Backgammon.tsx +++ b/src/components/Backgammon.tsx @@ -1,3 +1,4 @@ +"use client"; import { DimensionProvider, GameStateProvider, diff --git a/src/components/Board.tsx b/src/components/Board.tsx index 7e3cb7d..6b45f33 100644 --- a/src/components/Board.tsx +++ b/src/components/Board.tsx @@ -4,7 +4,6 @@ import { Checker } from "./Checker"; import { Point } from "./Point"; import { Sidebar } from "./Sidebar"; import { PipCounter } from "./PipCounter"; -import { PlayerType } from "../types"; import { Dice } from "./Dice"; export const Board: React.FC = () => { @@ -181,11 +180,8 @@ export const Board: React.FC = () => { height={boardHeight - borderWidth * 2} fill={colours.borderColor} /> - - + + diff --git a/src/components/Checker.tsx b/src/components/Checker.tsx index 3b9aee0..6c15ff2 100644 --- a/src/components/Checker.tsx +++ b/src/components/Checker.tsx @@ -21,11 +21,9 @@ export const Checker: React.FC = ({ opponentCheckerBorderColor, } = useTheme(); const fill = - playerType === PlayerType.PLAYER - ? playerCheckerColor - : opponentCheckerColor; + playerType === "player" ? playerCheckerColor : opponentCheckerColor; const stroke = - playerType === PlayerType.PLAYER + playerType === "player" ? playerCheckerBorderColor : opponentCheckerBorderColor; const pos = usePosition(); diff --git a/src/components/Dice.tsx b/src/components/Dice.tsx index 9909a4a..397fb79 100644 --- a/src/components/Dice.tsx +++ b/src/components/Dice.tsx @@ -1,5 +1,4 @@ import { useDimensions, useGameState } from "../providers"; -import { PlayerType } from "../types"; import { Die } from "./Die"; export const Dice = () => { @@ -12,10 +11,10 @@ export const Dice = () => { return ( <> - {dice?.[0] && } + {dice?.[0] && } {dice?.[1] && ( - + )} diff --git a/src/components/Die.tsx b/src/components/Die.tsx index 7bfba3d..dca68a5 100644 --- a/src/components/Die.tsx +++ b/src/components/Die.tsx @@ -16,11 +16,9 @@ export const Die: React.FC = ({ value = 2, colorSchema }) => { const { boardHeight, dieWidth, dieDotSize, panelWidth, barWidth } = useDimensions(); const dieBackgroundColor = - colorSchema === PlayerType.PLAYER - ? playerCheckerColor - : opponentCheckerColor; + colorSchema === "player" ? playerCheckerColor : opponentCheckerColor; const dotFillColor = - colorSchema === PlayerType.PLAYER + colorSchema === "player" ? playerCheckerBorderColor : opponentCheckerBorderColor; diff --git a/src/components/DoublingCube.tsx b/src/components/DoublingCube.tsx index 6e183de..2ab1745 100644 --- a/src/components/DoublingCube.tsx +++ b/src/components/DoublingCube.tsx @@ -1,17 +1,16 @@ import { useDimensions, useTheme } from "../providers"; import type { DoublingCube as DoublingCubeType } from "../types"; -import { PlayerType } from "../types"; export const DoublingCube: React.FC = ({ owner, value }) => { const { doublingCubeColor } = useTheme(); const { boardHeight, sidebarWidth, cubeWidth, borderWidth } = useDimensions(); const xPos = (sidebarWidth - cubeWidth) / 2; - // const yPos = (boardHeight - cubeWidth) / 2 + (owner === PlayerType.PLAYER ? cubeWidth / 2 : -(cubeWidth / 2)); + // const yPos = (boardHeight - cubeWidth) / 2 + (owner === "player" ? cubeWidth / 2 : -(cubeWidth / 2)); const yPos = owner === null ? boardHeight / 2 - cubeWidth / 2 - : owner === PlayerType.PLAYER + : owner === "player" ? boardHeight - cubeWidth - borderWidth / 2 : borderWidth / 2; diff --git a/src/components/PipCounter.tsx b/src/components/PipCounter.tsx index b3353db..fc1882d 100644 --- a/src/components/PipCounter.tsx +++ b/src/components/PipCounter.tsx @@ -13,7 +13,7 @@ export const PipCounter: React.FC = ({ playerType }) => { const pip = positions?.reduce((acc, current) => { const isPlayer = current.playerType === playerType; const normalisedPosition = - current.playerType === PlayerType.PLAYER + current.playerType === "player" ? current.position : 25 - current.position; return isPlayer ? acc + current.numberOfCheckers * normalisedPosition : acc; @@ -23,7 +23,7 @@ export const PipCounter: React.FC = ({ playerType }) => { { @@ -19,15 +18,14 @@ export const Sidebar: React.FC = () => { const playerOut = positions ?.filter( - ({ position, playerType }) => - playerType === PlayerType.PLAYER && position === 0, + ({ position, playerType }) => playerType === "player" && position === 0, ) .reduce((acc, current) => acc + current.numberOfCheckers, 0) ?? 0; const opponentOut = positions ?.filter( ({ position, playerType }) => - playerType === PlayerType.OPPONENT && position === 25, + playerType === "opponent" && position === 25, ) .reduce((acc, current) => acc + current.numberOfCheckers, 0) ?? 0; diff --git a/src/index.tsx b/src/index.tsx index d258a08..d916f88 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1 +1 @@ -export * from "./components/Board"; +export * from "./components/Backgammon"; diff --git a/src/providers/GameStateProvider.tsx b/src/providers/GameStateProvider.tsx index be071fa..b92dbd1 100644 --- a/src/providers/GameStateProvider.tsx +++ b/src/providers/GameStateProvider.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext } from "react"; -import { BoardStateState, PlayerType } from "../types"; +import { BoardStateState } from "../types"; // TODO: validate game state positions: // - each position value has to be unique @@ -7,15 +7,15 @@ import { BoardStateState, PlayerType } from "../types"; const initialState: BoardStateState = { positions: [ - { playerType: PlayerType.PLAYER, position: 24, numberOfCheckers: 2 }, - { playerType: PlayerType.PLAYER, position: 13, numberOfCheckers: 5 }, - { playerType: PlayerType.PLAYER, position: 8, numberOfCheckers: 3 }, - { playerType: PlayerType.PLAYER, position: 6, numberOfCheckers: 5 }, + { playerType: "player", position: 24, numberOfCheckers: 2 }, + { playerType: "player", position: 13, numberOfCheckers: 5 }, + { playerType: "player", position: 8, numberOfCheckers: 3 }, + { playerType: "player", position: 6, numberOfCheckers: 5 }, - { playerType: PlayerType.OPPONENT, position: 1, numberOfCheckers: 2 }, - { playerType: PlayerType.OPPONENT, position: 12, numberOfCheckers: 5 }, - { playerType: PlayerType.OPPONENT, position: 17, numberOfCheckers: 3 }, - { playerType: PlayerType.OPPONENT, position: 19, numberOfCheckers: 5 }, + { playerType: "opponent", position: 1, numberOfCheckers: 2 }, + { playerType: "opponent", position: 12, numberOfCheckers: 5 }, + { playerType: "opponent", position: 17, numberOfCheckers: 3 }, + { playerType: "opponent", position: 19, numberOfCheckers: 5 }, ], }; diff --git a/src/types.ts b/src/types.ts index a9935d5..bda1ccb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,6 @@ import { presets } from "./helpers/presets"; -export enum PlayerType { - PLAYER = "player", - OPPONENT = "opponent", -} +export type PlayerType = "player" | "opponent"; export type DieValue = 1 | 2 | 3 | 4 | 5 | 6; @@ -78,4 +75,5 @@ export type Theme = { playerCheckerBorderColor: string; opponentCheckerColor: string; opponentCheckerBorderColor: string; + doublingCubeColor: string; }; diff --git a/test-harness/package.json b/test-harness/package.json new file mode 100644 index 0000000..de66208 --- /dev/null +++ b/test-harness/package.json @@ -0,0 +1,14 @@ +{ + "name": "test-harness", + "type": "module", + "scripts": { + "dev": "vite --host", + "e2e": "playwright test", + "e2e:update": "playwright test --update-snapshots" + }, + "dependencies": { + "@fontsource/open-sans": "^5.1.1", + "@playwright/test": "^1.49.1", + "vite": "^5.4.10" + } +} diff --git a/test-harness/playwright.config.ts b/test-harness/playwright.config.ts new file mode 100644 index 0000000..298c0b3 --- /dev/null +++ b/test-harness/playwright.config.ts @@ -0,0 +1,46 @@ +import { defineConfig, devices } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests", + fullyParallel: true, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: "html", + use: { + baseURL: "http://localhost:3000", + trace: "on-first-retry", + }, + snapshotPathTemplate: + "{testDir}/__screenshots__/{testFilePath}/{projectName}/{arg}{ext}", + + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + + { + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, + { + name: "mobile chrome", + use: { ...devices["Pixel 5"] }, + }, + { + name: "mobile safari", + use: devices["iPhone 12"], + }, + ], + + webServer: { + command: "pnpm dev", + url: "http://localhost:3000/tests/index.html", + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/test-harness/pnpm-lock.yaml b/test-harness/pnpm-lock.yaml new file mode 100644 index 0000000..c02f982 --- /dev/null +++ b/test-harness/pnpm-lock.yaml @@ -0,0 +1,563 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@fontsource/open-sans': + specifier: ^5.1.1 + version: 5.1.1 + '@playwright/test': + specifier: ^1.49.1 + version: 1.49.1 + vite: + specifier: ^5.4.10 + version: 5.4.11 + +packages: + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@fontsource/open-sans@5.1.1': + resolution: {integrity: sha512-Wfio5om0XH24ZUu6FfW4r50e4xLdoLzvd8midtqUFT2unniyWQj6GJ05RW1YQsHp4Sug3i+agFBIxEmYQzUHSg==} + + '@playwright/test@1.49.1': + resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==} + engines: {node: '>=18'} + hasBin: true + + '@rollup/rollup-android-arm-eabi@4.30.1': + resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.30.1': + resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.30.1': + resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.30.1': + resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.30.1': + resolution: {integrity: sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.30.1': + resolution: {integrity: sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': + resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.30.1': + resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.30.1': + resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.30.1': + resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': + resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': + resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.30.1': + resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.30.1': + resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.30.1': + resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.30.1': + resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.30.1': + resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.30.1': + resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.30.1': + resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + playwright-core@1.49.1: + resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.49.1: + resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==} + engines: {node: '>=18'} + hasBin: true + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + + rollup@4.30.1: + resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + +snapshots: + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@fontsource/open-sans@5.1.1': {} + + '@playwright/test@1.49.1': + dependencies: + playwright: 1.49.1 + + '@rollup/rollup-android-arm-eabi@4.30.1': + optional: true + + '@rollup/rollup-android-arm64@4.30.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.30.1': + optional: true + + '@rollup/rollup-darwin-x64@4.30.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.30.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.30.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.30.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.30.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.30.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.30.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.30.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.30.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.30.1': + optional: true + + '@types/estree@1.0.6': {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + nanoid@3.3.8: {} + + picocolors@1.1.1: {} + + playwright-core@1.49.1: {} + + playwright@1.49.1: + dependencies: + playwright-core: 1.49.1 + optionalDependencies: + fsevents: 2.3.2 + + postcss@8.4.49: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + rollup@4.30.1: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.30.1 + '@rollup/rollup-android-arm64': 4.30.1 + '@rollup/rollup-darwin-arm64': 4.30.1 + '@rollup/rollup-darwin-x64': 4.30.1 + '@rollup/rollup-freebsd-arm64': 4.30.1 + '@rollup/rollup-freebsd-x64': 4.30.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.30.1 + '@rollup/rollup-linux-arm-musleabihf': 4.30.1 + '@rollup/rollup-linux-arm64-gnu': 4.30.1 + '@rollup/rollup-linux-arm64-musl': 4.30.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.30.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.30.1 + '@rollup/rollup-linux-riscv64-gnu': 4.30.1 + '@rollup/rollup-linux-s390x-gnu': 4.30.1 + '@rollup/rollup-linux-x64-gnu': 4.30.1 + '@rollup/rollup-linux-x64-musl': 4.30.1 + '@rollup/rollup-win32-arm64-msvc': 4.30.1 + '@rollup/rollup-win32-ia32-msvc': 4.30.1 + '@rollup/rollup-win32-x64-msvc': 4.30.1 + fsevents: 2.3.3 + + source-map-js@1.2.1: {} + + vite@5.4.11: + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.30.1 + optionalDependencies: + fsevents: 2.3.3 diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/chromium/crazy-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/crazy-1.png new file mode 100644 index 0000000..d3eddd8 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/crazy-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/chromium/default-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/default-1.png new file mode 100644 index 0000000..9e5d5b4 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/default-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/chromium/overload-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/overload-1.png new file mode 100644 index 0000000..163f844 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/chromium/overload-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/firefox/crazy-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/crazy-1.png new file mode 100644 index 0000000..672ebbc Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/crazy-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/firefox/default-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/default-1.png new file mode 100644 index 0000000..e695f66 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/default-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/firefox/overload-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/overload-1.png new file mode 100644 index 0000000..5927b16 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/firefox/overload-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/crazy-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/crazy-1.png new file mode 100644 index 0000000..ccddf60 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/crazy-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/default-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/default-1.png new file mode 100644 index 0000000..4352f7b Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/default-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/overload-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/overload-1.png new file mode 100644 index 0000000..db2690b Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-chrome/overload-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/crazy-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/crazy-1.png new file mode 100644 index 0000000..9bbe4c8 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/crazy-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/default-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/default-1.png new file mode 100644 index 0000000..78c760e Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/default-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/overload-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/overload-1.png new file mode 100644 index 0000000..9fd58d1 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/mobile-safari/overload-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/webkit/crazy-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/crazy-1.png new file mode 100644 index 0000000..f2397f7 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/crazy-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/webkit/default-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/default-1.png new file mode 100644 index 0000000..ecc0fd4 Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/default-1.png differ diff --git a/test-harness/tests/__screenshots__/tests.spec.ts/webkit/overload-1.png b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/overload-1.png new file mode 100644 index 0000000..e2c587d Binary files /dev/null and b/test-harness/tests/__screenshots__/tests.spec.ts/webkit/overload-1.png differ diff --git a/index.html b/test-harness/tests/index.html similarity index 80% rename from index.html rename to test-harness/tests/index.html index 5cf9055..8c59305 100644 --- a/index.html +++ b/test-harness/tests/index.html @@ -8,7 +8,7 @@ body { margin: 0; padding: 0; - font-family: sans-serif; + font-family: "Open Sans"; background: #f0f0f0; height: 100vh; } @@ -16,6 +16,6 @@
- + diff --git a/test-harness/tests/main.tsx b/test-harness/tests/main.tsx new file mode 100644 index 0000000..a6900de --- /dev/null +++ b/test-harness/tests/main.tsx @@ -0,0 +1,18 @@ +import React, { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Backgammon } from "../../src/components/Backgammon"; +import { positionsPresets, themePresets } from "./presets"; +import "@fontsource/open-sans"; + +const urlParams = new URLSearchParams(window.location.search); +const position = urlParams.get("position"); +const positions = positionsPresets[position!]; + +const themeParam = urlParams.get("theme"); +const theme = themePresets[themeParam!]; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/test-harness/tests/presets.ts b/test-harness/tests/presets.ts new file mode 100644 index 0000000..739ca79 --- /dev/null +++ b/test-harness/tests/presets.ts @@ -0,0 +1,109 @@ +import { BoardStateState, Theme } from "../../src/types"; + +const randomPositions = () => { + const takenByPlayer = new Map(); + const takenByOpponent = new Map(); + + const getPosition = (isPlayer) => { + const pos = Math.floor(Math.random() * 25) + 1; + return isPlayer && pos === 25 ? 0 : pos; + }; + + const placeChecker = (isPlayer) => { + const position = getPosition(isPlayer); + + if (isPlayer) { + if (takenByOpponent.has(position)) { + placeChecker(true); + } else if (takenByPlayer.has(position)) { + takenByPlayer.set(position, takenByPlayer.get(position) + 1); + } else { + takenByPlayer.set(position, 1); + } + } else { + if (takenByPlayer.has(position)) { + placeChecker(false); + } else if (takenByOpponent.has(position)) { + takenByOpponent.set(position, takenByOpponent.get(position) + 1); + } else { + takenByOpponent.set(position, 1); + } + } + }; + + Array.from({ length: 30 }).forEach((_, i) => placeChecker(i % 2 === 0)); + + return [ + ...Array.from(takenByPlayer.entries()).map( + ([position, numberOfCheckers]) => ({ + position, + playerType: "player", + numberOfCheckers, + }), + ), + ...Array.from(takenByOpponent.entries()).map( + ([position, numberOfCheckers]) => ({ + position, + playerType: "opponent", + numberOfCheckers, + }), + ), + ]; +}; + +export const positionsPresets: Record = { + default: [ + { position: 1, playerType: "opponent", numberOfCheckers: 2 }, + { position: 6, playerType: "player", numberOfCheckers: 5 }, + { position: 8, playerType: "player", numberOfCheckers: 3 }, + { position: 12, playerType: "opponent", numberOfCheckers: 5 }, + { position: 13, playerType: "player", numberOfCheckers: 5 }, + { position: 17, playerType: "opponent", numberOfCheckers: 3 }, + { position: 19, playerType: "opponent", numberOfCheckers: 5 }, + { position: 24, playerType: "player", numberOfCheckers: 2 }, + ], + overload: [ + { position: 0, playerType: "player", numberOfCheckers: 15 }, + { position: 1, playerType: "player", numberOfCheckers: 15 }, + { position: 2, playerType: "player", numberOfCheckers: 15 }, + { position: 3, playerType: "player", numberOfCheckers: 15 }, + { position: 4, playerType: "player", numberOfCheckers: 15 }, + { position: 5, playerType: "player", numberOfCheckers: 15 }, + { position: 6, playerType: "player", numberOfCheckers: 15 }, + { position: 7, playerType: "player", numberOfCheckers: 15 }, + { position: 8, playerType: "player", numberOfCheckers: 15 }, + { position: 9, playerType: "player", numberOfCheckers: 15 }, + { position: 10, playerType: "player", numberOfCheckers: 15 }, + { position: 11, playerType: "player", numberOfCheckers: 15 }, + { position: 12, playerType: "player", numberOfCheckers: 15 }, + { position: 13, playerType: "opponent", numberOfCheckers: 15 }, + { position: 14, playerType: "opponent", numberOfCheckers: 15 }, + { position: 15, playerType: "opponent", numberOfCheckers: 15 }, + { position: 16, playerType: "opponent", numberOfCheckers: 15 }, + { position: 17, playerType: "opponent", numberOfCheckers: 15 }, + { position: 18, playerType: "opponent", numberOfCheckers: 15 }, + { position: 19, playerType: "opponent", numberOfCheckers: 15 }, + { position: 20, playerType: "opponent", numberOfCheckers: 15 }, + { position: 21, playerType: "opponent", numberOfCheckers: 15 }, + { position: 22, playerType: "opponent", numberOfCheckers: 15 }, + { position: 23, playerType: "opponent", numberOfCheckers: 15 }, + { position: 24, playerType: "opponent", numberOfCheckers: 15 }, + { position: 25, playerType: "opponent", numberOfCheckers: 15 }, + ], + random: randomPositions(), +}; + +export const themePresets: Record = { + crazy: { + backgroundColor: "#f0f0f0", + borderColor: "red", + pointColor: "green", + pointNumberColor: "red", + altPointColor: "blue", + playerCheckerColor: "rebeccapurple", + playerCheckerBorderColor: "yellow", + opponentCheckerColor: "red", + opponentCheckerBorderColor: "green", + doublingCubeColor: "red", + }, +}; diff --git a/test-harness/tests/tests.spec.ts b/test-harness/tests/tests.spec.ts new file mode 100644 index 0000000..d7c1f84 --- /dev/null +++ b/test-harness/tests/tests.spec.ts @@ -0,0 +1,16 @@ +import { test, expect } from "@playwright/test"; + +test("overload", async ({ page }) => { + await page.goto("/tests/index.html?position=overload"); + await expect(page).toHaveScreenshot({ maxDiffPixelRatio: 0.01 }); +}); + +test("default", async ({ page }) => { + await page.goto("/tests/index.html?position=default"); + await expect(page).toHaveScreenshot({ maxDiffPixelRatio: 0.01 }); +}); + +test("crazy", async ({ page }) => { + await page.goto("/tests/index.html?position=default&theme=crazy"); + await expect(page).toHaveScreenshot({ maxDiffPixelRatio: 0.01 }); +}); diff --git a/test-harness/vite.config.ts b/test-harness/vite.config.ts new file mode 100644 index 0000000..a2cbc6b --- /dev/null +++ b/test-harness/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], + server: { + port: 3000, + open: "/tests/index.html", + }, +}); diff --git a/tsconfig.json b/tsconfig.json index b790f79..673a845 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,9 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "declaration": true, + "declarationDir": "dist", + "emitDeclarationOnly": true }, "include": ["src"] } diff --git a/vite.config.ts b/vite.config.ts index 0e43ae8..9ae73bc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,27 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; +import { resolve } from "path"; +import dts from "vite-plugin-dts"; // https://vite.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [react(), dts({ include: ["src"] })], + build: { + lib: { + entry: resolve(__dirname, "src/index.tsx"), + name: "BackgammonBoard", + fileName: (format) => `index.${format === "es" ? "js" : "umd.cjs"}`, + }, + // sourcemap: true, + rollupOptions: { + external: ["react", "react-dom"], + output: { + banner: `'use client';`, + globals: { + react: "React", + "react-dom": "ReactDOM", + }, + }, + }, + }, });