/** * Contains the fast prototyping wrappers for usage * with the itemize application in the fast prototyping mode * * @module */ import React, { useEffect } from "react"; import { createTheme, Theme } from "@mui/material/styles"; import { ILocaleContextType } from "../internal/providers/locale-provider"; import Moment from "moment"; import AdapterMoment from '@mui/lab/AdapterMoment'; import { IConfigRawJSONDataType } from "../../config"; import { ThemeProvider } from "@mui/material/styles"; import CssBaseline from "@mui/material/CssBaseline"; import LocalizationProvider from '@mui/lab/LocalizationProvider'; import { CacheProvider, EmotionCache } from "@emotion/react"; import createCache from '@emotion/cache'; import rtlPlugin from 'stylis-plugin-rtl'; import { prefixer } from 'stylis'; export const ReuseCacheContextEmotionIsAMess = React.createContext(false); /** * Removes the #ssr-sheets component that is injected by the collector if * SSR was used * @param props the props for the sheet remover * @returns a react node */ function SSRSheetsRemover(props: { children: React.ReactNode }) { useEffect(() => { const ssrStyles = document.querySelector('#ssr-sheets'); if (ssrStyles) { ssrStyles.parentElement.removeChild(ssrStyles); } }, []); // buggy typescript return props.children as any; } let cachedRtlCache: EmotionCache; let cachedLtrCache: EmotionCache; export function createEmotionCache(isRtl: boolean, useDoubleCache: boolean) { if (useDoubleCache) { if (cachedRtlCache && isRtl) { return cachedRtlCache; } else if (cachedLtrCache && !isRtl) { return cachedLtrCache; } } const newCache = isRtl ? createCache({ key: "cssrtl", stylisPlugins: [prefixer, rtlPlugin], }) : createCache({ key: "css", }); if (useDoubleCache) { if (isRtl) { cachedRtlCache = newCache; } else { cachedLtrCache = newCache; } } return newCache; } /** * The appwrapper is the static wrapper that does not really ever change and stays on top * of the entire application for this reason, it's expected to render once * * For fast prototyping we use material ui, and as such we pass those providers here * * @param app the application that react is asking to render * @param config the configuration that is being used, this is the same as the config.json */ export function appWrapper(app: React.ReactElement, config: IConfigRawJSONDataType) { // this is what our base app used to be before // very simple and it worked const baseApp = ( <> {app} ); return baseApp; } let cachedLTRTheme: Theme; let cachedRTLTheme: Theme; /** * The main wrapper stays under the app and it's a dynamic component that will be requested * to updated if the app locale context changes, which creates a chain effect * * for fast prototyping we use the mui pickers utility for material ui pickers, and these * need to change according to locale * * @param mainComponent the main component that is under the app * @param config the config of the app * @param localeContext the locale that we are using */ export function mainWrapper( mainComponent: React.ReactElement, config: IConfigRawJSONDataType, localeContext: ILocaleContextType, ) { const languageDeregionalized = localeContext.language.includes("-") ? localeContext.language.split("-")[0] : localeContext.language; const isRtl = config.rtlLanguages.includes(localeContext.language); let theme: Theme; if (isRtl && cachedRTLTheme) { theme = cachedRTLTheme; } else if (!isRtl && cachedLTRTheme) { theme = cachedLTRTheme; } else { theme = createTheme({ direction: isRtl ? "rtl" : "ltr", typography: { fontFamily: "'" + config.fontName + "', sans-serif", fontWeightLight: 300, fontWeightRegular: 400, fontWeightMedium: 500, } }); if (isRtl) { cachedRTLTheme = theme; } else { cachedLTRTheme = theme; } } const baseApp = ( {mainComponent} ); // this is what it has to do now with the introduction // of a dreaded emotion cache that is a total mess return ( {(shouldReuse: boolean) => { // the cache is already defined for the server // context in the collector, so it's not necessary // to create a new one, because emotion is so smart // it doesn't export its context so I can't read it // and must deal with a hack if (shouldReuse) { return baseApp; } else { const cache = createEmotionCache(isRtl, true); // client side basically or when // we don't use a styles collector return ( {baseApp} ); } }} ); }