@openmrs/esm-react-utils 4.0.1-pre.214 → 4.0.1-pre.219
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": "4.0.1-pre.
|
|
3
|
+
"version": "4.0.1-pre.219",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "React utilities for OpenMRS.",
|
|
6
6
|
"browser": "dist/openmrs-esm-react-utils.js",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
"react-i18next": "11.x"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@openmrs/esm-api": "^4.0.1-pre.
|
|
59
|
-
"@openmrs/esm-config": "^4.0.1-pre.
|
|
60
|
-
"@openmrs/esm-error-handling": "^4.0.1-pre.
|
|
61
|
-
"@openmrs/esm-extensions": "^4.0.1-pre.
|
|
62
|
-
"@openmrs/esm-globals": "^4.0.1-pre.
|
|
58
|
+
"@openmrs/esm-api": "^4.0.1-pre.219",
|
|
59
|
+
"@openmrs/esm-config": "^4.0.1-pre.219",
|
|
60
|
+
"@openmrs/esm-error-handling": "^4.0.1-pre.219",
|
|
61
|
+
"@openmrs/esm-extensions": "^4.0.1-pre.219",
|
|
62
|
+
"@openmrs/esm-globals": "^4.0.1-pre.219",
|
|
63
63
|
"dayjs": "^1.10.8",
|
|
64
64
|
"i18next": "^19.6.0",
|
|
65
65
|
"react": "^18.1.0",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"rxjs": "^6.5.3",
|
|
69
69
|
"unistore": "^3.5.2"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "e4225fe2ac3947ab26751d4b618bf3aafe9059e2"
|
|
72
72
|
}
|
package/src/ConfigurableLink.tsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/** @module @category Navigation */
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
MouseEvent,
|
|
4
|
+
AnchorHTMLAttributes,
|
|
5
|
+
PropsWithChildren,
|
|
6
|
+
} from "react";
|
|
3
7
|
import { navigate, interpolateUrl, TemplateParams } from "@openmrs/esm-config";
|
|
4
8
|
|
|
5
9
|
function handleClick(
|
|
@@ -40,7 +44,7 @@ export function ConfigurableLink({
|
|
|
40
44
|
templateParams,
|
|
41
45
|
children,
|
|
42
46
|
...otherProps
|
|
43
|
-
}: ConfigurableLinkProps) {
|
|
47
|
+
}: PropsWithChildren<ConfigurableLinkProps>) {
|
|
44
48
|
return (
|
|
45
49
|
<a
|
|
46
50
|
onClick={(event) => handleClick(event, to, templateParams)}
|
package/src/Extension.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderExtension } from "@openmrs/esm-extensions";
|
|
2
2
|
import React, {
|
|
3
|
+
PropsWithChildren,
|
|
3
4
|
useCallback,
|
|
4
5
|
useContext,
|
|
5
6
|
useEffect,
|
|
@@ -10,14 +11,18 @@ import { Parcel } from "single-spa";
|
|
|
10
11
|
import { ComponentContext } from ".";
|
|
11
12
|
import { ExtensionData } from "./ComponentContext";
|
|
12
13
|
|
|
13
|
-
export
|
|
14
|
+
export type ExtensionProps = {
|
|
14
15
|
state?: Record<string, any>;
|
|
15
16
|
/** @deprecated Pass a function as the child of `ExtensionSlot` instead. */
|
|
16
17
|
wrap?(
|
|
17
18
|
slot: React.ReactNode,
|
|
18
19
|
extension: ExtensionData
|
|
19
20
|
): React.ReactElement<any, any> | null;
|
|
20
|
-
}
|
|
21
|
+
} & Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
22
|
+
children?:
|
|
23
|
+
| React.ReactNode
|
|
24
|
+
| ((extension: React.ReactNode) => React.ReactNode);
|
|
25
|
+
};
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Represents the position in the DOM where each extension within
|
|
@@ -28,21 +33,37 @@ export interface ExtensionProps {
|
|
|
28
33
|
* Usage of this component *must* have an ancestor `<ExtensionSlot>`,
|
|
29
34
|
* and *must* only be used once within that `<ExtensionSlot>`.
|
|
30
35
|
*/
|
|
31
|
-
export const Extension: React.FC<ExtensionProps> = ({
|
|
36
|
+
export const Extension: React.FC<ExtensionProps> = ({
|
|
37
|
+
state,
|
|
38
|
+
children,
|
|
39
|
+
wrap,
|
|
40
|
+
...divProps
|
|
41
|
+
}) => {
|
|
32
42
|
const [domElement, setDomElement] = useState<HTMLDivElement>();
|
|
33
43
|
const { extension } = useContext(ComponentContext);
|
|
34
44
|
const parcel = useRef<Parcel | null>();
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (wrap) {
|
|
48
|
+
console.warn(
|
|
49
|
+
`'wrap' prop of Extension is being used ${
|
|
50
|
+
extension?.extensionId
|
|
51
|
+
? `by ${extension.extensionId} in ${extension.extensionSlotName}`
|
|
52
|
+
: ""
|
|
53
|
+
}. This will be removed in a future release.`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
// we only warn when component mounts
|
|
57
|
+
// eslint-disable-next-line eslintreact-hooks/exhaustive-deps
|
|
44
58
|
}, []);
|
|
45
59
|
|
|
60
|
+
const ref = useCallback(
|
|
61
|
+
(node) => {
|
|
62
|
+
setDomElement(node);
|
|
63
|
+
},
|
|
64
|
+
[setDomElement]
|
|
65
|
+
);
|
|
66
|
+
|
|
46
67
|
useEffect(() => {
|
|
47
68
|
if (domElement != null && extension && !parcel.current) {
|
|
48
69
|
parcel.current = renderExtension(
|
|
@@ -79,8 +100,13 @@ export const Extension: React.FC<ExtensionProps> = ({ state, wrap }) => {
|
|
|
79
100
|
ref={ref}
|
|
80
101
|
data-extension-id={extension?.extensionId}
|
|
81
102
|
style={{ position: "relative" }}
|
|
103
|
+
{...divProps}
|
|
82
104
|
/>
|
|
83
105
|
);
|
|
84
106
|
|
|
107
|
+
if (typeof children == "function" && !React.isValidElement(children)) {
|
|
108
|
+
return <>{children(slot)}</>;
|
|
109
|
+
}
|
|
110
|
+
|
|
85
111
|
return extension && wrap ? wrap(slot, extension) : slot;
|
|
86
112
|
};
|
package/src/extensions.test.tsx
CHANGED
|
@@ -254,6 +254,42 @@ describe("ExtensionSlot, Extension, and useExtensionSlotMeta", () => {
|
|
|
254
254
|
within(screen.getByTestId("Hindi")).getByRole("heading")
|
|
255
255
|
).toHaveTextContent("hi");
|
|
256
256
|
});
|
|
257
|
+
|
|
258
|
+
test("Extension renders with child function", async () => {
|
|
259
|
+
registerSimpleExtension("Hindi", "esm-languages-app", undefined, {
|
|
260
|
+
code: "hi",
|
|
261
|
+
});
|
|
262
|
+
attach("Box", "Hindi");
|
|
263
|
+
const App = openmrsComponentDecorator({
|
|
264
|
+
moduleName: "esm-languages-app",
|
|
265
|
+
featureName: "Languages",
|
|
266
|
+
disableTranslations: true,
|
|
267
|
+
})(() => {
|
|
268
|
+
return (
|
|
269
|
+
<div>
|
|
270
|
+
<ExtensionSlot name="Box">
|
|
271
|
+
{() => (
|
|
272
|
+
<Extension>
|
|
273
|
+
{(slot) => <div data-testid="custom-wrapper">{slot}</div>}
|
|
274
|
+
</Extension>
|
|
275
|
+
)}
|
|
276
|
+
</ExtensionSlot>
|
|
277
|
+
</div>
|
|
278
|
+
);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
render(<App />);
|
|
282
|
+
|
|
283
|
+
await waitFor(() =>
|
|
284
|
+
expect(screen.getByTestId("custom-wrapper")).toBeInTheDocument()
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
// essentially: is the first child of custom-wrapper the extension?
|
|
288
|
+
expect(screen.getByTestId("custom-wrapper").children[0]).toHaveAttribute(
|
|
289
|
+
"data-extension-id",
|
|
290
|
+
"Hindi"
|
|
291
|
+
);
|
|
292
|
+
});
|
|
257
293
|
});
|
|
258
294
|
|
|
259
295
|
function registerSimpleExtension(
|