icydraw/src/client/picker.ts

170 lines
4.8 KiB
TypeScript

import { hexToString, storeHex } from '../common/convert';
import { IcyNetUser } from '../common/types/user';
import { $ } from './utils/dom';
export class Picker {
private _fn?: (color: number) => void;
private _color: number = 0x000000;
private _pickerColor: number | null = null;
private _colorHistory: number[] = [];
private _wrapper = $('<div class="controls__wrapper">');
private _content = $('<div class="controls">');
private _colorsEl = $('<div class="controls__colors">');
private _colorHistoryEl = $('<div class="controls__colors-history">');
private _colorInput = $('<input type="color">') as HTMLInputElement;
private _placebtn = $('<button class="btn btn-primary btn-place">');
private _palettebtn = $('<button class="btn btn-palette">');
private _clearbtn = $('<button class="btn btn-palette">');
private _pickbtn = $('<button class="btn btn-palette">');
get element() {
return this._wrapper;
}
public place() {
if (this._fn) {
this._storeColor(this._color);
this._fn(this._color);
}
}
public pickPalette(index: number) {
if (this._colorHistory && this._colorHistory.length) {
this._setColor(this._colorHistory[index]);
}
}
public initialize() {
this._placebtn.innerText = 'Log in to place';
this._palettebtn.innerText = '>>';
this._clearbtn.innerText = 'Clear';
this._pickbtn.innerText = 'Pick';
this._wrapper.append(this._content);
this._content.append(this._colorsEl);
this._colorsEl.append(this._colorInput);
this._colorsEl.append(this._palettebtn);
this._colorsEl.append(this._colorHistoryEl);
this._colorsEl.append(this._clearbtn);
this._colorsEl.append(this._pickbtn);
this._content.append(this._placebtn);
this._pickbtn.setAttribute('disabled', 'true');
this._placebtn.setAttribute('disabled', 'true');
this._placebtn.addEventListener('click', (ev) => {
ev.preventDefault();
this.place();
});
this._colorInput.addEventListener('input', (ev) => {
this._color = storeHex(this._colorInput.value);
});
this._palettebtn.addEventListener('click', () => {
this._storeColor(this._color);
});
this._clearbtn.addEventListener('click', () => {
this._colorHistory.length = 0;
this._colorHistoryEl.innerHTML = '';
this._preserveHistory();
});
this._pickbtn.addEventListener('click', () => {
if (this._pickerColor !== null) {
this._setColor(this._pickerColor);
this._storeColor(this._pickerColor);
}
});
this._colorHistory = this._getHistory();
if (this._colorHistory.length) {
this._setColor(this._colorHistory[0]);
this._drawColorList();
}
}
public setLoggedIn(user: IcyNetUser): void {
if (!user) {
return;
}
this._placebtn.removeAttribute('disabled');
this._placebtn.innerText = 'Place';
}
public registerOnPlace(fn: (color: number) => void): void {
this._fn = fn;
}
public setPickColor(pickColor: number | null) {
if (pickColor !== null) {
this._pickbtn.removeAttribute('disabled');
this._pickbtn.classList.add('pickable');
this._pickbtn.style.setProperty('--pick-color', hexToString(pickColor));
} else if (this._pickerColor !== null && pickColor === null) {
this._pickbtn.setAttribute('disabled', 'true');
this._pickbtn.classList.remove('pickable');
this._pickbtn.style.removeProperty('--pick-color');
}
this._pickerColor = pickColor;
}
private _setColor(color: number): void {
this._color = color || 0;
this._colorInput.value = hexToString(color || 0);
}
private _drawColorList(): void {
this._colorHistoryEl.innerHTML = '';
this._colorHistory.map((item) => {
const str = hexToString(item);
const colEl = $(
`<div class="btn controls__color" style="background-color: ${str};">`,
);
colEl.addEventListener('click', () => {
this._colorInput.value = str;
this._color = item;
});
this._colorHistoryEl.append(colEl);
});
}
private _storeColor(color: number): void {
if (this._colorHistory.includes(color)) {
return;
}
this._colorHistory.unshift(color);
if (this._colorHistory.length > 10) {
this._colorHistory.length = 10;
}
this._drawColorList();
this._preserveHistory();
}
private _preserveHistory(): void {
if (window.localStorage) {
if (!this._colorHistory.length) {
window.localStorage.removeItem('colors');
return;
}
window.localStorage.setItem('colors', this._colorHistory.join('|'));
}
}
private _getHistory(): number[] {
if (window.localStorage) {
const list = window.localStorage.getItem('colors')?.split('|');
if (list?.length) {
return list.map((item) => Number(item));
}
}
return [];
}
}