@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.
- package/CHANGELOG.md +51 -303
- package/es/InstUISettingsProvider/index.js +1 -1
- package/es/getComponentThemeOverride.js +5 -4
- package/es/getTheme.js +2 -2
- package/es/index.js +4 -1
- package/es/styleUtils/calcFocusOutlineStyles.js +71 -0
- package/es/styleUtils/calcSpacingFromShorthand.js +112 -0
- package/es/styleUtils/index.js +2 -1
- package/es/useStyle.js +27 -6
- package/es/useStyleLegacy.js +49 -0
- package/es/useTheme.js +1 -1
- package/es/withStyle.js +13 -31
- package/es/withStyleLegacy.js +116 -0
- package/lib/InstUISettingsProvider/index.js +1 -1
- package/lib/getComponentThemeOverride.js +5 -4
- package/lib/getTheme.js +2 -2
- package/lib/index.js +38 -7
- package/lib/styleUtils/calcFocusOutlineStyles.js +78 -0
- package/lib/styleUtils/calcSpacingFromShorthand.js +118 -0
- package/lib/styleUtils/index.js +14 -7
- package/lib/useStyle.js +28 -6
- package/lib/useStyleLegacy.js +59 -0
- package/lib/useTheme.js +1 -1
- package/lib/withStyle.js +13 -31
- package/lib/withStyleLegacy.js +125 -0
- package/package.json +11 -9
- package/src/EmotionTypes.ts +10 -1
- package/src/InstUISettingsProvider/index.tsx +5 -1
- package/src/getComponentThemeOverride.ts +9 -8
- package/src/getTheme.ts +8 -2
- package/src/index.ts +7 -2
- package/src/styleUtils/calcFocusOutlineStyles.ts +106 -0
- package/src/styleUtils/calcSpacingFromShorthand.ts +127 -0
- package/src/styleUtils/index.ts +2 -1
- package/src/useStyle.ts +63 -32
- package/src/useStyleLegacy.ts +92 -0
- package/src/useTheme.ts +4 -1
- package/src/withStyle.tsx +29 -39
- package/src/withStyleLegacy.tsx +212 -0
- package/tsconfig.build.json +3 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/EmotionTypes.d.ts +4 -2
- package/types/EmotionTypes.d.ts.map +1 -1
- package/types/InstUISettingsProvider/index.d.ts.map +1 -1
- package/types/getComponentThemeOverride.d.ts +4 -5
- package/types/getComponentThemeOverride.d.ts.map +1 -1
- package/types/getTheme.d.ts.map +1 -1
- package/types/index.d.ts +6 -2
- package/types/index.d.ts.map +1 -1
- package/types/styleUtils/calcFocusOutlineStyles.d.ts +51 -0
- package/types/styleUtils/calcFocusOutlineStyles.d.ts.map +1 -0
- package/types/styleUtils/calcSpacingFromShorthand.d.ts +33 -0
- package/types/styleUtils/calcSpacingFromShorthand.d.ts.map +1 -0
- package/types/styleUtils/index.d.ts +2 -1
- package/types/styleUtils/index.d.ts.map +1 -1
- package/types/useStyle.d.ts +15 -13
- package/types/useStyle.d.ts.map +1 -1
- package/types/useStyleLegacy.d.ts +22 -0
- package/types/useStyleLegacy.d.ts.map +1 -0
- package/types/useTheme.d.ts.map +1 -1
- package/types/withStyle.d.ts +2 -22
- package/types/withStyle.d.ts.map +1 -1
- package/types/withStyleLegacy.d.ts +22 -0
- package/types/withStyleLegacy.d.ts.map +1 -0
- package/es/styleUtils/mapSpacingToShorthand.js +0 -29
- package/lib/styleUtils/mapSpacingToShorthand.js +0 -35
- package/src/styleUtils/mapSpacingToShorthand.ts +0 -35
- package/types/styleUtils/mapSpacingToShorthand.d.ts +0 -5
- 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,
|
|
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
|
+
}
|
package/es/styleUtils/index.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
34
|
-
const
|
|
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
|
-
...
|
|
58
|
+
...finalOverride
|
|
38
59
|
};
|
|
39
|
-
return generateStyle(componentTheme, 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
|
|
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,
|
|
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
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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(
|
|
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;
|