'page-draft-color' => '#7e50b1',
'app-color-dark' => '#195785',
'app-color-light-dark' => 'rgba(32,110,167,0.15)',
- 'link-color-dark' => '#195785',
+ 'link-color-dark' => '#429fe3',
'bookshelf-color-dark' => '#ff5454',
'book-color-dark' => '#389f60',
'chapter-color-dark' => '#ee7a2d',
export {PermissionsTable} from "./permissions-table.js"
export {Pointer} from "./pointer.js"
export {Popup} from "./popup.js"
-export {SettingAppColorPicker} from "./setting-app-color-picker.js"
+export {SettingAppColorScheme} from "./setting-app-color-scheme.js"
export {SettingColorPicker} from "./setting-color-picker.js"
export {SettingHomepageControl} from "./setting-homepage-control.js"
export {ShelfSort} from "./shelf-sort.js"
+++ /dev/null
-import {Component} from "./component";
-
-export class SettingAppColorPicker extends Component {
-
- setup() {
- // TODO
- this.colorInput = this.$refs.input;
- this.lightColorInput = this.$refs.lightInput;
-
- this.colorInput.addEventListener('change', this.updateColor.bind(this));
- this.colorInput.addEventListener('input', this.updateColor.bind(this));
- }
-
- /**
- * Update the app colors as a preview, and create a light version of the color.
- */
- updateColor() {
- const hexVal = this.colorInput.value;
- const rgb = this.hexToRgb(hexVal);
- const rgbLightVal = 'rgba('+ [rgb.r, rgb.g, rgb.b, '0.15'].join(',') +')';
-
- this.lightColorInput.value = rgbLightVal;
-
- const customStyles = document.getElementById('custom-styles');
- const oldColor = customStyles.getAttribute('data-color');
- const oldColorLight = customStyles.getAttribute('data-color-light');
-
- customStyles.innerHTML = customStyles.innerHTML.split(oldColor).join(hexVal);
- customStyles.innerHTML = customStyles.innerHTML.split(oldColorLight).join(rgbLightVal);
-
- customStyles.setAttribute('data-color', hexVal);
- customStyles.setAttribute('data-color-light', rgbLightVal);
- }
-
- /**
- * Covert a hex color code to rgb components.
- * @attribution https://stackoverflow.com/a/5624139
- * @param {String} hex
- * @returns {{r: Number, g: Number, b: Number}}
- */
- hexToRgb(hex) {
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return {
- r: result ? parseInt(result[1], 16) : 0,
- g: result ? parseInt(result[2], 16) : 0,
- b: result ? parseInt(result[3], 16) : 0
- };
- }
-
-}
--- /dev/null
+import {Component} from "./component";
+
+export class SettingAppColorScheme extends Component {
+
+ setup() {
+ this.container = this.$el;
+ this.mode = this.$opts.mode;
+ this.lightContainer = this.$refs.lightContainer;
+ this.darkContainer = this.$refs.darkContainer;
+
+ this.container.addEventListener('tabs-change', event => {
+ const panel = event.detail.showing;
+ const newMode = (panel === 'color-scheme-panel-light') ? 'light' : 'dark';
+ this.handleModeChange(newMode);
+ });
+
+ const onInputChange = (event) => {
+ this.updateAppColorsFromInputs();
+
+ if (event.target.name.startsWith('setting-app-color')) {
+ this.updateLightForInput(event.target);
+ }
+ };
+ this.container.addEventListener('change', onInputChange);
+ this.container.addEventListener('input', onInputChange);
+ }
+
+ handleModeChange(newMode) {
+ this.mode = newMode;
+ const isDark = (newMode === 'dark');
+
+ document.documentElement.classList.toggle('dark-mode', isDark);
+ this.updateAppColorsFromInputs();
+ }
+
+ updateAppColorsFromInputs() {
+ const inputContainer = this.mode === 'dark' ? this.darkContainer : this.lightContainer;
+ const inputs = inputContainer.querySelectorAll('input[type="color"]');
+ for (const input of inputs) {
+ const splitName = input.name.split('-');
+ const colorPos = splitName.indexOf('color');
+ let cssId = splitName.slice(1, colorPos).join('-');
+ if (cssId === 'app') {
+ cssId = 'primary';
+ }
+
+ const varName = '--color-' + cssId;
+ document.body.style.setProperty(varName, input.value);
+ }
+ }
+
+ /**
+ * Update the 'light' app color variant for the given input.
+ * @param {HTMLInputElement} input
+ */
+ updateLightForInput(input) {
+ const lightName = input.name.replace('-color', '-color-light');
+ const hexVal = input.value;
+ const rgb = this.hexToRgb(hexVal);
+ const rgbLightVal = 'rgba('+ [rgb.r, rgb.g, rgb.b, '0.15'].join(',') +')';
+
+ console.log(input.name, lightName, hexVal, rgbLightVal)
+ const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
+ lightColorInput.value = rgbLightVal;
+ }
+
+ /**
+ * Covert a hex color code to rgb components.
+ * @attribution https://stackoverflow.com/a/5624139
+ * @param {String} hex
+ * @returns {{r: Number, g: Number, b: Number}}
+ */
+ hexToRgb(hex) {
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return {
+ r: result ? parseInt(result[1], 16) : 0,
+ g: result ? parseInt(result[2], 16) : 0,
+ b: result ? parseInt(result[3], 16) : 0
+ };
+ }
+
+}
setValue(value) {
this.colorInput.value = value;
- this.colorInput.dispatchEvent(new Event('change'));
+ this.colorInput.dispatchEvent(new Event('change', {bubbles: true}));
}
}
\ No newline at end of file
tab.setAttribute('aria-selected', selected ? 'true' : 'false');
}
- this.$emit('change', {section: sectionId});
+ this.$emit('change', {showing: sectionId});
}
}
\ No newline at end of file
if (!element) return;
element.scrollIntoView({behavior: 'smooth'});
- const color = document.getElementById('custom-styles').getAttribute('data-color-light');
+ const color = getComputedStyle(document.body).getPropertyValue('--color-primary-light');
const initColor = window.getComputedStyle(element).getPropertyValue('background-color');
element.style.backgroundColor = color;
setTimeout(() => {
-<style id="custom-styles"
- data-color="{{ setting('app-color') }}"
- data-color-dark="{{ setting('app-color-dark') }}"
- data-color-light="{{ setting('app-color-light') }}"
- data-color-light-dark="{{ setting('app-color-light-dark') }}">
-
- @php
- $settingSuffix = setting()->getForCurrentUser('dark-mode-enabled') ? '-dark' : '';
- @endphp
-
+@php
+ $settingSuffix = setting()->getForCurrentUser('dark-mode-enabled') ? '-dark' : '';
+@endphp
+<style>
:root {
--color-primary: {{ setting('app-color' . $settingSuffix) }};
--color-primary-light: {{ setting('app-color-light' . $settingSuffix) }};
</div>
<!-- App Color Scheme -->
- <div class="pb-l">
+ @php
+ $darkMode = boolval(setting()->getForCurrentUser('dark-mode-enabled'));
+ @endphp
+ <div component="setting-app-color-scheme"
+ option:setting-app-color-scheme:mode="{{ $darkMode ? 'dark' : 'light' }}"
+ class="pb-l">
<div class="mb-l">
<label class="setting-list-label">{{ trans('settings.color_scheme') }}</label>
<p class="small">{{ trans('settings.color_scheme_desc') }}</p>
</div>
- @php
- $darkMode = boolval(setting()->getForCurrentUser('dark-mode-enabled'));
- @endphp
<div component="tabs" class="tab-container">
<div role="tablist" class="controls-card">
<button type="button"
</div>
<div class="sub-card">
<div id="color-scheme-panel-light"
+ refs="setting-app-color-scheme@lightContainer"
tabindex="0"
role="tabpanel"
aria-labelledby="color-scheme-tab-light"
@include('settings.parts.setting-color-scheme', ['mode' => 'light'])
</div>
<div id="color-scheme-panel-dark"
+ refs="setting-app-color-scheme@darkContainer"
tabindex="0"
role="tabpanel"
aria-labelledby="color-scheme-tab-light"
@include('settings.parts.setting-color-picker', ['type' => 'page', 'mode' => $mode])
@include('settings.parts.setting-color-picker', ['type' => 'page-draft', 'mode' => $mode])
</div>
-</div>
\ No newline at end of file
+</div>
+
+<input type="hidden"
+ value="{{ setting('app-color-light' . ($mode === 'dark' ? '-dark' : '')) }}"
+ name="setting-app-color-light{{ $mode === 'dark' ? '-dark' : '' }}">
\ No newline at end of file