@atlaskit/app-provider
Version:
A top level provider for the Design System.
54 lines (52 loc) • 2.32 kB
JavaScript
import React from 'react';
import { themeImportMap } from '@atlaskit/tokens/artifacts/theme-import-map';
import { getThemeOverridePreferences } from '@atlaskit/tokens/get-theme-override-preferences';
import { getThemePreferences } from '@atlaskit/tokens/get-theme-preferences';
/**
* TODO: Remove this React 18 compatibility guard when React 19 has shipped everywhere.
* At that point, use `import { use } from 'react'` directly.
*/
const themeCssPromises = new Map();
function getThemeCssPromise(themeId) {
let themeCssPromise = themeCssPromises.get(themeId);
if (!themeCssPromise) {
themeCssPromise = themeImportMap[themeId]().then(({
default: css
}) => css);
themeCssPromises.set(themeId, themeCssPromise);
}
return themeCssPromise;
}
function getInlineThemeCss(themeId) {
var _document$body$queryS, _document$body$queryS2;
const reactUse = React.use;
const isServer = globalThis.__SERVER__ === true || typeof document === 'undefined';
if (isServer) {
return reactUse === null || reactUse === void 0 ? void 0 : reactUse(getThemeCssPromise(themeId));
}
return (_document$body$queryS = (_document$body$queryS2 = document.body.querySelector(`style[data-theme="${themeId}"]`)) === null || _document$body$queryS2 === void 0 ? void 0 : _document$body$queryS2.textContent) !== null && _document$body$queryS !== void 0 ? _document$body$queryS : undefined;
}
/**
* Resolves CSS for the themes applied by a ThemeProvider.
*
* During React 19 server rendering, `use()` suspends the provider subtree until
* each requested CSS chunk is available. The resulting styles are rendered
* immediately before that subtree. React 18 does not provide `use()`, so it
* safely follows the existing path without inline CSS. During hydration, the CSS
* is read from server-rendered style elements so the initial client tree matches.
*/
export function getInlineThemeStyles(theme, colorMode) {
const themeState = {
...theme,
colorMode,
contrastMode: 'no-preference'
};
const themeIds = [...getThemePreferences(themeState), ...getThemeOverridePreferences(themeState)];
return [...new Set(themeIds)].map(themeId => {
const css = getInlineThemeCss(themeId);
return css ? {
id: themeId,
css
} : undefined;
}).filter(style => style !== undefined);
}