first commit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
*.zip
|
||||
*.log
|
||||
.idea/
|
||||
.vscode/
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Fallback dark palette when Blocksy Colour Mode Switch is not active.
|
||||
* Matches Beatwise Customizer tokens from test2.beatwise.nl.
|
||||
*/
|
||||
|
||||
html.theme-dark {
|
||||
color-scheme: dark;
|
||||
|
||||
--blc-beatwise-purple: #442b79;
|
||||
--blc-beatwise-purple-hover: #5a3d9a;
|
||||
--blc-beatwise-purple-light: #9b8fd4;
|
||||
--blc-beatwise-purple-soft: #c4b5fd;
|
||||
|
||||
--theme-palette-color-1: var(--blc-beatwise-purple);
|
||||
--theme-palette-color-2: var(--blc-beatwise-purple-hover);
|
||||
--theme-palette-color-3: #333;
|
||||
--theme-palette-color-4: #f5f5f5;
|
||||
--theme-palette-color-5: #404040;
|
||||
--theme-palette-color-6: #1e1e1e;
|
||||
--theme-palette-color-7: #121212;
|
||||
--theme-palette-color-8: #ffffff;
|
||||
|
||||
--theme-text-color: var(--theme-palette-color-3);
|
||||
--theme-link-initial-color: var(--blc-beatwise-purple-light);
|
||||
--theme-link-hover-color: var(--blc-beatwise-purple-soft);
|
||||
--theme-headings-color: var(--theme-palette-color-4);
|
||||
--theme-border-color: var(--theme-palette-color-5);
|
||||
--theme-selection-text-color: #ffffff;
|
||||
--theme-selection-background-color: var(--blc-beatwise-purple);
|
||||
--theme-button-background-initial-color: var(--blc-beatwise-purple);
|
||||
--theme-button-background-hover-color: var(--blc-beatwise-purple-hover);
|
||||
}
|
||||
|
||||
html.theme-dark body,
|
||||
html.theme-dark #main-container,
|
||||
html.theme-dark .site {
|
||||
background-color: var(--theme-palette-color-7);
|
||||
color: var(--theme-text-color);
|
||||
}
|
||||
|
||||
html.theme-dark input:not([type="submit"]):not([type="button"]):not([type="reset"]),
|
||||
html.theme-dark textarea,
|
||||
html.theme-dark select {
|
||||
background-color: var(--theme-palette-color-6);
|
||||
color: var(--theme-palette-color-3);
|
||||
border-color: var(--theme-palette-color-5);
|
||||
}
|
||||
|
||||
html.blc-ldt-animate,
|
||||
html.blc-ldt-animate body {
|
||||
transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
|
||||
}
|
||||
|
||||
html.theme.dark .bwam-day-header {
|
||||
color: #000 !important;
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Beatwise (test2.beatwise.nl) dark-mode fixes.
|
||||
* Tuned to Blocksy 2.1.38 global palette from the Customizer.
|
||||
*/
|
||||
|
||||
html.theme-dark {
|
||||
/* Beatwise brand — keep lavender purple, never blue */
|
||||
--blc-beatwise-purple: #442b79;
|
||||
--blc-beatwise-purple-hover: #5a3d9a;
|
||||
--blc-beatwise-purple-light: #9b8fd4;
|
||||
--blc-beatwise-purple-soft: #c4b5fd;
|
||||
|
||||
--theme-palette-color-1: var(--blc-beatwise-purple);
|
||||
--theme-palette-color-2: var(--blc-beatwise-purple-hover);
|
||||
--theme-palette-color-3: #e0e0e0;
|
||||
--theme-palette-color-4: #f5f5f5;
|
||||
--theme-palette-color-5: #404040;
|
||||
--theme-palette-color-6: #1e1e1e;
|
||||
--theme-palette-color-7: #121212;
|
||||
--theme-palette-color-8: #ffffff;
|
||||
|
||||
--theme-text-color: var(--theme-palette-color-3);
|
||||
--theme-headings-color: var(--theme-palette-color-4);
|
||||
--theme-link-initial-color: var(--blc-beatwise-purple-light);
|
||||
--theme-link-hover-color: var(--blc-beatwise-purple-soft);
|
||||
--theme-button-background-initial-color: var(--blc-beatwise-purple);
|
||||
--theme-button-background-hover-color: var(--blc-beatwise-purple-hover);
|
||||
--theme-selection-background-color: var(--blc-beatwise-purple);
|
||||
--theme-selection-text-color: #ffffff;
|
||||
}
|
||||
|
||||
html.theme-dark body {
|
||||
background-color: var(--theme-palette-color-7);
|
||||
color: var(--theme-text-color);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
1 & 3 — Header menu + dropdown (Blocksy header type-1)
|
||||
------------------------------------------------------------------------- */
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a,
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .ct-menu-link {
|
||||
--theme-link-initial-color: #ffffff !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a:hover,
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .ct-menu-link:hover {
|
||||
--theme-link-initial-color: var(--blc-beatwise-purple-soft) !important;
|
||||
color: var(--blc-beatwise-purple-soft) !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu {
|
||||
background-color: #2b2b2b !important;
|
||||
--dropdown-background-color: #2b2b2b !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu .ct-menu-link,
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu a {
|
||||
--theme-link-initial-color: #ffffff !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu .ct-menu-link:hover,
|
||||
html.theme-dark [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu a:hover {
|
||||
color: var(--blc-beatwise-purple-soft) !important;
|
||||
background-color: rgba(255, 255, 255, 0.06) !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-header*="type-1"] [data-id="mobile-menu"] a,
|
||||
html.theme-dark [data-header*="type-1"] #offcanvas .ct-menu-link,
|
||||
html.theme-dark [data-header*="type-1"] #offcanvas a {
|
||||
--theme-link-initial-color: #ffffff !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* Account dropdown */
|
||||
html.theme-dark [data-header*="type-1"] [data-id="account"] .ct-header-account-dropdown {
|
||||
--theme-text-color: #ffffff !important;
|
||||
--dropdown-background-color: #2b2b2b !important;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
5 — Footer: purple background + white text (same as light mode)
|
||||
------------------------------------------------------------------------- */
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer {
|
||||
background-color: var(--blc-beatwise-purple) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer p,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer li,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer span,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer div,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h1,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h2,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h3,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h4,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h5,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer h6,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer .widget-title,
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer .ct-widget,
|
||||
html.theme-dark [data-footer*="type-1"] [data-id="copyright"] {
|
||||
--theme-text-color: #ffffff !important;
|
||||
--theme-heading-color: #ffffff !important;
|
||||
--theme-link-initial-color: #ffffff !important;
|
||||
--theme-link-hover-color: var(--blc-beatwise-purple-soft) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
html.theme-dark [data-footer*="type-1"] .ct-footer a:hover,
|
||||
html.theme-dark [data-footer*="type-1"] [data-id="copyright"] a:hover {
|
||||
color: var(--blc-beatwise-purple-soft) !important;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
6 — /codes page: dark text on light hero/header area
|
||||
------------------------------------------------------------------------- */
|
||||
html.theme-dark.page-codes [data-header*="type-1"] .ct-header [data-row*="middle"],
|
||||
html.theme-dark.blc-ldt-page-codes [data-header*="type-1"] .ct-header [data-row*="middle"] {
|
||||
background-color: rgba(255, 255, 255, 0.94) !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-codes [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a,
|
||||
html.theme-dark.page-codes [data-header*="type-1"] .ct-header [data-id="menu"] .ct-menu-link,
|
||||
html.theme-dark.page-codes [data-header*="type-1"] .ct-header a,
|
||||
html.theme-dark.blc-ldt-page-codes [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a,
|
||||
html.theme-dark.blc-ldt-page-codes [data-header*="type-1"] .ct-header [data-id="menu"] .ct-menu-link {
|
||||
--theme-link-initial-color: #181818 !important;
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-codes [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a:hover,
|
||||
html.theme-dark.blc-ldt-page-codes [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a:hover {
|
||||
color: var(--blc-beatwise-purple) !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-codes .hero-section,
|
||||
html.theme-dark.page-codes .entry-header,
|
||||
html.theme-dark.page-codes .wp-block-cover,
|
||||
html.theme-dark.blc-ldt-page-codes .hero-section,
|
||||
html.theme-dark.blc-ldt-page-codes .entry-header,
|
||||
html.theme-dark.blc-ldt-page-codes .wp-block-cover {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-codes .hero-section h1,
|
||||
html.theme-dark.page-codes .hero-section p,
|
||||
html.theme-dark.page-codes .entry-header h1,
|
||||
html.theme-dark.page-codes .entry-header p,
|
||||
html.theme-dark.blc-ldt-page-codes .hero-section h1,
|
||||
html.theme-dark.blc-ldt-page-codes .hero-section p {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
2 — /reservations page: dark date labels on light schedule cards
|
||||
------------------------------------------------------------------------- */
|
||||
html.theme-dark.page-reservations .has-white-background-color,
|
||||
html.theme-dark.page-reservations .has-base-background-color,
|
||||
html.theme-dark.page-reservations .has-palette-color-8-background-color,
|
||||
html.theme-dark.page-reservations .has-palette-color-6-background-color,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-white-background-color,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-base-background-color,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-palette-color-8-background-color,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-palette-color-6-background-color {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-reservations .has-white-background-color strong,
|
||||
html.theme-dark.page-reservations .has-white-background-color span,
|
||||
html.theme-dark.page-reservations .has-base-background-color strong,
|
||||
html.theme-dark.page-reservations .has-base-background-color span,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-white-background-color strong,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-white-background-color span,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-base-background-color strong,
|
||||
html.theme-dark.blc-ldt-page-reservations .has-base-background-color span {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
/* Reservation schedule grid (day headers like "Zondag 7 jun") */
|
||||
html.theme-dark.page-reservations article strong,
|
||||
html.theme-dark.page-reservations article .wp-block-group strong,
|
||||
html.theme-dark.blc-ldt-page-reservations article strong,
|
||||
html.theme-dark.blc-ldt-page-reservations article .wp-block-group strong {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
html.theme-dark.page-reservations article .wp-block-group span,
|
||||
html.theme-dark.blc-ldt-page-reservations article .wp-block-group span {
|
||||
color: #181818 !important;
|
||||
}
|
||||
|
||||
/* Buttons stay Beatwise purple */
|
||||
html.theme-dark .wp-block-button__link,
|
||||
html.theme-dark .ct-button {
|
||||
background-color: var(--blc-beatwise-purple) !important;
|
||||
border-color: var(--blc-beatwise-purple) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
html.theme-dark .wp-block-button__link:hover,
|
||||
html.theme-dark .ct-button:hover {
|
||||
background-color: var(--blc-beatwise-purple-hover) !important;
|
||||
border-color: var(--blc-beatwise-purple-hover) !important;
|
||||
}
|
||||
|
||||
html.theme.dark .bwam-day-header {
|
||||
color: #000 !important;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
.blc-ldt-toggle {
|
||||
position: fixed;
|
||||
/* Position, offsets, and z-index are set via inline settings CSS. */
|
||||
right: 1.25rem;
|
||||
bottom: 1.25rem;
|
||||
z-index: 999999;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0.65rem 0.5rem 0.5rem;
|
||||
border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
|
||||
border-radius: 999px;
|
||||
background: var(--theme-palette-color-8, #ffffff);
|
||||
color: var(--theme-palette-color-1, #1a1a1a);
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
|
||||
font: 600 0.8125rem/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.blc-ldt-toggle:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.blc-ldt-toggle:focus-visible {
|
||||
outline: 2px solid var(--theme-palette-color-1, #442b79);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.blc-ldt-toggle__track {
|
||||
position: relative;
|
||||
width: 2.5rem;
|
||||
height: 1.375rem;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, currentColor 12%, transparent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.blc-ldt-toggle__thumb {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: calc(1.375rem - 4px);
|
||||
height: calc(1.375rem - 4px);
|
||||
border-radius: 50%;
|
||||
background: var(--theme-palette-color-1, #442b79);
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.blc-ldt-toggle--dark .blc-ldt-toggle__thumb {
|
||||
transform: translateX(1.125rem);
|
||||
}
|
||||
|
||||
.blc-ldt-toggle__icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
html:not(.theme-dark) .blc-ldt-toggle__icon--moon,
|
||||
html.theme-dark .blc-ldt-toggle__icon--sun {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.theme-dark .blc-ldt-toggle {
|
||||
background: var(--theme-palette-color-7, #1a1a1a);
|
||||
color: var(--theme-palette-color-4, #f5f5f5);
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
/* Avoid overlap with Blocksy back-to-top button */
|
||||
.ct-back-to-top ~ .blc-ldt-toggle,
|
||||
#ct-back-to-top ~ .blc-ldt-toggle {
|
||||
bottom: 4.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.blc-ldt-toggle {
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
padding: 0.45rem;
|
||||
}
|
||||
|
||||
.blc-ldt-toggle__icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var config = window.blcLdt || {};
|
||||
var btn = document.getElementById('blc-ldt-toggle');
|
||||
if (!btn) return;
|
||||
|
||||
var storageKey = config.storageKey || 'blc_ldt_scheme';
|
||||
var cookieName = config.cookieName || 'blc_ldt_scheme';
|
||||
var blocksyKeys = config.blocksyStorageKeys || ['blocksyColorMode', 'blocksy_color_mode', 'theme'];
|
||||
var allKeys = [storageKey].concat(blocksyKeys);
|
||||
var respectOs = config.respectOsPreference !== false;
|
||||
var enableAnimation = config.enableAnimation !== false;
|
||||
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
function getStoredScheme() {
|
||||
var i, stored;
|
||||
|
||||
try {
|
||||
for (i = 0; i < allKeys.length; i++) {
|
||||
stored = localStorage.getItem(allKeys[i]);
|
||||
if (stored === 'light' || stored === 'dark') {
|
||||
return stored;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
var match = document.cookie.match(
|
||||
new RegExp('(?:^|; )' + cookieName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '=([^;]*)')
|
||||
);
|
||||
if (match) {
|
||||
var cookieVal = decodeURIComponent(match[1]);
|
||||
if (cookieVal === 'light' || cookieVal === 'dark') {
|
||||
return cookieVal;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getScheme() {
|
||||
var stored = getStoredScheme();
|
||||
if (stored) {
|
||||
return stored;
|
||||
}
|
||||
return document.documentElement.classList.contains('theme-dark') ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
function isDark() {
|
||||
return getScheme() === 'dark';
|
||||
}
|
||||
|
||||
function setCookie(scheme) {
|
||||
var path = config.cookiePath || '/';
|
||||
var domain = config.cookieDomain ? '; domain=' + config.cookieDomain : '';
|
||||
var maxAge = 60 * 60 * 24 * 365;
|
||||
document.cookie =
|
||||
cookieName +
|
||||
'=' +
|
||||
encodeURIComponent(scheme) +
|
||||
';path=' +
|
||||
path +
|
||||
domain +
|
||||
';max-age=' +
|
||||
maxAge +
|
||||
';SameSite=Lax';
|
||||
}
|
||||
|
||||
function persistScheme(scheme) {
|
||||
var i;
|
||||
|
||||
try {
|
||||
localStorage.setItem(storageKey, scheme);
|
||||
for (i = 0; i < blocksyKeys.length; i++) {
|
||||
localStorage.setItem(blocksyKeys[i], scheme);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
setCookie(scheme);
|
||||
}
|
||||
|
||||
function applyScheme(scheme, animate) {
|
||||
var root = document.documentElement;
|
||||
var isDarkMode = scheme === 'dark';
|
||||
var shouldAnimate = animate && enableAnimation;
|
||||
|
||||
if (shouldAnimate) {
|
||||
root.classList.add('blc-ldt-animate');
|
||||
window.setTimeout(function () {
|
||||
root.classList.remove('blc-ldt-animate');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
root.classList.remove('theme-dark', 'theme-light');
|
||||
root.classList.add(isDarkMode ? 'theme-dark' : 'theme-light');
|
||||
root.setAttribute('data-blc-scheme', scheme);
|
||||
root.style.colorScheme = scheme;
|
||||
|
||||
persistScheme(scheme);
|
||||
updateButton(isDarkMode);
|
||||
|
||||
try {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent('ct:color-mode:changed', {
|
||||
bubbles: true,
|
||||
detail: { mode: scheme },
|
||||
})
|
||||
);
|
||||
} catch (e) {}
|
||||
|
||||
if (config.isLoggedIn && config.ajaxUrl && config.nonce) {
|
||||
var body = new FormData();
|
||||
body.append('action', 'blc_ldt_save_scheme');
|
||||
body.append('nonce', config.nonce);
|
||||
body.append('scheme', scheme);
|
||||
fetch(config.ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' });
|
||||
}
|
||||
}
|
||||
|
||||
function updateButton(dark) {
|
||||
var i18n = config.i18n || {};
|
||||
btn.setAttribute('aria-pressed', dark ? 'true' : 'false');
|
||||
btn.setAttribute(
|
||||
'aria-label',
|
||||
dark ? i18n.light || 'Switch to light mode' : i18n.dark || 'Switch to dark mode'
|
||||
);
|
||||
btn.setAttribute(
|
||||
'title',
|
||||
dark ? i18n.lightLabel || 'Light mode' : i18n.darkLabel || 'Dark mode'
|
||||
);
|
||||
btn.classList.toggle('blc-ldt-toggle--dark', dark);
|
||||
}
|
||||
|
||||
function defaultScheme() {
|
||||
if (respectOs && prefersDark.matches) {
|
||||
return 'dark';
|
||||
}
|
||||
return 'light';
|
||||
}
|
||||
|
||||
btn.addEventListener('click', function () {
|
||||
applyScheme(isDark() ? 'light' : 'dark', true);
|
||||
});
|
||||
|
||||
document.addEventListener('ct:color-mode:changed', function (event) {
|
||||
if (!event.detail || !event.detail.mode) {
|
||||
return;
|
||||
}
|
||||
if (event.detail.mode !== 'light' && event.detail.mode !== 'dark') {
|
||||
return;
|
||||
}
|
||||
updateButton(event.detail.mode === 'dark');
|
||||
});
|
||||
|
||||
if (!getStoredScheme() && !document.documentElement.getAttribute('data-blc-scheme')) {
|
||||
applyScheme(defaultScheme(), false);
|
||||
} else {
|
||||
updateButton(document.documentElement.classList.contains('theme-dark'));
|
||||
}
|
||||
|
||||
if (respectOs) {
|
||||
prefersDark.addEventListener('change', function (event) {
|
||||
if (getStoredScheme()) {
|
||||
return;
|
||||
}
|
||||
applyScheme(event.matches ? 'dark' : 'light', true);
|
||||
});
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Blocksy Light/Dark Toggle
|
||||
* Plugin URI: https://github.com/example/blocksy-light-dark-toggle
|
||||
* Description: Floating light/dark mode toggle for the Blocksy theme (v2.1+). Integrates with Blocksy's native colour mode system.
|
||||
* Version: 1.2.1
|
||||
* Requires at least: 6.0
|
||||
* Requires PHP: 7.4
|
||||
* Author: Blocksy Light/Dark Toggle
|
||||
* License: GPL-2.0-or-later
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
* Text Domain: blocksy-light-dark-toggle
|
||||
*
|
||||
* @package Blocksy_Light_Dark_Toggle
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
define( 'BLC_LDT_VERSION', '1.2.1' );
|
||||
define( 'BLC_LDT_FILE', __FILE__ );
|
||||
define( 'BLC_LDT_DIR', plugin_dir_path( __FILE__ ) );
|
||||
define( 'BLC_LDT_URL', plugin_dir_url( __FILE__ ) );
|
||||
define( 'BLC_LDT_COOKIE', 'blc_ldt_scheme' );
|
||||
define( 'BLC_LDT_STORAGE', 'blc_ldt_scheme' );
|
||||
|
||||
require_once BLC_LDT_DIR . 'includes/class-blc-ldt-settings.php';
|
||||
require_once BLC_LDT_DIR . 'includes/class-blc-ldt.php';
|
||||
|
||||
BLC_LDT_Settings::init();
|
||||
BLC_LDT::init();
|
||||
@@ -0,0 +1,369 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin settings.
|
||||
*
|
||||
* @package Blocksy_Light_Dark_Toggle
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Settings registration and helpers.
|
||||
*/
|
||||
class BLC_LDT_Settings {
|
||||
|
||||
const OPTION = 'blc_ldt_settings';
|
||||
|
||||
/**
|
||||
* Default settings.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function defaults() {
|
||||
return array(
|
||||
'position' => 'bottom-right',
|
||||
'offset_x' => '1.25rem',
|
||||
'offset_y' => '1.25rem',
|
||||
'z_index' => 999999,
|
||||
'hide_header_switch' => true,
|
||||
'respect_os_preference' => true,
|
||||
'enable_animation' => true,
|
||||
'show_on_mobile' => true,
|
||||
'show_on_desktop' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize admin settings.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'admin_init', array( __CLASS__, 'register' ) );
|
||||
add_action( 'admin_menu', array( __CLASS__, 'add_menu' ) );
|
||||
add_filter( 'plugin_action_links_' . plugin_basename( BLC_LDT_FILE ), array( __CLASS__, 'plugin_links' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get merged settings.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function get() {
|
||||
$stored = get_option( self::OPTION, array() );
|
||||
if ( ! is_array( $stored ) ) {
|
||||
$stored = array();
|
||||
}
|
||||
|
||||
$settings = wp_parse_args( $stored, self::defaults() );
|
||||
|
||||
return apply_filters( 'blc_ldt_settings', $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single setting.
|
||||
*
|
||||
* @param string $key Setting key.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_value( $key ) {
|
||||
$settings = self::get();
|
||||
return isset( $settings[ $key ] ) ? $settings[ $key ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register settings with the Settings API.
|
||||
*/
|
||||
public static function register() {
|
||||
register_setting(
|
||||
'blc_ldt_settings_group',
|
||||
self::OPTION,
|
||||
array(
|
||||
'type' => 'array',
|
||||
'sanitize_callback' => array( __CLASS__, 'sanitize' ),
|
||||
'default' => self::defaults(),
|
||||
)
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
'blc_ldt_main',
|
||||
__( 'Toggle appearance', 'blocksy-light-dark-toggle' ),
|
||||
'__return_false',
|
||||
'blc-ldt-settings'
|
||||
);
|
||||
|
||||
self::add_field( 'position', __( 'Position', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_position' ) );
|
||||
self::add_field( 'offset_x', __( 'Horizontal offset', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_offset_x' ) );
|
||||
self::add_field( 'offset_y', __( 'Vertical offset', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_offset_y' ) );
|
||||
self::add_field( 'z_index', __( 'Z-index', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_z_index' ) );
|
||||
|
||||
add_settings_section(
|
||||
'blc_ldt_behavior',
|
||||
__( 'Behavior', 'blocksy-light-dark-toggle' ),
|
||||
array( __CLASS__, 'section_behavior' ),
|
||||
'blc-ldt-settings'
|
||||
);
|
||||
|
||||
self::add_field( 'hide_header_switch', __( 'Hide header colour switch', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_hide_header_switch' ), 'blc_ldt_behavior' );
|
||||
self::add_field( 'respect_os_preference', __( 'Follow system preference', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_respect_os_preference' ), 'blc_ldt_behavior' );
|
||||
self::add_field( 'enable_animation', __( 'Animate transitions', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_enable_animation' ), 'blc_ldt_behavior' );
|
||||
self::add_field( 'show_on_mobile', __( 'Show on mobile', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_show_on_mobile' ), 'blc_ldt_behavior' );
|
||||
self::add_field( 'show_on_desktop', __( 'Show on desktop', 'blocksy-light-dark-toggle' ), array( __CLASS__, 'field_show_on_desktop' ), 'blc_ldt_behavior' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a settings field.
|
||||
*
|
||||
* @param string $id Field ID.
|
||||
* @param string $title Field title.
|
||||
* @param callable $callback Render callback.
|
||||
* @param string $section Settings section.
|
||||
*/
|
||||
private static function add_field( $id, $title, $callback, $section = 'blc_ldt_main' ) {
|
||||
add_settings_field(
|
||||
'blc_ldt_' . $id,
|
||||
$title,
|
||||
$callback,
|
||||
'blc-ldt-settings',
|
||||
$section,
|
||||
array( 'id' => $id )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize submitted settings.
|
||||
*
|
||||
* @param array<string, mixed> $input Raw input.
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function sanitize( $input ) {
|
||||
$defaults = self::defaults();
|
||||
$output = self::defaults();
|
||||
|
||||
if ( ! is_array( $input ) ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
$positions = array( 'bottom-right', 'bottom-left', 'top-right', 'top-left' );
|
||||
$output['position'] = in_array( $input['position'] ?? '', $positions, true )
|
||||
? $input['position']
|
||||
: $defaults['position'];
|
||||
|
||||
$output['offset_x'] = self::sanitize_css_length( $input['offset_x'] ?? $defaults['offset_x'], $defaults['offset_x'] );
|
||||
$output['offset_y'] = self::sanitize_css_length( $input['offset_y'] ?? $defaults['offset_y'], $defaults['offset_y'] );
|
||||
$output['z_index'] = max( 1, min( 9999999, absint( $input['z_index'] ?? $defaults['z_index'] ) ) );
|
||||
|
||||
$output['hide_header_switch'] = ! empty( $input['hide_header_switch'] );
|
||||
$output['respect_os_preference'] = ! empty( $input['respect_os_preference'] );
|
||||
$output['enable_animation'] = ! empty( $input['enable_animation'] );
|
||||
$output['show_on_mobile'] = ! empty( $input['show_on_mobile'] );
|
||||
$output['show_on_desktop'] = ! empty( $input['show_on_desktop'] );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a CSS length value.
|
||||
*
|
||||
* @param string $value Raw value.
|
||||
* @param string $default Default value.
|
||||
* @return string
|
||||
*/
|
||||
private static function sanitize_css_length( $value, $default ) {
|
||||
$value = trim( (string) $value );
|
||||
if ( preg_match( '/^\d+(\.\d+)?(px|rem|em|vh|vw|%)$/', $value ) ) {
|
||||
return $value;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings page.
|
||||
*/
|
||||
public static function add_menu() {
|
||||
add_options_page(
|
||||
__( 'Light/Dark Toggle', 'blocksy-light-dark-toggle' ),
|
||||
__( 'Light/Dark Toggle', 'blocksy-light-dark-toggle' ),
|
||||
'manage_options',
|
||||
'blc-ldt-settings',
|
||||
array( __CLASS__, 'render_page' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings link on plugins list.
|
||||
*
|
||||
* @param string[] $links Plugin action links.
|
||||
* @return string[]
|
||||
*/
|
||||
public static function plugin_links( $links ) {
|
||||
$links[] = '<a href="' . esc_url( admin_url( 'options-general.php?page=blc-ldt-settings' ) ) . '">' . esc_html__( 'Settings', 'blocksy-light-dark-toggle' ) . '</a>';
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Behavior section description.
|
||||
*/
|
||||
public static function section_behavior() {
|
||||
echo '<p>' . esc_html__( 'These options control how the toggle interacts with Blocksy and visitor preferences.', 'blocksy-light-dark-toggle' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render settings page.
|
||||
*/
|
||||
public static function render_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$has_color_mode = BLC_LDT::has_blocksy_color_mode();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Blocksy Light/Dark Toggle', 'blocksy-light-dark-toggle' ); ?></h1>
|
||||
|
||||
<?php if ( ! BLC_LDT::is_target_theme() ) : ?>
|
||||
<div class="notice notice-warning"><p>
|
||||
<?php esc_html_e( 'Blocksy is not the active theme. The toggle only appears on the front end when Blocksy (or a child theme) is active.', 'blocksy-light-dark-toggle' ); ?>
|
||||
</p></div>
|
||||
<?php elseif ( ! $has_color_mode ) : ?>
|
||||
<div class="notice notice-info"><p>
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
__( 'For heavily customized sites, enable Blocksy\'s <strong>Colour Mode Switch</strong> extension and configure your dark palette in the Customizer. The plugin will then use your custom dark colors instead of the built-in fallback palette.', 'blocksy-light-dark-toggle' )
|
||||
);
|
||||
?>
|
||||
</p></div>
|
||||
<?php else : ?>
|
||||
<div class="notice notice-success"><p>
|
||||
<?php esc_html_e( 'Blocksy Colour Mode Switch is active. Your Customizer dark palette will be used.', 'blocksy-light-dark-toggle' ); ?>
|
||||
</p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields( 'blc_ldt_settings_group' );
|
||||
do_settings_sections( 'blc-ldt-settings' );
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a checkbox value from settings.
|
||||
*
|
||||
* @param string $id Setting ID.
|
||||
* @return bool
|
||||
*/
|
||||
private static function is_checked( $id ) {
|
||||
return (bool) self::get_value( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render position field.
|
||||
*/
|
||||
public static function field_position() {
|
||||
$value = self::get_value( 'position' );
|
||||
$options = array(
|
||||
'bottom-right' => __( 'Bottom right', 'blocksy-light-dark-toggle' ),
|
||||
'bottom-left' => __( 'Bottom left', 'blocksy-light-dark-toggle' ),
|
||||
'top-right' => __( 'Top right', 'blocksy-light-dark-toggle' ),
|
||||
'top-left' => __( 'Top left', 'blocksy-light-dark-toggle' ),
|
||||
);
|
||||
?>
|
||||
<select name="<?php echo esc_attr( self::OPTION ); ?>[position]">
|
||||
<?php foreach ( $options as $key => $label ) : ?>
|
||||
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value, $key ); ?>><?php echo esc_html( $label ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render horizontal offset field.
|
||||
*/
|
||||
public static function field_offset_x() {
|
||||
?>
|
||||
<input type="text" class="small-text" name="<?php echo esc_attr( self::OPTION ); ?>[offset_x]" value="<?php echo esc_attr( (string) self::get_value( 'offset_x' ) ); ?>">
|
||||
<p class="description"><?php esc_html_e( 'CSS value, e.g. 1.25rem or 20px', 'blocksy-light-dark-toggle' ); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render vertical offset field.
|
||||
*/
|
||||
public static function field_offset_y() {
|
||||
?>
|
||||
<input type="text" class="small-text" name="<?php echo esc_attr( self::OPTION ); ?>[offset_y]" value="<?php echo esc_attr( (string) self::get_value( 'offset_y' ) ); ?>">
|
||||
<p class="description"><?php esc_html_e( 'CSS value, e.g. 1.25rem or 20px', 'blocksy-light-dark-toggle' ); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render z-index field.
|
||||
*/
|
||||
public static function field_z_index() {
|
||||
?>
|
||||
<input type="number" class="small-text" min="1" max="9999999" name="<?php echo esc_attr( self::OPTION ); ?>[z_index]" value="<?php echo esc_attr( (string) self::get_value( 'z_index' ) ); ?>">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render hide header switch field.
|
||||
*/
|
||||
public static function field_hide_header_switch() {
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[hide_header_switch]" value="1" <?php checked( self::is_checked( 'hide_header_switch' ) ); ?>>
|
||||
<?php esc_html_e( 'Hide Blocksy header colour switch to avoid duplicate toggles', 'blocksy-light-dark-toggle' ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render respect OS preference field.
|
||||
*/
|
||||
public static function field_respect_os_preference() {
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[respect_os_preference]" value="1" <?php checked( self::is_checked( 'respect_os_preference' ) ); ?>>
|
||||
<?php esc_html_e( 'Use system light/dark preference on first visit (before the visitor toggles)', 'blocksy-light-dark-toggle' ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render animation field.
|
||||
*/
|
||||
public static function field_enable_animation() {
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[enable_animation]" value="1" <?php checked( self::is_checked( 'enable_animation' ) ); ?>>
|
||||
<?php esc_html_e( 'Smooth colour transition when switching modes', 'blocksy-light-dark-toggle' ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render show on mobile field.
|
||||
*/
|
||||
public static function field_show_on_mobile() {
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[show_on_mobile]" value="1" <?php checked( self::is_checked( 'show_on_mobile' ) ); ?>>
|
||||
<?php esc_html_e( 'Show the floating toggle on mobile screens', 'blocksy-light-dark-toggle' ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render show on desktop field.
|
||||
*/
|
||||
public static function field_show_on_desktop() {
|
||||
?>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr( self::OPTION ); ?>[show_on_desktop]" value="1" <?php checked( self::is_checked( 'show_on_desktop' ) ); ?>>
|
||||
<?php esc_html_e( 'Show the floating toggle on desktop screens', 'blocksy-light-dark-toggle' ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,413 @@
|
||||
<?php
|
||||
/**
|
||||
* Main plugin bootstrap.
|
||||
*
|
||||
* @package Blocksy_Light_Dark_Toggle
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Blocksy Light/Dark Toggle plugin.
|
||||
*/
|
||||
class BLC_LDT {
|
||||
|
||||
/**
|
||||
* Blocksy localStorage keys used for colour mode.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
const BLOCKSY_STORAGE_KEYS = array( 'blocksyColorMode', 'blocksy_color_mode', 'theme' );
|
||||
|
||||
/**
|
||||
* Initialize hooks.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'plugins_loaded', array( __CLASS__, 'bootstrap' ) );
|
||||
add_action( 'admin_notices', array( __CLASS__, 'admin_theme_notice' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load frontend assets when Blocksy (or a child) is active.
|
||||
*/
|
||||
public static function bootstrap() {
|
||||
if ( ! self::is_target_theme() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ) );
|
||||
add_action( 'wp_footer', array( __CLASS__, 'render_toggle' ), 5 );
|
||||
add_action( 'wp_head', array( __CLASS__, 'inline_preference_script' ), 0 );
|
||||
add_action( 'wp_head', array( __CLASS__, 'inline_position_styles' ), 20 );
|
||||
|
||||
add_action( 'wp_ajax_blc_ldt_save_scheme', array( __CLASS__, 'ajax_save_scheme' ) );
|
||||
add_action( 'wp_ajax_nopriv_blc_ldt_save_scheme', array( __CLASS__, 'ajax_save_scheme' ) );
|
||||
add_filter( 'body_class', array( __CLASS__, 'body_class' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Blocksy (or a child of it) is active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_target_theme() {
|
||||
$theme = wp_get_theme();
|
||||
return 'blocksy' === $theme->get_template();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Blocksy's native Colour Mode Switch extension is active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function has_blocksy_color_mode() {
|
||||
$extensions = get_option( 'blocksy_active_extensions', array() );
|
||||
if ( is_array( $extensions ) && in_array( 'color-mode-switch', $extensions, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( function_exists( 'blc_get_extensions_status' ) ) {
|
||||
$status = blc_get_extensions_status();
|
||||
if ( is_array( $status ) && ! empty( $status['color-mode-switch'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (bool) apply_filters( 'blc_ldt_has_blocksy_color_mode', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the toggle should render on the current request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function should_render() {
|
||||
if ( is_admin() || wp_doing_ajax() || is_customize_preview() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = BLC_LDT_Settings::get();
|
||||
if ( empty( $settings['show_on_mobile'] ) && empty( $settings['show_on_desktop'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) apply_filters( 'blc_ldt_should_render', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Warn in admin if the theme is not supported.
|
||||
*/
|
||||
public static function admin_theme_notice() {
|
||||
if ( self::is_target_theme() || ! current_user_can( 'switch_themes' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
|
||||
if ( $screen && 'plugins' !== $screen->id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="notice notice-warning"><p>';
|
||||
echo esc_html__(
|
||||
'Blocksy Light/Dark Toggle is active but Blocksy is not the current theme. The toggle only appears with Blocksy.',
|
||||
'blocksy-light-dark-toggle'
|
||||
);
|
||||
echo '</p></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent flash of wrong theme by applying Blocksy classes before paint.
|
||||
*/
|
||||
public static function inline_preference_script() {
|
||||
if ( ! self::should_render() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scheme = self::get_initial_scheme();
|
||||
$settings = BLC_LDT_Settings::get();
|
||||
$storage_keys = array_merge( array( BLC_LDT_STORAGE ), self::BLOCKSY_STORAGE_KEYS );
|
||||
|
||||
?>
|
||||
<script id="blc-ldt-init">
|
||||
(function () {
|
||||
var storageKeys = <?php echo wp_json_encode( $storage_keys ); ?>;
|
||||
var cookieName = <?php echo wp_json_encode( BLC_LDT_COOKIE ); ?>;
|
||||
var serverScheme = <?php echo wp_json_encode( $scheme ); ?>;
|
||||
var respectOs = <?php echo wp_json_encode( ! empty( $settings['respect_os_preference'] ) ); ?>;
|
||||
var stored = '';
|
||||
|
||||
function readStored() {
|
||||
var i, val;
|
||||
try {
|
||||
for (i = 0; i < storageKeys.length; i++) {
|
||||
val = localStorage.getItem(storageKeys[i]);
|
||||
if (val === 'dark' || val === 'light') {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (document.cookie.indexOf(cookieName + '=') !== -1) {
|
||||
var match = document.cookie.match(new RegExp(cookieName + '=([^;]+)'));
|
||||
if (match) {
|
||||
val = decodeURIComponent(match[1]);
|
||||
if (val === 'dark' || val === 'light') {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function applyScheme(scheme) {
|
||||
var root = document.documentElement;
|
||||
root.classList.remove('theme-dark', 'theme-light');
|
||||
root.classList.add(scheme === 'dark' ? 'theme-dark' : 'theme-light');
|
||||
root.setAttribute('data-blc-scheme', scheme);
|
||||
root.style.colorScheme = scheme;
|
||||
}
|
||||
|
||||
function resolveScheme() {
|
||||
stored = readStored();
|
||||
if (stored) {
|
||||
return stored;
|
||||
}
|
||||
if (serverScheme) {
|
||||
return serverScheme;
|
||||
}
|
||||
if (respectOs && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return 'dark';
|
||||
}
|
||||
return 'light';
|
||||
}
|
||||
|
||||
applyScheme(resolveScheme());
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output dynamic positioning and visibility CSS from settings.
|
||||
*/
|
||||
public static function inline_position_styles() {
|
||||
if ( ! self::should_render() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = BLC_LDT_Settings::get();
|
||||
$position = $settings['position'];
|
||||
$offset_x = $settings['offset_x'];
|
||||
$offset_y = $settings['offset_y'];
|
||||
$z_index = (int) $settings['z_index'];
|
||||
|
||||
$rules = array(
|
||||
'z-index:' . $z_index,
|
||||
);
|
||||
|
||||
switch ( $position ) {
|
||||
case 'bottom-left':
|
||||
$rules[] = 'left:' . $offset_x;
|
||||
$rules[] = 'right:auto';
|
||||
$rules[] = 'bottom:' . $offset_y;
|
||||
$rules[] = 'top:auto';
|
||||
break;
|
||||
case 'top-right':
|
||||
$rules[] = 'right:' . $offset_x;
|
||||
$rules[] = 'left:auto';
|
||||
$rules[] = 'top:' . $offset_y;
|
||||
$rules[] = 'bottom:auto';
|
||||
break;
|
||||
case 'top-left':
|
||||
$rules[] = 'left:' . $offset_x;
|
||||
$rules[] = 'right:auto';
|
||||
$rules[] = 'top:' . $offset_y;
|
||||
$rules[] = 'bottom:auto';
|
||||
break;
|
||||
default:
|
||||
$rules[] = 'right:' . $offset_x;
|
||||
$rules[] = 'left:auto';
|
||||
$rules[] = 'bottom:' . $offset_y;
|
||||
$rules[] = 'top:auto';
|
||||
break;
|
||||
}
|
||||
|
||||
$css = '#blc-ldt-toggle{' . implode( ';', $rules ) . ';}';
|
||||
|
||||
if ( empty( $settings['show_on_mobile'] ) ) {
|
||||
$css .= '@media (max-width:689px){#blc-ldt-toggle{display:none!important;}}';
|
||||
}
|
||||
|
||||
if ( empty( $settings['show_on_desktop'] ) ) {
|
||||
$css .= '@media (min-width:690px){#blc-ldt-toggle{display:none!important;}}';
|
||||
}
|
||||
|
||||
if ( ! empty( $settings['hide_header_switch'] ) ) {
|
||||
$css .= '[data-id="color-mode-switch"],[data-shortcut="color-mode-switch"],.ct-color-switch,.ct-header-color-switch{display:none!important;}';
|
||||
}
|
||||
|
||||
echo '<style id="blc-ldt-position">' . esc_html( $css ) . '</style>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve saved scheme for first paint (cookie or user meta only).
|
||||
*
|
||||
* @return string light|dark|empty string when none saved.
|
||||
*/
|
||||
public static function get_initial_scheme() {
|
||||
if ( isset( $_COOKIE[ BLC_LDT_COOKIE ] ) ) {
|
||||
$cookie = sanitize_key( wp_unslash( $_COOKIE[ BLC_LDT_COOKIE ] ) );
|
||||
if ( in_array( $cookie, array( 'light', 'dark' ), true ) ) {
|
||||
return apply_filters( 'blc_ldt_initial_scheme', $cookie );
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_user_logged_in() ) {
|
||||
$meta = get_user_meta( get_current_user_id(), BLC_LDT_STORAGE, true );
|
||||
if ( in_array( $meta, array( 'light', 'dark' ), true ) ) {
|
||||
return apply_filters( 'blc_ldt_initial_scheme', $meta );
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'blc_ldt_initial_scheme', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles and toggle script.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
if ( ! self::should_render() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! self::has_blocksy_color_mode() ) {
|
||||
wp_enqueue_style(
|
||||
'blc-ldt-fallback',
|
||||
BLC_LDT_URL . 'assets/css/dark-fallback.css',
|
||||
array(),
|
||||
BLC_LDT_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'blc-ldt-overrides',
|
||||
BLC_LDT_URL . 'assets/css/dark-overrides.css',
|
||||
self::has_blocksy_color_mode() ? array() : array( 'blc-ldt-fallback' ),
|
||||
BLC_LDT_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'blc-ldt-toggle',
|
||||
BLC_LDT_URL . 'assets/css/toggle.css',
|
||||
array( 'blc-ldt-overrides' ),
|
||||
BLC_LDT_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'blc-ldt-toggle',
|
||||
BLC_LDT_URL . 'assets/js/toggle.js',
|
||||
array(),
|
||||
BLC_LDT_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
$settings = BLC_LDT_Settings::get();
|
||||
|
||||
wp_localize_script(
|
||||
'blc-ldt-toggle',
|
||||
'blcLdt',
|
||||
array(
|
||||
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'blc_ldt_save' ),
|
||||
'storageKey' => BLC_LDT_STORAGE,
|
||||
'cookieName' => BLC_LDT_COOKIE,
|
||||
'cookiePath' => COOKIEPATH ? COOKIEPATH : '/',
|
||||
'cookieDomain' => COOKIE_DOMAIN,
|
||||
'isLoggedIn' => is_user_logged_in(),
|
||||
'hasBlocksyColorMode' => self::has_blocksy_color_mode(),
|
||||
'blocksyStorageKeys' => self::BLOCKSY_STORAGE_KEYS,
|
||||
'respectOsPreference' => ! empty( $settings['respect_os_preference'] ),
|
||||
'enableAnimation' => ! empty( $settings['enable_animation'] ),
|
||||
'i18n' => array(
|
||||
'light' => __( 'Switch to light mode', 'blocksy-light-dark-toggle' ),
|
||||
'dark' => __( 'Switch to dark mode', 'blocksy-light-dark-toggle' ),
|
||||
'lightLabel' => __( 'Light', 'blocksy-light-dark-toggle' ),
|
||||
'darkLabel' => __( 'Dark', 'blocksy-light-dark-toggle' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output floating toggle button.
|
||||
*/
|
||||
public static function render_toggle() {
|
||||
if ( ! self::should_render() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$saved = self::get_initial_scheme();
|
||||
$is_dark = 'dark' === $saved;
|
||||
?>
|
||||
<button
|
||||
type="button"
|
||||
id="blc-ldt-toggle"
|
||||
class="blc-ldt-toggle<?php echo $is_dark ? ' blc-ldt-toggle--dark' : ''; ?>"
|
||||
aria-pressed="<?php echo $is_dark ? 'true' : 'false'; ?>"
|
||||
aria-label="<?php echo esc_attr( $is_dark ? __( 'Switch to light mode', 'blocksy-light-dark-toggle' ) : __( 'Switch to dark mode', 'blocksy-light-dark-toggle' ) ); ?>"
|
||||
title="<?php echo esc_attr( $is_dark ? __( 'Light mode', 'blocksy-light-dark-toggle' ) : __( 'Dark mode', 'blocksy-light-dark-toggle' ) ); ?>"
|
||||
>
|
||||
<span class="blc-ldt-toggle__track" aria-hidden="true">
|
||||
<span class="blc-ldt-toggle__thumb"></span>
|
||||
</span>
|
||||
<span class="blc-ldt-toggle__icon blc-ldt-toggle__icon--sun" aria-hidden="true">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
|
||||
</span>
|
||||
<span class="blc-ldt-toggle__icon blc-ldt-toggle__icon--moon" aria-hidden="true">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||||
</span>
|
||||
</button>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Add helper body classes for page-specific dark-mode fixes.
|
||||
*
|
||||
* @param string[] $classes Body classes.
|
||||
* @return string[]
|
||||
*/
|
||||
public static function body_class( $classes ) {
|
||||
if ( is_admin() ) {
|
||||
return $classes;
|
||||
}
|
||||
|
||||
if ( is_page( 'codes' ) ) {
|
||||
$classes[] = 'blc-ldt-page-codes';
|
||||
}
|
||||
|
||||
if ( is_page( array( 'reservations', 'studio-boeken', 'reserveren', 'reserveringen', 'booking', 'planning' ) ) ) {
|
||||
$classes[] = 'blc-ldt-page-reservations';
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist preference for logged-in users.
|
||||
*/
|
||||
public static function ajax_save_scheme() {
|
||||
check_ajax_referer( 'blc_ldt_save', 'nonce' );
|
||||
|
||||
$scheme = isset( $_POST['scheme'] ) ? sanitize_key( wp_unslash( $_POST['scheme'] ) ) : '';
|
||||
if ( ! in_array( $scheme, array( 'light', 'dark' ), true ) ) {
|
||||
wp_send_json_error( array( 'message' => 'Invalid scheme' ), 400 );
|
||||
}
|
||||
|
||||
if ( is_user_logged_in() ) {
|
||||
update_user_meta( get_current_user_id(), BLC_LDT_STORAGE, $scheme );
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Change the font color of the text in the upper grey blocks */
|
||||
.upper-grey-blocks {
|
||||
color: #333; /* Darker color */
|
||||
}
|
||||
|
||||
/* If the text is inside a specific element, you can target it directly */
|
||||
.upper-grey-blocks p {
|
||||
color: #333; /* Darker color */
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* Uninstall cleanup.
|
||||
*
|
||||
* @package Blocksy_Light_Dark_Toggle
|
||||
*/
|
||||
|
||||
defined( 'WP_UNINSTALL_PLUGIN' ) || exit;
|
||||
|
||||
delete_option( 'blc_ldt_settings' );
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM {$wpdb->usermeta} WHERE meta_key = %s",
|
||||
'blc_ldt_scheme'
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user