|
| 1 | +<!-- Icon Gallery for Development --> |
| 2 | +<script lang="ts"> |
| 3 | + import { dev } from '$app/environment'; |
| 4 | + import { goto } from '$app/navigation'; |
| 5 | + import { onMount } from 'svelte'; |
| 6 | +
|
| 7 | + // Redirect to home if not in development mode |
| 8 | + if (!dev) { |
| 9 | + goto('/'); |
| 10 | + } |
| 11 | +
|
| 12 | + // Automatically import all icon components using Vite's import.meta.glob |
| 13 | + const iconModules = import.meta.glob('$lib/icons/**/*.svelte', { eager: true }); |
| 14 | +
|
| 15 | + let icons: Array<{ name: string; path: string; component: any }> = []; |
| 16 | + let groupedIcons: { [folder: string]: Array<{ name: string; path: string; component: any }> } = |
| 17 | + {}; |
| 18 | +
|
| 19 | + onMount(() => { |
| 20 | + // Process the imported modules |
| 21 | + icons = Object.entries(iconModules) |
| 22 | + .map(([path, module]) => { |
| 23 | + // Extract the icon name from the file path |
| 24 | + const pathParts = path.split('/'); |
| 25 | + const fileName = pathParts[pathParts.length - 1]; |
| 26 | + const name = fileName.replace('.svelte', ''); |
| 27 | +
|
| 28 | + // Get relative path for display (remove the $lib/icons/ part) |
| 29 | + const relativePath = path.replace(/.*\/icons\//, ''); |
| 30 | +
|
| 31 | + return { |
| 32 | + name, |
| 33 | + path: relativePath, |
| 34 | + component: (module as any).default |
| 35 | + }; |
| 36 | + }) |
| 37 | + .sort((a, b) => a.name.localeCompare(b.name)); |
| 38 | +
|
| 39 | + // Group icons by folder |
| 40 | + groupedIcons = {}; |
| 41 | + icons.forEach((icon) => { |
| 42 | + const folder = icon.path.includes('/') ? icon.path.split('/')[0] : 'Root Icons'; |
| 43 | + if (!groupedIcons[folder]) { |
| 44 | + groupedIcons[folder] = []; |
| 45 | + } |
| 46 | + groupedIcons[folder].push(icon); |
| 47 | + }); |
| 48 | + }); |
| 49 | +
|
| 50 | + let selectedSize = '24'; |
| 51 | + let selectedColor = '#000000'; |
| 52 | + const sizes = ['16', '20', '24', '32', '48', '64']; |
| 53 | + const colors = ['#000000', '#ffffff', '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6']; |
| 54 | +</script> |
| 55 | + |
| 56 | +<svelte:head> |
| 57 | + <title>Icon Gallery - Development</title> |
| 58 | +</svelte:head> |
| 59 | + |
| 60 | +{#if dev} |
| 61 | + <div class="p-6 max-w-screen-lg mx-auto"> |
| 62 | + <h1 class="text-3xl font-bold mb-6">SVG Icon Gallery</h1> |
| 63 | + |
| 64 | + <div class="mb-6 flex gap-4 items-center flex-wrap"> |
| 65 | + <div class="flex items-center gap-2"> |
| 66 | + <label for="size-select" class="font-medium">Size:</label> |
| 67 | + <select id="size-select" bind:value={selectedSize} class="border rounded px-2 py-1"> |
| 68 | + {#each sizes as size} |
| 69 | + <option value={size}>{size}px</option> |
| 70 | + {/each} |
| 71 | + </select> |
| 72 | + </div> |
| 73 | + |
| 74 | + <div class="flex items-center gap-2"> |
| 75 | + <label for="color-input" class="font-medium">Color:</label> |
| 76 | + <input |
| 77 | + id="color-input" |
| 78 | + type="color" |
| 79 | + bind:value={selectedColor} |
| 80 | + class="w-8 h-8 border rounded cursor-pointer" |
| 81 | + /> |
| 82 | + <span class="text-sm text-gray-600">{selectedColor}</span> |
| 83 | + </div> |
| 84 | + </div> |
| 85 | + |
| 86 | + {#each Object.entries(groupedIcons) as [folder, folderIcons]} |
| 87 | + <div class="mb-8"> |
| 88 | + <h2 class="text-xl font-semibold mb-4 pb-2 border-b border-gray-300"> |
| 89 | + {folder} |
| 90 | + <span class="text-sm text-gray-500 font-normal ml-2" |
| 91 | + >({folderIcons.length} icons)</span |
| 92 | + > |
| 93 | + </h2> |
| 94 | + |
| 95 | + <div class="grid grid-cols-2 md:grid-cols-4 gap-6"> |
| 96 | + {#each folderIcons as icon} |
| 97 | + <div |
| 98 | + class="flex flex-col items-center p-4 border rounded-lg hover:bg-gray-50 transition-colors min-w-[250]" |
| 99 | + > |
| 100 | + <div |
| 101 | + class="flex items-center justify-center w-16 h-16 mb-2 bg-white border rounded" |
| 102 | + > |
| 103 | + <svelte:component |
| 104 | + this={icon.component} |
| 105 | + size={selectedSize} |
| 106 | + color={selectedColor} |
| 107 | + /> |
| 108 | + </div> |
| 109 | + <span class="text-sm text-center font-mono break-all">{icon.name}</span> |
| 110 | + <span class="text-xs text-gray-500 text-center mt-1">{icon.path}</span> |
| 111 | + </div> |
| 112 | + {/each} |
| 113 | + </div> |
| 114 | + </div> |
| 115 | + {/each} |
| 116 | + |
| 117 | + <div class="mt-8 p-4 bg-gray-100 rounded-lg"> |
| 118 | + <h3 class="font-bold mb-2">Usage Example:</h3> |
| 119 | + <pre class="text-sm bg-white p-2 rounded border"><code |
| 120 | + ><PlayIcon size="{selectedSize}" color="{selectedColor}" /></code |
| 121 | + ></pre> |
| 122 | + <div class="mt-2 text-sm text-gray-600"> |
| 123 | + <strong>Total Icons:</strong> |
| 124 | + {icons.length} |
| 125 | + </div> |
| 126 | + </div> |
| 127 | + </div> |
| 128 | +{:else} |
| 129 | + <div class="flex items-center justify-center min-h-screen"> |
| 130 | + <div class="text-center"> |
| 131 | + <h1 class="text-2xl font-bold text-gray-600">Development Tool</h1> |
| 132 | + <p class="text-gray-500 mt-2">This page is only available in development mode.</p> |
| 133 | + </div> |
| 134 | + </div> |
| 135 | +{/if} |
| 136 | + |
| 137 | +<style> |
| 138 | + :global(body) { |
| 139 | + background-color: #f9fafb; |
| 140 | + } |
| 141 | +</style> |
0 commit comments