chore: updated cli and build script to include multiple frameworks
1773e86e
36 file(s) · +2378 −17
| 1 | 1 | { |
|
| 2 | 2 | "components": "src/components", |
|
| 3 | - | "includeTypes": true |
|
| 3 | + | "includeTypes": true, |
|
| 4 | + | "framework": "react" |
|
| 4 | 5 | } |
| 1 | + | # Logs |
|
| 2 | + | logs |
|
| 3 | + | *.log |
|
| 4 | + | npm-debug.log* |
|
| 5 | + | yarn-debug.log* |
|
| 6 | + | yarn-error.log* |
|
| 7 | + | pnpm-debug.log* |
|
| 8 | + | lerna-debug.log* |
|
| 9 | + | ||
| 10 | + | node_modules |
|
| 11 | + | dist |
|
| 12 | + | dist-ssr |
|
| 13 | + | *.local |
|
| 14 | + | ||
| 15 | + | # Editor directories and files |
|
| 16 | + | .vscode/* |
|
| 17 | + | !.vscode/extensions.json |
|
| 18 | + | .idea |
|
| 19 | + | .DS_Store |
|
| 20 | + | *.suo |
|
| 21 | + | *.ntvs* |
|
| 22 | + | *.njsproj |
|
| 23 | + | *.sln |
|
| 24 | + | *.sw? |
| 1 | + | # Svelte + TS + Vite |
|
| 2 | + | ||
| 3 | + | This template should help get you started developing with Svelte and TypeScript in Vite. |
|
| 4 | + | ||
| 5 | + | ## Recommended IDE Setup |
|
| 6 | + | ||
| 7 | + | [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). |
|
| 8 | + | ||
| 9 | + | ## Need an official Svelte framework? |
|
| 10 | + | ||
| 11 | + | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more. |
|
| 12 | + | ||
| 13 | + | ## Technical considerations |
|
| 14 | + | ||
| 15 | + | **Why use this over SvelteKit?** |
|
| 16 | + | ||
| 17 | + | - It brings its own routing solution which might not be preferable for some users. |
|
| 18 | + | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. |
|
| 19 | + | ||
| 20 | + | This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project. |
|
| 21 | + | ||
| 22 | + | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate. |
|
| 23 | + | ||
| 24 | + | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** |
|
| 25 | + | ||
| 26 | + | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information. |
|
| 27 | + | ||
| 28 | + | **Why include `.vscode/extensions.json`?** |
|
| 29 | + | ||
| 30 | + | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project. |
|
| 31 | + | ||
| 32 | + | **Why enable `allowJs` in the TS template?** |
|
| 33 | + | ||
| 34 | + | While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant. |
|
| 35 | + | ||
| 36 | + | **Why is HMR not preserving my local component state?** |
|
| 37 | + | ||
| 38 | + | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr). |
|
| 39 | + | ||
| 40 | + | If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR. |
|
| 41 | + | ||
| 42 | + | ```ts |
|
| 43 | + | // store.ts |
|
| 44 | + | // An extremely simple external store |
|
| 45 | + | import { writable } from 'svelte/store' |
|
| 46 | + | export default writable(0) |
|
| 47 | + | ``` |
| 1 | + | { |
|
| 2 | + | "lockfileVersion": 1, |
|
| 3 | + | "workspaces": { |
|
| 4 | + | "": { |
|
| 5 | + | "name": "vite-svelte", |
|
| 6 | + | "devDependencies": { |
|
| 7 | + | "@sveltejs/vite-plugin-svelte": "^6.2.1", |
|
| 8 | + | "@tsconfig/svelte": "^5.0.5", |
|
| 9 | + | "@types/node": "^24.6.0", |
|
| 10 | + | "svelte": "^5.39.6", |
|
| 11 | + | "svelte-check": "^4.3.2", |
|
| 12 | + | "typescript": "~5.9.3", |
|
| 13 | + | "vite": "^7.1.7", |
|
| 14 | + | }, |
|
| 15 | + | }, |
|
| 16 | + | }, |
|
| 17 | + | "packages": { |
|
| 18 | + | "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="], |
|
| 19 | + | ||
| 20 | + | "@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="], |
|
| 21 | + | ||
| 22 | + | "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="], |
|
| 23 | + | ||
| 24 | + | "@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="], |
|
| 25 | + | ||
| 26 | + | "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="], |
|
| 27 | + | ||
| 28 | + | "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="], |
|
| 29 | + | ||
| 30 | + | "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="], |
|
| 31 | + | ||
| 32 | + | "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="], |
|
| 33 | + | ||
| 34 | + | "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="], |
|
| 35 | + | ||
| 36 | + | "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="], |
|
| 37 | + | ||
| 38 | + | "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="], |
|
| 39 | + | ||
| 40 | + | "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="], |
|
| 41 | + | ||
| 42 | + | "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="], |
|
| 43 | + | ||
| 44 | + | "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="], |
|
| 45 | + | ||
| 46 | + | "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="], |
|
| 47 | + | ||
| 48 | + | "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="], |
|
| 49 | + | ||
| 50 | + | "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="], |
|
| 51 | + | ||
| 52 | + | "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="], |
|
| 53 | + | ||
| 54 | + | "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="], |
|
| 55 | + | ||
| 56 | + | "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="], |
|
| 57 | + | ||
| 58 | + | "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="], |
|
| 59 | + | ||
| 60 | + | "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="], |
|
| 61 | + | ||
| 62 | + | "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="], |
|
| 63 | + | ||
| 64 | + | "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="], |
|
| 65 | + | ||
| 66 | + | "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="], |
|
| 67 | + | ||
| 68 | + | "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="], |
|
| 69 | + | ||
| 70 | + | "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], |
|
| 71 | + | ||
| 72 | + | "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], |
|
| 73 | + | ||
| 74 | + | "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], |
|
| 75 | + | ||
| 76 | + | "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], |
|
| 77 | + | ||
| 78 | + | "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], |
|
| 79 | + | ||
| 80 | + | "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="], |
|
| 81 | + | ||
| 82 | + | "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="], |
|
| 83 | + | ||
| 84 | + | "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="], |
|
| 85 | + | ||
| 86 | + | "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="], |
|
| 87 | + | ||
| 88 | + | "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="], |
|
| 89 | + | ||
| 90 | + | "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="], |
|
| 91 | + | ||
| 92 | + | "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="], |
|
| 93 | + | ||
| 94 | + | "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="], |
|
| 95 | + | ||
| 96 | + | "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="], |
|
| 97 | + | ||
| 98 | + | "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="], |
|
| 99 | + | ||
| 100 | + | "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="], |
|
| 101 | + | ||
| 102 | + | "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="], |
|
| 103 | + | ||
| 104 | + | "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="], |
|
| 105 | + | ||
| 106 | + | "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="], |
|
| 107 | + | ||
| 108 | + | "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="], |
|
| 109 | + | ||
| 110 | + | "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], |
|
| 111 | + | ||
| 112 | + | "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="], |
|
| 113 | + | ||
| 114 | + | "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="], |
|
| 115 | + | ||
| 116 | + | "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="], |
|
| 117 | + | ||
| 118 | + | "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="], |
|
| 119 | + | ||
| 120 | + | "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="], |
|
| 121 | + | ||
| 122 | + | "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="], |
|
| 123 | + | ||
| 124 | + | "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="], |
|
| 125 | + | ||
| 126 | + | "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="], |
|
| 127 | + | ||
| 128 | + | "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="], |
|
| 129 | + | ||
| 130 | + | "@tsconfig/svelte": ["@tsconfig/svelte@5.0.5", "", {}, "sha512-48fAnUjKye38FvMiNOj0J9I/4XlQQiZlpe9xaNPfe8vy2Y1hFBt8g1yqf2EGjVvHavo4jf2lC+TQyENCr4BJBQ=="], |
|
| 131 | + | ||
| 132 | + | "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], |
|
| 133 | + | ||
| 134 | + | "@types/node": ["@types/node@24.8.1", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q=="], |
|
| 135 | + | ||
| 136 | + | "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], |
|
| 137 | + | ||
| 138 | + | "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], |
|
| 139 | + | ||
| 140 | + | "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], |
|
| 141 | + | ||
| 142 | + | "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], |
|
| 143 | + | ||
| 144 | + | "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], |
|
| 145 | + | ||
| 146 | + | "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], |
|
| 147 | + | ||
| 148 | + | "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], |
|
| 149 | + | ||
| 150 | + | "esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="], |
|
| 151 | + | ||
| 152 | + | "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], |
|
| 153 | + | ||
| 154 | + | "esrap": ["esrap@2.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA=="], |
|
| 155 | + | ||
| 156 | + | "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], |
|
| 157 | + | ||
| 158 | + | "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], |
|
| 159 | + | ||
| 160 | + | "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], |
|
| 161 | + | ||
| 162 | + | "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], |
|
| 163 | + | ||
| 164 | + | "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], |
|
| 165 | + | ||
| 166 | + | "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], |
|
| 167 | + | ||
| 168 | + | "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], |
|
| 169 | + | ||
| 170 | + | "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], |
|
| 171 | + | ||
| 172 | + | "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], |
|
| 173 | + | ||
| 174 | + | "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|
| 175 | + | ||
| 176 | + | "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], |
|
| 177 | + | ||
| 178 | + | "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], |
|
| 179 | + | ||
| 180 | + | "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="], |
|
| 181 | + | ||
| 182 | + | "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], |
|
| 183 | + | ||
| 184 | + | "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], |
|
| 185 | + | ||
| 186 | + | "svelte": ["svelte@5.41.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-mP3vFFv5OUM5JN189+nJVW74kQ1dGqUrXTEzvCEVZqessY0GxZDls1nWVvt4Sxyv2USfQvAZO68VRaeIZvpzKg=="], |
|
| 187 | + | ||
| 188 | + | "svelte-check": ["svelte-check@4.3.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg=="], |
|
| 189 | + | ||
| 190 | + | "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], |
|
| 191 | + | ||
| 192 | + | "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], |
|
| 193 | + | ||
| 194 | + | "undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="], |
|
| 195 | + | ||
| 196 | + | "vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], |
|
| 197 | + | ||
| 198 | + | "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], |
|
| 199 | + | ||
| 200 | + | "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], |
|
| 201 | + | } |
|
| 202 | + | } |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en"> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|
| 6 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 7 | + | <title>vite-svelte</title> |
|
| 8 | + | </head> |
|
| 9 | + | <body> |
|
| 10 | + | <div id="app"></div> |
|
| 11 | + | <script type="module" src="/src/main.ts"></script> |
|
| 12 | + | </body> |
|
| 13 | + | </html> |
| 1 | + | { |
|
| 2 | + | "components": "src/components", |
|
| 3 | + | "includeTypes": true, |
|
| 4 | + | "framework": "svelte" |
|
| 5 | + | } |
| 1 | + | { |
|
| 2 | + | "name": "vite-svelte", |
|
| 3 | + | "private": true, |
|
| 4 | + | "version": "0.0.0", |
|
| 5 | + | "type": "module", |
|
| 6 | + | "scripts": { |
|
| 7 | + | "dev": "vite", |
|
| 8 | + | "build": "vite build", |
|
| 9 | + | "preview": "vite preview", |
|
| 10 | + | "check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json" |
|
| 11 | + | }, |
|
| 12 | + | "devDependencies": { |
|
| 13 | + | "@sveltejs/vite-plugin-svelte": "^6.2.1", |
|
| 14 | + | "@tsconfig/svelte": "^5.0.5", |
|
| 15 | + | "@types/node": "^24.6.0", |
|
| 16 | + | "svelte": "^5.39.6", |
|
| 17 | + | "svelte-check": "^4.3.2", |
|
| 18 | + | "typescript": "~5.9.3", |
|
| 19 | + | "vite": "^7.1.7" |
|
| 20 | + | } |
|
| 21 | + | } |
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> |
| 1 | + | <script lang="ts"> |
|
| 2 | + | import svelteLogo from "./assets/svelte.svg"; |
|
| 3 | + | import viteLogo from "/vite.svg"; |
|
| 4 | + | import Counter from "./lib/Counter.svelte"; |
|
| 5 | + | import "./components/connect-wallet"; |
|
| 6 | + | </script> |
|
| 7 | + | ||
| 8 | + | <main> |
|
| 9 | + | <div> |
|
| 10 | + | <a href="https://vite.dev" target="_blank" rel="noreferrer"> |
|
| 11 | + | <img src={viteLogo} class="logo" alt="Vite Logo" /> |
|
| 12 | + | </a> |
|
| 13 | + | <a href="https://svelte.dev" target="_blank" rel="noreferrer"> |
|
| 14 | + | <img src={svelteLogo} class="logo svelte" alt="Svelte Logo" /> |
|
| 15 | + | </a> |
|
| 16 | + | </div> |
|
| 17 | + | <h1>Vite + Svelte</h1> |
|
| 18 | + | ||
| 19 | + | <div class="card"> |
|
| 20 | + | <connect-wallet |
|
| 21 | + | chain-id='11155111' |
|
| 22 | + | ></connect-wallet> |
|
| 23 | + | </div> |
|
| 24 | + | ||
| 25 | + | <p> |
|
| 26 | + | Check out <a href="https://github.com/sveltejs/kit#readme" target="_blank" rel="noreferrer">SvelteKit</a>, the official Svelte app framework powered by Vite! |
|
| 27 | + | </p> |
|
| 28 | + | ||
| 29 | + | <p class="read-the-docs"> |
|
| 30 | + | Click on the Vite and Svelte logos to learn more |
|
| 31 | + | </p> |
|
| 32 | + | </main> |
|
| 33 | + | ||
| 34 | + | <style> |
|
| 35 | + | .logo { |
|
| 36 | + | height: 6em; |
|
| 37 | + | padding: 1.5em; |
|
| 38 | + | will-change: filter; |
|
| 39 | + | transition: filter 300ms; |
|
| 40 | + | } |
|
| 41 | + | .logo:hover { |
|
| 42 | + | filter: drop-shadow(0 0 2em #646cffaa); |
|
| 43 | + | } |
|
| 44 | + | .logo.svelte:hover { |
|
| 45 | + | filter: drop-shadow(0 0 2em #ff3e00aa); |
|
| 46 | + | } |
|
| 47 | + | .read-the-docs { |
|
| 48 | + | color: #888; |
|
| 49 | + | } |
|
| 50 | + | </style> |
| 1 | + | :root { |
|
| 2 | + | font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; |
|
| 3 | + | line-height: 1.5; |
|
| 4 | + | font-weight: 400; |
|
| 5 | + | ||
| 6 | + | color-scheme: light dark; |
|
| 7 | + | color: rgba(255, 255, 255, 0.87); |
|
| 8 | + | background-color: #242424; |
|
| 9 | + | ||
| 10 | + | font-synthesis: none; |
|
| 11 | + | text-rendering: optimizeLegibility; |
|
| 12 | + | -webkit-font-smoothing: antialiased; |
|
| 13 | + | -moz-osx-font-smoothing: grayscale; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | a { |
|
| 17 | + | font-weight: 500; |
|
| 18 | + | color: #646cff; |
|
| 19 | + | text-decoration: inherit; |
|
| 20 | + | } |
|
| 21 | + | a:hover { |
|
| 22 | + | color: #535bf2; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | body { |
|
| 26 | + | margin: 0; |
|
| 27 | + | display: flex; |
|
| 28 | + | place-items: center; |
|
| 29 | + | min-width: 320px; |
|
| 30 | + | min-height: 100vh; |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | h1 { |
|
| 34 | + | font-size: 3.2em; |
|
| 35 | + | line-height: 1.1; |
|
| 36 | + | } |
|
| 37 | + | ||
| 38 | + | .card { |
|
| 39 | + | padding: 2em; |
|
| 40 | + | } |
|
| 41 | + | ||
| 42 | + | #app { |
|
| 43 | + | max-width: 1280px; |
|
| 44 | + | margin: 0 auto; |
|
| 45 | + | padding: 2rem; |
|
| 46 | + | text-align: center; |
|
| 47 | + | } |
|
| 48 | + | ||
| 49 | + | button { |
|
| 50 | + | border-radius: 8px; |
|
| 51 | + | border: 1px solid transparent; |
|
| 52 | + | padding: 0.6em 1.2em; |
|
| 53 | + | font-size: 1em; |
|
| 54 | + | font-weight: 500; |
|
| 55 | + | font-family: inherit; |
|
| 56 | + | background-color: #1a1a1a; |
|
| 57 | + | cursor: pointer; |
|
| 58 | + | transition: border-color 0.25s; |
|
| 59 | + | } |
|
| 60 | + | button:hover { |
|
| 61 | + | border-color: #646cff; |
|
| 62 | + | } |
|
| 63 | + | button:focus, |
|
| 64 | + | button:focus-visible { |
|
| 65 | + | outline: 4px auto -webkit-focus-ring-color; |
|
| 66 | + | } |
|
| 67 | + | ||
| 68 | + | @media (prefers-color-scheme: light) { |
|
| 69 | + | :root { |
|
| 70 | + | color: #213547; |
|
| 71 | + | background-color: #ffffff; |
|
| 72 | + | } |
|
| 73 | + | a:hover { |
|
| 74 | + | color: #747bff; |
|
| 75 | + | } |
|
| 76 | + | button { |
|
| 77 | + | background-color: #f9f9f9; |
|
| 78 | + | } |
|
| 79 | + | } |
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg> |
| 1 | + | /** |
|
| 2 | + | * @fileoverview ConnectWallet Web Component - A customizable wallet connection component |
|
| 3 | + | * that supports Ethereum wallet integration with ENS resolution, balance display, and |
|
| 4 | + | * multi-chain support. |
|
| 5 | + | * |
|
| 6 | + | */ |
|
| 7 | + | ||
| 8 | + | /** |
|
| 9 | + | * ConnectWallet - A Web Component for Ethereum wallet connection and management |
|
| 10 | + | * |
|
| 11 | + | * This component provides a complete wallet connection interface with the following features: |
|
| 12 | + | * - Connect/disconnect wallet functionality |
|
| 13 | + | * - ENS name resolution and avatar display |
|
| 14 | + | * - Balance fetching and display |
|
| 15 | + | * - Multi-chain support with automatic switching |
|
| 16 | + | * - Customizable styling through attributes |
|
| 17 | + | * - Popover interface for wallet management |
|
| 18 | + | * |
|
| 19 | + | * @class ConnectWallet |
|
| 20 | + | * @extends HTMLElement |
|
| 21 | + | * |
|
| 22 | + | * @example |
|
| 23 | + | * // Basic usage |
|
| 24 | + | * <connect-wallet></connect-wallet> |
|
| 25 | + | * |
|
| 26 | + | * @example |
|
| 27 | + | * // With custom styling and chain |
|
| 28 | + | * <connect-wallet |
|
| 29 | + | * chain-id="0x89" |
|
| 30 | + | * primary="#4F46E5" |
|
| 31 | + | * background="#1F2937" |
|
| 32 | + | * border-radius="8px"> |
|
| 33 | + | * </connect-wallet> |
|
| 34 | + | * |
|
| 35 | + | * @fires ConnectWallet#wallet-connected - Fired when wallet is successfully connected |
|
| 36 | + | * @fires ConnectWallet#wallet-disconnected - Fired when wallet is disconnected |
|
| 37 | + | * @fires ConnectWallet#wallet-error - Fired when wallet connection fails |
|
| 38 | + | */ |
|
| 39 | + | ||
| 40 | + | class ConnectWallet extends HTMLElement { |
|
| 41 | + | // Constructor and lifecycle methods |
|
| 42 | + | constructor() { |
|
| 43 | + | super(); |
|
| 44 | + | this.attachShadow({ mode: "open" }); |
|
| 45 | + | this.connected = false; |
|
| 46 | + | this.address = ""; |
|
| 47 | + | this.ensData = null; |
|
| 48 | + | this.loading = false; |
|
| 49 | + | this.chainId = "0x1"; |
|
| 50 | + | this.currentChainId = null; |
|
| 51 | + | this.showPopover = false; |
|
| 52 | + | this.balance = "0"; |
|
| 53 | + | this.copySuccess = false; |
|
| 54 | + | ||
| 55 | + | // React-friendly callback properties |
|
| 56 | + | this.onWalletConnected = null; |
|
| 57 | + | this.onWalletDisconnected = null; |
|
| 58 | + | this.onWalletError = null; |
|
| 59 | + | } |
|
| 60 | + | ||
| 61 | + | static get observedAttributes() { |
|
| 62 | + | return [ |
|
| 63 | + | "chain-id", |
|
| 64 | + | "background", |
|
| 65 | + | "foreground", |
|
| 66 | + | "primary", |
|
| 67 | + | "secondary", |
|
| 68 | + | "border-radius", |
|
| 69 | + | ]; |
|
| 70 | + | } |
|
| 71 | + | ||
| 72 | + | attributeChangedCallback(name, oldValue, newValue) { |
|
| 73 | + | if (name === "chain-id" && oldValue !== newValue) { |
|
| 74 | + | this.chainId = this.normalizeChainId(newValue); |
|
| 75 | + | if (this.connected) { |
|
| 76 | + | this.checkAndSwitchChain(); |
|
| 77 | + | } |
|
| 78 | + | } else if ( |
|
| 79 | + | [ |
|
| 80 | + | "background", |
|
| 81 | + | "foreground", |
|
| 82 | + | "primary", |
|
| 83 | + | "secondary", |
|
| 84 | + | "border-radius", |
|
| 85 | + | ].includes(name) && |
|
| 86 | + | oldValue !== newValue |
|
| 87 | + | ) { |
|
| 88 | + | this.render(); |
|
| 89 | + | } |
|
| 90 | + | } |
|
| 91 | + | ||
| 92 | + | connectedCallback() { |
|
| 93 | + | const chainIdAttr = this.getAttribute("chain-id"); |
|
| 94 | + | this.chainId = this.normalizeChainId(chainIdAttr); |
|
| 95 | + | this.render(); |
|
| 96 | + | } |
|
| 97 | + | ||
| 98 | + | // Wallet connection methods |
|
| 99 | + | async connect() { |
|
| 100 | + | if (window.ethereum) { |
|
| 101 | + | try { |
|
| 102 | + | this.loading = true; |
|
| 103 | + | this.render(); |
|
| 104 | + | ||
| 105 | + | const accounts = await window.ethereum.request({ |
|
| 106 | + | method: "eth_requestAccounts", |
|
| 107 | + | }); |
|
| 108 | + | ||
| 109 | + | this.address = accounts[0]; |
|
| 110 | + | ||
| 111 | + | this.currentChainId = await window.ethereum.request({ |
|
| 112 | + | method: "eth_chainId", |
|
| 113 | + | }); |
|
| 114 | + | ||
| 115 | + | if (this.chainId && this.chainId !== this.currentChainId) { |
|
| 116 | + | await this.switchChain(this.chainId); |
|
| 117 | + | } |
|
| 118 | + | ||
| 119 | + | this.connected = true; |
|
| 120 | + | ||
| 121 | + | await Promise.all([this.fetchEnsData(), this.fetchBalance()]); |
|
| 122 | + | ||
| 123 | + | this.loading = false; |
|
| 124 | + | this.render(); |
|
| 125 | + | ||
| 126 | + | const eventDetail = { |
|
| 127 | + | address: this.address, |
|
| 128 | + | ensData: this.ensData, |
|
| 129 | + | chainId: this.currentChainId, |
|
| 130 | + | }; |
|
| 131 | + | ||
| 132 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 133 | + | this.dispatchEvent( |
|
| 134 | + | new CustomEvent("wallet-connected", { |
|
| 135 | + | detail: eventDetail, |
|
| 136 | + | }), |
|
| 137 | + | ); |
|
| 138 | + | ||
| 139 | + | // Call callback property if set (React-friendly) |
|
| 140 | + | if (typeof this.onWalletConnected === "function") { |
|
| 141 | + | this.onWalletConnected(eventDetail); |
|
| 142 | + | } |
|
| 143 | + | } catch (error) { |
|
| 144 | + | console.error("Connection failed", error); |
|
| 145 | + | this.loading = false; |
|
| 146 | + | this.render(); |
|
| 147 | + | ||
| 148 | + | const errorDetail = { error: error.message }; |
|
| 149 | + | ||
| 150 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 151 | + | this.dispatchEvent( |
|
| 152 | + | new CustomEvent("wallet-error", { |
|
| 153 | + | detail: errorDetail, |
|
| 154 | + | }), |
|
| 155 | + | ); |
|
| 156 | + | ||
| 157 | + | // Call callback property if set (React-friendly) |
|
| 158 | + | if (typeof this.onWalletError === "function") { |
|
| 159 | + | this.onWalletError(errorDetail); |
|
| 160 | + | } |
|
| 161 | + | } |
|
| 162 | + | } else { |
|
| 163 | + | alert("Please install a wallet extension like MetaMask"); |
|
| 164 | + | } |
|
| 165 | + | } |
|
| 166 | + | ||
| 167 | + | disconnect() { |
|
| 168 | + | this.connected = false; |
|
| 169 | + | this.address = ""; |
|
| 170 | + | this.ensData = null; |
|
| 171 | + | this.currentChainId = null; |
|
| 172 | + | this.balance = "0"; |
|
| 173 | + | this.showPopover = false; |
|
| 174 | + | this.copySuccess = false; |
|
| 175 | + | this.render(); |
|
| 176 | + | ||
| 177 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 178 | + | this.dispatchEvent(new CustomEvent("wallet-disconnected")); |
|
| 179 | + | ||
| 180 | + | // Call callback property if set (React-friendly) |
|
| 181 | + | if (typeof this.onWalletDisconnected === "function") { |
|
| 182 | + | this.onWalletDisconnected(); |
|
| 183 | + | } |
|
| 184 | + | } |
|
| 185 | + | ||
| 186 | + | // Chain management methods |
|
| 187 | + | /** |
|
| 188 | + | * Converts a numeric chain ID to hex format |
|
| 189 | + | * @param {string|number} chainId - Chain ID in numeric or hex format |
|
| 190 | + | * @returns {string} Chain ID in hex format (e.g., "0x2105") |
|
| 191 | + | */ |
|
| 192 | + | normalizeChainId(chainId) { |
|
| 193 | + | if (!chainId) return "0x1"; |
|
| 194 | + | ||
| 195 | + | const chainIdStr = String(chainId); |
|
| 196 | + | ||
| 197 | + | // If it's already in hex format (starts with 0x), return as-is |
|
| 198 | + | if (chainIdStr.startsWith("0x")) { |
|
| 199 | + | return chainIdStr.toLowerCase(); |
|
| 200 | + | } |
|
| 201 | + | ||
| 202 | + | // Convert numeric string to hex |
|
| 203 | + | const numericChainId = parseInt(chainIdStr, 10); |
|
| 204 | + | if (isNaN(numericChainId)) { |
|
| 205 | + | console.warn(`Invalid chain ID: ${chainId}, defaulting to 0x1`); |
|
| 206 | + | return "0x1"; |
|
| 207 | + | } |
|
| 208 | + | ||
| 209 | + | return `0x${numericChainId.toString(16)}`; |
|
| 210 | + | } |
|
| 211 | + | ||
| 212 | + | async switchChain(chainId) { |
|
| 213 | + | try { |
|
| 214 | + | await window.ethereum.request({ |
|
| 215 | + | method: "wallet_switchEthereumChain", |
|
| 216 | + | params: [{ chainId }], |
|
| 217 | + | }); |
|
| 218 | + | this.currentChainId = chainId; |
|
| 219 | + | } catch (switchError) { |
|
| 220 | + | throw new Error(`Failed to switch chain: ${switchError.message}`); |
|
| 221 | + | } |
|
| 222 | + | } |
|
| 223 | + | ||
| 224 | + | async checkAndSwitchChain() { |
|
| 225 | + | if (window.ethereum && this.chainId && this.connected) { |
|
| 226 | + | const currentChain = await window.ethereum.request({ |
|
| 227 | + | method: "eth_chainId", |
|
| 228 | + | }); |
|
| 229 | + | ||
| 230 | + | if (currentChain !== this.chainId) { |
|
| 231 | + | try { |
|
| 232 | + | await this.switchChain(this.chainId); |
|
| 233 | + | this.render(); |
|
| 234 | + | } catch (error) { |
|
| 235 | + | console.error("Failed to switch chain:", error); |
|
| 236 | + | } |
|
| 237 | + | } |
|
| 238 | + | } |
|
| 239 | + | } |
|
| 240 | + | ||
| 241 | + | getChainName(chainId) { |
|
| 242 | + | const chainNames = { |
|
| 243 | + | "0x1": "Ethereum", |
|
| 244 | + | "0x89": "Polygon", |
|
| 245 | + | "0xa": "Optimism", |
|
| 246 | + | "0xa4b1": "Arbitrum", |
|
| 247 | + | "0x2105": "Base", |
|
| 248 | + | }; |
|
| 249 | + | return chainNames[chainId] || `Chain ${chainId}`; |
|
| 250 | + | } |
|
| 251 | + | ||
| 252 | + | // Data fetching methods |
|
| 253 | + | async fetchEnsData() { |
|
| 254 | + | try { |
|
| 255 | + | const response = await fetch(`https://api.ensdata.net/${this.address}`); |
|
| 256 | + | if (response.ok) { |
|
| 257 | + | this.ensData = await response.json(); |
|
| 258 | + | console.log("ENS data loaded:", this.ensData); |
|
| 259 | + | } else { |
|
| 260 | + | console.log("No ENS data found for this address"); |
|
| 261 | + | this.ensData = null; |
|
| 262 | + | } |
|
| 263 | + | } catch (error) { |
|
| 264 | + | console.error("Failed to fetch ENS data", error); |
|
| 265 | + | this.ensData = null; |
|
| 266 | + | } |
|
| 267 | + | } |
|
| 268 | + | ||
| 269 | + | async fetchBalance() { |
|
| 270 | + | try { |
|
| 271 | + | const balanceWei = await window.ethereum.request({ |
|
| 272 | + | method: "eth_getBalance", |
|
| 273 | + | params: [this.address, "latest"], |
|
| 274 | + | }); |
|
| 275 | + | ||
| 276 | + | const balanceEth = parseInt(balanceWei, 16) / Math.pow(10, 18); |
|
| 277 | + | this.balance = balanceEth.toFixed(4); |
|
| 278 | + | } catch (error) { |
|
| 279 | + | console.error("Failed to fetch balance", error); |
|
| 280 | + | this.balance = "0"; |
|
| 281 | + | } |
|
| 282 | + | } |
|
| 283 | + | ||
| 284 | + | // UI helper methods |
|
| 285 | + | getDisplayName() { |
|
| 286 | + | if (this.ensData?.ens_primary) { |
|
| 287 | + | return this.ensData.ens_primary; |
|
| 288 | + | } |
|
| 289 | + | return this.truncateAddress(this.address); |
|
| 290 | + | } |
|
| 291 | + | ||
| 292 | + | truncateAddress(addr) { |
|
| 293 | + | if (!addr) return ""; |
|
| 294 | + | return addr.slice(0, 5) + "..." + addr.slice(-5); |
|
| 295 | + | } |
|
| 296 | + | ||
| 297 | + | async copyAddress() { |
|
| 298 | + | try { |
|
| 299 | + | await navigator.clipboard.writeText(this.address); |
|
| 300 | + | this.copySuccess = true; |
|
| 301 | + | this.showPopoverElement(); |
|
| 302 | + | ||
| 303 | + | setTimeout(() => { |
|
| 304 | + | this.copySuccess = false; |
|
| 305 | + | this.showPopoverElement(); |
|
| 306 | + | }, 1000); |
|
| 307 | + | } catch (error) { |
|
| 308 | + | console.error("Failed to copy address", error); |
|
| 309 | + | } |
|
| 310 | + | } |
|
| 311 | + | ||
| 312 | + | // Popover management methods |
|
| 313 | + | togglePopover() { |
|
| 314 | + | this.showPopover = !this.showPopover; |
|
| 315 | + | if (this.showPopover) { |
|
| 316 | + | this.showPopoverElement(); |
|
| 317 | + | } else { |
|
| 318 | + | this.hidePopoverElement(); |
|
| 319 | + | } |
|
| 320 | + | } |
|
| 321 | + | ||
| 322 | + | hidePopover() { |
|
| 323 | + | if (this.showPopover) { |
|
| 324 | + | this.showPopover = false; |
|
| 325 | + | this.hidePopoverElement(); |
|
| 326 | + | } |
|
| 327 | + | } |
|
| 328 | + | ||
| 329 | + | showPopoverElement() { |
|
| 330 | + | const profileContainer = |
|
| 331 | + | this.shadowRoot.querySelector(".profile-container"); |
|
| 332 | + | if (!profileContainer) return; |
|
| 333 | + | ||
| 334 | + | const existingPopover = profileContainer.querySelector(".popover"); |
|
| 335 | + | if (existingPopover) { |
|
| 336 | + | existingPopover.remove(); |
|
| 337 | + | } |
|
| 338 | + | ||
| 339 | + | const popover = document.createElement("div"); |
|
| 340 | + | popover.className = "popover"; |
|
| 341 | + | ||
| 342 | + | const copyIcon = this.copySuccess |
|
| 343 | + | ? `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>` |
|
| 344 | + | : `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 12.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>`; |
|
| 345 | + | ||
| 346 | + | const copyText = this.copySuccess ? "Copied!" : "Copy Address"; |
|
| 347 | + | popover.innerHTML = ` |
|
| 348 | + | <button class="popover-button copy-button"> |
|
| 349 | + | <span>${copyIcon}</span> |
|
| 350 | + | ${copyText} |
|
| 351 | + | </button> |
|
| 352 | + | <button class="popover-button disconnect-button"> |
|
| 353 | + | <span><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 1C2.44771 1 2 1.44772 2 2V13C2 13.5523 2.44772 14 3 14H10.5C10.7761 14 11 13.7761 11 13.5C11 13.2239 10.7761 13 10.5 13H3V2L10.5 2C10.7761 2 11 1.77614 11 1.5C11 1.22386 10.7761 1 10.5 1H3ZM12.6036 4.89645C12.4083 4.70118 12.0917 4.70118 11.8964 4.89645C11.7012 5.09171 11.7012 5.40829 11.8964 5.60355L13.2929 7H6.5C6.22386 7 6 7.22386 6 7.5C6 7.77614 6.22386 8 6.5 8H13.2929L11.8964 9.39645C11.7012 9.59171 11.7012 9.90829 11.8964 10.1036C12.0917 10.2988 12.4083 10.2988 12.6036 10.1036L14.8536 7.85355C15.0488 7.65829 15.0488 7.34171 14.8536 7.14645L12.6036 4.89645Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></span> |
|
| 354 | + | Disconnect |
|
| 355 | + | </button> |
|
| 356 | + | `; |
|
| 357 | + | ||
| 358 | + | popover.querySelector(".copy-button").addEventListener("click", (e) => { |
|
| 359 | + | e.stopPropagation(); |
|
| 360 | + | this.copyAddress(); |
|
| 361 | + | }); |
|
| 362 | + | ||
| 363 | + | popover |
|
| 364 | + | .querySelector(".disconnect-button") |
|
| 365 | + | .addEventListener("click", (e) => { |
|
| 366 | + | e.stopPropagation(); |
|
| 367 | + | this.disconnect(); |
|
| 368 | + | }); |
|
| 369 | + | ||
| 370 | + | profileContainer.appendChild(popover); |
|
| 371 | + | ||
| 372 | + | setTimeout(() => { |
|
| 373 | + | document.addEventListener("click", this.hidePopover.bind(this), { |
|
| 374 | + | once: true, |
|
| 375 | + | }); |
|
| 376 | + | }, 0); |
|
| 377 | + | } |
|
| 378 | + | ||
| 379 | + | hidePopoverElement() { |
|
| 380 | + | const profileContainer = |
|
| 381 | + | this.shadowRoot.querySelector(".profile-container"); |
|
| 382 | + | if (!profileContainer) return; |
|
| 383 | + | ||
| 384 | + | const popover = profileContainer.querySelector(".popover"); |
|
| 385 | + | if (popover) { |
|
| 386 | + | popover.remove(); |
|
| 387 | + | } |
|
| 388 | + | } |
|
| 389 | + | ||
| 390 | + | // Color helper methods |
|
| 391 | + | getCSSVariable(name, defaultValue) { |
|
| 392 | + | return this.getAttribute(name) || defaultValue; |
|
| 393 | + | } |
|
| 394 | + | ||
| 395 | + | // Render methods and styling |
|
| 396 | + | render() { |
|
| 397 | + | const background = this.getCSSVariable("background", "#232323"); |
|
| 398 | + | const foreground = this.getCSSVariable("foreground", "#ffffff"); |
|
| 399 | + | const primary = this.getCSSVariable("primary", "#5F8787"); |
|
| 400 | + | const secondary = this.getCSSVariable("secondary", "#6F9797"); |
|
| 401 | + | const borderRadius = this.getCSSVariable("border-radius", "4px"); |
|
| 402 | + | ||
| 403 | + | this.shadowRoot.innerHTML = ` |
|
| 404 | + | <style> |
|
| 405 | + | :host { |
|
| 406 | + | --color-background: ${background}; |
|
| 407 | + | --color-foreground: ${foreground}; |
|
| 408 | + | --color-primary: ${primary}; |
|
| 409 | + | --color-secondary: ${secondary}; |
|
| 410 | + | --border-radius: ${borderRadius}; |
|
| 411 | + | --bg-color: ${this.connected ? "var(--color-background)" : "var(--color-primary)"}; |
|
| 412 | + | --bg-hover-color: ${this.connected ? "var(--color-background)" : "var(--color-secondary)"}; |
|
| 413 | + | display: inline-block; |
|
| 414 | + | } |
|
| 415 | + | ||
| 416 | + | button { |
|
| 417 | + | padding: 10px 20px; |
|
| 418 | + | background: var(--bg-color); |
|
| 419 | + | color: var(--color-foreground); |
|
| 420 | + | border: none; |
|
| 421 | + | border-radius: var(--border-radius); |
|
| 422 | + | cursor: pointer; |
|
| 423 | + | font-size: 16px; |
|
| 424 | + | transition: background-color 0.3s ease; |
|
| 425 | + | } |
|
| 426 | + | ||
| 427 | + | button:hover { |
|
| 428 | + | background: var(--bg-hover-color); |
|
| 429 | + | } |
|
| 430 | + | ||
| 431 | + | button:disabled { |
|
| 432 | + | opacity: 0.7; |
|
| 433 | + | cursor: not-allowed; |
|
| 434 | + | } |
|
| 435 | + | ||
| 436 | + | .profile-container { |
|
| 437 | + | position: relative; |
|
| 438 | + | display: inline-block; |
|
| 439 | + | font-family: sans-serif; |
|
| 440 | + | } |
|
| 441 | + | ||
| 442 | + | .profile { |
|
| 443 | + | display: flex; |
|
| 444 | + | align-items: center; |
|
| 445 | + | gap: 8px; |
|
| 446 | + | padding: 10px 20px; |
|
| 447 | + | background: var(--bg-color); |
|
| 448 | + | border-radius: var(--border-radius); |
|
| 449 | + | color: var(--color-foreground); |
|
| 450 | + | min-width: auto; |
|
| 451 | + | transition: background-color 0.3s ease; |
|
| 452 | + | cursor: pointer; |
|
| 453 | + | } |
|
| 454 | + | ||
| 455 | + | .profile:hover { |
|
| 456 | + | background: var(--bg-hover-color); |
|
| 457 | + | } |
|
| 458 | + | ||
| 459 | + | .popover { |
|
| 460 | + | position: absolute; |
|
| 461 | + | top: 100%; |
|
| 462 | + | left: 0; |
|
| 463 | + | right: 0; |
|
| 464 | + | background: var(--bg-color); |
|
| 465 | + | border: 1px solid rgba(255, 255, 255, 0.1); |
|
| 466 | + | border-radius: var(--border-radius); |
|
| 467 | + | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); |
|
| 468 | + | z-index: 1000; |
|
| 469 | + | margin-top: 4px; |
|
| 470 | + | overflow: hidden; |
|
| 471 | + | } |
|
| 472 | + | ||
| 473 | + | .popover-button { |
|
| 474 | + | display: flex; |
|
| 475 | + | align-items: center; |
|
| 476 | + | gap: 8px; |
|
| 477 | + | width: 100%; |
|
| 478 | + | padding: 10px 16px; |
|
| 479 | + | background: var(--bg-color); |
|
| 480 | + | border: none; |
|
| 481 | + | color: var(--color-foreground); |
|
| 482 | + | font-size: 14px; |
|
| 483 | + | cursor: pointer; |
|
| 484 | + | transition: background-color 0.2s ease; |
|
| 485 | + | } |
|
| 486 | + | ||
| 487 | + | .popover-button:hover { |
|
| 488 | + | background: var(--bg-hover-color); |
|
| 489 | + | } |
|
| 490 | + | ||
| 491 | + | .popover-button:not(:last-child) { |
|
| 492 | + | border-bottom: 1px solid rgba(255, 255, 255, 0.1); |
|
| 493 | + | } |
|
| 494 | + | ||
| 495 | + | .popover-button span { |
|
| 496 | + | font-size: 16px; |
|
| 497 | + | } |
|
| 498 | + | ||
| 499 | + | .avatar { |
|
| 500 | + | width: 32px; |
|
| 501 | + | height: 32px; |
|
| 502 | + | border-radius: 50%; |
|
| 503 | + | object-fit: cover; |
|
| 504 | + | } |
|
| 505 | + | ||
| 506 | + | .avatar-placeholder { |
|
| 507 | + | width: 32px; |
|
| 508 | + | height: 32px; |
|
| 509 | + | border-radius: 50%; |
|
| 510 | + | background: linear-gradient(45deg, var(--color-primary), var(--color-secondary)); |
|
| 511 | + | display: flex; |
|
| 512 | + | align-items: center; |
|
| 513 | + | justify-content: center; |
|
| 514 | + | color: var(--color-foreground); |
|
| 515 | + | font-weight: bold; |
|
| 516 | + | font-size: 12px; |
|
| 517 | + | } |
|
| 518 | + | ||
| 519 | + | .profile-info { |
|
| 520 | + | flex: 1; |
|
| 521 | + | min-width: 0; |
|
| 522 | + | } |
|
| 523 | + | ||
| 524 | + | .profile-info h4 { |
|
| 525 | + | margin: 0 0 2px 0; |
|
| 526 | + | font-size: 14px; |
|
| 527 | + | font-weight: 600; |
|
| 528 | + | white-space: nowrap; |
|
| 529 | + | overflow: hidden; |
|
| 530 | + | text-overflow: ellipsis; |
|
| 531 | + | } |
|
| 532 | + | ||
| 533 | + | .profile-info p { |
|
| 534 | + | margin: 0; |
|
| 535 | + | font-size: 12px; |
|
| 536 | + | opacity: 0.8; |
|
| 537 | + | white-space: nowrap; |
|
| 538 | + | overflow: hidden; |
|
| 539 | + | text-overflow: ellipsis; |
|
| 540 | + | font-family: monospace; |
|
| 541 | + | } |
|
| 542 | + | ||
| 543 | + | .loading { |
|
| 544 | + | display: flex; |
|
| 545 | + | align-items: center; |
|
| 546 | + | gap: 8px; |
|
| 547 | + | } |
|
| 548 | + | ||
| 549 | + | .spinner { |
|
| 550 | + | width: 16px; |
|
| 551 | + | height: 16px; |
|
| 552 | + | border: 2px solid rgba(255, 255, 255, 0.3); |
|
| 553 | + | border-top: 2px solid var(--color-foreground); |
|
| 554 | + | border-radius: 50%; |
|
| 555 | + | animation: spin 1s linear infinite; |
|
| 556 | + | } |
|
| 557 | + | ||
| 558 | + | @keyframes spin { |
|
| 559 | + | from { transform: rotate(0deg); } |
|
| 560 | + | to { transform: rotate(360deg); } |
|
| 561 | + | } |
|
| 562 | + | </style> |
|
| 563 | + | `; |
|
| 564 | + | ||
| 565 | + | if (this.loading) { |
|
| 566 | + | this.renderLoading(); |
|
| 567 | + | } else if (this.connected) { |
|
| 568 | + | this.renderProfile(); |
|
| 569 | + | } else { |
|
| 570 | + | this.renderConnectButton(); |
|
| 571 | + | } |
|
| 572 | + | } |
|
| 573 | + | ||
| 574 | + | renderProfile() { |
|
| 575 | + | const profileContainer = document.createElement("div"); |
|
| 576 | + | profileContainer.className = "profile-container"; |
|
| 577 | + | ||
| 578 | + | const profileDiv = document.createElement("div"); |
|
| 579 | + | profileDiv.className = "profile"; |
|
| 580 | + | ||
| 581 | + | const avatar = this.ensData?.avatar_small; |
|
| 582 | + | const displayName = this.getDisplayName(); |
|
| 583 | + | ||
| 584 | + | let avatarElement = ""; |
|
| 585 | + | if (avatar) { |
|
| 586 | + | avatarElement = `<img src="${avatar}" alt="Avatar" class="avatar" onerror="this.style.display='none'">`; |
|
| 587 | + | } else { |
|
| 588 | + | avatarElement = `<div class="avatar-placeholder"></div>`; |
|
| 589 | + | } |
|
| 590 | + | ||
| 591 | + | profileDiv.innerHTML = ` |
|
| 592 | + | ${avatarElement} |
|
| 593 | + | <div class="profile-info"> |
|
| 594 | + | <h4>${displayName}</h4> |
|
| 595 | + | <p>${this.balance} ETH</p> |
|
| 596 | + | </div> |
|
| 597 | + | `; |
|
| 598 | + | ||
| 599 | + | profileDiv.addEventListener("click", (e) => { |
|
| 600 | + | e.stopPropagation(); |
|
| 601 | + | this.togglePopover(); |
|
| 602 | + | }); |
|
| 603 | + | ||
| 604 | + | profileContainer.appendChild(profileDiv); |
|
| 605 | + | this.shadowRoot.appendChild(profileContainer); |
|
| 606 | + | ||
| 607 | + | if (this.showPopover) { |
|
| 608 | + | this.showPopoverElement(); |
|
| 609 | + | } |
|
| 610 | + | } |
|
| 611 | + | ||
| 612 | + | renderLoading() { |
|
| 613 | + | const button = document.createElement("button"); |
|
| 614 | + | button.disabled = true; |
|
| 615 | + | button.innerHTML = ` |
|
| 616 | + | <div class="loading"> |
|
| 617 | + | <div class="spinner"></div> |
|
| 618 | + | <span>Connecting...</span> |
|
| 619 | + | </div> |
|
| 620 | + | `; |
|
| 621 | + | this.shadowRoot.appendChild(button); |
|
| 622 | + | } |
|
| 623 | + | ||
| 624 | + | renderConnectButton() { |
|
| 625 | + | const button = document.createElement("button"); |
|
| 626 | + | button.textContent = "Connect Wallet"; |
|
| 627 | + | button.addEventListener("click", () => this.connect()); |
|
| 628 | + | this.shadowRoot.appendChild(button); |
|
| 629 | + | } |
|
| 630 | + | } |
|
| 631 | + | ||
| 632 | + | customElements.define("connect-wallet", ConnectWallet); |
| 1 | + | declare module 'svelte/elements' { |
|
| 2 | + | export interface SvelteHTMLElements { |
|
| 3 | + | 'contract-call': { |
|
| 4 | + | 'contract-address'?: string; |
|
| 5 | + | 'chain-id'?: string; |
|
| 6 | + | 'method-name'?: string; |
|
| 7 | + | 'method-args'?: string; |
|
| 8 | + | 'abi-url'?: string; |
|
| 9 | + | 'abi'?: string; |
|
| 10 | + | 'button-text'?: string; |
|
| 11 | + | 'background'?: string; |
|
| 12 | + | 'foreground'?: string; |
|
| 13 | + | 'primary'?: string; |
|
| 14 | + | 'secondary'?: string; |
|
| 15 | + | 'border-radius'?: string; |
|
| 16 | + | 'error-color'?: string; |
|
| 17 | + | 'success-color'?: string; |
|
| 18 | + | 'on:abi-loaded'?: (event: CustomEvent) => void; |
|
| 19 | + | 'on:abi-error'?: (event: CustomEvent) => void; |
|
| 20 | + | 'on:contract-call-success'?: (event: CustomEvent) => void; |
|
| 21 | + | 'on:contract-call-error'?: (event: CustomEvent) => void; |
|
| 22 | + | }; |
|
| 23 | + | 'connect-wallet': { |
|
| 24 | + | 'chain-id'?: string; |
|
| 25 | + | 'background'?: string; |
|
| 26 | + | 'foreground'?: string; |
|
| 27 | + | 'primary'?: string; |
|
| 28 | + | 'secondary'?: string; |
|
| 29 | + | 'border-radius'?: string; |
|
| 30 | + | 'on:wallet-connected'?: (event: CustomEvent) => void; |
|
| 31 | + | 'on:wallet-error'?: (event: CustomEvent) => void; |
|
| 32 | + | 'on:wallet-disconnected'?: (event: CustomEvent) => void; |
|
| 33 | + | }; |
|
| 34 | + | } |
|
| 35 | + | } |
|
| 36 | + | ||
| 37 | + | export {}; |
| 1 | + | <script lang="ts"> |
|
| 2 | + | let count: number = $state(0) |
|
| 3 | + | const increment = () => { |
|
| 4 | + | count += 1 |
|
| 5 | + | } |
|
| 6 | + | </script> |
|
| 7 | + | ||
| 8 | + | <button onclick={increment}> |
|
| 9 | + | count is {count} |
|
| 10 | + | </button> |
| 1 | + | import { mount } from 'svelte' |
|
| 2 | + | import './app.css' |
|
| 3 | + | import App from './App.svelte' |
|
| 4 | + | ||
| 5 | + | const app = mount(App, { |
|
| 6 | + | target: document.getElementById('app')!, |
|
| 7 | + | }) |
|
| 8 | + | ||
| 9 | + | export default app |
| 1 | + | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' |
|
| 2 | + | ||
| 3 | + | /** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */ |
|
| 4 | + | export default { |
|
| 5 | + | // Consult https://svelte.dev/docs#compile-time-svelte-preprocess |
|
| 6 | + | // for more information about preprocessors |
|
| 7 | + | preprocess: vitePreprocess(), |
|
| 8 | + | } |
| 1 | + | { |
|
| 2 | + | "extends": "@tsconfig/svelte/tsconfig.json", |
|
| 3 | + | "compilerOptions": { |
|
| 4 | + | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", |
|
| 5 | + | "target": "ES2022", |
|
| 6 | + | "useDefineForClassFields": true, |
|
| 7 | + | "module": "ESNext", |
|
| 8 | + | "types": ["svelte", "vite/client"], |
|
| 9 | + | "noEmit": true, |
|
| 10 | + | /** |
|
| 11 | + | * Typecheck JS in `.svelte` and `.js` files by default. |
|
| 12 | + | * Disable checkJs if you'd like to use dynamic types in JS. |
|
| 13 | + | * Note that setting allowJs false does not prevent the use |
|
| 14 | + | * of JS in `.svelte` files. |
|
| 15 | + | */ |
|
| 16 | + | "allowJs": true, |
|
| 17 | + | "checkJs": true, |
|
| 18 | + | "moduleDetection": "force" |
|
| 19 | + | }, |
|
| 20 | + | "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] |
|
| 21 | + | } |
| 1 | + | { |
|
| 2 | + | "files": [], |
|
| 3 | + | "references": [ |
|
| 4 | + | { "path": "./tsconfig.app.json" }, |
|
| 5 | + | { "path": "./tsconfig.node.json" } |
|
| 6 | + | ] |
|
| 7 | + | } |
| 1 | + | { |
|
| 2 | + | "compilerOptions": { |
|
| 3 | + | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", |
|
| 4 | + | "target": "ES2023", |
|
| 5 | + | "lib": ["ES2023"], |
|
| 6 | + | "module": "ESNext", |
|
| 7 | + | "types": ["node"], |
|
| 8 | + | "skipLibCheck": true, |
|
| 9 | + | ||
| 10 | + | /* Bundler mode */ |
|
| 11 | + | "moduleResolution": "bundler", |
|
| 12 | + | "allowImportingTsExtensions": true, |
|
| 13 | + | "verbatimModuleSyntax": true, |
|
| 14 | + | "moduleDetection": "force", |
|
| 15 | + | "noEmit": true, |
|
| 16 | + | ||
| 17 | + | /* Linting */ |
|
| 18 | + | "strict": true, |
|
| 19 | + | "noUnusedLocals": true, |
|
| 20 | + | "noUnusedParameters": true, |
|
| 21 | + | "erasableSyntaxOnly": true, |
|
| 22 | + | "noFallthroughCasesInSwitch": true, |
|
| 23 | + | "noUncheckedSideEffectImports": true |
|
| 24 | + | }, |
|
| 25 | + | "include": ["vite.config.ts"] |
|
| 26 | + | } |
| 1 | + | import { defineConfig } from 'vite' |
|
| 2 | + | import { svelte } from '@sveltejs/vite-plugin-svelte' |
|
| 3 | + | ||
| 4 | + | // https://vite.dev/config/ |
|
| 5 | + | export default defineConfig({ |
|
| 6 | + | plugins: [svelte()], |
|
| 7 | + | }) |
| 1 | + | # Logs |
|
| 2 | + | logs |
|
| 3 | + | *.log |
|
| 4 | + | npm-debug.log* |
|
| 5 | + | yarn-debug.log* |
|
| 6 | + | yarn-error.log* |
|
| 7 | + | pnpm-debug.log* |
|
| 8 | + | lerna-debug.log* |
|
| 9 | + | ||
| 10 | + | node_modules |
|
| 11 | + | dist |
|
| 12 | + | dist-ssr |
|
| 13 | + | *.local |
|
| 14 | + | ||
| 15 | + | # Editor directories and files |
|
| 16 | + | .vscode/* |
|
| 17 | + | !.vscode/extensions.json |
|
| 18 | + | .idea |
|
| 19 | + | .DS_Store |
|
| 20 | + | *.suo |
|
| 21 | + | *.ntvs* |
|
| 22 | + | *.njsproj |
|
| 23 | + | *.sln |
|
| 24 | + | *.sw? |
| 1 | + | { |
|
| 2 | + | "lockfileVersion": 1, |
|
| 3 | + | "workspaces": { |
|
| 4 | + | "": { |
|
| 5 | + | "name": "vite-vanilla", |
|
| 6 | + | "devDependencies": { |
|
| 7 | + | "typescript": "~5.9.3", |
|
| 8 | + | "vite": "^7.1.7", |
|
| 9 | + | }, |
|
| 10 | + | }, |
|
| 11 | + | }, |
|
| 12 | + | "packages": { |
|
| 13 | + | "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="], |
|
| 14 | + | ||
| 15 | + | "@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="], |
|
| 16 | + | ||
| 17 | + | "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="], |
|
| 18 | + | ||
| 19 | + | "@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="], |
|
| 20 | + | ||
| 21 | + | "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="], |
|
| 22 | + | ||
| 23 | + | "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="], |
|
| 24 | + | ||
| 25 | + | "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="], |
|
| 26 | + | ||
| 27 | + | "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="], |
|
| 28 | + | ||
| 29 | + | "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="], |
|
| 30 | + | ||
| 31 | + | "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="], |
|
| 32 | + | ||
| 33 | + | "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="], |
|
| 34 | + | ||
| 35 | + | "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="], |
|
| 36 | + | ||
| 37 | + | "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="], |
|
| 38 | + | ||
| 39 | + | "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="], |
|
| 40 | + | ||
| 41 | + | "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="], |
|
| 42 | + | ||
| 43 | + | "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="], |
|
| 44 | + | ||
| 45 | + | "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="], |
|
| 46 | + | ||
| 47 | + | "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="], |
|
| 48 | + | ||
| 49 | + | "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="], |
|
| 50 | + | ||
| 51 | + | "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="], |
|
| 52 | + | ||
| 53 | + | "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="], |
|
| 54 | + | ||
| 55 | + | "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="], |
|
| 56 | + | ||
| 57 | + | "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="], |
|
| 58 | + | ||
| 59 | + | "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="], |
|
| 60 | + | ||
| 61 | + | "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="], |
|
| 62 | + | ||
| 63 | + | "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="], |
|
| 64 | + | ||
| 65 | + | "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="], |
|
| 66 | + | ||
| 67 | + | "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="], |
|
| 68 | + | ||
| 69 | + | "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="], |
|
| 70 | + | ||
| 71 | + | "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="], |
|
| 72 | + | ||
| 73 | + | "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="], |
|
| 74 | + | ||
| 75 | + | "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="], |
|
| 76 | + | ||
| 77 | + | "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="], |
|
| 78 | + | ||
| 79 | + | "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="], |
|
| 80 | + | ||
| 81 | + | "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="], |
|
| 82 | + | ||
| 83 | + | "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="], |
|
| 84 | + | ||
| 85 | + | "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="], |
|
| 86 | + | ||
| 87 | + | "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="], |
|
| 88 | + | ||
| 89 | + | "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="], |
|
| 90 | + | ||
| 91 | + | "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="], |
|
| 92 | + | ||
| 93 | + | "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="], |
|
| 94 | + | ||
| 95 | + | "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], |
|
| 96 | + | ||
| 97 | + | "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="], |
|
| 98 | + | ||
| 99 | + | "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="], |
|
| 100 | + | ||
| 101 | + | "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="], |
|
| 102 | + | ||
| 103 | + | "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="], |
|
| 104 | + | ||
| 105 | + | "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="], |
|
| 106 | + | ||
| 107 | + | "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="], |
|
| 108 | + | ||
| 109 | + | "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], |
|
| 110 | + | ||
| 111 | + | "esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="], |
|
| 112 | + | ||
| 113 | + | "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], |
|
| 114 | + | ||
| 115 | + | "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], |
|
| 116 | + | ||
| 117 | + | "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], |
|
| 118 | + | ||
| 119 | + | "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], |
|
| 120 | + | ||
| 121 | + | "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|
| 122 | + | ||
| 123 | + | "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], |
|
| 124 | + | ||
| 125 | + | "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="], |
|
| 126 | + | ||
| 127 | + | "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], |
|
| 128 | + | ||
| 129 | + | "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], |
|
| 130 | + | ||
| 131 | + | "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], |
|
| 132 | + | ||
| 133 | + | "vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], |
|
| 134 | + | } |
|
| 135 | + | } |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en"> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|
| 6 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 7 | + | <title>vite-vanilla</title> |
|
| 8 | + | </head> |
|
| 9 | + | <body> |
|
| 10 | + | <div id="app"></div> |
|
| 11 | + | <script type="module" src="/src/main.ts"></script> |
|
| 12 | + | </body> |
|
| 13 | + | </html> |
| 1 | + | { |
|
| 2 | + | "components": "src/components", |
|
| 3 | + | "includeTypes": true, |
|
| 4 | + | "framework": "typescript" |
|
| 5 | + | } |
| 1 | + | { |
|
| 2 | + | "name": "vite-vanilla", |
|
| 3 | + | "private": true, |
|
| 4 | + | "version": "0.0.0", |
|
| 5 | + | "type": "module", |
|
| 6 | + | "scripts": { |
|
| 7 | + | "dev": "vite", |
|
| 8 | + | "build": "tsc && vite build", |
|
| 9 | + | "preview": "vite preview" |
|
| 10 | + | }, |
|
| 11 | + | "devDependencies": { |
|
| 12 | + | "typescript": "~5.9.3", |
|
| 13 | + | "vite": "^7.1.7" |
|
| 14 | + | } |
|
| 15 | + | } |
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> |
| 1 | + | /** |
|
| 2 | + | * @fileoverview ConnectWallet Web Component - A customizable wallet connection component |
|
| 3 | + | * that supports Ethereum wallet integration with ENS resolution, balance display, and |
|
| 4 | + | * multi-chain support. |
|
| 5 | + | * |
|
| 6 | + | */ |
|
| 7 | + | ||
| 8 | + | /** |
|
| 9 | + | * ConnectWallet - A Web Component for Ethereum wallet connection and management |
|
| 10 | + | * |
|
| 11 | + | * This component provides a complete wallet connection interface with the following features: |
|
| 12 | + | * - Connect/disconnect wallet functionality |
|
| 13 | + | * - ENS name resolution and avatar display |
|
| 14 | + | * - Balance fetching and display |
|
| 15 | + | * - Multi-chain support with automatic switching |
|
| 16 | + | * - Customizable styling through attributes |
|
| 17 | + | * - Popover interface for wallet management |
|
| 18 | + | * |
|
| 19 | + | * @class ConnectWallet |
|
| 20 | + | * @extends HTMLElement |
|
| 21 | + | * |
|
| 22 | + | * @example |
|
| 23 | + | * // Basic usage |
|
| 24 | + | * <connect-wallet></connect-wallet> |
|
| 25 | + | * |
|
| 26 | + | * @example |
|
| 27 | + | * // With custom styling and chain |
|
| 28 | + | * <connect-wallet |
|
| 29 | + | * chain-id="0x89" |
|
| 30 | + | * primary="#4F46E5" |
|
| 31 | + | * background="#1F2937" |
|
| 32 | + | * border-radius="8px"> |
|
| 33 | + | * </connect-wallet> |
|
| 34 | + | * |
|
| 35 | + | * @fires ConnectWallet#wallet-connected - Fired when wallet is successfully connected |
|
| 36 | + | * @fires ConnectWallet#wallet-disconnected - Fired when wallet is disconnected |
|
| 37 | + | * @fires ConnectWallet#wallet-error - Fired when wallet connection fails |
|
| 38 | + | */ |
|
| 39 | + | ||
| 40 | + | class ConnectWallet extends HTMLElement { |
|
| 41 | + | // Constructor and lifecycle methods |
|
| 42 | + | constructor() { |
|
| 43 | + | super(); |
|
| 44 | + | this.attachShadow({ mode: "open" }); |
|
| 45 | + | this.connected = false; |
|
| 46 | + | this.address = ""; |
|
| 47 | + | this.ensData = null; |
|
| 48 | + | this.loading = false; |
|
| 49 | + | this.chainId = "0x1"; |
|
| 50 | + | this.currentChainId = null; |
|
| 51 | + | this.showPopover = false; |
|
| 52 | + | this.balance = "0"; |
|
| 53 | + | this.copySuccess = false; |
|
| 54 | + | ||
| 55 | + | // React-friendly callback properties |
|
| 56 | + | this.onWalletConnected = null; |
|
| 57 | + | this.onWalletDisconnected = null; |
|
| 58 | + | this.onWalletError = null; |
|
| 59 | + | } |
|
| 60 | + | ||
| 61 | + | static get observedAttributes() { |
|
| 62 | + | return [ |
|
| 63 | + | "chain-id", |
|
| 64 | + | "background", |
|
| 65 | + | "foreground", |
|
| 66 | + | "primary", |
|
| 67 | + | "secondary", |
|
| 68 | + | "border-radius", |
|
| 69 | + | ]; |
|
| 70 | + | } |
|
| 71 | + | ||
| 72 | + | attributeChangedCallback(name, oldValue, newValue) { |
|
| 73 | + | if (name === "chain-id" && oldValue !== newValue) { |
|
| 74 | + | this.chainId = this.normalizeChainId(newValue); |
|
| 75 | + | if (this.connected) { |
|
| 76 | + | this.checkAndSwitchChain(); |
|
| 77 | + | } |
|
| 78 | + | } else if ( |
|
| 79 | + | [ |
|
| 80 | + | "background", |
|
| 81 | + | "foreground", |
|
| 82 | + | "primary", |
|
| 83 | + | "secondary", |
|
| 84 | + | "border-radius", |
|
| 85 | + | ].includes(name) && |
|
| 86 | + | oldValue !== newValue |
|
| 87 | + | ) { |
|
| 88 | + | this.render(); |
|
| 89 | + | } |
|
| 90 | + | } |
|
| 91 | + | ||
| 92 | + | connectedCallback() { |
|
| 93 | + | const chainIdAttr = this.getAttribute("chain-id"); |
|
| 94 | + | this.chainId = this.normalizeChainId(chainIdAttr); |
|
| 95 | + | this.render(); |
|
| 96 | + | } |
|
| 97 | + | ||
| 98 | + | // Wallet connection methods |
|
| 99 | + | async connect() { |
|
| 100 | + | if (window.ethereum) { |
|
| 101 | + | try { |
|
| 102 | + | this.loading = true; |
|
| 103 | + | this.render(); |
|
| 104 | + | ||
| 105 | + | const accounts = await window.ethereum.request({ |
|
| 106 | + | method: "eth_requestAccounts", |
|
| 107 | + | }); |
|
| 108 | + | ||
| 109 | + | this.address = accounts[0]; |
|
| 110 | + | ||
| 111 | + | this.currentChainId = await window.ethereum.request({ |
|
| 112 | + | method: "eth_chainId", |
|
| 113 | + | }); |
|
| 114 | + | ||
| 115 | + | if (this.chainId && this.chainId !== this.currentChainId) { |
|
| 116 | + | await this.switchChain(this.chainId); |
|
| 117 | + | } |
|
| 118 | + | ||
| 119 | + | this.connected = true; |
|
| 120 | + | ||
| 121 | + | await Promise.all([this.fetchEnsData(), this.fetchBalance()]); |
|
| 122 | + | ||
| 123 | + | this.loading = false; |
|
| 124 | + | this.render(); |
|
| 125 | + | ||
| 126 | + | const eventDetail = { |
|
| 127 | + | address: this.address, |
|
| 128 | + | ensData: this.ensData, |
|
| 129 | + | chainId: this.currentChainId, |
|
| 130 | + | }; |
|
| 131 | + | ||
| 132 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 133 | + | this.dispatchEvent( |
|
| 134 | + | new CustomEvent("wallet-connected", { |
|
| 135 | + | detail: eventDetail, |
|
| 136 | + | }), |
|
| 137 | + | ); |
|
| 138 | + | ||
| 139 | + | // Call callback property if set (React-friendly) |
|
| 140 | + | if (typeof this.onWalletConnected === "function") { |
|
| 141 | + | this.onWalletConnected(eventDetail); |
|
| 142 | + | } |
|
| 143 | + | } catch (error) { |
|
| 144 | + | console.error("Connection failed", error); |
|
| 145 | + | this.loading = false; |
|
| 146 | + | this.render(); |
|
| 147 | + | ||
| 148 | + | const errorDetail = { error: error.message }; |
|
| 149 | + | ||
| 150 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 151 | + | this.dispatchEvent( |
|
| 152 | + | new CustomEvent("wallet-error", { |
|
| 153 | + | detail: errorDetail, |
|
| 154 | + | }), |
|
| 155 | + | ); |
|
| 156 | + | ||
| 157 | + | // Call callback property if set (React-friendly) |
|
| 158 | + | if (typeof this.onWalletError === "function") { |
|
| 159 | + | this.onWalletError(errorDetail); |
|
| 160 | + | } |
|
| 161 | + | } |
|
| 162 | + | } else { |
|
| 163 | + | alert("Please install a wallet extension like MetaMask"); |
|
| 164 | + | } |
|
| 165 | + | } |
|
| 166 | + | ||
| 167 | + | disconnect() { |
|
| 168 | + | this.connected = false; |
|
| 169 | + | this.address = ""; |
|
| 170 | + | this.ensData = null; |
|
| 171 | + | this.currentChainId = null; |
|
| 172 | + | this.balance = "0"; |
|
| 173 | + | this.showPopover = false; |
|
| 174 | + | this.copySuccess = false; |
|
| 175 | + | this.render(); |
|
| 176 | + | ||
| 177 | + | // Dispatch custom event for vanilla JS and other frameworks |
|
| 178 | + | this.dispatchEvent(new CustomEvent("wallet-disconnected")); |
|
| 179 | + | ||
| 180 | + | // Call callback property if set (React-friendly) |
|
| 181 | + | if (typeof this.onWalletDisconnected === "function") { |
|
| 182 | + | this.onWalletDisconnected(); |
|
| 183 | + | } |
|
| 184 | + | } |
|
| 185 | + | ||
| 186 | + | // Chain management methods |
|
| 187 | + | /** |
|
| 188 | + | * Converts a numeric chain ID to hex format |
|
| 189 | + | * @param {string|number} chainId - Chain ID in numeric or hex format |
|
| 190 | + | * @returns {string} Chain ID in hex format (e.g., "0x2105") |
|
| 191 | + | */ |
|
| 192 | + | normalizeChainId(chainId) { |
|
| 193 | + | if (!chainId) return "0x1"; |
|
| 194 | + | ||
| 195 | + | const chainIdStr = String(chainId); |
|
| 196 | + | ||
| 197 | + | // If it's already in hex format (starts with 0x), return as-is |
|
| 198 | + | if (chainIdStr.startsWith("0x")) { |
|
| 199 | + | return chainIdStr.toLowerCase(); |
|
| 200 | + | } |
|
| 201 | + | ||
| 202 | + | // Convert numeric string to hex |
|
| 203 | + | const numericChainId = parseInt(chainIdStr, 10); |
|
| 204 | + | if (isNaN(numericChainId)) { |
|
| 205 | + | console.warn(`Invalid chain ID: ${chainId}, defaulting to 0x1`); |
|
| 206 | + | return "0x1"; |
|
| 207 | + | } |
|
| 208 | + | ||
| 209 | + | return `0x${numericChainId.toString(16)}`; |
|
| 210 | + | } |
|
| 211 | + | ||
| 212 | + | async switchChain(chainId) { |
|
| 213 | + | try { |
|
| 214 | + | await window.ethereum.request({ |
|
| 215 | + | method: "wallet_switchEthereumChain", |
|
| 216 | + | params: [{ chainId }], |
|
| 217 | + | }); |
|
| 218 | + | this.currentChainId = chainId; |
|
| 219 | + | } catch (switchError) { |
|
| 220 | + | throw new Error(`Failed to switch chain: ${switchError.message}`); |
|
| 221 | + | } |
|
| 222 | + | } |
|
| 223 | + | ||
| 224 | + | async checkAndSwitchChain() { |
|
| 225 | + | if (window.ethereum && this.chainId && this.connected) { |
|
| 226 | + | const currentChain = await window.ethereum.request({ |
|
| 227 | + | method: "eth_chainId", |
|
| 228 | + | }); |
|
| 229 | + | ||
| 230 | + | if (currentChain !== this.chainId) { |
|
| 231 | + | try { |
|
| 232 | + | await this.switchChain(this.chainId); |
|
| 233 | + | this.render(); |
|
| 234 | + | } catch (error) { |
|
| 235 | + | console.error("Failed to switch chain:", error); |
|
| 236 | + | } |
|
| 237 | + | } |
|
| 238 | + | } |
|
| 239 | + | } |
|
| 240 | + | ||
| 241 | + | getChainName(chainId) { |
|
| 242 | + | const chainNames = { |
|
| 243 | + | "0x1": "Ethereum", |
|
| 244 | + | "0x89": "Polygon", |
|
| 245 | + | "0xa": "Optimism", |
|
| 246 | + | "0xa4b1": "Arbitrum", |
|
| 247 | + | "0x2105": "Base", |
|
| 248 | + | }; |
|
| 249 | + | return chainNames[chainId] || `Chain ${chainId}`; |
|
| 250 | + | } |
|
| 251 | + | ||
| 252 | + | // Data fetching methods |
|
| 253 | + | async fetchEnsData() { |
|
| 254 | + | try { |
|
| 255 | + | const response = await fetch(`https://api.ensdata.net/${this.address}`); |
|
| 256 | + | if (response.ok) { |
|
| 257 | + | this.ensData = await response.json(); |
|
| 258 | + | console.log("ENS data loaded:", this.ensData); |
|
| 259 | + | } else { |
|
| 260 | + | console.log("No ENS data found for this address"); |
|
| 261 | + | this.ensData = null; |
|
| 262 | + | } |
|
| 263 | + | } catch (error) { |
|
| 264 | + | console.error("Failed to fetch ENS data", error); |
|
| 265 | + | this.ensData = null; |
|
| 266 | + | } |
|
| 267 | + | } |
|
| 268 | + | ||
| 269 | + | async fetchBalance() { |
|
| 270 | + | try { |
|
| 271 | + | const balanceWei = await window.ethereum.request({ |
|
| 272 | + | method: "eth_getBalance", |
|
| 273 | + | params: [this.address, "latest"], |
|
| 274 | + | }); |
|
| 275 | + | ||
| 276 | + | const balanceEth = parseInt(balanceWei, 16) / Math.pow(10, 18); |
|
| 277 | + | this.balance = balanceEth.toFixed(4); |
|
| 278 | + | } catch (error) { |
|
| 279 | + | console.error("Failed to fetch balance", error); |
|
| 280 | + | this.balance = "0"; |
|
| 281 | + | } |
|
| 282 | + | } |
|
| 283 | + | ||
| 284 | + | // UI helper methods |
|
| 285 | + | getDisplayName() { |
|
| 286 | + | if (this.ensData?.ens_primary) { |
|
| 287 | + | return this.ensData.ens_primary; |
|
| 288 | + | } |
|
| 289 | + | return this.truncateAddress(this.address); |
|
| 290 | + | } |
|
| 291 | + | ||
| 292 | + | truncateAddress(addr) { |
|
| 293 | + | if (!addr) return ""; |
|
| 294 | + | return addr.slice(0, 5) + "..." + addr.slice(-5); |
|
| 295 | + | } |
|
| 296 | + | ||
| 297 | + | async copyAddress() { |
|
| 298 | + | try { |
|
| 299 | + | await navigator.clipboard.writeText(this.address); |
|
| 300 | + | this.copySuccess = true; |
|
| 301 | + | this.showPopoverElement(); |
|
| 302 | + | ||
| 303 | + | setTimeout(() => { |
|
| 304 | + | this.copySuccess = false; |
|
| 305 | + | this.showPopoverElement(); |
|
| 306 | + | }, 1000); |
|
| 307 | + | } catch (error) { |
|
| 308 | + | console.error("Failed to copy address", error); |
|
| 309 | + | } |
|
| 310 | + | } |
|
| 311 | + | ||
| 312 | + | // Popover management methods |
|
| 313 | + | togglePopover() { |
|
| 314 | + | this.showPopover = !this.showPopover; |
|
| 315 | + | if (this.showPopover) { |
|
| 316 | + | this.showPopoverElement(); |
|
| 317 | + | } else { |
|
| 318 | + | this.hidePopoverElement(); |
|
| 319 | + | } |
|
| 320 | + | } |
|
| 321 | + | ||
| 322 | + | hidePopover() { |
|
| 323 | + | if (this.showPopover) { |
|
| 324 | + | this.showPopover = false; |
|
| 325 | + | this.hidePopoverElement(); |
|
| 326 | + | } |
|
| 327 | + | } |
|
| 328 | + | ||
| 329 | + | showPopoverElement() { |
|
| 330 | + | const profileContainer = |
|
| 331 | + | this.shadowRoot.querySelector(".profile-container"); |
|
| 332 | + | if (!profileContainer) return; |
|
| 333 | + | ||
| 334 | + | const existingPopover = profileContainer.querySelector(".popover"); |
|
| 335 | + | if (existingPopover) { |
|
| 336 | + | existingPopover.remove(); |
|
| 337 | + | } |
|
| 338 | + | ||
| 339 | + | const popover = document.createElement("div"); |
|
| 340 | + | popover.className = "popover"; |
|
| 341 | + | ||
| 342 | + | const copyIcon = this.copySuccess |
|
| 343 | + | ? `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>` |
|
| 344 | + | : `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 12.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>`; |
|
| 345 | + | ||
| 346 | + | const copyText = this.copySuccess ? "Copied!" : "Copy Address"; |
|
| 347 | + | popover.innerHTML = ` |
|
| 348 | + | <button class="popover-button copy-button"> |
|
| 349 | + | <span>${copyIcon}</span> |
|
| 350 | + | ${copyText} |
|
| 351 | + | </button> |
|
| 352 | + | <button class="popover-button disconnect-button"> |
|
| 353 | + | <span><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 1C2.44771 1 2 1.44772 2 2V13C2 13.5523 2.44772 14 3 14H10.5C10.7761 14 11 13.7761 11 13.5C11 13.2239 10.7761 13 10.5 13H3V2L10.5 2C10.7761 2 11 1.77614 11 1.5C11 1.22386 10.7761 1 10.5 1H3ZM12.6036 4.89645C12.4083 4.70118 12.0917 4.70118 11.8964 4.89645C11.7012 5.09171 11.7012 5.40829 11.8964 5.60355L13.2929 7H6.5C6.22386 7 6 7.22386 6 7.5C6 7.77614 6.22386 8 6.5 8H13.2929L11.8964 9.39645C11.7012 9.59171 11.7012 9.90829 11.8964 10.1036C12.0917 10.2988 12.4083 10.2988 12.6036 10.1036L14.8536 7.85355C15.0488 7.65829 15.0488 7.34171 14.8536 7.14645L12.6036 4.89645Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></span> |
|
| 354 | + | Disconnect |
|
| 355 | + | </button> |
|
| 356 | + | `; |
|
| 357 | + | ||
| 358 | + | popover.querySelector(".copy-button").addEventListener("click", (e) => { |
|
| 359 | + | e.stopPropagation(); |
|
| 360 | + | this.copyAddress(); |
|
| 361 | + | }); |
|
| 362 | + | ||
| 363 | + | popover |
|
| 364 | + | .querySelector(".disconnect-button") |
|
| 365 | + | .addEventListener("click", (e) => { |
|
| 366 | + | e.stopPropagation(); |
|
| 367 | + | this.disconnect(); |
|
| 368 | + | }); |
|
| 369 | + | ||
| 370 | + | profileContainer.appendChild(popover); |
|
| 371 | + | ||
| 372 | + | setTimeout(() => { |
|
| 373 | + | document.addEventListener("click", this.hidePopover.bind(this), { |
|
| 374 | + | once: true, |
|
| 375 | + | }); |
|
| 376 | + | }, 0); |
|
| 377 | + | } |
|
| 378 | + | ||
| 379 | + | hidePopoverElement() { |
|
| 380 | + | const profileContainer = |
|
| 381 | + | this.shadowRoot.querySelector(".profile-container"); |
|
| 382 | + | if (!profileContainer) return; |
|
| 383 | + | ||
| 384 | + | const popover = profileContainer.querySelector(".popover"); |
|
| 385 | + | if (popover) { |
|
| 386 | + | popover.remove(); |
|
| 387 | + | } |
|
| 388 | + | } |
|
| 389 | + | ||
| 390 | + | // Color helper methods |
|
| 391 | + | getCSSVariable(name, defaultValue) { |
|
| 392 | + | return this.getAttribute(name) || defaultValue; |
|
| 393 | + | } |
|
| 394 | + | ||
| 395 | + | // Render methods and styling |
|
| 396 | + | render() { |
|
| 397 | + | const background = this.getCSSVariable("background", "#232323"); |
|
| 398 | + | const foreground = this.getCSSVariable("foreground", "#ffffff"); |
|
| 399 | + | const primary = this.getCSSVariable("primary", "#5F8787"); |
|
| 400 | + | const secondary = this.getCSSVariable("secondary", "#6F9797"); |
|
| 401 | + | const borderRadius = this.getCSSVariable("border-radius", "4px"); |
|
| 402 | + | ||
| 403 | + | this.shadowRoot.innerHTML = ` |
|
| 404 | + | <style> |
|
| 405 | + | :host { |
|
| 406 | + | --color-background: ${background}; |
|
| 407 | + | --color-foreground: ${foreground}; |
|
| 408 | + | --color-primary: ${primary}; |
|
| 409 | + | --color-secondary: ${secondary}; |
|
| 410 | + | --border-radius: ${borderRadius}; |
|
| 411 | + | --bg-color: ${this.connected ? "var(--color-background)" : "var(--color-primary)"}; |
|
| 412 | + | --bg-hover-color: ${this.connected ? "var(--color-background)" : "var(--color-secondary)"}; |
|
| 413 | + | display: inline-block; |
|
| 414 | + | } |
|
| 415 | + | ||
| 416 | + | button { |
|
| 417 | + | padding: 10px 20px; |
|
| 418 | + | background: var(--bg-color); |
|
| 419 | + | color: var(--color-foreground); |
|
| 420 | + | border: none; |
|
| 421 | + | border-radius: var(--border-radius); |
|
| 422 | + | cursor: pointer; |
|
| 423 | + | font-size: 16px; |
|
| 424 | + | transition: background-color 0.3s ease; |
|
| 425 | + | } |
|
| 426 | + | ||
| 427 | + | button:hover { |
|
| 428 | + | background: var(--bg-hover-color); |
|
| 429 | + | } |
|
| 430 | + | ||
| 431 | + | button:disabled { |
|
| 432 | + | opacity: 0.7; |
|
| 433 | + | cursor: not-allowed; |
|
| 434 | + | } |
|
| 435 | + | ||
| 436 | + | .profile-container { |
|
| 437 | + | position: relative; |
|
| 438 | + | display: inline-block; |
|
| 439 | + | font-family: sans-serif; |
|
| 440 | + | } |
|
| 441 | + | ||
| 442 | + | .profile { |
|
| 443 | + | display: flex; |
|
| 444 | + | align-items: center; |
|
| 445 | + | gap: 8px; |
|
| 446 | + | padding: 10px 20px; |
|
| 447 | + | background: var(--bg-color); |
|
| 448 | + | border-radius: var(--border-radius); |
|
| 449 | + | color: var(--color-foreground); |
|
| 450 | + | min-width: auto; |
|
| 451 | + | transition: background-color 0.3s ease; |
|
| 452 | + | cursor: pointer; |
|
| 453 | + | } |
|
| 454 | + | ||
| 455 | + | .profile:hover { |
|
| 456 | + | background: var(--bg-hover-color); |
|
| 457 | + | } |
|
| 458 | + | ||
| 459 | + | .popover { |
|
| 460 | + | position: absolute; |
|
| 461 | + | top: 100%; |
|
| 462 | + | left: 0; |
|
| 463 | + | right: 0; |
|
| 464 | + | background: var(--bg-color); |
|
| 465 | + | border: 1px solid rgba(255, 255, 255, 0.1); |
|
| 466 | + | border-radius: var(--border-radius); |
|
| 467 | + | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); |
|
| 468 | + | z-index: 1000; |
|
| 469 | + | margin-top: 4px; |
|
| 470 | + | overflow: hidden; |
|
| 471 | + | } |
|
| 472 | + | ||
| 473 | + | .popover-button { |
|
| 474 | + | display: flex; |
|
| 475 | + | align-items: center; |
|
| 476 | + | gap: 8px; |
|
| 477 | + | width: 100%; |
|
| 478 | + | padding: 10px 16px; |
|
| 479 | + | background: var(--bg-color); |
|
| 480 | + | border: none; |
|
| 481 | + | color: var(--color-foreground); |
|
| 482 | + | font-size: 14px; |
|
| 483 | + | cursor: pointer; |
|
| 484 | + | transition: background-color 0.2s ease; |
|
| 485 | + | } |
|
| 486 | + | ||
| 487 | + | .popover-button:hover { |
|
| 488 | + | background: var(--bg-hover-color); |
|
| 489 | + | } |
|
| 490 | + | ||
| 491 | + | .popover-button:not(:last-child) { |
|
| 492 | + | border-bottom: 1px solid rgba(255, 255, 255, 0.1); |
|
| 493 | + | } |
|
| 494 | + | ||
| 495 | + | .popover-button span { |
|
| 496 | + | font-size: 16px; |
|
| 497 | + | } |
|
| 498 | + | ||
| 499 | + | .avatar { |
|
| 500 | + | width: 32px; |
|
| 501 | + | height: 32px; |
|
| 502 | + | border-radius: 50%; |
|
| 503 | + | object-fit: cover; |
|
| 504 | + | } |
|
| 505 | + | ||
| 506 | + | .avatar-placeholder { |
|
| 507 | + | width: 32px; |
|
| 508 | + | height: 32px; |
|
| 509 | + | border-radius: 50%; |
|
| 510 | + | background: linear-gradient(45deg, var(--color-primary), var(--color-secondary)); |
|
| 511 | + | display: flex; |
|
| 512 | + | align-items: center; |
|
| 513 | + | justify-content: center; |
|
| 514 | + | color: var(--color-foreground); |
|
| 515 | + | font-weight: bold; |
|
| 516 | + | font-size: 12px; |
|
| 517 | + | } |
|
| 518 | + | ||
| 519 | + | .profile-info { |
|
| 520 | + | flex: 1; |
|
| 521 | + | min-width: 0; |
|
| 522 | + | } |
|
| 523 | + | ||
| 524 | + | .profile-info h4 { |
|
| 525 | + | margin: 0 0 2px 0; |
|
| 526 | + | font-size: 14px; |
|
| 527 | + | font-weight: 600; |
|
| 528 | + | white-space: nowrap; |
|
| 529 | + | overflow: hidden; |
|
| 530 | + | text-overflow: ellipsis; |
|
| 531 | + | } |
|
| 532 | + | ||
| 533 | + | .profile-info p { |
|
| 534 | + | margin: 0; |
|
| 535 | + | font-size: 12px; |
|
| 536 | + | opacity: 0.8; |
|
| 537 | + | white-space: nowrap; |
|
| 538 | + | overflow: hidden; |
|
| 539 | + | text-overflow: ellipsis; |
|
| 540 | + | font-family: monospace; |
|
| 541 | + | } |
|
| 542 | + | ||
| 543 | + | .loading { |
|
| 544 | + | display: flex; |
|
| 545 | + | align-items: center; |
|
| 546 | + | gap: 8px; |
|
| 547 | + | } |
|
| 548 | + | ||
| 549 | + | .spinner { |
|
| 550 | + | width: 16px; |
|
| 551 | + | height: 16px; |
|
| 552 | + | border: 2px solid rgba(255, 255, 255, 0.3); |
|
| 553 | + | border-top: 2px solid var(--color-foreground); |
|
| 554 | + | border-radius: 50%; |
|
| 555 | + | animation: spin 1s linear infinite; |
|
| 556 | + | } |
|
| 557 | + | ||
| 558 | + | @keyframes spin { |
|
| 559 | + | from { transform: rotate(0deg); } |
|
| 560 | + | to { transform: rotate(360deg); } |
|
| 561 | + | } |
|
| 562 | + | </style> |
|
| 563 | + | `; |
|
| 564 | + | ||
| 565 | + | if (this.loading) { |
|
| 566 | + | this.renderLoading(); |
|
| 567 | + | } else if (this.connected) { |
|
| 568 | + | this.renderProfile(); |
|
| 569 | + | } else { |
|
| 570 | + | this.renderConnectButton(); |
|
| 571 | + | } |
|
| 572 | + | } |
|
| 573 | + | ||
| 574 | + | renderProfile() { |
|
| 575 | + | const profileContainer = document.createElement("div"); |
|
| 576 | + | profileContainer.className = "profile-container"; |
|
| 577 | + | ||
| 578 | + | const profileDiv = document.createElement("div"); |
|
| 579 | + | profileDiv.className = "profile"; |
|
| 580 | + | ||
| 581 | + | const avatar = this.ensData?.avatar_small; |
|
| 582 | + | const displayName = this.getDisplayName(); |
|
| 583 | + | ||
| 584 | + | let avatarElement = ""; |
|
| 585 | + | if (avatar) { |
|
| 586 | + | avatarElement = `<img src="${avatar}" alt="Avatar" class="avatar" onerror="this.style.display='none'">`; |
|
| 587 | + | } else { |
|
| 588 | + | avatarElement = `<div class="avatar-placeholder"></div>`; |
|
| 589 | + | } |
|
| 590 | + | ||
| 591 | + | profileDiv.innerHTML = ` |
|
| 592 | + | ${avatarElement} |
|
| 593 | + | <div class="profile-info"> |
|
| 594 | + | <h4>${displayName}</h4> |
|
| 595 | + | <p>${this.balance} ETH</p> |
|
| 596 | + | </div> |
|
| 597 | + | `; |
|
| 598 | + | ||
| 599 | + | profileDiv.addEventListener("click", (e) => { |
|
| 600 | + | e.stopPropagation(); |
|
| 601 | + | this.togglePopover(); |
|
| 602 | + | }); |
|
| 603 | + | ||
| 604 | + | profileContainer.appendChild(profileDiv); |
|
| 605 | + | this.shadowRoot.appendChild(profileContainer); |
|
| 606 | + | ||
| 607 | + | if (this.showPopover) { |
|
| 608 | + | this.showPopoverElement(); |
|
| 609 | + | } |
|
| 610 | + | } |
|
| 611 | + | ||
| 612 | + | renderLoading() { |
|
| 613 | + | const button = document.createElement("button"); |
|
| 614 | + | button.disabled = true; |
|
| 615 | + | button.innerHTML = ` |
|
| 616 | + | <div class="loading"> |
|
| 617 | + | <div class="spinner"></div> |
|
| 618 | + | <span>Connecting...</span> |
|
| 619 | + | </div> |
|
| 620 | + | `; |
|
| 621 | + | this.shadowRoot.appendChild(button); |
|
| 622 | + | } |
|
| 623 | + | ||
| 624 | + | renderConnectButton() { |
|
| 625 | + | const button = document.createElement("button"); |
|
| 626 | + | button.textContent = "Connect Wallet"; |
|
| 627 | + | button.addEventListener("click", () => this.connect()); |
|
| 628 | + | this.shadowRoot.appendChild(button); |
|
| 629 | + | } |
|
| 630 | + | } |
|
| 631 | + | ||
| 632 | + | customElements.define("connect-wallet", ConnectWallet); |
| 1 | + | interface ContractCallElement extends HTMLElement { |
|
| 2 | + | setAttribute('contract-address', value: string): void; |
|
| 3 | + | setAttribute('chain-id', value: string): void; |
|
| 4 | + | setAttribute('method-name', value: string): void; |
|
| 5 | + | setAttribute('method-args', value: string): void; |
|
| 6 | + | setAttribute('abi-url', value: string): void; |
|
| 7 | + | setAttribute('abi', value: string): void; |
|
| 8 | + | setAttribute('button-text', value: string): void; |
|
| 9 | + | setAttribute('background', value: string): void; |
|
| 10 | + | setAttribute('foreground', value: string): void; |
|
| 11 | + | setAttribute('primary', value: string): void; |
|
| 12 | + | setAttribute('secondary', value: string): void; |
|
| 13 | + | setAttribute('border-radius', value: string): void; |
|
| 14 | + | setAttribute('error-color', value: string): void; |
|
| 15 | + | setAttribute('success-color', value: string): void; |
|
| 16 | + | addEventListener(type: 'abi-loaded', listener: (event: CustomEvent) => void): void; |
|
| 17 | + | addEventListener(type: 'abi-error', listener: (event: CustomEvent) => void): void; |
|
| 18 | + | addEventListener(type: 'contract-call-success', listener: (event: CustomEvent) => void): void; |
|
| 19 | + | addEventListener(type: 'contract-call-error', listener: (event: CustomEvent) => void): void; |
|
| 20 | + | } |
|
| 21 | + | ||
| 22 | + | interface ConnectWalletElement extends HTMLElement { |
|
| 23 | + | setAttribute('chain-id', value: string): void; |
|
| 24 | + | setAttribute('background', value: string): void; |
|
| 25 | + | setAttribute('foreground', value: string): void; |
|
| 26 | + | setAttribute('primary', value: string): void; |
|
| 27 | + | setAttribute('secondary', value: string): void; |
|
| 28 | + | setAttribute('border-radius', value: string): void; |
|
| 29 | + | addEventListener(type: 'wallet-connected', listener: (event: CustomEvent) => void): void; |
|
| 30 | + | addEventListener(type: 'wallet-error', listener: (event: CustomEvent) => void): void; |
|
| 31 | + | addEventListener(type: 'wallet-disconnected', listener: (event: CustomEvent) => void): void; |
|
| 32 | + | } |
|
| 33 | + | ||
| 34 | + | declare global { |
|
| 35 | + | interface HTMLElementTagNameMap { |
|
| 36 | + | 'contract-call': ContractCallElement; |
|
| 37 | + | 'connect-wallet': ConnectWalletElement; |
|
| 38 | + | } |
|
| 39 | + | } |
|
| 40 | + | ||
| 41 | + | export {}; |
| 1 | + | export function setupCounter(element: HTMLButtonElement) { |
|
| 2 | + | let counter = 0 |
|
| 3 | + | const setCounter = (count: number) => { |
|
| 4 | + | counter = count |
|
| 5 | + | element.innerHTML = `count is ${counter}` |
|
| 6 | + | } |
|
| 7 | + | element.addEventListener('click', () => setCounter(counter + 1)) |
|
| 8 | + | setCounter(0) |
|
| 9 | + | } |
| 1 | + | import "./style.css"; |
|
| 2 | + | import typescriptLogo from "./typescript.svg"; |
|
| 3 | + | import viteLogo from "/vite.svg"; |
|
| 4 | + | import { setupCounter } from "./counter.ts"; |
|
| 5 | + | import "./components/connect-wallet"; |
|
| 6 | + | ||
| 7 | + | document.querySelector<HTMLDivElement>("#app")!.innerHTML = ` |
|
| 8 | + | <div> |
|
| 9 | + | <a href="https://vite.dev" target="_blank"> |
|
| 10 | + | <img src="${viteLogo}" class="logo" alt="Vite logo" /> |
|
| 11 | + | </a> |
|
| 12 | + | <a href="https://www.typescriptlang.org/" target="_blank"> |
|
| 13 | + | <img src="${typescriptLogo}" class="logo vanilla" alt="TypeScript logo" /> |
|
| 14 | + | </a> |
|
| 15 | + | <h1>Vite + TypeScript</h1> |
|
| 16 | + | <div class="card"> |
|
| 17 | + | <connect-wallet |
|
| 18 | + | chain-id="11155111" |
|
| 19 | + | ></connect-wallet> |
|
| 20 | + | </div> |
|
| 21 | + | <p class="read-the-docs"> |
|
| 22 | + | Click on the Vite and TypeScript logos to learn more |
|
| 23 | + | </p> |
|
| 24 | + | </div> |
|
| 25 | + | `; |
|
| 26 | + | ||
| 27 | + | setupCounter(document.querySelector<HTMLButtonElement>("#counter")!); |
| 1 | + | :root { |
|
| 2 | + | font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; |
|
| 3 | + | line-height: 1.5; |
|
| 4 | + | font-weight: 400; |
|
| 5 | + | ||
| 6 | + | color-scheme: light dark; |
|
| 7 | + | color: rgba(255, 255, 255, 0.87); |
|
| 8 | + | background-color: #242424; |
|
| 9 | + | ||
| 10 | + | font-synthesis: none; |
|
| 11 | + | text-rendering: optimizeLegibility; |
|
| 12 | + | -webkit-font-smoothing: antialiased; |
|
| 13 | + | -moz-osx-font-smoothing: grayscale; |
|
| 14 | + | } |
|
| 15 | + | ||
| 16 | + | a { |
|
| 17 | + | font-weight: 500; |
|
| 18 | + | color: #646cff; |
|
| 19 | + | text-decoration: inherit; |
|
| 20 | + | } |
|
| 21 | + | a:hover { |
|
| 22 | + | color: #535bf2; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | body { |
|
| 26 | + | margin: 0; |
|
| 27 | + | display: flex; |
|
| 28 | + | place-items: center; |
|
| 29 | + | min-width: 320px; |
|
| 30 | + | min-height: 100vh; |
|
| 31 | + | } |
|
| 32 | + | ||
| 33 | + | h1 { |
|
| 34 | + | font-size: 3.2em; |
|
| 35 | + | line-height: 1.1; |
|
| 36 | + | } |
|
| 37 | + | ||
| 38 | + | #app { |
|
| 39 | + | max-width: 1280px; |
|
| 40 | + | margin: 0 auto; |
|
| 41 | + | padding: 2rem; |
|
| 42 | + | text-align: center; |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | .logo { |
|
| 46 | + | height: 6em; |
|
| 47 | + | padding: 1.5em; |
|
| 48 | + | will-change: filter; |
|
| 49 | + | transition: filter 300ms; |
|
| 50 | + | } |
|
| 51 | + | .logo:hover { |
|
| 52 | + | filter: drop-shadow(0 0 2em #646cffaa); |
|
| 53 | + | } |
|
| 54 | + | .logo.vanilla:hover { |
|
| 55 | + | filter: drop-shadow(0 0 2em #3178c6aa); |
|
| 56 | + | } |
|
| 57 | + | ||
| 58 | + | .card { |
|
| 59 | + | padding: 2em; |
|
| 60 | + | } |
|
| 61 | + | ||
| 62 | + | .read-the-docs { |
|
| 63 | + | color: #888; |
|
| 64 | + | } |
|
| 65 | + | ||
| 66 | + | button { |
|
| 67 | + | border-radius: 8px; |
|
| 68 | + | border: 1px solid transparent; |
|
| 69 | + | padding: 0.6em 1.2em; |
|
| 70 | + | font-size: 1em; |
|
| 71 | + | font-weight: 500; |
|
| 72 | + | font-family: inherit; |
|
| 73 | + | background-color: #1a1a1a; |
|
| 74 | + | cursor: pointer; |
|
| 75 | + | transition: border-color 0.25s; |
|
| 76 | + | } |
|
| 77 | + | button:hover { |
|
| 78 | + | border-color: #646cff; |
|
| 79 | + | } |
|
| 80 | + | button:focus, |
|
| 81 | + | button:focus-visible { |
|
| 82 | + | outline: 4px auto -webkit-focus-ring-color; |
|
| 83 | + | } |
|
| 84 | + | ||
| 85 | + | @media (prefers-color-scheme: light) { |
|
| 86 | + | :root { |
|
| 87 | + | color: #213547; |
|
| 88 | + | background-color: #ffffff; |
|
| 89 | + | } |
|
| 90 | + | a:hover { |
|
| 91 | + | color: #747bff; |
|
| 92 | + | } |
|
| 93 | + | button { |
|
| 94 | + | background-color: #f9f9f9; |
|
| 95 | + | } |
|
| 96 | + | } |
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#007ACC" d="M0 128v128h256V0H0z"></path><path fill="#FFF" d="m56.612 128.85l-.081 10.483h33.32v94.68h23.568v-94.68h33.321v-10.28c0-5.69-.122-10.444-.284-10.566c-.122-.162-20.4-.244-44.983-.203l-44.74.122l-.121 10.443Zm149.955-10.742c6.501 1.625 11.459 4.51 16.01 9.224c2.357 2.52 5.851 7.111 6.136 8.208c.08.325-11.053 7.802-17.798 11.988c-.244.162-1.22-.894-2.317-2.52c-3.291-4.795-6.745-6.867-12.028-7.233c-7.76-.528-12.759 3.535-12.718 10.321c0 1.992.284 3.17 1.097 4.795c1.707 3.536 4.876 5.649 14.832 9.956c18.326 7.883 26.168 13.084 31.045 20.48c5.445 8.249 6.664 21.415 2.966 31.208c-4.063 10.646-14.14 17.879-28.323 20.276c-4.388.772-14.79.65-19.504-.203c-10.28-1.828-20.033-6.908-26.047-13.572c-2.357-2.6-6.949-9.387-6.664-9.874c.122-.163 1.178-.813 2.356-1.504c1.138-.65 5.446-3.129 9.509-5.485l7.355-4.267l1.544 2.276c2.154 3.29 6.867 7.801 9.712 9.305c8.167 4.307 19.383 3.698 24.909-1.26c2.357-2.153 3.332-4.388 3.332-7.68c0-2.966-.366-4.266-1.91-6.501c-1.99-2.845-6.054-5.242-17.595-10.24c-13.206-5.69-18.895-9.224-24.096-14.832c-3.007-3.25-5.852-8.452-7.03-12.8c-.975-3.617-1.22-12.678-.447-16.335c2.723-12.76 12.353-21.659 26.25-24.3c4.51-.853 14.994-.528 19.424.569Z"></path></svg> |
| 1 | + | { |
|
| 2 | + | "compilerOptions": { |
|
| 3 | + | "target": "ES2022", |
|
| 4 | + | "useDefineForClassFields": true, |
|
| 5 | + | "module": "ESNext", |
|
| 6 | + | "lib": ["ES2022", "DOM", "DOM.Iterable"], |
|
| 7 | + | "types": ["vite/client"], |
|
| 8 | + | "skipLibCheck": true, |
|
| 9 | + | ||
| 10 | + | /* Bundler mode */ |
|
| 11 | + | "moduleResolution": "bundler", |
|
| 12 | + | "allowImportingTsExtensions": true, |
|
| 13 | + | "verbatimModuleSyntax": true, |
|
| 14 | + | "moduleDetection": "force", |
|
| 15 | + | "noEmit": true, |
|
| 16 | + | ||
| 17 | + | /* Linting */ |
|
| 18 | + | "strict": true, |
|
| 19 | + | "noUnusedLocals": true, |
|
| 20 | + | "noUnusedParameters": true, |
|
| 21 | + | "erasableSyntaxOnly": true, |
|
| 22 | + | "noFallthroughCasesInSwitch": true, |
|
| 23 | + | "noUncheckedSideEffectImports": true |
|
| 24 | + | }, |
|
| 25 | + | "include": ["src"] |
|
| 26 | + | } |
| 4 | 4 | import { join } from "node:path"; |
|
| 5 | 5 | ||
| 6 | 6 | const COMPONENTS_DIR = "src/components"; |
|
| 7 | - | const OUTPUT_PATH = "dist/custom-elements-jsx.d.ts"; |
|
| 7 | + | const OUTPUT_DIR = "dist"; |
|
| 8 | + | const REACT_OUTPUT = "custom-elements-jsx.ts"; |
|
| 9 | + | const SVELTE_OUTPUT = "custom-elements-svelte.ts"; |
|
| 10 | + | const TYPESCRIPT_OUTPUT = "custom-elements.ts"; |
|
| 8 | 11 | ||
| 9 | 12 | interface ComponentInfo { |
|
| 10 | 13 | tagName: string; |
|
| 69 | 72 | }; |
|
| 70 | 73 | } |
|
| 71 | 74 | ||
| 72 | - | function generateJSXTypes(components: ComponentInfo[]): string { |
|
| 75 | + | function generateReactTypes(components: ComponentInfo[]): string { |
|
| 73 | 76 | const intrinsicElements = components |
|
| 74 | 77 | .map((comp) => { |
|
| 75 | 78 | const attributeProps = comp.attributes |
|
| 122 | 125 | `; |
|
| 123 | 126 | } |
|
| 124 | 127 | ||
| 128 | + | function generateSvelteTypes(components: ComponentInfo[]): string { |
|
| 129 | + | const svelteHTMLElements = components |
|
| 130 | + | .map((comp) => { |
|
| 131 | + | const attributeProps = comp.attributes |
|
| 132 | + | .map((attr) => ` '${attr}'?: string;`) |
|
| 133 | + | .join("\n"); |
|
| 134 | + | ||
| 135 | + | const eventHandlers = comp.events |
|
| 136 | + | .map((event) => { |
|
| 137 | + | return ` 'on:${event}'?: (event: CustomEvent) => void;`; |
|
| 138 | + | }) |
|
| 139 | + | .join("\n"); |
|
| 140 | + | ||
| 141 | + | const allProps = [attributeProps, eventHandlers] |
|
| 142 | + | .filter((p) => p) |
|
| 143 | + | .join("\n"); |
|
| 144 | + | ||
| 145 | + | return ` '${comp.tagName}': {\n${allProps}\n };`; |
|
| 146 | + | }) |
|
| 147 | + | .join("\n"); |
|
| 148 | + | ||
| 149 | + | return `declare module 'svelte/elements' { |
|
| 150 | + | export interface SvelteHTMLElements { |
|
| 151 | + | ${svelteHTMLElements} |
|
| 152 | + | } |
|
| 153 | + | } |
|
| 154 | + | ||
| 155 | + | export {}; |
|
| 156 | + | `; |
|
| 157 | + | } |
|
| 158 | + | ||
| 159 | + | function generateTypeScriptTypes(components: ComponentInfo[]): string { |
|
| 160 | + | const elementInterfaces = components |
|
| 161 | + | .map((comp) => { |
|
| 162 | + | const attributeProps = comp.attributes |
|
| 163 | + | .map((attr) => ` setAttribute('${attr}', value: string): void;`) |
|
| 164 | + | .join("\n"); |
|
| 165 | + | ||
| 166 | + | const eventHandlers = comp.events |
|
| 167 | + | .map((event) => { |
|
| 168 | + | return ` addEventListener(type: '${event}', listener: (event: CustomEvent) => void): void;`; |
|
| 169 | + | }) |
|
| 170 | + | .join("\n"); |
|
| 171 | + | ||
| 172 | + | return `interface ${toPascalCase(comp.tagName)}Element extends HTMLElement { |
|
| 173 | + | ${attributeProps} |
|
| 174 | + | ${eventHandlers} |
|
| 175 | + | }`; |
|
| 176 | + | }) |
|
| 177 | + | .join("\n\n"); |
|
| 178 | + | ||
| 179 | + | const htmlElementTagMap = components |
|
| 180 | + | .map((comp) => { |
|
| 181 | + | return ` '${comp.tagName}': ${toPascalCase(comp.tagName)}Element;`; |
|
| 182 | + | }) |
|
| 183 | + | .join("\n"); |
|
| 184 | + | ||
| 185 | + | return `${elementInterfaces} |
|
| 186 | + | ||
| 187 | + | declare global { |
|
| 188 | + | interface HTMLElementTagNameMap { |
|
| 189 | + | ${htmlElementTagMap} |
|
| 190 | + | } |
|
| 191 | + | } |
|
| 192 | + | ||
| 193 | + | export {}; |
|
| 194 | + | `; |
|
| 195 | + | } |
|
| 196 | + | ||
| 197 | + | function toPascalCase(str: string): string { |
|
| 198 | + | return str |
|
| 199 | + | .split("-") |
|
| 200 | + | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) |
|
| 201 | + | .join(""); |
|
| 202 | + | } |
|
| 203 | + | ||
| 125 | 204 | async function main() { |
|
| 126 | 205 | try { |
|
| 127 | - | console.log("🔧 Building JSX types..."); |
|
| 206 | + | console.log("🔧 Building type definitions..."); |
|
| 128 | 207 | ||
| 129 | 208 | // Read component files |
|
| 130 | 209 | const files = await readdir(COMPONENTS_DIR); |
|
| 142 | 221 | ||
| 143 | 222 | console.log(`📦 Found ${components.length} custom elements`); |
|
| 144 | 223 | ||
| 145 | - | // Generate JSX intrinsic elements types |
|
| 146 | - | const jsxTypesCode = generateJSXTypes(components); |
|
| 147 | - | await writeFile(OUTPUT_PATH, jsxTypesCode); |
|
| 148 | - | console.log(`✅ Generated JSX types: ${OUTPUT_PATH}`); |
|
| 224 | + | // Generate React types |
|
| 225 | + | const reactTypesCode = generateReactTypes(components); |
|
| 226 | + | await writeFile(join(OUTPUT_DIR, REACT_OUTPUT), reactTypesCode); |
|
| 227 | + | console.log(`✅ Generated React types: ${REACT_OUTPUT}`); |
|
| 149 | 228 | ||
| 150 | - | console.log("🎉 JSX types generated successfully!"); |
|
| 229 | + | // Generate Svelte types |
|
| 230 | + | const svelteTypesCode = generateSvelteTypes(components); |
|
| 231 | + | await writeFile(join(OUTPUT_DIR, SVELTE_OUTPUT), svelteTypesCode); |
|
| 232 | + | console.log(`✅ Generated Svelte types: ${SVELTE_OUTPUT}`); |
|
| 233 | + | ||
| 234 | + | // Generate TypeScript types |
|
| 235 | + | const tsTypesCode = generateTypeScriptTypes(components); |
|
| 236 | + | await writeFile(join(OUTPUT_DIR, TYPESCRIPT_OUTPUT), tsTypesCode); |
|
| 237 | + | console.log(`✅ Generated TypeScript types: ${TYPESCRIPT_OUTPUT}`); |
|
| 238 | + | ||
| 239 | + | console.log("🎉 Type definitions generated successfully!"); |
|
| 151 | 240 | } catch (error) { |
|
| 152 | - | console.error("❌ Error generating JSX types:", error); |
|
| 241 | + | console.error("❌ Error generating type definitions:", error); |
|
| 153 | 242 | process.exit(1); |
|
| 154 | 243 | } |
|
| 155 | 244 | } |
|
| 21 | 21 | interface NornsConfig { |
|
| 22 | 22 | components: string; |
|
| 23 | 23 | includeTypes?: boolean; |
|
| 24 | + | framework?: "typescript" | "react" | "svelte"; |
|
| 24 | 25 | } |
|
| 25 | 26 | ||
| 26 | 27 | const DEFAULT_CONFIG: NornsConfig = { |
|
| 27 | 28 | components: "src/components", |
|
| 28 | 29 | includeTypes: true, |
|
| 30 | + | framework: "typescript", |
|
| 29 | 31 | }; |
|
| 30 | 32 | ||
| 31 | 33 | async function loadConfig(): Promise<NornsConfig | null> { |
|
| 100 | 102 | ||
| 101 | 103 | // Get TypeScript types preference |
|
| 102 | 104 | const includeTypesResponse = await promptUser( |
|
| 103 | - | "Include TypeScript definitions for React JSX? (Y/n)", |
|
| 105 | + | "Include TypeScript definitions? (Y/n)", |
|
| 104 | 106 | "y", |
|
| 105 | 107 | ); |
|
| 106 | 108 | const includeTypes = |
|
| 107 | 109 | includeTypesResponse.toLowerCase() !== "n" && |
|
| 108 | 110 | includeTypesResponse.toLowerCase() !== "no"; |
|
| 109 | 111 | ||
| 112 | + | // Get framework selection |
|
| 113 | + | let framework: "typescript" | "react" | "svelte" = "typescript"; |
|
| 114 | + | if (includeTypes) { |
|
| 115 | + | console.log(colors.blue("\n▸ Select your framework:")); |
|
| 116 | + | console.log(colors.cyan(" 1. TypeScript (standard)")); |
|
| 117 | + | console.log(colors.cyan(" 2. React")); |
|
| 118 | + | console.log(colors.cyan(" 3. Svelte")); |
|
| 119 | + | ||
| 120 | + | const frameworkChoice = await promptUser("Enter your choice (1-3)", "1"); |
|
| 121 | + | ||
| 122 | + | switch (frameworkChoice) { |
|
| 123 | + | case "1": |
|
| 124 | + | framework = "typescript"; |
|
| 125 | + | break; |
|
| 126 | + | case "2": |
|
| 127 | + | framework = "react"; |
|
| 128 | + | break; |
|
| 129 | + | case "3": |
|
| 130 | + | framework = "svelte"; |
|
| 131 | + | break; |
|
| 132 | + | default: |
|
| 133 | + | console.log( |
|
| 134 | + | colors.yellow(`▸ Invalid choice, defaulting to TypeScript`), |
|
| 135 | + | ); |
|
| 136 | + | framework = "typescript"; |
|
| 137 | + | } |
|
| 138 | + | } |
|
| 139 | + | ||
| 110 | 140 | // Create the configuration |
|
| 111 | 141 | const config: NornsConfig = { |
|
| 112 | 142 | components: componentsPath, |
|
| 113 | 143 | includeTypes, |
|
| 144 | + | framework, |
|
| 114 | 145 | }; |
|
| 115 | 146 | ||
| 116 | 147 | // Create components directory if it doesn't exist |
|
| 207 | 238 | ||
| 208 | 239 | // Copy TypeScript definitions if enabled |
|
| 209 | 240 | if (config.includeTypes !== false) { |
|
| 210 | - | const typesSourcePath = join( |
|
| 211 | - | COMPONENTS_DIR, |
|
| 212 | - | "../custom-elements-jsx.d.ts", |
|
| 213 | - | ); |
|
| 214 | - | const typesDestPath = join(componentsDir, "custom-elements-jsx.d.ts"); |
|
| 241 | + | const framework = config.framework || "typescript"; |
|
| 242 | + | let typesFileName: string; |
|
| 243 | + | ||
| 244 | + | switch (framework) { |
|
| 245 | + | case "react": |
|
| 246 | + | typesFileName = "custom-elements-jsx.ts"; |
|
| 247 | + | break; |
|
| 248 | + | case "svelte": |
|
| 249 | + | typesFileName = "custom-elements-svelte.ts"; |
|
| 250 | + | break; |
|
| 251 | + | case "typescript": |
|
| 252 | + | default: |
|
| 253 | + | typesFileName = "custom-elements.ts"; |
|
| 254 | + | break; |
|
| 255 | + | } |
|
| 256 | + | ||
| 257 | + | const typesSourcePath = join(COMPONENTS_DIR, `../${typesFileName}`); |
|
| 258 | + | const typesDestPath = join(componentsDir, typesFileName); |
|
| 215 | 259 | ||
| 216 | 260 | if (existsSync(typesSourcePath)) { |
|
| 217 | 261 | const typesContent = await readFile(typesSourcePath, "utf8"); |
|
| 218 | 262 | await writeFile(typesDestPath, typesContent, "utf8"); |
|
| 219 | 263 | console.log( |
|
| 220 | - | colors.blue(`▸ Added TypeScript definitions to ${typesDestPath}`), |
|
| 264 | + | colors.blue( |
|
| 265 | + | `▸ Added ${framework} TypeScript definitions to ${typesDestPath}`, |
|
| 266 | + | ), |
|
| 221 | 267 | ); |
|
| 222 | 268 | } |
|
| 223 | 269 | } |
|