From ccfbac35f363106d97e29a6e7388e36a623d7c25 Mon Sep 17 00:00:00 2001 From: mauro-balades Date: Mon, 7 Oct 2024 20:54:51 +0200 Subject: [PATCH] Add ZenThemePicker class for generating gradient picker --- src/ZenGradientGenerator.mjs | 131 +++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/ZenGradientGenerator.mjs diff --git a/src/ZenGradientGenerator.mjs b/src/ZenGradientGenerator.mjs new file mode 100644 index 0000000..4bfe53e --- /dev/null +++ b/src/ZenGradientGenerator.mjs @@ -0,0 +1,131 @@ + +{ + class ZenThemePicker { + #containerNode; + + #color1; + #color2; + #color3; + #color4; + + constructor(containerNode) { + return; + this.#containerNode = containerNode; + this.init(); + } + + // Getters + get zenColors() { + return [ + '#aac7ff', + '#74d7cb', + '#a0d490', + '#dec663', + '#ffb787', + ] + } + + // Methods + init() { + const wrapper = this.generateWrapper(); + this.generateGradientPicker(wrapper); + this.injectWrapper(wrapper); + } + + injectWrapper(wrapper) { + this.#containerNode.replaceChildren(wrapper); + } + + generateWrapper() { + const wrapper = document.createXULElement('hbox'); + wrapper.classList.add('zen-theme-picker'); + return wrapper; + } + + generateGradientPicker(wrapper) { + const gradientPicker = window.MozXULElement.parseXULToFragment(` + + + + + + + + + + `); + const canvas = gradientPicker.querySelector('.zen-theme-picker-gradient-canvas'); + const ctx = canvas.getContext('2d'); + + // Canvas dimensions + const width = canvas.width; + const height = canvas.height; + + ctx.globalCompositeOperation = 'lighter'; + const gradient = ctx.createLinearGradient(0, 0, width, height); + for (let i = 0; i < this.zenColors.length; i++) { + gradient.addColorStop(i / (this.zenColors.length - 1), this.zenColors[i]); + } + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, width, height); + + // Event listeners, each color can be dragged + const colors = gradientPicker.querySelectorAll('.zen-theme-picker-gradient-color'); + for (const color of colors) { + this.addColorDragListener(color, ctx); + } + + wrapper.appendChild(gradientPicker); + } + + addColorDragListener(color, ctx) { + const padding = 10; + color.addEventListener('mousedown', (event) => { + const colorIndex = Array.from(color.parentElement.children).indexOf(color); + color.setAttribute('dragging', 'true'); + const onMouseMove = (event) => { + const rect = color.parentElement.getBoundingClientRect(); + let x = event.clientX - rect.left; + let y = event.clientY - rect.top; + const width = rect.width; + const height = rect.height; + + // If x is out of bounds, set it to the padding + if (x < padding) { + x = padding; + } + if (x > width - padding) { + x = width - padding; + } + + // If y is out of bounds, set it to the padding + if (y < padding) { + y = padding; + } + if (y > height - padding) { + y = height - padding; + } + + let xRatio = Math.min(1, Math.max(0, x / width)); + let yRatio = Math.min(1, Math.max(0, y / height)); + + // Get the color from the canvas + const pixel = ctx.getImageData(x, y, 1, 1).data; + const rgb = `rgb(${pixel[0]}, ${pixel[1]}, ${pixel[2]})`; + color.style.left = `${xRatio * 100}%`; + color.style.top = `${yRatio * 100}%`; + color.style.setProperty("--zen-chosen-color", rgb); + } + const onMouseUp = (event) => { + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); + color.removeAttribute('dragging'); + } + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('mouseup', onMouseUp); + }); + } + } + + window.ZenThemePicker = ZenThemePicker; +}