import { Colors as Oklchs, Rgbs } from './color.js'; import * as Color from './color.js'; export class HistoryItem { name: string; oklch: Oklchs; rgb: Rgbs; constructor(name: string, oklch: Oklchs, rgb: Rgbs) { this.oklch = oklch; this.rgb = rgb; this.name = name; } asHtml(): HTMLButtonElement { const { lines, outer, belly1: belly, fins1: fins } = this.rgb; const content = ` fin colour: ${fins.css()} belly colour: ${belly.css()} outer body colour: ${outer.css()} sample of the palette for ${this.name}. fin colour: ${fins.css()}. belly colour: ${belly.css()}. outer body colour: ${outer.css()}. ${this.name} `; let button = document.createElement('button'); button.className = 'history-item'; button.dataset.name = this.name; button.innerHTML = content; return button; } } export class History { items: string[]; constructor(items: string[] = []) { this.items = items; } add(name: string): void { this.items.push(name); } *iterNames(maxLength: number = 100): Iterable { let seen = new Set; let done = 0; for (let i = this.items.length - 1; i >= 0; i--) { if (maxLength >= 0 && done > maxLength) break; const name = this.items[i]!; if (!name || seen.has(name)) continue; yield name; seen.add(name); done++; } } // pass a negative number to iterate over all *iterItems(maxLength?: number): Iterable { for (const name of this.iterNames(maxLength)) { const oklch = Color.colors(new Color.Rand(name), Color.KNOWN[name]); const rgbs = Color.toRgbs(oklch); yield new HistoryItem(name, oklch, rgbs); } } static validate(x: unknown): History | undefined { if (Array.isArray(x) && x.every(i => typeof i == 'string')) return new History(x); } toJSON(): unknown { return this.items; } save(persist = true): void { const storage = persist ? localStorage : sessionStorage; storage.setItem('history', JSON.stringify(this)); } // if no history exists, or it's invalid, just start a new one static load(): History { const json = sessionStorage.getItem('history') ?? localStorage.getItem('history'); if (json === null) return new History; return History.validate(JSON.parse(json)) ?? new History; } addSave(name: string, persist = true): void { this.add(name); this.save(persist); } prune(maxLength?: number): void { let keep = []; for (let name of this.iterNames(maxLength)) keep.push(name); this.items = keep.reverse(); } }