UNPKG

@codegouvfr/react-dsfr

Version:

French State Design System React integration library

295 lines 13.3 kB
"use client"; /* eslint-disable @typescript-eslint/no-non-null-assertion */ import React, { useMemo } from "react"; import { createTheme, ThemeProvider as MuiThemeProvider } from "@mui/material/styles"; import { fr } from "./fr"; import { useIsDark } from "./useIsDark"; import { typography } from "./fr/generatedFromCss/typography"; import { spacingTokenByValue } from "./fr/generatedFromCss/spacing"; import { assert } from "tsafe/assert"; import { objectKeys } from "tsafe/objectKeys"; import { id } from "tsafe/id"; import { useBreakpointsValues } from "./useBreakpointsValues"; export function getMuiDsfrThemeOptions(params) { const { isDark, breakpointsValues } = params; const { options, decisions } = fr.colors.getHex({ isDark }); return { "shape": { "borderRadius": 0 }, "breakpoints": { //NOTE: We would use "unit": breakpointsValuesUnit but only "px" works. "unit": "px", "values": breakpointsValues }, "palette": { "mode": isDark ? "dark" : "light", "primary": { "main": options.blueFrance.sun113_625.default, "light": options.blueFrance.sun113_625.active, "dark": options.blueFrance.sun113_625.hover, "contrastText": options.blueFrance._975sun113.default }, "secondary": { "main": options.blueFrance._950_100.default, "light": options.blueFrance._950_100.active, "dark": options.blueFrance._950_100.hover, "contrastText": options.blueFrance.sun113_625.default }, "error": { "light": options.error._425_625.active, "main": options.error._425_625.default, "dark": options.error._425_625.hover, "contrastText": options.grey._1000_50.default }, "warning": { "light": options.warning._425_625.default, "main": options.warning._425_625.default, "dark": options.warning._425_625.hover, "contrastText": options.grey._1000_50.default }, "info": { "light": options.info._425_625.active, "main": options.info._425_625.default, "dark": options.info._425_625.hover, "contrastText": options.grey._1000_50.default }, "success": { "light": options.success._425_625.active, "main": options.success._425_625.default, "dark": options.success._425_625.hover, "contrastText": options.grey._1000_50.default }, "text": { "primary": options.grey._50_1000.default, "secondary": options.grey._200_850.default, "disabled": options.grey._625_425.default }, "divider": options.grey._900_175.default, "action": { "active": options.grey._200_850.default, "hover": options.grey._975_100.default, "selected": options.blueFrance._925_125.active, "disabled": options.grey._625_425.default, "disabledBackground": options.grey._925_125.default, "focus": options.blueFrance.sun113_625.active }, "background": { "default": options.grey._1000_50.default, "paper": options.grey._1000_100.default } }, "typography": (() => { const getBySelector = (selector) => { const variant = typography.find(variant => variant.selector === selector); assert(variant !== undefined); const style = Object.assign({}, variant.style); //TODO: Investigate why we need to do that. delete style.margin; return style; }; return { "fontFamily": '"Marianne", arial, sans-serif', "h1": getBySelector("h1"), "h2": getBySelector("h2"), "h3": getBySelector("h3"), "h4": getBySelector("h4"), "h5": getBySelector("h5"), "h6": getBySelector("h6"), //"subtitle1": //"subtitle2": "body1": getBySelector("p") //"body2": {}, //"caption": {}, //"button": {}, //"overline": {} }; })(), "spacing": (() => { const values = []; //NOTE: The properties are declared sorted in the object. objectKeys(spacingTokenByValue).forEach(key => { if (key.endsWith("w")) { values.push(spacingTokenByValue[key]); } }); return (abs) => typeof abs === "string" ? abs : abs === 0 ? 0 : (() => { const value = values[abs - 1]; return value === undefined ? abs : value; })(); })(), "shadows": (() => { const [, , , , , , , , ...rest] = createTheme().shadows; return id([ "none", /** ButtonBar shadow */ "0px 6px 10px 0px rgba(0,0,0,0.07)", /** Explorer items */ "0px 4px 4px 0px rgba(0,0,0,0.1)", /** LeftBar */ "6px 0px 16px 0px rgba(0,0,0,0.15)", /** AccountTab default */ "4px 0px 10px 0px rgba(0,0,0,0.07)", /** AccountTab active */ "-4px 0px 10px 0px rgba(0,0,0,0.07)", /** Card over */ "0px 6px 10px 0px rgba(0,0,0,0.14)", /** Dialog **/ "0px 8px 10px -7px rgba(0,0,0,0.07)", ...rest ]); })(), "components": Object.assign({ "MuiButton": { "styleOverrides": { "root": { "textTransform": "unset" } } }, "MuiSvgIcon": { "styleOverrides": { "colorPrimary": ({ theme }) => ({ "color": theme.palette.text.primary }) } }, "MuiStepIcon": { "styleOverrides": { "text": { "fill": fr.colors.getHex({ "isDark": true }).decisions.text.title.grey .default } } }, "MuiTablePagination": { "styleOverrides": { "displayedRows": { //Fixes: https://user-images.githubusercontent.com/6702424/206063347-65e7d13c-3dea-410c-a0e0-51cf214deba0.png "margin": "unset" }, "selectLabel": { //Fixes: https://github.com/codegouvfr/react-dsfr/assets/6702424/678a7f69-d4e8-4897-85f0-65c605b46900 "margin": "unset" } } }, "MuiTypography": { "styleOverrides": { "root": { //Fixes double underline: https://user-images.githubusercontent.com/6702424/206064575-4f036145-ff40-47db-aabd-560f29136e71.png "backgroundImage": "unset" } } }, "MuiAutocomplete": { "styleOverrides": { "option": { "border": "1px solid transparent", "&.Mui-focusVisible": { "backgroundColor": decisions.background.contrast.grey.default + " !important", "border": `1px solid ${decisions.border.active.blueFrance.default}` } } } } }, (() => { const nonTypedMuiComponents = { "MuiDataGrid": { "styleOverrides": { "root": (() => { const set = new WeakSet(); const borderNone = { "border": "none" }; return (params) => { const { ownerState } = params; if (ownerState === undefined) { return borderNone; } if (ownerState.getRowClassName === undefined || !set.has(ownerState.getRowClassName)) { const originalGetRowClassName = ownerState.getRowClassName; ownerState.getRowClassName = params => { const { indexRelativeToCurrentPage } = params; const parityClassName = indexRelativeToCurrentPage % 2 === 0 ? "even" : "odd"; const className = originalGetRowClassName === null || originalGetRowClassName === void 0 ? void 0 : originalGetRowClassName(params); return className === undefined ? parityClassName : `${parityClassName} ${className}`; }; set.add(ownerState.getRowClassName); } return borderNone; }; })(), "columnHeaders": { "backgroundColor": decisions.background.contrast.grey.default, "&&": { "borderColor": decisions.border.plain.grey.default, "borderPosition": "bottom", "borderWidth": 2 } }, "row": () => { const hoveredAndSelected = { "&.Mui-hovered": { "backgroundColor": fr.colors.decisions.background.contrast.grey.hover }, "&.Mui-selected": { "backgroundColor": fr.colors.decisions.background.contrast.grey.active } }; return { "&.even": Object.assign({ "backgroundColor": decisions.background.contrast.grey.default, "&:hover": { "backgroundColor": decisions.background.contrast.grey.hover } }, hoveredAndSelected), "&.odd": Object.assign({ "backgroundColor": decisions.background.alt.grey.default, "&:hover": { "backgroundColor": decisions.background.alt.grey.hover } }, hoveredAndSelected) }; }, "columnSeparator": { "display": "none" } } } }; return nonTypedMuiComponents; })()) }; } /** *Generate a theme base on the options received. * * @param params — Dark or light mode. * * @param args — Deep merge the arguments with the about to be returned theme. * * @returns — A complete, ready-to-use mui theme object. */ export function createMuiDsfrTheme(params, ...args) { const muiTheme = createTheme(getMuiDsfrThemeOptions(params), ...args); return muiTheme; } export function createMuiDsfrThemeProvider(params) { const { augmentMuiTheme, useIsDark: useIsDark_props = useIsDark } = params; function MuiDsfrThemeProvider(props) { const { children } = props; const { isDark } = useIsDark_props(); const { breakpointsValues } = useBreakpointsValues(); const theme = useMemo(() => { const nonAugmentedMuiTheme = createMuiDsfrTheme({ isDark, breakpointsValues }); return augmentMuiTheme === undefined ? nonAugmentedMuiTheme : augmentMuiTheme({ nonAugmentedMuiTheme, isDark }); }, [isDark]); return React.createElement(MuiThemeProvider, { theme: theme }, children); } return { MuiDsfrThemeProvider }; } export const { MuiDsfrThemeProvider } = createMuiDsfrThemeProvider({}); export default MuiDsfrThemeProvider; //# sourceMappingURL=mui.js.map