hsl to rgba not as effect but immediately, so all components have the correct theme applied at once
This commit is contained in:
parent
40bb1ec28a
commit
4960df370c
|
@ -1,5 +1,5 @@
|
||||||
import {useStoredObjectState} from './useStoredState.ts';
|
import {useStoredObjectState} from './useStoredState.ts';
|
||||||
import {createContext, ReactNode, useContext, useEffect, useRef, useState} from 'react';
|
import {createContext, ReactNode, useContext, useMemo, useRef, useState} from 'react';
|
||||||
|
|
||||||
type HSL = {
|
type HSL = {
|
||||||
h: number;
|
h: number;
|
||||||
|
@ -14,6 +14,15 @@ export type HslTheme = {
|
||||||
tertiary: HSL;
|
tertiary: HSL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Rgba = Uint8ClampedArray;
|
||||||
|
|
||||||
|
export type RgbaTheme = {
|
||||||
|
primary: Rgba;
|
||||||
|
secondary: Rgba;
|
||||||
|
background: Rgba;
|
||||||
|
tertiary: Rgba;
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const rootStyle = document.querySelector(':root')?.style;
|
const rootStyle = document.querySelector(':root')?.style;
|
||||||
|
|
||||||
|
@ -76,22 +85,6 @@ export function getRandomTheme(): HslTheme {
|
||||||
return {background, primary, secondary, tertiary};
|
return {background, primary, secondary, tertiary};
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTheme(theme: HslTheme) {
|
|
||||||
console.log('apply theme', theme);
|
|
||||||
rootStyle.setProperty('--color-primary', hslToString(theme.primary));
|
|
||||||
rootStyle.setProperty('--color-secondary', hslToString(theme.secondary));
|
|
||||||
rootStyle.setProperty('--color-background', hslToString(theme.background));
|
|
||||||
}
|
|
||||||
|
|
||||||
type Rgba = Uint8ClampedArray;
|
|
||||||
|
|
||||||
export type RgbaTheme = {
|
|
||||||
primary: Rgba;
|
|
||||||
secondary: Rgba;
|
|
||||||
background: Rgba;
|
|
||||||
tertiary: Rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dummyRgbaTheme: RgbaTheme = {
|
const dummyRgbaTheme: RgbaTheme = {
|
||||||
primary: new Uint8ClampedArray([0, 0, 0, 0]),
|
primary: new Uint8ClampedArray([0, 0, 0, 0]),
|
||||||
secondary: new Uint8ClampedArray([0, 0, 0, 0]),
|
secondary: new Uint8ClampedArray([0, 0, 0, 0]),
|
||||||
|
@ -105,7 +98,6 @@ function hslToRgba(context: CanvasRenderingContext2D, color: HSL) {
|
||||||
return context.getImageData(0, 0, 1, 1).data;
|
return context.getImageData(0, 0, 1, 1).data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const HslThemeContext = createContext<null | {
|
const HslThemeContext = createContext<null | {
|
||||||
hslTheme: HslTheme,
|
hslTheme: HslTheme,
|
||||||
setHslTheme: (mutator: (oldState: HslTheme) => HslTheme) => void
|
setHslTheme: (mutator: (oldState: HslTheme) => HslTheme) => void
|
||||||
|
@ -128,34 +120,41 @@ export function useHslTheme() {
|
||||||
export function ThemeProvider({children}: {
|
export function ThemeProvider({children}: {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
const [rgbaTheme, setRgbaTheme] = useState<RgbaTheme | null>(null);
|
||||||
|
|
||||||
|
function applyTheme(theme: HslTheme) {
|
||||||
|
console.log('apply theme', theme);
|
||||||
|
rootStyle.setProperty('--color-primary', hslToString(theme.primary));
|
||||||
|
rootStyle.setProperty('--color-secondary', hslToString(theme.secondary));
|
||||||
|
rootStyle.setProperty('--color-background', hslToString(theme.background));
|
||||||
|
}
|
||||||
|
|
||||||
const [hslTheme, setHslTheme] = useStoredObjectState<HslTheme>('theme', getRandomTheme, {
|
const [hslTheme, setHslTheme] = useStoredObjectState<HslTheme>('theme', getRandomTheme, {
|
||||||
load: applyTheme,
|
load: applyTheme,
|
||||||
save: applyTheme
|
save: applyTheme
|
||||||
});
|
});
|
||||||
|
|
||||||
const [rgbaTheme, setRgbaTheme] = useState<RgbaTheme | null>(null);
|
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
const canvas = canvasRef.current;
|
||||||
const canvas = canvasRef.current;
|
|
||||||
if (canvas === null)
|
useMemo(() => {
|
||||||
throw new Error('canvas null');
|
if (!canvas)
|
||||||
|
return;
|
||||||
|
|
||||||
const drawContext = canvas.getContext('2d', {
|
const drawContext = canvas.getContext('2d', {
|
||||||
alpha: true,
|
alpha: false,
|
||||||
colorSpace: 'srgb',
|
colorSpace: 'srgb',
|
||||||
willReadFrequently: true
|
willReadFrequently: true
|
||||||
});
|
});
|
||||||
if (!drawContext)
|
if (!drawContext)
|
||||||
throw new Error('could not get draw context');
|
throw new Error('could not get draw context');
|
||||||
|
|
||||||
setRgbaTheme({
|
setRgbaTheme({
|
||||||
background: hslToRgba(drawContext, hslTheme.background),
|
background: hslToRgba(drawContext, hslTheme.background),
|
||||||
primary: hslToRgba(drawContext, hslTheme.primary),
|
primary: hslToRgba(drawContext, hslTheme.primary),
|
||||||
secondary: hslToRgba(drawContext, hslTheme.secondary),
|
secondary: hslToRgba(drawContext, hslTheme.secondary),
|
||||||
tertiary: hslToRgba(drawContext, hslTheme.tertiary),
|
tertiary: hslToRgba(drawContext, hslTheme.tertiary),
|
||||||
});
|
});
|
||||||
}, [hslTheme, canvasRef.current]);
|
}, [hslTheme, canvas]);
|
||||||
|
|
||||||
return <HslThemeContext.Provider value={{hslTheme, setHslTheme}}>
|
return <HslThemeContext.Provider value={{hslTheme, setHslTheme}}>
|
||||||
<RgbaThemeContext.Provider value={rgbaTheme || dummyRgbaTheme}>
|
<RgbaThemeContext.Provider value={rgbaTheme || dummyRgbaTheme}>
|
||||||
|
|
Loading…
Reference in a new issue