@instructure/emotion 11.6.0 → 11.6.1-snapshot-129

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 (69) hide show
  1. package/CHANGELOG.md +51 -303
  2. package/es/InstUISettingsProvider/index.js +1 -1
  3. package/es/getComponentThemeOverride.js +5 -4
  4. package/es/getTheme.js +2 -2
  5. package/es/index.js +4 -1
  6. package/es/styleUtils/calcFocusOutlineStyles.js +71 -0
  7. package/es/styleUtils/calcSpacingFromShorthand.js +112 -0
  8. package/es/styleUtils/index.js +2 -1
  9. package/es/useStyle.js +27 -6
  10. package/es/useStyleLegacy.js +49 -0
  11. package/es/useTheme.js +1 -1
  12. package/es/withStyle.js +13 -31
  13. package/es/withStyleLegacy.js +116 -0
  14. package/lib/InstUISettingsProvider/index.js +1 -1
  15. package/lib/getComponentThemeOverride.js +5 -4
  16. package/lib/getTheme.js +2 -2
  17. package/lib/index.js +38 -7
  18. package/lib/styleUtils/calcFocusOutlineStyles.js +78 -0
  19. package/lib/styleUtils/calcSpacingFromShorthand.js +118 -0
  20. package/lib/styleUtils/index.js +14 -7
  21. package/lib/useStyle.js +28 -6
  22. package/lib/useStyleLegacy.js +59 -0
  23. package/lib/useTheme.js +1 -1
  24. package/lib/withStyle.js +13 -31
  25. package/lib/withStyleLegacy.js +125 -0
  26. package/package.json +11 -9
  27. package/src/EmotionTypes.ts +10 -1
  28. package/src/InstUISettingsProvider/index.tsx +5 -1
  29. package/src/getComponentThemeOverride.ts +9 -8
  30. package/src/getTheme.ts +8 -2
  31. package/src/index.ts +7 -2
  32. package/src/styleUtils/calcFocusOutlineStyles.ts +106 -0
  33. package/src/styleUtils/calcSpacingFromShorthand.ts +127 -0
  34. package/src/styleUtils/index.ts +2 -1
  35. package/src/useStyle.ts +63 -32
  36. package/src/useStyleLegacy.ts +92 -0
  37. package/src/useTheme.ts +4 -1
  38. package/src/withStyle.tsx +29 -39
  39. package/src/withStyleLegacy.tsx +212 -0
  40. package/tsconfig.build.json +3 -0
  41. package/tsconfig.build.tsbuildinfo +1 -1
  42. package/types/EmotionTypes.d.ts +4 -2
  43. package/types/EmotionTypes.d.ts.map +1 -1
  44. package/types/InstUISettingsProvider/index.d.ts.map +1 -1
  45. package/types/getComponentThemeOverride.d.ts +4 -5
  46. package/types/getComponentThemeOverride.d.ts.map +1 -1
  47. package/types/getTheme.d.ts.map +1 -1
  48. package/types/index.d.ts +6 -2
  49. package/types/index.d.ts.map +1 -1
  50. package/types/styleUtils/calcFocusOutlineStyles.d.ts +51 -0
  51. package/types/styleUtils/calcFocusOutlineStyles.d.ts.map +1 -0
  52. package/types/styleUtils/calcSpacingFromShorthand.d.ts +33 -0
  53. package/types/styleUtils/calcSpacingFromShorthand.d.ts.map +1 -0
  54. package/types/styleUtils/index.d.ts +2 -1
  55. package/types/styleUtils/index.d.ts.map +1 -1
  56. package/types/useStyle.d.ts +15 -13
  57. package/types/useStyle.d.ts.map +1 -1
  58. package/types/useStyleLegacy.d.ts +22 -0
  59. package/types/useStyleLegacy.d.ts.map +1 -0
  60. package/types/useTheme.d.ts.map +1 -1
  61. package/types/withStyle.d.ts +2 -22
  62. package/types/withStyle.d.ts.map +1 -1
  63. package/types/withStyleLegacy.d.ts +22 -0
  64. package/types/withStyleLegacy.d.ts.map +1 -0
  65. package/es/styleUtils/mapSpacingToShorthand.js +0 -29
  66. package/lib/styleUtils/mapSpacingToShorthand.js +0 -35
  67. package/src/styleUtils/mapSpacingToShorthand.ts +0 -35
  68. package/types/styleUtils/mapSpacingToShorthand.d.ts +0 -5
  69. package/types/styleUtils/mapSpacingToShorthand.d.ts.map +0 -1
package/es/getTheme.js CHANGED
@@ -44,7 +44,7 @@ const getTheme = themeOrOverride => (ancestorTheme = {}) => {
44
44
  // we need to clone the ancestor theme not to override it
45
45
  let currentTheme;
46
46
  if (Object.keys(ancestorTheme).length === 0) {
47
- if (process.env.NODE_ENV !== 'production') {}
47
+ if (process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') {}
48
48
  currentTheme = canvas;
49
49
  } else {
50
50
  currentTheme = ancestorTheme;
@@ -62,7 +62,7 @@ const getTheme = themeOrOverride => (ancestorTheme = {}) => {
62
62
  // If the prop passed is not an Object, it will throw an error.
63
63
  // We are using this fail-safe here for the non-TS users,
64
64
  // because the whole page can break without a theme.
65
- if (process.env.NODE_ENV !== 'production') {}
65
+ if (process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') {}
66
66
  resolvedThemeOrOverride = {};
67
67
  }
68
68
  const themeName = currentTheme.key;
package/es/index.js CHANGED
@@ -25,7 +25,10 @@
25
25
 
26
26
  export * from '@emotion/react';
27
27
  export { InstUISettingsProvider } from "./InstUISettingsProvider/index.js";
28
+ export { withStyleLegacy } from "./withStyleLegacy.js";
29
+ export { getComponentThemeOverride } from "./getComponentThemeOverride.js";
28
30
  export { withStyle } from "./withStyle.js";
29
- export { ThemeablePropValues, makeThemeVars, getShorthandPropValue, mirrorShorthandCorners, mirrorShorthandEdges, mapSpacingToShorthand } from "./styleUtils/index.js";
31
+ export { ThemeablePropValues, makeThemeVars, getShorthandPropValue, mirrorShorthandCorners, mirrorShorthandEdges, calcSpacingFromShorthand, calcFocusOutlineStyles } from "./styleUtils/index.js";
32
+ export { useStyleLegacy } from "./useStyleLegacy.js";
30
33
  export { useStyle } from "./useStyle.js";
31
34
  export { useTheme } from "./useTheme.js";
@@ -0,0 +1,71 @@
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 { alpha } from '@instructure/ui-color-utils';
25
+ /**
26
+ * This function creates CSS-in-JS styles for focus indicators.
27
+ *
28
+ * @returns CSS-in-JS style object containing focus outline styles ready for use with emotion or similar libraries.
29
+ */
30
+ const calcFocusOutlineStyles = (theme, params) => {
31
+ var _params$focusColor, _params$focusPosition, _params$shouldAnimate, _params$focusWithin, _params$withFocusOutl, _params$customCSSSele;
32
+ const focusColor = (_params$focusColor = params === null || params === void 0 ? void 0 : params.focusColor) !== null && _params$focusColor !== void 0 ? _params$focusColor : 'info';
33
+ const focusPosition = (_params$focusPosition = params === null || params === void 0 ? void 0 : params.focusPosition) !== null && _params$focusPosition !== void 0 ? _params$focusPosition : 'offset';
34
+ const shouldAnimateFocus = (_params$shouldAnimate = params === null || params === void 0 ? void 0 : params.shouldAnimateFocus) !== null && _params$shouldAnimate !== void 0 ? _params$shouldAnimate : true;
35
+ const focusWithin = (_params$focusWithin = params === null || params === void 0 ? void 0 : params.focusWithin) !== null && _params$focusWithin !== void 0 ? _params$focusWithin : false;
36
+ const withFocusOutline = (_params$withFocusOutl = params === null || params === void 0 ? void 0 : params.withFocusOutline) !== null && _params$withFocusOutl !== void 0 ? _params$withFocusOutl : false;
37
+ const selector = (_params$customCSSSele = params === null || params === void 0 ? void 0 : params.customCSSSelector) !== null && _params$customCSSSele !== void 0 ? _params$customCSSSele : '&:focus';
38
+ const focusColorVariants = {
39
+ info: theme.infoColor,
40
+ inverse: theme.onColor,
41
+ success: theme.successColor,
42
+ danger: theme.dangerColor
43
+ };
44
+ const outlineStyle = {
45
+ outlineColor: focusColorVariants[focusColor],
46
+ outlineStyle: 'solid',
47
+ outlineWidth: theme.width,
48
+ outlineOffset: theme[focusPosition]
49
+ };
50
+ return {
51
+ ...(shouldAnimateFocus && {
52
+ transition: 'outline-color 0.2s, outline-offset 0.25s'
53
+ }),
54
+ outlineOffset: '-0.8rem',
55
+ outlineStyle: 'solid',
56
+ outlineColor: alpha(outlineStyle.outlineColor, 0),
57
+ ...(withFocusOutline && outlineStyle),
58
+ [selector]: {
59
+ ...outlineStyle,
60
+ '&:hover, &:active': {
61
+ // apply the same style so it's not overridden by some global style
62
+ ...outlineStyle
63
+ }
64
+ },
65
+ ...(focusWithin && {
66
+ '&:focus-within': outlineStyle
67
+ })
68
+ };
69
+ };
70
+ export default calcFocusOutlineStyles;
71
+ export { calcFocusOutlineStyles };
@@ -0,0 +1,112 @@
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
+ /**
26
+ * Converts hyphen-case strings to camelCase
27
+ * Example: 'medium-small' -> 'mediumSmall'
28
+ */
29
+ function camelize(str) {
30
+ return str.replace(/-([a-z])/g, g => g[1].toUpperCase());
31
+ }
32
+
33
+ /**
34
+ * Converts shorthand spacing values into CSS strings using theme spacing tokens.
35
+ *
36
+ * This function parses space-separated spacing values (margin, padding) and resolves theme
37
+ * tokens to their actual CSS values. It supports CSS shorthand syntax (1-4 values), nested
38
+ * theme token paths using dot notation, and automatically converts hyphen-case tokens to camelCase.
39
+ *
40
+ * @param {Spacing | undefined} value - The shorthand spacing value string containing space-separated tokens or CSS values.
41
+ * Tokens can be in camelCase (mediumSmall) or hyphen-case (medium-small).
42
+ * Can be undefined, in which case '0' is returned.
43
+ * @param {Record<string, string>} spacingMap - The spacing theme object containing spacing tokens and nested values.
44
+ * Typically comes from `sharedTokens.margin.spacing` or `sharedTokens.padding.spacing` in the component theme.
45
+ *
46
+ * @returns {string} The resolved CSS spacing string ready to be used in styles.
47
+ *
48
+ * @example
49
+ * // Hyphen-case tokens are converted to camelCase
50
+ * calcSpacingFromShorthand('medium-small', spacingMap) // resolves to spacingMap.mediumSmall
51
+ * calcSpacingFromShorthand('x-large small', spacingMap) // resolves to spacingMap.xLarge + spacingMap.small
52
+ *
53
+ * // Dot notation paths are NOT converted
54
+ * calcSpacingFromShorthand('gap.nested-value', spacingMap) // resolves to spacingMap.gap['nested-value']
55
+ *
56
+ * // CSS values like 'none', 'auto', '10px' are returned as-is
57
+ * calcSpacingFromShorthand('none', spacingMap) // returns 'none'
58
+ */
59
+ export function calcSpacingFromShorthand(value, spacingMap) {
60
+ // return undefined when there is no value -> this is important when a component (like View)
61
+ // doesn't have a prop like `padding` but has inline css for padding
62
+ // this makes sure to not overwrite the inline style
63
+ if (!value) return;
64
+ const tokens = value.trim().split(' ');
65
+
66
+ // Handle whitespace-only strings
67
+ if (tokens.length === 1 && tokens[0] === '') return '';
68
+
69
+ // Map each token to its resolved CSS value
70
+ const resolvedValues = tokens.map(token => {
71
+ // Handle special CSS value 'none' - convert to 0 for valid CSS
72
+ if (token === 'none') {
73
+ return '0';
74
+ }
75
+
76
+ // Handle valid CSS numeric and keyword values
77
+ if (token === '0' || token === 'auto') {
78
+ return token;
79
+ }
80
+
81
+ // Handle dot notation for nested theme token paths (no camelization)
82
+ if (token.includes('.')) {
83
+ const path = token.split('.');
84
+ let currentLevel = spacingMap;
85
+ for (const key of path) {
86
+ if (currentLevel && typeof currentLevel === 'object' && key in currentLevel) {
87
+ currentLevel = currentLevel[key];
88
+ } else {
89
+ // If path doesn't resolve, return the original token as fallback
90
+ return token;
91
+ }
92
+ }
93
+ if (typeof currentLevel === 'string') {
94
+ return currentLevel;
95
+ }
96
+ }
97
+
98
+ // For direct tokens, try camelized version
99
+ const camelizedToken = camelize(token);
100
+ const directValue = spacingMap[camelizedToken];
101
+ if (typeof directValue === 'string') {
102
+ return directValue;
103
+ }
104
+
105
+ // Return the original token if not found (could be a direct CSS value like 'auto', '10px', etc.)
106
+
107
+ return token;
108
+ });
109
+
110
+ // Return the space-separated resolved values
111
+ return resolvedValues.join(' ');
112
+ }
@@ -26,4 +26,5 @@ export { makeThemeVars } from "./makeThemeVars.js";
26
26
  export { getShorthandPropValue } from "./getShorthandPropValue.js";
27
27
  export { mirrorShorthandCorners } from "./mirrorShorthandCorners.js";
28
28
  export { mirrorShorthandEdges } from "./mirrorShorthandEdges.js";
29
- export { mapSpacingToShorthand } from "./mapSpacingToShorthand.js";
29
+ export { calcSpacingFromShorthand } from "./calcSpacingFromShorthand.js";
30
+ export { calcFocusOutlineStyles } from "./calcFocusOutlineStyles.js";
package/es/useStyle.js CHANGED
@@ -23,20 +23,41 @@
23
23
  */
24
24
  import { useTheme } from "./useTheme.js";
25
25
  import { getComponentThemeOverride } from "./getComponentThemeOverride.js"; // returns the second parameter of a function
26
+ /**
27
+ * Type for a theme override
28
+ */
29
+ const isNewThemeObject = obj => {
30
+ return typeof (obj === null || obj === void 0 ? void 0 : obj.newTheme) === 'object';
31
+ };
32
+
33
+ /**
34
+ * new useStyle syntax, use this with v12 themes
35
+ */
36
+
37
+ // TODO: improve useStyle to handle generateStyle functions that don't
38
+ // have a theme.
26
39
  const useStyle = useStyleParams => {
40
+ var _ref, _ref2;
27
41
  const generateStyle = useStyleParams.generateStyle,
28
- generateComponentTheme = useStyleParams.generateComponentTheme,
29
42
  params = useStyleParams.params,
30
43
  componentId = useStyleParams.componentId,
31
- displayName = useStyleParams.displayName;
44
+ displayName = useStyleParams.displayName,
45
+ themeOverride = useStyleParams.themeOverride;
46
+ const useTokensFrom = useStyleParams.useTokensFrom;
32
47
  const theme = useTheme();
33
- const baseComponentTheme = generateComponentTheme ? generateComponentTheme(theme) : {};
34
- const themeOverride = getComponentThemeOverride(theme, displayName ? displayName : componentId || '', componentId, params, baseComponentTheme);
48
+ let baseComponentTheme = {};
49
+ const componentWithTokensId = useTokensFrom !== null && useTokensFrom !== void 0 ? useTokensFrom : componentId;
50
+ if (isNewThemeObject(theme) &&
51
+ // TODO: is it possible not to have a theme object here?
52
+ theme.newTheme.components[componentWithTokensId]) {
53
+ baseComponentTheme = theme.newTheme.components[componentWithTokensId];
54
+ }
55
+ const finalOverride = getComponentThemeOverride(theme, (_ref = (_ref2 = useTokensFrom !== null && useTokensFrom !== void 0 ? useTokensFrom : displayName) !== null && _ref2 !== void 0 ? _ref2 : componentId) !== null && _ref !== void 0 ? _ref : '', componentWithTokensId, themeOverride, baseComponentTheme);
35
56
  const componentTheme = {
36
57
  ...baseComponentTheme,
37
- ...themeOverride
58
+ ...finalOverride
38
59
  };
39
- return generateStyle(componentTheme, params ? params : {});
60
+ return generateStyle(componentTheme, params, theme.newTheme.sharedTokens);
40
61
  };
41
62
  export default useStyle;
42
63
  export { useStyle };
@@ -0,0 +1,49 @@
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 { 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
+ */
32
+ const useStyleLegacy = useStyleParams => {
33
+ var _ref;
34
+ const generateStyle = useStyleParams.generateStyle,
35
+ params = useStyleParams.params,
36
+ componentId = useStyleParams.componentId,
37
+ displayName = useStyleParams.displayName;
38
+ const generateComponentTheme = useStyleParams === null || useStyleParams === void 0 ? void 0 : useStyleParams.generateComponentTheme;
39
+ const theme = useTheme();
40
+ const baseComponentTheme = typeof generateComponentTheme === 'function' ? generateComponentTheme(theme) : {};
41
+ const themeOverride = getComponentThemeOverride(theme, (_ref = displayName !== null && displayName !== void 0 ? displayName : componentId) !== null && _ref !== void 0 ? _ref : '', componentId, params === null || params === void 0 ? void 0 : params.themeOverride, baseComponentTheme);
42
+ const componentTheme = {
43
+ ...baseComponentTheme,
44
+ ...themeOverride
45
+ };
46
+ return generateStyle(componentTheme, params ? params : {}, theme);
47
+ };
48
+ export default useStyleLegacy;
49
+ export { useStyleLegacy };
package/es/useTheme.js CHANGED
@@ -37,7 +37,7 @@ const useTheme = () => {
37
37
  // This reads the theme from Emotion's ThemeContext
38
38
  let theme = useEmotionTheme();
39
39
  if (isEmpty(theme)) {
40
- if (process.env.NODE_ENV !== 'production') {}
40
+ if (process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') {}
41
41
  theme = canvas;
42
42
  }
43
43
  return theme;
package/es/withStyle.js CHANGED
@@ -52,9 +52,8 @@ const defaultValues = {
52
52
  * ```js-code
53
53
  * import { withStyle } from '@instructure/emotion'
54
54
  * import generateStyle from './styles'
55
- * import generateComponentTheme from './theme'
56
55
  *
57
- * export default withStyle(generateStyle, generateComponentTheme)(ExampleComponent)
56
+ * export default withStyle(generateStyle)(ExampleComponent)
58
57
  * ```
59
58
  *
60
59
  * Themeable components inject their themed styles into the document
@@ -73,24 +72,6 @@ const defaultValues = {
73
72
  *
74
73
  * See more about the overrides on the [Using theme overrides](/#using-theme-overrides) docs page.
75
74
  *
76
- * ```js-code
77
- * // ExampleComponent/theme.js
78
- * const generateComponentTheme = (theme) => {
79
- * const { colors } = theme
80
- *
81
- * const componentVariables = {
82
- * background: colors?.backgroundMedium,
83
- * color: colors?.textDarkest,
84
- *
85
- * hoverColor: colors?.textLightest,
86
- * hoverBackground: colors?.backgroundDarkest
87
- * }
88
- *
89
- * return componentVariables
90
- * }
91
- * export default generateComponentTheme
92
- * ```
93
- *
94
75
  * ```jsx-code
95
76
  * {// global theme override}
96
77
  * <InstUISettingsProvider theme={{
@@ -110,11 +91,12 @@ const defaultValues = {
110
91
  * @module withStyle
111
92
  *
112
93
  * @param {function} generateStyle - The function that returns the component's style object
113
- * @param {function} generateComponentTheme - The function that returns the component's theme variables object
114
94
  * @returns {ReactElement} The decorated WithStyle Component
115
95
  */
116
- const withStyle = decorator((ComposedComponent, generateStyle, generateComponentTheme) => {
96
+ const withStyle = decorator((ComposedComponent, generateStyle, useTokensFrom) => {
97
+ var _ComposedComponent$co;
117
98
  const displayName = ComposedComponent.displayName || ComposedComponent.name;
99
+ const componentId = (_ComposedComponent$co = ComposedComponent.componentId) === null || _ComposedComponent$co === void 0 ? void 0 : _ComposedComponent$co.replace('.', '');
118
100
  const WithStyle = /*#__PURE__*/forwardRef((props, ref) => {
119
101
  const theme = useTheme();
120
102
  if (props.styles) {
@@ -128,18 +110,21 @@ const withStyle = decorator((ComposedComponent, generateStyle, generateComponent
128
110
  ...props,
129
111
  ...defaultValues
130
112
  };
131
- let componentTheme = typeof generateComponentTheme === 'function' ? generateComponentTheme(theme) : {};
132
- const themeOverride = getComponentThemeOverride(theme, displayName, ComposedComponent.componentId, componentProps, componentTheme);
133
- componentTheme = {
134
- ...componentTheme,
113
+ const componentWithTokensId = useTokensFrom !== null && useTokensFrom !== void 0 ? useTokensFrom : componentId;
114
+ const baseComponentTheme = theme.newTheme.components[componentWithTokensId];
115
+ const themeOverride = getComponentThemeOverride(theme, displayName, ComposedComponent.componentId, componentProps.themeOverride, baseComponentTheme);
116
+ const componentTheme = {
117
+ ...baseComponentTheme,
135
118
  ...themeOverride
136
119
  };
137
- const _useState = useState(generateStyle ? generateStyle(componentTheme, componentProps, {}) : {}),
120
+
121
+ // TODO do not call here generateStyle, it does not receive the extraArgs
122
+ const _useState = useState(generateStyle ? generateStyle(componentTheme, componentProps, theme.newTheme.sharedTokens, {}) : {}),
138
123
  _useState2 = _slicedToArray(_useState, 2),
139
124
  styles = _useState2[0],
140
125
  setStyles = _useState2[1];
141
126
  const makeStyleHandler = extraArgs => {
142
- const calculatedStyles = generateStyle(componentTheme, componentProps, extraArgs);
127
+ const calculatedStyles = generateStyle(componentTheme, componentProps, theme.newTheme.sharedTokens, extraArgs);
143
128
  if (!isEqual(calculatedStyles, styles)) {
144
129
  setStyles(calculatedStyles);
145
130
  }
@@ -165,9 +150,6 @@ const withStyle = decorator((ComposedComponent, generateStyle, generateComponent
165
150
  // These static fields exist on InstUI components
166
151
  WithStyle.allowedProps = ComposedComponent.allowedProps;
167
152
 
168
- // we are exposing the theme generator for the docs generation
169
- WithStyle.generateComponentTheme = generateComponentTheme;
170
-
171
153
  // we have to add defaults to makeStyles and styles added by this decorator
172
154
  // eslint-disable-next-line no-param-reassign
173
155
  ComposedComponent.defaultProps = {
@@ -0,0 +1,116 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ /*
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2015 - present Instructure, Inc.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+
26
+ import { forwardRef, useState } from 'react';
27
+ import hoistNonReactStatics from 'hoist-non-react-statics';
28
+ import { deepEqual as isEqual } from '@instructure/ui-utils';
29
+ import { warn } from '@instructure/console';
30
+ import { decorator } from '@instructure/ui-decorator';
31
+ import { getComponentThemeOverride } from "./getComponentThemeOverride.js";
32
+ import { useTheme } from "./useTheme.js"; // Extract is needed because it would allow number otherwise
33
+ // https://stackoverflow.com/a/51808262/319473
34
+ // Unique name of an InstUI component
35
+ import { jsx as _jsx } from "@emotion/react/jsx-runtime";
36
+ const defaultValues = {
37
+ styles: {},
38
+ makeStyles: () => {}
39
+ };
40
+
41
+ /**
42
+ * ---
43
+ * category: utilities/themes
44
+ * ---
45
+ * used for old (v11 and eariler) theming system
46
+ * TODO delete when the theme migration is complete
47
+ */
48
+ const withStyleLegacy = decorator((ComposedComponent, generateStyle, generateComponentTheme) => {
49
+ const displayName = ComposedComponent.displayName || ComposedComponent.name;
50
+ const WithStyle = /*#__PURE__*/forwardRef((props, ref) => {
51
+ const theme = useTheme();
52
+ if (props.styles) {
53
+ 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);
54
+ }
55
+ if (props.makeStyles) {
56
+ warn(false, `Manually passing the "makeStyles" property is not allowed on the ${displayName} component. Styles are calculated by the @withStyle decorator.`);
57
+ }
58
+ const componentProps = {
59
+ ...ComposedComponent.defaultProps,
60
+ ...props,
61
+ ...defaultValues
62
+ };
63
+ let componentTheme = typeof generateComponentTheme === 'function' ? generateComponentTheme(theme) : {};
64
+ const themeOverride = getComponentThemeOverride(theme, displayName, ComposedComponent.componentId, componentProps.themeOverride, componentTheme);
65
+ componentTheme = {
66
+ ...componentTheme,
67
+ ...themeOverride
68
+ };
69
+ const _useState = useState(generateStyle ? generateStyle(componentTheme, componentProps, {}) : {}),
70
+ _useState2 = _slicedToArray(_useState, 2),
71
+ styles = _useState2[0],
72
+ setStyles = _useState2[1];
73
+ const makeStyleHandler = extraArgs => {
74
+ const calculatedStyles = generateStyle(componentTheme, componentProps, extraArgs);
75
+ if (!isEqual(calculatedStyles, styles)) {
76
+ setStyles(calculatedStyles);
77
+ }
78
+ };
79
+ return _jsx(ComposedComponent, {
80
+ ref: ref,
81
+ ...props,
82
+ makeStyles: makeStyleHandler,
83
+ styles: styles
84
+ // passing themeOverrides is needed for components like Button
85
+ // that have no makeStyles of their own and only pass themeOverrides
86
+ // to the underlying component (e.g.: BaseButton)
87
+ ,
88
+ themeOverride: themeOverride
89
+ });
90
+ });
91
+ hoistNonReactStatics(WithStyle, ComposedComponent);
92
+
93
+ // added so it can be tested with ReactTestUtils
94
+ // more info: https://github.com/facebook/react/issues/13455
95
+ WithStyle.originalType = ComposedComponent.originalType || ComposedComponent;
96
+ WithStyle.defaultProps = ComposedComponent.defaultProps;
97
+ // These static fields exist on InstUI components
98
+ WithStyle.allowedProps = ComposedComponent.allowedProps;
99
+
100
+ // we are exposing the theme generator for the docs generation
101
+ WithStyle.generateComponentTheme = generateComponentTheme;
102
+
103
+ // we have to add defaults to makeStyles and styles added by this decorator
104
+ // eslint-disable-next-line no-param-reassign
105
+ ComposedComponent.defaultProps = {
106
+ ...ComposedComponent.defaultProps,
107
+ makeStyles: defaultValues.makeStyles,
108
+ styles: defaultValues.styles
109
+ };
110
+ if (process.env.NODE_ENV !== 'production') {
111
+ WithStyle.displayName = `WithStyle(${displayName})`;
112
+ }
113
+ return WithStyle;
114
+ });
115
+ export default withStyleLegacy;
116
+ export { withStyleLegacy };
@@ -48,7 +48,7 @@ function InstUISettingsProvider({
48
48
  instanceCounterMap
49
49
  }) {
50
50
  const finalDir = dir || (0, _react.useContext)(_TextDirectionContext.TextDirectionContext);
51
- if (process.env.NODE_ENV !== 'production' && finalDir === 'auto') {}
51
+ if ((process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') && finalDir === 'auto') {}
52
52
  let providers = (0, _jsxRuntime.jsx)(_DeterministicIdContextProvider.DeterministicIdContextProvider, {
53
53
  instanceCounterMap: instanceCounterMap,
54
54
  children: (0, _jsxRuntime.jsx)(_react2.ThemeProvider, {
@@ -38,14 +38,13 @@ exports.getComponentThemeOverride = exports.default = void 0;
38
38
  * @param theme - Theme object
39
39
  * @param displayName - Name of the component
40
40
  * @param componentId - componentId of the component
41
- * @param props - The component's props object
41
+ * @param themeOverride - The theme override object
42
42
  * @param componentTheme - The component's default theme
43
43
  * @returns The calculated theme override object
44
44
  */
45
- const getComponentThemeOverride = (theme, displayName, componentId, props, componentTheme) => {
45
+ const getComponentThemeOverride = (theme, displayName, componentId, themeOverride, componentTheme) => {
46
46
  const name = displayName;
47
47
  const id = componentId;
48
- const themeOverride = props ? props.themeOverride : void 0;
49
48
  const _ref = theme,
50
49
  componentOverrides = _ref.componentOverrides;
51
50
  let overridesFromTheme = {};
@@ -55,7 +54,9 @@ const getComponentThemeOverride = (theme, displayName, componentId, props, compo
55
54
  }
56
55
  if (themeOverride) {
57
56
  if (typeof themeOverride === 'function') {
58
- overrideFromComponent = themeOverride(componentTheme || {},
57
+ overrideFromComponent = themeOverride(
58
+ //TODO type properly when the old theme is gone
59
+ componentTheme || {},
59
60
  // the `theme` technically could be a partial theme / override object too,
60
61
  // but we want to display all possible options
61
62
  theme);
package/lib/getTheme.js CHANGED
@@ -53,7 +53,7 @@ const getTheme = themeOrOverride => (ancestorTheme = {}) => {
53
53
  // we need to clone the ancestor theme not to override it
54
54
  let currentTheme;
55
55
  if (Object.keys(ancestorTheme).length === 0) {
56
- if (process.env.NODE_ENV !== 'production') {}
56
+ if (process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') {}
57
57
  currentTheme = _uiThemes.default;
58
58
  } else {
59
59
  currentTheme = ancestorTheme;
@@ -71,7 +71,7 @@ const getTheme = themeOrOverride => (ancestorTheme = {}) => {
71
71
  // If the prop passed is not an Object, it will throw an error.
72
72
  // We are using this fail-safe here for the non-TS users,
73
73
  // because the whole page can break without a theme.
74
- if (process.env.NODE_ENV !== 'production') {}
74
+ if (process.env.NODE_ENV !== 'production' || process.env.GITHUB_PULL_REQUEST_PREVIEW === 'true') {}
75
75
  resolvedThemeOrOverride = {};
76
76
  }
77
77
  const themeName = currentTheme.key;