From c38ccbd291e03c8798c68ec02cf017093b83c5f0 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 20 Dec 2025 10:11:31 +0000 Subject: [PATCH 01/13] fix: package.json to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-ROU3-14459107 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a86b8d14..d65e41f1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@tanstack/react-table": "^8.21.3", "@types/md5": "^2.3.6", "@types/validator": "^13.15.8", - "better-auth": "1.3.27", + "better-auth": "1.4.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", From ef619b582938408f98862ff5512d95df6d90aaa4 Mon Sep 17 00:00:00 2001 From: Inglan Date: Sat, 20 Dec 2025 10:11:49 +0000 Subject: [PATCH 02/13] Prettified Code! --- bun.lock | 66 ++++++++++++-------------------------------------------- 1 file changed, 14 insertions(+), 52 deletions(-) diff --git a/bun.lock b/bun.lock index bc2a637e..a0cb9978 100644 --- a/bun.lock +++ b/bun.lock @@ -23,7 +23,7 @@ "@tanstack/react-table": "^8.21.3", "@types/md5": "^2.3.6", "@types/validator": "^13.15.8", - "better-auth": "1.3.27", + "better-auth": "1.4.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", @@ -128,7 +128,9 @@ "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], - "@better-auth/core": ["@better-auth/core@1.3.27", "", { "dependencies": { "better-call": "1.0.19", "zod": "^4.1.5" } }, "sha512-3Sfdax6MQyronY+znx7bOsfQHI6m1SThvJWb0RDscFEAhfqLy95k1sl+/PgGyg0cwc2cUXoEiAOSqYdFYrg3vA=="], + "@better-auth/core": ["@better-auth/core@1.4.5", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "better-call": "1.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-dQ3hZOkUJzeBXfVEPTm2LVbzmWwka1nqd9KyWmB2OMlMfjr7IdUeBX4T7qJctF67d7QDhlX95jMoxu6JG0Eucw=="], + + "@better-auth/telemetry": ["@better-auth/telemetry@1.4.5", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18" }, "peerDependencies": { "@better-auth/core": "1.4.5" } }, "sha512-r3NyksbaBYA10SC86JA6QwmZfHwFutkUGcphgWGfu6MVx1zutYmZehIeC8LxTjOWZqqF9FI8vLjglWBHvPQeTg=="], "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="], @@ -204,8 +206,6 @@ "@hcaptcha/react-hcaptcha": ["@hcaptcha/react-hcaptcha@1.14.0", "", { "dependencies": { "@babel/runtime": "^7.17.9", "@hcaptcha/loader": "^2.2.0" }, "peerDependencies": { "react": ">= 16.3.0", "react-dom": ">= 16.3.0" } }, "sha512-XHFhmRjw4L6spgRfTEUj/uW4cN4iWTp7BxLHyheF5zEle6g65fIHUCmqKMrIA/6OKLzBSElUKyc1IuDU+V8RaQ=="], - "@hexagon/base64": ["@hexagon/base64@1.1.28", "", {}, "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="], - "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="], "@iconify-json/fa7-brands": ["@iconify-json/fa7-brands@1.2.0", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-OTdHSwRmycgQQXQr7wJQFyD08zj4OxoRfaWhCuI3a9MhbnHJApU4U2Qbp6hP4zicqOmQB9UII9+MA1IDNNLPlQ=="], @@ -234,8 +234,6 @@ "@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=="], - "@levischuck/tiny-cbor": ["@levischuck/tiny-cbor@0.2.11", "", {}, "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow=="], - "@marsidev/react-turnstile": ["@marsidev/react-turnstile@1.3.1", "", { "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0" } }, "sha512-h2THG/75k4Y049hgjSGPIcajxXnh+IZAiXVbryQyVmagkboN7pJtBgR16g8akjwUBSfRrg6jw6KvPDjscQflog=="], "@mjackson/node-fetch-server": ["@mjackson/node-fetch-server@0.2.0", "", {}, "sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng=="], @@ -250,30 +248,6 @@ "@npmcli/promise-spawn": ["@npmcli/promise-spawn@6.0.2", "", { "dependencies": { "which": "^3.0.0" } }, "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg=="], - "@peculiar/asn1-android": ["@peculiar/asn1-android@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A=="], - - "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "@peculiar/asn1-x509-attr": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A=="], - - "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ=="], - - "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg=="], - - "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.5.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-pkcs8": "^2.5.0", "@peculiar/asn1-rsa": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug=="], - - "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw=="], - - "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.5.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-pfx": "^2.5.0", "@peculiar/asn1-pkcs8": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "@peculiar/asn1-x509-attr": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A=="], - - "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q=="], - - "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.5.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ=="], - - "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ=="], - - "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.5.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A=="], - - "@peculiar/x509": ["@peculiar/x509@1.14.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.5.0", "@peculiar/asn1-csr": "^2.5.0", "@peculiar/asn1-ecc": "^2.5.0", "@peculiar/asn1-pkcs9": "^2.5.0", "@peculiar/asn1-rsa": "^2.5.0", "@peculiar/asn1-schema": "^2.5.0", "@peculiar/asn1-x509": "^2.5.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg=="], - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], "@posthog/core": ["@posthog/core@1.6.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-Tbh8UACwbb7jFdDC7wwXHtfNzO+4wKh3VbyMHmp2UBe6w1jliJixexTJNfkqdGZm+ht3M10mcKvGGPnoZ2zLBg=="], @@ -462,12 +436,10 @@ "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], - "@simplewebauthn/browser": ["@simplewebauthn/browser@13.2.2", "", {}, "sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA=="], - - "@simplewebauthn/server": ["@simplewebauthn/server@13.2.2", "", { "dependencies": { "@hexagon/base64": "^1.1.27", "@levischuck/tiny-cbor": "^0.2.2", "@peculiar/asn1-android": "^2.3.10", "@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-rsa": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-x509": "^2.3.8", "@peculiar/x509": "^1.13.0" } }, "sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA=="], - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="], "@svgr/babel-plugin-add-jsx-attribute": ["@svgr/babel-plugin-add-jsx-attribute@8.0.0", "", { "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g=="], @@ -572,8 +544,6 @@ "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], - "asn1js": ["asn1js@3.0.6", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA=="], - "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.10", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -582,9 +552,9 @@ "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="], - "better-auth": ["better-auth@1.3.27", "", { "dependencies": { "@better-auth/core": "1.3.27", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "better-call": "1.0.19", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.5" } }, "sha512-SwiGAJ7yU6dBhNg0NdV1h5M8T5sa7/AszZVc4vBfMDrLLmvUfbt9JoJ0uRUJUEdKRAAxTyl9yA+F3+GhtAD80w=="], + "better-auth": ["better-auth@1.4.5", "", { "dependencies": { "@better-auth/core": "1.4.5", "@better-auth/telemetry": "1.4.5", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.4", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "ms": "4.0.0-nightly.202508271359", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@sveltejs/kit", "@tanstack/react-start", "next", "react", "react-dom", "solid-js", "svelte", "vue"] }, "sha512-pHV2YE0OogRHvoA6pndHXCei4pcep/mjY7psSaHVrRgjBtumVI68SV1g9U9XPRZ4KkoGca9jfwuv+bB2UILiFw=="], - "better-call": ["better-call@1.0.19", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.5.1", "set-cookie-parser": "^2.7.1", "uncrypto": "^0.1.3" } }, "sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw=="], + "better-call": ["better-call@1.1.4", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-NJouLY6IVKv0nDuFoc6FcbKDFzEnmgMNofC9F60Mwx1Ecm7X6/Ecyoe5b+JSVZ42F/0n46/M89gbYP1ZCVv8xQ=="], "body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="], @@ -928,7 +898,7 @@ "motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="], - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "ms": ["ms@4.0.0-nightly.202508271359", "", {}, "sha512-WC/Eo7NzFrOV/RRrTaI0fxKVbNCzEy76j2VqNV8SxDf9D69gSE2Lh0QwYvDlhiYmheBYExAvEAxVf5NoN0cj2A=="], "mutative": ["mutative@1.3.0", "", {}, "sha512-8MJj6URmOZAV70dpFe1YnSppRTKC4DsMkXQiBDFayLcDI4ljGokHxmpqaBQuDWa4iAxWaJJ1PS8vAmbntjjKmQ=="], @@ -1022,10 +992,6 @@ "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], - "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], - - "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], - "qr.js": ["qr.js@0.0.0", "", {}, "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ=="], "qrcode.react": ["qrcode.react@4.2.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA=="], @@ -1068,8 +1034,6 @@ "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], - "remeda": ["remeda@2.32.0", "", { "dependencies": { "type-fest": "^4.41.0" } }, "sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -1078,7 +1042,7 @@ "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=="], - "rou3": ["rou3@0.5.1", "", {}, "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ=="], + "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], @@ -1164,8 +1128,6 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="], - "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], @@ -1180,8 +1142,6 @@ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], - "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], @@ -1338,6 +1298,8 @@ "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "express/cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -1368,14 +1330,14 @@ "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + "send/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], - "vite-node/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], From f16eaff3656fc078e8de3f3152149ae86f4773cf Mon Sep 17 00:00:00 2001 From: Ingo Wolf Date: Tue, 6 Jan 2026 11:29:09 +1100 Subject: [PATCH 03/13] change defualt theme --- lib/themes/default.css | 183 +++++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 63 deletions(-) diff --git a/lib/themes/default.css b/lib/themes/default.css index 62e35de1..59c29d4f 100644 --- a/lib/themes/default.css +++ b/lib/themes/default.css @@ -1,68 +1,125 @@ .theme-default { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + --background: #ffffff; + --foreground: #000000; + --card: #ffffff; + --card-foreground: #000000; + --popover: #ffffff; + --popover-foreground: #000000; + --primary: #00a63e; + --primary-foreground: #ffffff; + --secondary: #f5f5f5; + --secondary-foreground: #000000; + --muted: #f5f5f5; + --muted-foreground: #737373; + --accent: #f5f5f5; + --accent-foreground: #000000; + --destructive: #e7000b; + --destructive-foreground: #ffffff; + --border: #e5e5e5; + --input: #e5e5e5; + --ring: #a1a1a1; + --chart-1: #daebff; + --chart-2: #6ea2f8; + --chart-3: #5384f2; + --chart-4: #3968e7; + --chart-5: #254acc; + --sidebar: #fbfbfb; + --sidebar-foreground: #000000; + --sidebar-primary: #000000; + --sidebar-primary-foreground: #ffffff; + --sidebar-accent: #f5f5f5; + --sidebar-accent-foreground: #1d1d1f; + --sidebar-border: #e5e5e5; + --sidebar-ring: #a1a1a1; + --font-sans: + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + --radius: 1.5rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow-md: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1); + --shadow-lg: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1); + --shadow-xl: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); + --tracking-normal: 0em; + --spacing: 0.28rem; } .theme-default.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); + --background: #000000; + --foreground: #ffffff; + --card: #080808; + --card-foreground: #ffffff; + --popover: #050505; + --popover-foreground: #ffffff; + --primary: #008236; + --primary-foreground: #ffffff; + --secondary: #010101; + --secondary-foreground: #ffffff; + --muted: #010101; + --muted-foreground: #888888; + --accent: #111111; + --accent-foreground: #ffffff; + --destructive: #f40021; + --destructive-foreground: #ffffff; + --border: #050505; + --input: #111111; + --ring: #222222; + --chart-1: #daebff; + --chart-2: #6ea2f8; + --chart-3: #5384f2; + --chart-4: #3968e7; + --chart-5: #254acc; + --sidebar: #080808; + --sidebar-foreground: #ffffff; + --sidebar-primary: #ffffff; + --sidebar-primary-foreground: #000000; + --sidebar-accent: #111111; + --sidebar-accent-foreground: #ffffff; + --sidebar-border: #050505; + --sidebar-ring: #222222; + --font-sans: + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + --radius: 1.5rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow-md: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1); + --shadow-lg: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1); + --shadow-xl: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); } From 2252ca2bfce633d51d45a4c9f7a5f431dec0e482 Mon Sep 17 00:00:00 2001 From: Ingo Wolf Date: Tue, 6 Jan 2026 11:38:44 +1100 Subject: [PATCH 04/13] [With AI] replace all icons --- app/root.tsx | 4 +- app/routes/admin/columns.tsx | 8 +-- app/routes/admin/data-table.tsx | 10 ++-- app/routes/backups/page.tsx | 44 +++++++------- app/routes/g/columns.tsx | 6 +- app/routes/g/play.tsx | 50 ++++++++-------- app/routes/home.tsx | 42 +++++++------- app/routes/tools/base64-converter.tsx | 15 +++-- app/routes/tools/color-picker.tsx | 14 ++--- app/routes/tools/hash-generator.tsx | 6 +- app/routes/tools/json-formatter.tsx | 28 ++++----- app/routes/tools/markdown-preview.tsx | 12 ++-- app/routes/tools/number-base.tsx | 11 +++- app/routes/tools/password-generator.tsx | 8 +-- app/routes/tools/qr-code-generator.tsx | 6 +- app/routes/tools/random-number.tsx | 6 +- app/routes/tools/regex-tester.tsx | 15 +++-- app/routes/tools/roman-numeral.tsx | 24 ++++---- app/routes/tools/stopwatch-timer.tsx | 35 +++++++----- app/routes/tools/text-case.tsx | 6 +- app/routes/tools/unit-converter.tsx | 4 +- app/routes/tools/url-encoder.tsx | 10 ++-- app/routes/tools/uuid-generator.tsx | 17 ++++-- app/routes/tools/word-counter.tsx | 6 +- bun.lock | 4 +- components/app-sidebar.tsx | 36 ++++++------ components/command-palette.tsx | 14 ++--- components/header.tsx | 16 ++++-- components/search.tsx | 12 ++-- components/settings.tsx | 76 ++++++++++++------------- components/theme-mode-selector.tsx | 6 +- components/theme-selector.tsx | 6 +- components/ui/breadcrumb.tsx | 8 +-- components/ui/checkbox.tsx | 6 +- components/ui/command.tsx | 16 +++--- components/ui/dialog.tsx | 10 ++-- components/ui/dropdown-menu.tsx | 24 ++++---- components/ui/sheet.tsx | 8 +-- components/ui/sidebar.tsx | 36 ++++++------ components/ui/sonner.tsx | 22 +++---- components/ui/spinner.tsx | 4 +- lib/menu.ts | 46 +++++++-------- lib/tools.ts | 66 ++++++++++----------- package.json | 2 +- 44 files changed, 420 insertions(+), 385 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index 417b44d0..553451ad 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -40,7 +40,7 @@ import { cn } from "@/lib/utils"; import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; -import { Copy } from "lucide-react"; +import { PiCopy } from "react-icons/pi"; import { toast } from "sonner"; import { useCloak } from "@/hooks/use-cloak"; import { MotionConfig } from "motion/react"; @@ -311,7 +311,7 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { }); }} > - + diff --git a/app/routes/admin/columns.tsx b/app/routes/admin/columns.tsx index c5ba45ca..a3489524 100644 --- a/app/routes/admin/columns.tsx +++ b/app/routes/admin/columns.tsx @@ -1,7 +1,7 @@ "use client"; import { type ColumnDef } from "@tanstack/react-table"; -import { ArrowUpDown } from "lucide-react"; +import { PiArrowsUpDown } from "react-icons/pi"; import { Button } from "@/components/ui/button"; export type User = { @@ -27,7 +27,7 @@ export const createColumns = (): ColumnDef[] => [ onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Email - + ); }, @@ -42,7 +42,7 @@ export const createColumns = (): ColumnDef[] => [ onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Name - + ); }, @@ -90,7 +90,7 @@ export const createColumns = (): ColumnDef[] => [ onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Created - + ); }, diff --git a/app/routes/admin/data-table.tsx b/app/routes/admin/data-table.tsx index 8e2314b5..2395ae5c 100644 --- a/app/routes/admin/data-table.tsx +++ b/app/routes/admin/data-table.tsx @@ -13,7 +13,7 @@ import { getSortedRowModel, useReactTable, } from "@tanstack/react-table"; -import { ChevronDown } from "lucide-react"; +import { PiCaretDown } from "react-icons/pi"; import { Button } from "@/components/ui/button"; import { @@ -45,7 +45,7 @@ export function DataTable({ }: DataTableProps) { const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( - [], + [] ); const [columnVisibility, setColumnVisibility] = React.useState({}); @@ -104,7 +104,7 @@ export function DataTable({ @@ -141,7 +141,7 @@ export function DataTable({ ? null : flexRender( header.column.columnDef.header, - header.getContext(), + header.getContext() )} ); @@ -162,7 +162,7 @@ export function DataTable({ {flexRender( cell.column.columnDef.cell, - cell.getContext(), + cell.getContext() )} ))} diff --git a/app/routes/backups/page.tsx b/app/routes/backups/page.tsx index b0b2ebcd..bf57eaf9 100644 --- a/app/routes/backups/page.tsx +++ b/app/routes/backups/page.tsx @@ -22,14 +22,14 @@ import { useQuery, } from "convex/react"; import { - Archive, - ArchiveRestore, - ArrowRight, - Clipboard, - Copy, - Delete, - Trash, -} from "lucide-react"; + PiArchive, + PiArchiveTray, + PiArrowRight, + PiClipboard, + PiCopy, + PiTrash, + PiTrashSimple, +} from "react-icons/pi"; import { useEffect, useState } from "react"; import { toast } from "sonner"; import { AnimatePresence, motion } from "motion/react"; @@ -63,7 +63,7 @@ export default function BackupsPage() { const cloudBackups = useQuery(api.backups.getBackups); const createCloudBackup = useMutation( - api.backups.createBackup, + api.backups.createBackup ).withOptimisticUpdate((localStore, args) => { const { data, name, backupKey } = args; const currentBackups = localStore.getQuery(api.backups.getBackups); @@ -85,7 +85,7 @@ export default function BackupsPage() { { success: true, backups: [newBackup, ...currentBackups.backups], - }, + } ); } }); @@ -93,14 +93,14 @@ export default function BackupsPage() { const convexAuth = useConvexAuth(); const deleteCloudBackup = useMutation( - api.backups.deleteBackup, + api.backups.deleteBackup ).withOptimisticUpdate((localStore, args) => { const { id } = args; const currentBackups = localStore.getQuery(api.backups.getBackups); // If we've loaded the backups query, remove the backup being deleted if (currentBackups?.success && currentBackups.backups !== undefined) { const filteredBackups = currentBackups.backups.filter( - (backup) => backup._id !== id, + (backup) => backup._id !== id ); localStore.setQuery( api.backups.getBackups, @@ -108,7 +108,7 @@ export default function BackupsPage() { { success: true, backups: filteredBackups, - }, + } ); } }); @@ -141,7 +141,7 @@ export default function BackupsPage() { loading: "Creating backup...", success: "Backup created", error: (error) => error.message || "Failed to create backup", - }, + } ); }; @@ -170,7 +170,7 @@ export default function BackupsPage() { }); }} > - + @@ -247,7 +247,7 @@ export default function BackupsPage() { onClick={handleCreateBackup} disabled={!inputtedBackupName.trim()} > - + @@ -277,7 +277,7 @@ export default function BackupsPage() { @@ -308,7 +308,7 @@ export default function BackupsPage() { loading: "Deleting backup...", success: "Backup deleted", error: "Failed to delete backup", - }, + } ); }} > @@ -328,17 +328,17 @@ export default function BackupsPage() { }) .catch((error) => { toast.error( - "Failed to copy backup to clipboard", + "Failed to copy backup to clipboard" ); }); }} > - + @@ -386,7 +386,7 @@ export default function BackupsPage() { - + No backups yet diff --git a/app/routes/g/columns.tsx b/app/routes/g/columns.tsx index d616fc7f..47084590 100644 --- a/app/routes/g/columns.tsx +++ b/app/routes/g/columns.tsx @@ -1,7 +1,7 @@ "use client"; import type { ColumnDef } from "@tanstack/react-table"; -import { ArrowUpDown } from "lucide-react"; +import { PiArrowsUpDown } from "react-icons/pi"; import { Button } from "@/components/ui/button"; import type { ParsedGmae } from "@/lib/gmaes"; @@ -16,7 +16,7 @@ export const columns: ColumnDef[] = [ onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Name - + ); }, @@ -40,7 +40,7 @@ export const columns: ColumnDef[] = [ onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Category - + ); }, diff --git a/app/routes/g/play.tsx b/app/routes/g/play.tsx index d525b5f8..ad39c506 100644 --- a/app/routes/g/play.tsx +++ b/app/routes/g/play.tsx @@ -3,20 +3,20 @@ import type { Route } from "./+types/play"; import { data } from "react-router"; import { Button } from "@/components/ui/button"; import { - AppWindow, - Bookmark, - BookmarkCheck, - ChevronDown, - ChevronUp, - ExternalLink, - Fullscreen, - Keyboard, - Maximize, - RefreshCw, - Scan, - Share, - Square, -} from "lucide-react"; + PiAppWindow, + PiBookmark, + PiBookmarkFill, + PiCaretDown, + PiCaretUp, + PiArrowSquareOut, + PiArrowsOut, + PiKeyboard, + PiArrowsOutSimple, + PiArrowClockwise, + PiScan, + PiShare, + PiSquare, +} from "react-icons/pi"; import { ButtonGroup } from "@/components/ui/button-group"; import { Tooltip, @@ -61,7 +61,7 @@ export function Play({ params }: Route.ComponentProps) { const saved = useSavedGmaes((state) => state.saved); const toggleSaved = useSavedGmaes((state) => state.toggleSaved); const historyCollectionEnabled = usePrivacyState( - (state) => state.historyCollectionEnabled, + (state) => state.historyCollectionEnabled ); const isSaved = gmae?.id ? saved.includes(gmae.id) : false; @@ -100,7 +100,7 @@ export function Play({ params }: Route.ComponentProps) { toast.success("Focused gmae"); }} > - + Fix keyboard input @@ -115,7 +115,7 @@ export function Play({ params }: Route.ComponentProps) { iframeRef.current?.contentWindow?.location.reload(); }} > - + Reload @@ -130,7 +130,7 @@ export function Play({ params }: Route.ComponentProps) { const win = window.open( "", "", - "width=500px,height=500px", + "width=500px,height=500px" ); let frame = document.createElement("iframe"); @@ -145,7 +145,7 @@ export function Play({ params }: Route.ComponentProps) { } }} > - + Open in new window @@ -171,7 +171,7 @@ export function Play({ params }: Route.ComponentProps) { } }} > - + Open in new tab @@ -187,7 +187,7 @@ export function Play({ params }: Route.ComponentProps) { }} variant="outline" > - + Maximize @@ -202,7 +202,7 @@ export function Play({ params }: Route.ComponentProps) { iframeRef.current?.focus(); }} > - + Fullscreen @@ -218,7 +218,7 @@ export function Play({ params }: Route.ComponentProps) { } }} > - {isSaved ? : } + {isSaved ? : } {isSaved ? "Saved" : "Save"} @@ -266,7 +266,7 @@ export function Play({ params }: Route.ComponentProps) { setMaximized(false); }} > - + )} diff --git a/app/routes/home.tsx b/app/routes/home.tsx index bd93def4..f98725f2 100644 --- a/app/routes/home.tsx +++ b/app/routes/home.tsx @@ -3,15 +3,15 @@ import type { Route } from "./+types/home"; import { Link } from "react-router"; import { Button } from "@/components/ui/button"; import { - Bookmark, - History, - Wrench, - ArrowRight, - Star, - Gamepad2, - Trash2, - X, -} from "lucide-react"; + PiBookmark, + PiClockClockwise, + PiWrench, + PiArrowRight, + PiStar, + PiGameController, + PiTrash, + PiX, +} from "react-icons/pi"; import { useGmaeHistory, useSavedGmaes, @@ -36,7 +36,7 @@ import { cn } from "@/lib/utils"; export default function Home() { const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const history = useGmaeHistory((state) => state.history); const removeFromHistory = useGmaeHistory((state) => state.removeFromHistory); @@ -80,14 +80,14 @@ export default function Home() { "grid gap-6", experimentalFeatures ? "grid-cols-1 lg:grid-cols-3" - : "grid-cols-1 lg:grid-cols-2", + : "grid-cols-1 lg:grid-cols-2" )} > {/* Tools Section */} @@ -101,7 +101,7 @@ export default function Home() { className={cn( "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 gap-2", !experimentalFeatures && "lg:grid-cols-3", - experimentalFeatures && "max-h-[600px] overflow-y-auto", + experimentalFeatures && "max-h-[600px] overflow-y-auto" )} > {TOOLS.map((tool) => ( @@ -123,7 +123,7 @@ export default function Home() { {tool.label} - + @@ -138,7 +138,7 @@ export default function Home() { - + Saved Your bookmarked items @@ -177,7 +177,7 @@ export default function Home() { - + No saved items @@ -194,7 +194,7 @@ export default function Home() {
- + History Recently accessed items @@ -206,7 +206,7 @@ export default function Home() { className="text-muted-foreground hover:text-destructive h-8 px-2" onClick={clearHistory} > - + Clear )} @@ -223,7 +223,7 @@ export default function Home() { >
- + {item.label} @@ -240,7 +240,7 @@ export default function Home() { removeFromHistory(item.id); }} > - + Remove from history
@@ -250,7 +250,7 @@ export default function Home() { - + No history diff --git a/app/routes/tools/base64-converter.tsx b/app/routes/tools/base64-converter.tsx index 5c7b28da..714e48d2 100644 --- a/app/routes/tools/base64-converter.tsx +++ b/app/routes/tools/base64-converter.tsx @@ -1,7 +1,12 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; -import { Copy, ArrowRightLeft, Trash2, ClipboardPaste } from "lucide-react"; +import { + PiCopy, + PiArrowsLeftRight, + PiTrash, + PiClipboard, +} from "react-icons/pi"; export default function Base64Converter() { const [mode, setMode] = useState<"encode" | "decode">("encode"); @@ -17,7 +22,7 @@ export default function Base64Converter() { setOutput(encoded); } catch (err) { setError( - "Failed to encode. Make sure the input contains valid characters.", + "Failed to encode. Make sure the input contains valid characters." ); setOutput(""); } @@ -138,7 +143,7 @@ export default function Base64Converter() { onClick={pasteFromClipboard} className="h-8 px-2 text-xs" > - + Paste
@@ -178,7 +183,7 @@ export default function Base64Converter() { className="h-11 shrink-0" onClick={handleClear} > - + Clear @@ -207,7 +212,7 @@ export default function Base64Converter() { onClick={copyToClipboard} className="h-8 px-2 text-xs" > - + {copied ? "Copied!" : "Copy"} diff --git a/app/routes/tools/color-picker.tsx b/app/routes/tools/color-picker.tsx index ce6eacfd..07977993 100644 --- a/app/routes/tools/color-picker.tsx +++ b/app/routes/tools/color-picker.tsx @@ -8,7 +8,7 @@ import { CardTitle, CardDescription, } from "@/components/ui/card"; -import { Copy, Plus, X, Trash2 } from "lucide-react"; +import { PiCopy, PiPlus, PiX, PiTrash } from "react-icons/pi"; export default function ColorPicker() { const [color, setColor] = useState("#3b82f6"); @@ -154,7 +154,7 @@ export default function ColorPicker() { variant="outline" className="h-11 px-4" > - + Save @@ -204,7 +204,7 @@ export default function ColorPicker() { size="icon" className="h-11 w-11 shrink-0" > - + @@ -229,7 +229,7 @@ export default function ColorPicker() { size="icon" className="h-11 w-11 shrink-0" > - + @@ -250,14 +250,14 @@ export default function ColorPicker() { onClick={() => copyToClipboard( `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`, - "hsl", + "hsl" ) } variant={copied === "hsl" ? "default" : "outline"} size="icon" className="h-11 w-11 shrink-0" > - + @@ -354,7 +354,7 @@ export default function ColorPicker() { onClick={() => removeColor(savedColor)} className="absolute -top-2 -right-2 w-6 h-6 bg-destructive text-destructive-foreground rounded-full opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center hover:scale-110 shadow-sm" > - + ))} diff --git a/app/routes/tools/hash-generator.tsx b/app/routes/tools/hash-generator.tsx index da3775aa..8c429e2c 100644 --- a/app/routes/tools/hash-generator.tsx +++ b/app/routes/tools/hash-generator.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, Trash2, FileLock2 } from "lucide-react"; +import { PiCopy, PiArrowClockwise, PiTrash, PiLock } from "react-icons/pi"; import { toast } from "sonner"; async function hashText(text: string, algorithm: string): Promise { @@ -111,7 +111,7 @@ export default function HashGenerator() {

- + {algo.label}

{hashes[algo.value] && ( @@ -121,7 +121,7 @@ export default function HashGenerator() { onClick={() => copyToClipboard(hashes[algo.value])} className="h-8 px-2 text-xs" > - Copy + Copy )}
diff --git a/app/routes/tools/json-formatter.tsx b/app/routes/tools/json-formatter.tsx index bab0a5e0..34a05535 100644 --- a/app/routes/tools/json-formatter.tsx +++ b/app/routes/tools/json-formatter.tsx @@ -2,15 +2,15 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { - Copy, - Trash2, - AlertCircle, - CheckCircle2, - ClipboardPaste, - FileJson, - Minimize2, - AlignLeft, -} from "lucide-react"; + PiCopy, + PiTrash, + PiWarningCircle, + PiCheckCircle, + PiClipboard, + PiFileJson, + PiMinus, + PiAlignLeft, +} from "react-icons/pi"; import { toast } from "sonner"; export default function JsonFormatter() { @@ -115,7 +115,7 @@ export default function JsonFormatter() { onClick={clearAll} className="h-8 px-2 text-xs hover:text-destructive" > - + Clear @@ -142,7 +142,7 @@ export default function JsonFormatter() { )} {output && !error && ( - Valid JSON + Valid JSON )} @@ -180,7 +180,7 @@ export default function JsonFormatter() { className="h-8 w-8" title="Minify" > - + diff --git a/app/routes/tools/markdown-preview.tsx b/app/routes/tools/markdown-preview.tsx index 5e7413cd..8ae58404 100644 --- a/app/routes/tools/markdown-preview.tsx +++ b/app/routes/tools/markdown-preview.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, FileText, Eye } from "lucide-react"; +import { PiCopy, PiArrowClockwise, PiFileText, PiEye } from "react-icons/pi"; import { toast } from "sonner"; // Simple markdown parser @@ -28,13 +28,13 @@ function parseMarkdown(markdown: string): string { // Links html = html.replace( /\[([^\]]+)\]\(([^)]+)\)/gim, - '$1', + '$1' ); // Images html = html.replace( /!\[([^\]]*)\]\(([^)]+)\)/gim, - '$1', + '$1' ); // Lists @@ -122,7 +122,7 @@ export default function MarkdownPreview() { - + Markdown
@@ -149,7 +149,7 @@ export default function MarkdownPreview() { onClick={() => copyToClipboard(markdown)} className="h-8 px-2 text-xs" > - Copy MD + Copy MD
@@ -175,7 +175,7 @@ export default function MarkdownPreview() { onClick={() => copyToClipboard(parseMarkdown(markdown))} className="h-8 px-2 text-xs" > - Copy HTML + Copy HTML
diff --git a/app/routes/tools/number-base.tsx b/app/routes/tools/number-base.tsx index 75adc2f7..fb213325 100644 --- a/app/routes/tools/number-base.tsx +++ b/app/routes/tools/number-base.tsx @@ -2,7 +2,12 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, ArrowRightLeft, Binary } from "lucide-react"; +import { + PiCopy, + PiArrowClockwise, + PiArrowsLeftRight, + PiBinary, +} from "react-icons/pi"; import { toast } from "sonner"; function convertBase(value: string, fromBase: number, toBase: number): string { @@ -129,7 +134,7 @@ export default function NumberBase() { onClick={clear} className="h-8 px-2 text-xs" > - Clear + Clear - Copy + Copy )}
diff --git a/app/routes/tools/password-generator.tsx b/app/routes/tools/password-generator.tsx index 96ac0dfe..26ec3ccf 100644 --- a/app/routes/tools/password-generator.tsx +++ b/app/routes/tools/password-generator.tsx @@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; -import { Copy, RefreshCw, ShieldCheck } from "lucide-react"; +import { PiCopy, PiArrowClockwise, PiShieldCheck } from "react-icons/pi"; export default function PasswordGenerator() { const [password, setPassword] = useState(""); @@ -34,7 +34,7 @@ export default function PasswordGenerator() { let result = ""; for (let i = 0; i < length; i++) { result += characters.charAt( - Math.floor(Math.random() * characters.length), + Math.floor(Math.random() * characters.length) ); } @@ -83,7 +83,7 @@ export default function PasswordGenerator() { /> {password && (
- +
)} @@ -189,7 +189,7 @@ export default function PasswordGenerator() { className="w-full h-12 text-base font-medium" size="lg" > - + Generate Password diff --git a/app/routes/tools/qr-code-generator.tsx b/app/routes/tools/qr-code-generator.tsx index 5bdaa908..da4cdc51 100644 --- a/app/routes/tools/qr-code-generator.tsx +++ b/app/routes/tools/qr-code-generator.tsx @@ -4,7 +4,7 @@ import { Input } from "@/components/ui/input"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { QRCodeSVG } from "qrcode.react"; -import { Download, QrCode } from "lucide-react"; +import { PiDownload, PiQrCode } from "react-icons/pi"; export default function QrCodeGenerator() { const [text, setText] = useState(""); @@ -119,12 +119,12 @@ export default function QrCodeGenerator() { /> ) : (
- +

Enter content to generate a QR code

)} diff --git a/app/routes/tools/random-number.tsx b/app/routes/tools/random-number.tsx index 6f2307c1..e29b4dcb 100644 --- a/app/routes/tools/random-number.tsx +++ b/app/routes/tools/random-number.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent } from "@/components/ui/card"; -import { Copy, Dices, RefreshCw } from "lucide-react"; +import { PiCopy, PiDice, PiArrowClockwise } from "react-icons/pi"; export default function RandomNumber() { const [min, setMin] = useState(1); @@ -134,7 +134,7 @@ export default function RandomNumber() { className="w-full h-12 text-base font-medium" size="lg" > - + Generate @@ -155,7 +155,7 @@ export default function RandomNumber() { size="sm" className="h-8 px-2 text-xs" > - + {copied ? "Copied!" : "Copy"} diff --git a/app/routes/tools/regex-tester.tsx b/app/routes/tools/regex-tester.tsx index 96569e4f..8a270e77 100644 --- a/app/routes/tools/regex-tester.tsx +++ b/app/routes/tools/regex-tester.tsx @@ -3,7 +3,12 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; -import { Copy, RefreshCw, AlertTriangle, CheckCircle2 } from "lucide-react"; +import { + PiCopy, + PiArrowClockwise, + PiWarning, + PiCheckCircle, +} from "react-icons/pi"; import { toast } from "sonner"; export default function RegexTester() { @@ -51,7 +56,7 @@ export default function RegexTester() { while ((match = regex.exec(text)) !== null) { parts.push(text.substring(lastIndex, match.index)); parts.push( - `${match[0]}`, + `${match[0]}` ); lastIndex = regex.lastIndex; @@ -187,7 +192,7 @@ export default function RegexTester() { onClick={clear} className="h-8 px-2 text-xs" > - Clear + Clear
@@ -202,7 +207,7 @@ export default function RegexTester() { {error && (
- +
{error}
)} @@ -222,7 +227,7 @@ export default function RegexTester() { } className="h-8 px-2 text-xs" > - Copy Results + Copy Results diff --git a/app/routes/tools/roman-numeral.tsx b/app/routes/tools/roman-numeral.tsx index bb147f5d..0eb6a7b1 100644 --- a/app/routes/tools/roman-numeral.tsx +++ b/app/routes/tools/roman-numeral.tsx @@ -3,12 +3,12 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { - Copy, - RefreshCw, - ArrowRightLeft, - Type, - Calculator, -} from "lucide-react"; + PiCopy, + PiArrowClockwise, + PiArrowsLeftRight, + PiTextT, + PiCalculator, +} from "react-icons/pi"; import { toast } from "sonner"; const ROMAN_VALUES: Record = { @@ -85,7 +85,7 @@ export default function RomanNumeral() { const [number, setNumber] = useState(""); const [roman, setRoman] = useState(""); const [direction, setDirection] = useState<"to-roman" | "from-roman">( - "to-roman", + "to-roman" ); const handleNumberChange = (value: string) => { @@ -139,7 +139,7 @@ export default function RomanNumeral() { - + Arabic Number @@ -178,7 +178,7 @@ export default function RomanNumeral() { - + Roman Numeral @@ -226,7 +226,7 @@ export default function RomanNumeral() { {number || "?"} - + {roman || "?"} @@ -236,7 +236,7 @@ export default function RomanNumeral() { {roman || "?"} - + {number || "?"} )} @@ -256,7 +256,7 @@ export default function RomanNumeral() { onClick={clear} className="h-10 w-10" > - + diff --git a/app/routes/tools/stopwatch-timer.tsx b/app/routes/tools/stopwatch-timer.tsx index 4d4c1198..efd09dbf 100644 --- a/app/routes/tools/stopwatch-timer.tsx +++ b/app/routes/tools/stopwatch-timer.tsx @@ -2,7 +2,14 @@ import { useState, useEffect, useRef } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Play, Pause, RotateCcw, Flag, Timer, Watch } from "lucide-react"; +import { + PiPlay, + PiPause, + PiArrowCounterClockwise, + PiFlag, + PiTimer, + PiClock, +} from "react-icons/pi"; type Mode = "stopwatch" | "timer"; @@ -142,7 +149,7 @@ export default function StopwatchTimer() { size="lg" className="rounded-md" > - + Stopwatch @@ -185,7 +192,7 @@ export default function StopwatchTimer() { size="lg" className="h-14 text-lg font-medium" > - + Start ) : ( @@ -195,7 +202,7 @@ export default function StopwatchTimer() { variant="secondary" className="h-14 text-lg font-medium" > - + Pause )} @@ -217,7 +224,7 @@ export default function StopwatchTimer() { variant="ghost" className="w-full h-12 border-dashed border-2" > - + Lap )} @@ -304,8 +311,8 @@ export default function StopwatchTimer() { setTimerHours( Math.max( 0, - Math.min(23, parseInt(e.target.value) || 0), - ), + Math.min(23, parseInt(e.target.value) || 0) + ) ) } className="h-16 text-center text-2xl font-mono" @@ -325,8 +332,8 @@ export default function StopwatchTimer() { setTimerMinutes( Math.max( 0, - Math.min(59, parseInt(e.target.value) || 0), - ), + Math.min(59, parseInt(e.target.value) || 0) + ) ) } className="h-16 text-center text-2xl font-mono" @@ -346,8 +353,8 @@ export default function StopwatchTimer() { setTimerSeconds( Math.max( 0, - Math.min(59, parseInt(e.target.value) || 0), - ), + Math.min(59, parseInt(e.target.value) || 0) + ) ) } className="h-16 text-center text-2xl font-mono" @@ -394,7 +401,7 @@ export default function StopwatchTimer() { timerSeconds === 0 } > - + Start ) : ( @@ -404,7 +411,7 @@ export default function StopwatchTimer() { variant="secondary" className="h-14 text-lg font-medium" > - + Pause )} diff --git a/app/routes/tools/text-case.tsx b/app/routes/tools/text-case.tsx index 4d4aef61..189e1f28 100644 --- a/app/routes/tools/text-case.tsx +++ b/app/routes/tools/text-case.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, CaseUpper, CaseLower, Type } from "lucide-react"; +import { PiCopy, PiArrowClockwise, PiTextAa } from "react-icons/pi"; import { toast } from "sonner"; type CaseType = @@ -145,7 +145,7 @@ export default function TextCase() { onClick={clear} className="h-8 px-2 text-xs" > - Clear + Clear @@ -168,7 +168,7 @@ export default function TextCase() { onClick={() => copyToClipboard(output)} className="h-8 px-2 text-xs" > - Copy + Copy )} diff --git a/app/routes/tools/unit-converter.tsx b/app/routes/tools/unit-converter.tsx index c9fa3a08..894acadb 100644 --- a/app/routes/tools/unit-converter.tsx +++ b/app/routes/tools/unit-converter.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent } from "@/components/ui/card"; -import { ArrowRightLeft } from "lucide-react"; +import { PiArrowsLeftRight } from "react-icons/pi"; type UnitCategory = "length" | "weight" | "temperature" | "volume"; @@ -254,7 +254,7 @@ export default function UnitConverter() { onClick={swapUnits} className="rounded-full h-10 w-10 hover:bg-muted" > - + diff --git a/app/routes/tools/url-encoder.tsx b/app/routes/tools/url-encoder.tsx index 0c226bb3..8397c8c3 100644 --- a/app/routes/tools/url-encoder.tsx +++ b/app/routes/tools/url-encoder.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, Link, Globe } from "lucide-react"; +import { PiCopy, PiArrowClockwise, PiLink, PiGlobe } from "react-icons/pi"; import { toast } from "sonner"; export default function UrlEncoder() { @@ -60,7 +60,7 @@ export default function UrlEncoder() { - + Decoded URL {decoded && ( @@ -70,7 +70,7 @@ export default function UrlEncoder() { onClick={() => copyToClipboard(decoded)} className="h-8 px-2 text-xs" > - Copy + Copy )} @@ -97,7 +97,7 @@ export default function UrlEncoder() { onClick={() => copyToClipboard(encoded)} className="h-8 px-2 text-xs" > - Copy + Copy )} @@ -114,7 +114,7 @@ export default function UrlEncoder() {
diff --git a/app/routes/tools/uuid-generator.tsx b/app/routes/tools/uuid-generator.tsx index 86e60a53..e6a24df9 100644 --- a/app/routes/tools/uuid-generator.tsx +++ b/app/routes/tools/uuid-generator.tsx @@ -3,7 +3,12 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Copy, RefreshCw, Trash2, Fingerprint } from "lucide-react"; +import { + PiCopy, + PiArrowClockwise, + PiTrash, + PiFingerprint, +} from "react-icons/pi"; import { toast } from "sonner"; export default function UuidGenerator() { @@ -104,7 +109,7 @@ export default function UuidGenerator() {
@@ -124,7 +129,7 @@ export default function UuidGenerator() { onClick={copyAll} className="h-8 px-2 text-xs" > - Copy All + Copy All )} @@ -156,14 +161,14 @@ export default function UuidGenerator() { className="h-7 w-7 opacity-0 group-hover:opacity-100 transition-opacity" onClick={() => copyToClipboard(uuid)} > - + ))} ) : (
- +

Click Generate to create UUIDs

)} diff --git a/app/routes/tools/word-counter.tsx b/app/routes/tools/word-counter.tsx index 68d7a6cb..15faac11 100644 --- a/app/routes/tools/word-counter.tsx +++ b/app/routes/tools/word-counter.tsx @@ -1,7 +1,7 @@ import { useState, useMemo } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { ClipboardPaste, Trash2 } from "lucide-react"; +import { PiClipboard, PiTrash } from "react-icons/pi"; export default function WordCounter() { const [text, setText] = useState(""); @@ -77,7 +77,7 @@ export default function WordCounter() { onClick={handlePaste} className="h-8 px-2 text-xs" > - Paste + Paste diff --git a/bun.lock b/bun.lock index bc2a637e..4d8477bf 100644 --- a/bun.lock +++ b/bun.lock @@ -30,7 +30,6 @@ "convex": "^1.29.0", "current-git-branch": "^2.0.2", "isbot": "^5.1.31", - "lucide-react": "^0.553.0", "md5": "^2.3.0", "motion": "^12.23.24", "next-themes": "^0.4.6", @@ -39,6 +38,7 @@ "react": "^19.1.1", "react-dom": "^19.1.1", "react-hotkeys-hook": "^5.2.1", + "react-icons": "^5.5.0", "react-router": "^7.9.2", "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", @@ -1050,6 +1050,8 @@ "react-hotkeys-hook": ["react-hotkeys-hook@5.2.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg=="], + "react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="], + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "react-promise-suspense": ["react-promise-suspense@0.3.4", "", { "dependencies": { "fast-deep-equal": "^2.0.1" } }, "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ=="], diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 159b79d1..2d5a5eb6 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -1,13 +1,13 @@ import { - ChevronDown, - Clock, - Code, - GalleryVerticalEnd, - GitBranch, - PanelLeft, - Search, - Settings, -} from "lucide-react"; + PiCaretDown, + PiClock, + PiCode, + PiRows, + PiGitBranch, + PiSidebarSimple, + PiMagnifyingGlass, + PiGear, +} from "react-icons/pi"; import { Link, useLocation } from "react-router"; import { Sidebar, @@ -58,7 +58,7 @@ export function AppSidebar() { const setSearchOpen = useUiState((state) => state.setSearchOpen); const location = useLocation(); const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const currentUser = useQuery(api.auth.getCurrentUser); @@ -86,7 +86,7 @@ export function AppSidebar() { const menuItems = MENU_ITEMS.filter( (item) => !(item.experimental && !experimentalFeatures) && - !(item.requiresAdmin && !isAdmin), + !(item.requiresAdmin && !isAdmin) ); // Hide sidebar completely when experimental features are off @@ -99,7 +99,7 @@ export function AppSidebar() { variant="inset" className={clsx( "p-0 duration-200 transition-all ease-out", - !sidebar.open && !disableAllBlur && "blur-lg opacity-0", + !sidebar.open && !disableAllBlur && "blur-lg opacity-0" )} > @@ -126,7 +126,7 @@ export function AppSidebar() { onClick={() => setSearchOpen(true)} className="border cursor-text" > - + Search ⌘ @@ -144,7 +144,7 @@ export function AppSidebar() { {menuItems.map((item) => { const renderMenuItem = ( menuItem: typeof item, - isSubItem = false, + isSubItem = false ) => { const content = renderMenuItemContent(menuItem); const MenuButtonWrapper = isSubItem @@ -185,7 +185,7 @@ export function AppSidebar() { child.href == location.pathname, + (child) => child.href == location.pathname )} > @@ -237,15 +237,15 @@ export function AppSidebar() { target="_blank" className="flex flex-row gap-2 [&_svg:not([class*='size-'])]:size-4 items-center" > - + EducationalTools/src
- + {process.env.BRANCH_NAME}
- + Built on{" "} {new Date(process.env.BUILD_TIME || 0).toLocaleString()}
diff --git a/components/command-palette.tsx b/components/command-palette.tsx index 3454f207..51b3b4d2 100644 --- a/components/command-palette.tsx +++ b/components/command-palette.tsx @@ -8,21 +8,21 @@ import { CommandList, CommandShortcut, } from "@/components/ui/command"; -import { LogIn, LogOut, Settings } from "lucide-react"; +import { PiSignIn, PiSignOut, PiGear } from "react-icons/pi"; import { authClient } from "@/lib/auth-client"; export default function CommandPalette() { const commandPaletteOpen = useUiState((state) => state.commandPaletteOpen); const setCommandPaletteOpen = useUiState( - (state) => state.setCommandPaletteOpen, + (state) => state.setCommandPaletteOpen ); const setSettingsOpen = useUiState((state) => state.setSettingsOpen); const setLoadingOverlayOpen = useUiState( - (state) => state.setLoadingOverlayOpen, + (state) => state.setLoadingOverlayOpen ); const setLoadingOverlayMessage = useUiState( - (state) => state.setLoadingOverlayMessage, + (state) => state.setLoadingOverlayMessage ); const session = authClient.useSession(); @@ -35,7 +35,7 @@ export default function CommandPalette() { }[] = [ { label: "Settings", - icon: Settings, + icon: PiGear, onSelect: () => { setSettingsOpen(true); }, @@ -45,7 +45,7 @@ export default function CommandPalette() { ? [ { label: "Sign out", - icon: LogOut, + icon: PiSignOut, onSelect: async () => { setLoadingOverlayOpen(true); setLoadingOverlayMessage("Signing out..."); @@ -60,7 +60,7 @@ export default function CommandPalette() { { label: "Discord", id: "discord" }, ].map((item) => ({ label: "Continue with " + item.label, - icon: LogIn, + icon: PiSignIn, onSelect: async () => { const convexSiteUrl = new URL(import.meta.env.VITE_CONVEX_SITE_URL); diff --git a/components/header.tsx b/components/header.tsx index 2ab5b6df..b3c4005f 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -1,7 +1,13 @@ import { Link, useLocation } from "react-router"; import { useSidebar } from "./ui/sidebar"; import { Button, buttonVariants } from "./ui/button"; -import { Code, Loader2, Search, Settings, Sidebar } from "lucide-react"; +import { + PiCode, + PiSpinner, + PiMagnifyingGlass, + PiGear, + PiSidebarSimple, +} from "react-icons/pi"; import { motion, AnimatePresence } from "motion/react"; import { Breadcrumb, @@ -28,7 +34,7 @@ export default function Header() { const setSearchOpen = useUiState((state) => state.setSearchOpen); const setSettingsOpen = useUiState((state) => state.setSettingsOpen); const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const session = authClient.useSession(); @@ -69,7 +75,7 @@ export default function Header() { size="icon" onClick={() => setSearchOpen(true)} > - + @@ -97,7 +103,7 @@ export default function Header() { size="icon" onClick={() => sidebar.toggleSidebar()} > - + @@ -145,7 +151,7 @@ export default function Header() { size="icon" onClick={() => setSettingsOpen(true)} > - + diff --git a/components/search.tsx b/components/search.tsx index 39aa9894..fde21fd9 100644 --- a/components/search.tsx +++ b/components/search.tsx @@ -13,19 +13,19 @@ import { useCommandState } from "cmdk"; import { MENU_ITEMS } from "@/lib/menu"; import { useNavigate } from "react-router"; import { useEffect, useState } from "react"; -import { ArrowRight, Circle, CircleCheck } from "lucide-react"; +import { PiArrowRight, PiCircle, PiCheckCircle } from "react-icons/pi"; export default function Search() { const searchOpen = useUiState((state) => state.searchOpen); const setSearchOpen = useUiState((state) => state.setSearchOpen); const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const navigate = useNavigate(); const [placeholder, setPlaceholder] = useState("Search..."); const menuItems = MENU_ITEMS.filter( - (item) => !(item.experimental && !experimentalFeatures), + (item) => !(item.experimental && !experimentalFeatures) ); useEffect(() => { @@ -98,10 +98,10 @@ export default function Search() { function ExperimentalFeatures() { const search = useCommandState((state) => state.search); const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const toggleExperimentalFeatures = useExperimentalFeatures( - (state) => state.toggle, + (state) => state.toggle ); const setSearchOpen = useUiState((state) => state.setSearchOpen); @@ -117,7 +117,7 @@ function ExperimentalFeatures() { : "hidden" } > - {experimentalFeatures ? : } + {experimentalFeatures ? : } {experimentalFeatures ? "Disable" : "Enable"} Experimental Features ); diff --git a/components/settings.tsx b/components/settings.tsx index bf3db0cb..8d1e9ba1 100644 --- a/components/settings.tsx +++ b/components/settings.tsx @@ -29,19 +29,19 @@ import { CardTitle, } from "@/components/ui/card"; import { - Palette, - Shield, - Eye, - Keyboard, - Globe, - Info, - ArrowRight, - Trash2, - RotateCcw, - AlertTriangle, - Gauge, - Laptop, -} from "lucide-react"; + PiPalette, + PiShield, + PiEye, + PiKeyboard, + PiGlobe, + PiInfo, + PiArrowRight, + PiTrash, + PiArrowCounterClockwise, + PiWarning, + PiGauge, + PiLaptop, +} from "react-icons/pi"; import { Tabs, TabsList, TabsTrigger } from "./ui/tabs"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; @@ -78,37 +78,37 @@ export default function Settings() { const cloak = useSettingsState((state) => state.cloak); const setCloak = useSettingsState((state) => state.setCloak); const experimentalFeatures = useExperimentalFeatures( - (state) => state.enabled, + (state) => state.enabled ); const historyCollectionEnabled = usePrivacyState( - (state) => state.historyCollectionEnabled, + (state) => state.historyCollectionEnabled ); const setHistoryCollectionEnabled = usePrivacyState( - (state) => state.setHistoryCollectionEnabled, + (state) => state.setHistoryCollectionEnabled ); const history = useGmaeHistory((state) => state.history); const disableBlurBehind = useSettingsState( - (state) => state.disableBlurBehind, + (state) => state.disableBlurBehind ); const setDisableBlurBehind = useSettingsState( - (state) => state.setDisableBlurBehind, + (state) => state.setDisableBlurBehind ); const disableAllBlur = useSettingsState((state) => state.disableAllBlur); const setDisableAllBlur = useSettingsState( - (state) => state.setDisableAllBlur, + (state) => state.setDisableAllBlur ); const disableAnimations = useSettingsState( - (state) => state.disableAnimations, + (state) => state.disableAnimations ); const setDisableAnimations = useSettingsState( - (state) => state.setDisableAnimations, + (state) => state.setDisableAnimations ); const setLoadingOverlayOpen = useUiState( - (state) => state.setLoadingOverlayOpen, + (state) => state.setLoadingOverlayOpen ); const setLoadingOverlayMessage = useUiState( - (state) => state.setLoadingOverlayMessage, + (state) => state.setLoadingOverlayMessage ); const session = authClient.useSession(); @@ -135,7 +135,7 @@ export default function Settings() { size="lg" className="border rounded-xl" > - + Sessions @@ -153,7 +153,7 @@ export default function Settings() {
- + Theme
@@ -168,7 +168,7 @@ export default function Settings() {
- + Panic Key
- +