@itwin/itwinui-react 2.12.24 → 2.12.26
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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.12.26
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1949](https://github.com/iTwin/iTwinUI/pull/1949): ThemeProvider will now correctly inherit theme changes from a v3 ancestor.
|
|
8
|
+
|
|
9
|
+
## 2.12.25
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- b517fd0c: Fixed a bug in `Table` where `initialState.columnOrder` was not being respected.
|
|
14
|
+
|
|
3
15
|
## 2.12.24
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -27,6 +27,10 @@ The goal of this package is to provide React components that make it easier to u
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
🆕 **iTwinUI v3** is now available! To upgrade from an older version, check out the [v3 migration guide](https://github.com/iTwin/iTwinUI/wiki/iTwinUI-react-v3-migration-guide).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
30
34
|
## Installation
|
|
31
35
|
|
|
32
36
|
```
|
package/cjs/core/Table/Table.js
CHANGED
|
@@ -298,7 +298,8 @@ const Table = (props) => {
|
|
|
298
298
|
// This is to avoid the old columnOrder from affecting the new columns' columnOrder
|
|
299
299
|
React.useEffect(() => {
|
|
300
300
|
// Check if columns have changed (by value)
|
|
301
|
-
if (
|
|
301
|
+
if (lastPassedColumns.current.length > 0 &&
|
|
302
|
+
JSON.stringify(lastPassedColumns.current) !== JSON.stringify(columns)) {
|
|
302
303
|
instance.setColumnOrder([]);
|
|
303
304
|
}
|
|
304
305
|
lastPassedColumns.current = columns;
|
|
@@ -62,19 +62,17 @@ const useStyles_js_1 = require("../utils/hooks/useStyles.js");
|
|
|
62
62
|
* </ThemeProvider>
|
|
63
63
|
*/
|
|
64
64
|
exports.ThemeProvider = React.forwardRef((props, ref) => {
|
|
65
|
-
var _a, _b, _c, _d;
|
|
65
|
+
var _a, _b, _c, _d, _e;
|
|
66
66
|
const { theme: themeProp, children, themeOptions = {}, includeCss = { withLayer: true }, ...rest } = props;
|
|
67
67
|
const rootRef = React.useRef(null);
|
|
68
68
|
const mergedRefs = (0, index_js_1.useMergedRefs)(rootRef, ref);
|
|
69
69
|
const hasChildren = React.Children.count(children) > 0;
|
|
70
|
-
const
|
|
71
|
-
const theme = themeProp === 'inherit' ? (_a =
|
|
70
|
+
const parent = useParentThemeAndContext(rootRef);
|
|
71
|
+
const theme = themeProp === 'inherit' ? (_a = parent.theme) !== null && _a !== void 0 ? _a : 'light' : themeProp;
|
|
72
72
|
// default inherit highContrast option from parent if also inheriting base theme
|
|
73
|
-
(_b = themeOptions.highContrast) !== null && _b !== void 0 ? _b : (themeOptions.highContrast = themeProp === 'inherit'
|
|
74
|
-
? (_c = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _c === void 0 ? void 0 : _c.highContrast
|
|
75
|
-
: undefined);
|
|
73
|
+
(_b = themeOptions.highContrast) !== null && _b !== void 0 ? _b : (themeOptions.highContrast = themeProp === 'inherit' ? parent.highContrast : undefined);
|
|
76
74
|
const newStylesLoaded = React.useRef(false);
|
|
77
|
-
const stylesLoaded = (_d =
|
|
75
|
+
const stylesLoaded = (_d = (_c = parent.context) === null || _c === void 0 ? void 0 : _c.stylesLoaded) !== null && _d !== void 0 ? _d : newStylesLoaded;
|
|
78
76
|
const contextValue = React.useMemo(() => ({
|
|
79
77
|
theme,
|
|
80
78
|
themeOptions,
|
|
@@ -92,7 +90,7 @@ exports.ThemeProvider = React.forwardRef((props, ref) => {
|
|
|
92
90
|
]);
|
|
93
91
|
// if no children, then fallback to this wrapper component which calls useTheme
|
|
94
92
|
if (!hasChildren) {
|
|
95
|
-
return (React.createElement(ThemeLogicWrapper, { theme: theme, themeOptions: themeOptions !== null && themeOptions !== void 0 ? themeOptions :
|
|
93
|
+
return (React.createElement(ThemeLogicWrapper, { theme: theme, themeOptions: themeOptions !== null && themeOptions !== void 0 ? themeOptions : (_e = parent.context) === null || _e === void 0 ? void 0 : _e.themeOptions }));
|
|
96
94
|
}
|
|
97
95
|
// now that we know there are children, we can render the root and provide the context value
|
|
98
96
|
return (React.createElement(Root, { theme: theme, isInheritingTheme: themeProp === 'inherit', themeOptions: themeOptions, ref: mergedRefs, ...rest },
|
|
@@ -130,3 +128,49 @@ const Styles = (props) => {
|
|
|
130
128
|
(0, useStyles_js_1.useStyles)({ includeCss, document });
|
|
131
129
|
return null;
|
|
132
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Returns theme information from either parent ThemeContext or by reading the closest
|
|
133
|
+
* data-iui-theme attribute if context is not found.
|
|
134
|
+
*
|
|
135
|
+
* Also returns the ThemeContext itself (if found).
|
|
136
|
+
*/
|
|
137
|
+
const useParentThemeAndContext = (rootRef) => {
|
|
138
|
+
var _a, _b, _c, _d;
|
|
139
|
+
const parentContext = React.useContext(exports.ThemeContext);
|
|
140
|
+
const [parentThemeState, setParentTheme] = React.useState(parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme);
|
|
141
|
+
const [parentHighContrastState, setParentHighContrastState] = React.useState((_a = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _a === void 0 ? void 0 : _a.highContrast);
|
|
142
|
+
const parentThemeRef = (0, index_js_1.useLatestRef)(parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme);
|
|
143
|
+
(0, index_js_1.useIsomorphicLayoutEffect)(() => {
|
|
144
|
+
var _a, _b;
|
|
145
|
+
// bail if we already have theme from context
|
|
146
|
+
if (parentThemeRef.current) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// find parent theme from closest data-iui-theme attribute
|
|
150
|
+
const closestRoot = (_b = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.closest('[data-iui-theme]');
|
|
151
|
+
if (!closestRoot) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// helper function that updates state to match data attributes from closest root
|
|
155
|
+
const synchronizeTheme = () => {
|
|
156
|
+
setParentTheme(closestRoot === null || closestRoot === void 0 ? void 0 : closestRoot.getAttribute('data-iui-theme'));
|
|
157
|
+
setParentHighContrastState((closestRoot === null || closestRoot === void 0 ? void 0 : closestRoot.getAttribute('data-iui-contrast')) === 'high');
|
|
158
|
+
};
|
|
159
|
+
// set theme for initial mount
|
|
160
|
+
synchronizeTheme();
|
|
161
|
+
// use mutation observers to listen to future updates to data attributes
|
|
162
|
+
const observer = new MutationObserver(() => synchronizeTheme());
|
|
163
|
+
observer.observe(closestRoot, {
|
|
164
|
+
attributes: true,
|
|
165
|
+
attributeFilter: ['data-iui-theme', 'data-iui-contrast'],
|
|
166
|
+
});
|
|
167
|
+
return () => {
|
|
168
|
+
observer.disconnect();
|
|
169
|
+
};
|
|
170
|
+
}, [parentThemeRef]);
|
|
171
|
+
return {
|
|
172
|
+
theme: (_b = parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme) !== null && _b !== void 0 ? _b : parentThemeState,
|
|
173
|
+
highContrast: (_d = (_c = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _c === void 0 ? void 0 : _c.highContrast) !== null && _d !== void 0 ? _d : parentHighContrastState,
|
|
174
|
+
context: parentContext,
|
|
175
|
+
};
|
|
176
|
+
};
|
package/esm/core/Table/Table.js
CHANGED
|
@@ -269,7 +269,8 @@ export const Table = (props) => {
|
|
|
269
269
|
// This is to avoid the old columnOrder from affecting the new columns' columnOrder
|
|
270
270
|
React.useEffect(() => {
|
|
271
271
|
// Check if columns have changed (by value)
|
|
272
|
-
if (
|
|
272
|
+
if (lastPassedColumns.current.length > 0 &&
|
|
273
|
+
JSON.stringify(lastPassedColumns.current) !== JSON.stringify(columns)) {
|
|
273
274
|
instance.setColumnOrder([]);
|
|
274
275
|
}
|
|
275
276
|
lastPassedColumns.current = columns;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import cx from 'classnames';
|
|
7
|
-
import { useTheme, useMediaQuery, useMergedRefs, useIsThemeAlreadySet, } from '../utils/index.js';
|
|
7
|
+
import { useTheme, useMediaQuery, useMergedRefs, useIsThemeAlreadySet, useIsomorphicLayoutEffect, useLatestRef, } from '../utils/index.js';
|
|
8
8
|
import { useStyles } from '../utils/hooks/useStyles.js';
|
|
9
9
|
/**
|
|
10
10
|
* This component provides global styles and applies theme to the entire tree
|
|
@@ -33,19 +33,17 @@ import { useStyles } from '../utils/hooks/useStyles.js';
|
|
|
33
33
|
* </ThemeProvider>
|
|
34
34
|
*/
|
|
35
35
|
export const ThemeProvider = React.forwardRef((props, ref) => {
|
|
36
|
-
var _a, _b, _c, _d;
|
|
36
|
+
var _a, _b, _c, _d, _e;
|
|
37
37
|
const { theme: themeProp, children, themeOptions = {}, includeCss = { withLayer: true }, ...rest } = props;
|
|
38
38
|
const rootRef = React.useRef(null);
|
|
39
39
|
const mergedRefs = useMergedRefs(rootRef, ref);
|
|
40
40
|
const hasChildren = React.Children.count(children) > 0;
|
|
41
|
-
const
|
|
42
|
-
const theme = themeProp === 'inherit' ? (_a =
|
|
41
|
+
const parent = useParentThemeAndContext(rootRef);
|
|
42
|
+
const theme = themeProp === 'inherit' ? (_a = parent.theme) !== null && _a !== void 0 ? _a : 'light' : themeProp;
|
|
43
43
|
// default inherit highContrast option from parent if also inheriting base theme
|
|
44
|
-
(_b = themeOptions.highContrast) !== null && _b !== void 0 ? _b : (themeOptions.highContrast = themeProp === 'inherit'
|
|
45
|
-
? (_c = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _c === void 0 ? void 0 : _c.highContrast
|
|
46
|
-
: undefined);
|
|
44
|
+
(_b = themeOptions.highContrast) !== null && _b !== void 0 ? _b : (themeOptions.highContrast = themeProp === 'inherit' ? parent.highContrast : undefined);
|
|
47
45
|
const newStylesLoaded = React.useRef(false);
|
|
48
|
-
const stylesLoaded = (_d =
|
|
46
|
+
const stylesLoaded = (_d = (_c = parent.context) === null || _c === void 0 ? void 0 : _c.stylesLoaded) !== null && _d !== void 0 ? _d : newStylesLoaded;
|
|
49
47
|
const contextValue = React.useMemo(() => ({
|
|
50
48
|
theme,
|
|
51
49
|
themeOptions,
|
|
@@ -63,7 +61,7 @@ export const ThemeProvider = React.forwardRef((props, ref) => {
|
|
|
63
61
|
]);
|
|
64
62
|
// if no children, then fallback to this wrapper component which calls useTheme
|
|
65
63
|
if (!hasChildren) {
|
|
66
|
-
return (React.createElement(ThemeLogicWrapper, { theme: theme, themeOptions: themeOptions !== null && themeOptions !== void 0 ? themeOptions :
|
|
64
|
+
return (React.createElement(ThemeLogicWrapper, { theme: theme, themeOptions: themeOptions !== null && themeOptions !== void 0 ? themeOptions : (_e = parent.context) === null || _e === void 0 ? void 0 : _e.themeOptions }));
|
|
67
65
|
}
|
|
68
66
|
// now that we know there are children, we can render the root and provide the context value
|
|
69
67
|
return (React.createElement(Root, { theme: theme, isInheritingTheme: themeProp === 'inherit', themeOptions: themeOptions, ref: mergedRefs, ...rest },
|
|
@@ -101,3 +99,49 @@ const Styles = (props) => {
|
|
|
101
99
|
useStyles({ includeCss, document });
|
|
102
100
|
return null;
|
|
103
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Returns theme information from either parent ThemeContext or by reading the closest
|
|
104
|
+
* data-iui-theme attribute if context is not found.
|
|
105
|
+
*
|
|
106
|
+
* Also returns the ThemeContext itself (if found).
|
|
107
|
+
*/
|
|
108
|
+
const useParentThemeAndContext = (rootRef) => {
|
|
109
|
+
var _a, _b, _c, _d;
|
|
110
|
+
const parentContext = React.useContext(ThemeContext);
|
|
111
|
+
const [parentThemeState, setParentTheme] = React.useState(parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme);
|
|
112
|
+
const [parentHighContrastState, setParentHighContrastState] = React.useState((_a = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _a === void 0 ? void 0 : _a.highContrast);
|
|
113
|
+
const parentThemeRef = useLatestRef(parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme);
|
|
114
|
+
useIsomorphicLayoutEffect(() => {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
// bail if we already have theme from context
|
|
117
|
+
if (parentThemeRef.current) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// find parent theme from closest data-iui-theme attribute
|
|
121
|
+
const closestRoot = (_b = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.closest('[data-iui-theme]');
|
|
122
|
+
if (!closestRoot) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// helper function that updates state to match data attributes from closest root
|
|
126
|
+
const synchronizeTheme = () => {
|
|
127
|
+
setParentTheme(closestRoot === null || closestRoot === void 0 ? void 0 : closestRoot.getAttribute('data-iui-theme'));
|
|
128
|
+
setParentHighContrastState((closestRoot === null || closestRoot === void 0 ? void 0 : closestRoot.getAttribute('data-iui-contrast')) === 'high');
|
|
129
|
+
};
|
|
130
|
+
// set theme for initial mount
|
|
131
|
+
synchronizeTheme();
|
|
132
|
+
// use mutation observers to listen to future updates to data attributes
|
|
133
|
+
const observer = new MutationObserver(() => synchronizeTheme());
|
|
134
|
+
observer.observe(closestRoot, {
|
|
135
|
+
attributes: true,
|
|
136
|
+
attributeFilter: ['data-iui-theme', 'data-iui-contrast'],
|
|
137
|
+
});
|
|
138
|
+
return () => {
|
|
139
|
+
observer.disconnect();
|
|
140
|
+
};
|
|
141
|
+
}, [parentThemeRef]);
|
|
142
|
+
return {
|
|
143
|
+
theme: (_b = parentContext === null || parentContext === void 0 ? void 0 : parentContext.theme) !== null && _b !== void 0 ? _b : parentThemeState,
|
|
144
|
+
highContrast: (_d = (_c = parentContext === null || parentContext === void 0 ? void 0 : parentContext.themeOptions) === null || _c === void 0 ? void 0 : _c.highContrast) !== null && _d !== void 0 ? _d : parentHighContrastState,
|
|
145
|
+
context: parentContext,
|
|
146
|
+
};
|
|
147
|
+
};
|