@equinor/fusion-framework-dev-portal 4.0.4 → 5.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-dev-portal",
3
- "version": "4.0.4",
3
+ "version": "5.0.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "module": "./dist/main.js",
@@ -17,49 +17,65 @@
17
17
  "access": "public"
18
18
  },
19
19
  "devDependencies": {
20
- "@equinor/eds-core-react": "^0.49.0",
21
- "@equinor/eds-icons": "^0.22.0",
22
- "@equinor/eds-tokens": "^0.10.0",
23
- "@equinor/fusion-react-context-selector": "^1.0.6",
20
+ "@equinor/eds-core-react": "^2.3.7",
21
+ "@equinor/eds-icons": "^1.3.0",
22
+ "@equinor/eds-tokens": "^2.2.0",
23
+ "@equinor/fusion-react-context-selector": "^2.0.1",
24
24
  "@equinor/fusion-react-progress-indicator": "^0.3.0",
25
- "@equinor/fusion-react-side-sheet": "2.0.0",
26
- "@equinor/fusion-react-styles": "^0.6.4",
25
+ "@equinor/fusion-react-side-sheet": "^2.0.0",
26
+ "@equinor/fusion-react-styles": "^2.0.0",
27
27
  "@equinor/fusion-wc-chip": "^1.2.2",
28
28
  "@equinor/fusion-wc-person": "^3.4.0",
29
- "@material-ui/styles": "^4.11.5",
30
- "@types/dotenv": "^8.2.3",
31
- "@types/react": "^18.2.50",
32
- "@types/react-dom": "^18.2.7",
33
- "@vitejs/plugin-react": "^5.0.2",
34
- "dotenv": "^17.2.2",
35
- "react": "^18.2.0",
36
- "react-dom": "^18.2.0",
37
- "react-router-dom": "^6.15.0",
29
+ "@types/react": "^19.2.7",
30
+ "@types/react-dom": "^19.2.3",
31
+ "@vitejs/plugin-react": "^6.0.1",
32
+ "dotenv": "^17.3.1",
33
+ "react": "^19.2.1",
34
+ "react-dom": "^19.2.1",
35
+ "react-router-dom": "^7.9.5",
38
36
  "rxjs": "^7.8.1",
39
- "styled-components": "^6.0.7",
37
+ "styled-components": "^6.3.11",
40
38
  "tsx": "^4.19.3",
41
- "typescript": "^5.8.2",
42
- "vite": "^7.1.12"
39
+ "typescript": "^5.9.3",
40
+ "vite": "^8.0.0",
41
+ "@equinor/fusion-framework": "8.0.0",
42
+ "@equinor/fusion-framework-app": "11.0.0",
43
+ "@equinor/fusion-framework-dev-server": "2.0.0",
44
+ "@equinor/fusion-framework-module-ag-grid": "36.0.0",
45
+ "@equinor/fusion-framework-module-app": "8.0.0",
46
+ "@equinor/fusion-framework-module-analytics": "2.0.0",
47
+ "@equinor/fusion-framework-module-bookmark": "4.0.0",
48
+ "@equinor/fusion-framework-module-feature-flag": "2.0.0",
49
+ "@equinor/fusion-framework-module-navigation": "7.0.0",
50
+ "@equinor/fusion-framework-module-services": "8.0.0",
51
+ "@equinor/fusion-framework-react": "8.0.0",
52
+ "@equinor/fusion-framework-module-telemetry": "5.0.0",
53
+ "@equinor/fusion-framework-react-components-bookmark": "2.0.0",
54
+ "@equinor/fusion-framework-react-components-people-provider": "2.0.0",
55
+ "@equinor/fusion-framework-module-context": "8.0.0",
56
+ "@equinor/fusion-framework-react-module-bookmark": "6.0.0",
57
+ "@equinor/fusion-observable": "9.0.0",
58
+ "@equinor/fusion-query": "7.0.0"
43
59
  },
44
60
  "peerDependencies": {
45
- "@equinor/fusion-framework": "7.4.13",
46
- "@equinor/fusion-framework-dev-server": "1.1.31",
47
- "@equinor/fusion-framework-module-analytics": "1.0.2",
48
- "@equinor/fusion-framework-app": "10.4.9",
49
- "@equinor/fusion-framework-module-app": "7.4.1",
50
- "@equinor/fusion-framework-module-context": "7.0.3",
51
- "@equinor/fusion-framework-module-bookmark": "3.0.6",
52
- "@equinor/fusion-framework-module-navigation": "6.0.1",
53
- "@equinor/fusion-framework-module-feature-flag": "1.1.28",
54
- "@equinor/fusion-framework-module-services": "7.2.1",
55
- "@equinor/fusion-framework-module-telemetry": "4.6.4",
56
- "@equinor/fusion-framework-react": "7.4.20",
57
- "@equinor/fusion-framework-react-components-bookmark": "1.1.3",
58
- "@equinor/fusion-framework-react-components-people-provider": "1.6.3",
59
- "@equinor/fusion-framework-react-module-bookmark": "5.0.2",
60
- "@equinor/fusion-observable": "8.5.8",
61
- "@equinor/fusion-query": "6.0.4",
62
- "@equinor/fusion-framework-module-ag-grid": "35.0.2"
61
+ "@equinor/fusion-framework-app": "11.0.0",
62
+ "@equinor/fusion-framework-module-ag-grid": "36.0.0",
63
+ "@equinor/fusion-framework-module-app": "8.0.0",
64
+ "@equinor/fusion-framework-module-analytics": "2.0.0",
65
+ "@equinor/fusion-framework-dev-server": "2.0.0",
66
+ "@equinor/fusion-framework-module-bookmark": "4.0.0",
67
+ "@equinor/fusion-framework-module-context": "8.0.0",
68
+ "@equinor/fusion-framework": "8.0.0",
69
+ "@equinor/fusion-framework-module-feature-flag": "2.0.0",
70
+ "@equinor/fusion-framework-module-navigation": "7.0.0",
71
+ "@equinor/fusion-framework-module-services": "8.0.0",
72
+ "@equinor/fusion-framework-module-telemetry": "5.0.0",
73
+ "@equinor/fusion-framework-react-components-bookmark": "2.0.0",
74
+ "@equinor/fusion-framework-react-components-people-provider": "2.0.0",
75
+ "@equinor/fusion-framework-react-module-bookmark": "6.0.0",
76
+ "@equinor/fusion-framework-react": "8.0.0",
77
+ "@equinor/fusion-query": "7.0.0",
78
+ "@equinor/fusion-observable": "9.0.0"
63
79
  },
64
80
  "peerDependenciesMeta": {
65
81
  "@equinor/fusion-framework": {
package/src/AppLoader.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useEffect, useId, useMemo, useRef, useState } from 'react';
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
2
 
3
3
  import { Subscription } from 'rxjs';
4
4
  import { last } from 'rxjs/operators';
@@ -13,11 +13,18 @@ import { ErrorViewer } from './ErrorViewer';
13
13
  import type { AppModule } from '@equinor/fusion-framework-module-app';
14
14
  import EquinorLoader from './EquinorLoader';
15
15
 
16
+ /**
17
+ * URL search-parameter key used to specify an app version tag.
18
+ *
19
+ * When present in the URL as `?$tag=<value>`, the portal loads that
20
+ * specific version of the application instead of the default.
21
+ */
16
22
  export const TAG = '$tag';
17
23
 
18
24
  /**
19
- * Gets the app tag/version from the current URL search parameters
20
- * @returns The app tag/version if present in URL, otherwise null
25
+ * Reads the application version tag from the current URL search parameters.
26
+ *
27
+ * @returns The tag string if the `$tag` search parameter is present, otherwise `null`.
21
28
  */
22
29
  export const getAppTagFromUrl = (): string | null => {
23
30
  const url = new URL(window.location.href);
@@ -25,11 +32,14 @@ export const getAppTagFromUrl = (): string | null => {
25
32
  };
26
33
 
27
34
  /**
28
- * React Functional Component for handling current application
35
+ * Loads, initializes, and mounts a Fusion application by its key.
36
+ *
37
+ * Sets the current app on the framework's app module, observes initialization
38
+ * progress, and renders the app's script output into a private DOM element.
39
+ * Displays a loading spinner while the app initializes and an error view if
40
+ * manifest resolution or initialization fails.
29
41
  *
30
- * this component will set the current app by provided appKey.
31
- * when the appKey changes, this component will try to initialize the referred application
32
- * and render it.
42
+ * @param props.appKey - Unique key identifying the Fusion application to load.
33
43
  */
34
44
  export const AppLoader = (props: { readonly appKey: string }) => {
35
45
  const { appKey } = props;
@@ -37,7 +47,6 @@ export const AppLoader = (props: { readonly appKey: string }) => {
37
47
 
38
48
  /** reference of application section/container */
39
49
  const ref = useRef<HTMLElement>(null);
40
- const applicationContentId = useId();
41
50
 
42
51
  const [loading, setLoading] = useState<boolean>(false);
43
52
  const [error, setError] = useState<Error | undefined>();
@@ -130,7 +139,7 @@ export const AppLoader = (props: { readonly appKey: string }) => {
130
139
  }
131
140
 
132
141
  return (
133
- <section id={applicationContentId} ref={ref} style={{ display: 'contents' }}>
142
+ <section id="app-section" ref={ref} style={{ display: 'contents' }}>
134
143
  {loading && <EquinorLoader text="Loading Application" />}
135
144
  </section>
136
145
  );
@@ -3,11 +3,22 @@ import { Bookmark } from '@equinor/fusion-framework-react-components-bookmark';
3
3
  import { useBookmarkComponentContext } from '@equinor/fusion-framework-react-components-bookmark';
4
4
  import { SideSheet } from '@equinor/fusion-react-side-sheet';
5
5
 
6
+ /** Props for the {@link BookmarkSideSheet} component. */
6
7
  type BookmarkSideSheetProps = {
8
+ /** Whether the side sheet is currently visible. */
7
9
  readonly isOpen: boolean;
10
+ /** Callback invoked when the user dismisses the side sheet. */
8
11
  readonly onClose: VoidFunction;
9
12
  };
10
13
 
14
+ /**
15
+ * Side sheet overlay for browsing and creating application bookmarks.
16
+ *
17
+ * Wraps the `Bookmark` component from `@equinor/fusion-framework-react-components-bookmark`
18
+ * in a dismissible side sheet with an "Add Bookmark" action button.
19
+ *
20
+ * @param props - {@link BookmarkSideSheetProps}
21
+ */
11
22
  export const BookmarkSideSheet = ({ isOpen, onClose }: BookmarkSideSheetProps) => {
12
23
  const { provider, showCreateBookmark } = useBookmarkComponentContext();
13
24
 
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useId, useMemo } from 'react';
1
+ import { useCallback, useEffect, useId, useMemo, type ReactElement } from 'react';
2
2
  import {
3
3
  ContextProvider,
4
4
  ContextSearch,
@@ -9,11 +9,17 @@ import {
9
9
  import { useContextResolver } from './useContextResolver';
10
10
 
11
11
  /**
12
- * See fusion-react-component storybook for available attributes
13
- * @link https://equinor.github.io/fusion-react-components/?path=/docs/data-contextselector--component
14
- * @returns JSX element
12
+ * Context selector component wired to the current application's context module.
13
+ *
14
+ * Renders a search input with dropdown results from the Fusion context service.
15
+ * When the user selects a context item, it is set as the current context on the
16
+ * application's context provider. Clearing the selector resets the current context.
17
+ *
18
+ * @see {@link https://equinor.github.io/fusion-react-components/?path=/docs/data-contextselector--component | ContextSelector Storybook}
19
+ * @param props - Passthrough props for the underlying `ContextSearch` component.
20
+ * @returns The context selector element, or `null` if no context resolver is available.
15
21
  */
16
- export const ContextSelector = (props: ContextSearchProps): JSX.Element | null => {
22
+ export const ContextSelector = (props: ContextSearchProps): ReactElement | null => {
17
23
  const contextSelectorId = useId();
18
24
  const {
19
25
  resolver,
@@ -24,10 +24,22 @@ import type { AppModulesInstance } from '@equinor/fusion-framework-app';
24
24
  import type { QueryClientError } from '@equinor/fusion-query/client';
25
25
  import type { FusionContextSearchError } from '@equinor/fusion-framework-module-context/errors.js';
26
26
 
27
+ /**
28
+ * Capitalizes the first letter of a string and lowercases the rest.
29
+ *
30
+ * @param string - The input string to capitalize.
31
+ * @returns The capitalized string.
32
+ */
27
33
  function capitalizeFirstLetter(string: string): string {
28
34
  return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
29
35
  }
30
36
 
37
+ /**
38
+ * Converts a {@link ContextItem} graphic field to the shape expected by `ContextResultItem`.
39
+ *
40
+ * @param graphic - The graphic value from a context item (string, SVG object, or undefined).
41
+ * @returns An object with `graphic` and `graphicType` properties, or an empty object.
42
+ */
31
43
  function convertGraphic(
32
44
  graphic: ContextItem['graphic'],
33
45
  ): Pick<ContextResultItem, 'graphic' | 'graphicType'> {
@@ -57,6 +69,12 @@ function convertGraphic(
57
69
  };
58
70
  }
59
71
 
72
+ /**
73
+ * Converts a {@link ContextItem} meta field to the shape expected by `ContextResultItem`.
74
+ *
75
+ * @param meta - The meta value from a context item (string, SVG object, or undefined).
76
+ * @returns An object with `meta` and `metaType` properties, or an empty object.
77
+ */
60
78
  function convertMeta(meta: ContextItem['meta']): Pick<ContextResultItem, 'metaType' | 'meta'> {
61
79
  if (meta === undefined) {
62
80
  return {};
@@ -85,10 +103,13 @@ function convertMeta(meta: ContextItem['meta']): Pick<ContextResultItem, 'metaTy
85
103
  }
86
104
 
87
105
  /**
88
- * Map context query result to ContextSelectorResult.
89
- * Add any icons to selected types by using the 'graphic' property
90
- * @param src context query result
91
- * @returns src mapped to ContextResult type
106
+ * Maps an array of context items to `ContextResult` for the context selector dropdown.
107
+ *
108
+ * Applies custom rendering for `EquinorTask` (shows inactive state chip) and
109
+ * `OrgChart` (shows list icon and inactive state chip) context types.
110
+ *
111
+ * @param src - Array of context items from the context query.
112
+ * @returns Mapped array of `ContextResultItem` objects for the selector UI.
92
113
  */
93
114
  const mapper = (src: ContextItem<{ taskState?: string; state?: string }>[]): ContextResult => {
94
115
  return src.map((i) => {
@@ -127,19 +148,28 @@ const mapper = (src: ContextItem<{ taskState?: string; state?: string }>[]): Con
127
148
  };
128
149
 
129
150
  /**
130
- * Create a single ContextResultItem
131
- * @param props pops for the item to merge with defaults
132
- * @returns ContextResultItem
151
+ * Creates a single `ContextResultItem` with sensible defaults.
152
+ *
153
+ * Used to generate placeholder or error entries in the context selector dropdown.
154
+ *
155
+ * @param props - Partial properties to merge into the default item shape.
156
+ * @returns A complete `ContextResultItem` with defaults for `id` and `title`.
133
157
  */
134
158
  const singleItem = (props: Partial<ContextResultItem>): ContextResultItem => {
135
159
  return Object.assign({ id: 'no-such-item', title: 'Change me' }, props);
136
160
  };
137
161
 
138
162
  /**
139
- * Hook for querying context and setting resolver for ContextSelector component
140
- * See React Components storybook for info about ContextSelector component and its resolver
141
- * @link https://equinor.github.io/fusion-react-components/?path=/docs/data-contextselector--component
142
- * @return Array<ContextResolver, SetContextCallback>
163
+ * Hook that creates a context resolver, tracks the current context provider,
164
+ * and provides the currently selected context for the {@link ContextSelector}.
165
+ *
166
+ * Observes the current application's module instances. When the app exposes a
167
+ * context module, the hook wires up a search resolver that queries context items
168
+ * and maps results to `ContextResultItem`. It also handles error display and
169
+ * minimum query length enforcement.
170
+ *
171
+ * @see {@link https://equinor.github.io/fusion-react-components/?path=/docs/data-contextselector--component | ContextSelector Storybook}
172
+ * @returns An object containing the `resolver` for the selector, the current `provider`, and `currentContext` items.
143
173
  */
144
174
  export const useContextResolver = (): {
145
175
  resolver: ContextResolver | null;
@@ -1,10 +1,19 @@
1
1
  import type React from 'react';
2
2
  import { StarProgress } from '@equinor/fusion-react-progress-indicator';
3
3
 
4
+ /**
5
+ * Full-viewport loading indicator displaying the Equinor star spinner.
6
+ *
7
+ * Used as a fallback while the Fusion Framework or an application is initializing.
8
+ *
9
+ * @param props.text - Status message displayed below the spinner.
10
+ * @param props.children - Optional additional content rendered inside the spinner.
11
+ * @returns A centered full-screen loading overlay.
12
+ */
4
13
  export const EquinorLoader = ({
5
14
  children,
6
15
  text,
7
- }: React.PropsWithChildren<{ readonly text: string }>): JSX.Element => {
16
+ }: React.PropsWithChildren<{ readonly text: string }>): React.ReactElement => {
8
17
  return (
9
18
  <div
10
19
  style={{
@@ -1,5 +1,14 @@
1
1
  import { Typography } from '@equinor/eds-core-react';
2
2
 
3
+ /**
4
+ * Recursively renders an error and its causal chain.
5
+ *
6
+ * Displays the error message and stack trace for each error in the `cause`
7
+ * chain, providing full visibility into nested failures during app loading.
8
+ *
9
+ * @param props.error - The error to display, including any nested `cause` errors.
10
+ * @returns A bordered section showing the error message, stack trace, and any nested causes.
11
+ */
3
12
  export const ErrorViewer = ({ error }: { readonly error: Error }) => {
4
13
  return (
5
14
  <>
@@ -1,10 +1,22 @@
1
1
  import { useId } from 'react';
2
2
  import type { SVGProps } from 'react';
3
3
 
4
+ /** Props for the {@link FusionLogo} component. */
4
5
  type FusionLogoProps = Omit<SVGProps<SVGSVGElement>, 'viewBox'> & {
6
+ /** Uniform scale multiplier applied via CSS transform. Defaults to `1`. */
5
7
  readonly scale?: number;
6
8
  };
7
9
 
10
+ /**
11
+ * Inline SVG rendering of the Fusion logo.
12
+ *
13
+ * Uses unique gradient IDs per instance so multiple logos can coexist on the
14
+ * same page without gradient collisions.
15
+ *
16
+ * @param props.scale - Scale multiplier for the logo size.
17
+ * @param props.style - Additional inline styles merged with the computed transform.
18
+ * @returns An inline SVG element sized to `1em` height.
19
+ */
8
20
  export const FusionLogo = ({ scale = 1, style }: FusionLogoProps) => {
9
21
  const paint0Id = useId();
10
22
  const paint1Id = useId();
@@ -6,12 +6,24 @@ PersonAvatarElement;
6
6
 
7
7
  import { useBookmarkComponentContext } from '@equinor/fusion-framework-react-components-bookmark';
8
8
 
9
+ /** Props for the {@link HeaderActions} component. */
9
10
  interface HeaderActionProps {
11
+ /** Azure AD object ID of the current user, used for the person avatar. */
10
12
  readonly userAzureId?: string;
13
+ /** Toggle callback for the bookmark side sheet open/close state. */
11
14
  readonly toggleBookmark: (open: (status: boolean) => boolean) => void;
15
+ /** Toggle callback for the person settings side sheet open/close state. */
12
16
  readonly togglePerson: (open: (status: boolean) => boolean) => void;
13
17
  }
14
18
 
19
+ /**
20
+ * Action buttons displayed in the portal top bar header.
21
+ *
22
+ * Renders a bookmark toggle button (disabled when no bookmark provider is
23
+ * available) and a person-avatar button that opens the user settings sheet.
24
+ *
25
+ * @param props - {@link HeaderActionProps}
26
+ */
15
27
  export const HeaderActions = (props: HeaderActionProps) => {
16
28
  const { toggleBookmark, togglePerson, userAzureId } = props;
17
29
 
package/src/Header.tsx CHANGED
@@ -33,6 +33,13 @@ const Styled = {
33
33
  `,
34
34
  };
35
35
 
36
+ /**
37
+ * Portal top bar header containing the Fusion logo, context selector, and action buttons.
38
+ *
39
+ * Composes the bookmark provider with the current app and user so bookmark
40
+ * and person side sheets can operate in context. Provides the sticky top bar
41
+ * layout used across all portal pages.
42
+ */
36
43
  export const Header = () => {
37
44
  const currentUser = useCurrentUser();
38
45
  const topBarId = useId();
@@ -7,15 +7,23 @@ import { Divider } from '@equinor/eds-core-react';
7
7
 
8
8
  import { LandingSheetContent, FeatureSheetContent } from './sheets';
9
9
 
10
+ /** Props for the {@link PersonSideSheet} component. */
10
11
  type PersonSideSheetProps = {
12
+ /** Azure AD object ID of the user to display in the side sheet. */
11
13
  readonly azureId?: string;
14
+ /** Whether the side sheet is currently visible. */
12
15
  readonly isOpen: boolean;
16
+ /** Callback invoked when the user dismisses the side sheet. */
13
17
  onClose(): void;
14
18
  };
15
19
 
16
20
  /**
17
- * Add Sidesheet with settings for the current user.
18
- * @param PersonSideSheetProps
21
+ * Side sheet overlay that displays user settings and feature toggles.
22
+ *
23
+ * Contains a person list item for the current user and navigable sub-sheets
24
+ * for viewing and toggling application and portal feature flags.
25
+ *
26
+ * @param props - {@link PersonSideSheetProps}
19
27
  */
20
28
  export const PersonSideSheet = ({ azureId, isOpen, onClose }: PersonSideSheetProps) => {
21
29
  const [currentSheet, setCurrentSheet] = useState<string>('landing');
@@ -9,8 +9,12 @@ Icon.add({ arrow_back, category });
9
9
  import type { SheetContentProps } from './types';
10
10
 
11
11
  /**
12
- * JSX structure for the content of the PersonSidesheet's Features page.
13
- * @param SheetContentProps
12
+ * Feature flags sub-sheet for the person settings side sheet.
13
+ *
14
+ * Contains tabbed panels for toggling application-level and portal-level
15
+ * feature flags. Includes a back-navigation button to return to the landing sheet.
16
+ *
17
+ * @param props.navigate - Callback to navigate back to the landing sheet.
14
18
  */
15
19
  export const FeatureSheetContent = ({ navigate }: SheetContentProps) => {
16
20
  const [tab, setTab] = useState<number>(0);
@@ -5,7 +5,10 @@ import { Typography, Switch } from '@equinor/eds-core-react';
5
5
  import { Styled } from './Styled';
6
6
 
7
7
  /**
8
- * JSX structure for Feature toggler tab for app features in the PersonSidesheet's Feature page.
8
+ * Feature toggle list for application-level feature flags.
9
+ *
10
+ * Reads feature flags from the current app's feature-flag module and renders
11
+ * each flag as a labeled switch. Clicking a row toggles the flag.
9
12
  */
10
13
  export const FeatureTogglerApp = () => {
11
14
  const { features, toggleFeature } = useCurrentAppFeatures();
@@ -5,7 +5,10 @@ import { Typography, Switch } from '@equinor/eds-core-react';
5
5
  import { Styled } from './Styled';
6
6
 
7
7
  /**
8
- * Content for Feature toggler tab for portal features in the PersonSidesheet's Feature page.
8
+ * Feature toggle list for portal-level feature flags.
9
+ *
10
+ * Reads feature flags from the framework's feature-flag module and renders
11
+ * each flag as a labeled switch. Clicking a row toggles the flag.
9
12
  */
10
13
  export const FeatureTogglerPortal = () => {
11
14
  const { features, toggleFeature } = useFrameworkFeatures();
@@ -15,7 +15,13 @@ const BtnListItem = styled.li`
15
15
  `;
16
16
 
17
17
  /**
18
- * Content for the main tab in the PersonSidesheet.
18
+ * Landing page content for the person settings side sheet.
19
+ *
20
+ * Displays navigation buttons for sub-sheets (e.g., feature toggles) and
21
+ * an external link to the user's Delve profile.
22
+ *
23
+ * @param props.azureId - Azure AD object ID used to build the Delve profile link.
24
+ * @param props.navigate - Callback to navigate to a sub-sheet by key.
19
25
  */
20
26
  export const LandingSheetContent = ({ azureId, navigate }: SheetContentProps) => {
21
27
  return (
@@ -1,4 +1,8 @@
1
1
  import styled from 'styled-components';
2
+
3
+ /**
4
+ * Shared styled components used by feature toggle lists in the person side sheet.
5
+ */
2
6
  export const Styled = {
3
7
  SwitchList: styled.ul`
4
8
  list-style: none;
@@ -1,5 +1,14 @@
1
+ /**
2
+ * Shared props for person side sheet sub-pages.
3
+ *
4
+ * Each sheet content component receives these props from the parent
5
+ * {@link PersonSideSheet} to support navigation between sheets.
6
+ */
1
7
  export type SheetContentProps = {
8
+ /** Azure AD object ID of the current user. */
2
9
  readonly azureId?: string;
10
+ /** Key of the currently active sheet. */
3
11
  readonly sheet?: string;
12
+ /** Navigates to a different sheet by key, or back to the landing sheet when called without arguments. */
4
13
  navigate(sheet?: string): void;
5
14
  };
package/src/Router.tsx CHANGED
@@ -31,6 +31,12 @@ const Styled = {
31
31
  `,
32
32
  };
33
33
 
34
+ /**
35
+ * Root layout component for the dev portal.
36
+ *
37
+ * Renders the header and a scrollable main area via `Outlet`. Activates
38
+ * bookmark-to-navigation linking through `useBookmarkNavigate`.
39
+ */
34
40
  const Root = () => {
35
41
  useBookmarkNavigate({ resolveAppPath: (appKey: string) => `/apps/${appKey}` });
36
42
  return (
@@ -45,12 +51,16 @@ const Root = () => {
45
51
  );
46
52
  };
47
53
 
54
+ /**
55
+ * Route component that extracts the `appKey` parameter and delegates to {@link AppLoader}.
56
+ */
48
57
  // eslint-disable-next-line react/no-multi-comp
49
58
  const AppRoute = () => {
50
59
  const { appKey } = useParams();
51
60
  return appKey ? <AppLoader appKey={appKey} /> : null;
52
61
  };
53
62
 
63
+ /** Route definitions for the dev portal. */
54
64
  const routes = [
55
65
  {
56
66
  path: '/',
@@ -64,6 +74,13 @@ const routes = [
64
74
  },
65
75
  ];
66
76
 
77
+ /**
78
+ * Top-level router for the Fusion Dev Portal.
79
+ *
80
+ * Creates a router instance from the framework navigation module and
81
+ * renders it via `RouterProvider`. Observes context changes through
82
+ * {@link useAppContextNavigation} to keep the URL in sync.
83
+ */
67
84
  // eslint-disable-next-line react/no-multi-comp
68
85
  export const Router = () => {
69
86
  const { navigation } = useFramework<[NavigationModule]>().modules;
package/src/config.ts CHANGED
@@ -26,16 +26,21 @@ declare global {
26
26
  }
27
27
 
28
28
  /**
29
- * Configures the Fusion Dev Portal with all required modules and features
29
+ * Configures the Fusion Dev Portal framework with all required modules.
30
30
  *
31
- * This function sets up the complete framework configuration including:
32
- * - Telemetry tracking for portal analytics
33
- * - Core app functionality and navigation
34
- * - Bookmark management system
35
- * - Feature flagging for development features
36
- * - Service integrations
31
+ * Enables and wires together:
32
+ * - **Telemetry** portal-scoped usage analytics with version metadata.
33
+ * - **App module** application manifest loading and lifecycle.
34
+ * - **Navigation** router integration with optional telemetry.
35
+ * - **Services** standard Fusion service integrations.
36
+ * - **AG Grid** — enterprise license key from `window.FUSION_AG_GRID_KEY`.
37
+ * - **Analytics** — console adapter gated by the `fusionLogAnalytics` feature flag.
38
+ * - **Bookmarks** — source-system metadata identifying CLI-created bookmarks.
39
+ * - **Feature flags** — local-storage and URL-based flag plugins for dev toggles.
37
40
  *
38
- * @param config - The framework configurator instance to extend with portal features
41
+ * On initialization, exposes all modules on `window.Fusion` for debugging.
42
+ *
43
+ * @param config - The framework configurator instance to extend with portal modules.
39
44
  */
40
45
  export const configure = async (config: FrameworkConfigurator) => {
41
46
  // Enable telemetry tracking for portal usage analytics and monitoring
@@ -61,7 +66,15 @@ export const configure = async (config: FrameworkConfigurator) => {
61
66
 
62
67
  enableAppModule(config);
63
68
 
64
- enableNavigation(config);
69
+ enableNavigation(config, {
70
+ configure: (config) => {
71
+ config.setTelemetry(async (args) => {
72
+ if (args.hasModule('telemetry')) {
73
+ return await args.requireInstance('telemetry');
74
+ }
75
+ });
76
+ },
77
+ });
65
78
 
66
79
  enableServices(config);
67
80
 
@@ -121,7 +134,7 @@ export const configure = async (config: FrameworkConfigurator) => {
121
134
  config.onInitialized(async (modules) => {
122
135
  // NOTE: TypeScript ignore needed due to window object extension
123
136
  // This provides developer access to all initialized modules via window.Fusion
124
- // @ts-ignore
137
+ // @ts-expect-error
125
138
  window.Fusion = { modules };
126
139
  });
127
140
  };
package/src/main.tsx CHANGED
@@ -11,8 +11,19 @@ import { Router } from './Router';
11
11
 
12
12
  import fallbackSvg from './resources/fallback-photo.svg';
13
13
 
14
+ /** Fallback avatar image used when a person photo cannot be loaded. */
14
15
  const fallbackImage = new Blob([fallbackSvg], { type: 'image/svg+xml' });
15
16
 
17
+ /**
18
+ * Mounts the Fusion Dev Portal into the given DOM element.
19
+ *
20
+ * Creates a React root and renders the portal shell with the Equinor theme,
21
+ * Fusion Framework provider, people-resolver provider, and the portal router.
22
+ * This is the main entry point consumed by `@equinor/fusion-framework-dev-server`.
23
+ *
24
+ * @param target - The DOM element to mount the portal into.
25
+ * @param args - Render arguments containing a `ref` to the parent Fusion Framework instance.
26
+ */
16
27
  export const render: FusionRenderFn = (target, args) => {
17
28
  ReactDOM.createRoot(target).render(
18
29
  <ThemeProvider theme={theme}>