UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

112 lines (109 loc) 4.57 kB
export class ThemeService { constructor(api) { this.unsubscribe = () => { }; this.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); }; 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(); }; } 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('Please import Adaptable styles from "@adaptabletools/adaptable/index.css"'); } const isCustomUserTheme = !this.api.themeApi.internalApi.isSystemTheme(themeName); if (!isCustomUserTheme && abThemeLoaded !== themeName) { logger.consoleWarn(`Theme "${themeName}" doesn't seem to be loaded! Make sure you import the css file for the "${themeName}" theme! If it's an AdapTable system theme, try 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); }; } }