UNPKG

@protorians/widgets

Version:

Create your web user interfaces with widgets

194 lines (193 loc) 7.4 kB
import { ColorSchemeType } from "../enums.js"; import { Style, StyleWidget } from "../style.js"; import { Colorimetric, } from "@protorians/colorimetric"; import { WidgetException } from "../errors/index.js"; const schemes = { light: {}, dark: {}, }; export class ColorScheme { static generates(type, declarations) { Object.keys(declarations) .forEach(key => { schemes[type] = { ...schemes[type], ...Colorimetric.generates(key, declarations[key]) }; }); return schemes[type]; } static detect() { return (window.matchMedia) ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? ColorSchemeType.Dark : ColorSchemeType.Light) : undefined; } static get scheme() { return window.matchMedia('(prefers-color-scheme: dark)').matches ? ColorSchemeType.Dark : ColorSchemeType.Light; } static use(callable) { if ('matchMedia' in window) { const fn = (e) => callable(typeof e === 'undefined' ? this.current : (e.matches ? ColorSchemeType.Dark : ColorSchemeType.Light)); const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); mediaQuery.addEventListener('change', fn); fn(); } else throw (new WidgetException(`matchMedia not supported in ColorPalette:Scheme `)).show(); return this; } static get current() { const noUse = document.documentElement.hasAttribute('theme:no-scheme'); if (!noUse) return (document.documentElement.getAttribute('theme:scheme') || this.detect()); return this.detect(); } static set current(scheme) { scheme = scheme || this.detect(); const noUse = document.documentElement.hasAttribute('theme:no-scheme'); if (!noUse) { document.documentElement.setAttribute('theme:scheme', `${scheme}`); } } static switch(scheme, target) { scheme = scheme || this.detect(); const noUse = (target || document.documentElement).hasAttribute('theme:no-scheme'); if (!noUse) { (target || document.documentElement).setAttribute('theme:scheme', `${scheme}`); } } } export class ColorPalette { static _stylesheet; static _algo; static declarations = {}; static light = { text: 'oklch(12.75% 0.0375 251.46)', tint: 'oklch(95.21% 0 0)', ascent: 'oklch(56% 0.1933 256.16)', ascentfore: 'oklch(95.29% 0.1933 256.16)', one: 'oklch(56.29% 0.1933 256.16)', onefore: 'oklch(96.29% 0.1933 256.16)', two: 'oklch(67.51% 0.1493 246.05)', twofore: 'oklch(1.51% 0.1493 246.05)', three: 'oklch(48.7% 0.1959 328.46)', threefore: 'oklch(90.7% 0.1959 328.46)', four: 'oklch(43.74% 0.1762 297.9)', fourfore: 'oklch(90.74% 0.1762 297.9)', five: 'oklch(37.37% 0.1806 267.58)', fivefore: 'oklch(90% 0.1806 267.58)', error: 'oklch(48.42% 0.1891 28.19)', errorfore: 'oklch(90.42% 0.1891 28.19)', warning: 'oklch(80.81% 0.1613 103.51)', warningfore: 'oklch(10.81% 0.1613 103.51)', success: 'oklch(55.04% 0.1827 142.37)', successfore: 'oklch(90% 0.1827 142.37)', white: 'oklch(100% 0 0)', whitefore: 'oklch(10% 0 0)', black: 'oklch(0% 0 0)', blackfore: 'oklch(90% 0 0)', }; static dark = { text: 'oklch(87.25% 0.0375 251.46)', tint: 'oklch(4.79% 0 0)', one: 'oklch(43.71% 0.1933 256.16)', onefore: 'oklch(95.71% 0.1933 256.16)', two: 'oklch(32.49% 0.1493 246.05)', twofore: 'oklch(95.49% 0.1493 246.05)', three: 'oklch(51.3% 0.1959 328.46)', threefore: 'oklch(95.3% 0.1959 328.46)', four: 'oklch(56.26% 0.1762 297.9)', fourfore: 'oklch(96.26% 0.1762 297.9)', five: 'oklch(62.63% 0.1806 267.58)', fivefore: 'oklch(92.63% 0.1806 267.58)', error: 'oklch(51.58% 0.1891 28.19)', errorfore: 'oklch(96.58% 0.1891 28.19)', warning: 'oklch(19.19% 0.1613 103.51)', warningfore: 'oklch(95.19% 0.1613 103.51)', success: 'oklch(44.96% 0.1827 142.37)', successfore: 'oklch(90.96% 0.1827 142.37)', white: 'oklch(100% 0 0)', whitefore: 'oklch(10% 0 0)', black: 'oklch(0% 0 0)', blackfore: 'oklch(100% 0 0)', }; static set algorithm(algo) { this._algo = algo; } static get algorithm() { return this._algo || Colorimetric.Oklch; } static stylesheet() { this._stylesheet = this._stylesheet || (new StyleWidget({ attach: true })); return this._stylesheet; } static clear() { this.declarations = {}; this._stylesheet?.clear(); return this; } static value(type, name) { const scheme = this[type]; const color = scheme ? scheme[name] || undefined : undefined; const parsed = color ? this.algorithm.parse(color) : undefined; return parsed ? this.algorithm.toString(parsed) : undefined; } static generate(color, key) { const parsed = this.algorithm.parse(color); if (!parsed) return undefined; const xpath = `${key}`.split('-'); const variants = xpath.slice(1); let calculate = parsed; for (let index = 0; index < variants.length; index++) if (calculate) calculate = this.algorithm.variation(calculate, variants[index]); if (!calculate) return undefined; return this.algorithm.toString(calculate); } static generateVariables(key, provider) { const schemes = Object.values(ColorSchemeType); const values = {}; const parsed = schemes .map(type => { if (!type) return undefined; const scheme = provider || this[type]; const xpath = `${key}`.split('-'); const color = scheme[xpath[0]] || undefined; if (!color) return undefined; values[type] = String(this.generate(color, key)); return { type, value: values[type] }; }) .filter(v => typeof v !== 'undefined'); return { name: `--color-${key}`, lightName: `--color-light-${key}`, darkName: `--color-dark-${key}`, value: `light-dark(${parsed.map(({ type }) => `var(--color-${type}-${key})`).join(',')})`, light: `${values.light}`, dark: `${values.dark}`, }; } static variable(key) { const generated = this.generateVariables(key); const stylesheets = {}; this.declarations[`--color-light-${key}`] = generated.light; this.declarations[`--color-dark-${key}`] = generated.dark; this.declarations[`--color-${key}`] = generated.value; stylesheets[':root, :host'] = Style(this.declarations); this.stylesheet() ?.sync(stylesheets); return `var(--color-${key})`; } } export const Color = new Proxy({}, { get(target, key) { key = key.replace(/[_]/gi, '-'); target[key] = ColorPalette.variable(key); return target[key] || undefined; }, });