@adaptabletools/adaptable-cjs
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
114 lines (113 loc) • 4.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThemeService = void 0;
class ThemeService {
api;
unsubscribe = () => { };
styleSheetObject;
constructor(api) {
this.api = api;
this.subscribe();
if (!this.styleSheetObject) {
this.styleSheetObject = new CSSStyleSheet();
// ts does not know about adoptedStyleSheets
document.adoptedStyleSheets = [
...(document.adoptedStyleSheets ?? []),
this.styleSheetObject,
];
}
}
destroy() {
this.api = null;
this.unsubscribe();
document.adoptedStyleSheets = [...document.adoptedStyleSheets].filter((sheet) => sheet !== this.styleSheetObject);
}
subscribe() {
const themeChangedUnsubscribe = this.api.eventApi.on('ThemeChanged', this.onThemeChanged);
const prefferedColorSchemeUnsubscribe = this.attachPrefferedColorSchemeListener();
this.unsubscribe = () => {
themeChangedUnsubscribe();
prefferedColorSchemeUnsubscribe();
};
}
onThemeChanged = () => {
let currentTheme = this.api.themeApi.getCurrentThemeObject();
currentTheme = this.mapOsTheme(currentTheme);
this.applyNewThemeVariables(currentTheme);
// this needs to be called after variables are set
// as it may show the warning for a custom/runtime theme
this.showMissingThemeFiles(currentTheme);
};
applyNewThemeVariables(theme) {
const variables = theme.CSSVariables;
if (!variables || Object.keys(variables).length === 0) {
return;
}
let str = `html.${this.api.themeApi.internalApi.getThemeClassName(theme.Name)} {
--ab-theme-loaded: ab--theme-${theme.Name};
`;
for (const [key, value] of Object.entries(variables)) {
if (key.includes('--')) {
str += `${key}: ${value};`;
}
}
str += '}';
this.styleSheetObject.replaceSync(str);
}
showMissingThemeFiles(theme) {
// run time defined theme
// because it may be an empty theme
if (theme.Source === 'User') {
return;
}
const themeName = theme.Name;
const adaptable = this.api.internalApi.getAdaptableInstance();
const logger = adaptable.logger;
const documentElement = document.documentElement;
const computedDocumentStyle = getComputedStyle(documentElement);
const [abLoaded, abThemeLoaded] = ['--ab-loaded', '--ab-theme-loaded'].map((variable) => {
let val = computedDocumentStyle.getPropertyValue(variable);
if (typeof val === 'string' && val.trim) {
val = val.trim();
}
return val;
});
if (abLoaded !== '777') {
logger.consoleError('Adaptable styles not detected. Please import "@adaptabletools/adaptable/index.css".');
}
const isCustomUserTheme = !this.api.themeApi.internalApi.isSystemTheme(themeName);
if (!isCustomUserTheme && abThemeLoaded !== themeName) {
logger.consoleWarn(`Theme "${themeName}" does not appear to be loaded. Ensure the CSS file is imported, e.g.: import "@adaptabletools/adaptable/themes/${themeName}.css".`);
}
}
// prefers-color-scheme
getDOMPrefferedColorScheme() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
mapOsTheme(theme) {
theme = typeof theme === 'string' ? this.api.themeApi.getThemeByName(theme) : theme;
if ((typeof theme === 'string' && theme === 'os') ||
(typeof theme === 'object' && theme.Name === 'os')) {
return this.api.themeApi.getThemeByName(this.getDOMPrefferedColorScheme());
}
return theme;
}
attachPrefferedColorSchemeListener() {
const handlePrefferedColorSchemeChange = () => {
// we need to reapply the theme
const currentTheme = this.api.themeApi.getCurrentThemeObject();
if (currentTheme.Name === 'os') {
this.api.themeApi.applyCurrentTheme();
}
};
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', handlePrefferedColorSchemeChange);
return () => {
window
.matchMedia('(prefers-color-scheme: dark)')
.removeEventListener('change', handlePrefferedColorSchemeChange);
};
}
}
exports.ThemeService = ThemeService;