UNPKG

4.07 kBJavaScriptView Raw
1/*
2 * Copyright 2020 Palantir Technologies, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import * as React from "react";
17import { isEmptyString } from "./jsUtils";
18/**
19 * Returns true if `node` is null/undefined, false, empty string, or an array
20 * composed of those. If `node` is an array, only one level of the array is
21 * checked, for performance reasons.
22 */
23export function isReactNodeEmpty(node, skipArray) {
24 if (skipArray === void 0) { skipArray = false; }
25 return (node == null ||
26 node === "" ||
27 node === false ||
28 (!skipArray &&
29 Array.isArray(node) &&
30 // only recurse one level through arrays, for performance
31 (node.length === 0 || node.every(function (n) { return isReactNodeEmpty(n, true); }))));
32}
33/**
34 * Returns true if children are a mappable children array
35 *
36 * @internal
37 */
38export function isReactChildrenElementOrElements(children) {
39 return !isReactNodeEmpty(children, true) && children !== true;
40}
41/**
42 * Converts a React node to an element. Non-empty strings, numbers, and Fragments will be wrapped in given tag name;
43 * empty strings and booleans will be discarded.
44 *
45 * @param child the React node to convert
46 * @param tagName the HTML tag name to use when a wrapper element is needed
47 * @param props additional props to spread onto the element, if any. If the child is a React element and this argument
48 * is defined, the child will be cloned and these props will be merged in.
49 */
50export function ensureElement(child, tagName, props) {
51 if (tagName === void 0) { tagName = "span"; }
52 if (props === void 0) { props = {}; }
53 if (child == null || typeof child === "boolean" || isEmptyString(child)) {
54 return undefined;
55 }
56 else if (typeof child === "string" ||
57 typeof child === "number" ||
58 isReactFragment(child) ||
59 isReactNodeArray(child)) {
60 // wrap the child element
61 return React.createElement(tagName, props, child);
62 }
63 else if (isReactElement(child)) {
64 if (Object.keys(props).length > 0) {
65 // clone the element and merge props
66 return React.cloneElement(child, props);
67 }
68 else {
69 // nothing to do, it's a valid ReactElement
70 return child;
71 }
72 }
73 else {
74 // child is inferred as {}
75 return undefined;
76 }
77}
78export function isReactElement(child) {
79 return (typeof child === "object" &&
80 typeof child.type !== "undefined" &&
81 typeof child.props !== "undefined");
82}
83function isReactFragment(child) {
84 // bit hacky, but generally works
85 return typeof child.type === "symbol";
86}
87function isReactNodeArray(child) {
88 return Array.isArray(child);
89}
90/**
91 * Returns true if the given JSX element matches the given component type.
92 *
93 * NOTE: This function only checks equality of `displayName` for performance and
94 * to tolerate multiple minor versions of a component being included in one
95 * application bundle.
96 *
97 * @param element JSX element in question
98 * @param ComponentType desired component type of element
99 */
100// eslint-disable-next-line @typescript-eslint/ban-types
101export function isElementOfType(element, ComponentType) {
102 return (element != null &&
103 element.type != null &&
104 element.type.displayName != null &&
105 element.type.displayName === ComponentType.displayName);
106}
107export function isReact18() {
108 return React.version.startsWith("18");
109}
110//# sourceMappingURL=reactUtils.js.map
\No newline at end of file