]> BookStack Code Mirror - bookstack/blob - resources/js/components/setting-app-color-scheme.js
Merge branch 'rashadkhan359/development' into development
[bookstack] / resources / js / components / setting-app-color-scheme.js
1 import {Component} from './component';
2
3 export class SettingAppColorScheme extends Component {
4
5     setup() {
6         this.container = this.$el;
7         this.mode = this.$opts.mode;
8         this.lightContainer = this.$refs.lightContainer;
9         this.darkContainer = this.$refs.darkContainer;
10
11         this.container.addEventListener('tabs-change', event => {
12             const panel = event.detail.showing;
13             const newMode = (panel === 'color-scheme-panel-light') ? 'light' : 'dark';
14             this.handleModeChange(newMode);
15         });
16
17         const onInputChange = event => {
18             this.updateAppColorsFromInputs();
19
20             if (event.target.name.startsWith('setting-app-color')) {
21                 this.updateLightForInput(event.target);
22             }
23         };
24         this.container.addEventListener('change', onInputChange);
25         this.container.addEventListener('input', onInputChange);
26     }
27
28     handleModeChange(newMode) {
29         this.mode = newMode;
30         const isDark = (newMode === 'dark');
31
32         document.documentElement.classList.toggle('dark-mode', isDark);
33         this.updateAppColorsFromInputs();
34     }
35
36     updateAppColorsFromInputs() {
37         const inputContainer = this.mode === 'dark' ? this.darkContainer : this.lightContainer;
38         const inputs = inputContainer.querySelectorAll('input[type="color"]');
39         for (const input of inputs) {
40             const splitName = input.name.split('-');
41             const colorPos = splitName.indexOf('color');
42             let cssId = splitName.slice(1, colorPos).join('-');
43             if (cssId === 'app') {
44                 cssId = 'primary';
45             }
46
47             const varName = `--color-${cssId}`;
48             document.body.style.setProperty(varName, input.value);
49         }
50     }
51
52     /**
53      * Update the 'light' app color variant for the given input.
54      * @param {HTMLInputElement} input
55      */
56     updateLightForInput(input) {
57         const lightName = input.name.replace('-color', '-color-light');
58         const hexVal = input.value;
59         const rgb = this.hexToRgb(hexVal);
60         const rgbLightVal = `rgba(${[rgb.r, rgb.g, rgb.b, '0.15'].join(',')})`;
61
62         const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
63         lightColorInput.value = rgbLightVal;
64     }
65
66     /**
67      * Covert a hex color code to rgb components.
68      * @attribution https://stackoverflow.com/a/5624139
69      * @param {String} hex
70      * @returns {{r: Number, g: Number, b: Number}}
71      */
72     hexToRgb(hex) {
73         const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
74         return {
75             r: result ? parseInt(result[1], 16) : 0,
76             g: result ? parseInt(result[2], 16) : 0,
77             b: result ? parseInt(result[3], 16) : 0,
78         };
79     }
80
81 }