mrly.js

2.9 kB · javascript · 96 lines

1import init, * as wasm from '../pkg/mrlydemo.js';2import wasmUrl from '../pkg/mrlydemo_bg.wasm';3import { palette } from '../kit/ui/palette.js';4import { dark, light } from '../kit/ui/theme.js';56export const mrly = wasm;7export { palette, dark, light };89// THEME1011const scheme = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;1213export function isDark() {14  if (typeof document === 'undefined') return true;15  const set = document.documentElement.dataset.theme;16  return set ? set === 'dark' : Boolean(scheme?.matches);17}1819export function theme() {20  return isDark() ? dark : light;21}2223export const ink = new Proxy({}, { get: (_, key) => theme()[key] });2425export const role = () => [ink.dim, ink.yellow, ink.blue, ink.pink];2627export const plusminus = () => ({ plus: ink.orange, minus: ink.blue, empty: ink.deep });2829function tint() {30  if (typeof wasm.set_theme === 'function') wasm.set_theme(isDark());31}3233export async function ready() {34  const at = wasmUrl.startsWith('.') ? new URL(wasmUrl, import.meta.url) : wasmUrl;35  await init({ module_or_path: at });36  globalThis.mrly = wasm;37  tint();38  window.addEventListener('theme', tint);39  scheme?.addEventListener('change', tint);40  return wasm;41}4243export function rgb(hex) {44  const n = parseInt(hex.slice(1), 16);45  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];46}4748// FLAT4950export function blit(canvas, pixels) {51  canvas.width = pixels.width;52  canvas.height = pixels.height;53  const image = new ImageData(new Uint8ClampedArray(pixels.rgba), pixels.width, pixels.height);54  canvas.getContext('2d').putImageData(image, 0, 0);55}5657export function paint(canvas, grid, on = ink.fg, off = ink.deep) {58  const [w, h] = [grid.width, grid.height];59  const a = rgb(on), b = rgb(off);60  const rgba = new Uint8ClampedArray(w * h * 4);61  for (let i = 0; i < w * h; i++) {62    const c = grid.types[i] ? a : b;63    rgba.set(c, i * 4);64    rgba[i * 4 + 3] = 255;65  }66  canvas.width = w;67  canvas.height = h;68  canvas.getContext('2d').putImageData(new ImageData(rgba, w, h), 0, 0);69}7071// SIGNED7273export function signs(canvas, grid, hues = {}) {74  const [w, h] = [grid.width, grid.height];75  const base = plusminus();76  const ramp = [rgb(hues.plus ?? base.plus), rgb(hues.minus ?? base.minus), rgb(hues.empty ?? base.empty)];77  const rgba = new Uint8ClampedArray(w * h * 4);78  for (let i = 0; i < w * h; i++) {79    rgba.set(ramp[grid.types[i]] ?? ramp[2], i * 4);80    rgba[i * 4 + 3] = 255;81  }82  canvas.width = w;83  canvas.height = h;84  canvas.getContext('2d').putImageData(new ImageData(rgba, w, h), 0, 0);85}8687export function fit(canvas, height) {88  const scale = Math.min(devicePixelRatio || 1, 2);89  const w = canvas.clientWidth;90  canvas.width = w * scale;91  canvas.height = height * scale;92  canvas.style.height = height + 'px';93  const ctx = canvas.getContext('2d');94  ctx.setTransform(scale, 0, 0, scale, 0, 0);95  return [ctx, w, height];96}