fix: polish workspace files and editor shell
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
/**
|
||||
* Icon.svelte — Renders inline SVG icons.
|
||||
* Icon.svelte — Renders bundled Lucide SVG icons.
|
||||
*
|
||||
* Usage:
|
||||
* <Icon name="puzzle" size={18} />
|
||||
@@ -8,26 +8,60 @@
|
||||
*
|
||||
* Rules:
|
||||
* - NO emoji, NO unicode pictographic symbols
|
||||
* - ALL icons must be SVG registered in ../ui/icons.js
|
||||
* - If name is not found, renders a default dot icon
|
||||
* - NO dependency on system icon fonts
|
||||
* - If name is not found, renders a default circle icon
|
||||
*/
|
||||
import { iconPaths } from './icons.js';
|
||||
import Briefcase from 'lucide-svelte/icons/briefcase';
|
||||
import ChevronDown from 'lucide-svelte/icons/chevron-down';
|
||||
import ChevronRight from 'lucide-svelte/icons/chevron-right';
|
||||
import Circle from 'lucide-svelte/icons/circle';
|
||||
import FlaskConical from 'lucide-svelte/icons/flask-conical';
|
||||
import Folder from 'lucide-svelte/icons/folder';
|
||||
import LayoutGrid from 'lucide-svelte/icons/layout-grid';
|
||||
import PanelsTopLeft from 'lucide-svelte/icons/panels-top-left';
|
||||
import Pencil from 'lucide-svelte/icons/pencil';
|
||||
import Plug from 'lucide-svelte/icons/plug';
|
||||
import Puzzle from 'lucide-svelte/icons/puzzle';
|
||||
import Settings from 'lucide-svelte/icons/settings';
|
||||
import Shield from 'lucide-svelte/icons/shield';
|
||||
import TriangleAlert from 'lucide-svelte/icons/triangle-alert';
|
||||
|
||||
export let name = 'dot';
|
||||
export let size = 16;
|
||||
export let className = '';
|
||||
|
||||
$: icon = iconPaths[name] || iconPaths.dot;
|
||||
const icons = {
|
||||
case: Briefcase,
|
||||
chevronDown: ChevronDown,
|
||||
chevronRight: ChevronRight,
|
||||
dot: Circle,
|
||||
edit: Pencil,
|
||||
flask: FlaskConical,
|
||||
folder: Folder,
|
||||
gear: Settings,
|
||||
logo: PanelsTopLeft,
|
||||
plugin: Plug,
|
||||
puzzle: Puzzle,
|
||||
space: LayoutGrid,
|
||||
vault: Shield,
|
||||
warning: TriangleAlert,
|
||||
};
|
||||
|
||||
const aliases = {
|
||||
'🧪': 'flask',
|
||||
danger: 'warning',
|
||||
settings: 'gear',
|
||||
};
|
||||
|
||||
$: iconKey = aliases[name] || name || 'dot';
|
||||
$: IconComponent = icons[iconKey] || icons.dot;
|
||||
$: iconClass = [className, $$restProps.class].filter(Boolean).join(' ');
|
||||
</script>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox={icon.viewBox}
|
||||
width={size}
|
||||
height={size}
|
||||
class={className}
|
||||
>
|
||||
{#each icon.paths as p}
|
||||
<path d={p.d} {...p.attrs} />
|
||||
{/each}
|
||||
</svg>
|
||||
<svelte:component
|
||||
this={IconComponent}
|
||||
size={size}
|
||||
{...$$restProps}
|
||||
class={iconClass}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/**
|
||||
* icons.js — Centralised SVG icon set for Verstak.
|
||||
*
|
||||
* RULE: Icons MUST be SVG only. No emoji, no unicode symbols, no font-icons.
|
||||
* The Wails WebKitGTK webview does NOT render colour emoji.
|
||||
*
|
||||
* Each icon is an object: { viewBox, paths }
|
||||
* - viewBox: string, default '0 0 24 24'
|
||||
* - paths: array of <path> attributes or objects with { d, ...attrs }
|
||||
*
|
||||
* Usage in Svelte:
|
||||
* import { iconPaths } from '../lib/ui/icons.js';
|
||||
* <svg viewBox={iconPaths.puzzle.viewBox} width="16" height="16">
|
||||
* {#each iconPaths.puzzle.paths as p}
|
||||
* <path d={p.d} {...p.attrs} />
|
||||
* {/each}
|
||||
* </svg>
|
||||
*/
|
||||
|
||||
export const iconPaths = {
|
||||
/** Plugin Manager — puzzle piece */
|
||||
puzzle: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M4 5a3 3 0 0 1 3-3h4v2a2 2 0 0 0 4 0V2h4a2 2 0 0 1 2 2v4h-2a2 2 0 0 0 0 4h2v4a2 2 0 0 1-2 2h-4v-2a2 2 0 0 0-4 0v2H7a3 3 0 0 1-3-3v-3h2a2 2 0 0 0 0-4H4V5Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Platform Test / Diagnostics — flask/test-tube */
|
||||
flask: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M9 2v5.586l-5.293 5.293A1 1 0 0 0 4 14v4a4 4 0 0 0 4 4h8a4 4 0 0 0 4-4v-4a1 1 0 0 0-.293-.707L15 7.586V2H9Zm2 0v6a1 1 0 0 0 .293.707l5 5V14a1 1 0 0 1-1 1h-1l-2-2-2 2H8a1 1 0 0 1-1-1v-.293l3-3V2h3Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Verstak logo — stack/tray */
|
||||
logo: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M5 3h14a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Zm0 2v3h14V5H5Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
{ d: 'M5 12h14a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2Zm0 2v3h14v-3H5Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Default fallback — circle */
|
||||
dot: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2Zm0 6a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Vault — safe / shield */
|
||||
vault: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4Zm0 2.18L19 6.4v4.6c0 4.5-3.07 8.68-7 9.82-3.93-1.14-7-5.32-7-9.82V6.4l7-3.22ZM11 8v2H9v2h2v4h2v-4h2v-2h-2V8h-2Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Settings — gear */
|
||||
gear: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M19.14 13l.57-1.43 1.79-.5-1-2.29-1.64.73-.29-.28-.73-1.64 2.29-1-1-2.29-1.79.5-.57 1.43-2.17.17-.57-1.43-1.79-.5-1 2.29 1.64.73-.29.28-.73 1.64-2.29-1-1 2.29 1.79.5.57 1.43-.57 1.43-1.79.5 1 2.29 1.64-.73.29.28.73 1.64-2.29 1 1 2.29 1.79-.5.57-1.43 2.17-.17.57 1.43 1.79.5 1-2.29-1.64-.73.29-.28.73-1.64 2.29 1 1-2.29-1.79-.5-.57-1.43ZM12 9a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** Warning / error — triangle */
|
||||
warning: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M1 21h22L12 2 1 21Zm12-3h-2v-2h2v2Zm0-4h-2v-4h2v4Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/** General plugin — extension/puzzle alternative */
|
||||
plugin: {
|
||||
viewBox: '0 0 24 24',
|
||||
paths: [
|
||||
{ d: 'M11 2H5v6.172a3 3 0 0 0 0 5.656V20a1 1 0 0 0 1 1h4v-2H7v-4a1 1 0 0 0-1-1H5v-2h1a1 1 0 0 0 1-1V8h2V4h2a1 1 0 0 0 1-1V2h-1Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
{ d: 'M17 2a3 3 0 0 1 3 3v1h-4V5a1 1 0 0 0-1-1h-2v2h2v2h-2v2h4V8h2v2a3 3 0 0 1-3 3h-1v2h1a2 2 0 0 1 2 2v2h2v2a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2h2v-2h-2v-2h4a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-2v2h-2V4a2 2 0 0 1 2-2h3Z',
|
||||
attrs: { fill: 'currentColor', stroke: 'none' },
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Render an SVG icon string inline.
|
||||
* Returns an SVG string suitable for {@html } or innerHTML.
|
||||
* @param {string} name - icon key
|
||||
* @param {number|string} size - width/height
|
||||
* @param {string} className - optional CSS class
|
||||
*/
|
||||
export function svgIcon(name, size = 16, className = '') {
|
||||
const icon = iconPaths[name];
|
||||
if (!icon) return svgIcon('dot', size, className);
|
||||
const paths = icon.paths
|
||||
.map(p => {
|
||||
const attrs = p.attrs
|
||||
? Object.entries(p.attrs).map(([k, v]) => `${k}="${v}"`).join(' ')
|
||||
: '';
|
||||
return `<path d="${p.d}"${attrs ? ' ' + attrs : ''}/>`;
|
||||
})
|
||||
.join('');
|
||||
const cls = className ? ` class="${className}"` : '';
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${icon.viewBox}" width="${size}" height="${size}"${cls}>${paths}</svg>`;
|
||||
}
|
||||
Reference in New Issue
Block a user