colorsbymax 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +2 -0
- package/dist/{ThemeSwitcher-CFtLm7PM.js → ThemeSwitcher-Bl_5Us5y.js} +28 -16
- package/dist/auto.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/types/index.d.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
What changed in each colorsbymax release. Update with `npm install colorsbymax@latest`.
|
|
4
4
|
|
|
5
|
+
## 0.3.1 (2026-09-25)
|
|
6
|
+
|
|
7
|
+
- **`colourLogo` config option:** start with "Colour the logo too" on, for sites whose logo is drawn in the theme's colours. It's off by default, so logos keep their own colours, and visitors can still change it in settings. It also applies when the switcher is hidden. The colorsbymax site turns it on for its wordmark.
|
|
8
|
+
|
|
5
9
|
## 0.3.0 (2026-09-25)
|
|
6
10
|
|
|
7
11
|
- **Dark mode for every site, on every load.** The mode now lives in the theme provider: a saved Dark (or Auto on a dark device) turns the whole site dark as soon as it loads, not only when the mode is changed, and it keeps working when the switcher is hidden. Before, the panel could go dark while the site stayed light. Sites without a dark mode of their own get one: every theme's dark twin re-colours the page, contrast-checked.
|
package/README.md
CHANGED
|
@@ -326,6 +326,8 @@ Without a `siteName`, the site group is named from the page's `og:site_name`, it
|
|
|
326
326
|
position: 'bottom-right', // where the button starts: bottom-right (default), bottom-left,
|
|
327
327
|
// top-left, or top-right (just under a floating nav bar)
|
|
328
328
|
hidden: import.meta.env.PROD, // hide the button (the theme still applies), e.g. in production
|
|
329
|
+
colourLogo: false, // themes colour the logo too, for first-time visitors (default
|
|
330
|
+
// false: it keeps its own colours); visitors can change it
|
|
329
331
|
intro: true, // the button pops in with a burst of the theme's colours a moment
|
|
330
332
|
// after the page loads (default); reduced motion fades it in
|
|
331
333
|
}
|
|
@@ -1709,24 +1709,28 @@ var PANEL_PRESETS = [
|
|
|
1709
1709
|
height: "full"
|
|
1710
1710
|
}
|
|
1711
1711
|
];
|
|
1712
|
-
/**
|
|
1713
|
-
|
|
1712
|
+
/**
|
|
1713
|
+
* @param {string} storageKey
|
|
1714
|
+
* @param {PanelSettings} [defaults] the site's starting settings (see the config's colourLogo)
|
|
1715
|
+
* @returns {PanelSettings}
|
|
1716
|
+
*/
|
|
1717
|
+
function loadSettings(storageKey, defaults = DEFAULT_SETTINGS) {
|
|
1714
1718
|
try {
|
|
1715
1719
|
const saved = JSON.parse(window.localStorage.getItem(`${storageKey}:settings`) || "null");
|
|
1716
|
-
if (!saved || typeof saved !== "object") return
|
|
1717
|
-
const out = { ...
|
|
1718
|
-
for (const [key, fallback] of Object.entries(
|
|
1720
|
+
if (!saved || typeof saved !== "object") return defaults;
|
|
1721
|
+
const out = { ...defaults };
|
|
1722
|
+
for (const [key, fallback] of Object.entries(defaults)) if (typeof saved[key] === typeof fallback) out[key] = saved[key];
|
|
1719
1723
|
if (![
|
|
1720
1724
|
"light",
|
|
1721
1725
|
"dark",
|
|
1722
1726
|
"system"
|
|
1723
|
-
].includes(out.mode)) out.mode =
|
|
1727
|
+
].includes(out.mode)) out.mode = defaults.mode;
|
|
1724
1728
|
const size = (v) => typeof v === "number" && v > 0 && v < 1e4;
|
|
1725
1729
|
out.panelWidth = size(saved.panelWidth) ? saved.panelWidth : null;
|
|
1726
1730
|
out.panelHeight = size(saved.panelHeight) || saved.panelHeight === "full" ? saved.panelHeight : null;
|
|
1727
1731
|
return out;
|
|
1728
1732
|
} catch {
|
|
1729
|
-
return
|
|
1733
|
+
return defaults;
|
|
1730
1734
|
}
|
|
1731
1735
|
}
|
|
1732
1736
|
function saveSettings(storageKey, settings) {
|
|
@@ -1908,6 +1912,8 @@ var newId = () => `custom-${Date.now().toString(36)}-${Math.random().toString(36
|
|
|
1908
1912
|
* Where each token is used on this site, shown in the editors
|
|
1909
1913
|
* @property {boolean} [scrollbars] Colour the page's scrollbars from the theme (default true)
|
|
1910
1914
|
* @property {() => Promise<any>} [pdf] Enables PDF uploads: pass `loadPdf` from 'colorsbymax/pdf'
|
|
1915
|
+
* @property {boolean} [colourLogo] Whether themes colour the site's logo for a first-time visitor
|
|
1916
|
+
* (default false: the logo keeps its own colours). Visitors can still change it in settings.
|
|
1911
1917
|
* @property {boolean} [intro] Bring the colour button in with a short pop and burst of the theme's
|
|
1912
1918
|
* colours, a moment after the page loads (default true). Reduced motion fades it in instead.
|
|
1913
1919
|
* @property {boolean} [hidden] Hide the colour button and panel; the theme still applies. Use
|
|
@@ -2009,7 +2015,11 @@ function ThemeProvider({ config = {}, children }) {
|
|
|
2009
2015
|
recolourer.current = null;
|
|
2010
2016
|
};
|
|
2011
2017
|
}, [recolourMode]);
|
|
2012
|
-
const
|
|
2018
|
+
const settingDefaults = useMemo(() => ({
|
|
2019
|
+
...DEFAULT_SETTINGS,
|
|
2020
|
+
colourLogo: Boolean(initialConfig.colourLogo)
|
|
2021
|
+
}), [initialConfig]);
|
|
2022
|
+
const [logoColouring, setLogoColouring] = useState(() => loadSettings(storageKey, settingDefaults).colourLogo);
|
|
2013
2023
|
useLayoutEffect(() => {
|
|
2014
2024
|
recolourer.current?.setLogoColouring(logoColouring);
|
|
2015
2025
|
}, [logoColouring, pageColours]);
|
|
@@ -2077,7 +2087,7 @@ function ThemeProvider({ config = {}, children }) {
|
|
|
2077
2087
|
tokens: theme.tokens
|
|
2078
2088
|
} : s.snapshot
|
|
2079
2089
|
})), []);
|
|
2080
|
-
const [modeSetting, setModeSetting] = useState(() => loadSettings(storageKey).mode);
|
|
2090
|
+
const [modeSetting, setModeSetting] = useState(() => loadSettings(storageKey, settingDefaults).mode);
|
|
2081
2091
|
const prefersDark = usePrefersDark();
|
|
2082
2092
|
const mode = modeSetting === "system" ? prefersDark ? "dark" : "light" : modeSetting;
|
|
2083
2093
|
const modeRef = useRef(mode);
|
|
@@ -2090,10 +2100,10 @@ function ThemeProvider({ config = {}, children }) {
|
|
|
2090
2100
|
].includes(next)) return;
|
|
2091
2101
|
setModeSetting(next);
|
|
2092
2102
|
saveSettings(storageKey, {
|
|
2093
|
-
...loadSettings(storageKey),
|
|
2103
|
+
...loadSettings(storageKey, settingDefaults),
|
|
2094
2104
|
mode: next
|
|
2095
2105
|
});
|
|
2096
|
-
}, [storageKey]);
|
|
2106
|
+
}, [storageKey, settingDefaults]);
|
|
2097
2107
|
useLayoutEffect(() => {
|
|
2098
2108
|
if (base.custom) return;
|
|
2099
2109
|
if (mode === "dark" && !isDarkTheme(base.tokens)) {
|
|
@@ -2135,6 +2145,8 @@ function ThemeProvider({ config = {}, children }) {
|
|
|
2135
2145
|
}, [setMode]);
|
|
2136
2146
|
const api = {
|
|
2137
2147
|
state,
|
|
2148
|
+
/** The switcher's starting settings for this site. */
|
|
2149
|
+
settingDefaults,
|
|
2138
2150
|
/** The mode in effect ('light' or 'dark'), the visitor's setting ('system' follows the device), and a setter. */
|
|
2139
2151
|
mode,
|
|
2140
2152
|
modeSetting,
|
|
@@ -5711,7 +5723,7 @@ function ThemeSwitcher() {
|
|
|
5711
5723
|
return mount && createPortal(/* @__PURE__ */ jsx(Switcher, {}), mount);
|
|
5712
5724
|
}
|
|
5713
5725
|
function Switcher() {
|
|
5714
|
-
const { issues, storageKey, tokens, position: requested, setLogoColouring, intro, mode, modeSetting, setMode } = useTheme();
|
|
5726
|
+
const { issues, storageKey, tokens, position: requested, setLogoColouring, intro, mode, modeSetting, setMode, settingDefaults } = useTheme();
|
|
5715
5727
|
const position = CORNERS[requested] ? requested : "bottom-right";
|
|
5716
5728
|
const [open, setOpen] = useState(false);
|
|
5717
5729
|
const [arrived, setArrived] = useState(!intro);
|
|
@@ -5737,7 +5749,7 @@ function Switcher() {
|
|
|
5737
5749
|
}, BURST_TIME);
|
|
5738
5750
|
return () => clearTimeout(timer);
|
|
5739
5751
|
}, [burst]);
|
|
5740
|
-
const [settings, setSettings] = useState(() => loadSettings(storageKey));
|
|
5752
|
+
const [settings, setSettings] = useState(() => loadSettings(storageKey, settingDefaults));
|
|
5741
5753
|
useEffect(() => setLogoColouring(settings.colourLogo), [settings.colourLogo, setLogoColouring]);
|
|
5742
5754
|
const [auditOn, setAuditOn] = useState(false);
|
|
5743
5755
|
const [findings, setFindings] = useState([]);
|
|
@@ -5913,7 +5925,7 @@ function Switcher() {
|
|
|
5913
5925
|
const storeSettings = (next) => {
|
|
5914
5926
|
saveSettings(storageKey, {
|
|
5915
5927
|
...next,
|
|
5916
|
-
mode: loadSettings(storageKey).mode
|
|
5928
|
+
mode: loadSettings(storageKey, settingDefaults).mode
|
|
5917
5929
|
});
|
|
5918
5930
|
return next;
|
|
5919
5931
|
};
|
|
@@ -5944,8 +5956,8 @@ function Switcher() {
|
|
|
5944
5956
|
}));
|
|
5945
5957
|
},
|
|
5946
5958
|
reset: () => {
|
|
5947
|
-
setMode(
|
|
5948
|
-
setSettings(storeSettings(
|
|
5959
|
+
setMode(settingDefaults.mode);
|
|
5960
|
+
setSettings(storeSettings(settingDefaults));
|
|
5949
5961
|
},
|
|
5950
5962
|
resetButton: saved ? resetPosition : null
|
|
5951
5963
|
};
|
package/dist/auto.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as ThemeProvider, t as ThemeSwitcher } from "./ThemeSwitcher-
|
|
1
|
+
import { o as ThemeProvider, t as ThemeSwitcher } from "./ThemeSwitcher-Bl_5Us5y.js";
|
|
2
2
|
import { createElement } from "react";
|
|
3
3
|
import { createRoot } from "react-dom/client";
|
|
4
4
|
//#region src/auto.js
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as PAIRINGS, C as TOKEN_KEYS, D as MIN_CONTRAST_NON_TEXT, E as MIN_CONTRAST_LARGE_TEXT, F as contrastRatio, I as normalizeHex, M as checkTheme, N as fixAll, O as MIN_CONTRAST_TEXT, P as suggestFix, S as TOKEN_GROUPS, T as deriveAppTokens, _ as darkTokens, a as themeFromPalette, b as BASE_TOKENS, c as useTheme, d as DEFAULT_SETTINGS, f as collectColors, g as themeFromRoles, h as suggestThemes, i as rolesFromPalette, j as checkRamp, k as MIN_RAMP_STEP_DELTA_E, l as DEFAULT_STORAGE_KEY, m as inferRoles, n as coloursFromFile, o as ThemeProvider, p as detectSiteName, r as dominantColours, s as applyTokens, t as ThemeSwitcher, u as prePaintScript, v as isDarkTheme, w as completeTokens, x as PRESETS, y as toDark } from "./ThemeSwitcher-
|
|
1
|
+
import { A as PAIRINGS, C as TOKEN_KEYS, D as MIN_CONTRAST_NON_TEXT, E as MIN_CONTRAST_LARGE_TEXT, F as contrastRatio, I as normalizeHex, M as checkTheme, N as fixAll, O as MIN_CONTRAST_TEXT, P as suggestFix, S as TOKEN_GROUPS, T as deriveAppTokens, _ as darkTokens, a as themeFromPalette, b as BASE_TOKENS, c as useTheme, d as DEFAULT_SETTINGS, f as collectColors, g as themeFromRoles, h as suggestThemes, i as rolesFromPalette, j as checkRamp, k as MIN_RAMP_STEP_DELTA_E, l as DEFAULT_STORAGE_KEY, m as inferRoles, n as coloursFromFile, o as ThemeProvider, p as detectSiteName, r as dominantColours, s as applyTokens, t as ThemeSwitcher, u as prePaintScript, v as isDarkTheme, w as completeTokens, x as PRESETS, y as toDark } from "./ThemeSwitcher-Bl_5Us5y.js";
|
|
2
2
|
export { BASE_TOKENS, DEFAULT_SETTINGS, DEFAULT_STORAGE_KEY, MIN_CONTRAST_LARGE_TEXT, MIN_CONTRAST_NON_TEXT, MIN_CONTRAST_TEXT, MIN_RAMP_STEP_DELTA_E, PAIRINGS, PRESETS, TOKEN_GROUPS, TOKEN_KEYS, ThemeProvider, ThemeSwitcher, applyTokens, checkRamp, checkTheme, collectColors, coloursFromFile, completeTokens, contrastRatio, darkTokens, deriveAppTokens, detectSiteName, dominantColours, fixAll, inferRoles, isDarkTheme, normalizeHex, prePaintScript, rolesFromPalette, suggestFix, suggestThemes, themeFromPalette, themeFromRoles, toDark, useTheme };
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -90,6 +90,11 @@ export interface ColorsByMaxConfig {
|
|
|
90
90
|
* the page loads (default true). With reduced motion it fades in instead.
|
|
91
91
|
*/
|
|
92
92
|
intro?: boolean
|
|
93
|
+
/**
|
|
94
|
+
* Whether themes colour the site's logo for a first-time visitor (default false: the logo keeps
|
|
95
|
+
* its own colours). Visitors can still change it in the panel's settings.
|
|
96
|
+
*/
|
|
97
|
+
colourLogo?: boolean
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
export interface ThemeProviderProps {
|