@openmrs/esm-react-utils 5.1.1-pre.956 → 5.1.1-pre.977

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": "@openmrs/esm-react-utils",
3
- "version": "5.1.1-pre.956",
3
+ "version": "5.1.1-pre.977",
4
4
  "license": "MPL-2.0",
5
5
  "description": "React utilities for OpenMRS.",
6
6
  "browser": "dist/openmrs-esm-react-utils.js",
@@ -56,12 +56,12 @@
56
56
  "react-i18next": "11.x"
57
57
  },
58
58
  "devDependencies": {
59
- "@openmrs/esm-api": "^5.1.1-pre.956",
60
- "@openmrs/esm-config": "^5.1.1-pre.956",
61
- "@openmrs/esm-error-handling": "^5.1.1-pre.956",
62
- "@openmrs/esm-extensions": "^5.1.1-pre.956",
63
- "@openmrs/esm-feature-flags": "^5.1.1-pre.956",
64
- "@openmrs/esm-globals": "^5.1.1-pre.956",
59
+ "@openmrs/esm-api": "^5.1.1-pre.977",
60
+ "@openmrs/esm-config": "^5.1.1-pre.977",
61
+ "@openmrs/esm-error-handling": "^5.1.1-pre.977",
62
+ "@openmrs/esm-extensions": "^5.1.1-pre.977",
63
+ "@openmrs/esm-feature-flags": "^5.1.1-pre.977",
64
+ "@openmrs/esm-globals": "^5.1.1-pre.977",
65
65
  "dayjs": "^1.10.8",
66
66
  "i18next": "^19.6.0",
67
67
  "react": "^18.1.0",
@@ -70,5 +70,5 @@
70
70
  "rxjs": "^6.5.3",
71
71
  "webpack": "^5.88.0"
72
72
  },
73
- "gitHead": "927a57eaf6b330bc5c009f9a2f4436133ea8ffc5"
73
+ "gitHead": "2f86869e3d798182626597f57691400b1bdbca11"
74
74
  }
@@ -20,6 +20,12 @@ function RenderConfig(props) {
20
20
  return <button>{config[props.configKey]}</button>;
21
21
  }
22
22
 
23
+ function RenderExternalConfig(props) {
24
+ const config = useConfig({ externalModuleName: props.externalModuleName });
25
+
26
+ return <button>{config[props.configKey]}</button>;
27
+ }
28
+
23
29
  function clearConfig() {
24
30
  mockConfigInternalStore.resetMock();
25
31
  }
@@ -297,4 +303,40 @@ describe(`useConfig in an extension`, () => {
297
303
  expect(screen.findByText("Yet another thing")).toBeTruthy()
298
304
  );
299
305
  });
306
+
307
+ it("can optionally load an external module's configuration", async () => {
308
+ defineConfigSchema("first-module", {
309
+ thing: {
310
+ _default: "first thing",
311
+ },
312
+ });
313
+
314
+ defineConfigSchema("second-module", {
315
+ thing: {
316
+ _default: "second thing",
317
+ },
318
+ });
319
+
320
+ render(
321
+ <React.Suspense fallback={<div>Suspense!</div>}>
322
+ <ComponentContext.Provider
323
+ value={{
324
+ moduleName: "first-module",
325
+ extension: {
326
+ extensionSlotName: "fooSlot",
327
+ extensionSlotModuleName: "slot-mod",
328
+ extensionId: "fooExt#id1",
329
+ },
330
+ }}
331
+ >
332
+ <RenderExternalConfig
333
+ externalModuleName="second-module"
334
+ configKey="thing"
335
+ />
336
+ </ComponentContext.Provider>
337
+ </React.Suspense>
338
+ );
339
+
340
+ await waitFor(() => expect(screen.findByText("second thing")).toBeTruthy());
341
+ });
300
342
  });
package/src/useConfig.ts CHANGED
@@ -157,16 +157,24 @@ function useNormalConfig(moduleName: string) {
157
157
  return state;
158
158
  }
159
159
 
160
+ interface UseConfigOptions {
161
+ /** An external module to load the configuration from. This option should only be used if
162
+ absolutely necessary as it can end up making frontend modules coupled to one another. */
163
+ externalModuleName?: string;
164
+ }
165
+
160
166
  /**
161
167
  * Use this React Hook to obtain your module's configuration.
168
+ *
169
+ * @param options Additional options that can be passed to useConfig()
162
170
  */
163
- export function useConfig<
164
- T = Omit<ConfigObject, "Display conditions" | "Translation overrides">
165
- >() {
171
+ export function useConfig<T = Record<string, any>>(options?: UseConfigOptions) {
166
172
  // This hook uses the config of the MF defining the component.
167
173
  // If the component is used in an extension slot then the slot
168
174
  // may override (part of) its configuration.
169
- const { moduleName, extension } = useContext(ComponentContext);
175
+ const { moduleName: contextModuleName, extension } =
176
+ useContext(ComponentContext);
177
+ const moduleName = options?.externalModuleName ?? contextModuleName;
170
178
 
171
179
  if (!moduleName && !extension) {
172
180
  throw Error(errorMessage);
@@ -175,11 +183,11 @@ export function useConfig<
175
183
  const normalConfig = useNormalConfig(moduleName);
176
184
  const extensionConfig = useExtensionConfig(extension);
177
185
  const config = useMemo(
178
- () => ({
179
- ...normalConfig,
180
- ...extensionConfig,
181
- }),
182
- [normalConfig, extensionConfig]
186
+ () =>
187
+ options?.externalModuleName && moduleName === options.externalModuleName
188
+ ? { ...normalConfig }
189
+ : { ...normalConfig, ...extensionConfig },
190
+ [moduleName, options?.externalModuleName, normalConfig, extensionConfig]
183
191
  );
184
192
 
185
193
  return config as T;