UNPKG

react-to-imperative

Version:
80 lines (79 loc) 2.28 kB
import React from 'react'; export const inspectElements = (inputReactElements, opts) => { const { propsExtractor, maxDepth = 3, elementCreator = callSafe } = typeof opts === 'function' ? { propsExtractor: opts } : opts; const extractedProps = extractFromElement(inputReactElements, { maxDepth, elementCreator }, propsExtractor); return extractedProps; }; export default inspectElements; const extractFromElement = (elementRoot, opts, propsExtractor) => { // don't do this at home - it's not how React is meant to be used const stack = [{ element: elementRoot, depth: 0 }]; const results = []; while (stack.length > 0) { const { element, depth } = stack.shift(); React.Children.forEach(element, child => { if (! /*#__PURE__*/React.isValidElement(child)) { return; } const result = propsExtractor({ type: child.type, props: child.props, depth }); const nextDepth = depth + 1; const isGettingTooDeep = nextDepth >= opts.maxDepth; if (typeof result === 'object') { results.push(result); } else if (result === true && !isGettingTooDeep) { // go one level deeper const { props, type } = child; if (typeof type === 'function') { const nestedElement = opts.elementCreator(type, props); stack.push({ element: nestedElement, depth: nextDepth }); } else { // Fragment or other element const children = child.props.children; if (children) { stack.push({ element: children, depth: nextDepth }); } } } }); } return results; }; export const callSafe = (type, props) => { try { // if the component is a pure function component, call it directly with props and return the result // @ts-expect-error Not all constituents of type 'JSXElementConstructor<I>' are callable. return type(props); } catch { // catches errors like "Invalid hook call" if you use hooks or "cannot call a class as a function" if you use class components return null; } }; //# sourceMappingURL=index.js.map