@equinor/fusion-framework-react-app 10.0.7 → 11.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.
@@ -0,0 +1,139 @@
1
+ # Settings
2
+
3
+ Persist and read app-specific user settings using the Fusion settings service.
4
+
5
+ **Import:**
6
+
7
+ ```ts
8
+ import { useAppSetting, useAppSettings } from '@equinor/fusion-framework-react-app/settings';
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ App settings let users customise their experience (theme, layout, filters) with values persisted per-user by the Fusion platform. The `useAppSetting` hook manages a single setting, while `useAppSettings` provides access to all settings at once.
14
+
15
+ ## Type Your Settings
16
+
17
+ Use module augmentation to get type-safe setting keys and values:
18
+
19
+ ```ts
20
+ declare module '@equinor/fusion-framework-react-app/settings' {
21
+ interface AppSettings {
22
+ theme: 'default' | 'light' | 'dark';
23
+ mode: 'simple' | 'advanced';
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## useAppSetting
29
+
30
+ Manages a single setting by key. Returns the current value and a setter function, similar to `useState`.
31
+
32
+ **Signature:**
33
+
34
+ ```ts
35
+ function useAppSetting<TSettings, TProp extends keyof TSettings>(
36
+ prop: TProp,
37
+ defaultValue?: TSettings[TProp],
38
+ hooks?: AppSettingsStatusHooks & {
39
+ onError?: (error: Error | null) => void;
40
+ onUpdated?: () => void;
41
+ },
42
+ ): [TSettings[TProp] | undefined, (update: TSettings[TProp] | ((current: TSettings[TProp] | undefined) => TSettings[TProp])) => void];
43
+ ```
44
+
45
+ ### Example
46
+
47
+ ```tsx
48
+ import { useCallback } from 'react';
49
+ import { useAppSetting } from '@equinor/fusion-framework-react-app/settings';
50
+
51
+ const ThemeSwitcher = () => {
52
+ const [theme, setTheme] = useAppSetting('theme', 'default');
53
+ const [mode, setMode] = useAppSetting('mode', 'simple');
54
+
55
+ const toggleMode = useCallback(() => {
56
+ setMode((current) => (current === 'simple' ? 'advanced' : 'simple'));
57
+ }, [setMode]);
58
+
59
+ return (
60
+ <div>
61
+ {/* cast: e.target.value is string, but setTheme expects the union type */}
62
+ <select value={theme ?? 'default'} onChange={(e) => setTheme(e.target.value as AppSettings['theme'])}>
63
+ <option value="default">Default</option>
64
+ <option value="light">Light</option>
65
+ <option value="dark">Dark</option>
66
+ </select>
67
+ <button onClick={toggleMode}>Toggle mode ({mode})</button>
68
+ </div>
69
+ );
70
+ };
71
+ ```
72
+
73
+ ## useAppSettings
74
+
75
+ Returns all settings as a single object with a bulk setter. Use `useAppSetting` for individual settings when possible — `useAppSettings` triggers a re-render on _any_ setting change.
76
+
77
+ **Signature:**
78
+
79
+ ```ts
80
+ function useAppSettings<TSettings>(
81
+ defaultValue?: TSettings,
82
+ hooks?: AppSettingsStatusHooks & {
83
+ onError?: (error: Error | null) => void;
84
+ onUpdated?: () => void;
85
+ },
86
+ ): [TSettings, (update: TSettings | ((current: TSettings | undefined) => TSettings)) => void];
87
+ ```
88
+
89
+ > [!WARNING]
90
+ > **`setSettings` must include all settings, not just the ones you want to change.** Use a callback to merge with the current state:
91
+ >
92
+ > ```ts
93
+ > setSettings((current) => ({ ...current, theme: 'dark' }));
94
+ > ```
95
+
96
+ ### Example
97
+
98
+ ```tsx
99
+ import { useCallback } from 'react';
100
+ import { useAppSettings } from '@equinor/fusion-framework-react-app/settings';
101
+
102
+ const SettingsPanel = () => {
103
+ const [settings, setSettings] = useAppSettings();
104
+
105
+ const updateTheme = useCallback(
106
+ (theme: AppSettings['theme']) => setSettings((current) => ({ ...current, theme })),
107
+ [setSettings],
108
+ );
109
+
110
+ return <ThemeSelector value={settings?.theme} onChange={updateTheme} />;
111
+ };
112
+ ```
113
+
114
+ ## Status Hooks
115
+
116
+ Both hooks accept optional status callbacks for loading, updating, and error states:
117
+
118
+ ```tsx
119
+ const [loading, setLoading] = useState(false);
120
+ const [updating, setUpdating] = useState(false);
121
+ const [error, setError] = useState<Error | null>(null);
122
+
123
+ const [theme, setTheme] = useAppSetting('theme', 'default', {
124
+ onLoading: setLoading,
125
+ onUpdating: setUpdating,
126
+ onError: setError,
127
+ onUpdated: useCallback(() => console.log('Saved'), []),
128
+ });
129
+ ```
130
+
131
+ > [!NOTE]
132
+ > `onUpdating` and `onLoading` reflect the _global_ settings state, not individual settings. Disable update buttons while either is `true`.
133
+
134
+ ## Notes
135
+
136
+ - Settings are async — there is a loading phase when the component mounts and an updating phase when values are saved
137
+ - `useAppSetting` captures the `hooks` object once on mount (via `useState`); **the callbacks must be stable before the first render** — changes after mount are ignored
138
+ - `useAppSettings` reads `hooks` on every render; **memoise callbacks** (e.g. with `useCallback`) to avoid unnecessary re-renders
139
+ - Settings are persisted per-user per-app by the Fusion platform
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-react-app",
3
- "version": "10.0.7",
3
+ "version": "11.0.0",
4
4
  "description": "",
5
5
  "main": "./dist/esm/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -60,6 +60,10 @@
60
60
  "./widget": {
61
61
  "types": "./dist/types/widget/index.d.ts",
62
62
  "import": "./dist/esm/widget/index.js"
63
+ },
64
+ "./routing": {
65
+ "types": "./dist/types/routing/index.d.ts",
66
+ "import": "./dist/esm/routing/index.js"
63
67
  }
64
68
  },
65
69
  "typesVersions": {
@@ -102,6 +106,9 @@
102
106
  ],
103
107
  "widget": [
104
108
  "dist/types/widget/index.d.ts"
109
+ ],
110
+ "routing": [
111
+ "dist/types/routing/index.d.ts"
105
112
  ]
106
113
  }
107
114
  },
@@ -117,14 +124,14 @@
117
124
  "directory": "packages/react"
118
125
  },
119
126
  "dependencies": {
120
- "@equinor/fusion-framework-app": "11.0.5",
127
+ "@equinor/fusion-framework-app": "11.0.7",
128
+ "@equinor/fusion-framework-module": "6.1.0",
121
129
  "@equinor/fusion-framework-module-app": "8.0.2",
122
- "@equinor/fusion-framework-module": "6.0.0",
123
- "@equinor/fusion-framework-module-http": "8.0.1",
130
+ "@equinor/fusion-framework-module-navigation": "7.0.4",
131
+ "@equinor/fusion-framework-module-http": "8.0.2",
124
132
  "@equinor/fusion-framework-react": "8.0.0",
125
133
  "@equinor/fusion-framework-react-module-http": "11.0.0",
126
- "@equinor/fusion-framework-react-module": "4.0.0",
127
- "@equinor/fusion-framework-module-navigation": "7.0.3"
134
+ "@equinor/fusion-framework-react-module": "4.0.1"
128
135
  },
129
136
  "devDependencies": {
130
137
  "@types/react": "^19.2.7",
@@ -135,21 +142,23 @@
135
142
  "rxjs": "^7.8.1",
136
143
  "typescript": "^6.0.3",
137
144
  "vitest": "^4.1.0",
138
- "@equinor/fusion-framework-module-analytics": "2.0.4",
145
+ "@equinor/fusion-framework-module-analytics": "2.0.6",
146
+ "@equinor/fusion-framework-module-ag-grid": "36.0.1",
139
147
  "@equinor/fusion-framework-module-event": "6.0.0",
140
- "@equinor/fusion-framework-module-ag-grid": "36.0.0",
141
- "@equinor/fusion-framework-module-msal": "8.0.4",
142
- "@equinor/fusion-framework-react-module-context": "7.0.0",
143
148
  "@equinor/fusion-framework-module-feature-flag": "2.0.1",
144
149
  "@equinor/fusion-framework-react-module-bookmark": "6.0.0",
145
- "@equinor/fusion-observable": "9.0.1"
150
+ "@equinor/fusion-framework-react-module-context": "7.0.1",
151
+ "@equinor/fusion-framework-module-msal": "9.0.0",
152
+ "@equinor/fusion-framework-react-router": "2.2.0",
153
+ "@equinor/fusion-observable": "9.0.2"
146
154
  },
147
155
  "peerDependencies": {
148
156
  "@types/react": "^18.0.0 || ^19.0.0",
149
157
  "react": "^18.0.0 || ^19.0.0",
150
158
  "react-dom": "^18.0.0 || ^19.0.0",
151
159
  "rxjs": "^7.0.0",
152
- "@equinor/fusion-framework-module-msal": "^8.0.4"
160
+ "@equinor/fusion-framework-module-msal": "^9.0.0",
161
+ "@equinor/fusion-framework-react-router": "^2.2.0"
153
162
  },
154
163
  "peerDependenciesMeta": {
155
164
  "@equinor/fusion-framework-react-module-ag-grid": {
@@ -178,6 +187,9 @@
178
187
  },
179
188
  "rxjs": {
180
189
  "optional": true
190
+ },
191
+ "@equinor/fusion-framework-react-router": {
192
+ "optional": true
181
193
  }
182
194
  },
183
195
  "scripts": {
@@ -1,5 +1,8 @@
1
1
  # `@equinor/fusion-framework-react-app/apploader`
2
2
 
3
+ > [!NOTE]
4
+ > This file is kept for legacy tooling. The canonical documentation is in [`packages/react/app/docs/apploader.md`](../../docs/apploader.md) and published via VuePress.
5
+
3
6
  [Apploader](#apploader) component and [useApploader](#useapploader) is intended to be used to embed Fusion applications inside other Fusion application.
4
7
 
5
8
  > [!WARNING]
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Routing sub-path entry-point for `@equinor/fusion-framework-react-app`.
3
+ *
4
+ * Re-exports the full public API of `@equinor/fusion-framework-react-router`
5
+ * and its route builder DSL so consumers can import all routing primitives
6
+ * from a single entry point without adding a separate direct dependency.
7
+ *
8
+ * Requires `@equinor/fusion-framework-react-router` to be installed.
9
+ * It is declared as an optional peer dependency — install it only when
10
+ * you need routing in your app, portal, or widget.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { Router } from '@equinor/fusion-framework-react-app/routing';
15
+ * import { layout, index, route } from '@equinor/fusion-framework-react-app/routing';
16
+ * ```
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ export * from '@equinor/fusion-framework-react-router';
21
+ // Explicit re-exports from /routes so the DSL `Route` class takes precedence
22
+ // over the deprecated react-router `Route` component from the main entry.
23
+ export {
24
+ index,
25
+ IndexRoute,
26
+ route,
27
+ Route,
28
+ layout,
29
+ LayoutRoute,
30
+ prefix,
31
+ PrefixRoute,
32
+ } from '@equinor/fusion-framework-react-router/routes';
33
+ export type { RouteSchemaEntry } from '@equinor/fusion-framework-react-router/routes';
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '10.0.7';
2
+ export const version = '11.0.0';