@equinor/roma-framework 6.0.1-beta.1 → 6.0.1-beta.10

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.
@@ -30,7 +30,7 @@
30
30
 
31
31
  <meta name='viewport' content='width=device-width, initial-scale=1'/>
32
32
  <link rel='icon' type='image/x-icon' href='/favicon.ico'/>
33
- <script type="module" crossorigin src="/roma-framework.umd.js"></script>
33
+ <script type="module" crossorigin src="/index-DYpA1xV-.mjs"></script>
34
34
  <link rel="stylesheet" crossorigin href="/roma-framework.css">
35
35
  </head>
36
36
  <body>
@@ -1,4 +1,9 @@
1
1
  import { AppManifest } from '@equinor/fusion-framework-module-app';
2
+ type AppManifestWithMetadata = AppManifest & {
3
+ metadata?: {
4
+ assets?: Array<string>;
5
+ };
6
+ };
2
7
  /**
3
8
  * Component that will render a Fusion application
4
9
  *
@@ -8,7 +13,8 @@ import { AppManifest } from '@equinor/fusion-framework-module-app';
8
13
  * @constructor
9
14
  */
10
15
  export declare function AppLoader({ app, kind, props, }: {
11
- app: AppManifest | null;
16
+ app: AppManifestWithMetadata | null;
12
17
  kind?: 'app' | 'widget';
13
18
  props?: Record<string | number, any>;
14
19
  }): import("react/jsx-runtime").JSX.Element;
20
+ export {};
@@ -1,7 +1,12 @@
1
- import { AppBuildManifest, AppConfig, AppManifest, IAppClient } from '@equinor/fusion-framework-module-app';
1
+ import { AppBuildManifest, AppConfig, AppManifest as FusionAppManifest, IAppClient } from '@equinor/fusion-framework-module-app';
2
2
  import { Observable } from 'rxjs';
3
3
  import { IHttpClient } from '@equinor/fusion-framework-module-http';
4
4
  import { FetchRequest } from '@equinor/fusion-framework-module-http/client';
5
+ type AppManifest = FusionAppManifest & {
6
+ metadata?: {
7
+ assets?: Array<string>;
8
+ };
9
+ };
5
10
  export declare class CustomAppClient implements IAppClient {
6
11
  #private;
7
12
  private client;
@@ -59,6 +64,9 @@ export declare class CustomAppClient implements IAppClient {
59
64
  }[] | null | undefined;
60
65
  build?: (AppBuildManifest & import('../../api/roma').BuildDto) | undefined;
61
66
  routes?: import('@equinor/fusion-framework-module-app').RouteSchemaEntry[] | null | undefined;
67
+ metadata?: {
68
+ assets?: Array<string>;
69
+ };
62
70
  version: import('../../api/roma').VersionDto;
63
71
  shortName: string;
64
72
  entry: string;
@@ -82,3 +90,4 @@ export declare class CustomAppClient implements IAppClient {
82
90
  tag?: string;
83
91
  }): Observable<AppBuildManifest>;
84
92
  }
93
+ export {};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/roma-framework",
3
- "version": "6.0.1-beta.1",
3
+ "version": "6.0.1-beta.10",
4
4
  "repository": "https://github.com/equinor/tops-roma",
5
5
  "types": "./index.d.ts",
6
6
  "private": false,
@@ -22,10 +22,9 @@
22
22
  "@equinor/fusion-framework-react-module": "^4.0.0",
23
23
  "@equinor/fusion-framework-react-module-http": "^11.0.0",
24
24
  "@equinor/fusion-framework-react-router": "^1.0.2",
25
- "@equinor/roma-sse-module": "workspace:*",
25
+ "@equinor/roma-sse-module": "1.0.0-beta.6",
26
26
  "react": "^19.2.4",
27
27
  "react-dom": "^19.2.4",
28
- "react-intl": "^10.1.0",
29
28
  "react-router-dom": "^7.13.2",
30
29
  "rxjs": "^7.8.2",
31
30
  "styled-components": "^6.3.11"
@@ -36,6 +35,7 @@
36
35
  "@tanstack/react-query-persist-client": "^5.90.24",
37
36
  "idb-keyval": "^6.2.2",
38
37
  "immer": "^11.0.0",
38
+ "react-intl": "^10.1.0",
39
39
  "is-mergeable-object": "^1.1.1"
40
40
  },
41
41
  "devDependencies": {
@@ -1,4 +1,9 @@
1
1
  import { AppManifest } from '@equinor/fusion-framework-module-app';
2
+ type AppManifestWithMetadata = AppManifest & {
3
+ metadata?: {
4
+ assets?: Array<string>;
5
+ };
6
+ };
2
7
  /**
3
8
  * Component that will render a Fusion application
4
9
  *
@@ -8,7 +13,8 @@ import { AppManifest } from '@equinor/fusion-framework-module-app';
8
13
  * @constructor
9
14
  */
10
15
  export declare function AppLoader({ app, kind, props, }: {
11
- app: AppManifest | null;
16
+ app: AppManifestWithMetadata | null;
12
17
  kind?: 'app' | 'widget';
13
18
  props?: Record<string | number, any>;
14
19
  }): import("react/jsx-runtime").JSX.Element;
20
+ export {};
@@ -1,7 +1,12 @@
1
- import { AppBuildManifest, AppConfig, AppManifest, IAppClient } from '@equinor/fusion-framework-module-app';
1
+ import { AppBuildManifest, AppConfig, AppManifest as FusionAppManifest, IAppClient } from '@equinor/fusion-framework-module-app';
2
2
  import { Observable } from 'rxjs';
3
3
  import { IHttpClient } from '@equinor/fusion-framework-module-http';
4
4
  import { FetchRequest } from '@equinor/fusion-framework-module-http/client';
5
+ type AppManifest = FusionAppManifest & {
6
+ metadata?: {
7
+ assets?: Array<string>;
8
+ };
9
+ };
5
10
  export declare class CustomAppClient implements IAppClient {
6
11
  #private;
7
12
  private client;
@@ -59,6 +64,9 @@ export declare class CustomAppClient implements IAppClient {
59
64
  }[] | null | undefined;
60
65
  build?: (AppBuildManifest & import('../../api/roma').BuildDto) | undefined;
61
66
  routes?: import('@equinor/fusion-framework-module-app').RouteSchemaEntry[] | null | undefined;
67
+ metadata?: {
68
+ assets?: Array<string>;
69
+ };
62
70
  version: import('../../api/roma').VersionDto;
63
71
  shortName: string;
64
72
  entry: string;
@@ -82,3 +90,4 @@ export declare class CustomAppClient implements IAppClient {
82
90
  tag?: string;
83
91
  }): Observable<AppBuildManifest>;
84
92
  }
93
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/roma-framework",
3
- "version": "6.0.1-beta.1",
3
+ "version": "6.0.1-beta.10",
4
4
  "repository": "https://github.com/equinor/tops-roma",
5
5
  "types": "./index.d.ts",
6
6
  "private": false,
@@ -22,10 +22,9 @@
22
22
  "@equinor/fusion-framework-react-module": "^4.0.0",
23
23
  "@equinor/fusion-framework-react-module-http": "^11.0.0",
24
24
  "@equinor/fusion-framework-react-router": "^1.0.2",
25
- "@equinor/roma-sse-module": "workspace:*",
25
+ "@equinor/roma-sse-module": "1.0.0-beta.6",
26
26
  "react": "^19.2.4",
27
27
  "react-dom": "^19.2.4",
28
- "react-intl": "^10.1.0",
29
28
  "react-router-dom": "^7.13.2",
30
29
  "rxjs": "^7.8.2",
31
30
  "styled-components": "^6.3.11"
@@ -36,6 +35,7 @@
36
35
  "@tanstack/react-query-persist-client": "^5.90.24",
37
36
  "idb-keyval": "^6.2.2",
38
37
  "immer": "^11.0.0",
38
+ "react-intl": "^10.1.0",
39
39
  "is-mergeable-object": "^1.1.1"
40
40
  },
41
41
  "devDependencies": {
@@ -5,8 +5,9 @@ import { useState, useEffect, lazy, useRef, createContext, useContext, useMemo }
5
5
  import { ModuleProvider } from "@equinor/fusion-framework-react-module";
6
6
  import styled, { StyleSheetManager, keyframes } from "styled-components";
7
7
  import { EdsProvider, StarProgress, Typography, Card, Button, TopBar, Chip, SideSheet, Menu, Tooltip, Icon, List } from "@equinor/eds-core-react";
8
- import { E as EmptyError, o as operate, c as createOperatorSubscriber, i as innerFrom, a as identity, b as isFunction, I as IntlProvider, u as useParams, L as Link, B as BehaviorSubject, f as firstValueFrom, g as getDefaultExportFromCjs, d as of, e as from } from "./_commonjsHelpers-CIHTj2Un.mjs";
8
+ import { E as EmptyError, o as operate, c as createOperatorSubscriber, i as innerFrom, a as identity, b as isFunction, u as useParams, L as Link, B as BehaviorSubject, f as firstValueFrom, g as getDefaultExportFromCjs, d as of, e as from } from "./_commonjsHelpers-DKlypwS6.mjs";
9
9
  import { QueryClient, QueryClientProvider, useQueryClient, useMutation, useQuery } from "@tanstack/react-query";
10
+ import { IntlProvider } from "react-intl";
10
11
  import { useCurrentApp, useApps as useApps$1 } from "@equinor/fusion-framework-react/app";
11
12
  import { App } from "@equinor/fusion-framework-module-app/app";
12
13
  import { tokens } from "@equinor/eds-tokens";
@@ -196,7 +197,7 @@ const makeComponent = (Component, args, configure2) => lazy(async () => {
196
197
  source: Component
197
198
  });
198
199
  const queryClient = args.query ?? new QueryClient();
199
- const version2 = "6.0.1-beta.1";
200
+ const version2 = "6.0.1-beta.10";
200
201
  return {
201
202
  default: () => /* @__PURE__ */ jsx(FrameworkProvider, { value: fusion, children: /* @__PURE__ */ jsx(IntlProvider, { locale: navigator.language, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(StyleProvider, { scope: `roma-${appKey}`, version: version2, children: /* @__PURE__ */ jsx(
202
203
  EdsEventProvider,
@@ -281,6 +282,44 @@ function getAppModule(app, framework) {
281
282
  const appModuleScript = appModule.initialize();
282
283
  return { appModule, appModuleScript };
283
284
  }
285
+ async function loadCssAssets(app, container) {
286
+ const assets = app.metadata?.assets;
287
+ if (!assets || assets.length === 0)
288
+ return () => {
289
+ };
290
+ const cssAssets = assets.filter((url) => url.split("?")[0].endsWith(".css"));
291
+ const injectedStyles = [];
292
+ const results = await Promise.allSettled(
293
+ cssAssets.map(async (cssUrl) => {
294
+ const filename = cssUrl.split("?")[0].split("/").pop() ?? cssUrl;
295
+ const tag = `${app.appKey}-${filename}`;
296
+ if (container.querySelector(`style[data-asset="${tag}"]`)) return;
297
+ const response = await fetch(cssUrl);
298
+ if (!response.ok) {
299
+ console.warn(
300
+ `Failed to load CSS asset: ${cssUrl} (${response.status})`
301
+ );
302
+ return;
303
+ }
304
+ const cssText = await response.text();
305
+ const style = document.createElement("style");
306
+ style.setAttribute("data-asset", tag);
307
+ style.textContent = `@scope { ${cssText} }`;
308
+ container.appendChild(style);
309
+ injectedStyles.push(style);
310
+ })
311
+ );
312
+ for (const result of results) {
313
+ if (result.status === "rejected") {
314
+ console.warn("Failed to load CSS asset:", result.reason);
315
+ }
316
+ }
317
+ return () => {
318
+ for (const style of injectedStyles) {
319
+ style.remove();
320
+ }
321
+ };
322
+ }
284
323
  function AppLoader({
285
324
  app,
286
325
  kind,
@@ -298,15 +337,15 @@ function AppLoader({
298
337
  new CustomEvent(eventName, data)
299
338
  );
300
339
  };
301
- function renderApplication(el) {
340
+ async function renderApplication(el) {
302
341
  const { appModule, appModuleScript } = getAppModule(app, framework);
303
342
  const [basename] = window.location.pathname.match(
304
343
  /\/?apps\/[a-z|-]+(\/)?/g
305
344
  ) ?? [""];
306
- lastValueFrom(appModuleScript).then((x) => {
345
+ const cleanup = await lastValueFrom(appModuleScript).then((x) => {
307
346
  const script = x.script;
308
347
  const render = script.renderApp ?? script.default;
309
- render(el, {
348
+ const cleanup2 = render(el, {
310
349
  query: queryClient,
311
350
  fusion: framework,
312
351
  env: {
@@ -322,8 +361,9 @@ function AppLoader({
322
361
  if (kind === "app") {
323
362
  setCurrentApp(app.appKey);
324
363
  }
364
+ return cleanup2;
325
365
  });
326
- return appModule;
366
+ return { appModule, cleanup };
327
367
  }
328
368
  useEffect(() => {
329
369
  setError(null);
@@ -335,15 +375,41 @@ function AppLoader({
335
375
  setLoading(true);
336
376
  const el = document.createElement("div");
337
377
  ref.current?.appendChild(el);
338
- const appModule = renderApplication(el);
378
+ let cleanupCss = () => {
379
+ ref.current?.removeChild(
380
+ document.querySelector("[data-asset]")
381
+ );
382
+ };
383
+ loadCssAssets(app, ref.current).then((cleanup2) => {
384
+ cleanupCss = cleanup2;
385
+ });
386
+ let appModule = null;
387
+ let cleanup = null;
388
+ let disposed = false;
389
+ renderApplication(el).then((r) => {
390
+ if (disposed) {
391
+ queueMicrotask(() => {
392
+ r.cleanup();
393
+ r.appModule.dispose();
394
+ });
395
+ return;
396
+ }
397
+ appModule = r.appModule;
398
+ cleanup = r.cleanup;
399
+ });
339
400
  setLoading(false);
340
401
  const currentRef = ref.current;
341
402
  return () => {
403
+ disposed = true;
404
+ cleanupCss?.();
342
405
  try {
343
406
  currentRef?.removeChild(el);
344
407
  } catch {
345
408
  }
346
- appModule.dispose();
409
+ queueMicrotask(() => {
410
+ if (appModule) appModule.dispose();
411
+ if (cleanup) cleanup();
412
+ });
347
413
  if (kind === "app") clearCurrentApp();
348
414
  };
349
415
  }, [app]);