@codegouvfr/react-dsfr
Version:
French State Design System React integration library
153 lines (110 loc) • 3.95 kB
text/typescript
import type { ColorScheme } from "./client";
import { data_fr_scheme, data_fr_theme, rootColorSchemeStyleTagId } from "./constants";
import { fr } from "../fr";
type GetScriptToRunAsap = (props: {
defaultColorScheme: ColorScheme | "system";
nonce: string | undefined;
trustedTypesPolicyName: string;
}) => string;
declare global {
interface Window {
ssrWasPerformedWithIsDark?: boolean;
ssrNonce?: string;
}
}
// TODO enhance to use DOMPurify with trustedTypes
export const getScriptToRunAsap: GetScriptToRunAsap = ({
defaultColorScheme,
nonce = "",
trustedTypesPolicyName
}) => `
{
window.ssrWasPerformedWithIsDark = "${defaultColorScheme}" === "dark";
const sanitizer = typeof trustedTypes !== "undefined" ? trustedTypes.createPolicy("${trustedTypesPolicyName}-asap", { createHTML: s => s }) : {
createHTML: s => s,
};
reset_persisted_value_if_website_config_changed: {
const localStorageKey = "scheme-website-config-default";
const localStorageValue = localStorage.getItem(localStorageKey);
if (localStorageValue === "${defaultColorScheme}") {
break reset_persisted_value_if_website_config_changed;
}
localStorage.removeItem("scheme");
localStorage.setItem(localStorageKey, "${defaultColorScheme}");
}
const isDark = (() => {
const isDarkExplicitlyProvidedAsParameter = (() => {
if ("${defaultColorScheme}" === "system") {
return undefined;
}
switch ("${defaultColorScheme}") {
case "dark": return true;
case "light": return false;
}
})();
const isDarkFromLocalStorage = (() => {
const colorSchemeReadFromLocalStorage = localStorage.getItem("scheme");
if (colorSchemeReadFromLocalStorage === null) {
return undefined;
}
if (colorSchemeReadFromLocalStorage === "system") {
return undefined;
}
switch (colorSchemeReadFromLocalStorage) {
case "dark":
return true;
case "light":
return false;
}
})();
const isDarkFromOsPreference = (() => {
if (!window.matchMedia) {
return false;
}
return window.matchMedia("(prefers-color-scheme: dark)").matches;
})();
return (
isDarkFromLocalStorage ??
isDarkExplicitlyProvidedAsParameter ??
isDarkFromOsPreference
);
})();
document.documentElement.setAttribute(
"${data_fr_scheme}",
(() => {
const colorSchemeReadFromLocalStorage = localStorage.getItem("scheme");
if (colorSchemeReadFromLocalStorage === null) {
return "${defaultColorScheme}";
}
return colorSchemeReadFromLocalStorage;
})()
);
document.documentElement.setAttribute("${data_fr_theme}", isDark ? "dark" : "light")
{
let element= document.getElementById("${rootColorSchemeStyleTagId}");
if( element !== null ){
element.remove()
}
element = document.createElement("style");
if ("${nonce}" !== "") {
element.setAttribute("nonce", "${nonce}");
}
element.id = "${rootColorSchemeStyleTagId}";
element.innerHTML = sanitizer.createHTML(\`:root { color-scheme: \${isDark ? "dark" : "light"}; }\`);
document.head.appendChild(element);
}
{
const name = "theme-color";
let element = document.querySelector(\`meta[name=\${name}]\`);
if( element !== null ){
element.remove();
}
element = document.createElement("meta");
element.name = name;
element.content = isDark ? "${
fr.colors.getHex({ "isDark": true }).decisions.background.default.grey.default
}" : "${fr.colors.getHex({ "isDark": false }).decisions.background.default.grey.default}";
document.head.appendChild(element);
}
}
`;