text: (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-dataflow'), require('vega-util'), require('d3-collection'), require('d3-hierarchy')) :
    typeof define === 'function' && define.amd ? define(['exports', 'vega-dataflow', 'vega-util', 'd3-collection', 'd3-hierarchy'], factory) :
    (factory((global.vega = global.vega || {}, global.vega.transforms = {}),global.vega,global.vega,global.d3,global.d3));
  }(this, (function (exports,vegaDataflow,vegaUtil,d3Collection,d3Hierarchy) { 'use strict';
  
    // Build lookup table mapping tuple keys to tree node instances
    function lookup(tree, key, filter) {
      var map = {};
      tree.each(function(node) {
        var t = node.data;
        if (filter(t)) map[key(t)] = node;
      });
      tree.lookup = map;
      return tree;
    }
  
    /**
      * Nest tuples into a tree structure, grouped by key values.
      * @constructor
      * @param {object} params - The parameters for this operator.
      * @param {Array<function(object): *>} params.keys - The key fields to nest by, in order.
      * @param {boolean} [params.generate=false] - A boolean flag indicating if
      *   non-leaf nodes generated by this transform should be included in the
      *   output. The default (false) includes only the input data (leaf nodes)
      *   in the data stream.
      */
    function Nest(params) {
      vegaDataflow.Transform.call(this, null, params);
    }
  
    Nest.Definition = {
      "type": "Nest",
      "metadata": {"treesource": true, "changes": true},
      "params": [
        { "name": "keys", "type": "field", "array": true },
        { "name": "generate", "type": "boolean" }
      ]
    };
  
    var prototype = vegaUtil.inherits(Nest, vegaDataflow.Transform);
  
    function children(n) {
      return n.values;
    }
  
    prototype.transform = function(_, pulse) {
      if (!pulse.source) {
        vegaUtil.error('Nest transform requires an upstream data source.');
      }
  
      var gen = _.generate,
          mod = _.modified(),
          out = pulse.clone(),
          tree = this.value;
  
      if (!tree || mod || pulse.changed()) {
        // collect nodes to remove
        if (tree) {
          tree.each(function(node) {
            if (node.children && vegaDataflow.isTuple(node.data)) {
              out.rem.push(node.data);
            }
          });
        }
  
        // generate new tree structure
        this.value = tree = d3Hierarchy.hierarchy({
          values: vegaUtil.array(_.keys)
                    .reduce(function(n, k) { n.key(k); return n; }, d3Collection.nest())
                    .entries(out.source)
        }, children);
  
        // collect nodes to add
        if (gen) {
          tree.each(function(node) {
            if (node.children) {
              node = vegaDataflow.ingest(node.data);
              out.add.push(node);
              out.source.push(node);
            }
          });
        }
  
        // build lookup table
        lookup(tree, vegaDataflow.tupleid, vegaDataflow.tupleid);
      }
  
      out.source.root = tree;
      return out;
    };
  
    /**
     * Abstract class for tree layout.
     * @constructor
     * @param {object} params - The parameters for this operator.
     */
    function HierarchyLayout(params) {
      vegaDataflow.Transform.call(this, null, params);
    }
  
    var prototype$1 = vegaUtil.inherits(HierarchyLayout, vegaDataflow.Transform);
  
    prototype$1.transform = function(_, pulse) {
      if (!pulse.source || !pulse.source.root) {
        vegaUtil.error(this.constructor.name
          + ' transform requires a backing tree data source.');
      }
  
      var layout = this.layout(_.method),
          fields = this.fields,
          root = pulse.source.root,
          as = _.as || fields;
  
      if (_.field) root.sum(_.field);
      if (_.sort) root.sort(_.sort);
  
      setParams(layout, this.params, _);
      if (layout.separation) {
        layout.separation(_.separation !== false ? defaultSeparation : vegaUtil.one);
      }
  
      try {
        this.value = layout(root);
      } catch (err) {
        vegaUtil.error(err);
      }
      root.each(function(node) { setFields(node, fields, as); });
  
      return pulse.reflow(_.modified()).modifies(as).modifies('leaf');
    };
  
    function setParams(layout, params, _) {
      for (var p, i=0, n=params.length; i<n; ++i) {
        p = params[i];
        if (p in _) layout[p](_[p]);
      }
    }
  
    function setFields(node, fields, as) {
      var t = node.data;
      for (var i=0, n=fields.length-1; i<n; ++i) {
        t[as[i]] = node[fields[i]];
      }
      t[as[n]] = node.children ? node.children.length : 0;
    }
  
    function defaultSeparation(a, b) {
      return a.parent === b.parent ? 1 : 2;
    }
  
    var Output = ['x', 'y', 'r', 'depth', 'children'];
  
    /**
     * Packed circle tree layout.
     * @constructor
     * @param {object} params - The parameters for this operator.
     * @param {function(object): *} params.field - The value field to size nodes.
     */
    function Pack(params) {
      HierarchyLayout.call(this, params);
    }
  
    Pack.Definition = {
      "type": "Pack",
      "metadata": {"tree": true, "modifies": true},
      "params": [
        { "name": "field", "type": "field" },
        { "name": "sort", "type": "compare" },
        { "name": "padding", "type": "number", "default": 0 },
        { "name": "radius", "type": "field", "default": null },
        { "name": "size", "type": "number", "array": true, "length": 2 },
        { "name": "as", "type": "string", "array": true, "length": Output.length, "default": Output }
      ]
    };
  
    var prototype$2 = vegaUtil.inherits(Pack, HierarchyLayout);
  
    prototype$2.layout = d3Hierarchy.pack;
  
    prototype$2.params = ['size', 'padding'];
  
    prototype$2.fields = Output;
  
    var Output$1 = ['x0', 'y0', 'x1', 'y1', 'depth', 'children'];
  
    /**
     * Partition tree layout.
     * @constructor
     * @param {object} params - The parameters for this operator.
     * @param {function(object): *} params.field - The value field to size nodes.
     */
    function Partition(params) {
      HierarchyLayout.call(this, params);
    }
  
    Partition.Definition = {
      "type": "Partition",
      "metadata": {"tree": true, "modifies": true},
      "params": [
        { "name": "field", "type": "field" },
        { "name": "sort", "type": "compare" },
        { "name": "padding", "type": "number", "default": 0 },
        { "name": "round", "type": "boolean", "default": false },
        { "name": "size", "type": "number", "array": true, "length": 2 },
        { "name": "as", "type": "string", "array": true, "length": Output$1.length, "default": Output$1 }
      ]
    };
  
    var prototype$3 = vegaUtil.inherits(Partition, HierarchyLayout);
  
    prototype$3.layout = d3Hierarchy.partition;
  
    prototype$3.params = ['size', 'round', 'padding'];
  
    prototype$3.fields = Output$1;
  
    /**
      * Stratify a collection of tuples into a tree structure based on
      * id and parent id fields.
      * @constructor
      * @param {object} params - The parameters for this operator.
      * @param {function(object): *} params.key - Unique key field for each tuple.
      * @param {function(object): *} params.parentKey - Field with key for parent tuple.
      */
    function Stratify(params) {
      vegaDataflow.Transform.call(this, null, params);
    }
  
    Stratify.Definition = {
      "type": "Stratify",
      "metadata": {"treesource": true},
      "params": [
        { "name": "key", "type": "field", "required": true },
        { "name": "parentKey", "type": "field", "required": true  }
      ]
    };
  
    var prototype$4 = vegaUtil.inherits(Stratify, vegaDataflow.Transform);
  
    prototype$4.transform = function(_, pulse) {
      if (!pulse.source) {
        vegaUtil.error('Stratify transform requires an upstream data source.');
      }
  
      var tree = this.value,
          mod = _.modified(),
          out = pulse.fork(pulse.ALL).materialize(pulse.SOURCE),
          run = !this.value
             || mod
             || pulse.changed(pulse.ADD_REM)
             || pulse.modified(_.key.fields)
             || pulse.modified(_.parentKey.fields);
  
      // prevent upstream source pollution
      out.source = out.source.slice();
  
      if (run) {
        if (out.source.length) {
          tree = lookup(
            d3Hierarchy.stratify().id(_.key).parentId(_.parentKey)(out.source)
            , _.key, vegaUtil.truthy);
        } else {
          tree = lookup(d3Hierarchy.stratify()([{}]), _.key, _.key);
        }
      }
  
      out.source.root = this.value = tree;
      return out;
    };
  
    var Layouts = {
      tidy: d3Hierarchy.tree,
      cluster: d3Hierarchy.cluster
    };
  
    var Output$2 = ['x', 'y', 'depth', 'children'];
  
    /**
     * Tree layout. Depending on the method parameter, performs either
     * Reingold-Tilford 'tidy' layout or dendrogram 'cluster' layout.
     * @constructor
     * @param {object} params - The parameters for this operator.
     */
    function Tree(params) {
      HierarchyLayout.call(this, params);
    }
  
    Tree.Definition = {
      "type": "Tree",
      "metadata": {"tree": true, "modifies": true},
      "params": [
        { "name": "field", "type": "field" },
        { "name": "sort", "type": "compare" },
        { "name": "method", "type": "enum", "default": "tidy", "values": ["tidy", "cluster"] },
        { "name": "size", "type": "number", "array": true, "length": 2 },
        { "name": "nodeSize", "type": "number", "array": true, "length": 2 },
        { "name": "separation", "type": "boolean", "default": true },
        { "name": "as", "type": "string", "array": true, "length": Output$2.length, "default": Output$2 }
      ]
    };
  
    var prototype$5 = vegaUtil.inherits(Tree, HierarchyLayout);
  
    /**
     * Tree layout generator. Supports both 'tidy' and 'cluster' layouts.
     */
    prototype$5.layout = function(method) {
      var m = method || 'tidy';
      if (Layouts.hasOwnProperty(m)) return Layouts[m]();
      else vegaUtil.error('Unrecognized Tree layout method: ' + m);
    };
  
    prototype$5.params = ['size', 'nodeSize'];
  
    prototype$5.fields = Output$2;
  
    /**
      * Generate tuples representing links between tree nodes.
      * The resulting tuples will contain 'source' and 'target' fields,
      * which point to parent and child node tuples, respectively.
      * @constructor
      * @param {object} params - The parameters for this operator.
      */
    function TreeLinks(params) {
      vegaDataflow.Transform.call(this, [], params);
    }
  
    TreeLinks.Definition = {
      "type": "TreeLinks",
      "metadata": {"tree": true, "generates": true, "changes": true},
      "params": []
    };
  
    var prototype$6 = vegaUtil.inherits(TreeLinks, vegaDataflow.Transform);
  
    prototype$6.transform = function(_, pulse) {
      var links = this.value,
          tree = pulse.source && pulse.source.root,
          out = pulse.fork(pulse.NO_SOURCE),
          lut = {};
  
      if (!tree) vegaUtil.error('TreeLinks transform requires a tree data source.');
  
      if (pulse.changed(pulse.ADD_REM)) {
        // remove previous links
        out.rem = links;
  
        // build lookup table of valid tuples
        pulse.visit(pulse.SOURCE, function(t) { lut[vegaDataflow.tupleid(t)] = 1; });
  
        // generate links for all edges incident on valid tuples
        tree.each(function(node) {
          var t = node.data,
              p = node.parent && node.parent.data;
          if (p && lut[vegaDataflow.tupleid(t)] && lut[vegaDataflow.tupleid(p)]) {
            out.add.push(vegaDataflow.ingest({source: p, target: t}));
          }
        });
        this.value = out.add;
      }
  
      else if (pulse.changed(pulse.MOD)) {
        // build lookup table of modified tuples
        pulse.visit(pulse.MOD, function(t) { lut[vegaDataflow.tupleid(t)] = 1; });
  
        // gather links incident on modified tuples
        links.forEach(function(link) {
          if (lut[vegaDataflow.tupleid(link.source)] || lut[vegaDataflow.tupleid(link.target)]) {
            out.mod.push(link);
          }
        });
      }
  
      return out;
    };
  
    var Tiles = {
      binary: d3Hierarchy.treemapBinary,
      dice: d3Hierarchy.treemapDice,
      slice: d3Hierarchy.treemapSlice,
      slicedice: d3Hierarchy.treemapSliceDice,
      squarify: d3Hierarchy.treemapSquarify,
      resquarify: d3Hierarchy.treemapResquarify
    };
  
    var Output$3 = ['x0', 'y0', 'x1', 'y1', 'depth', 'children'];
  
    /**
     * Treemap layout.
     * @constructor
     * @param {object} params - The parameters for this operator.
     * @param {function(object): *} params.field - The value field to size nodes.
     */
    function Treemap(params) {
      HierarchyLayout.call(this, params);
    }
  
    Treemap.Definition = {
      "type": "Treemap",
      "metadata": {"tree": true, "modifies": true},
      "params": [
        { "name": "field", "type": "field" },
        { "name": "sort", "type": "compare" },
        { "name": "method", "type": "enum", "default": "squarify",
          "values": ["squarify", "resquarify", "binary", "dice", "slice", "slicedice"] },
        { "name": "padding", "type": "number", "default": 0 },
        { "name": "paddingInner", "type": "number", "default": 0 },
        { "name": "paddingOuter", "type": "number", "default": 0 },
        { "name": "paddingTop", "type": "number", "default": 0 },
        { "name": "paddingRight", "type": "number", "default": 0 },
        { "name": "paddingBottom", "type": "number", "default": 0 },
        { "name": "paddingLeft", "type": "number", "default": 0 },
        { "name": "ratio", "type": "number", "default": 1.618033988749895 },
        { "name": "round", "type": "boolean", "default": false },
        { "name": "size", "type": "number", "array": true, "length": 2 },
        { "name": "as", "type": "string", "array": true, "length": Output$3.length, "default": Output$3 }
      ]
    };
  
    var prototype$7 = vegaUtil.inherits(Treemap, HierarchyLayout);
  
    /**
     * Treemap layout generator. Adds 'method' and 'ratio' parameters
     * to configure the underlying tile method.
     */
    prototype$7.layout = function() {
      var x = d3Hierarchy.treemap();
      x.ratio = function(_) {
        var t = x.tile();
        if (t.ratio) x.tile(t.ratio(_));
      };
      x.method = function(_) {
        if (Tiles.hasOwnProperty(_)) x.tile(Tiles[_]);
        else vegaUtil.error('Unrecognized Treemap layout method: ' + _);
      };
      return x;
    };
  
    prototype$7.params = [
      'method', 'ratio', 'size', 'round',
      'padding', 'paddingInner', 'paddingOuter',
      'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'
    ];
  
    prototype$7.fields = Output$3;
  
    exports.nest = Nest;
    exports.pack = Pack;
    exports.partition = Partition;
    exports.stratify = Stratify;
    exports.tree = Tree;
    exports.treelinks = TreeLinks;
    exports.treemap = Treemap;
  
    Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  