UNPKG

@descope/sdk-mixins

Version:
175 lines (172 loc) 12.1 kB
import { __classPrivateFieldGet, __classPrivateFieldSet } from 'tslib'; import { createSingletonMixin, compose } from '@descope/sdk-helpers'; import { configMixin } from '../configMixin/configMixin.js'; import { createValidateAttributesMixin } from '../createValidateAttributesMixin/createValidateAttributesMixin.js'; import { descopeUiMixin } from '../descopeUiMixin/descopeUiMixin.js'; import { initElementMixin } from '../initElementMixin.js'; import { initLifecycleMixin } from '../initLifecycleMixin.js'; import { staticResourcesMixin } from '../staticResourcesMixin/staticResourcesMixin.js'; import { DEFAULT_STYLE_ID } from './constants.js'; import { loadFont, loadDevTheme } from './helpers.js'; import { observeAttributesMixin } from '../observeAttributesMixin/observeAttributesMixin.js'; import { UI_COMPONENTS_URL_KEY } from '../descopeUiMixin/constants.js'; import { injectStyleMixin } from '../injectStyleMixin.js'; const themeValidation = (_, theme) => (theme || false) && theme !== 'light' && theme !== 'dark' && 'Supported theme values are "light", "dark", or leave empty for using the OS theme'; const themeMixin = createSingletonMixin((superclass) => { var _ThemeMixinClass_instances, _ThemeMixinClass_globalStyle, _ThemeMixinClass__themeResource, _ThemeMixinClass_fetchTheme, _ThemeMixinClass_themeResource_get, _ThemeMixinClass_loadGlobalStyle, _ThemeMixinClass_loadComponentsStyle, _ThemeMixinClass_getFontsConfig, _ThemeMixinClass_loadFonts, _ThemeMixinClass_applyTheme, _ThemeMixinClass_onThemeChange, _ThemeMixinClass_loadTheme, _ThemeMixinClass_toggleOsThemeChangeListener, _a; const BaseClass = compose(createValidateAttributesMixin({ theme: themeValidation }), staticResourcesMixin, initLifecycleMixin, descopeUiMixin, configMixin, initElementMixin, observeAttributesMixin, injectStyleMixin)(superclass); return _a = class ThemeMixinClass extends BaseClass { constructor() { super(...arguments); _ThemeMixinClass_instances.add(this); _ThemeMixinClass_globalStyle.set(this, void 0); _ThemeMixinClass__themeResource.set(this, void 0); _ThemeMixinClass_onThemeChange.set(this, () => { __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadTheme).call(this); __classPrivateFieldGet(this, _ThemeMixinClass_toggleOsThemeChangeListener, "f").call(this, this.getAttribute('theme') === 'os'); }); // add or remove os theme change listener _ThemeMixinClass_toggleOsThemeChangeListener.set(this, (listen) => { var _b, _c, _d; const method = listen ? 'addEventListener' : 'removeEventListener'; (_d = (_c = (_b = window .matchMedia) === null || _b === void 0 ? void 0 : _b.call(window, '(prefers-color-scheme: dark)')) === null || _c === void 0 ? void 0 : _c[method]) === null || _d === void 0 ? void 0 : _d.call(_c, 'change', () => __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadTheme).call(this)); }); } get theme() { var _b, _c; const theme = this.getAttribute('theme'); if (theme === 'os') { const isOsDark = window.matchMedia && ((_c = (_b = window.matchMedia) === null || _b === void 0 ? void 0 : _b.call(window, '(prefers-color-scheme: dark)')) === null || _c === void 0 ? void 0 : _c.matches); return isOsDark ? 'dark' : 'light'; } return theme || 'light'; } get styleId() { return this.getAttribute('style-id') || DEFAULT_STYLE_ID; } async init() { var _b; await ((_b = super.init) === null || _b === void 0 ? void 0 : _b.call(this)); __classPrivateFieldGet(this, _ThemeMixinClass_onThemeChange, "f").call(this); await Promise.all([ __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadGlobalStyle).call(this), __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadComponentsStyle).call(this), ]); this.observeAttributes(['theme'], __classPrivateFieldGet(this, _ThemeMixinClass_onThemeChange, "f")); this.observeAttributes(['style-id'], () => { __classPrivateFieldSet(this, _ThemeMixinClass__themeResource, null, "f"); __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadFonts).call(this); __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadGlobalStyle).call(this); __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadComponentsStyle).call(this); }); } }, _ThemeMixinClass_globalStyle = new WeakMap(), _ThemeMixinClass__themeResource = new WeakMap(), _ThemeMixinClass_onThemeChange = new WeakMap(), _ThemeMixinClass_toggleOsThemeChangeListener = new WeakMap(), _ThemeMixinClass_instances = new WeakSet(), _ThemeMixinClass_fetchTheme = async function _ThemeMixinClass_fetchTheme() { try { const { body: fetchedTheme } = await this.fetchStaticResource(`${this.styleId}.json`, 'json'); // In development mode, we sometimes want to override the UI components URL // The override components might have a different theme, so we need to merge it with the project theme in order to see the components correctly if (process.env.NODE_ENV === 'development') { if (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem(UI_COMPONENTS_URL_KEY)) { try { this.logger.warn('You are in DEV mode, and UI components override URL was found\ntrying to merge project theme with the default theme of the UI components'); const devTheme = await loadDevTheme(); if (devTheme) { fetchedTheme.light.components = Object.assign(Object.assign({}, fetchedTheme.light.components), devTheme.light.components); fetchedTheme.dark.components = Object.assign(Object.assign({}, fetchedTheme.dark.components), devTheme.dark.components); this.logger.warn('Theme was merged successfully'); // eslint-disable-next-line no-console console.log('%cNOTICE! This is not the theme that will be used in production!\n\nMake sure to test it without the override UI components URL!', 'color: black; background-color:yellow; font-size: x-large'); } } catch (e) { this.logger.error('Failed to merge UI components theme\n', e); } } } return fetchedTheme; } catch (e) { this.logger.error('Cannot fetch theme file', 'make sure that your projectId & flowId are correct'); } return undefined; }, _ThemeMixinClass_themeResource_get = function _ThemeMixinClass_themeResource_get() { if (!__classPrivateFieldGet(this, _ThemeMixinClass__themeResource, "f")) { __classPrivateFieldSet(this, _ThemeMixinClass__themeResource, __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_fetchTheme).call(this), "f"); __classPrivateFieldGet(this, _ThemeMixinClass__themeResource, "f").then((theme) => this.logger.debug('Fetched theme', theme)); } // eslint-disable-next-line no-underscore-dangle return __classPrivateFieldGet(this, _ThemeMixinClass__themeResource, "f"); }, _ThemeMixinClass_loadGlobalStyle = async function _ThemeMixinClass_loadGlobalStyle() { var _b, _c; const theme = await __classPrivateFieldGet(this, _ThemeMixinClass_instances, "a", _ThemeMixinClass_themeResource_get); if (!theme) return; if (!__classPrivateFieldGet(this, _ThemeMixinClass_globalStyle, "f")) { __classPrivateFieldSet(this, _ThemeMixinClass_globalStyle, this.injectStyle(''), "f"); } __classPrivateFieldGet(this, _ThemeMixinClass_globalStyle, "f").replaceSync((((_b = theme === null || theme === void 0 ? void 0 : theme.light) === null || _b === void 0 ? void 0 : _b.globals) || '') + (((_c = theme === null || theme === void 0 ? void 0 : theme.dark) === null || _c === void 0 ? void 0 : _c.globals) || '')); }, _ThemeMixinClass_loadComponentsStyle = async function _ThemeMixinClass_loadComponentsStyle() { var _b, _c; const theme = await __classPrivateFieldGet(this, _ThemeMixinClass_instances, "a", _ThemeMixinClass_themeResource_get); if (!theme) return; const descopeUi = await this.descopeUi; if (descopeUi === null || descopeUi === void 0 ? void 0 : descopeUi.componentsThemeManager) { descopeUi.componentsThemeManager.themes = { light: (_b = theme === null || theme === void 0 ? void 0 : theme.light) === null || _b === void 0 ? void 0 : _b.components, dark: (_c = theme === null || theme === void 0 ? void 0 : theme.dark) === null || _c === void 0 ? void 0 : _c.components, }; } }, _ThemeMixinClass_getFontsConfig = async function _ThemeMixinClass_getFontsConfig() { var _b, _c; const { projectConfig } = (await this.config) || {}; const newConfig = (_b = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.styles) === null || _b === void 0 ? void 0 : _b[this.styleId]; const oldConfig = projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.cssTemplate; const config = newConfig || oldConfig; const fonts = (_c = config === null || config === void 0 ? void 0 : config[this.theme]) === null || _c === void 0 ? void 0 : _c.fonts; return fonts; }, _ThemeMixinClass_loadFonts = async function _ThemeMixinClass_loadFonts() { const fonts = await __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_getFontsConfig).call(this); if (fonts) { Object.values(fonts).forEach((font) => { if (font.url) { this.logger.debug(`Loading font from URL "${font.url}"`); loadFont(font.url); } }); } else { this.logger.debug('No fonts to load'); } }, _ThemeMixinClass_applyTheme = async function _ThemeMixinClass_applyTheme() { this.rootElement.setAttribute('data-theme', this.theme); const descopeUi = await this.descopeUi; if (descopeUi === null || descopeUi === void 0 ? void 0 : descopeUi.componentsThemeManager) { descopeUi.componentsThemeManager.currentThemeName = this.theme; } }, _ThemeMixinClass_loadTheme = function _ThemeMixinClass_loadTheme() { __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_loadFonts).call(this); __classPrivateFieldGet(this, _ThemeMixinClass_instances, "m", _ThemeMixinClass_applyTheme).call(this); }, _a; }); export { themeMixin }; //# sourceMappingURL=themeMixin.js.map