Mercurial > code > home > repos > light9
diff web/light9-color-picker.ts @ 2376:4556eebe5d73
topdir reorgs; let pdm have its src/ dir; separate vite area from light9/
author | drewp@bigasterisk.com |
---|---|
date | Sun, 12 May 2024 19:02:10 -0700 |
parents | light9/web/light9-color-picker.ts@18d6bdd422f2 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/light9-color-picker.ts Sun May 12 19:02:10 2024 -0700 @@ -0,0 +1,106 @@ +import debug from "debug"; +import { css, html, LitElement, PropertyValueMap } from "lit"; +import { customElement, property, queryAsync, state } from "lit/decorators.js"; +import color from "onecolor"; +import { ClientCoord, pickerFloat } from "./floating_color_picker"; +export { Slider } from "@material/mwc-slider"; + +const log = debug("control.color"); +type int8 = number; + +@customElement("light9-color-picker") +export class Light9ColorPicker extends LitElement { + static styles = [ + css` + :host { + position: relative; + display: flex; + align-items: center; + flex-wrap: wrap; + user-select: none; + } + + #swatch { + display: inline-block; + width: 50px; + height: 30px; + margin-right: 3px; + border: 1px solid #333; + } + + mwc-slider { + width: 160px; + } + + #vee { + display: flex; + align-items: center; + } + `, + ]; + render() { + return html` + <div id="swatch" style="background-color: ${this.color}; border-color: ${this.hueSatColor}" @mousedown=${this.startFloatingPick}></div> + <span id="vee"> V: <mwc-slider id="value" .value=${this.value} step="1" min="0" max="255" @input=${this.onVSliderChange}></mwc-slider> </span> + `; + } + + // Selected color. Read/write. Equal to value*hueSatColor. Never null. + @property() color: string = "#000"; + + @state() hueSatColor: string = "#fff"; // always full value + @state() value: int8 = 0; + + @queryAsync("#swatch") swatchEl!: Promise<HTMLElement>; + + connectedCallback(): void { + super.connectedCallback(); + pickerFloat.pageInit(); + } + update(changedProperties: PropertyValueMap<this>) { + super.update(changedProperties); + if (changedProperties.has("color")) { + this.setColor(this.color); + } + if (changedProperties.has("value") || changedProperties.has("hueSatColor")) { + this.updateColorFromHSV(); + + this.dispatchEvent(new CustomEvent("input", { detail: { value: this.color } })); + + this.swatchEl.then((sw) => { + sw.style.borderColor = this.hueSatColor; + }); + } + } + + private updateColorFromHSV() { + this.color = color(this.hueSatColor) + .value(this.value / 255) + .hex(); + } + + private onVSliderChange(ev: CustomEvent) { + this.value = ev.detail.value; + } + + // for outside users of the component + setColor(col: string) { + if (col === null) throw new Error("col===null"); + if (typeof col !== "string") throw new Error("typeof col=" + typeof col); + this.value = color(col).value() * 255; + + // don't update this if only the value changed, or we desaturate + this.hueSatColor = color(col).value(1).hex(); + } + + private startFloatingPick(ev: MouseEvent) { + if (this.value < (20 as int8)) { + log("boost"); + this.value = 255 as int8; + this.updateColorFromHSV(); + } + pickerFloat.startPick(new ClientCoord(ev.clientX, ev.clientY), this.color, (hsc: string) => { + this.hueSatColor = hsc; + }); + } +}