mirror of
https://github.com/shadoll/sLogos.git
synced 2025-12-20 06:30:00 +00:00
feat: enhance SVG handling by updating color targets and adding SVG source retrieval; refactor Actions and InlineSvg components for improved functionality
This commit is contained in:
@@ -1544,30 +1544,33 @@
|
|||||||
"ua_yellow": "#FFDD00"
|
"ua_yellow": "#FFDD00"
|
||||||
},
|
},
|
||||||
"targets": {
|
"targets": {
|
||||||
"part_s1": "#s1",
|
"part_s": "#s",
|
||||||
"part_s2": "#s2",
|
"part_s_stroke": "#s&stroke",
|
||||||
"part_l": "#l"
|
"part_l": "#l",
|
||||||
|
"part_l_stroke": "#l&stroke"
|
||||||
},
|
},
|
||||||
"sets": {
|
"sets": {
|
||||||
"light": {
|
"light": {
|
||||||
"part_s1": "red",
|
"part_s": "red",
|
||||||
"part_s2": "red",
|
"part_l": "white",
|
||||||
"part_l": "white"
|
"part_l_stroke": "black",
|
||||||
|
"part_s_stroke": "black"
|
||||||
},
|
},
|
||||||
"dark": {
|
"dark": {
|
||||||
"part_s1": "red",
|
"part_s": "red",
|
||||||
"part_s2": "red",
|
"part_l": "black",
|
||||||
"part_l": "black"
|
"part_l_stroke": "white",
|
||||||
|
"part_s_stroke": "white"
|
||||||
},
|
},
|
||||||
"uk": {
|
"uk": {
|
||||||
"part_s1": "uk_red",
|
|
||||||
"part_s2": "uk_red",
|
"part_s2": "uk_red",
|
||||||
"part_l": "uk_blue"
|
"part_l": "uk_blue"
|
||||||
},
|
},
|
||||||
"ua": {
|
"ua": {
|
||||||
"part_s1": "ua_blue",
|
"part_s": "ua_blue",
|
||||||
"part_s2": "ua_blue",
|
"part_l": "ua_yellow",
|
||||||
"part_l": "ua_yellow"
|
"part_l_stroke": "none",
|
||||||
|
"part_s_stroke": "none"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1582,7 +1585,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Shkafnik Logo",
|
"name": "Shkafnik",
|
||||||
"path": "logos/shkafnik_logo.svg",
|
"path": "logos/shkafnik_logo.svg",
|
||||||
"format": "SVG",
|
"format": "SVG",
|
||||||
"disable": false,
|
"disable": false,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" height="510" width="510" viewBox="0 0 510 510">
|
<svg xmlns="http://www.w3.org/2000/svg" height="510" width="510" viewBox="0 0 510 510">
|
||||||
<path id="l" d="m286.7 401.2 61.9 60.2v-389.4l-62.4-60.6z" fill="currentColor" stroke="#eee" stroke-width="0"
|
<path id="l" d="m286.7 401.2 61.9 60.2v-389.4l-62.4-60.6z" fill="currentColor" stroke="none" stroke-width="2"
|
||||||
stroke-miterlimit="10" />
|
stroke-miterlimit="10" />
|
||||||
<g stroke="#eee" stroke-width="0" stroke-miterlimit="10">
|
<g id="s" fill="#dc2108" stroke="none" stroke-width="2" stroke-miterlimit="10">
|
||||||
<path id="s1" fill="#dc2108" d="m161.2 500 106.1-100.8-39-37.2-66.9 63.6z" />
|
<path d="m161.2 500 106.1-100.8-39-37.2-66.9 63.6z" />
|
||||||
<path id="s2" fill="#dc2108" d="m275 174.3-113.8 108.9 113.8 108.9v-73.6l-37-35.3 37-36.3z" />
|
<path d="m275 174.3-113.8 108.9 113.8 108.9v-73.6l-37-35.3 37-36.3z" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 461 B |
@@ -393,7 +393,7 @@
|
|||||||
top: 110%;
|
top: 110%;
|
||||||
right: auto;
|
right: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
min-width: 200px; /* Increased width from 160px */
|
min-width: 200px;
|
||||||
background: var(--color-card, #fff);
|
background: var(--color-card, #fff);
|
||||||
color: var(--color-text, #222);
|
color: var(--color-text, #222);
|
||||||
border: 1px solid var(--color-border, #ddd);
|
border: 1px solid var(--color-border, #ddd);
|
||||||
@@ -407,7 +407,6 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dropdown menus are positioned with JavaScript instead of CSS */
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
background: none;
|
background: none;
|
||||||
color: var(--color-text, #222);
|
color: var(--color-text, #222);
|
||||||
@@ -439,7 +438,7 @@
|
|||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
/* Notification styles moved to Notification.svelte */
|
|
||||||
.notification-overlay {
|
.notification-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
|||||||
@@ -23,12 +23,41 @@
|
|||||||
// For SVG source code display
|
// For SVG source code display
|
||||||
let svgSource = "";
|
let svgSource = "";
|
||||||
let isFetchingSvgSource = false;
|
let isFetchingSvgSource = false;
|
||||||
|
let inlineSvgRef; // Reference to the InlineSvg component
|
||||||
|
|
||||||
|
// Watch for color changes and update SVG source
|
||||||
|
function updateSvgSource() {
|
||||||
|
if (inlineSvgRef && typeof inlineSvgRef.getSvgSource === 'function') {
|
||||||
|
const newSource = inlineSvgRef.getSvgSource();
|
||||||
|
if (newSource) {
|
||||||
|
svgSource = newSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isSvgLogo(logo) {
|
function isSvgLogo(logo) {
|
||||||
return logo && logo.format && logo.format.toLowerCase() === "svg";
|
return logo && logo.format && logo.format.toLowerCase() === "svg";
|
||||||
}
|
}
|
||||||
function copySvgSourceFromTextarea() {
|
function copySvgSourceFromTextarea() {
|
||||||
if (svgSource) {
|
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');
|
||||||
|
tempEl.value = updatedSource || svgSource;
|
||||||
|
document.body.appendChild(tempEl);
|
||||||
|
tempEl.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(tempEl);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error copying SVG source:", err);
|
||||||
|
window.prompt("Copy the SVG source code:", updatedSource || svgSource);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (svgSource) {
|
||||||
|
// Fallback to the original source if component reference is not available
|
||||||
try {
|
try {
|
||||||
navigator.clipboard.writeText(svgSource);
|
navigator.clipboard.writeText(svgSource);
|
||||||
return true;
|
return true;
|
||||||
@@ -41,14 +70,18 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: getLogoThemeColor = (logo) => getDefaultLogoColor(logo.colors, theme);
|
// Update SVG source every time the component rerenders with new colors
|
||||||
|
$: if (logo && (logo._activeColor || (logo && logo._activeSet))) {
|
||||||
|
// Use a small delay to ensure the SVG has been rendered with the new colors
|
||||||
|
setTimeout(updateSvgSource, 100);
|
||||||
|
}
|
||||||
|
|
||||||
$: validColorConfig =
|
$: validColorConfig =
|
||||||
logo && typeof logo.colorConfig === "object" && logo.colorConfig.selector
|
logo && typeof logo.colorConfig === "object" && logo.colorConfig.selector
|
||||||
? logo.colorConfig
|
? logo.colorConfig
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
// Only fetch SVG source when displayed
|
$: getLogoThemeColor = (logo) => getDefaultLogoColor(logo.colors, theme);
|
||||||
$: if (show && logo) {
|
$: if (show && logo) {
|
||||||
if (logo.format === "SVG" && !svgSource) {
|
if (logo.format === "SVG" && !svgSource) {
|
||||||
isFetchingSvgSource = true;
|
isFetchingSvgSource = true;
|
||||||
@@ -106,6 +139,7 @@
|
|||||||
<div class="preview-container" use:removeSvgSize>
|
<div class="preview-container" use:removeSvgSize>
|
||||||
{#if isSvgLogo(logo)}
|
{#if isSvgLogo(logo)}
|
||||||
<InlineSvg
|
<InlineSvg
|
||||||
|
bind:this={inlineSvgRef}
|
||||||
path={logo.path}
|
path={logo.path}
|
||||||
color={logo.colors
|
color={logo.colors
|
||||||
? logo._activeColor || getLogoThemeColor(logo)
|
? logo._activeColor || getLogoThemeColor(logo)
|
||||||
@@ -132,10 +166,18 @@
|
|||||||
role="button"
|
role="button"
|
||||||
aria-label="Reset to theme color"
|
aria-label="Reset to theme color"
|
||||||
style="background: none; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; padding: 0; margin: 0; border: none;"
|
style="background: none; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; padding: 0; margin: 0; border: none;"
|
||||||
on:click|stopPropagation={() => (logo._activeColor = undefined)}
|
on:click|stopPropagation={() => {
|
||||||
on:keydown|stopPropagation={(e) =>
|
logo._activeColor = undefined;
|
||||||
(e.key === "Enter" || e.key === " ") &&
|
logo._activeSet = undefined; // Reset activeSet too
|
||||||
(logo._activeColor = undefined)}
|
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);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
width="100%"
|
width="100%"
|
||||||
@@ -160,6 +202,7 @@
|
|||||||
i % Object.keys(logo.colors).length
|
i % Object.keys(logo.colors).length
|
||||||
];
|
];
|
||||||
logo._activeSet = setName;
|
logo._activeSet = setName;
|
||||||
|
setTimeout(updateSvgSource, 100); // Update SVG source after color change
|
||||||
}}
|
}}
|
||||||
on:keydown|stopPropagation={(e) => {
|
on:keydown|stopPropagation={(e) => {
|
||||||
if (e.key === "Enter" || e.key === " ") {
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
@@ -167,6 +210,7 @@
|
|||||||
i % Object.keys(logo.colors).length
|
i % Object.keys(logo.colors).length
|
||||||
];
|
];
|
||||||
logo._activeSet = setName;
|
logo._activeSet = setName;
|
||||||
|
setTimeout(updateSvgSource, 100); // Update SVG source after color change
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style="padding: 0; overflow: hidden;"
|
style="padding: 0; overflow: hidden;"
|
||||||
@@ -182,11 +226,18 @@
|
|||||||
style={`background:${colorValue}`}
|
style={`background:${colorValue}`}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="button"
|
role="button"
|
||||||
on:click|stopPropagation={() =>
|
on:click|stopPropagation={() => {
|
||||||
(logo._activeColor = colorValue)}
|
logo._activeColor = colorValue;
|
||||||
on:keydown|stopPropagation={(e) =>
|
logo._activeSet = undefined; // Clear any active set when setting individual color
|
||||||
(e.key === "Enter" || e.key === " ") &&
|
setTimeout(updateSvgSource, 100); // Update SVG source after color change
|
||||||
(logo._activeColor = colorValue)}
|
}}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}}
|
||||||
></span>
|
></span>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
export let colors = null;
|
export let colors = null;
|
||||||
export let alt = "";
|
export let alt = "";
|
||||||
let svgHtml = "";
|
let svgHtml = "";
|
||||||
|
let svgSource = ""; // Store the updated SVG source code
|
||||||
|
|
||||||
async function fetchAndColorSvg() {
|
async function fetchAndColorSvg() {
|
||||||
const res = await fetch(path);
|
const res = await fetch(path);
|
||||||
@@ -58,37 +59,69 @@
|
|||||||
// Remove all <style> elements
|
// Remove all <style> elements
|
||||||
styleEls.forEach((styleEl) => styleEl.remove());
|
styleEls.forEach((styleEl) => styleEl.remove());
|
||||||
// Handle the new format with targets and sets if available
|
// Handle the new format with targets and sets if available
|
||||||
if (targets && sets && activeSet && sets[activeSet]) {
|
if (targets && sets && activeSet && typeof activeSet === 'string' && sets[activeSet]) {
|
||||||
// Get the color assignments from the active set
|
try {
|
||||||
const colorAssignments = sets[activeSet];
|
// Get the color assignments from the active set
|
||||||
|
const colorAssignments = sets[activeSet];
|
||||||
|
|
||||||
// Apply each target-color pair
|
// Apply each target-color pair
|
||||||
for (const [targetName, colorName] of Object.entries(colorAssignments)) {
|
for (const [targetName, colorName] of Object.entries(colorAssignments)) {
|
||||||
if (targets[targetName] && colors && colors[colorName]) {
|
if (targets[targetName] && colors && colors[colorName]) {
|
||||||
// Get the selector for this target
|
// Get the selector and determine if it's for fill or stroke
|
||||||
const selector = targets[targetName];
|
const targetInfo = targets[targetName];
|
||||||
const targetElements = doc.querySelectorAll(selector);
|
|
||||||
// Get the actual color value for this target
|
|
||||||
const targetColor = colors[colorName];
|
|
||||||
|
|
||||||
// Apply the color to all elements matching this selector
|
// Parse the selector to extract the target and attribute (fill/stroke)
|
||||||
targetElements.forEach(el => {
|
let selector, attribute;
|
||||||
// Always override fill and stroke unless they are 'none'
|
|
||||||
if (el.hasAttribute("fill") && el.getAttribute("fill") !== "none") {
|
if (typeof targetInfo === 'string') {
|
||||||
el.setAttribute("fill", targetColor);
|
if (targetInfo.includes('&stroke')) {
|
||||||
|
// Format: "#element&stroke" - target stroke attribute
|
||||||
|
selector = targetInfo.split('&stroke')[0];
|
||||||
|
attribute = 'stroke';
|
||||||
|
} else if (targetInfo.includes('&fill')) {
|
||||||
|
// Format: "#element&fill" - target fill attribute
|
||||||
|
selector = targetInfo.split('&fill')[0];
|
||||||
|
attribute = 'fill';
|
||||||
|
} else {
|
||||||
|
// Default is fill if not specified
|
||||||
|
selector = targetInfo;
|
||||||
|
attribute = 'fill';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback for older format
|
||||||
|
selector = targetInfo;
|
||||||
|
attribute = 'fill';
|
||||||
}
|
}
|
||||||
if (el.hasAttribute("stroke") && el.getAttribute("stroke") !== "none") {
|
|
||||||
el.setAttribute("stroke", targetColor);
|
// Proceed with selecting elements and applying colors
|
||||||
}
|
const targetElements = doc.querySelectorAll(selector);
|
||||||
if (!el.hasAttribute("fill") && !el.hasAttribute("stroke")) {
|
const targetColor = colors[colorName];
|
||||||
// If neither, prefer fill
|
|
||||||
el.setAttribute("fill", targetColor);
|
// Apply the color to all elements matching this selector
|
||||||
}
|
targetElements.forEach(el => {
|
||||||
});
|
if (colorName === "none") {
|
||||||
|
// Special case for 'none' value
|
||||||
|
el.setAttribute(attribute, "none");
|
||||||
|
} else if (attribute === 'fill') {
|
||||||
|
el.setAttribute("fill", targetColor);
|
||||||
|
} else if (attribute === 'stroke') {
|
||||||
|
el.setAttribute("stroke", targetColor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error applying color set:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svgHtml = doc.documentElement.outerHTML;
|
svgHtml = doc.documentElement.outerHTML;
|
||||||
|
// Update the svgSource property to store the modified SVG code
|
||||||
|
svgSource = doc.documentElement.outerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the svgSource so it can be accessed from outside
|
||||||
|
export function getSvgSource() {
|
||||||
|
return svgSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: path, color, colorConfig, targets, sets, activeSet, colors, fetchAndColorSvg();
|
$: path, color, colorConfig, targets, sets, activeSet, colors, fetchAndColorSvg();
|
||||||
|
|||||||
Reference in New Issue
Block a user