@atlaskit/tokens 1.22.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/custom-themes/package.json +17 -0
  3. package/dist/cjs/constants.js +3 -1
  4. package/dist/cjs/custom-theme.js +45 -79
  5. package/dist/cjs/enable-global-theme.js +70 -0
  6. package/dist/cjs/entry-points/custom-themes.js +13 -0
  7. package/dist/cjs/get-theme-html-attrs.js +3 -5
  8. package/dist/cjs/get-token-value.js +1 -1
  9. package/dist/cjs/get-token.js +1 -1
  10. package/dist/cjs/index.js +7 -0
  11. package/dist/cjs/load-custom-theme-styles.js +45 -0
  12. package/dist/cjs/set-global-theme.js +50 -94
  13. package/dist/cjs/theme-config.js +6 -1
  14. package/dist/cjs/utils/color-mode-listeners.js +66 -0
  15. package/dist/cjs/utils/configure-page.js +34 -0
  16. package/dist/cjs/utils/get-theme-preferences.js +0 -5
  17. package/dist/es2019/constants.js +1 -0
  18. package/dist/es2019/custom-theme.js +4 -4
  19. package/dist/es2019/enable-global-theme.js +53 -0
  20. package/dist/es2019/entry-points/custom-themes.js +1 -0
  21. package/dist/es2019/get-theme-html-attrs.js +3 -5
  22. package/dist/es2019/get-token-value.js +1 -1
  23. package/dist/es2019/get-token.js +1 -1
  24. package/dist/es2019/index.js +1 -0
  25. package/dist/es2019/load-custom-theme-styles.js +37 -0
  26. package/dist/es2019/set-global-theme.js +34 -65
  27. package/dist/es2019/theme-config.js +7 -1
  28. package/dist/es2019/utils/color-mode-listeners.js +48 -0
  29. package/dist/es2019/utils/configure-page.js +22 -0
  30. package/dist/es2019/utils/get-theme-preferences.js +0 -5
  31. package/dist/esm/constants.js +1 -0
  32. package/dist/esm/custom-theme.js +45 -78
  33. package/dist/esm/enable-global-theme.js +63 -0
  34. package/dist/esm/entry-points/custom-themes.js +1 -0
  35. package/dist/esm/get-theme-html-attrs.js +3 -5
  36. package/dist/esm/get-token-value.js +1 -1
  37. package/dist/esm/get-token.js +1 -1
  38. package/dist/esm/index.js +1 -0
  39. package/dist/esm/load-custom-theme-styles.js +39 -0
  40. package/dist/esm/set-global-theme.js +49 -93
  41. package/dist/esm/theme-config.js +7 -1
  42. package/dist/esm/utils/color-mode-listeners.js +58 -0
  43. package/dist/esm/utils/configure-page.js +28 -0
  44. package/dist/esm/utils/get-theme-preferences.js +0 -5
  45. package/dist/types/constants.d.ts +1 -0
  46. package/dist/types/custom-theme.d.ts +3 -3
  47. package/dist/types/enable-global-theme.d.ts +25 -0
  48. package/dist/types/entry-points/custom-themes.d.ts +1 -0
  49. package/dist/types/get-global-theme.d.ts +1 -1
  50. package/dist/types/index.d.ts +1 -0
  51. package/dist/types/load-custom-theme-styles.d.ts +17 -0
  52. package/dist/types/set-global-theme.d.ts +1 -4
  53. package/dist/types/theme-config.d.ts +8 -1
  54. package/dist/types/theme-mutation-observer.d.ts +1 -1
  55. package/dist/types/use-theme-observer.d.ts +1 -1
  56. package/dist/types/utils/color-mode-listeners.d.ts +13 -0
  57. package/dist/types/utils/configure-page.d.ts +6 -0
  58. package/dist/types-ts4.5/constants.d.ts +1 -0
  59. package/dist/types-ts4.5/custom-theme.d.ts +3 -3
  60. package/dist/types-ts4.5/enable-global-theme.d.ts +25 -0
  61. package/dist/types-ts4.5/entry-points/custom-themes.d.ts +1 -0
  62. package/dist/types-ts4.5/get-global-theme.d.ts +1 -1
  63. package/dist/types-ts4.5/index.d.ts +1 -0
  64. package/dist/types-ts4.5/load-custom-theme-styles.d.ts +17 -0
  65. package/dist/types-ts4.5/set-global-theme.d.ts +1 -4
  66. package/dist/types-ts4.5/theme-config.d.ts +8 -1
  67. package/dist/types-ts4.5/theme-mutation-observer.d.ts +1 -1
  68. package/dist/types-ts4.5/use-theme-observer.d.ts +1 -1
  69. package/dist/types-ts4.5/utils/color-mode-listeners.d.ts +13 -0
  70. package/dist/types-ts4.5/utils/configure-page.d.ts +6 -0
  71. package/package.json +2 -1
  72. package/report.api.md +17 -3
  73. package/tmp/api-report-tmp.d.ts +6 -3
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _bindEventListener = require("bind-event-listener");
12
+ var _constants = require("../constants");
13
+ var _themeLoading = require("./theme-loading");
14
+ var isMatchMediaAvailable = typeof window !== 'undefined' && 'matchMedia' in window;
15
+
16
+ /**
17
+ * Updates the current theme when the system theme changes. Should be bound
18
+ * to an event listener listening on the '(prefers-color-scheme: dark)' query
19
+ * @param e The event representing a change in system theme.
20
+ */
21
+ function checkNativeListener(e) {
22
+ var element = document.documentElement;
23
+ element.setAttribute(_constants.COLOR_MODE_ATTRIBUTE, e.matches ? 'dark' : 'light');
24
+ }
25
+ var darkModeMql = isMatchMediaAvailable && window.matchMedia(_themeLoading.darkModeMediaQuery);
26
+ var ColorModeObserver = /*#__PURE__*/function () {
27
+ function ColorModeObserver() {
28
+ (0, _classCallCheck2.default)(this, ColorModeObserver);
29
+ (0, _defineProperty2.default)(this, "unbindThemeChangeListener", null);
30
+ }
31
+ (0, _createClass2.default)(ColorModeObserver, [{
32
+ key: "getColorMode",
33
+ value: function getColorMode() {
34
+ if (!darkModeMql) {
35
+ return 'light';
36
+ }
37
+ return darkModeMql !== null && darkModeMql !== void 0 && darkModeMql.matches ? 'dark' : 'light';
38
+ }
39
+ }, {
40
+ key: "bind",
41
+ value: function bind() {
42
+ if (darkModeMql && this.unbindThemeChangeListener === null) {
43
+ this.unbindThemeChangeListener = (0, _bindEventListener.bind)(darkModeMql, {
44
+ type: 'change',
45
+ listener: checkNativeListener
46
+ });
47
+ }
48
+ }
49
+ }, {
50
+ key: "unbind",
51
+ value: function unbind() {
52
+ if (this.unbindThemeChangeListener) {
53
+ this.unbindThemeChangeListener();
54
+ this.unbindThemeChangeListener = null;
55
+ }
56
+ }
57
+ }]);
58
+ return ColorModeObserver;
59
+ }();
60
+ /**
61
+ * A singleton color mode observer - binds "auto" switching logic to a single `mediaQueryList` listener
62
+ * that can be unbound by any consumer when no longer needed.
63
+ */
64
+ var SingletonColorModeObserver = new ColorModeObserver();
65
+ var _default = SingletonColorModeObserver;
66
+ exports.default = _default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = configurePage;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _getThemeHtmlAttrs = _interopRequireDefault(require("../get-theme-html-attrs"));
10
+ var _colorModeListeners = _interopRequireDefault(require("./color-mode-listeners"));
11
+ /**
12
+ * Given ThemeState, sets appropriate html attributes on the documentElement,
13
+ * adds a listener to keep colorMode updated, and returns a function to unbind.
14
+ */
15
+ function configurePage(themeState) {
16
+ if (themeState.colorMode === 'auto') {
17
+ // Set colorMode based on the user preference
18
+ themeState.colorMode = _colorModeListeners.default.getColorMode();
19
+ // Bind a listener (if one doesn't already exist) to keep colorMode updated
20
+ _colorModeListeners.default.bind();
21
+ } else {
22
+ _colorModeListeners.default.unbind();
23
+ }
24
+ var themeAttributes = (0, _getThemeHtmlAttrs.default)(themeState);
25
+ Object.entries(themeAttributes).forEach(function (_ref) {
26
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
27
+ key = _ref2[0],
28
+ value = _ref2[1];
29
+ document.documentElement.setAttribute(key, value);
30
+ });
31
+ return function () {
32
+ return _colorModeListeners.default.unbind;
33
+ };
34
+ }
@@ -23,11 +23,6 @@ var getThemePreferences = function getThemePreferences(themeState) {
23
23
  if ((0, _platformFeatureFlags.getBooleanFF)('platform.design-system-team.border-checkbox_nyoiu')) {
24
24
  themePreferences.push("".concat(themePreferences.includes('dark') ? 'dark' : 'light', "-new-input-border"));
25
25
  }
26
-
27
- // Load spacing by default
28
- if (!themePreferences.includes('spacing')) {
29
- themePreferences.push('spacing');
30
- }
31
26
  return (0, _toConsumableArray2.default)(new Set(themePreferences));
32
27
  };
33
28
  exports.getThemePreferences = getThemePreferences;
@@ -1,6 +1,7 @@
1
1
  export const THEME_DATA_ATTRIBUTE = 'data-theme';
2
2
  export const COLOR_MODE_ATTRIBUTE = 'data-color-mode';
3
3
  export const CUSTOM_THEME_ATTRIBUTE = 'data-custom-theme';
4
+ export const DEFAULT_THEME = 'light';
4
5
  export const CSS_PREFIX = 'ds';
5
6
  export const CSS_VAR_FULL = ['opacity', 'font', 'space', 'border'];
6
7
  export const TOKEN_NOT_FOUND_CSS_VAR = `--${CSS_PREFIX}-token-not-found`;
@@ -18,10 +18,10 @@ export const CUSTOM_STYLE_ELEMENTS_SIZE_THRESHOLD = 10;
18
18
  * @param {string} themeState.colorMode Determines which color theme is applied
19
19
  * @param {Object} themeState.UNSAFE_themeOptions The custom branding options to be used for custom theme generation
20
20
  *
21
- * @returns A Promise of an object array, containing theme IDs, data-attributes to attach to the theme, and the theme CSS.
21
+ * @returns An object array, containing theme IDs, data-attributes to attach to the theme, and the theme CSS.
22
22
  * If an error is encountered while loading themes, the themes array will be empty.
23
23
  */
24
- export async function getCustomThemeStyles(themeState) {
24
+ export function getCustomThemeStyles(themeState) {
25
25
  var _themeState$UNSAFE_th;
26
26
  const brandColor = themeState === null || themeState === void 0 ? void 0 : (_themeState$UNSAFE_th = themeState.UNSAFE_themeOptions) === null || _themeState$UNSAFE_th === void 0 ? void 0 : _themeState$UNSAFE_th.brandColor;
27
27
  const mode = (themeState === null || themeState === void 0 ? void 0 : themeState.colorMode) || themeStateDefaults['colorMode'];
@@ -64,8 +64,8 @@ html[${CUSTOM_THEME_ATTRIBUTE}="${uniqueId}"][${COLOR_MODE_ATTRIBUTE}="dark"][da
64
64
  }
65
65
  return themes;
66
66
  }
67
- export async function loadAndAppendCustomThemeCss(themeState) {
68
- const themes = await getCustomThemeStyles(themeState);
67
+ export function loadAndAppendCustomThemeCss(themeState) {
68
+ const themes = getCustomThemeStyles(themeState);
69
69
  limitSizeOfCustomStyleElements(CUSTOM_STYLE_ELEMENTS_SIZE_THRESHOLD);
70
70
  themes.map(theme => {
71
71
  const styleTag = document.createElement('style');
@@ -0,0 +1,53 @@
1
+ import { themeStateDefaults } from './theme-config';
2
+ import configurePage from './utils/configure-page';
3
+ import { getThemePreferences } from './utils/get-theme-preferences';
4
+
5
+ /**
6
+ * Synchronously sets the theme globally at runtime. Themes are not loaded;
7
+ * use `getThemeStyles` and other server-side utilities to generate and load them.
8
+ *
9
+ * @param {Object<string, string>} themeState The themes and color mode that should be applied.
10
+ * @param {string} themeState.colorMode Determines which color theme is applied. If set to `auto`, the theme applied will be determined by the OS setting.
11
+ * @param {string} themeState.dark The color theme to be applied when the color mode resolves to 'dark'.
12
+ * @param {string} themeState.light The color theme to be applied when the color mode resolves to 'light'.
13
+ * @param {string} themeState.shape The shape theme to be applied.
14
+ * @param {string} themeState.spacing The spacing theme to be applied.
15
+ * @param {string} themeState.typography The typography theme to be applied.
16
+ * @param {Object} themeState.UNSAFE_themeOptions The custom branding options to be used for custom theme generation
17
+ * @param {function} themeLoader Callback function used to override the default theme loading functionality.
18
+ *
19
+ * @returns An unbind function, that can be used to stop listening for changes to system theme.
20
+ *
21
+ * @example
22
+ * ```
23
+ * enableGlobalTheme({colorMode: 'auto', light: 'light', dark: 'dark', spacing: 'spacing'});
24
+ * ```
25
+ */
26
+ const enableGlobalTheme = ({
27
+ colorMode = themeStateDefaults['colorMode'],
28
+ dark = themeStateDefaults['dark'],
29
+ light = themeStateDefaults['light'],
30
+ shape = themeStateDefaults['shape'],
31
+ spacing = themeStateDefaults['spacing'],
32
+ typography = themeStateDefaults['typography'],
33
+ UNSAFE_themeOptions = themeStateDefaults['UNSAFE_themeOptions']
34
+ } = {}, themeLoader) => {
35
+ const themeState = {
36
+ colorMode,
37
+ dark,
38
+ light,
39
+ shape,
40
+ spacing,
41
+ typography,
42
+ UNSAFE_themeOptions: themeLoader ? undefined : UNSAFE_themeOptions
43
+ };
44
+
45
+ // Determine what to load and call theme loader
46
+ const themePreferences = getThemePreferences(themeState);
47
+ if (themeLoader) {
48
+ themePreferences.map(themeId => themeLoader(themeId));
49
+ }
50
+ const autoUnbind = configurePage(themeState);
51
+ return autoUnbind;
52
+ };
53
+ export default enableGlobalTheme;
@@ -0,0 +1 @@
1
+ export { default as UNSAFE_loadCustomThemeStyles } from '../load-custom-theme-styles';
@@ -28,15 +28,13 @@ const getThemeHtmlAttrs = ({
28
28
  typography = themeStateDefaults['typography'],
29
29
  UNSAFE_themeOptions = themeStateDefaults['UNSAFE_themeOptions']
30
30
  } = {}) => {
31
- let themePreferences = {
31
+ const themeAttribute = themeObjectToString({
32
32
  dark,
33
33
  light,
34
34
  shape,
35
- // Load spacing by default
36
- spacing: spacing || 'spacing',
35
+ spacing,
37
36
  typography
38
- };
39
- const themeAttribute = themeObjectToString(themePreferences);
37
+ });
40
38
  const result = {
41
39
  [THEME_DATA_ATTRIBUTE]: themeAttribute,
42
40
  [COLOR_MODE_ATTRIBUTE]: colorMode === 'auto' ? defaultColorMode : colorMode
@@ -1,7 +1,7 @@
1
1
  import warnOnce from '@atlaskit/ds-lib/warn-once';
2
2
  import tokens from './artifacts/token-names';
3
3
  const name = "@atlaskit/tokens";
4
- const version = "1.22.0";
4
+ const version = "1.23.0";
5
5
  /**
6
6
  * Takes a dot-separated token name and and an optional fallback, and returns the current computed CSS value for the
7
7
  * resulting CSS Custom Property.
@@ -2,7 +2,7 @@ import warnOnce from '@atlaskit/ds-lib/warn-once';
2
2
  import tokens from './artifacts/token-names';
3
3
  import { TOKEN_NOT_FOUND_CSS_VAR } from './constants';
4
4
  const name = "@atlaskit/tokens";
5
- const version = "1.22.0";
5
+ const version = "1.23.0";
6
6
  /**
7
7
  * Takes a dot-separated token name and an optional fallback, and returns the CSS custom property for the corresponding token.
8
8
  * This should be used to implement design decisions throughout your application.
@@ -2,6 +2,7 @@ export { default as themeConfig } from './theme-config';
2
2
  export { default as token } from './get-token';
3
3
  export { default as getTokenValue } from './get-token-value';
4
4
  export { default as setGlobalTheme } from './set-global-theme';
5
+ export { default as enableGlobalTheme } from './enable-global-theme';
5
6
  export { default as getThemeStyles } from './get-theme-styles';
6
7
  export { default as getThemeHtmlAttrs } from './get-theme-html-attrs';
7
8
  export { default as getSSRAutoScript } from './get-ssr-auto-script';
@@ -0,0 +1,37 @@
1
+ import { loadAndAppendCustomThemeCss } from './custom-theme';
2
+ import { themeStateDefaults } from './theme-config';
3
+ import { isValidBrandHex } from './utils/color-utils';
4
+ import { findMissingCustomStyleElements } from './utils/custom-theme-loading-utils';
5
+
6
+ /**
7
+ * Synchronously generates and applies custom theme styles to the page.
8
+ *
9
+ * @param {Object<string, string>} themeState The themes and color mode that should be applied.
10
+ * @param {Object} themeState.UNSAFE_themeOptions The custom branding options to be used for custom theme generation
11
+ *
12
+ * @example
13
+ * ```
14
+ * UNSAFE_loadCustomThemeStyles({
15
+ * colorMode: 'auto',
16
+ * UNSAFE_themeOptions: { brandColor: '#FF0000' }
17
+ * });
18
+ * ```
19
+ */
20
+ const UNSAFE_loadCustomThemeStyles = ({
21
+ colorMode = themeStateDefaults['colorMode'],
22
+ UNSAFE_themeOptions = themeStateDefaults['UNSAFE_themeOptions']
23
+ } = {}) => {
24
+ // Load custom theme styles
25
+ if (UNSAFE_themeOptions && isValidBrandHex(UNSAFE_themeOptions === null || UNSAFE_themeOptions === void 0 ? void 0 : UNSAFE_themeOptions.brandColor)) {
26
+ const attrOfMissingCustomStyles = findMissingCustomStyleElements(UNSAFE_themeOptions, colorMode);
27
+ if (attrOfMissingCustomStyles.length !== 0) {
28
+ loadAndAppendCustomThemeCss({
29
+ colorMode: attrOfMissingCustomStyles.length === 2 ? 'auto' :
30
+ // only load the missing custom theme styles
31
+ attrOfMissingCustomStyles[0],
32
+ UNSAFE_themeOptions
33
+ });
34
+ }
35
+ }
36
+ };
37
+ export default UNSAFE_loadCustomThemeStyles;
@@ -1,28 +1,9 @@
1
- import { bind } from 'bind-event-listener';
2
- import noop from '@atlaskit/ds-lib/noop';
3
- import { COLOR_MODE_ATTRIBUTE } from './constants';
4
- import getThemeHtmlAttrs from './get-theme-html-attrs';
5
1
  import { themeStateDefaults } from './theme-config';
6
2
  import { isValidBrandHex } from './utils/color-utils';
3
+ import configurePage from './utils/configure-page';
7
4
  import { findMissingCustomStyleElements } from './utils/custom-theme-loading-utils';
8
5
  import { getThemePreferences } from './utils/get-theme-preferences';
9
- import { darkModeMediaQuery, loadAndAppendThemeCss } from './utils/theme-loading';
10
-
11
- // Represents theme state once mounted to the page (auto is hidden from observers)
12
-
13
- const isMatchMediaAvailable = typeof window !== 'undefined' && 'matchMedia' in window;
14
- const darkModeMql = isMatchMediaAvailable && window.matchMedia(darkModeMediaQuery);
15
- let unbindThemeChangeListener = noop;
16
-
17
- /**
18
- * Updates the current theme when the system theme changes. Should be bound
19
- * to an event listener listening on the '(prefers-color-scheme: dark)' query
20
- * @param e The event representing a change in system theme.
21
- */
22
- const checkNativeListener = function (e) {
23
- const element = document.documentElement;
24
- element.setAttribute(COLOR_MODE_ATTRIBUTE, e.matches ? 'dark' : 'light');
25
- };
6
+ import { loadAndAppendThemeCss } from './utils/theme-loading';
26
7
 
27
8
  /**
28
9
  * Sets the theme globally at runtime. This updates the `data-theme` and `data-color-mode` attributes on your page's <html> tag.
@@ -53,57 +34,45 @@ const setGlobalTheme = async ({
53
34
  typography = themeStateDefaults['typography'],
54
35
  UNSAFE_themeOptions = themeStateDefaults['UNSAFE_themeOptions']
55
36
  } = {}, themeLoader) => {
56
- const themePreferences = getThemePreferences({
37
+ const themeState = {
57
38
  colorMode,
58
39
  dark,
59
40
  light,
60
41
  shape,
61
42
  spacing,
62
- typography
63
- });
43
+ typography,
44
+ UNSAFE_themeOptions: themeLoader ? undefined : UNSAFE_themeOptions
45
+ };
46
+
47
+ // Determine what to load and loading strategy
48
+ const themePreferences = getThemePreferences(themeState);
64
49
  const loadingStrategy = themeLoader ? themeLoader : loadAndAppendThemeCss;
65
- await Promise.all([...themePreferences.map(async themeId => await loadingStrategy(themeId)), (async () => {
66
- if (!themeLoader && UNSAFE_themeOptions && isValidBrandHex(UNSAFE_themeOptions === null || UNSAFE_themeOptions === void 0 ? void 0 : UNSAFE_themeOptions.brandColor)) {
67
- const mode = colorMode || themeStateDefaults['colorMode'];
68
- const attrOfMissingCustomStyles = findMissingCustomStyleElements(UNSAFE_themeOptions, mode);
69
- if (attrOfMissingCustomStyles.length === 0) {
70
- return false;
71
- }
72
- const {
73
- loadAndAppendCustomThemeCss
74
- } = await import( /* webpackChunkName: "@atlaskit-internal_atlassian-custom-theme" */
75
- './custom-theme');
76
- await loadAndAppendCustomThemeCss({
77
- colorMode: attrOfMissingCustomStyles.length === 2 ? 'auto' :
78
- // only load the missing custom theme styles
79
- attrOfMissingCustomStyles[0],
80
- UNSAFE_themeOptions
81
- });
50
+
51
+ // Load standard themes
52
+ const loadingTasks = themePreferences.map(async themeId => await loadingStrategy(themeId));
53
+
54
+ // Load custom themes if needed
55
+ if (!themeLoader && UNSAFE_themeOptions && isValidBrandHex(UNSAFE_themeOptions === null || UNSAFE_themeOptions === void 0 ? void 0 : UNSAFE_themeOptions.brandColor)) {
56
+ const mode = colorMode || themeStateDefaults['colorMode'];
57
+ const attrOfMissingCustomStyles = findMissingCustomStyleElements(UNSAFE_themeOptions, mode);
58
+ if (attrOfMissingCustomStyles.length > 0) {
59
+ // Load custom theme styles
60
+ loadingTasks.push((async () => {
61
+ const {
62
+ loadAndAppendCustomThemeCss
63
+ } = await import( /* webpackChunkName: "@atlaskit-internal_atlassian-custom-theme" */
64
+ './custom-theme');
65
+ loadAndAppendCustomThemeCss({
66
+ colorMode: attrOfMissingCustomStyles.length === 2 ? 'auto' :
67
+ // only load the missing custom theme styles
68
+ attrOfMissingCustomStyles[0],
69
+ UNSAFE_themeOptions
70
+ });
71
+ })());
82
72
  }
83
- })()]);
84
- if (colorMode === 'auto' && darkModeMql) {
85
- colorMode = darkModeMql.matches ? 'dark' : 'light';
86
- // Add an event listener for changes to the system theme.
87
- // If the function exists, it will not be added again.
88
- unbindThemeChangeListener = bind(darkModeMql, {
89
- type: 'change',
90
- listener: checkNativeListener
91
- });
92
- } else {
93
- unbindThemeChangeListener();
94
73
  }
95
- const themeAttributes = getThemeHtmlAttrs({
96
- colorMode,
97
- dark,
98
- light,
99
- shape,
100
- spacing,
101
- typography,
102
- UNSAFE_themeOptions: themeLoader ? undefined : UNSAFE_themeOptions
103
- });
104
- Object.entries(themeAttributes).forEach(([key, value]) => {
105
- document.documentElement.setAttribute(key, value);
106
- });
107
- return unbindThemeChangeListener;
74
+ await Promise.all(loadingTasks);
75
+ const autoUnbind = configurePage(themeState);
76
+ return autoUnbind;
108
77
  };
109
78
  export default setGlobalTheme;
@@ -174,8 +174,14 @@ export const themeStateDefaults = {
174
174
  dark: 'dark',
175
175
  light: 'light',
176
176
  shape: undefined,
177
- spacing: undefined,
177
+ spacing: 'spacing',
178
178
  typography: undefined,
179
179
  UNSAFE_themeOptions: undefined
180
180
  };
181
+
182
+ /**
183
+ * Represents theme state once mounted to the page
184
+ * (the page doesn't have an "auto" color mode, it's either light or dark)
185
+ */
186
+
181
187
  export default themeConfig;
@@ -0,0 +1,48 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { bind } from 'bind-event-listener';
3
+ import { COLOR_MODE_ATTRIBUTE } from '../constants';
4
+ import { darkModeMediaQuery } from './theme-loading';
5
+ const isMatchMediaAvailable = typeof window !== 'undefined' && 'matchMedia' in window;
6
+
7
+ /**
8
+ * Updates the current theme when the system theme changes. Should be bound
9
+ * to an event listener listening on the '(prefers-color-scheme: dark)' query
10
+ * @param e The event representing a change in system theme.
11
+ */
12
+ function checkNativeListener(e) {
13
+ const element = document.documentElement;
14
+ element.setAttribute(COLOR_MODE_ATTRIBUTE, e.matches ? 'dark' : 'light');
15
+ }
16
+ const darkModeMql = isMatchMediaAvailable && window.matchMedia(darkModeMediaQuery);
17
+ class ColorModeObserver {
18
+ constructor() {
19
+ _defineProperty(this, "unbindThemeChangeListener", null);
20
+ }
21
+ getColorMode() {
22
+ if (!darkModeMql) {
23
+ return 'light';
24
+ }
25
+ return darkModeMql !== null && darkModeMql !== void 0 && darkModeMql.matches ? 'dark' : 'light';
26
+ }
27
+ bind() {
28
+ if (darkModeMql && this.unbindThemeChangeListener === null) {
29
+ this.unbindThemeChangeListener = bind(darkModeMql, {
30
+ type: 'change',
31
+ listener: checkNativeListener
32
+ });
33
+ }
34
+ }
35
+ unbind() {
36
+ if (this.unbindThemeChangeListener) {
37
+ this.unbindThemeChangeListener();
38
+ this.unbindThemeChangeListener = null;
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * A singleton color mode observer - binds "auto" switching logic to a single `mediaQueryList` listener
45
+ * that can be unbound by any consumer when no longer needed.
46
+ */
47
+ const SingletonColorModeObserver = new ColorModeObserver();
48
+ export default SingletonColorModeObserver;
@@ -0,0 +1,22 @@
1
+ import getThemeHtmlAttrs from '../get-theme-html-attrs';
2
+ import ColorModeObserver from './color-mode-listeners';
3
+
4
+ /**
5
+ * Given ThemeState, sets appropriate html attributes on the documentElement,
6
+ * adds a listener to keep colorMode updated, and returns a function to unbind.
7
+ */
8
+ export default function configurePage(themeState) {
9
+ if (themeState.colorMode === 'auto') {
10
+ // Set colorMode based on the user preference
11
+ themeState.colorMode = ColorModeObserver.getColorMode();
12
+ // Bind a listener (if one doesn't already exist) to keep colorMode updated
13
+ ColorModeObserver.bind();
14
+ } else {
15
+ ColorModeObserver.unbind();
16
+ }
17
+ const themeAttributes = getThemeHtmlAttrs(themeState);
18
+ Object.entries(themeAttributes).forEach(([key, value]) => {
19
+ document.documentElement.setAttribute(key, value);
20
+ });
21
+ return () => ColorModeObserver.unbind;
22
+ }
@@ -17,10 +17,5 @@ export const getThemePreferences = themeState => {
17
17
  if (getBooleanFF('platform.design-system-team.border-checkbox_nyoiu')) {
18
18
  themePreferences.push(`${themePreferences.includes('dark') ? 'dark' : 'light'}-new-input-border`);
19
19
  }
20
-
21
- // Load spacing by default
22
- if (!themePreferences.includes('spacing')) {
23
- themePreferences.push('spacing');
24
- }
25
20
  return [...new Set(themePreferences)];
26
21
  };
@@ -1,6 +1,7 @@
1
1
  export var THEME_DATA_ATTRIBUTE = 'data-theme';
2
2
  export var COLOR_MODE_ATTRIBUTE = 'data-color-mode';
3
3
  export var CUSTOM_THEME_ATTRIBUTE = 'data-custom-theme';
4
+ export var DEFAULT_THEME = 'light';
4
5
  export var CSS_PREFIX = 'ds';
5
6
  export var CSS_VAR_FULL = ['opacity', 'font', 'space', 'border'];
6
7
  export var TOKEN_NOT_FOUND_CSS_VAR = "--".concat(CSS_PREFIX, "-token-not-found");