/** * Inline SVG icon library for the plank training app. * * Each icon is a 24x24 Material-style path. We bake the color directly into * the SVG data URI, so consumers can switch between "active" and "inactive" * variants by simply selecting a different key — no font loading, no CSS * pseudo-element tricks, and exact pixel rendering at any size. * * Usage: * const icons = require('../../utils/icons') * const map = icons.build({ primary: '#FF6B35', primaryLight: '#FF8C5A', success: '#4CAF50' }) * // map.playFill => "data:image/svg+xml;..." (orange play) * // map.play => "data:image/svg+xml;..." (gray play) * * Naming convention: * = outlined / inactive (neutral gray) * Fill = filled / active (theme color) */ const PATHS = { // Navigation & UI home: '', homeFill: '', calendar: '', calendarFill: '', settings: '', settingsFill: '', back: '', right: '', close: '', check: '', // Status & feedback hot: '', hotFill: '', like: '', likeFill: '', // Training specific play: '', playFill: '', stop: '', stopFill: '', pause: '', pauseFill: '', time: '', timeFill: '', // Markers & targets target: '', targetFill: '', mark: '', markFill: '', // Stats & charts rank: '', rankFill: '', crown: '', crownFill: '', form: '', formFill: '', // Notification notification: '', notificationFill: '', notificationForbid: '', notificationForbidFill: '', // People & users people: '', peopleFill: '', // Actions delete: '', deleteFill: '', info: '', infoFill: '', // Theme & preferences skin: '', skinFill: '', // Lightbulb & tip light: '', lightFill: '', // Voice voice: '', voiceFill: '', // Round check roundCheck: '', roundCheckFill: '', // Emoji / face emoji: '', emojiFill: '', // Edit (pencil) edit: '', editFill: '' } // NOTE: must encodeURIComponent the SVG so that the `#` in colors like // `#FF6B35` doesn't get parsed as a fragment-identifier delimiter — that // would silently truncate the SVG and the image would fail to render. const _svg = (path, color) => { const svg = '' + path + '' return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg) } const INACTIVE = '#999999' const DANGER = '#E53935' /** * Build an icon map keyed by name. Two variants per name: * = inactive (gray) * Fill = active (theme primary) * Plus semantic aliases (delete, etc.) with appropriate colors. * * @param {object} theme - { primary, primaryLight, success, danger } * @returns {object} { : dataUri, ... } */ const build = (theme) => { const t = theme || {} const p = t.primary || '#FF6B35' const s = t.success || '#4CAF50' const d = t.danger || DANGER const out = {} Object.keys(PATHS).forEach((name) => { if (name.endsWith('Fill')) { // Fill variant: filled path + primary color. // Do NOT write out[base] here — that would overwrite the outlined // variant set by the base-name entry below with the wrong path. out[name] = _svg(PATHS[name], p) } else { // Outlined variant: outlined path + inactive gray. out[name] = _svg(PATHS[name], INACTIVE) } }) // Semantic overrides out.deleteActive = _svg(PATHS.deleteFill, d) out.deleteInactive = _svg(PATHS.delete, INACTIVE) out.successFill = _svg(PATHS.roundCheckFill, s) out.successLine = _svg(PATHS.roundCheck, INACTIVE) return out } module.exports = { build, PATHS, INACTIVE }