@forge/react 11.17.0-next.2-experimental-a344346 → 11.18.0-next.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 +15 -2
- package/out/components/global/index.d.ts +1 -1
- package/out/components/global/index.d.ts.map +1 -1
- package/out/components/global/index.js +2 -2
- package/out/hooks/__test__/useTheme.test.js +34 -10
- package/out/hooks/useTheme.d.ts.map +1 -1
- package/out/hooks/useTheme.js +42 -12
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# @forge/react
|
|
2
2
|
|
|
3
|
-
## 11.
|
|
3
|
+
## 11.18.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 01550cf: Fix flaky unit test
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 7504dd5: Fix naming on PersonalSettingsItem
|
|
12
|
+
- Updated dependencies [b0b69a2]
|
|
13
|
+
- Updated dependencies [561f8f4]
|
|
14
|
+
- @forge/bridge@5.18.0-next.0
|
|
15
|
+
|
|
16
|
+
## 11.17.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
6
19
|
|
|
@@ -12,7 +25,7 @@
|
|
|
12
25
|
- Updated dependencies [f7f06c8]
|
|
13
26
|
- Updated dependencies [dba5074]
|
|
14
27
|
- Updated dependencies [fc55c83]
|
|
15
|
-
- @forge/bridge@5.17.0
|
|
28
|
+
- @forge/bridge@5.17.0
|
|
16
29
|
|
|
17
30
|
## 11.17.0-next.2
|
|
18
31
|
|
|
@@ -10,6 +10,6 @@ export declare const CreateButton: TCreateButton<ForgeElement<Record<string, any
|
|
|
10
10
|
export declare const CreateMenuItem: TCreateMenuItem<ForgeElement<Record<string, any>>>;
|
|
11
11
|
export declare const HelpLink: THelpLink<ForgeElement<Record<string, any>>>;
|
|
12
12
|
export declare const PersonalSettings: TPersonalSettings<ForgeElement<Record<string, any>>>;
|
|
13
|
-
export declare const
|
|
13
|
+
export declare const PersonalSettingsItem: TPersonalSettingsItem<ForgeElement<Record<string, any>>>;
|
|
14
14
|
export type { GlobalProps, MainProps, SidebarProps, LinkMenuItemProps, ExpandableMenuItemProps, FlyOutMenuItemProps, CreateButtonProps, CreateMenuItemProps, HelpLinkProps, PersonalSettingsProps, PersonalSettingsItemProps } from '@atlaskit/forge-react-types/global';
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/global/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,QAAQ,EACR,KAAK,EACL,OAAO,EACP,aAAa,EACb,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,MAAM,4CAA+C,CAAC;AACnE,eAAO,MAAM,IAAI,0CAA2C,CAAC;AAC7D,eAAO,MAAM,OAAO,6CAAiD,CAAC;AACtE,eAAO,MAAM,YAAY,kDAA2D,CAAC;AACrF,eAAO,MAAM,kBAAkB,wDAAuE,CAAC;AACvG,eAAO,MAAM,cAAc,oDAA+D,CAAC;AAC3F,eAAO,MAAM,YAAY,kDAA2D,CAAC;AACrF,eAAO,MAAM,cAAc,oDAA+D,CAAC;AAC3F,eAAO,MAAM,QAAQ,8CAAmD,CAAC;AACzE,eAAO,MAAM,gBAAgB,sDAAmE,CAAC;AACjG,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/global/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,QAAQ,EACR,KAAK,EACL,OAAO,EACP,aAAa,EACb,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,MAAM,4CAA+C,CAAC;AACnE,eAAO,MAAM,IAAI,0CAA2C,CAAC;AAC7D,eAAO,MAAM,OAAO,6CAAiD,CAAC;AACtE,eAAO,MAAM,YAAY,kDAA2D,CAAC;AACrF,eAAO,MAAM,kBAAkB,wDAAuE,CAAC;AACvG,eAAO,MAAM,cAAc,oDAA+D,CAAC;AAC3F,eAAO,MAAM,YAAY,kDAA2D,CAAC;AACrF,eAAO,MAAM,cAAc,oDAA+D,CAAC;AAC3F,eAAO,MAAM,QAAQ,8CAAmD,CAAC;AACzE,eAAO,MAAM,gBAAgB,sDAAmE,CAAC;AACjG,eAAO,MAAM,oBAAoB,0DAA2E,CAAC;AAG7G,YAAY,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,yBAAyB,EAC1B,MAAM,oCAAoC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PersonalSettingsItem = exports.PersonalSettings = exports.HelpLink = exports.CreateMenuItem = exports.CreateButton = exports.FlyOutMenuItem = exports.ExpandableMenuItem = exports.LinkMenuItem = exports.Sidebar = exports.Main = exports.Global = void 0;
|
|
4
4
|
exports.Global = 'Global';
|
|
5
5
|
exports.Main = 'Main';
|
|
6
6
|
exports.Sidebar = 'Sidebar';
|
|
@@ -11,4 +11,4 @@ exports.CreateButton = 'CreateButton';
|
|
|
11
11
|
exports.CreateMenuItem = 'CreateMenuItem';
|
|
12
12
|
exports.HelpLink = 'HelpLink';
|
|
13
13
|
exports.PersonalSettings = 'PersonalSettings';
|
|
14
|
-
exports.
|
|
14
|
+
exports.PersonalSettingsItem = 'PersonalSettingsItem';
|
|
@@ -26,14 +26,28 @@ const MOCK_CONTEXT_NO_THEME = {
|
|
|
26
26
|
extension: {}
|
|
27
27
|
};
|
|
28
28
|
const themeListener = jest.fn();
|
|
29
|
+
const flushUpdates = () => reconcilerTestRenderer_1.default.act(async () => {
|
|
30
|
+
await Promise.resolve();
|
|
31
|
+
await (0, utils_1.sleep)();
|
|
32
|
+
});
|
|
33
|
+
const emitThemeChanged = async (theme) => {
|
|
34
|
+
await reconcilerTestRenderer_1.default.act(async () => {
|
|
35
|
+
utils_1.simpleBridgeEvents.emit('FORGE_CORE_THEME_CHANGED', { theme });
|
|
36
|
+
await (0, utils_1.sleep)();
|
|
37
|
+
});
|
|
38
|
+
};
|
|
29
39
|
// react app fragment to load useTheme hook
|
|
30
|
-
const renderTest = async () => {
|
|
40
|
+
const renderTest = async (options) => {
|
|
41
|
+
const flushAfterMount = options?.flushAfterMount ?? true;
|
|
31
42
|
const Test = () => {
|
|
32
43
|
const theme = (0, useTheme_1.useTheme)();
|
|
33
44
|
(0, react_1.useEffect)(() => themeListener(theme), [theme]);
|
|
34
45
|
return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, {});
|
|
35
46
|
};
|
|
36
47
|
const { update } = await reconcilerTestRenderer_1.default.create((0, jsx_runtime_1.jsx)(Test, {}));
|
|
48
|
+
if (flushAfterMount) {
|
|
49
|
+
await flushUpdates();
|
|
50
|
+
}
|
|
37
51
|
return {
|
|
38
52
|
update: async () => {
|
|
39
53
|
await update((0, jsx_runtime_1.jsx)(Test, {}));
|
|
@@ -62,17 +76,19 @@ describe('useTheme', () => {
|
|
|
62
76
|
await renderTest();
|
|
63
77
|
expect(themeListener).toHaveBeenCalledWith(expect.objectContaining(MOCK_THEME));
|
|
64
78
|
const newTheme = { colorMode: 'light', colorScheme: 'red' };
|
|
65
|
-
|
|
66
|
-
await (0, utils_1.sleep)();
|
|
79
|
+
await emitThemeChanged(newTheme);
|
|
67
80
|
expect(themeListener).toHaveBeenCalledWith(expect.objectContaining(newTheme));
|
|
68
81
|
});
|
|
69
82
|
it('does not cause re-render when theme content is the same', async () => {
|
|
70
83
|
mockGetContext.mockResolvedValue(MOCK_CONTEXT_WITH_THEME);
|
|
71
84
|
await renderTest();
|
|
72
|
-
expect(themeListener).toHaveBeenCalledTimes(2); //
|
|
85
|
+
expect(themeListener).toHaveBeenCalledTimes(2); // null, then theme
|
|
73
86
|
// Emit same theme content but different object reference
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
await reconcilerTestRenderer_1.default.act(async () => {
|
|
88
|
+
utils_1.simpleBridgeEvents.emit('FORGE_CORE_THEME_CHANGED', {
|
|
89
|
+
theme: { ...MOCK_THEME } // New object, same content
|
|
90
|
+
});
|
|
91
|
+
await (0, utils_1.sleep)();
|
|
76
92
|
});
|
|
77
93
|
// Should not trigger re-render due to isEqual check
|
|
78
94
|
expect(themeListener).toHaveBeenCalledTimes(2);
|
|
@@ -84,13 +100,21 @@ describe('useTheme', () => {
|
|
|
84
100
|
resolveGetContext = resolve;
|
|
85
101
|
});
|
|
86
102
|
mockGetContext.mockReturnValue(getContextPromise);
|
|
87
|
-
const renderPromise = renderTest();
|
|
103
|
+
const renderPromise = renderTest({ flushAfterMount: false });
|
|
104
|
+
await renderPromise;
|
|
88
105
|
// Fire event before getContext resolves
|
|
89
106
|
const eventTheme = { colorMode: 'light', colorScheme: 'green' };
|
|
90
|
-
|
|
107
|
+
await reconcilerTestRenderer_1.default.act(async () => {
|
|
108
|
+
utils_1.simpleBridgeEvents.emit('FORGE_CORE_THEME_CHANGED', { theme: eventTheme });
|
|
109
|
+
await (0, utils_1.sleep)();
|
|
110
|
+
});
|
|
91
111
|
// Now resolve getContext
|
|
92
|
-
|
|
93
|
-
|
|
112
|
+
await reconcilerTestRenderer_1.default.act(async () => {
|
|
113
|
+
resolveGetContext?.(MOCK_CONTEXT_WITH_THEME);
|
|
114
|
+
await getContextPromise;
|
|
115
|
+
await (0, utils_1.sleep)();
|
|
116
|
+
});
|
|
117
|
+
await flushUpdates();
|
|
94
118
|
// Should have the event theme, not the getContext theme
|
|
95
119
|
expect(themeListener).toHaveBeenCalledWith(expect.objectContaining(eventTheme));
|
|
96
120
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/hooks/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,WAAW,EAAQ,MAAM,eAAe,CAAC;AAG/D,aAAK,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAElC,eAAO,MAAM,QAAQ,QAAO,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/hooks/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,WAAW,EAAQ,MAAM,eAAe,CAAC;AAG/D,aAAK,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAElC,eAAO,MAAM,QAAQ,QAAO,KAAK,GAAG,IAkEnC,CAAC"}
|
package/out/hooks/useTheme.js
CHANGED
|
@@ -7,31 +7,61 @@ const bridge_1 = require("@forge/bridge");
|
|
|
7
7
|
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
8
8
|
const useTheme = () => {
|
|
9
9
|
const [theme, setTheme] = (0, react_1.useState)(null);
|
|
10
|
+
const themeRef = (0, react_1.useRef)(null);
|
|
10
11
|
const themeLoadedRef = (0, react_1.useRef)(false);
|
|
12
|
+
const loadingContextRef = (0, react_1.useRef)(false);
|
|
13
|
+
const applyTheme = (0, react_1.useCallback)((nextTheme) => {
|
|
14
|
+
if ((0, isEqual_1.default)(themeRef.current, nextTheme)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
themeRef.current = nextTheme;
|
|
18
|
+
setTheme((current) => ((0, isEqual_1.default)(current, nextTheme) ? current : nextTheme));
|
|
19
|
+
}, []);
|
|
11
20
|
(0, react_1.useEffect)(() => {
|
|
21
|
+
let cancelled = false;
|
|
12
22
|
void (async () => {
|
|
13
|
-
if (
|
|
23
|
+
if (themeLoadedRef.current || loadingContextRef.current) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
loadingContextRef.current = true;
|
|
27
|
+
try {
|
|
14
28
|
const context = await bridge_1.view.getContext();
|
|
15
|
-
if (context?.theme
|
|
16
|
-
|
|
17
|
-
return (0, isEqual_1.default)(currentTheme, context.theme) ? currentTheme : context.theme;
|
|
18
|
-
});
|
|
19
|
-
themeLoadedRef.current = true;
|
|
29
|
+
if (cancelled || !context?.theme || themeLoadedRef.current) {
|
|
30
|
+
return;
|
|
20
31
|
}
|
|
32
|
+
applyTheme(context.theme);
|
|
33
|
+
themeLoadedRef.current = true;
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
loadingContextRef.current = false;
|
|
21
37
|
}
|
|
22
38
|
})();
|
|
23
|
-
|
|
39
|
+
return () => {
|
|
40
|
+
cancelled = true;
|
|
41
|
+
};
|
|
42
|
+
}, [applyTheme]);
|
|
24
43
|
(0, react_1.useEffect)(() => {
|
|
44
|
+
let unsubscribeFn = null;
|
|
45
|
+
let cancelled = false;
|
|
25
46
|
const sub = bridge_1.events.on('FORGE_CORE_THEME_CHANGED', ({ theme: updatedTheme }) => {
|
|
26
47
|
themeLoadedRef.current = true;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
applyTheme(updatedTheme);
|
|
49
|
+
});
|
|
50
|
+
void sub.then((subscription) => {
|
|
51
|
+
if (cancelled) {
|
|
52
|
+
subscription.unsubscribe();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
unsubscribeFn = () => subscription.unsubscribe();
|
|
56
|
+
}
|
|
30
57
|
});
|
|
31
58
|
return () => {
|
|
32
|
-
|
|
59
|
+
cancelled = true;
|
|
60
|
+
if (unsubscribeFn) {
|
|
61
|
+
unsubscribeFn();
|
|
62
|
+
}
|
|
33
63
|
};
|
|
34
|
-
}, []);
|
|
64
|
+
}, [applyTheme]);
|
|
35
65
|
return theme;
|
|
36
66
|
};
|
|
37
67
|
exports.useTheme = useTheme;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/react",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.18.0-next.0",
|
|
4
4
|
"description": "Forge React reconciler",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@atlaskit/adf-schema": "^48.0.0",
|
|
33
33
|
"@atlaskit/adf-utils": "^19.19.0",
|
|
34
34
|
"@atlaskit/forge-react-types": "^1.7.0",
|
|
35
|
-
"@forge/bridge": "^5.
|
|
35
|
+
"@forge/bridge": "^5.18.0-next.0",
|
|
36
36
|
"@forge/egress": "^2.3.2",
|
|
37
37
|
"@forge/i18n": "0.0.7",
|
|
38
38
|
"@types/react": "^18.2.64",
|