172 lines
5.4 KiB
JavaScript
172 lines
5.4 KiB
JavaScript
(function () {
|
|
var THEME_STORAGE_KEY = 'web-theme';
|
|
var CKEDITOR_THEME_STYLE_ID = 'ckeditor-dark-theme-overrides';
|
|
|
|
function getPreferredTheme() {
|
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
return 'dark';
|
|
}
|
|
return 'light';
|
|
}
|
|
|
|
function getStoredTheme() {
|
|
try {
|
|
var storedTheme = window.localStorage.getItem(THEME_STORAGE_KEY);
|
|
if (storedTheme === 'dark' || storedTheme === 'light') {
|
|
return storedTheme;
|
|
}
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function setStoredTheme(theme) {
|
|
try {
|
|
window.localStorage.setItem(THEME_STORAGE_KEY, theme);
|
|
} catch (error) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
function getOrCreateCkeditorThemeStyleElement() {
|
|
var styleElement = document.getElementById(CKEDITOR_THEME_STYLE_ID);
|
|
|
|
if (styleElement) {
|
|
return styleElement;
|
|
}
|
|
|
|
styleElement = document.createElement('style');
|
|
styleElement.id = CKEDITOR_THEME_STYLE_ID;
|
|
document.head.appendChild(styleElement);
|
|
|
|
return styleElement;
|
|
}
|
|
|
|
function syncCkeditorTheme(theme) {
|
|
var styleElement = getOrCreateCkeditorThemeStyleElement();
|
|
|
|
if (theme !== 'dark') {
|
|
styleElement.textContent = '';
|
|
return;
|
|
}
|
|
|
|
styleElement.textContent = [
|
|
'.ck-body-wrapper .ck.ck-dropdown__panel,',
|
|
'.ck-body-wrapper .ck.ck-list__panel,',
|
|
'.ck-body-wrapper .ck.ck-list,',
|
|
'.ck-body-wrapper .ck.ck-balloon-panel {',
|
|
' background: var(--bs-body-bg) !important;',
|
|
' background-color: var(--bs-body-bg) !important;',
|
|
' border-color: var(--bs-border-color) !important;',
|
|
' color: var(--bs-body-color) !important;',
|
|
'}',
|
|
'.ck-body-wrapper .ck.ck-list .ck-list-item-button {',
|
|
' background: transparent !important;',
|
|
' background-color: transparent !important;',
|
|
' color: var(--bs-body-color) !important;',
|
|
'}',
|
|
'.ck-body-wrapper .ck.ck-list .ck-list-item-button:hover {',
|
|
' background: var(--bs-secondary-bg) !important;',
|
|
' background-color: var(--bs-secondary-bg) !important;',
|
|
'}',
|
|
'.ck-body-wrapper .ck.ck-color-grid,',
|
|
'.ck-body-wrapper .ck.ck-color-grid__tile {',
|
|
' color: var(--bs-body-color) !important;',
|
|
'}',
|
|
'.ck-body-wrapper .ck.ck-color-grid__tile {',
|
|
' border-color: var(--bs-border-color) !important;',
|
|
'}'
|
|
].join('\n');
|
|
}
|
|
|
|
function applyTheme(theme) {
|
|
var normalizedTheme = theme === 'dark' ? 'dark' : 'light';
|
|
var nextTheme = normalizedTheme === 'dark' ? 'light' : 'dark';
|
|
var nextThemeLabel = nextTheme === 'dark' ? 'Dark mode' : 'Light mode';
|
|
|
|
document.documentElement.dataset.bsTheme = normalizedTheme;
|
|
document.documentElement.style.colorScheme = normalizedTheme;
|
|
syncCkeditorTheme(normalizedTheme);
|
|
|
|
Array.prototype.forEach.call(document.querySelectorAll('[data-theme-toggle]'), function (toggleButton) {
|
|
var icon = toggleButton.querySelector('.theme-toggle__icon');
|
|
toggleButton.setAttribute('aria-pressed', normalizedTheme === 'dark' ? 'true' : 'false');
|
|
toggleButton.setAttribute('aria-label', 'Switch to ' + nextThemeLabel.toLowerCase());
|
|
if (icon) {
|
|
icon.classList.remove('theme-toggle__icon--moon', 'theme-toggle__icon--sun');
|
|
icon.classList.add(normalizedTheme === 'dark' ? 'theme-toggle__icon--sun' : 'theme-toggle__icon--moon');
|
|
}
|
|
});
|
|
|
|
return normalizedTheme;
|
|
}
|
|
|
|
function initThemeToggle() {
|
|
var toggleButtons = Array.prototype.slice.call(document.querySelectorAll('[data-theme-toggle]'));
|
|
var storedTheme = getStoredTheme();
|
|
var theme = storedTheme || getPreferredTheme();
|
|
|
|
applyTheme(theme);
|
|
|
|
if (!toggleButtons.length) {
|
|
return;
|
|
}
|
|
|
|
Array.prototype.forEach.call(toggleButtons, function (toggleButton) {
|
|
toggleButton.addEventListener('click', function () {
|
|
var nextTheme = document.documentElement.dataset.bsTheme === 'dark' ? 'light' : 'dark';
|
|
setStoredTheme(nextTheme);
|
|
applyTheme(nextTheme);
|
|
});
|
|
});
|
|
}
|
|
|
|
function initSidebarToggle() {
|
|
var body = document.body;
|
|
var toggleButtons = Array.prototype.slice.call(document.querySelectorAll('[data-sidebar-toggle]'));
|
|
var backdrop = document.querySelector('[data-sidebar-backdrop]');
|
|
|
|
if (!toggleButtons.length || !backdrop) {
|
|
return;
|
|
}
|
|
|
|
function setSidebarOpen(isOpen) {
|
|
body.classList.toggle('is-sidebar-open', isOpen);
|
|
Array.prototype.forEach.call(toggleButtons, function (toggleButton) {
|
|
toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
|
});
|
|
}
|
|
|
|
function toggleSidebar() {
|
|
setSidebarOpen(!body.classList.contains('is-sidebar-open'));
|
|
}
|
|
|
|
Array.prototype.forEach.call(toggleButtons, function (toggleButton) {
|
|
toggleButton.addEventListener('click', function () {
|
|
toggleSidebar();
|
|
});
|
|
});
|
|
|
|
backdrop.addEventListener('click', function () {
|
|
setSidebarOpen(false);
|
|
});
|
|
|
|
document.addEventListener('keydown', function (event) {
|
|
if (event.key === 'Escape') {
|
|
setSidebarOpen(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
window.getPreferredTheme = getPreferredTheme;
|
|
window.getStoredTheme = getStoredTheme;
|
|
window.setStoredTheme = setStoredTheme;
|
|
window.applyTheme = applyTheme;
|
|
window.initThemeToggle = initThemeToggle;
|
|
window.initSidebarToggle = initSidebarToggle;
|
|
|
|
initThemeToggle();
|
|
initSidebarToggle();
|
|
}());
|