reshow-build
Version:
React super cloneElement and createElement
166 lines (158 loc) • 4.42 kB
JavaScript
// @ts-check
import { OBJ_SIZE, STRING, FUNCTION, T_NULL, T_TRUE, TYPE_ERROR, T_UNDEFINED, IS_ARRAY } from "reshow-constant";
import { removeEmpty } from "array.merge";
import * as React from "react";
import { jsx as _jsx } from "react/jsx-runtime";
var {
isValidElement,
cloneElement,
createElement,
Children,
Fragment
} = React;
/**
* @typedef {React.ComponentType|React.ReactNode|Function} Component
*/
/**
* @typedef {import('./mergeRef').RefType} RefType
*/
/**
* @typedef {object} BuildProps
*/
/**
* @typedef {object} ComponentOption
* @property {Component} [altWrap] This will only be used when the original component is not a valid element.
* @property {boolean} [doCallFunction]
*/
/**
* @param {function} component
* @param {BuildProps} props
* @param {Component|Component[]} child
* @param {ComponentOption} componentOption
* @returns {React.ReactElement?}
*/
var buildFunc = function buildFunc(component, props, child, componentOption) {
// anonymous function will call directly
var {
altWrap,
doCallFunction
} = componentOption || {};
if (FUNCTION === typeof component && (!component.name || "children" === component.name) || doCallFunction) {
try {
if (child != T_NULL) {
props.children = /** @type React.ReactElement*/child;
}
var el = component(props);
if (isValidElement(el)) {
var elKey = el.key || props.key;
return null != elKey ? _buildReact(el, {
key: elKey
}) : el;
} else {
return altWrap ? _buildReact(altWrap, props, el) : _buildReact(el, props);
}
} catch (e) {
if (e.name === TYPE_ERROR) {
return _buildReact(component, props, child);
} else {
throw e;
}
}
} else {
return _buildReact(component, props, child);
}
};
/**
* @param {Component} component
* @param {BuildProps} props
* @param {Component|Component[]} child
* @returns {React.ReactElement?}
*/
var _buildReact = function buildReact(component, props, child) {
if (props === void 0) {
props = {};
}
if (child === void 0) {
child = T_UNDEFINED;
}
if (T_NULL == component) {
return T_NULL;
}
var isValidComp = isValidElement(component);
if (isValidComp && !OBJ_SIZE(props) && null == child) {
return component;
}
var params = [component, props];
if (child != T_NULL) {
params.push(child);
}
if (!component || T_TRUE === component || STRING === typeof component && component !== /**@type string*/component.replace(/[^a-z1-6]/g, "")) {
if (null != props.children) {
throw new TypeError("String component should not have child");
} else {
return _buildReact(/*#__PURE__*/_jsx("span", {
children: (/**@type string*/component)
}), props);
}
} else {
return (isValidComp ? cloneElement : createElement).apply(T_NULL, params);
}
};
/**
* @param {Component|Component[]} [component]
* @param {ComponentOption} componentOption
*/
var build = function build(component, componentOption) {
if (componentOption === void 0) {
componentOption = {};
}
return (
/**
* @param {BuildProps} props
* @param {Component|Component[]} child
* @returns {React.ReactElement?}
*/
function (props, child) {
if (props === void 0) {
props = {};
}
if (child === void 0) {
child = T_UNDEFINED;
}
if (T_NULL == component) {
return T_NULL;
}
var {
altWrap
} = componentOption || {};
if (altWrap) {
if (FUNCTION !== typeof component && !isValidElement(component)) {
child = component;
component = altWrap;
}
}
/**
* @param {Component} comp
*/
var run = function run(comp) {
props = removeEmpty(props, T_TRUE);
return (isValidElement(comp) ? _buildReact : buildFunc)(/**@type any*/comp, props, child, componentOption);
};
if (IS_ARRAY(component)) {
var key = props.key;
props.key = T_UNDEFINED;
return /*#__PURE__*/_jsx(Fragment, {
children: Children.map(component.map(function (comp) {
return run(comp);
}), function (c) {
return c;
})
}, key);
} else {
return run(component);
}
}
);
};
export default build;
export { mergeRef } from "./mergeRef.mjs";