diff --git a/web/.gitignore b/web/.gitignore index fda67f1..4b6375c 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -22,6 +22,9 @@ chrome-dev-tools /.next/ /out/ +# sveltekit +/.svelte-kit/ + # production /build diff --git a/web/jsconfig.json b/web/jsconfig.json index 2a2e4b3..4be8af7 100644 --- a/web/jsconfig.json +++ b/web/jsconfig.json @@ -1,6 +1,12 @@ { + "extends": "./.svelte-kit/tsconfig.json", "compilerOptions": { + "allowJs": true, + "checkJs": false, + "module": "esnext", + "moduleResolution": "bundler", "paths": { + "$app/types": ["./.svelte-kit/types/index.d.ts"], "@/*": ["./*"] } } diff --git a/web/package.json b/web/package.json index bc2b25f..60ef9d4 100644 --- a/web/package.json +++ b/web/package.json @@ -2,14 +2,17 @@ "name": "loldle", "version": "0.1.0", "private": true, + "type": "module", "packageManager": "pnpm@11.1.1", "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", "lint": "eslint", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "next:dev": "next dev", + "next:build": "next build" }, "dependencies": { "next": "16.2.10", @@ -17,10 +20,16 @@ "react-dom": "19.2.7" }, "devDependencies": { + "@sveltejs/adapter-static": "^3.0.10", + "@sveltejs/kit": "^2.70.1", + "@sveltejs/vite-plugin-svelte": "^7.2.0", "@tailwindcss/postcss": "^4.3.3", + "@tailwindcss/vite": "^4.3.3", "eslint": "^9", "eslint-config-next": "16.2.10", + "svelte": "^5.56.7", "tailwindcss": "^4.3.3", + "vite": "^8.1.5", "vitest": "^4.1.10" } } diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 65bb00b..c9e840e 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -23,18 +23,36 @@ importers: specifier: 19.2.7 version: 19.2.7(react@19.2.7) devDependencies: + '@sveltejs/adapter-static': + specifier: ^3.0.10 + version: 3.0.10(@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)))(svelte@5.56.7(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.1.5(jiti@2.7.0))) + '@sveltejs/kit': + specifier: ^2.70.1 + version: 2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)))(svelte@5.56.7(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.1.5(jiti@2.7.0)) + '@sveltejs/vite-plugin-svelte': + specifier: ^7.2.0 + version: 7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)) '@tailwindcss/postcss': specifier: ^4.3.3 version: 4.3.3 + '@tailwindcss/vite': + specifier: ^4.3.3 + version: 4.3.3(vite@8.1.5(jiti@2.7.0)) eslint: specifier: ^9 version: 9.39.5(jiti@2.7.0) eslint-config-next: specifier: 16.2.10 version: 16.2.10(@typescript-eslint/parser@8.59.4(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3) + svelte: + specifier: ^5.56.7 + version: 5.56.7(@typescript-eslint/types@8.59.4) tailwindcss: specifier: ^4.3.3 version: 4.3.3 + vite: + specifier: ^8.1.5 + version: 8.1.5(jiti@2.7.0) vitest: specifier: ^4.1.10 version: 4.1.10(vite@8.1.5(jiti@2.7.0)) @@ -463,6 +481,9 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@rolldown/binding-android-arm64@1.1.5': resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -567,6 +588,39 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@sveltejs/acorn-typescript@1.0.11': + resolution: {integrity: sha512-LFuZUkjJ9iF7JZye/aG5XM0SFcQ5VyL0oVX4WJ9dc0Va3R3s0OauX1BESVCb+YN/ol8TAfqGDDAQsTG627Y5kw==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/adapter-static@3.0.10': + resolution: {integrity: sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==} + peerDependencies: + '@sveltejs/kit': ^2.0.0 + + '@sveltejs/kit@2.70.1': + resolution: {integrity: sha512-nY9SPHGOZro3doud9vZXDBwl9tCZIouuJztjgSHs6PAIrv9M/z5O7eOhPV5xU7CgVHA976Jwu3BA1hIFvXztkA==} + engines: {node: '>=18.13'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.0.0 + '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + typescript: ^5.3.3 || ^6.0.0 + vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + typescript: + optional: true + + '@sveltejs/vite-plugin-svelte@7.2.0': + resolution: {integrity: sha512-1SpkuMSRLfugrVX+IrKfE1RUegzo8AQzKQ6qQPfVzbcWi5IhuTPaKb5ZrLpucleFznkc4/RTeSPoRnGWFxX+EQ==} + engines: {node: ^20.19 || ^22.12 || >=24} + peerDependencies: + svelte: ^5.46.4 + vite: ^8.0.0-beta.7 || ^8.0.0 + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -662,6 +716,11 @@ packages: '@tailwindcss/postcss@4.3.3': resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -671,6 +730,9 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -683,6 +745,9 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@typescript-eslint/eslint-plugin@8.59.4': resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -911,6 +976,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.1: + resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} + engines: {node: '>= 0.4'} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -1028,6 +1097,10 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1041,6 +1114,10 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1080,6 +1157,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -1092,6 +1173,9 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + devalue@5.8.2: + resolution: {integrity: sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA==} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1253,6 +1337,9 @@ packages: jiti: optional: true + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1261,6 +1348,14 @@ packages: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} + esrap@2.3.0: + resolution: {integrity: sha512-GQ/7RN8uOtEfNpzZzBMTzW9JBcX42oaSVtPzdF+6cEL8pqIL094iUpr9jzYGn4O4P/1S60dJ6izyT8F4LYARng==} + peerDependencies: + '@typescript-eslint/types': ^8.2.0 + peerDependenciesMeta: + '@typescript-eslint/types': + optional: true + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -1513,6 +1608,9 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1600,6 +1698,10 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -1685,6 +1787,9 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1724,6 +1829,10 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1944,6 +2053,9 @@ packages: engines: {node: '>=10'} hasBin: true + set-cookie-parser@3.1.2: + resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -1987,6 +2099,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2056,6 +2172,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svelte@5.56.7: + resolution: {integrity: sha512-5qERUZX80oQj6XrDMUmD2Uhd/cIpCPDWWKBK3ZHmyRUC9apPyamWM8xMo31mbWsIQxwG2hVoSnOJ/EcnhVkkzQ==} + engines: {node: '>=18'} + tailwindcss@4.3.3: resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} @@ -2086,6 +2206,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -2189,6 +2313,14 @@ packages: yaml: optional: true + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@4.1.10: resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2267,6 +2399,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} @@ -2663,6 +2798,8 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@polka/url@1.0.0-next.29': {} + '@rolldown/binding-android-arm64@1.1.5': optional: true @@ -2718,6 +2855,43 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@sveltejs/acorn-typescript@1.0.11(acorn@8.16.0)': + dependencies: + acorn: 8.16.0 + + '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)))(svelte@5.56.7(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.1.5(jiti@2.7.0)))': + dependencies: + '@sveltejs/kit': 2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)))(svelte@5.56.7(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.1.5(jiti@2.7.0)) + + '@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)))(svelte@5.56.7(@typescript-eslint/types@8.59.4))(typescript@6.0.3)(vite@8.1.5(jiti@2.7.0))': + dependencies: + '@standard-schema/spec': 1.1.0 + '@sveltejs/acorn-typescript': 1.0.11(acorn@8.16.0) + '@sveltejs/vite-plugin-svelte': 7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0)) + '@types/cookie': 0.6.0 + acorn: 8.16.0 + cookie: 0.6.0 + devalue: 5.8.2 + esm-env: 1.2.2 + kleur: 4.1.5 + magic-string: 0.30.21 + mrmime: 2.0.1 + set-cookie-parser: 3.1.2 + sirv: 3.0.2 + svelte: 5.56.7(@typescript-eslint/types@8.59.4) + vite: 8.1.5(jiti@2.7.0) + optionalDependencies: + typescript: 6.0.3 + + '@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.7(@typescript-eslint/types@8.59.4))(vite@8.1.5(jiti@2.7.0))': + dependencies: + deepmerge: 4.3.1 + magic-string: 0.30.21 + obug: 2.1.4 + svelte: 5.56.7(@typescript-eslint/types@8.59.4) + vite: 8.1.5(jiti@2.7.0) + vitefu: 1.1.3(vite@8.1.5(jiti@2.7.0)) + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -2791,6 +2965,13 @@ snapshots: postcss: 8.5.19 tailwindcss: 4.3.3 + '@tailwindcss/vite@4.3.3(vite@8.1.5(jiti@2.7.0))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.1.5(jiti@2.7.0) + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -2806,6 +2987,8 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/cookie@0.6.0': {} + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} @@ -2814,6 +2997,8 @@ snapshots: '@types/json5@0.0.29': {} + '@types/trusted-types@2.0.7': {} + '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -2883,7 +3068,7 @@ snapshots: debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: @@ -3035,6 +3220,8 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.1: {} + aria-query@5.3.2: {} array-buffer-byte-length@1.0.2: @@ -3175,6 +3362,8 @@ snapshots: client-only@0.0.1: {} + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3185,6 +3374,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie@0.6.0: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3221,6 +3412,8 @@ snapshots: deep-is@0.1.4: {} + deepmerge@4.3.1: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -3235,6 +3428,8 @@ snapshots: detect-libc@2.1.2: {} + devalue@5.8.2: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -3548,6 +3743,8 @@ snapshots: transitivePeerDependencies: - supports-color + esm-env@1.2.2: {} + espree@10.4.0: dependencies: acorn: 8.16.0 @@ -3558,6 +3755,12 @@ snapshots: dependencies: estraverse: 5.3.0 + esrap@2.3.0(@typescript-eslint/types@8.59.4): + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + optionalDependencies: + '@typescript-eslint/types': 8.59.4 + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -3594,6 +3797,10 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -3805,6 +4012,10 @@ snapshots: is-number@7.0.0: {} + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.9 + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -3890,6 +4101,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kleur@4.1.5: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -3950,6 +4163,8 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + locate-character@3.0.0: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3987,6 +4202,8 @@ snapshots: minimist@1.2.8: {} + mrmime@2.0.1: {} + ms@2.1.3: {} nanoid@3.3.12: {} @@ -4229,6 +4446,8 @@ snapshots: semver@7.8.1: {} + set-cookie-parser@3.1.2: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4319,6 +4538,12 @@ snapshots: siginfo@2.0.0: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + source-map-js@1.2.1: {} stable-hash@0.0.5: {} @@ -4399,6 +4624,27 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svelte@5.56.7(@typescript-eslint/types@8.59.4): + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.11(acorn@8.16.0) + '@types/estree': 1.0.9 + '@types/trusted-types': 2.0.7 + acorn: 8.16.0 + aria-query: 5.3.1 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.8.2 + esm-env: 1.2.2 + esrap: 2.3.0(@typescript-eslint/types@8.59.4) + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + transitivePeerDependencies: + - '@typescript-eslint/types' + tailwindcss@4.3.3: {} tapable@2.3.3: {} @@ -4414,8 +4660,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 tinyrainbow@3.1.0: {} @@ -4423,6 +4669,8 @@ snapshots: dependencies: is-number: 7.0.0 + totalist@3.0.1: {} + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: typescript: 6.0.3 @@ -4541,6 +4789,10 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 + vitefu@1.1.3(vite@8.1.5(jiti@2.7.0)): + optionalDependencies: + vite: 8.1.5(jiti@2.7.0) + vitest@4.1.10(vite@8.1.5(jiti@2.7.0)): dependencies: '@vitest/expect': 4.1.10 @@ -4622,6 +4874,8 @@ snapshots: yocto-queue@0.1.0: {} + zimmerframe@1.1.4: {} + zod-validation-error@4.0.2(zod@4.4.3): dependencies: zod: 4.4.3 diff --git a/web/src/app.css b/web/src/app.css new file mode 100644 index 0000000..b4d482e --- /dev/null +++ b/web/src/app.css @@ -0,0 +1,122 @@ +@import "tailwindcss"; + +:root { + --color-bg: #1a1a2e; + --color-surface: #16213e; + --color-surface-hover: #1a2745; + --color-text: #e0e0e0; + --color-text-muted: #8a8a9a; + --color-correct: #4ecb71; + --color-partial: #f4b35e; + --color-wrong: #d85b5b; + --color-header: #2a2a4a; + --color-input-bg: #0f3460; + --color-input-border: #533483; + --color-accent: #533483; + --cell-size: 90px; +} + +body { + background: var(--color-bg); + color: var(--color-text); + font-family: "Segoe UI", system-ui, -apple-system, sans-serif; + min-height: 100vh; +} + +/* Guess grid layout */ +.guess-row { + display: grid; + grid-template-columns: 130px repeat(7, var(--cell-size)); + gap: 4px; + margin-bottom: 4px; + min-width: fit-content; +} + +.guess-cell { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 8px 4px; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 500; + min-height: 56px; + word-break: break-word; + animation: cellReveal 0.3s ease forwards; + opacity: 0; +} + +.header-row { + margin-bottom: 8px; +} + +.header-cell { + background: var(--color-header); + color: var(--color-text-muted); + font-weight: 600; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.5px; + opacity: 1; + animation: none; +} + +.champion-cell { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-start; + padding-left: 8px; + background: var(--color-surface); +} + +.cell-correct { + background: var(--color-correct); + color: #1a1a2e; +} + +.cell-partial { + background: var(--color-partial); + color: #1a1a2e; +} + +.cell-wrong { + background: var(--color-wrong); + color: #fff; +} + +@keyframes cellReveal { + from { + opacity: 0; + transform: scale(0.8); + } + to { + opacity: 1; + transform: scale(1); + } +} + +/* Responsive */ +@media (max-width: 768px) { + :root { + --cell-size: 72px; + } + .guess-row { + grid-template-columns: 100px repeat(7, var(--cell-size)); + } + .guess-cell { + font-size: 0.7rem; + min-height: 48px; + padding: 6px 2px; + } +} + +@media (max-width: 480px) { + :root { + --cell-size: 60px; + } + .guess-row { + grid-template-columns: 80px repeat(7, var(--cell-size)); + } +} diff --git a/web/src/app.html b/web/src/app.html new file mode 100644 index 0000000..adf8bd8 --- /dev/null +++ b/web/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/web/src/routes/+layout.js b/web/src/routes/+layout.js new file mode 100644 index 0000000..189f71e --- /dev/null +++ b/web/src/routes/+layout.js @@ -0,0 +1 @@ +export const prerender = true; diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte new file mode 100644 index 0000000..a8dbb88 --- /dev/null +++ b/web/src/routes/+layout.svelte @@ -0,0 +1,12 @@ + + + + LoLdle + + + +{@render children()} diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte new file mode 100644 index 0000000..bbf213e --- /dev/null +++ b/web/src/routes/+page.svelte @@ -0,0 +1,9 @@ + +
+
+

+ LoLdle +

+
+
diff --git a/web/static/.nojekyll b/web/static/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/web/static/champions.json b/web/static/champions.json new file mode 100644 index 0000000..9c8a61d --- /dev/null +++ b/web/static/champions.json @@ -0,0 +1,3803 @@ +[ + { + "id": "Aatrox", + "name": "Aatrox", + "title": "the Darkin Blade", + "resource": "Blood Well", + "genre": "Fighter", + "skinCount": 41, + "image": { + "full": "Aatrox.png", + "sprite": "champion0.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2013, + "region": "runeterra", + "lane": "top" + }, + { + "id": "Ahri", + "name": "Ahri", + "title": "the Nine-Tailed Fox", + "resource": "Mana", + "genre": "Mage,Assassin", + "skinCount": 95, + "image": { + "full": "Ahri.png", + "sprite": "champion0.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2011, + "region": "ionia", + "lane": "mid" + }, + { + "id": "Akali", + "name": "Akali", + "title": "the Rogue Assassin", + "resource": "Energy", + "genre": "Assassin", + "skinCount": 101, + "image": { + "full": "Akali.png", + "sprite": "champion0.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2010, + "region": "ionia", + "lane": "top,mid" + }, + { + "id": "Akshan", + "name": "Akshan", + "title": "the Rogue Sentinel", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 30, + "image": { + "full": "Akshan.png", + "sprite": "champion0.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2021, + "region": "shurima", + "lane": "mid" + }, + { + "id": "Alistar", + "name": "Alistar", + "title": "the Minotaur", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 46, + "image": { + "full": "Alistar.png", + "sprite": "champion0.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "runeterra", + "lane": "support" + }, + { + "id": "Ambessa", + "name": "Ambessa", + "title": "Matriarch of War", + "resource": "Energy", + "genre": "Fighter,Assassin", + "skinCount": 15, + "image": { + "full": "Ambessa.png", + "sprite": "champion0.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2024, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Amumu", + "name": "Amumu", + "title": "the Sad Mummy", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 62, + "image": { + "full": "Amumu.png", + "sprite": "champion0.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "shurima", + "lane": "jungle" + }, + { + "id": "Anivia", + "name": "Anivia", + "title": "the Cryophoenix", + "resource": "Mana", + "genre": "Mage", + "skinCount": 55, + "image": { + "full": "Anivia.png", + "sprite": "champion0.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "freljord", + "lane": "mid" + }, + { + "id": "Annie", + "name": "Annie", + "title": "the Dark Child", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 59, + "image": { + "full": "Annie.png", + "sprite": "champion0.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "runeterra", + "lane": "mid" + }, + { + "id": "Aphelios", + "name": "Aphelios", + "title": "the Weapon of the Faithful", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 40, + "image": { + "full": "Aphelios.png", + "sprite": "champion0.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2019, + "region": "mount-targon", + "lane": "bottom" + }, + { + "id": "Ashe", + "name": "Ashe", + "title": "the Frost Archer", + "resource": "Mana", + "genre": "Marksman,Support", + "skinCount": 93, + "image": { + "full": "Ashe.png", + "sprite": "champion0.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "freljord", + "lane": "bottom,support" + }, + { + "id": "AurelionSol", + "name": "Aurelion Sol", + "title": "The Star Forger", + "resource": "Mana", + "genre": "Mage", + "skinCount": 38, + "image": { + "full": "AurelionSol.png", + "sprite": "champion0.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2016, + "region": "mount-targon", + "lane": "mid" + }, + { + "id": "Aurora", + "name": "Aurora", + "title": "the Witch Between Worlds", + "resource": "Mana", + "genre": "Mage,Assassin", + "skinCount": 29, + "image": { + "full": "Aurora.png", + "sprite": "champion0.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2024, + "region": "freljord", + "lane": "top,mid" + }, + { + "id": "Azir", + "name": "Azir", + "title": "the Emperor of the Sands", + "resource": "Mana", + "genre": "Mage,Marksman", + "skinCount": 28, + "image": { + "full": "Azir.png", + "sprite": "champion0.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2014, + "region": "shurima", + "lane": "mid" + }, + { + "id": "Bard", + "name": "Bard", + "title": "the Wandering Caretaker", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 46, + "image": { + "full": "Bard.png", + "sprite": "champion0.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2015, + "region": "runeterra", + "lane": "support" + }, + { + "id": "Belveth", + "name": "Bel'Veth", + "title": "the Empress of the Void", + "resource": "", + "genre": "Fighter", + "skinCount": 29, + "image": { + "full": "Belveth.png", + "sprite": "champion0.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2022, + "region": "void", + "lane": "jungle" + }, + { + "id": "Blitzcrank", + "name": "Blitzcrank", + "title": "the Great Steam Golem", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 74, + "image": { + "full": "Blitzcrank.png", + "sprite": "champion0.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "zaun", + "lane": "support" + }, + { + "id": "Brand", + "name": "Brand", + "title": "the Burning Vengeance", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 54, + "image": { + "full": "Brand.png", + "sprite": "champion0.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2011, + "region": "runeterra", + "lane": "jungle,support" + }, + { + "id": "Braum", + "name": "Braum", + "title": "the Heart of the Freljord", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 61, + "image": { + "full": "Braum.png", + "sprite": "champion0.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2014, + "region": "freljord", + "lane": "support" + }, + { + "id": "Briar", + "name": "Briar", + "title": "the Restrained Hunger", + "resource": "Fury", + "genre": "Fighter,Assassin", + "skinCount": 29, + "image": { + "full": "Briar.png", + "sprite": "champion0.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2023, + "region": "noxus", + "lane": "jungle" + }, + { + "id": "Caitlyn", + "name": "Caitlyn", + "title": "the Sheriff of Piltover", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 63, + "image": { + "full": "Caitlyn.png", + "sprite": "champion0.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2011, + "region": "piltover", + "lane": "bottom" + }, + { + "id": "Camille", + "name": "Camille", + "title": "the Steel Shadow", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 53, + "image": { + "full": "Camille.png", + "sprite": "champion0.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2016, + "region": "piltover", + "lane": "top" + }, + { + "id": "Cassiopeia", + "name": "Cassiopeia", + "title": "the Serpent's Embrace", + "resource": "Mana", + "genre": "Mage", + "skinCount": 38, + "image": { + "full": "Cassiopeia.png", + "sprite": "champion0.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2010, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Chogath", + "name": "Cho'Gath", + "title": "the Terror of the Void", + "resource": "Mana", + "genre": "Tank,Mage", + "skinCount": 42, + "image": { + "full": "Chogath.png", + "sprite": "champion0.png", + "group": "champion", + "x": 144, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "divers", + "attackType": "close", + "releaseDate": 2009, + "region": "void", + "lane": "top" + }, + { + "id": "Corki", + "name": "Corki", + "title": "the Daring Bombardier", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 45, + "image": { + "full": "Corki.png", + "sprite": "champion0.png", + "group": "champion", + "x": 192, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "bandle-city", + "lane": "mid" + }, + { + "id": "Darius", + "name": "Darius", + "title": "the Hand of Noxus", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 73, + "image": { + "full": "Darius.png", + "sprite": "champion0.png", + "group": "champion", + "x": 240, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "noxus", + "lane": "top" + }, + { + "id": "Diana", + "name": "Diana", + "title": "Scorn of the Moon", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 83, + "image": { + "full": "Diana.png", + "sprite": "champion0.png", + "group": "champion", + "x": 288, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2012, + "region": "mount-targon", + "lane": "jungle,mid" + }, + { + "id": "DrMundo", + "name": "Dr. Mundo", + "title": "the Madman of Zaun", + "resource": "None", + "genre": "Tank,Fighter", + "skinCount": 30, + "image": { + "full": "DrMundo.png", + "sprite": "champion0.png", + "group": "champion", + "x": 384, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "zaun", + "lane": "top" + }, + { + "id": "Draven", + "name": "Draven", + "title": "the Glorious Executioner", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 78, + "image": { + "full": "Draven.png", + "sprite": "champion0.png", + "group": "champion", + "x": 336, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2012, + "region": "noxus", + "lane": "bottom" + }, + { + "id": "Ekko", + "name": "Ekko", + "title": "the Boy Who Shattered Time", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 59, + "image": { + "full": "Ekko.png", + "sprite": "champion0.png", + "group": "champion", + "x": 432, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2015, + "region": "zaun", + "lane": "jungle,mid" + }, + { + "id": "Elise", + "name": "Elise", + "title": "the Spider Queen", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 36, + "image": { + "full": "Elise.png", + "sprite": "champion1.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2012, + "region": "shadow-isles", + "lane": "jungle" + }, + { + "id": "Evelynn", + "name": "Evelynn", + "title": "Agony's Embrace", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 65, + "image": { + "full": "Evelynn.png", + "sprite": "champion1.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2009, + "region": "runeterra", + "lane": "jungle" + }, + { + "id": "Ezreal", + "name": "Ezreal", + "title": "the Prodigal Explorer", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 76, + "image": { + "full": "Ezreal.png", + "sprite": "champion1.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2010, + "region": "piltover", + "lane": "bottom" + }, + { + "id": "Fiddlesticks", + "name": "Fiddlesticks", + "title": "the Ancient Fear", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 55, + "image": { + "full": "Fiddlesticks.png", + "sprite": "champion1.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "runeterra", + "lane": "jungle" + }, + { + "id": "Fiora", + "name": "Fiora", + "title": "the Grand Duelist", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 100, + "image": { + "full": "Fiora.png", + "sprite": "champion1.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2012, + "region": "demacia", + "lane": "top" + }, + { + "id": "Fizz", + "name": "Fizz", + "title": "the Tidal Trickster", + "resource": "Mana", + "genre": "Assassin,Fighter", + "skinCount": 44, + "image": { + "full": "Fizz.png", + "sprite": "champion1.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "bilgewater", + "lane": "mid" + }, + { + "id": "Galio", + "name": "Galio", + "title": "the Colossus", + "resource": "Mana", + "genre": "Tank,Mage", + "skinCount": 54, + "image": { + "full": "Galio.png", + "sprite": "champion1.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "demacia", + "lane": "mid" + }, + { + "id": "Gangplank", + "name": "Gangplank", + "title": "the Saltwater Scourge", + "resource": "Mana", + "genre": "Fighter", + "skinCount": 42, + "image": { + "full": "Gangplank.png", + "sprite": "champion1.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "bilgewater", + "lane": "top" + }, + { + "id": "Garen", + "name": "Garen", + "title": "The Might of Demacia", + "resource": "None", + "genre": "Fighter,Tank", + "skinCount": 54, + "image": { + "full": "Garen.png", + "sprite": "champion1.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "demacia", + "lane": "top" + }, + { + "id": "Gnar", + "name": "Gnar", + "title": "the Missing Link", + "resource": "Rage", + "genre": "Fighter,Tank", + "skinCount": 44, + "image": { + "full": "Gnar.png", + "sprite": "champion1.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2014, + "region": "freljord", + "lane": "top" + }, + { + "id": "Gragas", + "name": "Gragas", + "title": "the Rabble Rouser", + "resource": "Mana", + "genre": "Fighter,Mage", + "skinCount": 48, + "image": { + "full": "Gragas.png", + "sprite": "champion1.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "freljord", + "lane": "jungle" + }, + { + "id": "Graves", + "name": "Graves", + "title": "the Outlaw", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 54, + "image": { + "full": "Graves.png", + "sprite": "champion1.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "bilgewater", + "lane": "jungle" + }, + { + "id": "Gwen", + "name": "Gwen", + "title": "The Hallowed Seamstress", + "resource": "Mana", + "genre": "Fighter", + "skinCount": 48, + "image": { + "full": "Gwen.png", + "sprite": "champion1.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2021, + "region": "shadow-isles", + "lane": "top" + }, + { + "id": "Hecarim", + "name": "Hecarim", + "title": "the Shadow of War", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 50, + "image": { + "full": "Hecarim.png", + "sprite": "champion1.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "shadow-isles", + "lane": "jungle" + }, + { + "id": "Heimerdinger", + "name": "Heimerdinger", + "title": "the Revered Inventor", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 27, + "image": { + "full": "Heimerdinger.png", + "sprite": "champion1.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "piltover", + "lane": "support" + }, + { + "id": "Hwei", + "name": "Hwei", + "title": "the Visionary", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 22, + "image": { + "full": "Hwei.png", + "sprite": "champion1.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2023, + "region": "ionia", + "lane": "mid,support" + }, + { + "id": "Illaoi", + "name": "Illaoi", + "title": "the Kraken Priestess", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 46, + "image": { + "full": "Illaoi.png", + "sprite": "champion1.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2015, + "region": "bilgewater", + "lane": "top" + }, + { + "id": "Irelia", + "name": "Irelia", + "title": "the Blade Dancer", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 72, + "image": { + "full": "Irelia.png", + "sprite": "champion1.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2010, + "region": "ionia", + "lane": "top,mid" + }, + { + "id": "Ivern", + "name": "Ivern", + "title": "the Green Father", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 39, + "image": { + "full": "Ivern.png", + "sprite": "champion1.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2016, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Janna", + "name": "Janna", + "title": "the Storm's Fury", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 67, + "image": { + "full": "Janna.png", + "sprite": "champion1.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "zaun", + "lane": "support" + }, + { + "id": "JarvanIV", + "name": "Jarvan IV", + "title": "the Exemplar of Demacia", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 55, + "image": { + "full": "JarvanIV.png", + "sprite": "champion1.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "demacia", + "lane": "jungle" + }, + { + "id": "Jax", + "name": "Jax", + "title": "Grandmaster at Arms", + "resource": "Mana", + "genre": "Fighter", + "skinCount": 42, + "image": { + "full": "Jax.png", + "sprite": "champion1.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "runeterra", + "lane": "top,jungle" + }, + { + "id": "Jayce", + "name": "Jayce", + "title": "the Defender of Tomorrow", + "resource": "Mana", + "genre": "Fighter,Marksman", + "skinCount": 47, + "image": { + "full": "Jayce.png", + "sprite": "champion1.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "piltover", + "lane": "top" + }, + { + "id": "Jhin", + "name": "Jhin", + "title": "the Virtuoso", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 63, + "image": { + "full": "Jhin.png", + "sprite": "champion1.png", + "group": "champion", + "x": 144, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2016, + "region": "ionia", + "lane": "bottom" + }, + { + "id": "Jinx", + "name": "Jinx", + "title": "the Loose Cannon", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 64, + "image": { + "full": "Jinx.png", + "sprite": "champion1.png", + "group": "champion", + "x": 192, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2013, + "region": "zaun", + "lane": "bottom" + }, + { + "id": "KSante", + "name": "K'Sante", + "title": "the Pride of Nazumah", + "resource": "Mana", + "genre": "Tank,Fighter", + "skinCount": 18, + "image": { + "full": "KSante.png", + "sprite": "champion2.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2022, + "region": "shurima", + "lane": "top" + }, + { + "id": "Kaisa", + "name": "Kai'Sa", + "title": "Daughter of the Void", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 79, + "image": { + "full": "Kaisa.png", + "sprite": "champion1.png", + "group": "champion", + "x": 240, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2018, + "region": "void", + "lane": "bottom" + }, + { + "id": "Kalista", + "name": "Kalista", + "title": "the Spear of Vengeance", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 33, + "image": { + "full": "Kalista.png", + "sprite": "champion1.png", + "group": "champion", + "x": 288, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2014, + "region": "shadow-isles", + "lane": "bottom" + }, + { + "id": "Karma", + "name": "Karma", + "title": "the Enlightened One", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 76, + "image": { + "full": "Karma.png", + "sprite": "champion1.png", + "group": "champion", + "x": 336, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2011, + "region": "ionia", + "lane": "mid,support" + }, + { + "id": "Karthus", + "name": "Karthus", + "title": "the Deathsinger", + "resource": "Mana", + "genre": "Mage", + "skinCount": 44, + "image": { + "full": "Karthus.png", + "sprite": "champion1.png", + "group": "champion", + "x": 384, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "shadow-isles", + "lane": "jungle" + }, + { + "id": "Kassadin", + "name": "Kassadin", + "title": "the Void Walker", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 32, + "image": { + "full": "Kassadin.png", + "sprite": "champion1.png", + "group": "champion", + "x": 432, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "void", + "lane": "mid" + }, + { + "id": "Katarina", + "name": "Katarina", + "title": "the Sinister Blade", + "resource": "None", + "genre": "Assassin,Mage", + "skinCount": 78, + "image": { + "full": "Katarina.png", + "sprite": "champion2.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2009, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Kayle", + "name": "Kayle", + "title": "the Righteous", + "resource": "Mana", + "genre": "Mage,Marksman", + "skinCount": 88, + "image": { + "full": "Kayle.png", + "sprite": "champion2.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2009, + "region": "demacia", + "lane": "top" + }, + { + "id": "Kayn", + "name": "Kayn", + "title": "the Shadow Reaper", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 31, + "image": { + "full": "Kayn.png", + "sprite": "champion2.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2017, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Kennen", + "name": "Kennen", + "title": "the Heart of the Tempest", + "resource": "Energy", + "genre": "Mage", + "skinCount": 34, + "image": { + "full": "Kennen.png", + "sprite": "champion2.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2010, + "region": "ionia", + "lane": "top" + }, + { + "id": "Khazix", + "name": "Kha'Zix", + "title": "the Voidreaver", + "resource": "Mana", + "genre": "Assassin", + "skinCount": 58, + "image": { + "full": "Khazix.png", + "sprite": "champion2.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "void", + "lane": "jungle" + }, + { + "id": "Kindred", + "name": "Kindred", + "title": "The Eternal Hunters", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 44, + "image": { + "full": "Kindred.png", + "sprite": "champion2.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2015, + "region": "runeterra", + "lane": "jungle" + }, + { + "id": "Kled", + "name": "Kled", + "title": "the Cantankerous Cavalier", + "resource": "Courage", + "genre": "Fighter", + "skinCount": 27, + "image": { + "full": "Kled.png", + "sprite": "champion2.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2016, + "region": "noxus", + "lane": "top" + }, + { + "id": "KogMaw", + "name": "Kog'Maw", + "title": "the Mouth of the Abyss", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 65, + "image": { + "full": "KogMaw.png", + "sprite": "champion2.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2010, + "region": "void", + "lane": "bottom" + }, + { + "id": "Leblanc", + "name": "LeBlanc", + "title": "the Deceiver", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 61, + "image": { + "full": "Leblanc.png", + "sprite": "champion2.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2010, + "region": "noxus", + "lane": "mid" + }, + { + "id": "LeeSin", + "name": "Lee Sin", + "title": "the Blind Monk", + "resource": "Energy", + "genre": "Fighter,Assassin", + "skinCount": 80, + "image": { + "full": "LeeSin.png", + "sprite": "champion2.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Leona", + "name": "Leona", + "title": "the Radiant Dawn", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 71, + "image": { + "full": "Leona.png", + "sprite": "champion2.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2011, + "region": "mount-targon", + "lane": "support" + }, + { + "id": "Lillia", + "name": "Lillia", + "title": "the Bashful Bloom", + "resource": "Mana", + "genre": "Fighter,Mage", + "skinCount": 53, + "image": { + "full": "Lillia.png", + "sprite": "champion2.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2020, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Lissandra", + "name": "Lissandra", + "title": "the Ice Witch", + "resource": "Mana", + "genre": "Mage", + "skinCount": 52, + "image": { + "full": "Lissandra.png", + "sprite": "champion2.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2013, + "region": "freljord", + "lane": "mid" + }, + { + "id": "Locke", + "name": "Locke", + "title": "the Ashen Exorcist", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 10, + "image": { + "full": "Locke.png", + "sprite": "champion2.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "region": "demacia" + }, + { + "id": "Lucian", + "name": "Lucian", + "title": "the Purifier", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 73, + "image": { + "full": "Lucian.png", + "sprite": "champion2.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2013, + "region": "demacia", + "lane": "bottom" + }, + { + "id": "Lulu", + "name": "Lulu", + "title": "the Fae Sorceress", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 56, + "image": { + "full": "Lulu.png", + "sprite": "champion2.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2012, + "region": "bandle-city", + "lane": "support" + }, + { + "id": "Lux", + "name": "Lux", + "title": "the Lady of Luminosity", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 81, + "image": { + "full": "Lux.png", + "sprite": "champion2.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2010, + "region": "demacia", + "lane": "mid,support" + }, + { + "id": "Malphite", + "name": "Malphite", + "title": "Shard of the Monolith", + "resource": "Mana", + "genre": "Tank,Mage", + "skinCount": 57, + "image": { + "full": "Malphite.png", + "sprite": "champion2.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "ixtal", + "lane": "top" + }, + { + "id": "Malzahar", + "name": "Malzahar", + "title": "the Prophet of the Void", + "resource": "Mana", + "genre": "Mage", + "skinCount": 58, + "image": { + "full": "Malzahar.png", + "sprite": "champion2.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2010, + "region": "void", + "lane": "mid" + }, + { + "id": "Maokai", + "name": "Maokai", + "title": "the Twisted Treant", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 36, + "image": { + "full": "Maokai.png", + "sprite": "champion2.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "shadow-isles", + "lane": "support" + }, + { + "id": "MasterYi", + "name": "Master Yi", + "title": "the Wuju Bladesman", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 90, + "image": { + "full": "MasterYi.png", + "sprite": "champion2.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Mel", + "name": "Mel", + "title": "the Soul's Reflection", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 12, + "image": { + "full": "Mel.png", + "sprite": "champion2.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2025, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Milio", + "name": "Milio", + "title": "The Gentle Flame", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 29, + "image": { + "full": "Milio.png", + "sprite": "champion2.png", + "group": "champion", + "x": 144, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2023, + "region": "ixtal", + "lane": "support" + }, + { + "id": "MissFortune", + "name": "Miss Fortune", + "title": "the Bounty Hunter", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 76, + "image": { + "full": "MissFortune.png", + "sprite": "champion2.png", + "group": "champion", + "x": 192, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2010, + "region": "bilgewater", + "lane": "bottom" + }, + { + "id": "Mordekaiser", + "name": "Mordekaiser", + "title": "the Iron Revenant", + "resource": "Shield", + "genre": "Fighter,Mage", + "skinCount": 57, + "image": { + "full": "Mordekaiser.png", + "sprite": "champion2.png", + "group": "champion", + "x": 288, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "noxus", + "lane": "top" + }, + { + "id": "Morgana", + "name": "Morgana", + "title": "the Fallen", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 82, + "image": { + "full": "Morgana.png", + "sprite": "champion2.png", + "group": "champion", + "x": 336, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2009, + "region": "demacia", + "lane": "support" + }, + { + "id": "Naafiri", + "name": "Naafiri", + "title": "the Hound of a Hundred Bites", + "resource": "Mana", + "genre": "Assassin,Fighter", + "skinCount": 38, + "image": { + "full": "Naafiri.png", + "sprite": "champion2.png", + "group": "champion", + "x": 384, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2023, + "region": "shurima", + "lane": "mid" + }, + { + "id": "Nami", + "name": "Nami", + "title": "the Tidecaller", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 68, + "image": { + "full": "Nami.png", + "sprite": "champion2.png", + "group": "champion", + "x": 432, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2012, + "region": "runeterra", + "lane": "support" + }, + { + "id": "Nasus", + "name": "Nasus", + "title": "the Curator of the Sands", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 63, + "image": { + "full": "Nasus.png", + "sprite": "champion3.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "shurima", + "lane": "top" + }, + { + "id": "Nautilus", + "name": "Nautilus", + "title": "the Titan of the Depths", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 46, + "image": { + "full": "Nautilus.png", + "sprite": "champion3.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "bilgewater", + "lane": "support" + }, + { + "id": "Neeko", + "name": "Neeko", + "title": "the Curious Chameleon", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 50, + "image": { + "full": "Neeko.png", + "sprite": "champion3.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2018, + "region": "ixtal", + "lane": "mid,support" + }, + { + "id": "Nidalee", + "name": "Nidalee", + "title": "the Bestial Huntress", + "resource": "Mana", + "genre": "Assassin,Mage", + "skinCount": 67, + "image": { + "full": "Nidalee.png", + "sprite": "champion3.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "ixtal", + "lane": "jungle" + }, + { + "id": "Nilah", + "name": "Nilah", + "title": "the Joy Unbound", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 30, + "image": { + "full": "Nilah.png", + "sprite": "champion3.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2022, + "region": "runeterra", + "lane": "bottom" + }, + { + "id": "Nocturne", + "name": "Nocturne", + "title": "the Eternal Nightmare", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 36, + "image": { + "full": "Nocturne.png", + "sprite": "champion3.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "divers", + "attackType": "close", + "releaseDate": 2011, + "region": "runeterra", + "lane": "jungle" + }, + { + "id": "Nunu", + "name": "Nunu & Willump", + "title": "the Boy and His Yeti", + "resource": "Mana", + "genre": "Tank,Mage", + "skinCount": 54, + "image": { + "full": "Nunu.png", + "sprite": "champion3.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "freljord", + "lane": "jungle" + }, + { + "id": "Olaf", + "name": "Olaf", + "title": "the Berserker", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 53, + "image": { + "full": "Olaf.png", + "sprite": "champion3.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "freljord", + "lane": "top" + }, + { + "id": "Orianna", + "name": "Orianna", + "title": "the Lady of Clockwork", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 40, + "image": { + "full": "Orianna.png", + "sprite": "champion3.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2011, + "region": "piltover", + "lane": "mid" + }, + { + "id": "Ornn", + "name": "Ornn", + "title": "The Fire below the Mountain", + "resource": "Mana", + "genre": "Tank", + "skinCount": 38, + "image": { + "full": "Ornn.png", + "sprite": "champion3.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2017, + "region": "freljord", + "lane": "top" + }, + { + "id": "Pantheon", + "name": "Pantheon", + "title": "the Unbreakable Spear", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 47, + "image": { + "full": "Pantheon.png", + "sprite": "champion3.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "mount-targon", + "lane": "top,support" + }, + { + "id": "Poppy", + "name": "Poppy", + "title": "Keeper of the Hammer", + "resource": "Mana", + "genre": "Tank,Fighter", + "skinCount": 51, + "image": { + "full": "Poppy.png", + "sprite": "champion3.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2010, + "region": "demacia", + "lane": "top,jungle" + }, + { + "id": "Pyke", + "name": "Pyke", + "title": "the Bloodharbor Ripper", + "resource": "Mana", + "genre": "Support,Assassin", + "skinCount": 85, + "image": { + "full": "Pyke.png", + "sprite": "champion3.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2018, + "region": "bilgewater", + "lane": "support" + }, + { + "id": "Qiyana", + "name": "Qiyana", + "title": "Empress of the Elements", + "resource": "Mana", + "genre": "Assassin", + "skinCount": 51, + "image": { + "full": "Qiyana.png", + "sprite": "champion3.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2019, + "region": "ixtal", + "lane": "mid" + }, + { + "id": "Quinn", + "name": "Quinn", + "title": "Demacia's Wings", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 33, + "image": { + "full": "Quinn.png", + "sprite": "champion3.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2013, + "region": "demacia", + "lane": "top" + }, + { + "id": "Rakan", + "name": "Rakan", + "title": "The Charmer", + "resource": "Mana", + "genre": "Support", + "skinCount": 58, + "image": { + "full": "Rakan.png", + "sprite": "champion3.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2017, + "region": "ionia", + "lane": "support" + }, + { + "id": "Rammus", + "name": "Rammus", + "title": "the Armordillo", + "resource": "Mana", + "genre": "Tank", + "skinCount": 35, + "image": { + "full": "Rammus.png", + "sprite": "champion3.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "shurima", + "lane": "jungle" + }, + { + "id": "RekSai", + "name": "Rek'Sai", + "title": "the Void Burrower", + "resource": "Rage", + "genre": "Fighter,Tank", + "skinCount": 36, + "image": { + "full": "RekSai.png", + "sprite": "champion3.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2014, + "region": "void", + "lane": "jungle" + }, + { + "id": "Rell", + "name": "Rell", + "title": "the Iron Maiden", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 31, + "image": { + "full": "Rell.png", + "sprite": "champion3.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2020, + "region": "noxus", + "lane": "support" + }, + { + "id": "Renata", + "name": "Renata Glasc", + "title": "the Chem-Baroness", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 32, + "image": { + "full": "Renata.png", + "sprite": "champion3.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2022, + "region": "zaun", + "lane": "support" + }, + { + "id": "Renekton", + "name": "Renekton", + "title": "the Butcher of the Sands", + "resource": "Fury", + "genre": "Fighter,Tank", + "skinCount": 57, + "image": { + "full": "Renekton.png", + "sprite": "champion3.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "shurima", + "lane": "top" + }, + { + "id": "Rengar", + "name": "Rengar", + "title": "the Pridestalker", + "resource": "Ferocity", + "genre": "Assassin,Fighter", + "skinCount": 59, + "image": { + "full": "Rengar.png", + "sprite": "champion3.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "ixtal", + "lane": "jungle" + }, + { + "id": "Riven", + "name": "Riven", + "title": "the Exile", + "resource": "None", + "genre": "Fighter,Assassin", + "skinCount": 73, + "image": { + "full": "Riven.png", + "sprite": "champion3.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2011, + "region": "noxus", + "lane": "top" + }, + { + "id": "Rumble", + "name": "Rumble", + "title": "the Mechanized Menace", + "resource": "Heat", + "genre": "Fighter,Mage", + "skinCount": 32, + "image": { + "full": "Rumble.png", + "sprite": "champion3.png", + "group": "champion", + "x": 144, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "bandle-city", + "lane": "top" + }, + { + "id": "Ryze", + "name": "Ryze", + "title": "the Rune Mage", + "resource": "Mana", + "genre": "Mage", + "skinCount": 39, + "image": { + "full": "Ryze.png", + "sprite": "champion3.png", + "group": "champion", + "x": 192, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "runeterra", + "lane": "mid" + }, + { + "id": "Samira", + "name": "Samira", + "title": "the Desert Rose", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 42, + "image": { + "full": "Samira.png", + "sprite": "champion3.png", + "group": "champion", + "x": 240, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2020, + "region": "noxus", + "lane": "bottom" + }, + { + "id": "Sejuani", + "name": "Sejuani", + "title": "Fury of the North", + "resource": "Mana", + "genre": "Tank", + "skinCount": 57, + "image": { + "full": "Sejuani.png", + "sprite": "champion3.png", + "group": "champion", + "x": 288, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2012, + "region": "freljord", + "lane": "jungle" + }, + { + "id": "Senna", + "name": "Senna", + "title": "the Redeemer", + "resource": "Mana", + "genre": "Support,Marksman", + "skinCount": 80, + "image": { + "full": "Senna.png", + "sprite": "champion3.png", + "group": "champion", + "x": 336, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2019, + "region": "runeterra", + "lane": "bottom,support" + }, + { + "id": "Seraphine", + "name": "Seraphine", + "title": "the Starry-Eyed Songstress", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 75, + "image": { + "full": "Seraphine.png", + "sprite": "champion3.png", + "group": "champion", + "x": 384, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2020, + "region": "piltover", + "lane": "bottom,support" + }, + { + "id": "Sett", + "name": "Sett", + "title": "the Boss", + "resource": "Grit", + "genre": "Fighter,Tank", + "skinCount": 76, + "image": { + "full": "Sett.png", + "sprite": "champion3.png", + "group": "champion", + "x": 432, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2020, + "region": "ionia", + "lane": "top" + }, + { + "id": "Shaco", + "name": "Shaco", + "title": "the Demon Jester", + "resource": "Mana", + "genre": "Assassin", + "skinCount": 73, + "image": { + "full": "Shaco.png", + "sprite": "champion4.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "runeterra", + "lane": "jungle" + }, + { + "id": "Shen", + "name": "Shen", + "title": "the Eye of Twilight", + "resource": "Energy", + "genre": "Tank", + "skinCount": 62, + "image": { + "full": "Shen.png", + "sprite": "champion4.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "ionia", + "lane": "top" + }, + { + "id": "Shyvana", + "name": "Shyvana", + "title": "the Half-Dragon", + "resource": "Fury", + "genre": "Fighter,Tank", + "skinCount": 26, + "image": { + "full": "Shyvana.png", + "sprite": "champion4.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2011, + "region": "demacia", + "lane": "jungle" + }, + { + "id": "Singed", + "name": "Singed", + "title": "the Mad Chemist", + "resource": "Mana", + "genre": "Tank,Mage", + "skinCount": 29, + "image": { + "full": "Singed.png", + "sprite": "champion4.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "zaun", + "lane": "top" + }, + { + "id": "Sion", + "name": "Sion", + "title": "The Undead Juggernaut", + "resource": "Mana", + "genre": "Tank,Fighter", + "skinCount": 59, + "image": { + "full": "Sion.png", + "sprite": "champion4.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "noxus", + "lane": "top" + }, + { + "id": "Sivir", + "name": "Sivir", + "title": "the Battle Mistress", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 81, + "image": { + "full": "Sivir.png", + "sprite": "champion4.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "shurima", + "lane": "bottom" + }, + { + "id": "Skarner", + "name": "Skarner", + "title": "the Primordial Sovereign", + "resource": "Mana", + "genre": "Tank,Fighter", + "skinCount": 15, + "image": { + "full": "Skarner.png", + "sprite": "champion4.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "ixtal", + "lane": "top,jungle" + }, + { + "id": "Smolder", + "name": "Smolder", + "title": "the Fiery Fledgling", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 20, + "image": { + "full": "Smolder.png", + "sprite": "champion4.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2024, + "region": "runeterra", + "lane": "bottom" + }, + { + "id": "Sona", + "name": "Sona", + "title": "Maven of the Strings", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 77, + "image": { + "full": "Sona.png", + "sprite": "champion4.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2010, + "region": "demacia", + "lane": "support" + }, + { + "id": "Soraka", + "name": "Soraka", + "title": "the Starchild", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 63, + "image": { + "full": "Soraka.png", + "sprite": "champion4.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "mount-targon", + "lane": "support" + }, + { + "id": "Swain", + "name": "Swain", + "title": "the Noxian Grand General", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 51, + "image": { + "full": "Swain.png", + "sprite": "champion4.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2010, + "region": "noxus", + "lane": "support" + }, + { + "id": "Sylas", + "name": "Sylas", + "title": "the Unshackled", + "resource": "Mana", + "genre": "Mage,Assassin", + "skinCount": 54, + "image": { + "full": "Sylas.png", + "sprite": "champion4.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2019, + "region": "demacia", + "lane": "mid" + }, + { + "id": "Syndra", + "name": "Syndra", + "title": "the Dark Sovereign", + "resource": "Mana", + "genre": "Mage", + "skinCount": 74, + "image": { + "full": "Syndra.png", + "sprite": "champion4.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2012, + "region": "ionia", + "lane": "mid" + }, + { + "id": "TahmKench", + "name": "Tahm Kench", + "title": "The River King", + "resource": "Mana", + "genre": "Tank,Support", + "skinCount": 47, + "image": { + "full": "TahmKench.png", + "sprite": "champion4.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2015, + "region": "bilgewater", + "lane": "top" + }, + { + "id": "Taliyah", + "name": "Taliyah", + "title": "the Stoneweaver", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 25, + "image": { + "full": "Taliyah.png", + "sprite": "champion4.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2016, + "region": "shurima", + "lane": "jungle" + }, + { + "id": "Talon", + "name": "Talon", + "title": "the Blade's Shadow", + "resource": "Mana", + "genre": "Assassin", + "skinCount": 60, + "image": { + "full": "Talon.png", + "sprite": "champion4.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Taric", + "name": "Taric", + "title": "the Shield of Valoran", + "resource": "Mana", + "genre": "Support,Tank", + "skinCount": 36, + "image": { + "full": "Taric.png", + "sprite": "champion4.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "mount-targon", + "lane": "support" + }, + { + "id": "Teemo", + "name": "Teemo", + "title": "the Swift Scout", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 63, + "image": { + "full": "Teemo.png", + "sprite": "champion4.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "bandle-city", + "lane": "top" + }, + { + "id": "Thresh", + "name": "Thresh", + "title": "the Chain Warden", + "resource": "Mana", + "genre": "Support,Tank", + "skinCount": 68, + "image": { + "full": "Thresh.png", + "sprite": "champion4.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2013, + "region": "shadow-isles", + "lane": "support" + }, + { + "id": "Tristana", + "name": "Tristana", + "title": "the Yordle Gunner", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 79, + "image": { + "full": "Tristana.png", + "sprite": "champion4.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2009, + "region": "bandle-city", + "lane": "bottom" + }, + { + "id": "Trundle", + "name": "Trundle", + "title": "the Troll King", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 30, + "image": { + "full": "Trundle.png", + "sprite": "champion4.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "freljord", + "lane": "top" + }, + { + "id": "Tryndamere", + "name": "Tryndamere", + "title": "the Barbarian King", + "resource": "Fury", + "genre": "Fighter,Assassin", + "skinCount": 47, + "image": { + "full": "Tryndamere.png", + "sprite": "champion4.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "freljord", + "lane": "top" + }, + { + "id": "TwistedFate", + "name": "Twisted Fate", + "title": "the Card Master", + "resource": "Mana", + "genre": "Mage,Marksman", + "skinCount": 54, + "image": { + "full": "TwistedFate.png", + "sprite": "champion4.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "bilgewater", + "lane": "mid,bottom" + }, + { + "id": "Twitch", + "name": "Twitch", + "title": "the Plague Rat", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 59, + "image": { + "full": "Twitch.png", + "sprite": "champion4.png", + "group": "champion", + "x": 144, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "zaun", + "lane": "bottom" + }, + { + "id": "Udyr", + "name": "Udyr", + "title": "the Spirit Walker", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 12, + "image": { + "full": "Udyr.png", + "sprite": "champion4.png", + "group": "champion", + "x": 192, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "freljord", + "lane": "top,jungle" + }, + { + "id": "Urgot", + "name": "Urgot", + "title": "the Dreadnought", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 41, + "image": { + "full": "Urgot.png", + "sprite": "champion4.png", + "group": "champion", + "x": 240, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "zaun", + "lane": "top" + }, + { + "id": "Varus", + "name": "Varus", + "title": "the Arrow of Retribution", + "resource": "Mana", + "genre": "Marksman,Mage", + "skinCount": 71, + "image": { + "full": "Varus.png", + "sprite": "champion4.png", + "group": "champion", + "x": 288, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2012, + "region": "ionia", + "lane": "bottom" + }, + { + "id": "Vayne", + "name": "Vayne", + "title": "the Night Hunter", + "resource": "Mana", + "genre": "Marksman,Assassin", + "skinCount": 74, + "image": { + "full": "Vayne.png", + "sprite": "champion4.png", + "group": "champion", + "x": 336, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2011, + "region": "demacia", + "lane": "bottom" + }, + { + "id": "Veigar", + "name": "Veigar", + "title": "the Tiny Master of Evil", + "resource": "Mana", + "genre": "Mage", + "skinCount": 67, + "image": { + "full": "Veigar.png", + "sprite": "champion4.png", + "group": "champion", + "x": 384, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "bandle-city", + "lane": "mid" + }, + { + "id": "Velkoz", + "name": "Vel'Koz", + "title": "the Eye of the Void", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 36, + "image": { + "full": "Velkoz.png", + "sprite": "champion4.png", + "group": "champion", + "x": 432, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2014, + "region": "void", + "lane": "support" + }, + { + "id": "Vex", + "name": "Vex", + "title": "the Gloomist", + "resource": "Mana", + "genre": "Mage", + "skinCount": 38, + "image": { + "full": "Vex.png", + "sprite": "champion5.png", + "group": "champion", + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2021, + "region": "shadow-isles", + "lane": "mid" + }, + { + "id": "Vi", + "name": "Vi", + "title": "the Piltover Enforcer", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 51, + "image": { + "full": "Vi.png", + "sprite": "champion5.png", + "group": "champion", + "x": 48, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2012, + "region": "piltover", + "lane": "jungle" + }, + { + "id": "Viego", + "name": "Viego", + "title": "The Ruined King", + "resource": "None", + "genre": "Fighter,Assassin", + "skinCount": 43, + "image": { + "full": "Viego.png", + "sprite": "champion5.png", + "group": "champion", + "x": 96, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2021, + "region": "shadow-isles", + "lane": "jungle" + }, + { + "id": "Viktor", + "name": "Viktor", + "title": "the Herald of the Arcane", + "resource": "Mana", + "genre": "Mage", + "skinCount": 34, + "image": { + "full": "Viktor.png", + "sprite": "champion5.png", + "group": "champion", + "x": 144, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2011, + "region": "zaun", + "lane": "mid" + }, + { + "id": "Vladimir", + "name": "Vladimir", + "title": "the Crimson Reaper", + "resource": "Crimson Rush", + "genre": "Mage,Fighter", + "skinCount": 58, + "image": { + "full": "Vladimir.png", + "sprite": "champion5.png", + "group": "champion", + "x": 192, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "noxus", + "lane": "mid" + }, + { + "id": "Volibear", + "name": "Volibear", + "title": "the Relentless Storm", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 37, + "image": { + "full": "Volibear.png", + "sprite": "champion5.png", + "group": "champion", + "x": 240, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "freljord", + "lane": "top" + }, + { + "id": "Warwick", + "name": "Warwick", + "title": "the Uncaged Wrath of Zaun", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 61, + "image": { + "full": "Warwick.png", + "sprite": "champion5.png", + "group": "champion", + "x": 288, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2009, + "region": "zaun", + "lane": "jungle" + }, + { + "id": "MonkeyKing", + "name": "Wukong", + "title": "the Monkey King", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 36, + "image": { + "full": "MonkeyKing.png", + "sprite": "champion2.png", + "group": "champion", + "x": 240, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "ionia", + "lane": "jungle" + }, + { + "id": "Xayah", + "name": "Xayah", + "title": "the Rebel", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 65, + "image": { + "full": "Xayah.png", + "sprite": "champion5.png", + "group": "champion", + "x": 336, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2017, + "region": "ionia", + "lane": "bottom" + }, + { + "id": "Xerath", + "name": "Xerath", + "title": "the Magus Ascendant", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 33, + "image": { + "full": "Xerath.png", + "sprite": "champion5.png", + "group": "champion", + "x": 384, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2011, + "region": "shurima", + "lane": "mid,support" + }, + { + "id": "XinZhao", + "name": "Xin Zhao", + "title": "the Seneschal of Demacia", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 59, + "image": { + "full": "XinZhao.png", + "sprite": "champion5.png", + "group": "champion", + "x": 432, + "y": 0, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2010, + "region": "demacia", + "lane": "jungle" + }, + { + "id": "Yasuo", + "name": "Yasuo", + "title": "the Unforgiven", + "resource": "Flow", + "genre": "Fighter,Assassin", + "skinCount": 97, + "image": { + "full": "Yasuo.png", + "sprite": "champion5.png", + "group": "champion", + "x": 0, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2013, + "region": "ionia", + "lane": "top,mid,bottom" + }, + { + "id": "Yone", + "name": "Yone", + "title": "the Unforgotten", + "resource": "Flow", + "genre": "Fighter,Assassin", + "skinCount": 76, + "image": { + "full": "Yone.png", + "sprite": "champion5.png", + "group": "champion", + "x": 48, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2020, + "region": "ionia", + "lane": "top,mid" + }, + { + "id": "Yorick", + "name": "Yorick", + "title": "Shepherd of Souls", + "resource": "Mana", + "genre": "Fighter,Tank", + "skinCount": 59, + "image": { + "full": "Yorick.png", + "sprite": "champion5.png", + "group": "champion", + "x": 96, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2011, + "region": "shadow-isles", + "lane": "top" + }, + { + "id": "Yunara", + "name": "Yunara", + "title": "the Unbroken Faith", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 17, + "image": { + "full": "Yunara.png", + "sprite": "champion5.png", + "group": "champion", + "x": 144, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2026, + "region": "ionia" + }, + { + "id": "Yuumi", + "name": "Yuumi", + "title": "the Magical Cat", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 79, + "image": { + "full": "Yuumi.png", + "sprite": "champion5.png", + "group": "champion", + "x": 192, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "close", + "releaseDate": 2019, + "region": "bandle-city", + "lane": "support" + }, + { + "id": "Zaahen", + "name": "Zaahen", + "title": "The Unsundered", + "resource": "Mana", + "genre": "Fighter,Assassin", + "skinCount": 10, + "image": { + "full": "Zaahen.png", + "sprite": "champion5.png", + "group": "champion", + "x": 240, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "region": "runeterra" + }, + { + "id": "Zac", + "name": "Zac", + "title": "the Secret Weapon", + "resource": "None", + "genre": "Tank,Fighter", + "skinCount": 42, + "image": { + "full": "Zac.png", + "sprite": "champion5.png", + "group": "champion", + "x": 288, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2013, + "region": "zaun", + "lane": "jungle" + }, + { + "id": "Zed", + "name": "Zed", + "title": "the Master of Shadows", + "resource": "Energy", + "genre": "Assassin", + "skinCount": 71, + "image": { + "full": "Zed.png", + "sprite": "champion5.png", + "group": "champion", + "x": 336, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "close", + "releaseDate": 2012, + "region": "ionia", + "lane": "mid" + }, + { + "id": "Zeri", + "name": "Zeri", + "title": "The Spark of Zaun", + "resource": "Mana", + "genre": "Marksman", + "skinCount": 47, + "image": { + "full": "Zeri.png", + "sprite": "champion5.png", + "group": "champion", + "x": 384, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2022, + "region": "zaun", + "lane": "bottom" + }, + { + "id": "Ziggs", + "name": "Ziggs", + "title": "the Hexplosives Expert", + "resource": "Mana", + "genre": "Mage", + "skinCount": 52, + "image": { + "full": "Ziggs.png", + "sprite": "champion5.png", + "group": "champion", + "x": 432, + "y": 48, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2012, + "region": "zaun", + "lane": "bottom" + }, + { + "id": "Zilean", + "name": "Zilean", + "title": "the Chronokeeper", + "resource": "Mana", + "genre": "Support,Mage", + "skinCount": 33, + "image": { + "full": "Zilean.png", + "sprite": "champion5.png", + "group": "champion", + "x": 0, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "male", + "attackType": "range", + "releaseDate": 2009, + "region": "runeterra", + "lane": "support" + }, + { + "id": "Zoe", + "name": "Zoe", + "title": "the Aspect of Twilight", + "resource": "Mana", + "genre": "Mage", + "skinCount": 45, + "image": { + "full": "Zoe.png", + "sprite": "champion5.png", + "group": "champion", + "x": 48, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2017, + "region": "mount-targon", + "lane": "mid" + }, + { + "id": "Zyra", + "name": "Zyra", + "title": "Rise of the Thorns", + "resource": "Mana", + "genre": "Mage,Support", + "skinCount": 74, + "image": { + "full": "Zyra.png", + "sprite": "champion5.png", + "group": "champion", + "x": 96, + "y": 96, + "w": 48, + "h": 48 + }, + "gender": "female", + "attackType": "range", + "releaseDate": 2012, + "region": "ixtal", + "lane": "support" + } +] diff --git a/web/svelte.config.js b/web/svelte.config.js new file mode 100644 index 0000000..78ac63d --- /dev/null +++ b/web/svelte.config.js @@ -0,0 +1,15 @@ +import adapter from "@sveltejs/adapter-static"; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + // No options: output goes to build/. No fallback either — every route is + // prerendered, so a fallback page would mask a real prerender failure. + adapter: adapter(), + paths: { + base: process.env.BASE_PATH || "", + }, + }, +}; + +export default config; diff --git a/web/vite.config.js b/web/vite.config.js new file mode 100644 index 0000000..ebfff1b --- /dev/null +++ b/web/vite.config.js @@ -0,0 +1,8 @@ +import { sveltekit } from "@sveltejs/kit/vite"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vite"; + +export default defineConfig({ + // tailwindcss() must precede sveltekit(), per the Tailwind v4 SvelteKit guide. + plugins: [tailwindcss(), sveltekit()], +});