@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.
- package/CHANGELOG.md +6 -1
- package/es/getTheme.js +1 -1
- package/es/index.js +3 -3
- package/es/useStyle.js +16 -28
- package/es/useStyleNew.js +79 -0
- package/es/withStyle.js +24 -93
- package/es/withStyleNew.js +185 -0
- package/lib/getTheme.js +1 -1
- package/lib/index.js +10 -10
- package/lib/useStyle.js +17 -25
- package/lib/useStyleNew.js +85 -0
- package/lib/withStyle.js +23 -93
- package/lib/withStyleNew.js +195 -0
- package/package.json +10 -10
- package/src/InstUISettingsProvider/README.md +1 -1
- package/src/getComponentThemeOverride.ts +1 -1
- package/src/getTheme.ts +1 -1
- package/src/index.ts +4 -4
- package/src/useStyle.ts +47 -78
- package/src/useStyleNew.ts +146 -0
- package/src/withStyle.tsx +43 -142
- package/src/withStyleNew.tsx +322 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/getComponentThemeOverride.d.ts +1 -1
- package/types/getComponentThemeOverride.d.ts.map +1 -1
- package/types/getTheme.d.ts +1 -1
- package/types/index.d.ts +4 -4
- package/types/index.d.ts.map +1 -1
- package/types/useStyle.d.ts +17 -16
- package/types/useStyle.d.ts.map +1 -1
- package/types/useStyleNew.d.ts +23 -0
- package/types/useStyleNew.d.ts.map +1 -0
- package/types/withStyle.d.ts +7 -56
- package/types/withStyle.d.ts.map +1 -1
- package/types/withStyleNew.d.ts +71 -0
- package/types/withStyleNew.d.ts.map +1 -0
- package/es/useStyleLegacy.js +0 -50
- package/es/withStyleLegacy.js +0 -112
- package/lib/useStyleLegacy.js +0 -60
- package/lib/withStyleLegacy.js +0 -121
- package/src/useStyleLegacy.ts +0 -92
- package/src/withStyleLegacy.tsx +0 -217
- package/types/useStyleLegacy.d.ts +0 -22
- package/types/useStyleLegacy.d.ts.map +0 -1
- package/types/withStyleLegacy.d.ts +0 -22
- 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-
|
|
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
|
-
* `
|
|
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 {
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
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
|
-
|
|
37
|
+
displayName
|
|
40
38
|
} = useStyleParams;
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
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
|
-
*
|
|
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,
|
|
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
|
|
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 @
|
|
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 @
|
|
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
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
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
|
-
* `
|
|
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, "
|
|
89
|
+
Object.defineProperty(exports, "useStyleNew", {
|
|
90
90
|
enumerable: true,
|
|
91
91
|
get: function () {
|
|
92
|
-
return
|
|
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, "
|
|
107
|
+
Object.defineProperty(exports, "withStyleNew", {
|
|
108
108
|
enumerable: true,
|
|
109
109
|
get: function () {
|
|
110
|
-
return
|
|
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");
|