Skip to content

Commit

Permalink
fix: React 17 JSX transform change for functional components
Browse files Browse the repository at this point in the history
  • Loading branch information
yawetse committed Mar 23, 2021
1 parent b480954 commit 37eaf46
Show file tree
Hide file tree
Showing 33 changed files with 2,142 additions and 1,986 deletions.
3 changes: 2 additions & 1 deletion .npmignore
@@ -1,2 +1,3 @@
node_modules
lib/vendor
lib/vendor
examples
23 changes: 21 additions & 2 deletions build/components.d.ts
Expand Up @@ -17,6 +17,25 @@ declare global {
}
}
}
export declare const ReactHookForm: {
ErrorMessage: <TFieldErrors extends import("react-hook-form").DeepMap<Record<string, any>, import("react-hook-form").FieldError>, TAs extends "symbol" | "object" | "body" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "br" | "button" | "canvas" | "caption" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "details" | "dfn" | "dialog" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "footer" | "form" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "main" | "map" | "mark" | "menu" | "menuitem" | "meta" | "meter" | "nav" | "noindex" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "slot" | "script" | "section" | "select" | "small" | "source" | "span" | "strong" | "style" | "sub" | "summary" | "sup" | "table" | "template" | "tbody" | "td" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "u" | "ul" | "var" | "video" | "wbr" | "webview" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | React.FunctionComponent<any> | React.ComponentClass<any, any> | React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)> | undefined = undefined>({ as, errors, name, message, render, ...rest }: import("react-hook-form").Assign<{
as?: TAs | undefined;
errors?: TFieldErrors | undefined;
name: import("react-hook-form").FieldName<import("@hookform/error-message").FieldValuesFromFieldErrors<TFieldErrors>>;
message?: string | undefined;
render?: ((data: {
message: string;
messages?: import("react-hook-form").MultipleFieldErrors | undefined;
}) => React.ReactNode) | undefined;
}, TAs extends undefined ? {} : TAs extends React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)> ? Record<string, any> : TAs extends React.ComponentType<infer P> ? P : TAs extends "symbol" | "object" | "body" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "br" | "button" | "canvas" | "caption" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "details" | "dfn" | "dialog" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "footer" | "form" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "main" | "map" | "mark" | "menu" | "menuitem" | "meta" | "meter" | "nav" | "noindex" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "slot" | "script" | "section" | "select" | "small" | "source" | "span" | "strong" | "style" | "sub" | "summary" | "sup" | "table" | "template" | "tbody" | "td" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "u" | "ul" | "var" | "video" | "wbr" | "webview" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" ? JSX.IntrinsicElements[TAs] : never>) => React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)> | null;
Controller: <TAs_1 extends "input" | "select" | "textarea" | React.FunctionComponent<any> | React.ComponentClass<any, any> | React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)>, TFieldValues extends Record<string, any> = Record<string, any>>(props: import("react-hook-form").Assign<({
as: TAs_1;
render?: undefined;
} & import("react-hook-form").UseControllerOptions<Record<string, any>>) | ({
as?: undefined;
render: (field: import("react-hook-form").ControllerRenderProps<TFieldValues>, state: import("react-hook-form").InputState) => React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)>;
} & import("react-hook-form").UseControllerOptions<Record<string, any>>), TAs_1 extends undefined ? {} : TAs_1 extends React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)> ? Record<string, any> : TAs_1 extends React.ComponentType<infer P_1> ? P_1 : TAs_1 extends "symbol" | "object" | "body" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "br" | "button" | "canvas" | "caption" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "details" | "dfn" | "dialog" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "footer" | "form" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "main" | "map" | "mark" | "menu" | "menuitem" | "meta" | "meter" | "nav" | "noindex" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "slot" | "script" | "section" | "select" | "small" | "source" | "span" | "strong" | "style" | "sub" | "summary" | "sup" | "table" | "template" | "tbody" | "td" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "u" | "ul" | "var" | "video" | "wbr" | "webview" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" ? JSX.IntrinsicElements[TAs_1] : never>) => React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<any, any, any>)> | null;
};
/**
*/
Expand Down Expand Up @@ -107,13 +126,13 @@ export declare function getReactClassComponent(this: defs.Context, reactComponen
* @param this
* @param props
*/
export declare function FormComponent(this: defs.Context, props?: defs.formComponentProps): string | defs.JSONReactElement | ReactElementLike | null | undefined;
export declare function FormComponent(this: defs.Context, props?: defs.formComponentProps): (componentProps: any) => string | defs.JSONReactElement | ReactElementLike | null | undefined;
/**
* A helper component that allows you to create components that load data and render asynchronously.
* @param this
* @param props
*/
export declare function DynamicComponent(this: defs.Context, props?: defs.dynamicComponentProps): string | defs.JSONReactElement | ReactElementLike | null | undefined;
export declare function DynamicComponent(this: defs.Context, props?: defs.dynamicComponentProps): (componentProps: any) => string | defs.JSONReactElement | ReactElementLike | null | undefined;
/**
* Returns new React Function Component
Expand Down
221 changes: 125 additions & 96 deletions build/components.js
Expand Up @@ -11,6 +11,7 @@ import { getAdvancedBinding, fetchJSON } from "./utils";
import createReactClass from "create-react-class";
import { getReactElementFromJSONX } from ".";
const cache = new memoryCache.Cache();
export const ReactHookForm = { ErrorMessage, Controller };
// if (typeof window === 'undefined') {
// var window = window || global.window || {};
// }
Expand Down Expand Up @@ -273,120 +274,148 @@ export function getReactClassComponent(reactComponent = {}, options = {}) {
* @param props
*/
export function FormComponent(props = {}) {
const { hookFormOptions = {}, formComponent = { component: "div", children: "empty form" }, onSubmit, formWrapperComponent, formKey, formWrapperProps, } = props;
// const { register, unregister, errors, watch, handleSubmit, reset, setError, clearError, setValue, getValues, triggerValidation, control, formState, } = useForm(hookFormOptions);
const reactHookForm = useForm(hookFormOptions);
const context = {
...this || {},
...{ reactHookForm, },
};
if (!context.componentLibraries || !context.componentLibraries.ReactHookForm) {
context.componentLibraries = {
...context.componentLibraries,
...{
ReactHookForm: {
Controller, ErrorMessage,
function FormComponentFunction(componentProps) {
const { hookFormOptions = {},
// formComponent = { component: "div", children: "empty form" },
onSubmit, formWrapperComponent, formKey, formWrapperProps, } = props;
const formComponent = {
component: "div",
children: "empty form",
...props.formComponent,
};
formComponent.props = { ...formComponent.props, ...componentProps };
// const { register, unregister, errors, watch, handleSubmit, reset, setError, clearError, setValue, getValues, triggerValidation, control, formState, } = useForm(hookFormOptions);
const reactHookForm = useForm(hookFormOptions);
const context = {
...this || {},
...{ reactHookForm, },
};
if (!context.componentLibraries || !context.componentLibraries.ReactHookForm) {
context.componentLibraries = {
...context.componentLibraries,
...{
ReactHookForm: {
Controller, ErrorMessage,
}
}
};
}
const formWrapperJXM = formWrapperComponent || {
component: 'form',
props: {
onSubmit: onSubmit ? reactHookForm.handleSubmit(onSubmit) : undefined,
key: formKey ? `formWrapperJXM-${formKey}` : undefined,
...formWrapperProps,
}
};
formWrapperJXM.children = Array.isArray(formComponent) ? formComponent : [formComponent];
const renderJSONX = useMemo(() => getReactElementFromJSONX.bind(context), [
context
]);
return renderJSONX(formWrapperJXM);
}
const formWrapperJXM = formWrapperComponent || {
component: 'form',
props: {
onSubmit: onSubmit ? reactHookForm.handleSubmit(onSubmit) : undefined,
key: formKey ? `formWrapperJXM-${formKey}` : undefined,
...formWrapperProps,
}
};
formWrapperJXM.children = Array.isArray(formComponent) ? formComponent : [formComponent];
const renderJSONX = useMemo(() => getReactElementFromJSONX.bind(context), [
context
]);
return renderJSONX(formWrapperJXM);
if (props.name) {
Object.defineProperty(FormComponentFunction, "name", {
value: props.name
});
}
return FormComponentFunction.bind(this);
}
/**
* A helper component that allows you to create components that load data and render asynchronously.
* @param this
* @param props
*/
export function DynamicComponent(props = {}) {
//@ts-ignore
const { useCache = true, cacheTimeout = 60 * 60 * 5, loadingJSONX = { component: "div", children: "...Loading" },
//@ts-ignore
loadingErrorJSONX = {
component: "div",
children: [
{ component: "span", children: "Error: " },
{
component: "span",
resourceprops: { _children: ["error", "message"] }
}
]
}, cacheTimeoutFunction = () => { }, jsonx, transformFunction = (data) => data, fetchURL, fetchOptions, fetchFunction } = props;
const context = this || {};
const [state, setState] = useState({
hasLoaded: false,
hasError: false,
resources: {},
error: undefined
});
const transformer = useMemo(() => getFunctionFromEval(transformFunction), [
transformFunction
]);
const timeoutFunction = useMemo(() => getFunctionFromEval(cacheTimeoutFunction), [cacheTimeoutFunction]);
const renderJSONX = useMemo(() => getReactElementFromJSONX.bind(context), [
context
]);
const loadingComponent = useMemo(() => renderJSONX(loadingJSONX), [
loadingJSONX
]);
const loadingError = useMemo(() => renderJSONX(loadingErrorJSONX, { error: state.error }), [loadingErrorJSONX, state.error]);
useEffect(() => {
async function getData() {
try {
//@ts-ignore
let transformedData;
if (useCache && cache.get(fetchURL)) {
transformedData = cache.get(fetchURL);
function DynamicComponentFunction(componentProps) {
//@ts-ignore
const { useCache = true, cacheTimeout = 60 * 60 * 5, loadingJSONX = { component: "div", children: "...Loading" },
//@ts-ignore
loadingErrorJSONX = {
component: "div",
children: [
{ component: "span", children: "Error: " },
{
component: "span",
resourceprops: { _children: ["error", "message"] }
}
else {
let fetchedData;
if (fetchFunction) {
fetchedData = await fetchFunction(fetchURL, fetchOptions);
]
}, cacheTimeoutFunction = () => { }, transformFunction = (data) => data, fetchURL, fetchOptions, fetchFunction } = props;
const jsonx = {
...props.jsonx,
};
jsonx.props = { ...jsonx.props, ...componentProps };
const context = this || {};
const [state, setState] = useState({
hasLoaded: false,
hasError: false,
resources: {},
error: undefined
});
const transformer = useMemo(() => getFunctionFromEval(transformFunction), [
transformFunction
]);
const timeoutFunction = useMemo(() => getFunctionFromEval(cacheTimeoutFunction), [cacheTimeoutFunction]);
const renderJSONX = useMemo(() => getReactElementFromJSONX.bind(context), [
context
]);
const loadingComponent = useMemo(() => renderJSONX(loadingJSONX), [
loadingJSONX
]);
const loadingError = useMemo(() => renderJSONX(loadingErrorJSONX, { error: state.error }), [loadingErrorJSONX, state.error]);
useEffect(() => {
async function getData() {
try {
//@ts-ignore
let transformedData;
if (useCache && cache.get(fetchURL)) {
transformedData = cache.get(fetchURL);
}
else {
let fetchedData;
if (fetchFunction) {
fetchedData = await fetchFunction(fetchURL, fetchOptions);
}
else
fetchedData = await fetchJSON(fetchURL, fetchOptions);
transformedData = await transformer(fetchedData);
if (useCache)
cache.put(fetchURL, transformedData, cacheTimeout, timeoutFunction);
}
else
fetchedData = await fetchJSON(fetchURL, fetchOptions);
transformedData = await transformer(fetchedData);
if (useCache)
cache.put(fetchURL, transformedData, cacheTimeout, timeoutFunction);
//@ts-ignore
setState(prevState => Object.assign({}, prevState, {
hasLoaded: true,
hasError: false,
resources: { DynamicComponentData: transformedData }
}));
}
catch (e) {
if (context.debug)
console.warn(e);
//@ts-ignore
setState({ hasError: true, error: e });
}
//@ts-ignore
setState(prevState => Object.assign({}, prevState, {
hasLoaded: true,
hasError: false,
resources: { DynamicComponentData: transformedData }
}));
}
catch (e) {
if (context.debug)
console.warn(e);
//@ts-ignore
setState({ hasError: true, error: e });
}
if (fetchURL)
getData();
}, [fetchURL, fetchOptions]);
if (!fetchURL)
return null;
else if (state.hasError) {
return loadingError;
}
if (fetchURL)
getData();
}, [fetchURL, fetchOptions]);
if (!fetchURL)
return null;
else if (state.hasError) {
return loadingError;
else if (state.hasLoaded === false) {
return loadingComponent;
}
else
return renderJSONX(jsonx, state.resources);
}
else if (state.hasLoaded === false) {
return loadingComponent;
if (props.name) {
Object.defineProperty(DynamicComponentFunction, "name", {
value: props.name
});
}
else
return renderJSONX(jsonx, state.resources);
return DynamicComponentFunction.bind(this);
}
/**
* Returns new React Function Component
Expand Down

0 comments on commit 37eaf46

Please sign in to comment.