mirror of
				https://github.com/walkxcode/dashboard-icons.git
				synced 2025-10-26 21:19:04 +08:00 
			
		
		
		
	chore(web): remove unused components and styles
This commit is contained in:
		| @@ -42,7 +42,6 @@ | ||||
| 		"canvas-confetti": "^1.9.3", | ||||
| 		"class-variance-authority": "^0.7.1", | ||||
| 		"clsx": "^2.1.1", | ||||
| 		"cmdk": "^1.1.1", | ||||
| 		"date-fns": "^4.1.0", | ||||
| 		"embla-carousel-react": "^8.6.0", | ||||
| 		"framer-motion": "^12.7.3", | ||||
|   | ||||
							
								
								
									
										249
									
								
								web/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										249
									
								
								web/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @@ -101,9 +101,6 @@ importers: | ||||
|       clsx: | ||||
|         specifier: ^2.1.1 | ||||
|         version: 2.1.1 | ||||
|       cmdk: | ||||
|         specifier: ^1.1.1 | ||||
|         version: 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.0))(@types/react@19.1.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) | ||||
|       date-fns: | ||||
|         specifier: ^4.1.0 | ||||
|         version: 4.1.0 | ||||
| @@ -160,7 +157,7 @@ importers: | ||||
|         version: 3.2.0 | ||||
|       tailwindcss-motion: | ||||
|         specifier: ^1.1.0 | ||||
|         version: 1.1.0(tailwindcss@4.1.3) | ||||
|         version: 1.1.0(tailwindcss@4.1.4) | ||||
|       tw-animate-css: | ||||
|         specifier: ^1.2.5 | ||||
|         version: 1.2.5 | ||||
| @@ -176,13 +173,13 @@ importers: | ||||
|         version: 1.9.4 | ||||
|       '@tailwindcss/postcss': | ||||
|         specifier: ^4.1.3 | ||||
|         version: 4.1.3 | ||||
|         version: 4.1.4 | ||||
|       '@types/canvas-confetti': | ||||
|         specifier: ^1.9.0 | ||||
|         version: 1.9.0 | ||||
|       '@types/node': | ||||
|         specifier: ^22.14.0 | ||||
|         version: 22.14.0 | ||||
|         version: 22.14.1 | ||||
|       '@types/react': | ||||
|         specifier: ^19.1.0 | ||||
|         version: 19.1.0 | ||||
| @@ -191,13 +188,13 @@ importers: | ||||
|         version: 19.1.2(@types/react@19.1.0) | ||||
|       tailwindcss: | ||||
|         specifier: ^4.1.3 | ||||
|         version: 4.1.3 | ||||
|         version: 4.1.4 | ||||
|       typescript: | ||||
|         specifier: ^5.8.3 | ||||
|         version: 5.8.3 | ||||
|       wrangler: | ||||
|         specifier: ^4.12.0 | ||||
|         version: 4.12.0 | ||||
|         version: 4.12.1 | ||||
|  | ||||
| packages: | ||||
|  | ||||
| @@ -275,32 +272,32 @@ packages: | ||||
|       workerd: | ||||
|         optional: true | ||||
|  | ||||
|   '@cloudflare/workerd-darwin-64@1.20250416.0': | ||||
|     resolution: {integrity: sha512-aZgF8Swp9eVYxJPWOoZbAgAaYjWuYqGmEA+QJ2ecRGDBqm87rT4GEw7/mmLpxrpllny3VfEEhkk9iYCGv8nlFw==} | ||||
|   '@cloudflare/workerd-darwin-64@1.20250417.0': | ||||
|     resolution: {integrity: sha512-4Adfl92aKepjxb8e6af2d+xpD2sBOADgHqvkyXsFmoLb80weMEDDRGJi1p1m5q1M78/oVnGcpdmuRCAathanRg==} | ||||
|     engines: {node: '>=16'} | ||||
|     cpu: [x64] | ||||
|     os: [darwin] | ||||
|  | ||||
|   '@cloudflare/workerd-darwin-arm64@1.20250416.0': | ||||
|     resolution: {integrity: sha512-FhswG1QYRfaTZ4FAlUkfVWaoM2lrlqumiBTrhbo9czMJdGR/oBXS4SGynuI6zyhApHeBf3/fZpA/SBAe4cXdgg==} | ||||
|   '@cloudflare/workerd-darwin-arm64@1.20250417.0': | ||||
|     resolution: {integrity: sha512-dSlk18F4i3T1OTzFBxx3pKpXRMP6w2xZ26+oIV32BFWrCi/HxGzUd6gVA0q37oLGqITRt8xU693J4Gl1CwC/Ag==} | ||||
|     engines: {node: '>=16'} | ||||
|     cpu: [arm64] | ||||
|     os: [darwin] | ||||
|  | ||||
|   '@cloudflare/workerd-linux-64@1.20250416.0': | ||||
|     resolution: {integrity: sha512-G+nXEAJ/9y+A857XShwxKeRdfxok6UcjiQe6G+wQeCn/Ofkp/EWydacKdyeVU6QIm1oHS78DwJ7AzbCYywf9aw==} | ||||
|   '@cloudflare/workerd-linux-64@1.20250417.0': | ||||
|     resolution: {integrity: sha512-27MVzOa/lENcqewC2L9EcqstXW843UhjBMcwV1umDfsjwLyZOEv6Gtm/6j5r0L0gASvkRTam3fAmtPk/gt48TA==} | ||||
|     engines: {node: '>=16'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@cloudflare/workerd-linux-arm64@1.20250416.0': | ||||
|     resolution: {integrity: sha512-U6oVW0d9w1fpnDYNrjPJ9SFkDlGJWJWbXHlTBObXl6vccP16WewvuxyHkKqyUhUc8hyBaph7sxeKzKmuCFQ4SA==} | ||||
|   '@cloudflare/workerd-linux-arm64@1.20250417.0': | ||||
|     resolution: {integrity: sha512-34qBk0htAXmUneOTQxW6/g6pjNVR91r0vJzz2FID84cAIOYVl4hZLijkjmVl+MMDU6boXUs+yDwhItdg06YvAg==} | ||||
|     engines: {node: '>=16'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@cloudflare/workerd-windows-64@1.20250416.0': | ||||
|     resolution: {integrity: sha512-YAjjTzL1z9YYeN4sqYfj1dtQXd2Bblj+B+hl4Rz2aOhblpZEZAdhapZlOCRvLLkOJshKJUnRD3mDlytAdgwybQ==} | ||||
|   '@cloudflare/workerd-windows-64@1.20250417.0': | ||||
|     resolution: {integrity: sha512-PDwATFioff+geVHfgTzSWsxgwjgotrdXStb0EL0lMyMT5zNmHArAnOx83CbDtud63Uv9rVX1BAfPP4tyD1O+5A==} | ||||
|     engines: {node: '>=16'} | ||||
|     cpu: [x64] | ||||
|     os: [win32] | ||||
| @@ -1365,81 +1362,93 @@ packages: | ||||
|   '@swc/helpers@0.5.15': | ||||
|     resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} | ||||
|  | ||||
|   '@tailwindcss/node@4.1.3': | ||||
|     resolution: {integrity: sha512-H/6r6IPFJkCfBJZ2dKZiPJ7Ueb2wbL592+9bQEl2r73qbX6yGnmQVIfiUvDRB2YI0a3PWDrzUwkvQx1XW1bNkA==} | ||||
|   '@tailwindcss/node@4.1.4': | ||||
|     resolution: {integrity: sha512-MT5118zaiO6x6hNA04OWInuAiP1YISXql8Z+/Y8iisV5nuhM8VXlyhRuqc2PEviPszcXI66W44bCIk500Oolhw==} | ||||
|  | ||||
|   '@tailwindcss/oxide-android-arm64@4.1.3': | ||||
|     resolution: {integrity: sha512-cxklKjtNLwFl3mDYw4XpEfBY+G8ssSg9ADL4Wm6//5woi3XGqlxFsnV5Zb6v07dxw1NvEX2uoqsxO/zWQsgR+g==} | ||||
|   '@tailwindcss/oxide-android-arm64@4.1.4': | ||||
|     resolution: {integrity: sha512-xMMAe/SaCN/vHfQYui3fqaBDEXMu22BVwQ33veLc8ep+DNy7CWN52L+TTG9y1K397w9nkzv+Mw+mZWISiqhmlA==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [android] | ||||
|  | ||||
|   '@tailwindcss/oxide-darwin-arm64@4.1.3': | ||||
|     resolution: {integrity: sha512-mqkf2tLR5VCrjBvuRDwzKNShRu99gCAVMkVsaEOFvv6cCjlEKXRecPu9DEnxp6STk5z+Vlbh1M5zY3nQCXMXhw==} | ||||
|   '@tailwindcss/oxide-darwin-arm64@4.1.4': | ||||
|     resolution: {integrity: sha512-JGRj0SYFuDuAGilWFBlshcexev2hOKfNkoX+0QTksKYq2zgF9VY/vVMq9m8IObYnLna0Xlg+ytCi2FN2rOL0Sg==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [darwin] | ||||
|  | ||||
|   '@tailwindcss/oxide-darwin-x64@4.1.3': | ||||
|     resolution: {integrity: sha512-7sGraGaWzXvCLyxrc7d+CCpUN3fYnkkcso3rCzwUmo/LteAl2ZGCDlGvDD8Y/1D3ngxT8KgDj1DSwOnNewKhmg==} | ||||
|   '@tailwindcss/oxide-darwin-x64@4.1.4': | ||||
|     resolution: {integrity: sha512-sdDeLNvs3cYeWsEJ4H1DvjOzaGios4QbBTNLVLVs0XQ0V95bffT3+scptzYGPMjm7xv4+qMhCDrkHwhnUySEzA==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [darwin] | ||||
|  | ||||
|   '@tailwindcss/oxide-freebsd-x64@4.1.3': | ||||
|     resolution: {integrity: sha512-E2+PbcbzIReaAYZe997wb9rId246yDkCwAakllAWSGqe6VTg9hHle67hfH6ExjpV2LSK/siRzBUs5wVff3RW9w==} | ||||
|   '@tailwindcss/oxide-freebsd-x64@4.1.4': | ||||
|     resolution: {integrity: sha512-VHxAqxqdghM83HslPhRsNhHo91McsxRJaEnShJOMu8mHmEj9Ig7ToHJtDukkuLWLzLboh2XSjq/0zO6wgvykNA==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [freebsd] | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.3': | ||||
|     resolution: {integrity: sha512-GvfbJ8wjSSjbLFFE3UYz4Eh8i4L6GiEYqCtA8j2Zd2oXriPuom/Ah/64pg/szWycQpzRnbDiJozoxFU2oJZyfg==} | ||||
|   '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.4': | ||||
|     resolution: {integrity: sha512-OTU/m/eV4gQKxy9r5acuesqaymyeSCnsx1cFto/I1WhPmi5HDxX1nkzb8KYBiwkHIGg7CTfo/AcGzoXAJBxLfg==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm64-gnu@4.1.3': | ||||
|     resolution: {integrity: sha512-35UkuCWQTeG9BHcBQXndDOrpsnt3Pj9NVIB4CgNiKmpG8GnCNXeMczkUpOoqcOhO6Cc/mM2W7kaQ/MTEENDDXg==} | ||||
|   '@tailwindcss/oxide-linux-arm64-gnu@4.1.4': | ||||
|     resolution: {integrity: sha512-hKlLNvbmUC6z5g/J4H+Zx7f7w15whSVImokLPmP6ff1QqTVE+TxUM9PGuNsjHvkvlHUtGTdDnOvGNSEUiXI1Ww==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm64-musl@4.1.3': | ||||
|     resolution: {integrity: sha512-dm18aQiML5QCj9DQo7wMbt1Z2tl3Giht54uVR87a84X8qRtuXxUqnKQkRDK5B4bCOmcZ580lF9YcoMkbDYTXHQ==} | ||||
|   '@tailwindcss/oxide-linux-arm64-musl@4.1.4': | ||||
|     resolution: {integrity: sha512-X3As2xhtgPTY/m5edUtddmZ8rCruvBvtxYLMw9OsZdH01L2gS2icsHRwxdU0dMItNfVmrBezueXZCHxVeeb7Aw==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-x64-gnu@4.1.3': | ||||
|     resolution: {integrity: sha512-LMdTmGe/NPtGOaOfV2HuO7w07jI3cflPrVq5CXl+2O93DCewADK0uW1ORNAcfu2YxDUS035eY2W38TxrsqngxA==} | ||||
|   '@tailwindcss/oxide-linux-x64-gnu@4.1.4': | ||||
|     resolution: {integrity: sha512-2VG4DqhGaDSmYIu6C4ua2vSLXnJsb/C9liej7TuSO04NK+JJJgJucDUgmX6sn7Gw3Cs5ZJ9ZLrnI0QRDOjLfNQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-x64-musl@4.1.3': | ||||
|     resolution: {integrity: sha512-aalNWwIi54bbFEizwl1/XpmdDrOaCjRFQRgtbv9slWjmNPuJJTIKPHf5/XXDARc9CneW9FkSTqTbyvNecYAEGw==} | ||||
|   '@tailwindcss/oxide-linux-x64-musl@4.1.4': | ||||
|     resolution: {integrity: sha512-v+mxVgH2kmur/X5Mdrz9m7TsoVjbdYQT0b4Z+dr+I4RvreCNXyCFELZL/DO0M1RsidZTrm6O1eMnV6zlgEzTMQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|  | ||||
|   '@tailwindcss/oxide-win32-arm64-msvc@4.1.3': | ||||
|     resolution: {integrity: sha512-PEj7XR4OGTGoboTIAdXicKuWl4EQIjKHKuR+bFy9oYN7CFZo0eu74+70O4XuERX4yjqVZGAkCdglBODlgqcCXg==} | ||||
|   '@tailwindcss/oxide-wasm32-wasi@4.1.4': | ||||
|     resolution: {integrity: sha512-2TLe9ir+9esCf6Wm+lLWTMbgklIjiF0pbmDnwmhR9MksVOq+e8aP3TSsXySnBDDvTTVd/vKu1aNttEGj3P6l8Q==} | ||||
|     engines: {node: '>=14.0.0'} | ||||
|     cpu: [wasm32] | ||||
|     bundledDependencies: | ||||
|       - '@napi-rs/wasm-runtime' | ||||
|       - '@emnapi/core' | ||||
|       - '@emnapi/runtime' | ||||
|       - '@tybys/wasm-util' | ||||
|       - '@emnapi/wasi-threads' | ||||
|       - tslib | ||||
|  | ||||
|   '@tailwindcss/oxide-win32-arm64-msvc@4.1.4': | ||||
|     resolution: {integrity: sha512-VlnhfilPlO0ltxW9/BgfLI5547PYzqBMPIzRrk4W7uupgCt8z6Trw/tAj6QUtF2om+1MH281Pg+HHUJoLesmng==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [win32] | ||||
|  | ||||
|   '@tailwindcss/oxide-win32-x64-msvc@4.1.3': | ||||
|     resolution: {integrity: sha512-T8gfxECWDBENotpw3HR9SmNiHC9AOJdxs+woasRZ8Q/J4VHN0OMs7F+4yVNZ9EVN26Wv6mZbK0jv7eHYuLJLwA==} | ||||
|   '@tailwindcss/oxide-win32-x64-msvc@4.1.4': | ||||
|     resolution: {integrity: sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [win32] | ||||
|  | ||||
|   '@tailwindcss/oxide@4.1.3': | ||||
|     resolution: {integrity: sha512-t16lpHCU7LBxDe/8dCj9ntyNpXaSTAgxWm1u2XQP5NiIu4KGSyrDJJRlK9hJ4U9yJxx0UKCVI67MJWFNll5mOQ==} | ||||
|   '@tailwindcss/oxide@4.1.4': | ||||
|     resolution: {integrity: sha512-p5wOpXyOJx7mKh5MXh5oKk+kqcz8T+bA3z/5VWWeQwFrmuBItGwz8Y2CHk/sJ+dNb9B0nYFfn0rj/cKHZyjahQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|  | ||||
|   '@tailwindcss/postcss@4.1.3': | ||||
|     resolution: {integrity: sha512-6s5nJODm98F++QT49qn8xJKHQRamhYHfMi3X7/ltxiSQ9dyRsaFSfFkfaMsanWzf+TMYQtbk8mt5f6cCVXJwfg==} | ||||
|   '@tailwindcss/postcss@4.1.4': | ||||
|     resolution: {integrity: sha512-bjV6sqycCEa+AQSt2Kr7wpGF1bOZJ5wsqnLEkqSbM/JEHxx/yhMH8wHmdkPyApF9xhHeMSwnnkDUUMMM/hYnXw==} | ||||
|  | ||||
|   '@tanstack/react-virtual@3.13.6': | ||||
|     resolution: {integrity: sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA==} | ||||
| @@ -1480,8 +1489,8 @@ packages: | ||||
|   '@types/d3-timer@3.0.2': | ||||
|     resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} | ||||
|  | ||||
|   '@types/node@22.14.0': | ||||
|     resolution: {integrity: sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==} | ||||
|   '@types/node@22.14.1': | ||||
|     resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} | ||||
|  | ||||
|   '@types/react-dom@19.1.2': | ||||
|     resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==} | ||||
| @@ -1540,12 +1549,6 @@ packages: | ||||
|     resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} | ||||
|     engines: {node: '>=6'} | ||||
|  | ||||
|   cmdk@1.1.1: | ||||
|     resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} | ||||
|     peerDependencies: | ||||
|       react: ^18 || ^19 || ^19.0.0-rc | ||||
|       react-dom: ^18 || ^19 || ^19.0.0-rc | ||||
|  | ||||
|   color-convert@2.0.1: | ||||
|     resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} | ||||
|     engines: {node: '>=7.0.0'} | ||||
| @@ -1888,8 +1891,8 @@ packages: | ||||
|     engines: {node: '>=10.0.0'} | ||||
|     hasBin: true | ||||
|  | ||||
|   miniflare@4.20250416.0: | ||||
|     resolution: {integrity: sha512-261PhPgD9zs5/BTdbWqwiaXtWxb+Av5zKCwTU+HXrA5E4tf3qnULwh3u6SVUOAEArEroFuKJzawsQ9COtNBurQ==} | ||||
|   miniflare@4.20250417.0: | ||||
|     resolution: {integrity: sha512-bROKLQKr4CoS93tnGuw5e08VaNwM3VowTL3Z2Cps1HzY6a4Bq8uNtggQ7WogriMq77jcHn6kbz64bvWyF//Jkw==} | ||||
|     engines: {node: '>=18.0.0'} | ||||
|     hasBin: true | ||||
|  | ||||
| @@ -2153,8 +2156,8 @@ packages: | ||||
|     peerDependencies: | ||||
|       tailwindcss: '>=3.0.0 || insiders' | ||||
|  | ||||
|   tailwindcss@4.1.3: | ||||
|     resolution: {integrity: sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==} | ||||
|   tailwindcss@4.1.4: | ||||
|     resolution: {integrity: sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==} | ||||
|  | ||||
|   tapable@2.2.1: | ||||
|     resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} | ||||
| @@ -2219,17 +2222,17 @@ packages: | ||||
|   web-vitals@4.2.4: | ||||
|     resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} | ||||
|  | ||||
|   workerd@1.20250416.0: | ||||
|     resolution: {integrity: sha512-Yrx/bZAKbmSvomdTAzzIpOHwpYhs0ldr2wqed22UEhQ0mIplAHY4xmY+SjAJhP/TydZrciOVzBxwM1+4T40KNA==} | ||||
|   workerd@1.20250417.0: | ||||
|     resolution: {integrity: sha512-naz6oJiVODd3/Lkp9l3vtc56HKOOvx+AWDvEsTa5eSfi5SI9V0HYpLYSPblAwrfazbQ4ff1Vl3jkTl/5JxqCAA==} | ||||
|     engines: {node: '>=16'} | ||||
|     hasBin: true | ||||
|  | ||||
|   wrangler@4.12.0: | ||||
|     resolution: {integrity: sha512-4rfAXOi5KqM3ECvOrZJ97k3zEqxVwtdt4bijd8jcRBZ6iJYvEtjgjVi4TsfkVa/eXGhpfHTUnKu2uk8UHa8M2w==} | ||||
|   wrangler@4.12.1: | ||||
|     resolution: {integrity: sha512-jYrz8y2ffhsRqvQLO2dXFi9HLvPUJk3jn7U71GWfBBCHm0I6r2ik7Vs9ajpRcTGlbNw1RY0uIHVJBVR/7bEN5A==} | ||||
|     engines: {node: '>=18.0.0'} | ||||
|     hasBin: true | ||||
|     peerDependencies: | ||||
|       '@cloudflare/workers-types': ^4.20250415.0 | ||||
|       '@cloudflare/workers-types': ^4.20250417.0 | ||||
|     peerDependenciesMeta: | ||||
|       '@cloudflare/workers-types': | ||||
|         optional: true | ||||
| @@ -2302,25 +2305,25 @@ snapshots: | ||||
|     dependencies: | ||||
|       mime: 3.0.0 | ||||
|  | ||||
|   '@cloudflare/unenv-preset@2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250416.0)': | ||||
|   '@cloudflare/unenv-preset@2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250417.0)': | ||||
|     dependencies: | ||||
|       unenv: 2.0.0-rc.15 | ||||
|     optionalDependencies: | ||||
|       workerd: 1.20250416.0 | ||||
|       workerd: 1.20250417.0 | ||||
|  | ||||
|   '@cloudflare/workerd-darwin-64@1.20250416.0': | ||||
|   '@cloudflare/workerd-darwin-64@1.20250417.0': | ||||
|     optional: true | ||||
|  | ||||
|   '@cloudflare/workerd-darwin-arm64@1.20250416.0': | ||||
|   '@cloudflare/workerd-darwin-arm64@1.20250417.0': | ||||
|     optional: true | ||||
|  | ||||
|   '@cloudflare/workerd-linux-64@1.20250416.0': | ||||
|   '@cloudflare/workerd-linux-64@1.20250417.0': | ||||
|     optional: true | ||||
|  | ||||
|   '@cloudflare/workerd-linux-arm64@1.20250416.0': | ||||
|   '@cloudflare/workerd-linux-arm64@1.20250417.0': | ||||
|     optional: true | ||||
|  | ||||
|   '@cloudflare/workerd-windows-64@1.20250416.0': | ||||
|   '@cloudflare/workerd-windows-64@1.20250417.0': | ||||
|     optional: true | ||||
|  | ||||
|   '@cspotcode/source-map-support@0.8.1': | ||||
| @@ -3264,67 +3267,71 @@ snapshots: | ||||
|     dependencies: | ||||
|       tslib: 2.8.1 | ||||
|  | ||||
|   '@tailwindcss/node@4.1.3': | ||||
|   '@tailwindcss/node@4.1.4': | ||||
|     dependencies: | ||||
|       enhanced-resolve: 5.18.1 | ||||
|       jiti: 2.4.2 | ||||
|       lightningcss: 1.29.2 | ||||
|       tailwindcss: 4.1.3 | ||||
|       tailwindcss: 4.1.4 | ||||
|  | ||||
|   '@tailwindcss/oxide-android-arm64@4.1.3': | ||||
|   '@tailwindcss/oxide-android-arm64@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-darwin-arm64@4.1.3': | ||||
|   '@tailwindcss/oxide-darwin-arm64@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-darwin-x64@4.1.3': | ||||
|   '@tailwindcss/oxide-darwin-x64@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-freebsd-x64@4.1.3': | ||||
|   '@tailwindcss/oxide-freebsd-x64@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.3': | ||||
|   '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm64-gnu@4.1.3': | ||||
|   '@tailwindcss/oxide-linux-arm64-gnu@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-arm64-musl@4.1.3': | ||||
|   '@tailwindcss/oxide-linux-arm64-musl@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-x64-gnu@4.1.3': | ||||
|   '@tailwindcss/oxide-linux-x64-gnu@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-linux-x64-musl@4.1.3': | ||||
|   '@tailwindcss/oxide-linux-x64-musl@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-win32-arm64-msvc@4.1.3': | ||||
|   '@tailwindcss/oxide-wasm32-wasi@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide-win32-x64-msvc@4.1.3': | ||||
|   '@tailwindcss/oxide-win32-arm64-msvc@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide@4.1.3': | ||||
|   '@tailwindcss/oxide-win32-x64-msvc@4.1.4': | ||||
|     optional: true | ||||
|  | ||||
|   '@tailwindcss/oxide@4.1.4': | ||||
|     optionalDependencies: | ||||
|       '@tailwindcss/oxide-android-arm64': 4.1.3 | ||||
|       '@tailwindcss/oxide-darwin-arm64': 4.1.3 | ||||
|       '@tailwindcss/oxide-darwin-x64': 4.1.3 | ||||
|       '@tailwindcss/oxide-freebsd-x64': 4.1.3 | ||||
|       '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.3 | ||||
|       '@tailwindcss/oxide-linux-arm64-gnu': 4.1.3 | ||||
|       '@tailwindcss/oxide-linux-arm64-musl': 4.1.3 | ||||
|       '@tailwindcss/oxide-linux-x64-gnu': 4.1.3 | ||||
|       '@tailwindcss/oxide-linux-x64-musl': 4.1.3 | ||||
|       '@tailwindcss/oxide-win32-arm64-msvc': 4.1.3 | ||||
|       '@tailwindcss/oxide-win32-x64-msvc': 4.1.3 | ||||
|       '@tailwindcss/oxide-android-arm64': 4.1.4 | ||||
|       '@tailwindcss/oxide-darwin-arm64': 4.1.4 | ||||
|       '@tailwindcss/oxide-darwin-x64': 4.1.4 | ||||
|       '@tailwindcss/oxide-freebsd-x64': 4.1.4 | ||||
|       '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.4 | ||||
|       '@tailwindcss/oxide-linux-arm64-gnu': 4.1.4 | ||||
|       '@tailwindcss/oxide-linux-arm64-musl': 4.1.4 | ||||
|       '@tailwindcss/oxide-linux-x64-gnu': 4.1.4 | ||||
|       '@tailwindcss/oxide-linux-x64-musl': 4.1.4 | ||||
|       '@tailwindcss/oxide-wasm32-wasi': 4.1.4 | ||||
|       '@tailwindcss/oxide-win32-arm64-msvc': 4.1.4 | ||||
|       '@tailwindcss/oxide-win32-x64-msvc': 4.1.4 | ||||
|  | ||||
|   '@tailwindcss/postcss@4.1.3': | ||||
|   '@tailwindcss/postcss@4.1.4': | ||||
|     dependencies: | ||||
|       '@alloc/quick-lru': 5.2.0 | ||||
|       '@tailwindcss/node': 4.1.3 | ||||
|       '@tailwindcss/oxide': 4.1.3 | ||||
|       '@tailwindcss/node': 4.1.4 | ||||
|       '@tailwindcss/oxide': 4.1.4 | ||||
|       postcss: 8.5.3 | ||||
|       tailwindcss: 4.1.3 | ||||
|       tailwindcss: 4.1.4 | ||||
|  | ||||
|   '@tanstack/react-virtual@3.13.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': | ||||
|     dependencies: | ||||
| @@ -3360,7 +3367,7 @@ snapshots: | ||||
|  | ||||
|   '@types/d3-timer@3.0.2': {} | ||||
|  | ||||
|   '@types/node@22.14.0': | ||||
|   '@types/node@22.14.1': | ||||
|     dependencies: | ||||
|       undici-types: 6.21.0 | ||||
|  | ||||
| @@ -3417,18 +3424,6 @@ snapshots: | ||||
|  | ||||
|   clsx@2.1.1: {} | ||||
|  | ||||
|   cmdk@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.0))(@types/react@19.1.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): | ||||
|     dependencies: | ||||
|       '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.0)(react@19.1.0) | ||||
|       '@radix-ui/react-dialog': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.0))(@types/react@19.1.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) | ||||
|       '@radix-ui/react-id': 1.1.1(@types/react@19.1.0)(react@19.1.0) | ||||
|       '@radix-ui/react-primitive': 2.0.3(@types/react-dom@19.1.2(@types/react@19.1.0))(@types/react@19.1.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) | ||||
|       react: 19.1.0 | ||||
|       react-dom: 19.1.0(react@19.1.0) | ||||
|     transitivePeerDependencies: | ||||
|       - '@types/react' | ||||
|       - '@types/react-dom' | ||||
|  | ||||
|   color-convert@2.0.1: | ||||
|     dependencies: | ||||
|       color-name: 1.1.4 | ||||
| @@ -3735,7 +3730,7 @@ snapshots: | ||||
|  | ||||
|   mime@3.0.0: {} | ||||
|  | ||||
|   miniflare@4.20250416.0: | ||||
|   miniflare@4.20250417.0: | ||||
|     dependencies: | ||||
|       '@cspotcode/source-map-support': 0.8.1 | ||||
|       acorn: 8.14.0 | ||||
| @@ -3744,7 +3739,7 @@ snapshots: | ||||
|       glob-to-regexp: 0.4.1 | ||||
|       stoppable: 1.1.0 | ||||
|       undici: 5.29.0 | ||||
|       workerd: 1.20250416.0 | ||||
|       workerd: 1.20250417.0 | ||||
|       ws: 8.18.0 | ||||
|       youch: 3.3.4 | ||||
|       zod: 3.22.3 | ||||
| @@ -4025,11 +4020,11 @@ snapshots: | ||||
|  | ||||
|   tailwind-merge@3.2.0: {} | ||||
|  | ||||
|   tailwindcss-motion@1.1.0(tailwindcss@4.1.3): | ||||
|   tailwindcss-motion@1.1.0(tailwindcss@4.1.4): | ||||
|     dependencies: | ||||
|       tailwindcss: 4.1.3 | ||||
|       tailwindcss: 4.1.4 | ||||
|  | ||||
|   tailwindcss@4.1.3: {} | ||||
|   tailwindcss@4.1.4: {} | ||||
|  | ||||
|   tapable@2.2.1: {} | ||||
|  | ||||
| @@ -4100,24 +4095,24 @@ snapshots: | ||||
|  | ||||
|   web-vitals@4.2.4: {} | ||||
|  | ||||
|   workerd@1.20250416.0: | ||||
|   workerd@1.20250417.0: | ||||
|     optionalDependencies: | ||||
|       '@cloudflare/workerd-darwin-64': 1.20250416.0 | ||||
|       '@cloudflare/workerd-darwin-arm64': 1.20250416.0 | ||||
|       '@cloudflare/workerd-linux-64': 1.20250416.0 | ||||
|       '@cloudflare/workerd-linux-arm64': 1.20250416.0 | ||||
|       '@cloudflare/workerd-windows-64': 1.20250416.0 | ||||
|       '@cloudflare/workerd-darwin-64': 1.20250417.0 | ||||
|       '@cloudflare/workerd-darwin-arm64': 1.20250417.0 | ||||
|       '@cloudflare/workerd-linux-64': 1.20250417.0 | ||||
|       '@cloudflare/workerd-linux-arm64': 1.20250417.0 | ||||
|       '@cloudflare/workerd-windows-64': 1.20250417.0 | ||||
|  | ||||
|   wrangler@4.12.0: | ||||
|   wrangler@4.12.1: | ||||
|     dependencies: | ||||
|       '@cloudflare/kv-asset-handler': 0.4.0 | ||||
|       '@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250416.0) | ||||
|       '@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250417.0) | ||||
|       blake3-wasm: 2.1.5 | ||||
|       esbuild: 0.25.2 | ||||
|       miniflare: 4.20250416.0 | ||||
|       miniflare: 4.20250417.0 | ||||
|       path-to-regexp: 6.3.0 | ||||
|       unenv: 2.0.0-rc.15 | ||||
|       workerd: 1.20250416.0 | ||||
|       workerd: 1.20250417.0 | ||||
|     optionalDependencies: | ||||
|       fsevents: 2.3.3 | ||||
|       sharp: 0.33.5 | ||||
|   | ||||
| @@ -118,19 +118,6 @@ | ||||
| 			transform: rotate(-5deg) scale(0.9); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	--animate-shiny-text: shiny-text 8s infinite; | ||||
| 	@keyframes shiny-text { | ||||
| 		0%, | ||||
| 		90%, | ||||
| 		100% { | ||||
| 			background-position: calc(-100% - var(--shiny-width)) 0; | ||||
| 		} | ||||
| 		30%, | ||||
| 		60% { | ||||
| 			background-position: calc(100% + var(--shiny-width)) 0; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| :root { | ||||
|   | ||||
| @@ -1,87 +0,0 @@ | ||||
| "use client" | ||||
|  | ||||
| import { Input } from "@/components/ui/input" | ||||
| import { BASE_URL } from "@/constants" | ||||
| import type { IconSearchProps, IconWithName } from "@/types/icons" | ||||
| import { Search } from "lucide-react" | ||||
| import Image from "next/image" | ||||
| import Link from "next/link" | ||||
| import { useState } from "react" | ||||
|  | ||||
| export function IconSearch({ icons, initialQuery = "" }: IconSearchProps) { | ||||
| 	const [searchQuery, setSearchQuery] = useState(initialQuery) | ||||
| 	const [filteredIcons, setFilteredIcons] = useState<IconWithName[]>(() => { | ||||
| 		if (!initialQuery.trim()) return icons | ||||
|  | ||||
| 		const q = initialQuery.toLowerCase() | ||||
| 		return icons.filter(({ name, data }) => { | ||||
| 			if (name.toLowerCase().includes(q)) return true | ||||
| 			if (data.aliases.some((alias) => alias.toLowerCase().includes(q))) return true | ||||
| 			if (data.categories.some((category) => category.toLowerCase().includes(q))) return true | ||||
|  | ||||
| 			return false | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
| 	const handleSearch = (query: string) => { | ||||
| 		setSearchQuery(query) | ||||
|  | ||||
| 		if (!query.trim()) { | ||||
| 			setFilteredIcons(icons) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		const q = query.toLowerCase() | ||||
| 		const filtered = icons.filter(({ name, data }) => { | ||||
| 			if (name.toLowerCase().includes(q)) return true | ||||
| 			if (data.aliases.some((alias) => alias.toLowerCase().includes(q))) return true | ||||
| 			if (data.categories.some((category) => category.toLowerCase().includes(q))) return true | ||||
|  | ||||
| 			return false | ||||
| 		}) | ||||
|  | ||||
| 		setFilteredIcons(filtered) | ||||
| 	} | ||||
|  | ||||
| 	return ( | ||||
| 		<> | ||||
| 			<div className="relative w-full max-w-md"> | ||||
| 				<Search className="absolute left-2.5 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground transition-all duration-300" /> | ||||
| 				<Input | ||||
| 					type="search" | ||||
| 					placeholder="Search icons by name, aliases, or categories..." | ||||
| 					className="w-full pl-8 transition-all duration-300 text-sm md:text-base" | ||||
| 					value={searchQuery} | ||||
| 					onChange={(e) => handleSearch(e.target.value)} | ||||
| 				/> | ||||
| 			</div> | ||||
|  | ||||
| 			{filteredIcons.length === 0 ? ( | ||||
| 				<div className="text-center py-12"> | ||||
| 					<h2 className="text-xl font-semibold">No icons found</h2> | ||||
| 					<p className="text-muted-foreground mt-2">Try a different search term.</p> | ||||
| 				</div> | ||||
| 			) : ( | ||||
| 				<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4 mt-8"> | ||||
| 					{filteredIcons.map(({ name, data }) => ( | ||||
| 						<Link | ||||
| 							key={name} | ||||
| 							href={`/icons/${name}`} | ||||
| 							className="group flex flex-col items-center p-4 rounded-lg border border-border hover:border-primary hover:bg-accent transition-colors" | ||||
| 						> | ||||
| 							<div className="relative h-16 w-16 mb-2"> | ||||
| 								<Image | ||||
| 									src={`${BASE_URL}/${data.base}/${name}.${data.base}`} | ||||
| 									alt={`${name} icon`} | ||||
| 									fill | ||||
| 									className="object-contain p-1 group-hover:scale-110 transition-transform" | ||||
| 								/> | ||||
| 							</div> | ||||
| 							<span className="text-sm text-center truncate w-full">{name.replace(/-/g, " ")}</span> | ||||
| 						</Link> | ||||
| 					))} | ||||
| 				</div> | ||||
| 			)} | ||||
| 		</> | ||||
| 	) | ||||
| } | ||||
| @@ -1,149 +0,0 @@ | ||||
| "use client" | ||||
|  | ||||
| import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command" | ||||
| import { useMediaQuery } from "@/hooks/use-media-query" | ||||
| import { fuzzySearch } from "@/lib/utils" | ||||
| import { Icon } from "@/types/icons" | ||||
| import { useRouter } from "next/navigation" | ||||
| import { useCallback, useEffect, useState } from "react" | ||||
|  | ||||
| interface CommandMenuProps { | ||||
| 	icons: { | ||||
| 		name: string | ||||
| 		data: { | ||||
| 			categories: string[] | ||||
| 			aliases: string[] | ||||
| 			[key: string]: unknown | ||||
| 		} | ||||
| 	}[] | ||||
| 	triggerButtonId?: string | ||||
| 	open?: boolean | ||||
| 	onOpenChange?: (open: boolean) => void | ||||
| } | ||||
|  | ||||
| export function CommandMenu({ icons, open: externalOpen, onOpenChange: externalOnOpenChange }: CommandMenuProps) { | ||||
| 	const router = useRouter() | ||||
| 	const [internalOpen, setInternalOpen] = useState(false) | ||||
| 	const [query, setQuery] = useState("") | ||||
| 	const isDesktop = useMediaQuery("(min-width: 768px)") | ||||
|  | ||||
| 	// Use either external or internal state for controlling open state | ||||
| 	const isOpen = externalOpen !== undefined ? externalOpen : internalOpen | ||||
|  | ||||
| 	// Wrap setIsOpen in useCallback to fix dependency issue | ||||
| 	const setIsOpen = useCallback( | ||||
| 		(value: boolean) => { | ||||
| 			if (externalOnOpenChange) { | ||||
| 				externalOnOpenChange(value) | ||||
| 			} else { | ||||
| 				setInternalOpen(value) | ||||
| 			} | ||||
| 		}, | ||||
| 		[externalOnOpenChange], | ||||
| 	) | ||||
|  | ||||
| 	const filteredIcons = getFilteredIcons(icons, query) | ||||
|  | ||||
| 	useEffect(() => { | ||||
| 		const handleKeyDown = (e: KeyboardEvent) => { | ||||
| 			if ( | ||||
| 				(e.key === "k" && (e.metaKey || e.ctrlKey)) || | ||||
| 				(e.key === "/" && document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA") | ||||
| 			) { | ||||
| 				e.preventDefault() | ||||
| 				setIsOpen(!isOpen) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		document.addEventListener("keydown", handleKeyDown) | ||||
| 		return () => document.removeEventListener("keydown", handleKeyDown) | ||||
| 	}, [isOpen, setIsOpen]) | ||||
|  | ||||
| 	function getFilteredIcons(iconList: CommandMenuProps["icons"], query: string) { | ||||
| 		if (!query) { | ||||
| 			// Return a limited number of icons when no query is provided | ||||
| 			return iconList.slice(0, 8) | ||||
| 		} | ||||
|  | ||||
| 		// Calculate scores for each icon | ||||
| 		const scoredIcons = iconList.map((icon) => { | ||||
| 			// Calculate scores for different fields | ||||
| 			const nameScore = fuzzySearch(icon.name, query) * 2.0 // Give more weight to name matches | ||||
|  | ||||
| 			// Get max score from aliases | ||||
| 			const aliasScore = | ||||
| 				icon.data.aliases && icon.data.aliases.length > 0 | ||||
| 					? Math.max(...icon.data.aliases.map((alias) => fuzzySearch(alias, query))) * 1.8 // Increased weight for aliases | ||||
| 					: 0 | ||||
|  | ||||
| 			// Get max score from categories | ||||
| 			const categoryScore = | ||||
| 				icon.data.categories && icon.data.categories.length > 0 | ||||
| 					? Math.max(...icon.data.categories.map((category) => fuzzySearch(category, query))) | ||||
| 					: 0 | ||||
|  | ||||
| 			// Use the highest score | ||||
| 			const score = Math.max(nameScore, aliasScore, categoryScore) | ||||
|  | ||||
| 			return { icon, score, matchedField: score === nameScore ? "name" : score === aliasScore ? "alias" : "category" } | ||||
| 		}) | ||||
|  | ||||
| 		// Filter icons with a minimum score and sort by highest score | ||||
| 		return scoredIcons | ||||
| 			.filter((item) => item.score > 0.3) // Higher threshold for more accurate results | ||||
| 			.sort((a, b) => b.score - a.score) | ||||
| 			.slice(0, 20) // Limit the number of results | ||||
| 			.map((item) => item.icon) | ||||
| 	} | ||||
|  | ||||
| 	const handleSelect = (name: string) => { | ||||
| 		setIsOpen(false) | ||||
| 		router.push(`/icons/${name}`) | ||||
| 	} | ||||
|  | ||||
| 	return ( | ||||
| 		<CommandDialog open={isOpen} onOpenChange={setIsOpen}> | ||||
| 			<CommandInput placeholder="Search icons by name, category, or alias..." value={query} onValueChange={setQuery} /> | ||||
| 			<CommandList className="max-h-[350px]"> | ||||
| 				<CommandEmpty> | ||||
| 					<div className="py-6 text-center"> | ||||
| 						<p className="text-sm text-muted-foreground">No matching icons found.</p> | ||||
| 						<p className="text-xs text-muted-foreground mt-1">Try a different search term or browse all icons.</p> | ||||
| 					</div> | ||||
| 				</CommandEmpty> | ||||
| 				<CommandGroup heading="Icons"> | ||||
| 					{filteredIcons.map(({ name, data }) => { | ||||
| 						// Find matched alias for display if available | ||||
| 						const matchedAlias = | ||||
| 							query && data.aliases && data.aliases.length > 0 | ||||
| 								? data.aliases.find((alias) => alias.toLowerCase().includes(query.toLowerCase())) | ||||
| 								: null | ||||
|  | ||||
| 						return ( | ||||
| 							<CommandItem key={name} value={name} onSelect={() => handleSelect(name)} className="flex items-center gap-3 cursor-pointer"> | ||||
| 								<div className="flex-shrink-0 h-8 w-8 relative"> | ||||
| 									<div className="h-8 w-8 bg-accent/40 dark:bg-accent/25 rounded-lg border border-border/60 flex items-center justify-center shadow-sm backdrop-blur-sm"> | ||||
| 										<span className="text-[10px] font-medium">{name.substring(0, 2).toUpperCase()}</span> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div className="flex flex-col gap-0.5"> | ||||
| 									<span className="capitalize text-sm font-medium">{name.replace(/-/g, " ")}</span> | ||||
| 									{matchedAlias && ( | ||||
| 										<span className="text-xs text-muted-foreground truncate max-w-[180px]"> | ||||
| 											Alias: {matchedAlias} | ||||
| 										</span> | ||||
| 									)} | ||||
| 									{!matchedAlias && data.categories && data.categories.length > 0 && ( | ||||
| 										<span className="text-xs text-muted-foreground truncate max-w-[180px]"> | ||||
| 											{data.categories[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())} | ||||
| 										</span> | ||||
| 									)} | ||||
| 								</div> | ||||
| 							</CommandItem> | ||||
| 						) | ||||
| 					})} | ||||
| 				</CommandGroup> | ||||
| 			</CommandList> | ||||
| 		</CommandDialog> | ||||
| 	) | ||||
| } | ||||
| @@ -3,42 +3,14 @@ | ||||
| import { IconSubmissionForm } from "@/components/icon-submission-form" | ||||
| import { ThemeSwitcher } from "@/components/theme-switcher" | ||||
| import { REPO_PATH } from "@/constants" | ||||
| import { getIconsArray } from "@/lib/api" | ||||
| import type { IconWithName } from "@/types/icons" | ||||
| import { motion } from "framer-motion" | ||||
| import { Github, Search } from "lucide-react" | ||||
| import { Github } from "lucide-react" | ||||
| import Link from "next/link" | ||||
| import { useEffect, useState } from "react" | ||||
| import { CommandMenu } from "./command-menu" | ||||
| import { HeaderNav } from "./header-nav" | ||||
| import { Button } from "./ui/button" | ||||
| import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip" | ||||
|  | ||||
| export function Header() { | ||||
| 	const [iconsData, setIconsData] = useState<IconWithName[]>([]) | ||||
| 	const [isLoaded, setIsLoaded] = useState(false) | ||||
| 	const [commandMenuOpen, setCommandMenuOpen] = useState(false) | ||||
|  | ||||
| 	useEffect(() => { | ||||
| 		async function loadIcons() { | ||||
| 			try { | ||||
| 				const icons = await getIconsArray() | ||||
| 				setIconsData(icons) | ||||
| 				setIsLoaded(true) | ||||
| 			} catch (error) { | ||||
| 				console.error("Failed to load icons:", error) | ||||
| 				setIsLoaded(true) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		loadIcons() | ||||
| 	}, []) | ||||
|  | ||||
| 	// Function to open the command menu | ||||
| 	const openCommandMenu = () => { | ||||
| 		setCommandMenuOpen(true) | ||||
| 	} | ||||
|  | ||||
| 	return ( | ||||
| 		<motion.header | ||||
| 			className="border-b sticky top-0 z-50 backdrop-blur-2xl bg-background/50 border-border/50" | ||||
| @@ -56,30 +28,6 @@ export function Header() { | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div className="flex items-center gap-2 md:gap-4"> | ||||
| 					{/* Desktop search button */} | ||||
| 					<div className="hidden md:block"> | ||||
| 						<Button variant="outline" className="gap-2 cursor-pointer   transition-all duration-300" onClick={openCommandMenu}> | ||||
| 							<Search className="h-4 w-4 transition-all duration-300" /> | ||||
| 							<span>Find icons</span> | ||||
| 							<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-border/80 bg-muted/80 px-1.5 font-mono text-[10px] font-medium opacity-100"> | ||||
| 								<span className="text-xs">⌘</span>K | ||||
| 							</kbd> | ||||
| 						</Button> | ||||
| 					</div> | ||||
|  | ||||
| 					{/* Mobile search button */} | ||||
| 					<div className="md:hidden"> | ||||
| 						<Button | ||||
| 							variant="ghost" | ||||
| 							size="icon" | ||||
| 							className="rounded-lg cursor-pointer transition-all duration-300 hover:ring-2 " | ||||
| 							onClick={openCommandMenu} | ||||
| 						> | ||||
| 							<Search className="h-5 w-5 transition-all duration-300" /> | ||||
| 							<span className="sr-only">Find icons</span> | ||||
| 						</Button> | ||||
| 					</div> | ||||
|  | ||||
| 					<div className="hidden md:flex items-center gap-2 md:gap-4"> | ||||
| 						<IconSubmissionForm /> | ||||
| 						<TooltipProvider> | ||||
| @@ -106,9 +54,6 @@ export function Header() { | ||||
| 					<ThemeSwitcher /> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | ||||
| 			{/* Single instance of CommandMenu */} | ||||
| 			{isLoaded && <CommandMenu icons={iconsData} open={commandMenuOpen} onOpenChange={setCommandMenuOpen} />} | ||||
| 		</motion.header> | ||||
| 	) | ||||
| } | ||||
|   | ||||
| @@ -526,7 +526,7 @@ function SearchInput({ searchQuery, setSearchQuery, totalIcons }: SearchInputPro | ||||
| 				name="q" | ||||
| 				autoFocus | ||||
| 				type="search" | ||||
| 				placeholder={`Search from ${totalIcons} icons...`} | ||||
| 				placeholder="Search for icons..." | ||||
| 				className="pl-10 h-10 md:h-12 rounded-lg w-full border-border focus:border-primary/20 text-sm md:text-base" | ||||
| 				value={searchQuery} | ||||
| 				onChange={(e) => setSearchQuery(e.target.value)} | ||||
|   | ||||
| @@ -73,7 +73,7 @@ export function IconSubmissionForm() { | ||||
| 		<Dialog open={open} onOpenChange={setOpen}> | ||||
| 			<DialogTrigger asChild> | ||||
| 				<Button variant="outline" className="hidden md:inline-flex cursor-pointer transition-all duration-300"> | ||||
| 					<PlusCircle className="h-4 w-4 transition-all duration-300" /> Submit icon | ||||
| 					<PlusCircle className="h-4 w-4 transition-all duration-300" /> Submit icon(s) | ||||
| 				</Button> | ||||
| 			</DialogTrigger> | ||||
| 			<DialogContent className="md:max-w-4xl backdrop-blur-2xl bg-background"> | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| import type { CSSProperties, ComponentPropsWithoutRef, FC } from "react" | ||||
|  | ||||
| import { cn } from "@/lib/utils" | ||||
|  | ||||
| export interface AnimatedShinyTextProps extends ComponentPropsWithoutRef<"span"> { | ||||
| 	shimmerWidth?: number | ||||
| } | ||||
|  | ||||
| export const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({ children, className, shimmerWidth = 100, ...props }) => { | ||||
| 	return ( | ||||
| 		<span | ||||
| 			style={ | ||||
| 				{ | ||||
| 					"--shiny-width": `${shimmerWidth}px`, | ||||
| 				} as CSSProperties | ||||
| 			} | ||||
| 			className={cn( | ||||
| 				"mx-auto max-w-md text-neutral-600/70 dark:text-neutral-400/70", | ||||
|  | ||||
| 				// Shine effect | ||||
| 				"animate-shiny-text bg-clip-text bg-no-repeat [background-position:0_0] [background-size:var(--shiny-width)_100%] [transition:background-position_1s_cubic-bezier(.6,.6,0,1)_infinite]", | ||||
|  | ||||
| 				// Shine gradient | ||||
| 				"bg-gradient-to-r from-transparent via-black/80 via-50% to-transparent  dark:via-white/80", | ||||
|  | ||||
| 				className, | ||||
| 			)} | ||||
| 			{...props} | ||||
| 		> | ||||
| 			{children} | ||||
| 		</span> | ||||
| 	) | ||||
| } | ||||
| @@ -1,181 +0,0 @@ | ||||
| "use client" | ||||
|  | ||||
| import * as React from "react" | ||||
| import { Command as CommandPrimitive } from "cmdk" | ||||
| import { SearchIcon } from "lucide-react" | ||||
|  | ||||
| import { cn } from "@/lib/utils" | ||||
| import { | ||||
|   Dialog, | ||||
|   DialogContent, | ||||
|   DialogDescription, | ||||
|   DialogHeader, | ||||
|   DialogTitle, | ||||
| } from "@/components/ui/dialog" | ||||
|  | ||||
| function Command({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive>) { | ||||
|   return ( | ||||
|     <CommandPrimitive | ||||
|       data-slot="command" | ||||
|       className={cn( | ||||
|         "bg-transparent text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandDialog({ | ||||
|   title = "Command Menu", | ||||
|   description = "Search for icons...", | ||||
|   children, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof Dialog> & { | ||||
|   title?: string | ||||
|   description?: string | ||||
| }) { | ||||
|   return ( | ||||
|     <Dialog {...props}> | ||||
|       <DialogHeader className="sr-only"> | ||||
|         <DialogTitle>{title}</DialogTitle> | ||||
|         <DialogDescription>{description}</DialogDescription> | ||||
|       </DialogHeader> | ||||
|       <DialogContent className="overflow-hidden p-0 border-border bg-background/80 backdrop-blur-xl shadow-lg sm:max-w-md rounded-xl transition-all duration-200 ease-in-out"> | ||||
|         <Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-3 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> | ||||
|           {children} | ||||
|         </Command> | ||||
|       </DialogContent> | ||||
|     </Dialog> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandInput({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.Input>) { | ||||
|   return ( | ||||
|     <div | ||||
|       data-slot="command-input-wrapper" | ||||
|       className="flex h-12 items-center gap-3 border-b border-border/60 px-4 bg-transparent" | ||||
|     > | ||||
|       <SearchIcon className="size-4 shrink-0 text-muted-foreground" /> | ||||
|       <CommandPrimitive.Input | ||||
|         data-slot="command-input" | ||||
|         className={cn( | ||||
|           "placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50", | ||||
|           className | ||||
|         )} | ||||
|         {...props} | ||||
|       /> | ||||
|     </div> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandList({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.List>) { | ||||
|   return ( | ||||
|     <CommandPrimitive.List | ||||
|       data-slot="command-list" | ||||
|       className={cn( | ||||
|         "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandEmpty({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.Empty>) { | ||||
|   return ( | ||||
|     <CommandPrimitive.Empty | ||||
|       data-slot="command-empty" | ||||
|       className={cn( | ||||
|         "py-6 text-center text-sm text-muted-foreground", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandGroup({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.Group>) { | ||||
|   return ( | ||||
|     <CommandPrimitive.Group | ||||
|       data-slot="command-group" | ||||
|       className={cn( | ||||
|         "text-foreground overflow-hidden p-1.5 px-2 [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandSeparator({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.Separator>) { | ||||
|   return ( | ||||
|     <CommandPrimitive.Separator | ||||
|       data-slot="command-separator" | ||||
|       className={cn("bg-border -mx-1 h-px", className)} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandItem({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<typeof CommandPrimitive.Item>) { | ||||
|   return ( | ||||
|     <CommandPrimitive.Item | ||||
|       data-slot="command-item" | ||||
|       className={cn( | ||||
|         "data-[selected=true]:bg-accent/70 data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 transition-colors duration-200", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| function CommandShortcut({ | ||||
|   className, | ||||
|   ...props | ||||
| }: React.ComponentProps<"span">) { | ||||
|   return ( | ||||
|     <span | ||||
|       data-slot="command-shortcut" | ||||
|       className={cn( | ||||
|         "text-muted-foreground ml-auto text-xs tracking-widest", | ||||
|         className | ||||
|       )} | ||||
|       {...props} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| export { | ||||
|   Command, | ||||
|   CommandDialog, | ||||
|   CommandInput, | ||||
|   CommandList, | ||||
|   CommandEmpty, | ||||
|   CommandGroup, | ||||
|   CommandItem, | ||||
|   CommandShortcut, | ||||
|   CommandSeparator, | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
| "use client" | ||||
|  | ||||
| import { useEffect, useState } from "react" | ||||
|  | ||||
| export function useMediaQuery(query: string): boolean { | ||||
| 	const [matches, setMatches] = useState(false) | ||||
|  | ||||
| 	useEffect(() => { | ||||
| 		const media = window.matchMedia(query) | ||||
|  | ||||
| 		// Initial check | ||||
| 		if (media.matches !== matches) { | ||||
| 			setMatches(media.matches) | ||||
| 		} | ||||
|  | ||||
| 		// Setup listener for changes | ||||
| 		const listener = () => setMatches(media.matches) | ||||
| 		media.addEventListener("change", listener) | ||||
|  | ||||
| 		// Cleanup | ||||
| 		return () => media.removeEventListener("change", listener) | ||||
| 	}, [query, matches]) | ||||
|  | ||||
| 	return matches | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Bjorn Lammers
					Bjorn Lammers