import { Colors } from './color.js'; import * as Color from './color.js'; export class HistoryItem { name: string; cols: Colors; constructor(name: string, cols: Colors) { this.cols = cols; this.name = name; } asHtml(): HTMLButtonElement { const { lines, outer, belly1: belly, fins1: fins } = this.cols; 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} `; const 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 { const 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 cols = Color.colors(new Color.Rand(name), Color.KNOWN[name]); yield new HistoryItem(name, cols); } } 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 { const keep = []; for (const name of this.iterNames(maxLength)) keep.push(name); this.items = keep.reverse(); } }