"use strict"; /* ───────────────────────────────────────────────────────────────────────── Veskslop icons — Phosphor geometry. Replaces the hand-drawn 16-unit set. Three things change: 1. Grid. Phosphor draws on 256 units; the old set drew on 16, so curves were quantised to half-pixels and the mic, gear and camera all had visibly different optical weights from each other. 2. Terminals. Round caps and joins throughout, as Phosphor regular. 3. Stroke. Held at a constant ~1.35 device pixels whatever the render size, instead of a fixed 1.3 unit stroke that thickened as icons grew. A 44px icon and a 13px icon now read as the same weight of line. The API is unchanged — VK.icon(name, size) and VK.iconEl(name, size) — and every previous name still resolves, so nothing needs editing to adopt this. New names are listed at the bottom. If you would rather ship the real Phosphor set, swap this file for @phosphor-icons/web and keep VK.icon as a thin wrapper; the names below are Phosphor's own, so the mapping is one to one. ───────────────────────────────────────────────────────────────────────── */ window.VK = window.VK ?? {}; const ICON_PATHS = { /* ── Channels and navigation ── */ hash: '', users: '', user: '', chat: '', activity: '', robot: '', /* ── Voice ── */ mic: '', micSlash: '', volume: '', speaker: '', speakerSlash: '', headphones: '', headphonesSlash: '', waveform: '', wave: '', /* ── Media ── */ monitor: '', screenshare: '', camera: '', image: '', film: '', audio: '', folder: '', play: '', pause: '', stop: '', /* ── Controls ── */ caretDown: '', caretUp: '', caretRight: '', caretLeft: '', x: '', check: '', plus: '', minus: '', dots: '', search: '', funnel: '', gear: '', sliders: '', refresh: '', download: '', copy: '', pencil: '', trash: '', pin: '', popout: '', lock: '', star: '', /* ── Status ── */ info: '', warning: '', error: '', ok: '', clock: '' }; /* Aliases — every name the app used before this file landed. */ ICON_PATHS.microphone = ICON_PATHS.mic; ICON_PATHS.deafen = ICON_PATHS.headphonesSlash; ICON_PATHS.listen = ICON_PATHS.headphones; ICON_PATHS.video = ICON_PATHS.camera; ICON_PATHS.close = ICON_PATHS.x; ICON_PATHS.settings = ICON_PATHS.gear; ICON_PATHS.tts = ICON_PATHS.wave; ICON_PATHS.magnify = ICON_PATHS.search; const FILLED = new Set(["star", "play", "dots"]); /* Solid marks keep a hairline of their own so they hold shape at 10-11px. */ const HAIRLINE = new Set(["dots"]); window.VK.icon = function icon(name, size = 13) { const path = ICON_PATHS[name]; if (!path) { if (name) console.warn("VK.icon: unknown icon", name); return ""; } const filled = FILLED.has(name); /* Constant optical weight: ~1.35 device px of stroke at any render size. */ const sw = Math.min(30, Math.max(12, +((1.35 / size) * 256).toFixed(1))); return ( `${path}` ); }; window.VK.iconEl = function iconEl(name, size = 13) { const span = document.createElement("span"); span.className = "vk-icon"; span.innerHTML = window.VK.icon(name, size); return span; }; /* Fills any empty [data-icon] span. Safe to call repeatedly — it skips anything already rendered, so it will not fight whatever app.js does. */ window.VK.hydrateIcons = function hydrateIcons(root = document) { root.querySelectorAll("[data-icon]").forEach((el) => { if (el.firstElementChild) return; const size = Number(el.dataset.iconSize) || 13; el.innerHTML = window.VK.icon(el.dataset.icon, size); }); }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => window.VK.hydrateIcons()); } else { window.VK.hydrateIcons(); }