Skip to content

Commit 16a31c4

Browse files
added forwardRef to py-script
1 parent 420961e commit 16a31c4

File tree

2 files changed

+100
-76
lines changed

2 files changed

+100
-76
lines changed

source/library/components/py-script/py-script.tsx

Lines changed: 84 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import propTypes from "prop-types";
22
import {
3-
DetailedHTMLProps,
4-
HTMLAttributes,
5-
WeakValidationMap,
63
createElement,
4+
forwardRef,
75
useMemo,
6+
type DetailedHTMLProps,
7+
type ForwardedRef,
8+
type HTMLAttributes,
9+
type WeakValidationMap,
810
} from "react";
9-
import {
11+
import type {
1012
PyConfigPropertiesWithJsonType,
1113
PyConfigPropertiesWithTomlType,
1214
PyConfigPropertiesWithoutChildren,
1315
} from "~components/py-config/py-config.types";
14-
import ReactElementProps from "~root/source/library/types/react-element-properties/react-element-properties";
16+
import type ReactElementProps from "~root/source/library/types/react-element-properties/react-element-properties";
1517
import PyConfig from "../py-config/py-config";
1618
import PyEnv from "../py-env/py-env";
1719
import type {
@@ -36,47 +38,36 @@ import type {
3638
* @see {@link https://docs.pyscript.net/latest/reference/elements/py-script.html} Original py-script element documentation.
3739
* @see {@link https://pyscript-react.github.io/} Pyscript-react element documentation.
3840
*/
39-
const PyScript: PyScriptTag = <T extends object>({
40-
children,
41-
output,
42-
generateOutputTag,
43-
pyEnvContent,
44-
pyEnvProps,
45-
pyConfigContent,
46-
pyConfigProps,
47-
src,
48-
source,
49-
...rest
50-
}: PyScriptProperties<T>): JSX.Element => {
51-
const pyConfigElement: "" | JSX.Element | undefined = useMemo(():
52-
| ""
53-
| JSX.Element
54-
| undefined => {
55-
const isPyConfigSource: boolean = Boolean(
56-
(pyConfigProps as Partial<PyConfigPropertiesWithoutChildren>)?.source,
57-
);
58-
const isPyConfigContentJsonType: boolean = pyConfigProps?.type === "json";
59-
const pyConfigElementWithContent: "" | JSX.Element | undefined =
60-
isPyConfigContentJsonType ? (
61-
<PyConfig
62-
{...(pyConfigProps as Omit<
63-
PyConfigPropertiesWithJsonType,
64-
"children"
65-
> &
66-
Omit<
67-
ReactElementProps<
68-
DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>
69-
>,
70-
"children"
71-
>)}
72-
>
73-
{pyConfigContent as PyConfigPropertiesWithJsonType["children"]}
74-
</PyConfig>
75-
) : (
76-
pyConfigContent && (
41+
const PyScript: PyScriptTag = forwardRef(
42+
<OptionalProperties extends object>(
43+
{
44+
children,
45+
output,
46+
generateOutputTag,
47+
pyEnvContent,
48+
pyEnvProps,
49+
pyConfigContent,
50+
pyConfigProps,
51+
src,
52+
source,
53+
...rest
54+
}: PyScriptProperties<OptionalProperties>,
55+
reference: ForwardedRef<HTMLElement> | undefined,
56+
// eslint-disable-next-line max-params
57+
): JSX.Element => {
58+
const pyConfigElement: "" | JSX.Element | undefined = useMemo(():
59+
| ""
60+
| JSX.Element
61+
| undefined => {
62+
const isPyConfigSource: boolean = Boolean(
63+
(pyConfigProps as Partial<PyConfigPropertiesWithoutChildren>)?.source,
64+
);
65+
const isPyConfigContentJsonType: boolean = pyConfigProps?.type === "json";
66+
const pyConfigElementWithContent: "" | JSX.Element | undefined =
67+
isPyConfigContentJsonType ? (
7768
<PyConfig
7869
{...(pyConfigProps as Omit<
79-
PyConfigPropertiesWithTomlType,
70+
PyConfigPropertiesWithJsonType,
8071
"children"
8172
> &
8273
Omit<
@@ -86,34 +77,58 @@ const PyScript: PyScriptTag = <T extends object>({
8677
"children"
8778
>)}
8879
>
89-
{pyConfigContent as PyConfigPropertiesWithTomlType["children"]}
80+
{pyConfigContent as PyConfigPropertiesWithJsonType["children"]}
9081
</PyConfig>
91-
)
82+
) : (
83+
pyConfigContent && (
84+
<PyConfig
85+
{...(pyConfigProps as Omit<
86+
PyConfigPropertiesWithTomlType,
87+
"children"
88+
> &
89+
Omit<
90+
ReactElementProps<
91+
DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>
92+
>,
93+
"children"
94+
>)}
95+
>
96+
{pyConfigContent as PyConfigPropertiesWithTomlType["children"]}
97+
</PyConfig>
98+
)
99+
);
100+
return isPyConfigSource ? (
101+
<PyConfig {...(pyConfigProps as PyConfigPropertiesWithoutChildren)} />
102+
) : (
103+
pyConfigElementWithContent
92104
);
93-
return isPyConfigSource ? (
94-
<PyConfig {...(pyConfigProps as PyConfigPropertiesWithoutChildren)} />
95-
) : (
96-
pyConfigElementWithContent
105+
}, [pyConfigProps, pyConfigContent]);
106+
return (
107+
<>
108+
{pyConfigElement}
109+
{pyEnvContent && <PyEnv {...pyEnvProps}>{pyEnvContent}</PyEnv>}
110+
{output &&
111+
generateOutputTag &&
112+
createElement(
113+
typeof generateOutputTag === "string" ? generateOutputTag : "div",
114+
{
115+
id: output,
116+
},
117+
)}
118+
<py-script
119+
ref={reference}
120+
{...rest}
121+
src={source ?? src}
122+
output={output}
123+
>
124+
{children ?? ""}
125+
</py-script>
126+
</>
97127
);
98-
}, [pyConfigProps, pyConfigContent]);
99-
return (
100-
<>
101-
{pyConfigElement}
102-
{pyEnvContent && <PyEnv {...pyEnvProps}>{pyEnvContent}</PyEnv>}
103-
{output &&
104-
generateOutputTag &&
105-
createElement(
106-
typeof generateOutputTag === "string" ? generateOutputTag : "div",
107-
{
108-
id: output,
109-
},
110-
)}
111-
<py-script {...rest} src={source || src} output={output}>
112-
{children || ""}
113-
</py-script>
114-
</>
115-
);
116-
};
128+
},
129+
) as PyScriptTag;
130+
131+
PyScript.displayName = "PyScript";
117132

118133
PyScript.propTypes = {
119134
children: propTypes.string,

source/library/components/py-script/py-script.types.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import type {
22
DetailedHTMLProps,
3+
ForwardedRef,
34
HTMLAttributes,
45
WeakValidationMap,
56
} from "react";
67
import type { PyEnvPropertiesBase } from "~components/py-env/py-env.types";
7-
import { PyConfigPropertiesWithoutChildren } from "~root/source/library/components/py-config/py-config.types";
8+
import type { PyConfigPropertiesWithoutChildren } from "~root/source/library/components/py-config/py-config.types";
89
import type ReactElementProps from "~types/react-element-properties/react-element-properties";
10+
911
import type {
1012
PyConfigPropertiesWithJsonType,
1113
PyConfigPropertiesWithTomlType,
@@ -145,13 +147,20 @@ export type PyScriptPropertiesWithoutGeneric = PyScriptPropertiesBase &
145147
| PyScriptPropertiesWithSourceFullName
146148
);
147149

148-
export type PyScriptProperties<T> = T extends infer T
149-
? T & PyScriptPropertiesWithoutGeneric
150-
: PyScriptPropertiesWithoutGeneric;
150+
export type PyScriptProperties<OptionalProperties> =
151+
OptionalProperties extends infer OptionalProperties
152+
? OptionalProperties & PyScriptPropertiesWithoutGeneric
153+
: PyScriptPropertiesWithoutGeneric;
151154

152-
export type PyScriptProps<T> = PyScriptProperties<T>;
155+
export type PyScriptProps<OptionalProperties> =
156+
PyScriptProperties<OptionalProperties>;
153157

154158
export type PyScriptTag = {
155-
<T extends object>(properties: PyScriptProperties<T>): JSX.Element;
156-
propTypes: WeakValidationMap<PyScriptPropertiesWithoutGeneric>;
159+
<OptionalProperties extends object>(
160+
properties: PyScriptProperties<OptionalProperties>,
161+
reference?: ForwardedRef<HTMLElement>,
162+
): JSX.Element;
163+
displayName?: string;
164+
defaultProps?: Partial<PyScriptPropertiesWithoutGeneric>;
165+
propTypes?: WeakValidationMap<PyScriptPropertiesWithoutGeneric>;
157166
};

0 commit comments

Comments
 (0)