Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/modules / ___dist / SSR / react-tree-walker / reactTreeWalker.js
Size: Mime:
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.reactTreeWalker = reactTreeWalker;

var _promiseFun = require("../../_forks/promise-fun");

var _deps = require("./deps");

/* eslint-disable no-console */
// Inspired by the awesome work by the Apollo team: 😘
// https://github.com/apollographql/react-apollo/blob/master/src/getDataFromTree.ts
//
// This version has been adapted to be Promise based and support native Preact.
// Recurse a React Element tree, running the provided visitor against each element.
// If a visitor call returns `false` then we will not recurse into the respective
// elements children.
function reactTreeWalker(tree, visitor, context, options = _deps.defaultOptions) {
  return new Promise((resolve, reject) => {
    const safeVisitor = (...args) => {
      try {
        return visitor(...args);
      } catch (err) {
        reject(err);
      }

      return undefined;
    };

    const recursive = (currentElement, currentContext) => {
      if (Array.isArray(currentElement)) {
        return Promise.all(currentElement.map(item => recursive(item, currentContext)));
      }

      if (!currentElement) {
        return Promise.resolve();
      }

      if (typeof currentElement === 'string' || typeof currentElement === 'number') {
        // Just visit these, they are leaves so we don't keep traversing.
        safeVisitor(currentElement, null, currentContext);
        return Promise.resolve();
      }

      if ((0, _deps.isReactElement)(currentElement)) {
        return new Promise(innerResolve => {
          const visitCurrentElement = (render, compInstance, elContext, childContext) => Promise.resolve(safeVisitor(currentElement, compInstance, elContext, childContext)).then(result => {
            if (result !== false) {
              // A false wasn't returned so we will attempt to visit the children
              // for the current element.
              const tempChildren = render();
              const children = (0, _deps.ensureChild)(tempChildren);

              if (children) {
                if (Array.isArray(children)) {
                  // If its a react Children collection we need to breadth-first
                  // traverse each of them, and pMapSeries allows us to do a
                  // depth-first traversal that respects Promises. Thanks @sindresorhus!
                  return (0, _promiseFun.pMapSeries)(children, child => child ? recursive(child, childContext) : Promise.resolve()).then(innerResolve, reject).catch(reject);
                } // Otherwise we pass the individual child to the next recursion.


                return recursive(children, childContext).then(innerResolve, reject).catch(reject);
              }
            }

            return undefined;
          }).catch(reject);

          if (typeof (0, _deps.getType)(currentElement) === 'function') {
            const Component = (0, _deps.getType)(currentElement);
            const props = Object.assign({}, Component.defaultProps, (0, _deps.getProps)(currentElement), // For Preact support so that the props get passed into render
            // function.
            {
              children: (0, _deps.getChildren)(currentElement)
            });

            if ((0, _deps.isClassComponent)(Component)) {
              // Class component
              const instance = new Component(props, currentContext); // In case the user doesn't pass these to super in the constructor

              instance.props = instance.props || props;
              instance.context = instance.context || currentContext; // set the instance state to null (not undefined) if not set, to match React behaviour

              instance.state = instance.state || null; // Make the setState synchronous.

              instance.setState = newState => {
                if (typeof newState === 'function') {
                  // eslint-disable-next-line no-param-reassign
                  newState = newState(instance.state, instance.props, instance.context);
                }

                instance.state = Object.assign({}, instance.state, newState);
              };

              if (instance.componentWillMount) {
                instance.componentWillMount();
              }

              const childContext = (0, _deps.providesChildContext)(instance) ? Object.assign({}, currentContext, instance.getChildContext()) : currentContext;
              visitCurrentElement( // Note: preact API also allows props and state to be referenced
              // as arguments to the render func, so we pass them through
              // here
              () => instance.render(instance.props, instance.state), instance, currentContext, childContext).then(() => {
                if (options.componentWillUnmount && instance.componentWillUnmount) {
                  instance.componentWillUnmount();
                }
              }).then(innerResolve);
            } else {
              // Stateless Functional Component
              visitCurrentElement(() => Component(props, currentContext), null, currentContext, currentContext).then(innerResolve);
            }
          } else {
            // A basic element, such as a dom node, string, number etc.
            visitCurrentElement(() => (0, _deps.getChildren)(currentElement), null, currentContext, currentContext).then(innerResolve);
          }
        });
      } // Portals


      if (currentElement.containerInfo && currentElement.children && currentElement.children.props && Array.isArray(currentElement.children.props.children)) {
        return Promise.all(currentElement.children.props.children.map(child => recursive(child, currentContext)));
      }

      return Promise.resolve();
    };

    recursive(tree, context).then(resolve, reject);
  });
}