@instructure/emotion 11.7.3-snapshot-33 → 11.7.3-snapshot-37

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 (46) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/es/getTheme.js +1 -1
  3. package/es/index.js +3 -3
  4. package/es/useStyle.js +16 -28
  5. package/es/useStyleNew.js +79 -0
  6. package/es/withStyle.js +24 -93
  7. package/es/withStyleNew.js +185 -0
  8. package/lib/getTheme.js +1 -1
  9. package/lib/index.js +10 -10
  10. package/lib/useStyle.js +17 -25
  11. package/lib/useStyleNew.js +85 -0
  12. package/lib/withStyle.js +23 -93
  13. package/lib/withStyleNew.js +195 -0
  14. package/package.json +10 -10
  15. package/src/InstUISettingsProvider/README.md +1 -1
  16. package/src/getComponentThemeOverride.ts +1 -1
  17. package/src/getTheme.ts +1 -1
  18. package/src/index.ts +4 -4
  19. package/src/useStyle.ts +47 -78
  20. package/src/useStyleNew.ts +146 -0
  21. package/src/withStyle.tsx +43 -142
  22. package/src/withStyleNew.tsx +322 -0
  23. package/tsconfig.build.tsbuildinfo +1 -1
  24. package/types/getComponentThemeOverride.d.ts +1 -1
  25. package/types/getComponentThemeOverride.d.ts.map +1 -1
  26. package/types/getTheme.d.ts +1 -1
  27. package/types/index.d.ts +4 -4
  28. package/types/index.d.ts.map +1 -1
  29. package/types/useStyle.d.ts +17 -16
  30. package/types/useStyle.d.ts.map +1 -1
  31. package/types/useStyleNew.d.ts +23 -0
  32. package/types/useStyleNew.d.ts.map +1 -0
  33. package/types/withStyle.d.ts +7 -56
  34. package/types/withStyle.d.ts.map +1 -1
  35. package/types/withStyleNew.d.ts +71 -0
  36. package/types/withStyleNew.d.ts.map +1 -0
  37. package/es/useStyleLegacy.js +0 -50
  38. package/es/withStyleLegacy.js +0 -112
  39. package/lib/useStyleLegacy.js +0 -60
  40. package/lib/withStyleLegacy.js +0 -121
  41. package/src/useStyleLegacy.ts +0 -92
  42. package/src/withStyleLegacy.tsx +0 -217
  43. package/types/useStyleLegacy.d.ts +0 -22
  44. package/types/useStyleLegacy.d.ts.map +0 -1
  45. package/types/withStyleLegacy.d.ts +0 -22
  46. package/types/withStyleLegacy.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -3,7 +3,7 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [11.7.3-snapshot-33](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-33) (2026-05-07)
6
+ ## [11.7.3-snapshot-37](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-37) (2026-05-07)
7
7
 
8
8
 
9
9
  ### Bug Fixes
@@ -11,6 +11,11 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
11
11
  * **many:** update dependencies, remove lots of Babel plugins, remove Webpack 4 support ([f916fca](https://github.com/instructure/instructure-ui/commit/f916fcafdddcb2d7de401f93e8ff92cfdfa47bba))
12
12
 
13
13
 
14
+ ### Features
15
+
16
+ * **many:** add a way for consumers to pass their own component theme definition so they can build their own components with InstUI ([ce01c3e](https://github.com/instructure/instructure-ui/commit/ce01c3eedc46aa2588f4c8309a6eabf4461aaec7))
17
+
18
+
14
19
 
15
20
 
16
21
 
package/es/getTheme.js CHANGED
@@ -38,7 +38,7 @@ import { isBaseTheme, mergeDeep } from '@instructure/ui-utils';
38
38
  * @param themeOverride - if provided, it means it's a new theming-system override.
39
39
  * This will be merged into theme.themeOverride and will be treated separately
40
40
  * from the old way of applying overrides. This override will be applied in the
41
- * `withStyle.ts` decorator
41
+ * `withStyleNew.ts` decorator
42
42
  * @returns A function that returns with the theme object for the [ThemeProvider](https://emotion.sh/docs/theming#themeprovider-reactcomponenttype)
43
43
  * This function is called by Emotion on theme provider creation, where
44
44
  * `ancestorTheme` is a theme object from an ancestor `ThemeProvider`
package/es/index.js CHANGED
@@ -26,10 +26,10 @@
26
26
  export * from '@emotion/react';
27
27
  export { useComputedTheme } from "./useComputedTheme.js";
28
28
  export { InstUISettingsProvider } from "./InstUISettingsProvider/index.js";
29
- export { withStyleLegacy } from "./withStyleLegacy.js";
30
- export { getComponentThemeOverride } from "./getComponentThemeOverride.js";
31
29
  export { withStyle } from "./withStyle.js";
30
+ export { getComponentThemeOverride } from "./getComponentThemeOverride.js";
31
+ export { withStyleNew } from "./withStyleNew.js";
32
32
  export { ThemeablePropValues, makeThemeVars, getShorthandPropValue, mirrorShorthandCorners, mirrorShorthandEdges, calcSpacingFromShorthand, calcFocusOutlineStyles } from "./styleUtils/index.js";
33
- export { useStyleLegacy } from "./useStyleLegacy.js";
34
33
  export { useStyle } from "./useStyle.js";
34
+ export { useStyleNew } from "./useStyleNew.js";
35
35
  export { useTheme } from "./useTheme.js";
package/es/useStyle.js CHANGED
@@ -22,41 +22,29 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
  import { useTheme } from "./useTheme.js";
25
- import { mergeDeep } from '@instructure/ui-utils';
26
-
27
- // returns the second parameter of a function
28
-
29
- /**
30
- * new useStyle syntax, use this with v11.7+ themes
25
+ import { getComponentThemeOverride } from "./getComponentThemeOverride.js"; // returns the second parameter of a function
26
+ // TODO this is only used by the old themes, remove when everything uses the new
27
+ // theming system
28
+ /*
29
+ * This is only used by the **old themes**, remove when everything uses the new
30
+ * theming system (InstUI v12)
31
31
  */
32
- // TODO: improve useStyle to handle generateStyle functions that don't
33
- // have a theme.
34
32
  const useStyle = useStyleParams => {
35
33
  const {
36
34
  generateStyle,
37
35
  params,
38
36
  componentId,
39
- themeOverride
37
+ displayName
40
38
  } = useStyleParams;
41
- const useTokensFrom = useStyleParams.useTokensFrom;
42
- const themeInContext = useTheme();
43
- const themeOverrideFromProvider = themeInContext.themeOverride;
44
- const componentWithTokensId = useTokensFrom ?? componentId;
45
-
46
- // resolving the theming functions and applying the overrides
47
- const primitiveOverrides = themeOverrideFromProvider?.primitives;
48
- const semanticsOverrides = themeOverrideFromProvider?.semantics;
49
- const sharedTokensOverrides = themeOverrideFromProvider?.sharedTokens;
50
- const componentOverridesFromSettingsProvider = themeOverrideFromProvider?.components?.[componentWithTokensId];
51
- const primitives = mergeDeep(themeInContext.newTheme.primitives, primitiveOverrides);
52
- const semantics = mergeDeep(themeInContext.newTheme.semantics?.(primitives), semanticsOverrides);
53
- const sharedTokens = mergeDeep(themeInContext.newTheme.sharedTokens?.(semantics), sharedTokensOverrides);
54
- const baseComponentTheme = themeInContext.newTheme.components[componentWithTokensId]?.(semantics);
55
- const componentThemeFromSettingsProvider = mergeDeep(baseComponentTheme, componentOverridesFromSettingsProvider);
56
- const componentTheme = mergeDeep(componentThemeFromSettingsProvider, typeof themeOverride === 'function' ? themeOverride(componentThemeFromSettingsProvider, themeInContext) : themeOverride);
57
-
58
- // @ts-ignore TODO-theme-types: fix typing
59
- return generateStyle(componentTheme, params, sharedTokens);
39
+ const generateComponentTheme = useStyleParams?.generateComponentTheme;
40
+ const theme = useTheme();
41
+ const baseComponentTheme = typeof generateComponentTheme === 'function' ? generateComponentTheme(theme) : {};
42
+ const themeOverride = getComponentThemeOverride(theme, displayName ?? componentId ?? '', componentId, params?.themeOverride, baseComponentTheme);
43
+ const componentTheme = {
44
+ ...baseComponentTheme,
45
+ ...themeOverride
46
+ };
47
+ return generateStyle(componentTheme, params ? params : {}, theme);
60
48
  };
61
49
  export default useStyle;
62
50
  export { useStyle };
@@ -0,0 +1,79 @@
1
+ /*
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) 2015 - present Instructure, Inc.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+ import { useTheme } from "./useTheme.js";
25
+ import { mergeDeep } from '@instructure/ui-utils';
26
+
27
+ // returns the second parameter of a function
28
+
29
+ /**
30
+ * new useStyleNew syntax, use this with v11.7+ themes
31
+ */
32
+ // TODO: improve useStyleNew to handle generateStyle functions that don't
33
+ // have a theme.
34
+ const useStyleNew = useStyleParams => {
35
+ const {
36
+ generateStyle,
37
+ params,
38
+ componentId,
39
+ themeOverride,
40
+ frozenTheme,
41
+ generateComponentTheme
42
+ } = useStyleParams;
43
+ const useTokensFrom = useStyleParams.useTokensFrom;
44
+ const themeInContext = useTheme();
45
+ const themeKey = themeInContext.key;
46
+
47
+ // if a new theme has been added to the lib since this component version has been frozen, it can't be used with this
48
+ // theme, so we throw an error. Solution: upgrade to the latest version, it will support it
49
+ if (frozenTheme && !frozenTheme[themeKey]) {}
50
+
51
+ // if this component is an older component version but still uses the new theming system, it'll have a frozenTheme
52
+ // object passed to it. We use that instead of the current theme so backward compatibility stays intact
53
+ const theme = frozenTheme ? {
54
+ newTheme: frozenTheme[themeKey]
55
+ } : themeInContext;
56
+ const themeOverrideFromProvider = themeInContext.themeOverride;
57
+ const componentWithTokensId = useTokensFrom ?? componentId;
58
+
59
+ // resolving the theming functions and applying the overrides
60
+ const primitiveOverrides = themeOverrideFromProvider?.primitives;
61
+ const semanticsOverrides = themeOverrideFromProvider?.semantics;
62
+ const sharedTokensOverrides = themeOverrideFromProvider?.sharedTokens;
63
+ const componentOverridesFromSettingsProvider = themeOverrideFromProvider?.components?.[componentWithTokensId];
64
+ const primitives = mergeDeep(theme.newTheme.primitives, primitiveOverrides);
65
+ const semantics = mergeDeep(theme.newTheme.semantics?.(primitives), semanticsOverrides);
66
+ const sharedTokens = mergeDeep(theme.newTheme.sharedTokens?.(semantics), sharedTokensOverrides);
67
+ const baseComponentTheme = generateComponentTheme ? generateComponentTheme({
68
+ primitives,
69
+ semantics,
70
+ sharedTokens
71
+ }) : theme.newTheme.components[componentWithTokensId]?.(semantics);
72
+ const componentThemeFromSettingsProvider = mergeDeep(baseComponentTheme, componentOverridesFromSettingsProvider);
73
+ const componentTheme = mergeDeep(componentThemeFromSettingsProvider, typeof themeOverride === 'function' ? themeOverride(componentThemeFromSettingsProvider, themeInContext) : themeOverride);
74
+
75
+ // @ts-ignore TODO-theme-types: fix typing
76
+ return generateStyle(componentTheme, params, sharedTokens);
77
+ };
78
+ export default useStyleNew;
79
+ export { useStyleNew };
package/es/withStyle.js CHANGED
@@ -24,9 +24,10 @@
24
24
 
25
25
  import { forwardRef, useState } from 'react';
26
26
  import hoistNonReactStatics from 'hoist-non-react-statics';
27
- import { deepEqual as isEqual, mergeDeep } from '@instructure/ui-utils';
27
+ import { deepEqual as isEqual } from '@instructure/ui-utils';
28
28
  import { warn } from '@instructure/console';
29
29
  import { decorator } from '@instructure/ui-decorator';
30
+ import { getComponentThemeOverride } from "./getComponentThemeOverride.js";
30
31
  import { useTheme } from "./useTheme.js"; // Extract is needed because it would allow number otherwise
31
32
  // https://stackoverflow.com/a/51808262/319473
32
33
  // Unique name of an InstUI component
@@ -40,111 +41,33 @@ const defaultValues = {
40
41
  * ---
41
42
  * category: utilities/themes
42
43
  * ---
43
- *
44
- * A decorator or higher order component that makes a component themeable.
45
- *
46
- * It adds a `makeStyles` function and the generated `styles` object to the decorated Component's props. If it has an own theme, it also adds the `themeOverride` prop to the component.
47
- *
48
- * As a HOC:
49
- *
50
- * ```js-code
51
- * import { withStyle } from '@instructure/emotion'
52
- * import generateStyle from './styles'
53
- *
54
- * export default withStyle(generateStyle)(ExampleComponent)
55
- * ```
56
- *
57
- * Themeable components inject their themed styles into the document
58
- * when they are mounted.
59
- *
60
- * ### Applying themes
61
- *
62
- * A themeable component’s theme can be configured via wrapping it in an
63
- * [InstUISettingsProvider](InstUISettingsProvider) component, and/or set
64
- * explicitly via its `themeOverride` prop.
65
- *
66
- * InstUISettingsProvider provides a theme object (e.g. the [canvas theme](/#canvas)).
67
- * These variables are mapped to the component's own variables in `theme.js` (see [theming](theming-basics) for more info).
68
- *
69
- * With the `themeOverride` prop you can directly set/override the component theme variables declared in theme.js. It accepts an object or a function. The function has the component's theme and the currently active main theme as its parameter.
70
- *
71
- * See more about the overrides on the [Using theme overrides](/#using-theme-overrides) docs page.
72
- *
73
- * ```jsx-code
74
- * {// global theme override}
75
- * <InstUISettingsProvider theme={{
76
- * colors: { backgroundMedium: '#888' }
77
- * }}>
78
- * {// component theme override}
79
- * <ExampleComponent themeOverride={{ hoverColor: '#eee' }} />
80
- *
81
- * {// component theme override with function}
82
- * <ExampleComponent themeOverride={(componentTheme, currentTheme) => ({
83
- * hoverBackground: componentTheme.background,
84
- * activeBackground: currentTheme.colors.backgroundBrand
85
- * })} />
86
- * </InstUISettingsProvider>
87
- * ```
88
- *
89
- * @module withStyle
90
- *
91
- * @param {function} generateStyle - The function that returns the component's style object
92
- * @returns {ReactElement} The decorated WithStyle Component
44
+ * used for old (v11 and eariler) theming system
45
+ * TODO delete when the theme migration is complete
93
46
  */
94
- const withStyle = decorator((ComposedComponent, generateStyle, useTokensFrom, frozenTheme) => {
47
+ const withStyle = decorator((ComposedComponent, generateStyle, generateComponentTheme) => {
95
48
  const displayName = ComposedComponent.displayName || ComposedComponent.name;
96
- const componentId = useTokensFrom ?? ComposedComponent.componentId?.replace('.', '');
97
49
  const WithStyle = /*#__PURE__*/forwardRef((props, ref) => {
98
- const themeInContext = useTheme();
99
- const themeKey = themeInContext.key;
100
-
101
- // this is for the new overrides. theme.themeOverride has all the overrides
102
- const themeOverride = themeInContext.themeOverride;
103
-
104
- // if a new theme has been added to the lib since this component version has been frozen, it can't be used with this
105
- // theme, so we throw an error. Solution: upgrade to the latest version, it will support it
106
- if (frozenTheme && !frozenTheme[themeKey]) {}
107
-
108
- // if this component is an older component version but still uses the new theming system, it'll have a frozenTheme
109
- // object passed to it. We use that instead of the current theme so backward compatibility stays intact
110
- const theme = frozenTheme ? {
111
- newTheme: frozenTheme[themeKey]
112
- } : themeInContext;
50
+ const theme = useTheme();
113
51
  if (props.styles) {
114
- warn(false, `Manually passing the "styles" property is not allowed on the ${displayName} component. Using the default styles calculated by the @withStyle decorator instead.\n`, props.styles);
52
+ warn(false, `Manually passing the "styles" property is not allowed on the ${displayName} component. Using the default styles calculated by the @withStyleNew decorator instead.\n`, props.styles);
115
53
  }
116
54
  if (props.makeStyles) {
117
- warn(false, `Manually passing the "makeStyles" property is not allowed on the ${displayName} component. Styles are calculated by the @withStyle decorator.`);
55
+ warn(false, `Manually passing the "makeStyles" property is not allowed on the ${displayName} component. Styles are calculated by the @withStyleNew decorator.`);
118
56
  }
119
57
  const componentProps = {
120
58
  ...ComposedComponent.defaultProps,
121
59
  ...props,
122
60
  ...defaultValues
123
61
  };
124
- // resolving the theming functions and applying the overrides
125
- const primitiveOverrides = themeOverride?.primitives;
126
- const semanticsOverrides = themeOverride?.semantics;
127
- const sharedTokensOverrides = themeOverride?.sharedTokens;
128
- const componentOverridesFromSettingsProvider = themeOverride?.components?.[componentId];
129
- const componentOverridesFromThemeOverrideProp = componentProps.themeOverride;
130
- const primitives = mergeDeep(theme.newTheme.primitives, primitiveOverrides);
131
- const semantics = mergeDeep(theme.newTheme.semantics?.(primitives), semanticsOverrides);
132
- const sharedTokens = mergeDeep(theme.newTheme.sharedTokens?.(semantics), sharedTokensOverrides);
133
- // Note: Some components do not have a theme, e.g., FormFieldMessages
134
- const baseComponentTheme = theme.newTheme.components[componentId]?.(semantics);
135
- const componentThemeFromSettingsProvider = mergeDeep(baseComponentTheme, componentOverridesFromSettingsProvider);
136
- const componentTheme = mergeDeep(componentThemeFromSettingsProvider,
137
- // @ts-ignore TODO-theme-types: fix typing
138
- typeof componentOverridesFromThemeOverrideProp === 'function' ? componentOverridesFromThemeOverrideProp(componentThemeFromSettingsProvider, themeInContext) : componentOverridesFromThemeOverrideProp);
139
-
140
- // TODO do not call here generateStyle, it does not receive the extraArgs
141
- const [styles, setStyles] = useState(generateStyle ?
142
- // @ts-ignore TODO-theme-types: fix typing
143
- generateStyle(componentTheme, componentProps, sharedTokens, {}) : {});
62
+ let componentTheme = typeof generateComponentTheme === 'function' ? generateComponentTheme(theme) : {};
63
+ const themeOverride = getComponentThemeOverride(theme, displayName, ComposedComponent.componentId, componentProps.themeOverride, componentTheme);
64
+ componentTheme = {
65
+ ...componentTheme,
66
+ ...themeOverride
67
+ };
68
+ const [styles, setStyles] = useState(generateStyle ? generateStyle(componentTheme, componentProps, {}) : {});
144
69
  const makeStyleHandler = extraArgs => {
145
- const calculatedStyles = generateStyle(componentTheme, componentProps,
146
- // @ts-ignore TODO-theme-types: fix typing
147
- sharedTokens, extraArgs);
70
+ const calculatedStyles = generateStyle(componentTheme, componentProps, extraArgs);
148
71
  if (!isEqual(calculatedStyles, styles)) {
149
72
  setStyles(calculatedStyles);
150
73
  }
@@ -154,6 +77,11 @@ const withStyle = decorator((ComposedComponent, generateStyle, useTokensFrom, fr
154
77
  ...props,
155
78
  makeStyles: makeStyleHandler,
156
79
  styles: styles
80
+ // passing themeOverrides is needed for components like Button
81
+ // that have no makeStyles of their own and only pass themeOverrides
82
+ // to the underlying component (e.g.: BaseButton)
83
+ ,
84
+ themeOverride: themeOverride
157
85
  });
158
86
  });
159
87
  hoistNonReactStatics(WithStyle, ComposedComponent);
@@ -165,6 +93,9 @@ const withStyle = decorator((ComposedComponent, generateStyle, useTokensFrom, fr
165
93
  // These static fields exist on InstUI components
166
94
  WithStyle.allowedProps = ComposedComponent.allowedProps;
167
95
 
96
+ // we are exposing the theme generator for the docs generation
97
+ WithStyle.generateComponentTheme = generateComponentTheme;
98
+
168
99
  // we have to add defaults to makeStyles and styles added by this decorator
169
100
  // eslint-disable-next-line no-param-reassign
170
101
  ComposedComponent.defaultProps = {
@@ -0,0 +1,185 @@
1
+ /*
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) 2015 - present Instructure, Inc.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+
25
+ import { forwardRef, useState } from 'react';
26
+ import hoistNonReactStatics from 'hoist-non-react-statics';
27
+ import { deepEqual as isEqual, mergeDeep } from '@instructure/ui-utils';
28
+ import { warn } from '@instructure/console';
29
+ import { decorator } from '@instructure/ui-decorator';
30
+ import { useTheme } from "./useTheme.js"; // Extract is needed because it would allow number otherwise
31
+ // https://stackoverflow.com/a/51808262/319473
32
+ // Unique name of an InstUI component
33
+ import { jsx as _jsx } from "@emotion/react/jsx-runtime";
34
+ const defaultValues = {
35
+ styles: {},
36
+ makeStyles: () => {}
37
+ };
38
+
39
+ /**
40
+ * ---
41
+ * category: utilities/themes
42
+ * ---
43
+ *
44
+ * A decorator or higher order component that makes a component themeable.
45
+ *
46
+ * It adds a `makeStyles` function and the generated `styles` object to the decorated Component's props. If it has an own theme, it also adds the `themeOverride` prop to the component.
47
+ *
48
+ * As a HOC:
49
+ *
50
+ * ```js-code
51
+ * import { withStyleNew } from '@instructure/emotion'
52
+ * import generateStyle from './styles'
53
+ *
54
+ * export default withStyleNew(generateStyle)(ExampleComponent)
55
+ * ```
56
+ *
57
+ * Themeable components inject their themed styles into the document
58
+ * when they are mounted.
59
+ *
60
+ * ### Applying themes
61
+ *
62
+ * A themeable component’s theme can be configured via wrapping it in an
63
+ * [InstUISettingsProvider](InstUISettingsProvider) component, and/or set
64
+ * explicitly via its `themeOverride` prop.
65
+ *
66
+ * InstUISettingsProvider provides a theme object (e.g. the [canvas theme](/#canvas)).
67
+ * These variables are mapped to the component's own variables in `theme.js` (see [theming](theming-basics) for more info).
68
+ *
69
+ * With the `themeOverride` prop you can directly set/override the component theme variables declared in theme.js. It accepts an object or a function. The function has the component's theme and the currently active main theme as its parameter.
70
+ *
71
+ * See more about the overrides on the [Using theme overrides](/#using-theme-overrides) docs page.
72
+ *
73
+ * ```jsx-code
74
+ * {// global theme override}
75
+ * <InstUISettingsProvider theme={{
76
+ * colors: { backgroundMedium: '#888' }
77
+ * }}>
78
+ * {// component theme override}
79
+ * <ExampleComponent themeOverride={{ hoverColor: '#eee' }} />
80
+ *
81
+ * {// component theme override with function}
82
+ * <ExampleComponent themeOverride={(componentTheme, currentTheme) => ({
83
+ * hoverBackground: componentTheme.background,
84
+ * activeBackground: currentTheme.colors.backgroundBrand
85
+ * })} />
86
+ * </InstUISettingsProvider>
87
+ * ```
88
+ *
89
+ * @module withStyleNew
90
+ *
91
+ * @param {function} generateStyle - The function that returns the component's style object
92
+ * @returns {ReactElement} The decorated WithStyle Component
93
+ */
94
+ const withStyleNew = decorator((ComposedComponent, generateStyle, useTokensFrom, frozenTheme, generateComponentTheme) => {
95
+ const displayName = ComposedComponent.displayName || ComposedComponent.name;
96
+ const componentId = useTokensFrom ?? ComposedComponent.componentId?.replace('.', '');
97
+ const WithStyle = /*#__PURE__*/forwardRef((props, ref) => {
98
+ const themeInContext = useTheme();
99
+ const themeKey = themeInContext.key;
100
+
101
+ // this is for the new overrides. theme.themeOverride has all the overrides
102
+ const themeOverride = themeInContext.themeOverride;
103
+
104
+ // if a new theme has been added to the lib since this component version has been frozen, it can't be used with this
105
+ // theme, so we throw an error. Solution: upgrade to the latest version, it will support it
106
+ if (frozenTheme && !frozenTheme[themeKey]) {}
107
+
108
+ // if this component is an older component version but still uses the new theming system, it'll have a frozenTheme
109
+ // object passed to it. We use that instead of the current theme so backward compatibility stays intact
110
+ const theme = frozenTheme ? {
111
+ newTheme: frozenTheme[themeKey]
112
+ } : themeInContext;
113
+ if (props.styles) {
114
+ warn(false, `Manually passing the "styles" property is not allowed on the ${displayName} component. Using the default styles calculated by the @withStyleNew decorator instead.\n`, props.styles);
115
+ }
116
+ if (props.makeStyles) {
117
+ warn(false, `Manually passing the "makeStyles" property is not allowed on the ${displayName} component. Styles are calculated by the @withStyleNew decorator.`);
118
+ }
119
+ const componentProps = {
120
+ ...ComposedComponent.defaultProps,
121
+ ...props,
122
+ ...defaultValues
123
+ };
124
+ // resolving the theming functions and applying the overrides
125
+ const primitiveOverrides = themeOverride?.primitives;
126
+ const semanticsOverrides = themeOverride?.semantics;
127
+ const sharedTokensOverrides = themeOverride?.sharedTokens;
128
+ const componentOverridesFromSettingsProvider = themeOverride?.components?.[componentId];
129
+ const componentOverridesFromThemeOverrideProp = componentProps.themeOverride;
130
+ const primitives = mergeDeep(theme.newTheme.primitives, primitiveOverrides);
131
+ const semantics = mergeDeep(theme.newTheme.semantics?.(primitives), semanticsOverrides);
132
+ const sharedTokens = mergeDeep(theme.newTheme.sharedTokens?.(semantics), sharedTokensOverrides);
133
+ // Note: Some components do not have a theme, e.g., FormFieldMessages
134
+ const baseComponentTheme = generateComponentTheme ? generateComponentTheme({
135
+ primitives,
136
+ semantics,
137
+ sharedTokens
138
+ }) : theme.newTheme.components[componentId]?.(semantics);
139
+ const componentThemeFromSettingsProvider = mergeDeep(baseComponentTheme, componentOverridesFromSettingsProvider);
140
+ const componentTheme = mergeDeep(componentThemeFromSettingsProvider,
141
+ // @ts-ignore TODO-theme-types: fix typing
142
+ typeof componentOverridesFromThemeOverrideProp === 'function' ? componentOverridesFromThemeOverrideProp(componentThemeFromSettingsProvider, themeInContext) : componentOverridesFromThemeOverrideProp);
143
+
144
+ // TODO do not call here generateStyle, it does not receive the extraArgs
145
+ const [styles, setStyles] = useState(generateStyle ?
146
+ // @ts-ignore TODO-theme-types: fix typing
147
+ generateStyle(componentTheme, componentProps, sharedTokens, {}) : {});
148
+ const makeStyleHandler = extraArgs => {
149
+ const calculatedStyles = generateStyle(componentTheme, componentProps,
150
+ // @ts-ignore TODO-theme-types: fix typing
151
+ sharedTokens, extraArgs);
152
+ if (!isEqual(calculatedStyles, styles)) {
153
+ setStyles(calculatedStyles);
154
+ }
155
+ };
156
+ return _jsx(ComposedComponent, {
157
+ ref: ref,
158
+ ...props,
159
+ makeStyles: makeStyleHandler,
160
+ styles: styles
161
+ });
162
+ });
163
+ hoistNonReactStatics(WithStyle, ComposedComponent);
164
+
165
+ // added so it can be tested with ReactTestUtils
166
+ // more info: https://github.com/facebook/react/issues/13455
167
+ WithStyle.originalType = ComposedComponent.originalType || ComposedComponent;
168
+ WithStyle.defaultProps = ComposedComponent.defaultProps;
169
+ // These static fields exist on InstUI components
170
+ WithStyle.allowedProps = ComposedComponent.allowedProps;
171
+
172
+ // we have to add defaults to makeStyles and styles added by this decorator
173
+ // eslint-disable-next-line no-param-reassign
174
+ ComposedComponent.defaultProps = {
175
+ ...ComposedComponent.defaultProps,
176
+ makeStyles: defaultValues.makeStyles,
177
+ styles: defaultValues.styles
178
+ };
179
+ if (typeof process !== 'undefined' && process?.env?.NODE_ENV !== 'production') {
180
+ WithStyle.displayName = `WithStyle(${displayName})`;
181
+ }
182
+ return WithStyle;
183
+ });
184
+ export default withStyleNew;
185
+ export { withStyleNew };
package/lib/getTheme.js CHANGED
@@ -47,7 +47,7 @@ var _mergeDeep = require("@instructure/ui-utils/lib/mergeDeep.js");
47
47
  * @param themeOverride - if provided, it means it's a new theming-system override.
48
48
  * This will be merged into theme.themeOverride and will be treated separately
49
49
  * from the old way of applying overrides. This override will be applied in the
50
- * `withStyle.ts` decorator
50
+ * `withStyleNew.ts` decorator
51
51
  * @returns A function that returns with the theme object for the [ThemeProvider](https://emotion.sh/docs/theming#themeprovider-reactcomponenttype)
52
52
  * This function is called by Emotion on theme provider creation, where
53
53
  * `ancestorTheme` is a theme object from an ancestor `ThemeProvider`
package/lib/index.js CHANGED
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", {
6
6
  var _exportNames = {
7
7
  useComputedTheme: true,
8
8
  InstUISettingsProvider: true,
9
- withStyleLegacy: true,
10
- getComponentThemeOverride: true,
11
9
  withStyle: true,
10
+ getComponentThemeOverride: true,
11
+ withStyleNew: true,
12
12
  ThemeablePropValues: true,
13
13
  makeThemeVars: true,
14
14
  getShorthandPropValue: true,
@@ -16,8 +16,8 @@ var _exportNames = {
16
16
  mirrorShorthandEdges: true,
17
17
  calcSpacingFromShorthand: true,
18
18
  calcFocusOutlineStyles: true,
19
- useStyleLegacy: true,
20
19
  useStyle: true,
20
+ useStyleNew: true,
21
21
  useTheme: true
22
22
  };
23
23
  Object.defineProperty(exports, "InstUISettingsProvider", {
@@ -86,10 +86,10 @@ Object.defineProperty(exports, "useStyle", {
86
86
  return _useStyle.useStyle;
87
87
  }
88
88
  });
89
- Object.defineProperty(exports, "useStyleLegacy", {
89
+ Object.defineProperty(exports, "useStyleNew", {
90
90
  enumerable: true,
91
91
  get: function () {
92
- return _useStyleLegacy.useStyleLegacy;
92
+ return _useStyleNew.useStyleNew;
93
93
  }
94
94
  });
95
95
  Object.defineProperty(exports, "useTheme", {
@@ -104,10 +104,10 @@ Object.defineProperty(exports, "withStyle", {
104
104
  return _withStyle.withStyle;
105
105
  }
106
106
  });
107
- Object.defineProperty(exports, "withStyleLegacy", {
107
+ Object.defineProperty(exports, "withStyleNew", {
108
108
  enumerable: true,
109
109
  get: function () {
110
- return _withStyleLegacy.withStyleLegacy;
110
+ return _withStyleNew.withStyleNew;
111
111
  }
112
112
  });
113
113
  var _react = require("@emotion/react");
@@ -124,10 +124,10 @@ Object.keys(_react).forEach(function (key) {
124
124
  });
125
125
  var _useComputedTheme = require("./useComputedTheme");
126
126
  var _InstUISettingsProvider = require("./InstUISettingsProvider");
127
- var _withStyleLegacy = require("./withStyleLegacy");
128
- var _getComponentThemeOverride = require("./getComponentThemeOverride");
129
127
  var _withStyle = require("./withStyle");
128
+ var _getComponentThemeOverride = require("./getComponentThemeOverride");
129
+ var _withStyleNew = require("./withStyleNew");
130
130
  var _styleUtils = require("./styleUtils");
131
- var _useStyleLegacy = require("./useStyleLegacy");
132
131
  var _useStyle = require("./useStyle");
132
+ var _useStyleNew = require("./useStyleNew");
133
133
  var _useTheme = require("./useTheme");