@atlaskit/app-provider 1.4.3 → 1.6.0
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,27 @@
|
|
|
1
1
|
# @atlaskit/app-provider
|
|
2
2
|
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#98648](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/98648)
|
|
8
|
+
[`940af9dafa883`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/940af9dafa883) -
|
|
9
|
+
[ux] Default typography theme changed to modernized behind feature flag
|
|
10
|
+
`platform-default-typography-modernized`. If testing is successful the change will be available in
|
|
11
|
+
a later release.
|
|
12
|
+
|
|
13
|
+
## 1.5.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- [#101755](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/101755)
|
|
18
|
+
[`07ee1368bd69d`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/07ee1368bd69d) -
|
|
19
|
+
Fixes a race condition with setting the theme. This change is behind a feature flag.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
|
|
3
25
|
## 1.4.3
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
|
@@ -12,19 +12,25 @@ exports.useColorMode = useColorMode;
|
|
|
12
12
|
exports.useSetColorMode = useSetColorMode;
|
|
13
13
|
exports.useSetTheme = useSetTheme;
|
|
14
14
|
exports.useTheme = useTheme;
|
|
15
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
16
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
15
17
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
16
18
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
17
19
|
var _react = _interopRequireWildcard(require("react"));
|
|
18
20
|
var _bindEventListener = require("bind-event-listener");
|
|
21
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
19
22
|
var _tokens = require("@atlaskit/tokens");
|
|
20
23
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
21
24
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
22
25
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
23
26
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
24
|
-
var defaultThemeSettings = {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
var defaultThemeSettings = function defaultThemeSettings() {
|
|
28
|
+
return {
|
|
29
|
+
dark: 'dark',
|
|
30
|
+
light: 'light',
|
|
31
|
+
spacing: 'spacing',
|
|
32
|
+
typography: (0, _platformFeatureFlags.fg)('platform-default-typography-modernized') ? 'typography-modernized' : undefined
|
|
33
|
+
};
|
|
28
34
|
};
|
|
29
35
|
var ColorModeContext = /*#__PURE__*/(0, _react.createContext)(undefined);
|
|
30
36
|
var SetColorModeContext = /*#__PURE__*/(0, _react.createContext)(undefined);
|
|
@@ -115,16 +121,7 @@ function getReconciledColorMode(colorMode) {
|
|
|
115
121
|
function ThemeProvider(_ref) {
|
|
116
122
|
var children = _ref.children,
|
|
117
123
|
defaultColorMode = _ref.defaultColorMode,
|
|
118
|
-
|
|
119
|
-
_ref$defaultTheme2 = _ref$defaultTheme === void 0 ? defaultThemeSettings : _ref$defaultTheme,
|
|
120
|
-
_ref$defaultTheme2$da = _ref$defaultTheme2.dark,
|
|
121
|
-
dark = _ref$defaultTheme2$da === void 0 ? 'dark' : _ref$defaultTheme2$da,
|
|
122
|
-
_ref$defaultTheme2$li = _ref$defaultTheme2.light,
|
|
123
|
-
light = _ref$defaultTheme2$li === void 0 ? 'light' : _ref$defaultTheme2$li,
|
|
124
|
-
_ref$defaultTheme2$sp = _ref$defaultTheme2.spacing,
|
|
125
|
-
spacing = _ref$defaultTheme2$sp === void 0 ? 'spacing' : _ref$defaultTheme2$sp,
|
|
126
|
-
typography = _ref$defaultTheme2.typography,
|
|
127
|
-
shape = _ref$defaultTheme2.shape;
|
|
124
|
+
defaultTheme = _ref.defaultTheme;
|
|
128
125
|
var _useState = (0, _react.useState)(defaultColorMode),
|
|
129
126
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
130
127
|
chosenColorMode = _useState2[0],
|
|
@@ -133,12 +130,8 @@ function ThemeProvider(_ref) {
|
|
|
133
130
|
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
134
131
|
reconciledColorMode = _useState4[0],
|
|
135
132
|
setReconciledColorMode = _useState4[1];
|
|
136
|
-
var _useState5 = (0, _react.useState)({
|
|
137
|
-
|
|
138
|
-
light: light,
|
|
139
|
-
spacing: spacing,
|
|
140
|
-
typography: typography,
|
|
141
|
-
shape: shape
|
|
133
|
+
var _useState5 = (0, _react.useState)(function () {
|
|
134
|
+
return _objectSpread(_objectSpread({}, defaultThemeSettings()), defaultTheme);
|
|
142
135
|
}),
|
|
143
136
|
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
144
137
|
theme = _useState6[0],
|
|
@@ -153,10 +146,87 @@ function ThemeProvider(_ref) {
|
|
|
153
146
|
});
|
|
154
147
|
}, []);
|
|
155
148
|
(0, _react.useEffect)(function () {
|
|
149
|
+
if ((0, _platformFeatureFlags.fg)('platform_dst_fix_set_theme_race')) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
156
152
|
(0, _tokens.setGlobalTheme)(_objectSpread(_objectSpread({}, theme), {}, {
|
|
157
153
|
colorMode: reconciledColorMode
|
|
158
154
|
}));
|
|
159
155
|
}, [theme, reconciledColorMode]);
|
|
156
|
+
var lastSetGlobalThemePromiseRef = (0, _react.useRef)(null);
|
|
157
|
+
(0, _react.useEffect)(function () {
|
|
158
|
+
if (!(0, _platformFeatureFlags.fg)('platform_dst_fix_set_theme_race')) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* We need to wait for any previous `setGlobalTheme` calls to finish before calling it again.
|
|
164
|
+
* This is to prevent race conditions as `setGlobalTheme` is async and mutates the DOM (e.g. sets the
|
|
165
|
+
* `data-color-mode` attribute on the root element).
|
|
166
|
+
*
|
|
167
|
+
* Since we can't safely abort the `setGlobalTheme` execution, we need to wait for it to properly finish before
|
|
168
|
+
* applying the new theme.
|
|
169
|
+
*
|
|
170
|
+
* Without this, we can end up in the following scenario:
|
|
171
|
+
* 1. app loads with the default 'light' theme, kicking off `setGlobalTheme`
|
|
172
|
+
* 2. app switches to 'dark' theme after retrieving value persisted in local storage, calling `setGlobalTheme` again
|
|
173
|
+
* 3. `setGlobalTheme` function execution for `dark` finishes before the initial `light` execution
|
|
174
|
+
* 4. `setGlobalTheme` function execution for `light` then finishes, resulting in the 'light' theme being applied.
|
|
175
|
+
*/
|
|
176
|
+
var cleanupLastFnCall = /*#__PURE__*/function () {
|
|
177
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
178
|
+
var unbindFn;
|
|
179
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
180
|
+
while (1) switch (_context.prev = _context.next) {
|
|
181
|
+
case 0:
|
|
182
|
+
if (!lastSetGlobalThemePromiseRef.current) {
|
|
183
|
+
_context.next = 6;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
_context.next = 3;
|
|
187
|
+
return lastSetGlobalThemePromiseRef.current;
|
|
188
|
+
case 3:
|
|
189
|
+
unbindFn = _context.sent;
|
|
190
|
+
unbindFn();
|
|
191
|
+
lastSetGlobalThemePromiseRef.current = null;
|
|
192
|
+
case 6:
|
|
193
|
+
case "end":
|
|
194
|
+
return _context.stop();
|
|
195
|
+
}
|
|
196
|
+
}, _callee);
|
|
197
|
+
}));
|
|
198
|
+
return function cleanupLastFnCall() {
|
|
199
|
+
return _ref2.apply(this, arguments);
|
|
200
|
+
};
|
|
201
|
+
}();
|
|
202
|
+
var safelySetGlobalTheme = /*#__PURE__*/function () {
|
|
203
|
+
var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
204
|
+
var promise;
|
|
205
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
206
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
207
|
+
case 0:
|
|
208
|
+
_context2.next = 2;
|
|
209
|
+
return cleanupLastFnCall();
|
|
210
|
+
case 2:
|
|
211
|
+
promise = (0, _tokens.setGlobalTheme)(_objectSpread(_objectSpread({}, theme), {}, {
|
|
212
|
+
colorMode: reconciledColorMode
|
|
213
|
+
}));
|
|
214
|
+
lastSetGlobalThemePromiseRef.current = promise;
|
|
215
|
+
case 4:
|
|
216
|
+
case "end":
|
|
217
|
+
return _context2.stop();
|
|
218
|
+
}
|
|
219
|
+
}, _callee2);
|
|
220
|
+
}));
|
|
221
|
+
return function safelySetGlobalTheme() {
|
|
222
|
+
return _ref3.apply(this, arguments);
|
|
223
|
+
};
|
|
224
|
+
}();
|
|
225
|
+
safelySetGlobalTheme();
|
|
226
|
+
return function cleanup() {
|
|
227
|
+
cleanupLastFnCall();
|
|
228
|
+
};
|
|
229
|
+
}, [theme, reconciledColorMode]);
|
|
160
230
|
(0, _react.useEffect)(function () {
|
|
161
231
|
if (!prefersDarkModeMql) {
|
|
162
232
|
return;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
1
|
+
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { bind } from 'bind-event-listener';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
4
|
import { setGlobalTheme } from '@atlaskit/tokens';
|
|
4
|
-
const defaultThemeSettings = {
|
|
5
|
+
const defaultThemeSettings = () => ({
|
|
5
6
|
dark: 'dark',
|
|
6
7
|
light: 'light',
|
|
7
|
-
spacing: 'spacing'
|
|
8
|
-
|
|
8
|
+
spacing: 'spacing',
|
|
9
|
+
typography: fg('platform-default-typography-modernized') ? 'typography-modernized' : undefined
|
|
10
|
+
});
|
|
9
11
|
const ColorModeContext = /*#__PURE__*/createContext(undefined);
|
|
10
12
|
const SetColorModeContext = /*#__PURE__*/createContext(undefined);
|
|
11
13
|
const ThemeContext = /*#__PURE__*/createContext(undefined);
|
|
@@ -95,23 +97,14 @@ function getReconciledColorMode(colorMode) {
|
|
|
95
97
|
export function ThemeProvider({
|
|
96
98
|
children,
|
|
97
99
|
defaultColorMode,
|
|
98
|
-
defaultTheme
|
|
99
|
-
dark = 'dark',
|
|
100
|
-
light = 'light',
|
|
101
|
-
spacing = 'spacing',
|
|
102
|
-
typography,
|
|
103
|
-
shape
|
|
104
|
-
} = defaultThemeSettings
|
|
100
|
+
defaultTheme
|
|
105
101
|
}) {
|
|
106
102
|
const [chosenColorMode, setChosenColorMode] = useState(defaultColorMode);
|
|
107
103
|
const [reconciledColorMode, setReconciledColorMode] = useState(getReconciledColorMode(defaultColorMode));
|
|
108
|
-
const [theme, setTheme] = useState({
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
typography,
|
|
113
|
-
shape
|
|
114
|
-
});
|
|
104
|
+
const [theme, setTheme] = useState(() => ({
|
|
105
|
+
...defaultThemeSettings(),
|
|
106
|
+
...defaultTheme
|
|
107
|
+
}));
|
|
115
108
|
const setColorMode = useCallback(colorMode => {
|
|
116
109
|
setChosenColorMode(colorMode);
|
|
117
110
|
setReconciledColorMode(getReconciledColorMode(colorMode));
|
|
@@ -123,11 +116,54 @@ export function ThemeProvider({
|
|
|
123
116
|
}));
|
|
124
117
|
}, []);
|
|
125
118
|
useEffect(() => {
|
|
119
|
+
if (fg('platform_dst_fix_set_theme_race')) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
126
122
|
setGlobalTheme({
|
|
127
123
|
...theme,
|
|
128
124
|
colorMode: reconciledColorMode
|
|
129
125
|
});
|
|
130
126
|
}, [theme, reconciledColorMode]);
|
|
127
|
+
const lastSetGlobalThemePromiseRef = useRef(null);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!fg('platform_dst_fix_set_theme_race')) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* We need to wait for any previous `setGlobalTheme` calls to finish before calling it again.
|
|
135
|
+
* This is to prevent race conditions as `setGlobalTheme` is async and mutates the DOM (e.g. sets the
|
|
136
|
+
* `data-color-mode` attribute on the root element).
|
|
137
|
+
*
|
|
138
|
+
* Since we can't safely abort the `setGlobalTheme` execution, we need to wait for it to properly finish before
|
|
139
|
+
* applying the new theme.
|
|
140
|
+
*
|
|
141
|
+
* Without this, we can end up in the following scenario:
|
|
142
|
+
* 1. app loads with the default 'light' theme, kicking off `setGlobalTheme`
|
|
143
|
+
* 2. app switches to 'dark' theme after retrieving value persisted in local storage, calling `setGlobalTheme` again
|
|
144
|
+
* 3. `setGlobalTheme` function execution for `dark` finishes before the initial `light` execution
|
|
145
|
+
* 4. `setGlobalTheme` function execution for `light` then finishes, resulting in the 'light' theme being applied.
|
|
146
|
+
*/
|
|
147
|
+
const cleanupLastFnCall = async () => {
|
|
148
|
+
if (lastSetGlobalThemePromiseRef.current) {
|
|
149
|
+
const unbindFn = await lastSetGlobalThemePromiseRef.current;
|
|
150
|
+
unbindFn();
|
|
151
|
+
lastSetGlobalThemePromiseRef.current = null;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const safelySetGlobalTheme = async () => {
|
|
155
|
+
await cleanupLastFnCall();
|
|
156
|
+
const promise = setGlobalTheme({
|
|
157
|
+
...theme,
|
|
158
|
+
colorMode: reconciledColorMode
|
|
159
|
+
});
|
|
160
|
+
lastSetGlobalThemePromiseRef.current = promise;
|
|
161
|
+
};
|
|
162
|
+
safelySetGlobalTheme();
|
|
163
|
+
return function cleanup() {
|
|
164
|
+
cleanupLastFnCall();
|
|
165
|
+
};
|
|
166
|
+
}, [theme, reconciledColorMode]);
|
|
131
167
|
useEffect(() => {
|
|
132
168
|
if (!prefersDarkModeMql) {
|
|
133
169
|
return;
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
1
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
3
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
5
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
6
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
-
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
7
|
+
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
6
8
|
import { bind } from 'bind-event-listener';
|
|
9
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
10
|
import { setGlobalTheme } from '@atlaskit/tokens';
|
|
8
|
-
var defaultThemeSettings = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
var defaultThemeSettings = function defaultThemeSettings() {
|
|
12
|
+
return {
|
|
13
|
+
dark: 'dark',
|
|
14
|
+
light: 'light',
|
|
15
|
+
spacing: 'spacing',
|
|
16
|
+
typography: fg('platform-default-typography-modernized') ? 'typography-modernized' : undefined
|
|
17
|
+
};
|
|
12
18
|
};
|
|
13
19
|
var ColorModeContext = /*#__PURE__*/createContext(undefined);
|
|
14
20
|
var SetColorModeContext = /*#__PURE__*/createContext(undefined);
|
|
@@ -99,16 +105,7 @@ function getReconciledColorMode(colorMode) {
|
|
|
99
105
|
export function ThemeProvider(_ref) {
|
|
100
106
|
var children = _ref.children,
|
|
101
107
|
defaultColorMode = _ref.defaultColorMode,
|
|
102
|
-
|
|
103
|
-
_ref$defaultTheme2 = _ref$defaultTheme === void 0 ? defaultThemeSettings : _ref$defaultTheme,
|
|
104
|
-
_ref$defaultTheme2$da = _ref$defaultTheme2.dark,
|
|
105
|
-
dark = _ref$defaultTheme2$da === void 0 ? 'dark' : _ref$defaultTheme2$da,
|
|
106
|
-
_ref$defaultTheme2$li = _ref$defaultTheme2.light,
|
|
107
|
-
light = _ref$defaultTheme2$li === void 0 ? 'light' : _ref$defaultTheme2$li,
|
|
108
|
-
_ref$defaultTheme2$sp = _ref$defaultTheme2.spacing,
|
|
109
|
-
spacing = _ref$defaultTheme2$sp === void 0 ? 'spacing' : _ref$defaultTheme2$sp,
|
|
110
|
-
typography = _ref$defaultTheme2.typography,
|
|
111
|
-
shape = _ref$defaultTheme2.shape;
|
|
108
|
+
defaultTheme = _ref.defaultTheme;
|
|
112
109
|
var _useState = useState(defaultColorMode),
|
|
113
110
|
_useState2 = _slicedToArray(_useState, 2),
|
|
114
111
|
chosenColorMode = _useState2[0],
|
|
@@ -117,12 +114,8 @@ export function ThemeProvider(_ref) {
|
|
|
117
114
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
118
115
|
reconciledColorMode = _useState4[0],
|
|
119
116
|
setReconciledColorMode = _useState4[1];
|
|
120
|
-
var _useState5 = useState({
|
|
121
|
-
|
|
122
|
-
light: light,
|
|
123
|
-
spacing: spacing,
|
|
124
|
-
typography: typography,
|
|
125
|
-
shape: shape
|
|
117
|
+
var _useState5 = useState(function () {
|
|
118
|
+
return _objectSpread(_objectSpread({}, defaultThemeSettings()), defaultTheme);
|
|
126
119
|
}),
|
|
127
120
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
128
121
|
theme = _useState6[0],
|
|
@@ -137,10 +130,87 @@ export function ThemeProvider(_ref) {
|
|
|
137
130
|
});
|
|
138
131
|
}, []);
|
|
139
132
|
useEffect(function () {
|
|
133
|
+
if (fg('platform_dst_fix_set_theme_race')) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
140
136
|
setGlobalTheme(_objectSpread(_objectSpread({}, theme), {}, {
|
|
141
137
|
colorMode: reconciledColorMode
|
|
142
138
|
}));
|
|
143
139
|
}, [theme, reconciledColorMode]);
|
|
140
|
+
var lastSetGlobalThemePromiseRef = useRef(null);
|
|
141
|
+
useEffect(function () {
|
|
142
|
+
if (!fg('platform_dst_fix_set_theme_race')) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* We need to wait for any previous `setGlobalTheme` calls to finish before calling it again.
|
|
148
|
+
* This is to prevent race conditions as `setGlobalTheme` is async and mutates the DOM (e.g. sets the
|
|
149
|
+
* `data-color-mode` attribute on the root element).
|
|
150
|
+
*
|
|
151
|
+
* Since we can't safely abort the `setGlobalTheme` execution, we need to wait for it to properly finish before
|
|
152
|
+
* applying the new theme.
|
|
153
|
+
*
|
|
154
|
+
* Without this, we can end up in the following scenario:
|
|
155
|
+
* 1. app loads with the default 'light' theme, kicking off `setGlobalTheme`
|
|
156
|
+
* 2. app switches to 'dark' theme after retrieving value persisted in local storage, calling `setGlobalTheme` again
|
|
157
|
+
* 3. `setGlobalTheme` function execution for `dark` finishes before the initial `light` execution
|
|
158
|
+
* 4. `setGlobalTheme` function execution for `light` then finishes, resulting in the 'light' theme being applied.
|
|
159
|
+
*/
|
|
160
|
+
var cleanupLastFnCall = /*#__PURE__*/function () {
|
|
161
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
162
|
+
var unbindFn;
|
|
163
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
164
|
+
while (1) switch (_context.prev = _context.next) {
|
|
165
|
+
case 0:
|
|
166
|
+
if (!lastSetGlobalThemePromiseRef.current) {
|
|
167
|
+
_context.next = 6;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
_context.next = 3;
|
|
171
|
+
return lastSetGlobalThemePromiseRef.current;
|
|
172
|
+
case 3:
|
|
173
|
+
unbindFn = _context.sent;
|
|
174
|
+
unbindFn();
|
|
175
|
+
lastSetGlobalThemePromiseRef.current = null;
|
|
176
|
+
case 6:
|
|
177
|
+
case "end":
|
|
178
|
+
return _context.stop();
|
|
179
|
+
}
|
|
180
|
+
}, _callee);
|
|
181
|
+
}));
|
|
182
|
+
return function cleanupLastFnCall() {
|
|
183
|
+
return _ref2.apply(this, arguments);
|
|
184
|
+
};
|
|
185
|
+
}();
|
|
186
|
+
var safelySetGlobalTheme = /*#__PURE__*/function () {
|
|
187
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
188
|
+
var promise;
|
|
189
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
190
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
191
|
+
case 0:
|
|
192
|
+
_context2.next = 2;
|
|
193
|
+
return cleanupLastFnCall();
|
|
194
|
+
case 2:
|
|
195
|
+
promise = setGlobalTheme(_objectSpread(_objectSpread({}, theme), {}, {
|
|
196
|
+
colorMode: reconciledColorMode
|
|
197
|
+
}));
|
|
198
|
+
lastSetGlobalThemePromiseRef.current = promise;
|
|
199
|
+
case 4:
|
|
200
|
+
case "end":
|
|
201
|
+
return _context2.stop();
|
|
202
|
+
}
|
|
203
|
+
}, _callee2);
|
|
204
|
+
}));
|
|
205
|
+
return function safelySetGlobalTheme() {
|
|
206
|
+
return _ref3.apply(this, arguments);
|
|
207
|
+
};
|
|
208
|
+
}();
|
|
209
|
+
safelySetGlobalTheme();
|
|
210
|
+
return function cleanup() {
|
|
211
|
+
cleanupLastFnCall();
|
|
212
|
+
};
|
|
213
|
+
}, [theme, reconciledColorMode]);
|
|
144
214
|
useEffect(function () {
|
|
145
215
|
if (!prefersDarkModeMql) {
|
|
146
216
|
return;
|
|
@@ -47,5 +47,5 @@ interface ThemeProviderProps {
|
|
|
47
47
|
*
|
|
48
48
|
* @internal
|
|
49
49
|
*/
|
|
50
|
-
export declare function ThemeProvider({ children, defaultColorMode, defaultTheme
|
|
50
|
+
export declare function ThemeProvider({ children, defaultColorMode, defaultTheme }: ThemeProviderProps): JSX.Element;
|
|
51
51
|
export default ThemeProvider;
|
|
@@ -47,5 +47,5 @@ interface ThemeProviderProps {
|
|
|
47
47
|
*
|
|
48
48
|
* @internal
|
|
49
49
|
*/
|
|
50
|
-
export declare function ThemeProvider({ children, defaultColorMode, defaultTheme
|
|
50
|
+
export declare function ThemeProvider({ children, defaultColorMode, defaultTheme }: ThemeProviderProps): JSX.Element;
|
|
51
51
|
export default ThemeProvider;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/app-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A top level provider for the Design System.",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
".": "./src/index.tsx"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@atlaskit/
|
|
42
|
+
"@atlaskit/platform-feature-flags": "^0.3.0",
|
|
43
|
+
"@atlaskit/tokens": "^3.0.0",
|
|
43
44
|
"@babel/runtime": "^7.0.0",
|
|
44
45
|
"bind-event-listener": "^3.0.0"
|
|
45
46
|
},
|
|
@@ -90,5 +91,13 @@
|
|
|
90
91
|
]
|
|
91
92
|
}
|
|
92
93
|
},
|
|
93
|
-
"homepage": "https://atlassian.design/components/app-provider"
|
|
94
|
+
"homepage": "https://atlassian.design/components/app-provider",
|
|
95
|
+
"platform-feature-flags": {
|
|
96
|
+
"platform_dst_fix_set_theme_race": {
|
|
97
|
+
"type": "boolean"
|
|
98
|
+
},
|
|
99
|
+
"platform-default-typography-modernized": {
|
|
100
|
+
"type": "boolean"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
94
103
|
}
|