From 5f529b2b262cbf0d6ab4122a373328ed4ed68bfa Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 17 Jan 2023 07:39:14 +0100 Subject: [PATCH] Add Stimulus theme controller --- .../controllers/theme_controller.ts | 79 +++++++++++++++++++ .../retrospring/initializers/stimulus.ts | 2 + 2 files changed, 81 insertions(+) create mode 100644 app/javascript/retrospring/controllers/theme_controller.ts diff --git a/app/javascript/retrospring/controllers/theme_controller.ts b/app/javascript/retrospring/controllers/theme_controller.ts new file mode 100644 index 00000000..eff86e98 --- /dev/null +++ b/app/javascript/retrospring/controllers/theme_controller.ts @@ -0,0 +1,79 @@ +import { Controller } from '@hotwired/stimulus'; +import Coloris from '@melloware/coloris'; + +import { + THEME_MAPPING, + getColorForKey, + getHexColorFromThemeValue, + getIntegerFromHexColor +} from 'utilities/theme'; + +export default class extends Controller { + static targets = ['color']; + + declare readonly colorTargets: HTMLInputElement[]; + + previewStyle = null; + previewTimeout = null; + + setupPreviewElement(): void { + this.previewStyle = document.createElement('style'); + this.previewStyle.setAttribute('data-preview-style', ''); + document.body.appendChild(this.previewStyle); + } + + convertColors(): void { + this.colorTargets.forEach((color) => { + color.value = `#${getHexColorFromThemeValue(color.value)}`; + }); + } + + connect(): void { + this.setupPreviewElement(); + this.convertColors(); + + Coloris.init(); + Coloris({ + el: '.color', + wrap: false, + formatToggle: false, + alpha: false + }); + } + + updatePreview(): void { + clearTimeout(this.previewTimeout); + this.previewTimeout = setTimeout(this.previewTheme.bind(this), 1000); + } + + previewTheme(): void { + const payload = {}; + + this.colorTargets.forEach((color) => { + const name = color.name.substring(6, color.name.length - 1); + payload[name] = parseInt(color.value.substr(1, 6), 16); + }); + + this.generateTheme(payload); + } + + generateTheme(payload: Record): void { + let body = ":root {\n"; + + Object.entries(payload).forEach(([key, value]) => { + if (THEME_MAPPING[key]) { + body += `--${THEME_MAPPING[key]}: ${getColorForKey(THEME_MAPPING[key], value)};\n`; + } + }); + + body += "}"; + + this.previewStyle.innerHTML = body; + } + + submit(): void { + this.colorTargets.forEach((color) => { + color.value = String(getIntegerFromHexColor(color.value)); + }); + } +} diff --git a/app/javascript/retrospring/initializers/stimulus.ts b/app/javascript/retrospring/initializers/stimulus.ts index 56e27d7f..64fa8968 100644 --- a/app/javascript/retrospring/initializers/stimulus.ts +++ b/app/javascript/retrospring/initializers/stimulus.ts @@ -5,6 +5,7 @@ import CharacterCountController from "retrospring/controllers/character_count_co import CharacterCountWarningController from "retrospring/controllers/character_count_warning_controller"; import FormatPopupController from "retrospring/controllers/format_popup_controller"; import CollapseController from "retrospring/controllers/collapse_controller"; +import ThemeController from "retrospring/controllers/theme_controller"; /** * This module sets up Stimulus and our controllers @@ -21,4 +22,5 @@ export default function (): void { window['Stimulus'].register('character-count-warning', CharacterCountWarningController); window['Stimulus'].register('collapse', CollapseController); window['Stimulus'].register('format-popup', FormatPopupController); + window['Stimulus'].register('theme', ThemeController); }