@equinor/fusion-framework-react-app 6.1.6-next.0 → 6.2.0-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9

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,14 +1,105 @@
1
1
  # Change Log
2
2
 
3
- ## 6.1.6-next.0
3
+ ## 6.2.0-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
4
+
5
+ ### Minor Changes
6
+
7
+ - [#3039](https://github.com/equinor/fusion-framework/pull/3039) [`4c7c39a`](https://github.com/equinor/fusion-framework/commit/4c7c39a75513b2c0f6c630aeb058dc98ff4b21f6) Thanks [@eikeland](https://github.com/eikeland)! - `@equinor/fusion-framework-react-app/fusion-apploader`
8
+
9
+ [FusionApploader](#fusionapploader) component and [useFusionApploader](#usefusionapploader) is intended to be used to embed Fusion applications inside other Fusion application.
10
+
11
+ > [!WARNING] > `FusionApploader` is an experimental poc.
12
+ >
13
+ > The embedded application will likely have issues with routing, context and other framework functionality, so use with care.
14
+ >
15
+ > Should only be used to embed 'simple' applications like **PowerBI** and **PowerApps**.
16
+
17
+ ## FusionApploader
18
+
19
+ React component for embeding a Fusion child application inside a parent Fusion application.
20
+
21
+ Handles loading and error states, and mounts the child app's DOM element into a container div.
22
+
23
+ If you need to customise the error and loading messages, then use the hook `useFusionApploader` and create your own component.
24
+
25
+ ### Example usage
26
+
27
+ ```typescript
28
+ <FusionApploader appKey="my-app" />
29
+ ```
30
+
31
+ ## useFusionApploader
32
+
33
+ A React hook for dynamically loading and mounting a Fusion child app inside a parent Fusion app. Handles loading state, error reporting, and provides a reference to the mounted app’s DOM element.
34
+
35
+ ### Signature
36
+
37
+ ```typescript
38
+ useFusionApploader({ appKey }: { appKey: string }): {
39
+ loading: boolean;
40
+ error: Error | undefined;
41
+ appRef: React.RefObject<HTMLDivElement | null>;
42
+ }
43
+ ```
44
+
45
+ ### Parameters
46
+
47
+ `appKey (string)`: The key of the Fusion app to load and mount.
48
+
49
+ ### Returns
50
+
51
+ - **loading** `(boolean)`: true while the app is loading.
52
+ - **error** `(Error | undefined)`: Error object if loading fails, otherwise undefined.
53
+ - **appRef** `(React.RefObject<HTMLDivElement | null>)`: Ref to the DOM element where the child app is mounted.
54
+
55
+ ### Usage Example
56
+
57
+ ```typescript
58
+ import React, { useEffect, useRef } from "react";
59
+ import { useFusionApploader } from "./useFusionAppLoader";
60
+
61
+ const MyAppLoader = ({ appKey }: { appKey: string }) => {
62
+ const wrapperRef = useRef<HTMLDivElement | null>(null);
63
+ const { loading, error, appRef } = useFusionApploader({ appKey });
64
+
65
+ useEffect(() => {
66
+ if (wrapperRef.current && appRef.current) {
67
+ wrapperRef.current.appendChild(appRef.current);
68
+ }
69
+ }, [appRef.current]);
70
+
71
+ if (loading) return <div>Loading {appKey}...</div>;
72
+ if (error)
73
+ return (
74
+ <div>
75
+ Error loading {appKey}: {error.message}
76
+ </div>
77
+ );
78
+
79
+ return <div ref={wrapperRef} />;
80
+ };
81
+ ```
82
+
83
+ ### Notes
84
+
85
+ - The hook is designed to be used in a parent Fusion app context.
86
+ - The returned appRef should be appended to a container element in your component.
87
+ - Handles subscription and cleanup automatically.
88
+ - Useful for micro-frontend scenarios where apps are loaded dynamically.
4
89
 
5
90
  ### Patch Changes
6
91
 
92
+ - pre-release changeset for tag **apploader**, all public packages are patched
93
+
7
94
  - Updated dependencies []:
8
- - @equinor/fusion-framework-app@9.3.15-next.0
9
- - @equinor/fusion-framework-module-app@6.1.13
10
- - @equinor/fusion-framework-react-module-http@9.0.3-next.0
11
- - @equinor/fusion-framework-react@7.4.13-next.0
95
+ - @equinor/fusion-framework-app@9.3.15-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
96
+ - @equinor/fusion-framework-module-app@6.1.14-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
97
+ - @equinor/fusion-framework-module@4.4.3-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
98
+ - @equinor/fusion-framework-module-msal@4.0.7-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
99
+ - @equinor/fusion-framework-module-navigation@5.0.3-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
100
+ - @equinor/fusion-framework-react@7.4.13-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
101
+ - @equinor/fusion-framework-react-module-http@9.0.3-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
102
+ - @equinor/fusion-framework-react-module@3.1.13-apploader-be21a6b60eb13eee8bf869e75002d8634e9c50a9
12
103
 
13
104
  ## 6.1.5
14
105
 
@@ -0,0 +1,35 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import { useFusionApploader } from './useFusionApploader';
4
+ /**
5
+ * FusionApploader component
6
+ *
7
+ * Embeds a Fusion child application inside a parent Fusion application.
8
+ * Handles loading and error states, and mounts the child app's DOM element into a container div.
9
+ *
10
+ * @param { FusionApploaderProps } props - The props for the component.
11
+ * @param { string } props.appKey - The key of the Fusion app to load and mount.
12
+ * @returns { JSX.Element } The rendered component, which displays loading, error, or the embedded app.
13
+ *
14
+ * @example
15
+ * <FusionApploader appKey="my-app" />
16
+ */
17
+ export const FusionApploader = ({ appKey }) => {
18
+ const refWrapp = useRef(null);
19
+ const { loading, error, appRef } = useFusionApploader({ appKey });
20
+ useEffect(() => {
21
+ if (!refWrapp.current || !appRef.current) {
22
+ return;
23
+ }
24
+ refWrapp.current.appendChild(appRef.current);
25
+ }, [appRef.current]);
26
+ if (loading) {
27
+ return _jsxs("div", { children: ["Loading ", appKey] });
28
+ }
29
+ if (error) {
30
+ return (_jsxs("div", { children: ["Error loading ", appKey, ". Error: ", error.message] }));
31
+ }
32
+ return _jsx("div", { ref: refWrapp });
33
+ };
34
+ export default FusionApploader;
35
+ //# sourceMappingURL=FusionApploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FusionApploader.js","sourceRoot":"","sources":["../../../src/fusion-apploader/FusionApploader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAM1D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,MAAM,EAAwB,EAAe,EAAE;IAC/E,MAAM,QAAQ,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO;QACT,CAAC;QAED,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAErB,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,sCAAc,MAAM,IAAO,CAAC;IACrC,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,4CACiB,MAAM,eAAW,KAAK,CAAC,OAAO,IACzC,CACP,CAAC;IACJ,CAAC;IAED,OAAO,cAAK,GAAG,EAAE,QAAQ,GAAI,CAAC;AAChC,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { FusionApploader } from './FusionApploader';
2
+ export { useFusionApploader } from './useFusionApploader';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/fusion-apploader/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA6B,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useFramework } from '@equinor/fusion-framework-react';
3
+ /**
4
+ * React hook for dynamically loading and mounting a Fusion child app inside a parent Fusion app.
5
+ * Handles loading state, error reporting, and provides a reference to the mounted app’s DOM element.
6
+ *
7
+ * @param { Object } params
8
+ * @param { string } params.appKey - The key of the Fusion app to load and mount.
9
+ * @returns {{
10
+ * loading: boolean,
11
+ * error: Error | undefined,
12
+ * appRef: React.RefObject<HTMLDivElement | null>
13
+ * }} An object containing loading state, error, and a ref to the mounted app element.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const { loading, error, appRef } = useFusionApploader({ appKey: 'my-app' });
18
+ *
19
+ * useEffect(() => {
20
+ * if (containerRef.current && appRef.current) {
21
+ * containerRef.current.appendChild(appRef.current);
22
+ * }
23
+ * }, [appRef.current]);
24
+ *
25
+ * if (loading) return <div>Loading...</div>;
26
+ * if (error) return <div>Error: {error.message}</div>;
27
+ * return <div ref={containerRef} />;
28
+ * ```
29
+ */
30
+ export const useFusionApploader = ({ appKey, }) => {
31
+ const [loading, setLoading] = useState(true);
32
+ const [error, setError] = useState();
33
+ const appRef = useRef(null);
34
+ const fusion = useFramework();
35
+ /**
36
+ * The current fusion app.
37
+ * aka the parent app that is loading the child app.
38
+ */
39
+ const fusionApp = useMemo(() => fusion.modules.app.current, [fusion]);
40
+ /**
41
+ * The app to be mounted
42
+ * aka the child app that is being loaded.
43
+ */
44
+ const loadedApp = useMemo(() => fusion.modules.app.createApp({ appKey }), [fusion, appKey]);
45
+ useEffect(() => {
46
+ setLoading(true);
47
+ setError(undefined);
48
+ const subscription$ = loadedApp?.initialize().subscribe({
49
+ next: ({ manifest, script, config }) => {
50
+ /* Application Element for mounting */
51
+ appRef.current = document.createElement('div');
52
+ appRef.current.id = manifest.appKey;
53
+ appRef.current.style.display = 'contents';
54
+ /* Use basename of current fusionApp */
55
+ const basename = `/apps/${fusionApp?.appKey}`;
56
+ try {
57
+ const render = script.renderApp ?? script.default;
58
+ if (render) {
59
+ return render(appRef.current, {
60
+ fusion,
61
+ env: { basename, config, manifest, props: {} },
62
+ });
63
+ }
64
+ throw Error('Application is not supported, no render function provided');
65
+ }
66
+ catch (error) {
67
+ console.error('App loading Error: ', error);
68
+ setError(error);
69
+ }
70
+ },
71
+ complete: () => {
72
+ setLoading(false);
73
+ },
74
+ error: (error) => {
75
+ setError(error);
76
+ setLoading(false);
77
+ },
78
+ });
79
+ return () => {
80
+ subscription$.unsubscribe();
81
+ };
82
+ }, [fusionApp, loadedApp, fusion]);
83
+ return {
84
+ loading,
85
+ error,
86
+ appRef,
87
+ };
88
+ };
89
+ //# sourceMappingURL=useFusionApploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFusionApploader.js","sourceRoot":"","sources":["../../../src/fusion-apploader/useFusionApploader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAK/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,MAAM,GACS,EAIf,EAAE;IACF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAqB,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,YAAY,EAAe,CAAC;IAE3C;;;OAGG;IACH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEtE;;;OAGG;IACH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5F,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpB,MAAM,aAAa,GAAG,SAAS,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC;YACtD,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;gBACrC,sCAAsC;gBACtC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC/C,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC;gBACpC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC;gBAE1C,uCAAuC;gBACvC,MAAM,QAAQ,GAAG,SAAS,SAAS,EAAE,MAAM,EAAE,CAAC;gBAE9C,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC;oBAClD,IAAI,MAAM,EAAE,CAAC;wBACX,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;4BAC5B,MAAM;4BACN,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;yBAC/C,CAAC,CAAC;oBACL,CAAC;oBACD,MAAM,KAAK,CAAC,2DAA2D,CAAC,CAAC;gBAC3E,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;oBAC5C,QAAQ,CAAC,KAAc,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;YACD,QAAQ,EAAE,GAAG,EAAE;gBACb,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,EAAE,CAAC,KAAY,EAAE,EAAE;gBACtB,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;SACF,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,aAAa,CAAC,WAAW,EAAE,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IAEnC,OAAO;QACL,OAAO;QACP,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  // Generated by genversion.
2
- export const version = '6.1.6-next.0';
2
+ export const version = '6.1.5';
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,cAAc,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}