(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-dataflow'), require('vega-scenegraph'), require('vega-util')) : typeof define === 'function' && define.amd ? define(['exports', 'vega-dataflow', 'vega-scenegraph', 'vega-util'], factory) : (global = global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.vega, global.vega, global.vega)); }(this, (function (exports, vegaDataflow, vegaScenegraph, vegaUtil) { 'use strict'; const Top = 'top'; const Left = 'left'; const Right = 'right'; const Bottom = 'bottom'; const TopLeft = 'top-left'; const TopRight = 'top-right'; const BottomLeft = 'bottom-left'; const BottomRight = 'bottom-right'; const Start = 'start'; const Middle = 'middle'; const End = 'end'; const X = 'x'; const Y = 'y'; const Group = 'group'; const AxisRole = 'axis'; const TitleRole = 'title'; const FrameRole = 'frame'; const ScopeRole = 'scope'; const LegendRole = 'legend'; const RowHeader = 'row-header'; const RowFooter = 'row-footer'; const RowTitle = 'row-title'; const ColHeader = 'column-header'; const ColFooter = 'column-footer'; const ColTitle = 'column-title'; const Padding = 'padding'; const Symbols = 'symbol'; const Fit = 'fit'; const FitX = 'fit-x'; const FitY = 'fit-y'; const Pad = 'pad'; const None = 'none'; const All = 'all'; const Each = 'each'; const Flush = 'flush'; const Column = 'column'; const Row = 'row'; /** * Calculate bounding boxes for scenegraph items. * @constructor * @param {object} params - The parameters for this operator. * @param {object} params.mark - The scenegraph mark instance to bound. */ function Bound(params) { vegaDataflow.Transform.call(this, null, params); } var prototype = vegaUtil.inherits(Bound, vegaDataflow.Transform); prototype.transform = function(_, pulse) { var view = pulse.dataflow, mark = _.mark, type = mark.marktype, entry = vegaScenegraph.Marks[type], bound = entry.bound, markBounds = mark.bounds, rebound; if (entry.nested) { // multi-item marks have a single bounds instance if (mark.items.length) view.dirty(mark.items[0]); markBounds = boundItem(mark, bound); mark.items.forEach(function(item) { item.bounds.clear().union(markBounds); }); } else if (type === Group || _.modified()) { // operator parameters modified -> re-bound all items // updates group bounds in response to modified group content pulse.visit(pulse.MOD, function(item) { view.dirty(item); }); markBounds.clear(); mark.items.forEach(function(item) { markBounds.union(boundItem(item, bound)); }); // force reflow for axes/legends/titles to propagate any layout changes switch (mark.role) { case AxisRole: case LegendRole: case TitleRole: pulse.reflow(); } } else { // incrementally update bounds, re-bound mark as needed rebound = pulse.changed(pulse.REM); pulse.visit(pulse.ADD, function(item) { markBounds.union(boundItem(item, bound)); }); pulse.visit(pulse.MOD, function(item) { rebound = rebound || markBounds.alignsWith(item.bounds); view.dirty(item); markBounds.union(boundItem(item, bound)); }); if (rebound) { markBounds.clear(); mark.items.forEach(function(item) { markBounds.union(item.bounds); }); } } // ensure mark bounds do not exceed any clipping region vegaScenegraph.boundClip(mark); return pulse.modifies('bounds'); }; function boundItem(item, bound, opt) { return bound(item.bounds.clear(), item, opt); } var COUNTER_NAME = ':vega_identifier:'; /** * Adds a unique identifier to all added tuples. * This transform creates a new signal that serves as an id counter. * As a result, the id counter is shared across all instances of this * transform, generating unique ids across multiple data streams. In * addition, this signal value can be included in a snapshot of the * dataflow state, enabling correct resumption of id allocation. * @constructor * @param {object} params - The parameters for this operator. * @param {string} params.as - The field name for the generated identifier. */ function Identifier(params) { vegaDataflow.Transform.call(this, 0, params); } Identifier.Definition = { "type": "Identifier", "metadata": {"modifies": true}, "params": [ { "name": "as", "type": "string", "required": true } ] }; var prototype$1 = vegaUtil.inherits(Identifier, vegaDataflow.Transform); prototype$1.transform = function(_, pulse) { var counter = getCounter(pulse.dataflow), id = counter.value, as = _.as; pulse.visit(pulse.ADD, function(t) { if (!t[as]) t[as] = ++id; }); counter.set(this.value = id); return pulse; }; function getCounter(view) { var counter = view._signals[COUNTER_NAME]; if (!counter) { view._signals[COUNTER_NAME] = (counter = view.add(0)); } return counter; } /** * Bind scenegraph items to a scenegraph mark instance. * @constructor * @param {object} params - The parameters for this operator. * @param {object} params.markdef - The mark definition for creating the mark. * This is an object of legal scenegraph mark properties which *must* include * the 'marktype' property. */ function Mark(params) { vegaDataflow.Transform.call(this, null, params); } var prototype$2 = vegaUtil.inherits(Mark, vegaDataflow.Transform); prototype$2.transform = function(_, pulse) { var mark = this.value; // acquire mark on first invocation, bind context and group if (!mark) { mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup(_), _.index); mark.group.context = _.context; if (!_.context.group) _.context.group = mark.group; mark.source = this.source; // point to upstream collector mark.clip = _.clip; mark.interactive = _.interactive; this.value = mark; } // initialize entering items var Init = mark.marktype === Group ? vegaScenegraph.GroupItem : vegaScenegraph.Item; pulse.visit(pulse.ADD, function(item) { Init.call(item, mark); }); // update clipping and/or interactive status if (_.modified('clip') || _.modified('interactive')) { mark.clip = _.clip; mark.interactive = !!_.interactive; mark.zdirty = true; // force scenegraph re-eval pulse.reflow(); } // bind items array to scenegraph mark mark.items = pulse.source; return pulse; }; function lookup(_) { var g = _.groups, p = _.parent; return g && g.size === 1 ? g.get(Object.keys(g.object)[0]) : g && p ? g.lookup(p) : null; } /** * Analyze items for overlap, changing opacity to hide items with * overlapping bounding boxes. This transform will preserve at least * two items (e.g., first and last) even if overlap persists. * @param {object} params - The parameters for this operator. * @param {function(*,*): number} [params.sort] - A comparator * function for sorting items. * @param {object} [params.method] - The overlap removal method to apply. * One of 'parity' (default, hide every other item until there is no * more overlap) or 'greedy' (sequentially scan and hide and items that * overlap with the last visible item). * @param {object} [params.boundScale] - A scale whose range should be used * to bound the items. Items exceeding the bounds of the scale range * will be treated as overlapping. If null or undefined, no bounds check * will be applied. * @param {object} [params.boundOrient] - The orientation of the scale * (top, bottom, left, or right) used to bound items. This parameter is * ignored if boundScale is null or undefined. * @param {object} [params.boundTolerance] - The tolerance in pixels for * bound inclusion testing (default 1). This specifies by how many pixels * an item's bounds may exceed the scale range bounds and not be culled. * @constructor */ function Overlap(params) { vegaDataflow.Transform.call(this, null, params); } var prototype$3 = vegaUtil.inherits(Overlap, vegaDataflow.Transform); var methods = { parity: function(items) { return items.filter((item, i) => i % 2 ? (item.opacity = 0) : 1); }, greedy: function(items, sep) { var a; return items.filter((b, i) => { if (!i || !intersect(a.bounds, b.bounds, sep)) { a = b; return 1; } else { return b.opacity = 0; } }); } }; // compute bounding box intersection // including padding pixels of separation function intersect(a, b, sep) { return sep > Math.max( b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2 ); } function hasOverlap(items, pad) { for (var i=1, n=items.length, a=items[0].bounds, b; i 1 && b.height() > 1; } function boundTest(scale, orient, tolerance) { var range = scale.range(), b = new vegaScenegraph.Bounds(); if (orient === Top || orient === Bottom) { b.set(range[0], -Infinity, range[1], +Infinity); } else { b.set(-Infinity, range[0], +Infinity, range[1]); } b.expand(tolerance || 1); return item => b.encloses(item.bounds); } // reset all items to be fully opaque function reset(source) { source.forEach(item => item.opacity = 1); return source; } // add all tuples to mod, fork pulse if parameters were modified // fork prevents cross-stream tuple pollution (e.g., pulse from scale) function reflow(pulse, _) { return pulse.reflow(_.modified()).modifies('opacity'); } prototype$3.transform = function(_, pulse) { var reduce = methods[_.method] || methods.parity, source = pulse.materialize(pulse.SOURCE).source, sep = _.separation || 0, items, test, bounds; if (!source || !source.length) return; if (!_.method) { // early exit if method is falsy if (_.modified('method')) { reset(source); pulse = reflow(pulse, _); } return pulse; } if (_.sort) { source = source.slice().sort(_.sort); } // skip labels with no content source = source.filter(hasBounds); items = reset(source); pulse = reflow(pulse, _); if (items.length >= 3 && hasOverlap(items, sep)) { do { items = reduce(items, sep); } while (items.length >= 3 && hasOverlap(items, sep)); if (items.length < 3 && !vegaUtil.peek(source).opacity) { if (items.length > 1) vegaUtil.peek(items).opacity = 0; vegaUtil.peek(source).opacity = 1; } } if (_.boundScale && _.boundTolerance >= 0) { test = boundTest(_.boundScale, _.boundOrient, +_.boundTolerance); source.forEach(item => { if (!test(item)) item.opacity = 0; }); } // re-calculate mark bounds bounds = items[0].mark.bounds.clear(); source.forEach(item => { if (item.opacity) bounds.union(item.bounds); }); return pulse; }; /** * Queue modified scenegraph items for rendering. * @constructor */ function Render(params) { vegaDataflow.Transform.call(this, null, params); } var prototype$4 = vegaUtil.inherits(Render, vegaDataflow.Transform); prototype$4.transform = function(_, pulse) { var view = pulse.dataflow; pulse.visit(pulse.ALL, function(item) { view.dirty(item); }); // set z-index dirty flag as needed if (pulse.fields && pulse.fields['zindex']) { var item = pulse.source && pulse.source[0]; if (item) item.mark.zdirty = true; } }; const tempBounds = new vegaScenegraph.Bounds(); function set(item, property, value) { return item[property] === value ? 0 : (item[property] = value, 1); } function isYAxis(mark) { var orient = mark.items[0].datum.orient; return orient === Left || orient === Right; } function axisIndices(datum) { var index = +datum.grid; return [ datum.ticks ? index++ : -1, // ticks index datum.labels ? index++ : -1, // labels index index + (+datum.domain) // title index ]; } function axisLayout(view, axis, width, height) { var item = axis.items[0], datum = item.datum, orient = datum.orient, delta = datum.translate != null ? datum.translate : 0.5, indices = axisIndices(datum), range = item.range, offset = item.offset, position = item.position, minExtent = item.minExtent, maxExtent = item.maxExtent, title = datum.title && item.items[indices[2]].items[0], titlePadding = item.titlePadding, bounds = item.bounds, dl = title && vegaScenegraph.multiLineOffset(title), x = 0, y = 0, i, s; tempBounds.clear().union(bounds); bounds.clear(); if ((i=indices[0]) > -1) bounds.union(item.items[i].bounds); if ((i=indices[1]) > -1) bounds.union(item.items[i].bounds); // position axis group and title switch (orient) { case Top: x = position || 0; y = -offset; s = Math.max(minExtent, Math.min(maxExtent, -bounds.y1)); if (title) s = axisTitleLayout(view, title, s, titlePadding, dl, 0, -1, bounds); bounds.add(0, -s).add(range, 0); break; case Left: x = -offset; y = position || 0; s = Math.max(minExtent, Math.min(maxExtent, -bounds.x1)); if (title) s = axisTitleLayout(view, title, s, titlePadding, dl, 1, -1, bounds); bounds.add(-s, 0).add(0, range); break; case Right: x = width + offset; y = position || 0; s = Math.max(minExtent, Math.min(maxExtent, bounds.x2)); if (title) s = axisTitleLayout(view, title, s, titlePadding, dl, 1, 1, bounds); bounds.add(0, 0).add(s, range); break; case Bottom: x = position || 0; y = height + offset; s = Math.max(minExtent, Math.min(maxExtent, bounds.y2)); if (title) s = axisTitleLayout(view, title, s, titlePadding, 0, 0, 1, bounds); bounds.add(0, 0).add(range, s); break; default: x = item.x; y = item.y; } // update bounds vegaScenegraph.boundStroke(bounds.translate(x, y), item); if (set(item, 'x', x + delta) | set(item, 'y', y + delta)) { item.bounds = tempBounds; view.dirty(item); item.bounds = bounds; view.dirty(item); } return item.mark.bounds.clear().union(bounds); } function axisTitleLayout(view, title, offset, pad, dl, isYAxis, sign, bounds) { var b = title.bounds, dx = 0, dy = 0; if (title.auto) { view.dirty(title); offset += pad; isYAxis ? dx = (title.x || 0) - (title.x = sign * (offset + dl)) : dy = (title.y || 0) - (title.y = sign * (offset + dl)); title.mark.bounds.clear().union(b.translate(-dx, -dy)); view.dirty(title); if (isYAxis) { bounds.add(0, b.y1).add(0, b.y2); offset += b.width(); } else { bounds.add(b.x1, 0).add(b.x2, 0); offset += b.height(); } } else { bounds.union(b); } return offset; } function gridLayoutGroups(group) { var groups = group.items, n = groups.length, i = 0, mark, items; var views = { marks: [], rowheaders: [], rowfooters: [], colheaders: [], colfooters: [], rowtitle: null, coltitle: null }; // layout axes, gather legends, collect bounds for (; i 1) { for (i=0; i 0) dx[i] += x / 2; } } // perform vertical centering if (alignRow && get(opt.center, Row) && ncols !== 1) { for (i=0; i 0) dy[i] += y / 2; } } // position grid relative to anchor for (i=0; i limit) { view.warn('Grid headers exceed limit: ' + limit); headers = headers.slice(0, limit); } // apply offset init += offset; // clear mark bounds for all headers for (j=0, m=headers.length; j= 0 && (g = groups[k]) == null; k-=back); // assign coordinates and update bounds if (isX) { x = band == null ? g.x : Math.round(g.bounds.x1 + band * g.bounds.width()); y = init; } else { x = init; y = band == null ? g.y : Math.round(g.bounds.y1 + band * g.bounds.height()); } b.union(h.bounds.translate(x - (h.x || 0), y - (h.y || 0))); h.x = x; h.y = y; view.dirty(h); // update current edge of layout bounds edge = agg(edge, b[bf]); } return edge; } function layoutTitle(view, g, offset, isX, bounds, band) { if (!g) return; view.dirty(g); // compute title coordinates var x = offset, y = offset; isX ? (x = Math.round(bounds.x1 + band * bounds.width())) : (y = Math.round(bounds.y1 + band * bounds.height())); // assign coordinates and update bounds g.bounds.translate(x - (g.x || 0), y - (g.y || 0)); g.mark.bounds.clear().union(g.bounds); g.x = x; g.y = y; // queue title for redraw view.dirty(g); } // utility for looking up legend layout configuration function lookup$1(config, orient) { const opt = config[orient] || {}; return (key, d) => opt[key] != null ? opt[key] : config[key] != null ? config[key] : d; } // if legends specify offset directly, use the maximum specified value function offsets(legends, value) { var max = -Infinity; legends.forEach(item => { if (item.offset != null) max = Math.max(max, item.offset); }); return max > -Infinity ? max : value; } function legendParams(g, orient, config, xb, yb, w, h) { const _ = lookup$1(config, orient), offset = offsets(g, _('offset', 0)), anchor = _('anchor', Start), mult = anchor === End ? 1 : anchor === Middle ? 0.5 : 0; const p = { align: Each, bounds: _('bounds', Flush), columns: _('direction') === 'vertical' ? 1 : g.length, padding: _('margin', 8), center: _('center'), nodirty: true }; switch (orient) { case Left: p.anchor = { x: Math.floor(xb.x1) - offset, column: End, y: mult * (h || xb.height() + 2 * xb.y1), row: anchor }; break; case Right: p.anchor = { x: Math.ceil(xb.x2) + offset, y: mult * (h || xb.height() + 2 * xb.y1), row: anchor }; break; case Top: p.anchor = { y: Math.floor(yb.y1) - offset, row: End, x: mult * (w || yb.width() + 2 * yb.x1), column: anchor }; break; case Bottom: p.anchor = { y: Math.ceil(yb.y2) + offset, x: mult * (w || yb.width() + 2 * yb.x1), column: anchor }; break; case TopLeft: p.anchor = {x: offset, y: offset}; break; case TopRight: p.anchor = {x: w - offset, y: offset, column: End}; break; case BottomLeft: p.anchor = {x: offset, y: h - offset, row: End}; break; case BottomRight: p.anchor = {x: w - offset, y: h - offset, column: End, row: End}; break; } return p; } function legendLayout(view, legend) { var item = legend.items[0], datum = item.datum, orient = item.orient, bounds = item.bounds, x = item.x, y = item.y, w, h; // cache current bounds for later comparison item._bounds ? item._bounds.clear().union(bounds) : item._bounds = bounds.clone(); bounds.clear(); // adjust legend to accommodate padding and title legendGroupLayout(view, item, item.items[0].items[0]); // aggregate bounds to determine size, and include origin bounds = legendBounds(item, bounds); w = 2 * item.padding; h = 2 * item.padding; if (!bounds.empty()) { w = Math.ceil(bounds.width() + w); h = Math.ceil(bounds.height() + h); } if (datum.type === Symbols) { legendEntryLayout(item.items[0].items[0].items[0].items); } if (orient !== None) { item.x = x = 0; item.y = y = 0; } item.width = w; item.height = h; vegaScenegraph.boundStroke(bounds.set(x, y, x + w, y + h), item); item.mark.bounds.clear().union(bounds); return item; } function legendBounds(item, b) { // aggregate item bounds item.items.forEach(_ => b.union(_.bounds)); // anchor to legend origin b.x1 = item.padding; b.y1 = item.padding; return b; } function legendGroupLayout(view, item, entry) { var pad = item.padding, ex = pad - entry.x, ey = pad - entry.y; if (!item.datum.title) { if (ex || ey) translate(view, entry, ex, ey); } else { var title = item.items[1].items[0], anchor = title.anchor, tpad = item.titlePadding || 0, tx = pad - title.x, ty = pad - title.y; switch (title.orient) { case Left: ex += Math.ceil(title.bounds.width()) + tpad; break; case Right: case Bottom: break; default: ey += title.bounds.height() + tpad; } if (ex || ey) translate(view, entry, ex, ey); switch (title.orient) { case Left: ty += legendTitleOffset(item, entry, title, anchor, 1, 1); break; case Right: tx += legendTitleOffset(item, entry, title, End, 0, 0) + tpad; ty += legendTitleOffset(item, entry, title, anchor, 1, 1); break; case Bottom: tx += legendTitleOffset(item, entry, title, anchor, 0, 0); ty += legendTitleOffset(item, entry, title, End, -1, 0, 1) + tpad; break; default: tx += legendTitleOffset(item, entry, title, anchor, 0, 0); } if (tx || ty) translate(view, title, tx, ty); // translate legend if title pushes into negative coordinates if ((tx = Math.round(title.bounds.x1 - pad)) < 0) { translate(view, entry, -tx, 0); translate(view, title, -tx, 0); } } } function legendTitleOffset(item, entry, title, anchor, y, lr, noBar) { const grad = item.datum.type !== 'symbol', vgrad = title.datum.vgrad, e = grad && (lr || !vgrad) && !noBar ? entry.items[0] : entry, s = e.bounds[y ? 'y2' : 'x2'] - item.padding, u = vgrad && lr ? s : 0, v = vgrad && lr ? 0 : s, o = y <= 0 ? 0 : vegaScenegraph.multiLineOffset(title); return Math.round(anchor === Start ? u : anchor === End ? (v - o) : 0.5 * (s - o)); } function translate(view, item, dx, dy) { item.x += dx; item.y += dy; item.bounds.translate(dx, dy); item.mark.bounds.translate(dx, dy); view.dirty(item); } function legendEntryLayout(entries) { // get max widths for each column var widths = entries.reduce(function(w, g) { w[g.column] = Math.max(g.bounds.x2 - g.x, w[g.column] || 0); return w; }, {}); // set dimensions of legend entry groups entries.forEach(function(g) { g.width = widths[g.column]; g.height = g.bounds.y2 - g.y; }); } function titleLayout(view, mark, width, height, viewBounds) { var group = mark.items[0], frame = group.frame, orient = group.orient, anchor = group.anchor, offset = group.offset, padding = group.padding, title = group.items[0].items[0], subtitle = group.items[1] && group.items[1].items[0], end = (orient === Left || orient === Right) ? height : width, start = 0, x = 0, y = 0, sx = 0, sy = 0, pos; if (frame !== Group) { orient === Left ? (start = viewBounds.y2, end = viewBounds.y1) : orient === Right ? (start = viewBounds.y1, end = viewBounds.y2) : (start = viewBounds.x1, end = viewBounds.x2); } else if (orient === Left) { start = height, end = 0; } pos = (anchor === Start) ? start : (anchor === End) ? end : (start + end) / 2; if (subtitle && subtitle.text) { // position subtitle switch (orient) { case Top: case Bottom: sy = title.bounds.height() + padding; break; case Left: sx = title.bounds.width() + padding; break; case Right: sx = -title.bounds.width() - padding; break; } tempBounds.clear().union(subtitle.bounds); tempBounds.translate(sx - (subtitle.x || 0), sy - (subtitle.y || 0)); if (set(subtitle, 'x', sx) | set(subtitle, 'y', sy)) { view.dirty(subtitle); subtitle.bounds.clear().union(tempBounds); subtitle.mark.bounds.clear().union(tempBounds); view.dirty(subtitle); } tempBounds.clear().union(subtitle.bounds); } else { tempBounds.clear(); } tempBounds.union(title.bounds); // position title group switch (orient) { case Top: x = pos; y = viewBounds.y1 - tempBounds.height() - offset; break; case Left: x = viewBounds.x1 - tempBounds.width() - offset; y = pos; break; case Right: x = viewBounds.x2 + tempBounds.width() + offset; y = pos; break; case Bottom: x = pos; y = viewBounds.y2 + offset; break; default: x = group.x; y = group.y; } if (set(group, 'x', x) | set(group, 'y', y)) { tempBounds.translate(x, y); view.dirty(group); group.bounds.clear().union(tempBounds); mark.bounds.clear().union(tempBounds); view.dirty(group); } return group.bounds; } /** * Layout view elements such as axes and legends. * Also performs size adjustments. * @constructor * @param {object} params - The parameters for this operator. * @param {object} params.mark - Scenegraph mark of groups to layout. */ function ViewLayout(params) { vegaDataflow.Transform.call(this, null, params); } var prototype$5 = vegaUtil.inherits(ViewLayout, vegaDataflow.Transform); prototype$5.transform = function(_, pulse) { // TODO incremental update, output? var view = pulse.dataflow; _.mark.items.forEach(function(group) { if (_.layout) trellisLayout(view, group, _.layout); layoutGroup(view, group, _); }); if (_.modified()) pulse.reflow(); return pulse; }; function layoutGroup(view, group, _) { var items = group.items, width = Math.max(0, group.width || 0), height = Math.max(0, group.height || 0), viewBounds = new vegaScenegraph.Bounds().set(0, 0, width, height), xBounds = viewBounds.clone(), yBounds = viewBounds.clone(), legends = [], title, mark, orient, b, i, n; // layout axes, gather legends, collect bounds for (i=0, n=items.length; i { orient = item.orient || Right; if (orient !== None) (l[orient] || (l[orient] = [])).push(item); }); // perform grid layout for each orient group for (let orient in l) { const g = l[orient]; gridLayout(view, g, legendParams( g, orient, _.legends, xBounds, yBounds, width, height )); } // update view bounds legends.forEach(item => { const b = item.bounds; if (!b.equals(item._bounds)) { item.bounds = item._bounds; view.dirty(item); // dirty previous location item.bounds = b; view.dirty(item); } if (_.autosize && _.autosize.type === Fit) { // For autosize fit, incorporate the orthogonal dimension only. // Legends that overrun the chart area will then be clipped; // otherwise the chart area gets reduced to nothing! switch(item.orient) { case Left: case Right: viewBounds.add(b.x1, 0).add(b.x2, 0); break; case Top: case Bottom: viewBounds.add(0, b.y1).add(0, b.y2); } } else { viewBounds.union(b); } }); } // combine bounding boxes viewBounds.union(xBounds).union(yBounds); // layout title, adjust bounds if (title) { viewBounds.union(titleLayout(view, title, width, height, viewBounds)); } // override aggregated view bounds if content is clipped if (group.clip) { viewBounds.set(0, 0, group.width || 0, group.height || 0); } // perform size adjustment viewSizeLayout(view, group, viewBounds, _); } function viewSizeLayout(view, group, viewBounds, _) { var auto = _.autosize || {}, type = auto.type, viewWidth = view._width, viewHeight = view._height, padding = view.padding(); if (view._autosize < 1 || !type) return; var width = Math.max(0, group.width || 0), left = Math.max(0, Math.ceil(-viewBounds.x1)), right = Math.max(0, Math.ceil(viewBounds.x2 - width)), height = Math.max(0, group.height || 0), top = Math.max(0, Math.ceil(-viewBounds.y1)), bottom = Math.max(0, Math.ceil(viewBounds.y2 - height)); if (auto.contains === Padding) { viewWidth -= padding.left + padding.right; viewHeight -= padding.top + padding.bottom; } if (type === None) { left = 0; top = 0; width = viewWidth; height = viewHeight; } else if (type === Fit) { width = Math.max(0, viewWidth - left - right); height = Math.max(0, viewHeight - top - bottom); } else if (type === FitX) { width = Math.max(0, viewWidth - left - right); viewHeight = height + top + bottom; } else if (type === FitY) { viewWidth = width + left + right; height = Math.max(0, viewHeight - top - bottom); } else if (type === Pad) { viewWidth = width + left + right; viewHeight = height + top + bottom; } view._resizeView( viewWidth, viewHeight, width, height, [left, top], auto.resize ); } exports.bound = Bound; exports.identifier = Identifier; exports.mark = Mark; exports.overlap = Overlap; exports.render = Render; exports.viewlayout = ViewLayout; Object.defineProperty(exports, '__esModule', { value: true }); })));