From ec55af55d94ba84bc24da7fdae793dc112db7f46 Mon Sep 17 00:00:00 2001 From: sHa Date: Thu, 12 Jun 2025 03:27:57 +0300 Subject: [PATCH] feat: Implement ColorSwitcher component and integrate it into logo cards for enhanced color selection --- ToDo.md | 2 +- src/components/CardFull.svelte | 120 +++---------------- src/components/CardMiddle.svelte | 106 ++++++----------- src/components/CardSmall.svelte | 106 +++++------------ src/components/CardTiny.svelte | 28 ++++- src/components/ColorSwitcher.svelte | 168 +++++++++++++++++++++++++++ src/components/ColorsVariants.svelte | 54 +++++++++ 7 files changed, 324 insertions(+), 260 deletions(-) create mode 100644 src/components/ColorSwitcher.svelte create mode 100644 src/components/ColorsVariants.svelte diff --git a/ToDo.md b/ToDo.md index 45359db..ac2c41a 100644 --- a/ToDo.md +++ b/ToDo.md @@ -1,4 +1,4 @@ -[ ] Improove: To the tiny card add the color chooser. It should be one circle that display current color, on click it should open color picker. +[v] Improove: To the tiny card add the color chooser. It should be one circle that display current color, on click it should open color picker. [ ] Improove: In the preview page, add full header. [ ] Improove: Split header into two parts: static top and dynamic bottom. [ ] Improove: In the preview page, add possibility select custom color for each target. diff --git a/src/components/CardFull.svelte b/src/components/CardFull.svelte index 6e4972f..25fe3de 100644 --- a/src/components/CardFull.svelte +++ b/src/components/CardFull.svelte @@ -2,8 +2,8 @@ import { onMount } from "svelte"; import InlineSvg from "./InlineSvg.svelte"; import Actions from "./Actions.svelte"; + import ColorSwitcher from "./ColorSwitcher.svelte"; import { getDefaultLogoColor, getThemeColor } from "../utils/colorTheme.js"; - import { generateColorSetCircle } from "../utils/colorCircles.js"; import { fetchSvgSource } from "../utils/svgSource.js"; export let show = false; @@ -27,7 +27,7 @@ // Watch for color changes and update SVG source function updateSvgSource() { - if (inlineSvgRef && typeof inlineSvgRef.getSvgSource === 'function') { + if (inlineSvgRef && typeof inlineSvgRef.getSvgSource === "function") { const newSource = inlineSvgRef.getSvgSource(); if (newSource) { svgSource = newSource; @@ -39,16 +39,16 @@ return logo && logo.format && logo.format.toLowerCase() === "svg"; } function copySvgSourceFromTextarea() { - if (inlineSvgRef && typeof inlineSvgRef.getSvgSource === 'function') { + if (inlineSvgRef && typeof inlineSvgRef.getSvgSource === "function") { // Get the updated SVG source with all color changes applied const updatedSource = inlineSvgRef.getSvgSource(); try { - const tempEl = document.createElement('textarea'); + const tempEl = document.createElement("textarea"); tempEl.value = updatedSource || svgSource; document.body.appendChild(tempEl); tempEl.select(); - document.execCommand('copy'); + document.execCommand("copy"); document.body.removeChild(tempEl); return true; } catch (err) { @@ -157,91 +157,12 @@
- {#if isSvgLogo(logo) && logo.colors} -
- { - logo._activeColor = undefined; - logo._activeSet = undefined; // Reset activeSet too - setTimeout(updateSvgSource, 100); // Update SVG source after color reset - }} - on:keydown|stopPropagation={(e) => { - if (e.key === "Enter" || e.key === " ") { - logo._activeColor = undefined; - logo._activeSet = undefined; - setTimeout(updateSvgSource, 100); - } - }} - > - - - {#if logo.sets} - {#each Object.entries(logo.sets) as [setName, setConfig], i} - { - logo._activeColor = Object.values(logo.colors)[ - i % Object.keys(logo.colors).length - ]; - logo._activeSet = setName; - setTimeout(updateSvgSource, 100); // Update SVG source after color change - }} - on:keydown|stopPropagation={(e) => { - if (e.key === "Enter" || e.key === " ") { - logo._activeColor = Object.values(logo.colors)[ - i % Object.keys(logo.colors).length - ]; - logo._activeSet = setName; - setTimeout(updateSvgSource, 100); // Update SVG source after color change - } - }} - style="padding: 0; overflow: hidden;" - > - {@html generateColorSetCircle(logo.colors, setConfig)} - - {/each} - {:else} - {#each Object.entries(logo.colors) as [colorName, colorValue]} - { - logo._activeColor = colorValue; - logo._activeSet = undefined; // Clear any active set when setting individual color - setTimeout(updateSvgSource, 100); // Update SVG source after color change - }} - on:keydown|stopPropagation={(e) => { - if (e.key === "Enter" || e.key === " ") { - logo._activeColor = colorValue; - logo._activeSet = undefined; // Clear any active set - setTimeout(updateSvgSource, 100); // Update SVG source after color change - } - }} - > - {/each} - {/if} -
+ {#if logo.colors} + { + logo._activeColor = color; + logo._activeSet = setName; + setTimeout(updateSvgSource, 100); + }} /> {/if} {#if logo.brand}

Brand: {logo.brand}

@@ -304,20 +225,6 @@ width: 100%; } - .set-circle { - background: var(--color-border); - color: var(--color-text); - font-size: 10px; - font-weight: bold; - display: flex; - align-items: center; - justify-content: center; - } - - :global(.dark-theme) .set-circle { - background: #444; - color: #eee; - } .preview-wrapper { position: relative; width: 100%; @@ -406,7 +313,6 @@ gap: 0.5rem; } - .preview-actions-container { margin-top: 2rem; border-top: 1px solid var(--color-border); @@ -417,7 +323,7 @@ overflow-y: auto; } - .preview-body { + .preview_body { flex-direction: column; align-items: stretch; overflow: visible; @@ -504,7 +410,6 @@ overflow-y: auto; } - .logo-details { margin-top: 1rem; color: var(--color-text); @@ -520,4 +425,5 @@ .logo-details span { color: var(--color-text); } + diff --git a/src/components/CardMiddle.svelte b/src/components/CardMiddle.svelte index cc2f6b4..4429398 100644 --- a/src/components/CardMiddle.svelte +++ b/src/components/CardMiddle.svelte @@ -1,8 +1,8 @@
{#if isSvgLogo(logo)} @@ -54,6 +57,12 @@ {logo.name} {/if}
+ {#if logo.colors} + { + logo._activeColor = color; + logo._activeSet = setName; + }} /> + {/if}
{logo.name}
@@ -66,10 +75,16 @@ border-radius: 8px; padding: 12px; cursor: pointer; - transition: background 0.2s, color 0.2s, transform 0.2s, box-shadow 0.2s; + transition: + background 0.2s, + color 0.2s, + transform 0.2s, + box-shadow 0.2s; display: flex; flex-direction: column; gap: 8px; + position: relative; /* Ensure absolute children are positioned correctly */ + overflow: visible; } .card-tiny:hover { @@ -88,6 +103,7 @@ align-items: center; justify-content: center; overflow: hidden; + position: relative; /* Needed for color chooser absolute positioning */ } .image-container img { diff --git a/src/components/ColorSwitcher.svelte b/src/components/ColorSwitcher.svelte new file mode 100644 index 0000000..d28c94e --- /dev/null +++ b/src/components/ColorSwitcher.svelte @@ -0,0 +1,168 @@ + + +{#if logo.colors} + {#if mode === 'compact'} +
+ (showDropdown = !showDropdown)} + on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && (showDropdown = !showDropdown)} + > + {@html logo._activeSet && logo.sets && logo.sets[logo._activeSet] + ? generateColorSetCircle(logo.colors, logo.sets[logo._activeSet], 24) + : getNoColorCircle()} + + {#if showDropdown} +
+
+ handleCircleClick(undefined, undefined, e)} + on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && handleCircleClick(undefined, undefined, e)} + > + {@html getNoColorCircle()} + + {#if logo.sets} + handleCircleClick(Object.values(logo.colors)[Object.keys(logo.sets).indexOf(setName) % Object.keys(logo.colors).length], setName)} /> + {/if} +
+
+ {/if} +
+ {:else} +
+ handleCircleClick(undefined, undefined, e)} + on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && handleCircleClick(undefined, undefined, e)} + > + {@html getNoColorCircle()} + + {#if logo.sets} + handleCircleClick(Object.values(logo.colors)[Object.keys(logo.sets).indexOf(setName) % Object.keys(logo.colors).length], setName)} /> + {/if} +
+ {/if} +{/if} + + diff --git a/src/components/ColorsVariants.svelte b/src/components/ColorsVariants.svelte new file mode 100644 index 0000000..cc14544 --- /dev/null +++ b/src/components/ColorsVariants.svelte @@ -0,0 +1,54 @@ + + +{#if sets && Object.keys(sets).length} +
+ {#each Object.entries(sets) as [setName, setConfig], i} + onSelect(setName)} + on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && onSelect(setName)} + style="padding: 0; overflow: hidden;" + > + {@html generateColorSetCircle(colors, sets[setName], 24)} + + {/each} +
+{/if} + +