vega-view-transforms
Advanced tools
Comparing version 4.5.8 to 4.5.9
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.vega, global.vega, global.vega)); | ||
}(this, (function (exports, vegaDataflow, vegaScenegraph, vegaUtil) { 'use strict'; | ||
})(this, (function (exports, vegaDataflow, vegaScenegraph, vegaUtil) { 'use strict'; | ||
@@ -52,3 +52,2 @@ const Top = 'top'; | ||
*/ | ||
function Bound(params) { | ||
@@ -60,9 +59,8 @@ vegaDataflow.Transform.call(this, null, params); | ||
const view = pulse.dataflow, | ||
mark = _.mark, | ||
type = mark.marktype, | ||
entry = vegaScenegraph.Marks[type], | ||
bound = entry.bound; | ||
mark = _.mark, | ||
type = mark.marktype, | ||
entry = vegaScenegraph.Marks[type], | ||
bound = entry.bound; | ||
let markBounds = mark.bounds, | ||
rebound; | ||
rebound; | ||
if (entry.nested) { | ||
@@ -80,4 +78,5 @@ // multi-item marks have a single bounds instance | ||
markBounds.clear(); | ||
mark.items.forEach(item => markBounds.union(boundItem(item, bound))); // force reflow for axes/legends/titles to propagate any layout changes | ||
mark.items.forEach(item => markBounds.union(boundItem(item, bound))); | ||
// force reflow for axes/legends/titles to propagate any layout changes | ||
switch (mark.role) { | ||
@@ -100,3 +99,2 @@ case AxisRole: | ||
}); | ||
if (rebound) { | ||
@@ -106,11 +104,9 @@ markBounds.clear(); | ||
} | ||
} // ensure mark bounds do not exceed any clipping region | ||
} | ||
// ensure mark bounds do not exceed any clipping region | ||
vegaScenegraph.boundClip(mark); | ||
return pulse.modifies('bounds'); | ||
} | ||
}); | ||
function boundItem(item, bound, opt) { | ||
@@ -121,2 +117,3 @@ return bound(item.bounds.clear(), item, opt); | ||
const COUNTER_NAME = ':vega_identifier:'; | ||
/** | ||
@@ -133,3 +130,2 @@ * Adds a unique identifier to all added tuples. | ||
*/ | ||
function Identifier(params) { | ||
@@ -152,3 +148,3 @@ vegaDataflow.Transform.call(this, 0, params); | ||
const counter = getCounter(pulse.dataflow), | ||
as = _.as; | ||
as = _.as; | ||
let id = counter.value; | ||
@@ -159,5 +155,3 @@ pulse.visit(pulse.ADD, t => t[as] = t[as] || ++id); | ||
} | ||
}); | ||
function getCounter(view) { | ||
@@ -175,3 +169,2 @@ return view._signals[COUNTER_NAME] || (view._signals[COUNTER_NAME] = view.add(0)); | ||
*/ | ||
function Mark(params) { | ||
@@ -182,19 +175,20 @@ vegaDataflow.Transform.call(this, null, params); | ||
transform(_, pulse) { | ||
let mark = this.value; // acquire mark on first invocation, bind context and group | ||
let mark = this.value; | ||
// acquire mark on first invocation, bind context and group | ||
if (!mark) { | ||
mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup(_), _.index); | ||
mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup$1(_), _.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 | ||
} | ||
// initialize entering items | ||
const Init = mark.marktype === Group ? vegaScenegraph.GroupItem : vegaScenegraph.Item; | ||
pulse.visit(pulse.ADD, item => Init.call(item, mark)); // update clipping and/or interactive status | ||
pulse.visit(pulse.ADD, item => Init.call(item, mark)); | ||
// update clipping and/or interactive status | ||
if (_.modified('clip') || _.modified('interactive')) { | ||
@@ -204,16 +198,13 @@ mark.clip = _.clip; | ||
mark.zdirty = true; // force scenegraph re-eval | ||
pulse.reflow(); | ||
} // bind items array to scenegraph mark | ||
} | ||
// bind items array to scenegraph mark | ||
mark.items = pulse.source; | ||
return pulse; | ||
} | ||
}); | ||
function lookup(_) { | ||
function lookup$1(_) { | ||
const g = _.groups, | ||
p = _.parent; | ||
p = _.parent; | ||
return g && g.size === 1 ? g.get(Object.keys(g.object)[0]) : g && p ? g.lookup(p) : null; | ||
@@ -245,3 +236,2 @@ } | ||
*/ | ||
function Overlap(params) { | ||
@@ -256,7 +246,7 @@ vegaDataflow.Transform.call(this, null, params); | ||
} | ||
}; // compute bounding box intersection | ||
}; | ||
// compute bounding box intersection | ||
// including padding pixels of separation | ||
const intersect = (a, b, sep) => sep > Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2); | ||
const hasOverlap = (items, pad) => { | ||
@@ -267,3 +257,2 @@ for (var i = 1, n = items.length, a = items[0].bounds, b; i < n; a = b, ++i) { | ||
}; | ||
const hasBounds = item => { | ||
@@ -273,7 +262,5 @@ const b = item.bounds; | ||
}; | ||
const boundTest = (scale, orient, tolerance) => { | ||
var range = scale.range(), | ||
b = new vegaScenegraph.Bounds(); | ||
b = new vegaScenegraph.Bounds(); | ||
if (orient === Top || orient === Bottom) { | ||
@@ -284,26 +271,23 @@ b.set(range[0], -Infinity, range[1], +Infinity); | ||
} | ||
b.expand(tolerance || 1); | ||
return item => b.encloses(item.bounds); | ||
}; // reset all items to be fully opaque | ||
}; | ||
// reset all items to be fully opaque | ||
const reset = source => { | ||
source.forEach(item => item.opacity = 1); | ||
return source; | ||
}; // add all tuples to mod, fork pulse if parameters were modified | ||
}; | ||
// add all tuples to mod, fork pulse if parameters were modified | ||
// fork prevents cross-stream tuple pollution (e.g., pulse from scale) | ||
const reflow = (pulse, _) => pulse.reflow(_.modified()).modifies('opacity'); | ||
vegaUtil.inherits(Overlap, vegaDataflow.Transform, { | ||
transform(_, pulse) { | ||
const reduce = methods[_.method] || methods.parity, | ||
sep = _.separation || 0; | ||
sep = _.separation || 0; | ||
let source = pulse.materialize(pulse.SOURCE).source, | ||
items, | ||
test; | ||
items, | ||
test; | ||
if (!source || !source.length) return; | ||
if (!_.method) { | ||
@@ -315,18 +299,15 @@ // early exit if method is falsy | ||
} | ||
return pulse; | ||
} // skip labels with no content | ||
} | ||
// skip labels with no content | ||
source = source.filter(hasBounds); | ||
source = source.filter(hasBounds); // early exit, nothing to do | ||
// early exit, nothing to do | ||
if (!source.length) return; | ||
if (_.sort) { | ||
source = source.slice().sort(_.sort); | ||
} | ||
items = reset(source); | ||
pulse = reflow(pulse, _); | ||
if (items.length >= 3 && hasOverlap(items, sep)) { | ||
@@ -336,3 +317,2 @@ do { | ||
} while (items.length >= 3 && hasOverlap(items, sep)); | ||
if (items.length < 3 && !vegaUtil.peek(source).opacity) { | ||
@@ -343,3 +323,2 @@ if (items.length > 1) vegaUtil.peek(items).opacity = 0; | ||
} | ||
if (_.boundScale && _.boundTolerance >= 0) { | ||
@@ -350,5 +329,5 @@ test = boundTest(_.boundScale, _.boundOrient, +_.boundTolerance); | ||
}); | ||
} // re-calculate mark bounds | ||
} | ||
// re-calculate mark bounds | ||
const bounds = items[0].mark.bounds.clear(); | ||
@@ -360,3 +339,2 @@ source.forEach(item => { | ||
} | ||
}); | ||
@@ -368,3 +346,2 @@ | ||
*/ | ||
function Render(params) { | ||
@@ -376,4 +353,5 @@ vegaDataflow.Transform.call(this, null, params); | ||
const view = pulse.dataflow; | ||
pulse.visit(pulse.ALL, item => view.dirty(item)); // set z-index dirty flag as needed | ||
pulse.visit(pulse.ALL, item => view.dirty(item)); | ||
// set z-index dirty flag as needed | ||
if (pulse.fields && pulse.fields['zindex']) { | ||
@@ -384,3 +362,2 @@ const item = pulse.source && pulse.source[0]; | ||
} | ||
}); | ||
@@ -397,7 +374,8 @@ | ||
} | ||
function axisIndices(datum) { | ||
let index = +datum.grid; | ||
return [datum.ticks ? index++ : -1, // ticks index | ||
datum.labels ? index++ : -1, // labels index | ||
return [datum.ticks ? index++ : -1, | ||
// ticks index | ||
datum.labels ? index++ : -1, | ||
// labels index | ||
index + +datum.domain // title index | ||
@@ -409,24 +387,25 @@ ]; | ||
var item = axis.items[0], | ||
datum = item.datum, | ||
delta = item.translate != null ? item.translate : 0.5, | ||
orient = item.orient, | ||
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; | ||
datum = item.datum, | ||
delta = item.translate != null ? item.translate : 0.5, | ||
orient = item.orient, | ||
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 | ||
if ((i = indices[1]) > -1) bounds.union(item.items[i].bounds); | ||
// position axis group and title | ||
switch (orient) { | ||
@@ -440,3 +419,2 @@ case Top: | ||
break; | ||
case Left: | ||
@@ -449,3 +427,2 @@ x = -offset; | ||
break; | ||
case Right: | ||
@@ -458,3 +435,2 @@ x = width + offset; | ||
break; | ||
case Bottom: | ||
@@ -467,11 +443,9 @@ x = position || 0; | ||
break; | ||
default: | ||
x = item.x; | ||
y = item.y; | ||
} // update bounds | ||
} | ||
// update bounds | ||
vegaScenegraph.boundStroke(bounds.translate(x, y), item); | ||
if (set(item, 'x', x + delta) | set(item, 'y', y + delta)) { | ||
@@ -483,13 +457,10 @@ item.bounds = tempBounds; | ||
} | ||
return item.mark.bounds.clear().union(bounds); | ||
} | ||
function axisTitleLayout(view, title, offset, pad, dl, isYAxis, sign, bounds) { | ||
const b = title.bounds; | ||
if (title.auto) { | ||
const v = sign * (offset + dl + pad); | ||
let dx = 0, | ||
dy = 0; | ||
dy = 0; | ||
view.dirty(title); | ||
@@ -500,16 +471,14 @@ isYAxis ? dx = (title.x || 0) - (title.x = v) : dy = (title.y || 0) - (title.y = v); | ||
} | ||
bounds.union(b); | ||
} | ||
// aggregation functions for grid margin determination | ||
const min = (a, b) => Math.floor(Math.min(a, b)); | ||
const max = (a, b) => Math.ceil(Math.max(a, b)); | ||
function gridLayoutGroups(group) { | ||
var groups = group.items, | ||
n = groups.length, | ||
i = 0, | ||
mark, | ||
items; | ||
n = groups.length, | ||
i = 0, | ||
mark, | ||
items; | ||
const views = { | ||
@@ -523,8 +492,8 @@ marks: [], | ||
coltitle: null | ||
}; // layout axes, gather legends, collect bounds | ||
}; | ||
// layout axes, gather legends, collect bounds | ||
for (; i < n; ++i) { | ||
mark = groups[i]; | ||
items = mark.items; | ||
if (mark.marktype === Group) { | ||
@@ -536,27 +505,20 @@ switch (mark.role) { | ||
break; | ||
case RowHeader: | ||
views.rowheaders.push(...items); | ||
break; | ||
case RowFooter: | ||
views.rowfooters.push(...items); | ||
break; | ||
case ColHeader: | ||
views.colheaders.push(...items); | ||
break; | ||
case ColFooter: | ||
views.colfooters.push(...items); | ||
break; | ||
case RowTitle: | ||
views.rowtitle = items[0]; | ||
break; | ||
case ColTitle: | ||
views.coltitle = items[0]; | ||
break; | ||
default: | ||
@@ -567,10 +529,7 @@ views.marks.push(...items); | ||
} | ||
return views; | ||
} | ||
function bboxFlush(item) { | ||
return new vegaScenegraph.Bounds().set(0, 0, item.width || 0, item.height || 0); | ||
} | ||
function bboxFull(item) { | ||
@@ -580,3 +539,2 @@ const b = item.bounds.clone(); | ||
} | ||
function get(opt, key, d) { | ||
@@ -586,44 +544,40 @@ const v = vegaUtil.isObject(opt) ? opt[key] : opt; | ||
} | ||
function offsetValue(v) { | ||
return v < 0 ? Math.ceil(-v) : 0; | ||
} | ||
function gridLayout(view, groups, opt) { | ||
var dirty = !opt.nodirty, | ||
bbox = opt.bounds === Flush ? bboxFlush : bboxFull, | ||
bounds = tempBounds.set(0, 0, 0, 0), | ||
alignCol = get(opt.align, Column), | ||
alignRow = get(opt.align, Row), | ||
padCol = get(opt.padding, Column), | ||
padRow = get(opt.padding, Row), | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
n = groups.length, | ||
xOffset = Array(n), | ||
xExtent = Array(ncols), | ||
xMax = 0, | ||
yOffset = Array(n), | ||
yExtent = Array(nrows), | ||
yMax = 0, | ||
dx = Array(n), | ||
dy = Array(n), | ||
boxes = Array(n), | ||
m, | ||
i, | ||
c, | ||
r, | ||
b, | ||
g, | ||
px, | ||
py, | ||
x, | ||
y, | ||
offset; | ||
bbox = opt.bounds === Flush ? bboxFlush : bboxFull, | ||
bounds = tempBounds.set(0, 0, 0, 0), | ||
alignCol = get(opt.align, Column), | ||
alignRow = get(opt.align, Row), | ||
padCol = get(opt.padding, Column), | ||
padRow = get(opt.padding, Row), | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
n = groups.length, | ||
xOffset = Array(n), | ||
xExtent = Array(ncols), | ||
xMax = 0, | ||
yOffset = Array(n), | ||
yExtent = Array(nrows), | ||
yMax = 0, | ||
dx = Array(n), | ||
dy = Array(n), | ||
boxes = Array(n), | ||
m, | ||
i, | ||
c, | ||
r, | ||
b, | ||
g, | ||
px, | ||
py, | ||
x, | ||
y, | ||
offset; | ||
for (i = 0; i < ncols; ++i) xExtent[i] = 0; | ||
for (i = 0; i < nrows; ++i) yExtent[i] = 0; | ||
for (i = 0; i < nrows; ++i) yExtent[i] = 0; // determine offsets for each group | ||
// determine offsets for each group | ||
for (i = 0; i < n; ++i) { | ||
@@ -645,11 +599,11 @@ g = groups[i]; | ||
if (dirty) view.dirty(groups[i]); | ||
} // set initial alignment offsets | ||
} | ||
// set initial alignment offsets | ||
for (i = 0; i < n; ++i) { | ||
if (i % ncols === 0) xOffset[i] = 0; | ||
if (i < ncols) yOffset[i] = 0; | ||
} // enforce column alignment constraints | ||
} | ||
// enforce column alignment constraints | ||
if (alignCol === Each) { | ||
@@ -660,3 +614,2 @@ for (c = 1; c < ncols; ++c) { | ||
} | ||
for (i = c; i < n; i += ncols) { | ||
@@ -670,3 +623,2 @@ xOffset[i] = offset + xExtent[c - 1]; | ||
} | ||
for (i = 0; i < n; ++i) { | ||
@@ -681,5 +633,5 @@ if (i % ncols) xOffset[i] = offset + xMax; | ||
} | ||
} // enforce row alignment constraints | ||
} | ||
// enforce row alignment constraints | ||
if (alignRow === Each) { | ||
@@ -690,3 +642,2 @@ for (r = 1; r < nrows; ++r) { | ||
} | ||
for (i = r * ncols; i < m; ++i) { | ||
@@ -700,3 +651,2 @@ yOffset[i] = offset + yExtent[r - 1]; | ||
} | ||
for (i = ncols; i < n; ++i) { | ||
@@ -711,11 +661,11 @@ yOffset[i] = offset + yMax; | ||
} | ||
} // perform horizontal grid layout | ||
} | ||
// perform horizontal grid layout | ||
for (x = 0, i = 0; i < n; ++i) { | ||
x = xOffset[i] + (i % ncols ? x : 0); | ||
dx[i] += x - groups[i].x; | ||
} // perform vertical grid layout | ||
} | ||
// perform vertical grid layout | ||
for (c = 0; c < ncols; ++c) { | ||
@@ -726,5 +676,5 @@ for (y = 0, i = c; i < n; i += ncols) { | ||
} | ||
} // perform horizontal centering | ||
} | ||
// perform horizontal centering | ||
if (alignCol && get(opt.center, Column) && nrows > 1) { | ||
@@ -736,5 +686,5 @@ for (i = 0; i < n; ++i) { | ||
} | ||
} // perform vertical centering | ||
} | ||
// perform vertical centering | ||
if (alignRow && get(opt.center, Row) && ncols !== 1) { | ||
@@ -746,12 +696,10 @@ for (i = 0; i < n; ++i) { | ||
} | ||
} // position grid relative to anchor | ||
} | ||
// position grid relative to anchor | ||
for (i = 0; i < n; ++i) { | ||
bounds.union(boxes[i].translate(dx[i], dy[i])); | ||
} | ||
x = get(opt.anchor, X); | ||
y = get(opt.anchor, Y); | ||
switch (get(opt.anchor, Column)) { | ||
@@ -761,7 +709,5 @@ case End: | ||
break; | ||
case Middle: | ||
x -= bounds.width() / 2; | ||
} | ||
switch (get(opt.anchor, Row)) { | ||
@@ -771,16 +717,13 @@ case End: | ||
break; | ||
case Middle: | ||
y -= bounds.height() / 2; | ||
} | ||
x = Math.round(x); | ||
y = Math.round(y); // update mark positions, bounds, dirty | ||
y = Math.round(y); | ||
// update mark positions, bounds, dirty | ||
bounds.clear(); | ||
for (i = 0; i < n; ++i) { | ||
groups[i].mark.bounds.clear(); | ||
} | ||
for (i = 0; i < n; ++i) { | ||
@@ -793,3 +736,2 @@ g = groups[i]; | ||
} | ||
return bounds; | ||
@@ -799,45 +741,47 @@ } | ||
var views = gridLayoutGroups(group), | ||
groups = views.marks, | ||
bbox = opt.bounds === Flush ? boundFlush : boundFull, | ||
off = opt.offset, | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
cells = nrows * ncols, | ||
x, | ||
y, | ||
x2, | ||
y2, | ||
anchor, | ||
band, | ||
offset; // -- initial grid layout | ||
groups = views.marks, | ||
bbox = opt.bounds === Flush ? boundFlush : boundFull, | ||
off = opt.offset, | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
cells = nrows * ncols, | ||
x, | ||
y, | ||
x2, | ||
y2, | ||
anchor, | ||
band, | ||
offset; | ||
// -- initial grid layout | ||
const bounds = gridLayout(view, groups, opt); | ||
if (bounds.empty()) bounds.set(0, 0, 0, 0); // empty grid | ||
// -- layout grid headers and footers -- | ||
// perform row header layout | ||
if (views.rowheaders) { | ||
band = get(opt.headerBand, Row, null); | ||
x = layoutHeaders(view, views.rowheaders, groups, ncols, nrows, -get(off, 'rowHeader'), min, 0, bbox, 'x1', 0, ncols, 1, band); | ||
} // perform column header layout | ||
} | ||
// perform column header layout | ||
if (views.colheaders) { | ||
band = get(opt.headerBand, Column, null); | ||
y = layoutHeaders(view, views.colheaders, groups, ncols, ncols, -get(off, 'columnHeader'), min, 1, bbox, 'y1', 0, 1, ncols, band); | ||
} // perform row footer layout | ||
} | ||
// perform row footer layout | ||
if (views.rowfooters) { | ||
band = get(opt.footerBand, Row, null); | ||
x2 = layoutHeaders(view, views.rowfooters, groups, ncols, nrows, get(off, 'rowFooter'), max, 0, bbox, 'x2', ncols - 1, ncols, 1, band); | ||
} // perform column footer layout | ||
} | ||
// perform column footer layout | ||
if (views.colfooters) { | ||
band = get(opt.footerBand, Column, null); | ||
y2 = layoutHeaders(view, views.colfooters, groups, ncols, ncols, get(off, 'columnFooter'), max, 1, bbox, 'y2', cells - ncols, 1, ncols, band); | ||
} // perform row title layout | ||
} | ||
// perform row title layout | ||
if (views.rowtitle) { | ||
@@ -849,5 +793,5 @@ anchor = get(opt.titleAnchor, Row); | ||
layoutTitle(view, views.rowtitle, offset, 0, bounds, band); | ||
} // perform column title layout | ||
} | ||
// perform column title layout | ||
if (views.coltitle) { | ||
@@ -861,56 +805,58 @@ anchor = get(opt.titleAnchor, Column); | ||
} | ||
function boundFlush(item, field) { | ||
return field === 'x1' ? item.x || 0 : field === 'y1' ? item.y || 0 : field === 'x2' ? (item.x || 0) + (item.width || 0) : field === 'y2' ? (item.y || 0) + (item.height || 0) : undefined; | ||
} | ||
function boundFull(item, field) { | ||
return item.bounds[field]; | ||
} | ||
function layoutHeaders(view, headers, groups, ncols, limit, offset, agg, isX, bound, bf, start, stride, back, band) { | ||
var n = groups.length, | ||
init = 0, | ||
edge = 0, | ||
i, | ||
j, | ||
k, | ||
m, | ||
b, | ||
h, | ||
g, | ||
x, | ||
y; // if no groups, early exit and return 0 | ||
init = 0, | ||
edge = 0, | ||
i, | ||
j, | ||
k, | ||
m, | ||
b, | ||
h, | ||
g, | ||
x, | ||
y; | ||
if (!n) return init; // compute margin | ||
// if no groups, early exit and return 0 | ||
if (!n) return init; | ||
// compute margin | ||
for (i = start; i < n; i += stride) { | ||
if (groups[i]) init = agg(init, bound(groups[i], bf)); | ||
} // if no headers, return margin calculation | ||
} | ||
// if no headers, return margin calculation | ||
if (!headers.length) return init; | ||
if (!headers.length) return init; // check if number of headers exceeds number of rows or columns | ||
// check if number of headers exceeds number of rows or columns | ||
if (headers.length > limit) { | ||
view.warn('Grid headers exceed limit: ' + limit); | ||
headers = headers.slice(0, limit); | ||
} // apply offset | ||
} | ||
// apply offset | ||
init += offset; | ||
init += offset; // clear mark bounds for all headers | ||
// clear mark bounds for all headers | ||
for (j = 0, m = headers.length; j < m; ++j) { | ||
view.dirty(headers[j]); | ||
headers[j].mark.bounds.clear(); | ||
} // layout each header | ||
} | ||
// layout each header | ||
for (i = start, j = 0, m = headers.length; j < m; ++j, i += stride) { | ||
h = headers[j]; | ||
b = h.mark.bounds; // search for nearest group to align to | ||
b = h.mark.bounds; | ||
// search for nearest group to align to | ||
// necessary if table has empty cells | ||
for (k = i; k >= 0 && (g = groups[k]) == null; k -= back); | ||
for (k = i; k >= 0 && (g = groups[k]) == null; k -= back); // assign coordinates and update bounds | ||
// assign coordinates and update bounds | ||
if (isX) { | ||
@@ -923,36 +869,38 @@ x = band == null ? g.x : Math.round(g.bounds.x1 + band * g.bounds.width()); | ||
} | ||
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 | ||
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 | ||
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 | ||
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 | ||
g.y = y; | ||
// queue title for redraw | ||
view.dirty(g); | ||
} | ||
function lookup$1(config, orient) { | ||
// utility for looking up legend layout configuration | ||
function lookup(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 | ||
} | ||
// if legends specify offset directly, use the maximum specified value | ||
function offsets(legends, value) { | ||
@@ -965,9 +913,7 @@ let max = -Infinity; | ||
} | ||
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 _ = lookup(config, orient), | ||
offset = offsets(g, _('offset', 0)), | ||
anchor = _('anchor', Start), | ||
mult = anchor === End ? 1 : anchor === Middle ? 0.5 : 0; | ||
const p = { | ||
@@ -981,3 +927,2 @@ align: Each, | ||
}; | ||
switch (orient) { | ||
@@ -992,3 +937,2 @@ case Left: | ||
break; | ||
case Right: | ||
@@ -1001,3 +945,2 @@ p.anchor = { | ||
break; | ||
case Top: | ||
@@ -1011,3 +954,2 @@ p.anchor = { | ||
break; | ||
case Bottom: | ||
@@ -1020,3 +962,2 @@ p.anchor = { | ||
break; | ||
case TopLeft: | ||
@@ -1028,3 +969,2 @@ p.anchor = { | ||
break; | ||
case TopRight: | ||
@@ -1037,3 +977,2 @@ p.anchor = { | ||
break; | ||
case BottomLeft: | ||
@@ -1046,3 +985,2 @@ p.anchor = { | ||
break; | ||
case BottomRight: | ||
@@ -1057,3 +995,2 @@ p.anchor = { | ||
} | ||
return p; | ||
@@ -1063,19 +1000,21 @@ } | ||
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 | ||
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 | ||
bounds.clear(); | ||
legendGroupLayout(view, item, item.items[0].items[0]); // aggregate bounds to determine size, and include origin | ||
// 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()) { | ||
@@ -1085,7 +1024,5 @@ w = Math.ceil(bounds.width() + w); | ||
} | ||
if (datum.type === Symbols) { | ||
legendEntryLayout(item.items[0].items[0].items[0].items); | ||
} | ||
if (orient !== None) { | ||
@@ -1095,3 +1032,2 @@ item.x = x = 0; | ||
} | ||
item.width = w; | ||
@@ -1103,7 +1039,7 @@ item.height = h; | ||
} | ||
function legendBounds(item, b) { | ||
// aggregate item bounds | ||
item.items.forEach(_ => b.union(_.bounds)); // anchor to legend origin | ||
item.items.forEach(_ => b.union(_.bounds)); | ||
// anchor to legend origin | ||
b.x1 = item.padding; | ||
@@ -1113,8 +1049,6 @@ b.y1 = item.padding; | ||
} | ||
function legendGroupLayout(view, item, entry) { | ||
var pad = item.padding, | ||
ex = pad - entry.x, | ||
ey = pad - entry.y; | ||
ex = pad - entry.x, | ||
ey = pad - entry.y; | ||
if (!item.datum.title) { | ||
@@ -1124,7 +1058,6 @@ if (ex || ey) translate(view, entry, ex, ey); | ||
var title = item.items[1].items[0], | ||
anchor = title.anchor, | ||
tpad = item.titlePadding || 0, | ||
tx = pad - title.x, | ||
ty = pad - title.y; | ||
anchor = title.anchor, | ||
tpad = item.titlePadding || 0, | ||
tx = pad - title.x, | ||
ty = pad - title.y; | ||
switch (title.orient) { | ||
@@ -1134,13 +1067,9 @@ case Left: | ||
break; | ||
case Right: | ||
case Bottom: | ||
break; | ||
default: | ||
ey += title.bounds.height() + tpad; | ||
} | ||
if (ex || ey) translate(view, entry, ex, ey); | ||
switch (title.orient) { | ||
@@ -1150,3 +1079,2 @@ case Left: | ||
break; | ||
case Right: | ||
@@ -1156,3 +1084,2 @@ tx += legendTitleOffset(item, entry, title, End, 0, 0) + tpad; | ||
break; | ||
case Bottom: | ||
@@ -1162,9 +1089,8 @@ tx += legendTitleOffset(item, entry, title, anchor, 0, 0); | ||
break; | ||
default: | ||
tx += legendTitleOffset(item, entry, title, anchor, 0, 0); | ||
} | ||
if (tx || ty) translate(view, title, tx, ty); | ||
if (tx || ty) translate(view, title, tx, ty); // translate legend if title pushes into negative coordinates | ||
// translate legend if title pushes into negative coordinates | ||
if ((tx = Math.round(title.bounds.x1 - pad)) < 0) { | ||
@@ -1176,14 +1102,12 @@ translate(view, entry, -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); | ||
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) { | ||
@@ -1196,3 +1120,2 @@ item.x += dx; | ||
} | ||
function legendEntryLayout(entries) { | ||
@@ -1203,4 +1126,5 @@ // get max widths for each column | ||
return w; | ||
}, {}); // set dimensions of legend entry groups | ||
}, {}); | ||
// set dimensions of legend entry groups | ||
entries.forEach(g => { | ||
@@ -1214,17 +1138,16 @@ g.width = widths[g.column]; | ||
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; | ||
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) { | ||
@@ -1235,5 +1158,3 @@ orient === Left ? (start = viewBounds.y2, end = viewBounds.y1) : orient === Right ? (start = viewBounds.y1, end = viewBounds.y2) : (start = viewBounds.x1, end = viewBounds.x2); | ||
} | ||
pos = anchor === Start ? start : anchor === End ? end : (start + end) / 2; | ||
if (subtitle && subtitle.text) { | ||
@@ -1246,7 +1167,5 @@ // position subtitle | ||
break; | ||
case Left: | ||
sx = title.bounds.width() + padding; | ||
break; | ||
case Right: | ||
@@ -1256,6 +1175,4 @@ sx = -title.bounds.width() - padding; | ||
} | ||
tempBounds.clear().union(subtitle.bounds); | ||
tempBounds.translate(sx - (subtitle.x || 0), sy - (subtitle.y || 0)); | ||
if (set(subtitle, 'x', sx) | set(subtitle, 'y', sy)) { | ||
@@ -1267,3 +1184,2 @@ view.dirty(subtitle); | ||
} | ||
tempBounds.clear().union(subtitle.bounds); | ||
@@ -1273,5 +1189,5 @@ } else { | ||
} | ||
tempBounds.union(title.bounds); | ||
tempBounds.union(title.bounds); // position title group | ||
// position title group | ||
switch (orient) { | ||
@@ -1282,3 +1198,2 @@ case Top: | ||
break; | ||
case Left: | ||
@@ -1288,3 +1203,2 @@ x = viewBounds.x1 - tempBounds.width() - offset; | ||
break; | ||
case Right: | ||
@@ -1294,3 +1208,2 @@ x = viewBounds.x2 + tempBounds.width() + offset; | ||
break; | ||
case Bottom: | ||
@@ -1300,3 +1213,2 @@ x = pos; | ||
break; | ||
default: | ||
@@ -1306,3 +1218,2 @@ x = group.x; | ||
} | ||
if (set(group, 'x', x) | set(group, 'y', y)) { | ||
@@ -1315,3 +1226,2 @@ tempBounds.translate(x, y); | ||
} | ||
return group.bounds; | ||
@@ -1327,3 +1237,2 @@ } | ||
*/ | ||
function ViewLayout(params) { | ||
@@ -1335,3 +1244,2 @@ vegaDataflow.Transform.call(this, null, params); | ||
const view = pulse.dataflow; | ||
_.mark.items.forEach(group => { | ||
@@ -1341,8 +1249,5 @@ if (_.layout) trellisLayout(view, group, _.layout); | ||
}); | ||
return shouldReflow(_.mark.group) ? pulse.reflow() : pulse; | ||
} | ||
}); | ||
function shouldReflow(group) { | ||
@@ -1356,21 +1261,20 @@ // We typically should reflow if layout is invoked (#2568), as child items | ||
} | ||
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 | ||
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 < n; ++i) { | ||
mark = items[i]; | ||
switch (mark.role) { | ||
@@ -1381,11 +1285,8 @@ case AxisRole: | ||
break; | ||
case TitleRole: | ||
title = mark; | ||
break; | ||
case LegendRole: | ||
legends.push(legendLayout(view, mark)); | ||
break; | ||
case FrameRole: | ||
@@ -1402,9 +1303,8 @@ case ScopeRole: | ||
break; | ||
default: | ||
viewBounds.union(mark.bounds); | ||
} | ||
} // layout legends, adjust viewBounds | ||
} | ||
// layout legends, adjust viewBounds | ||
if (legends.length) { | ||
@@ -1416,22 +1316,20 @@ // group legends by orient | ||
if (orient !== None) (l[orient] || (l[orient] = [])).push(item); | ||
}); // perform grid layout for each orient group | ||
}); | ||
// perform grid layout for each orient group | ||
for (const orient in l) { | ||
const g = l[orient]; | ||
gridLayout(view, g, legendParams(g, orient, _.legends, xBounds, yBounds, width, height)); | ||
} // update view bounds | ||
} | ||
// 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) { | ||
if (_.autosize && (_.autosize.type === Fit || _.autosize.type === FitX || _.autosize.type === FitY)) { | ||
// For autosize fit, incorporate the orthogonal dimension only. | ||
@@ -1445,3 +1343,2 @@ // Legends that overrun the chart area will then be clipped; | ||
break; | ||
case Top: | ||
@@ -1455,33 +1352,32 @@ case Bottom: | ||
}); | ||
} // combine bounding boxes | ||
} | ||
// combine bounding boxes | ||
viewBounds.union(xBounds).union(yBounds); | ||
viewBounds.union(xBounds).union(yBounds); // layout title, adjust bounds | ||
// layout title, adjust bounds | ||
if (title) { | ||
viewBounds.union(titleLayout(view, title, width, height, viewBounds)); | ||
} // override aggregated view bounds if content is clipped | ||
} | ||
// override aggregated view bounds if content is clipped | ||
if (group.clip) { | ||
viewBounds.set(0, 0, group.width || 0, group.height || 0); | ||
} // perform size adjustment | ||
} | ||
// perform size adjustment | ||
viewSizeLayout(view, group, viewBounds, _); | ||
} | ||
function viewSizeLayout(view, group, viewBounds, _) { | ||
const auto = _.autosize || {}, | ||
type = auto.type; | ||
type = auto.type; | ||
if (view._autosize < 1 || !type) return; | ||
let viewWidth = view._width, | ||
viewHeight = view._height, | ||
width = Math.max(0, group.width || 0), | ||
left = Math.max(0, Math.ceil(-viewBounds.x1)), | ||
height = Math.max(0, group.height || 0), | ||
top = Math.max(0, Math.ceil(-viewBounds.y1)); | ||
viewHeight = view._height, | ||
width = Math.max(0, group.width || 0), | ||
left = Math.max(0, Math.ceil(-viewBounds.x1)), | ||
height = Math.max(0, group.height || 0), | ||
top = Math.max(0, Math.ceil(-viewBounds.y1)); | ||
const right = Math.max(0, Math.ceil(viewBounds.x2 - width)), | ||
bottom = Math.max(0, Math.ceil(viewBounds.y2 - height)); | ||
bottom = Math.max(0, Math.ceil(viewBounds.y2 - height)); | ||
if (auto.contains === Padding) { | ||
@@ -1492,3 +1388,2 @@ const padding = view.padding(); | ||
} | ||
if (type === None) { | ||
@@ -1512,3 +1407,2 @@ left = 0; | ||
} | ||
view._resizeView(viewWidth, viewHeight, width, height, [left, top], auto.resize); | ||
@@ -1524,4 +1418,2 @@ } | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); | ||
})); |
@@ -1,2 +0,2 @@ | ||
this.vega=this.vega||{},this.vega.transforms=function(t,e,n,o){"use strict";const r="top",a="left",i="right",s="bottom",c="start",u="middle",d="end",l="group",h="axis",f="title",m="frame",y="scope",b="legend",x="row-header",g="row-footer",p="row-title",w="column-header",k="column-footer",M="column-title",v="padding",E="fit",T="fit-x",A="fit-y",_="none",z="all",B="each",D="flush",O="column",S="row";function L(t){e.Transform.call(this,null,t)}function j(t,e,n){return e(t.bounds.clear(),t,n)}o.inherits(L,e.Transform,{transform(t,e){const o=e.dataflow,r=t.mark,a=r.marktype,i=n.Marks[a],s=i.bound;let c,u=r.bounds;if(i.nested)r.items.length&&o.dirty(r.items[0]),u=j(r,s),r.items.forEach(t=>{t.bounds.clear().union(u)});else if(a===l||t.modified())switch(e.visit(e.MOD,t=>o.dirty(t)),u.clear(),r.items.forEach(t=>u.union(j(t,s))),r.role){case h:case b:case f:e.reflow()}else c=e.changed(e.REM),e.visit(e.ADD,t=>{u.union(j(t,s))}),e.visit(e.MOD,t=>{c=c||u.alignsWith(t.bounds),o.dirty(t),u.union(j(t,s))}),c&&(u.clear(),r.items.forEach(t=>u.union(t.bounds)));return n.boundClip(r),e.modifies("bounds")}});const I=":vega_identifier:";function q(t){e.Transform.call(this,0,t)}function C(t){e.Transform.call(this,null,t)}function F(t){e.Transform.call(this,null,t)}q.Definition={type:"Identifier",metadata:{modifies:!0},params:[{name:"as",type:"string",required:!0}]},o.inherits(q,e.Transform,{transform(t,e){const n=(r=e.dataflow)._signals[I]||(r._signals[I]=r.add(0)),o=t.as;var r;let a=n.value;return e.visit(e.ADD,t=>t[o]=t[o]||++a),n.set(this.value=a),e}}),o.inherits(C,e.Transform,{transform(t,e){let o=this.value;o||(o=e.dataflow.scenegraph().mark(t.markdef,function(t){const e=t.groups,n=t.parent;return e&&1===e.size?e.get(Object.keys(e.object)[0]):e&&n?e.lookup(n):null}(t),t.index),o.group.context=t.context,t.context.group||(t.context.group=o.group),o.source=this.source,o.clip=t.clip,o.interactive=t.interactive,this.value=o);const r=o.marktype===l?n.GroupItem:n.Item;return e.visit(e.ADD,t=>r.call(t,o)),(t.modified("clip")||t.modified("interactive"))&&(o.clip=t.clip,o.interactive=!!t.interactive,o.zdirty=!0,e.reflow()),o.items=e.source,e}});const G={parity:t=>t.filter((t,e)=>e%2?t.opacity=0:1),greedy:(t,e)=>{let n;return t.filter((t,o)=>o&&H(n.bounds,t.bounds,e)?t.opacity=0:(n=t,1))}},H=(t,e,n)=>n>Math.max(e.x1-t.x2,t.x1-e.x2,e.y1-t.y2,t.y1-e.y2),P=(t,e)=>{for(var n,o=1,r=t.length,a=t[0].bounds;o<r;a=n,++o)if(H(a,n=t[o].bounds,e))return!0},R=t=>{const e=t.bounds;return e.width()>1&&e.height()>1},U=t=>(t.forEach(t=>t.opacity=1),t),V=(t,e)=>t.reflow(e.modified()).modifies("opacity");function W(t){e.Transform.call(this,null,t)}o.inherits(F,e.Transform,{transform(t,e){const a=G[t.method]||G.parity,i=t.separation||0;let c,u,d=e.materialize(e.SOURCE).source;if(!d||!d.length)return;if(!t.method)return t.modified("method")&&(U(d),e=V(e,t)),e;if(d=d.filter(R),!d.length)return;if(t.sort&&(d=d.slice().sort(t.sort)),c=U(d),e=V(e,t),c.length>=3&&P(c,i)){do{c=a(c,i)}while(c.length>=3&&P(c,i));c.length<3&&!o.peek(d).opacity&&(c.length>1&&(o.peek(c).opacity=0),o.peek(d).opacity=1)}var l,h,f,m,y;t.boundScale&&t.boundTolerance>=0&&(l=t.boundScale,h=t.boundOrient,f=+t.boundTolerance,m=l.range(),y=new n.Bounds,h===r||h===s?y.set(m[0],-1/0,m[1],1/0):y.set(-1/0,m[0],1/0,m[1]),y.expand(f||1),u=t=>y.encloses(t.bounds),d.forEach(t=>{u(t)||(t.opacity=0)}));const b=c[0].mark.bounds.clear();return d.forEach(t=>{t.opacity&&b.union(t.bounds)}),e}}),o.inherits(W,e.Transform,{transform(t,e){const n=e.dataflow;if(e.visit(e.ALL,t=>n.dirty(t)),e.fields&&e.fields.zindex){const t=e.source&&e.source[0];t&&(t.mark.zdirty=!0)}}});const J=new n.Bounds;function K(t,e,n){return t[e]===n?0:(t[e]=n,1)}function N(t){var e=t.items[0].orient;return e===a||e===i}function Q(t,e,o,c){var u,d,l=e.items[0],h=l.datum,f=null!=l.translate?l.translate:.5,m=l.orient,y=function(t){let e=+t.grid;return[t.ticks?e++:-1,t.labels?e++:-1,e+ +t.domain]}(h),b=l.range,x=l.offset,g=l.position,p=l.minExtent,w=l.maxExtent,k=h.title&&l.items[y[2]].items[0],M=l.titlePadding,v=l.bounds,E=k&&n.multiLineOffset(k),T=0,A=0;switch(J.clear().union(v),v.clear(),(u=y[0])>-1&&v.union(l.items[u].bounds),(u=y[1])>-1&&v.union(l.items[u].bounds),m){case r:T=g||0,A=-x,d=Math.max(p,Math.min(w,-v.y1)),v.add(0,-d).add(b,0),k&&X(t,k,d,M,E,0,-1,v);break;case a:T=-x,A=g||0,d=Math.max(p,Math.min(w,-v.x1)),v.add(-d,0).add(0,b),k&&X(t,k,d,M,E,1,-1,v);break;case i:T=o+x,A=g||0,d=Math.max(p,Math.min(w,v.x2)),v.add(0,0).add(d,b),k&&X(t,k,d,M,E,1,1,v);break;case s:T=g||0,A=c+x,d=Math.max(p,Math.min(w,v.y2)),v.add(0,0).add(b,d),k&&X(t,k,d,M,0,0,1,v);break;default:T=l.x,A=l.y}return n.boundStroke(v.translate(T,A),l),K(l,"x",T+f)|K(l,"y",A+f)&&(l.bounds=J,t.dirty(l),l.bounds=v,t.dirty(l)),l.mark.bounds.clear().union(v)}function X(t,e,n,o,r,a,i,s){const c=e.bounds;if(e.auto){const s=i*(n+r+o);let u=0,d=0;t.dirty(e),a?u=(e.x||0)-(e.x=s):d=(e.y||0)-(e.y=s),e.mark.bounds.clear().union(c.translate(-u,-d)),t.dirty(e)}s.union(c)}const Y=(t,e)=>Math.floor(Math.min(t,e)),Z=(t,e)=>Math.ceil(Math.max(t,e));function $(t){return(new n.Bounds).set(0,0,t.width||0,t.height||0)}function tt(t){const e=t.bounds.clone();return e.empty()?e.set(0,0,0,0):e.translate(-(t.x||0),-(t.y||0))}function et(t,e,n){const r=o.isObject(t)?t[e]:t;return null!=r?r:void 0!==n?n:0}function nt(t){return t<0?Math.ceil(-t):0}function ot(t,e,n){var o,r,a,i,s,c,l,h,f,m,y,b=!n.nodirty,x=n.bounds===D?$:tt,g=J.set(0,0,0,0),p=et(n.align,O),w=et(n.align,S),k=et(n.padding,O),M=et(n.padding,S),v=n.columns||e.length,E=v<=0?1:Math.ceil(e.length/v),T=e.length,A=Array(T),_=Array(v),L=0,j=Array(T),I=Array(E),q=0,C=Array(T),F=Array(T),G=Array(T);for(r=0;r<v;++r)_[r]=0;for(r=0;r<E;++r)I[r]=0;for(r=0;r<T;++r)c=e[r],s=G[r]=x(c),c.x=c.x||0,C[r]=0,c.y=c.y||0,F[r]=0,a=r%v,i=~~(r/v),L=Math.max(L,l=Math.ceil(s.x2)),q=Math.max(q,h=Math.ceil(s.y2)),_[a]=Math.max(_[a],l),I[i]=Math.max(I[i],h),A[r]=k+nt(s.x1),j[r]=M+nt(s.y1),b&&t.dirty(e[r]);for(r=0;r<T;++r)r%v==0&&(A[r]=0),r<v&&(j[r]=0);if(p===B)for(a=1;a<v;++a){for(y=0,r=a;r<T;r+=v)y<A[r]&&(y=A[r]);for(r=a;r<T;r+=v)A[r]=y+_[a-1]}else if(p===z){for(y=0,r=0;r<T;++r)r%v&&y<A[r]&&(y=A[r]);for(r=0;r<T;++r)r%v&&(A[r]=y+L)}else for(p=!1,a=1;a<v;++a)for(r=a;r<T;r+=v)A[r]+=_[a-1];if(w===B)for(i=1;i<E;++i){for(y=0,o=(r=i*v)+v;r<o;++r)y<j[r]&&(y=j[r]);for(r=i*v;r<o;++r)j[r]=y+I[i-1]}else if(w===z){for(y=0,r=v;r<T;++r)y<j[r]&&(y=j[r]);for(r=v;r<T;++r)j[r]=y+q}else for(w=!1,i=1;i<E;++i)for(o=(r=i*v)+v;r<o;++r)j[r]+=I[i-1];for(f=0,r=0;r<T;++r)f=A[r]+(r%v?f:0),C[r]+=f-e[r].x;for(a=0;a<v;++a)for(m=0,r=a;r<T;r+=v)m+=j[r],F[r]+=m-e[r].y;if(p&&et(n.center,O)&&E>1)for(r=0;r<T;++r)(f=(s=p===z?L:_[r%v])-G[r].x2-e[r].x-C[r])>0&&(C[r]+=f/2);if(w&&et(n.center,S)&&1!==v)for(r=0;r<T;++r)(m=(s=w===z?q:I[~~(r/v)])-G[r].y2-e[r].y-F[r])>0&&(F[r]+=m/2);for(r=0;r<T;++r)g.union(G[r].translate(C[r],F[r]));switch(f=et(n.anchor,"x"),m=et(n.anchor,"y"),et(n.anchor,O)){case d:f-=g.width();break;case u:f-=g.width()/2}switch(et(n.anchor,S)){case d:m-=g.height();break;case u:m-=g.height()/2}for(f=Math.round(f),m=Math.round(m),g.clear(),r=0;r<T;++r)e[r].mark.bounds.clear();for(r=0;r<T;++r)(c=e[r]).x+=C[r]+=f,c.y+=F[r]+=m,g.union(c.mark.bounds.union(c.bounds.translate(C[r],F[r]))),b&&t.dirty(c);return g}function rt(t,e,n){var o,r,a,i,s,c,u,m=function(t){var e,n,o=t.items,r=o.length,a=0;const i={marks:[],rowheaders:[],rowfooters:[],colheaders:[],colfooters:[],rowtitle:null,coltitle:null};for(;a<r;++a)if(n=(e=o[a]).items,e.marktype===l)switch(e.role){case h:case b:case f:break;case x:i.rowheaders.push(...n);break;case g:i.rowfooters.push(...n);break;case w:i.colheaders.push(...n);break;case k:i.colfooters.push(...n);break;case p:i.rowtitle=n[0];break;case M:i.coltitle=n[0];break;default:i.marks.push(...n)}return i}(e),y=m.marks,v=n.bounds===D?at:it,E=n.offset,T=n.columns||y.length,A=T<=0?1:Math.ceil(y.length/T),_=A*T;const z=ot(t,y,n);z.empty()&&z.set(0,0,0,0),m.rowheaders&&(c=et(n.headerBand,S,null),o=st(t,m.rowheaders,y,T,A,-et(E,"rowHeader"),Y,0,v,"x1",0,T,1,c)),m.colheaders&&(c=et(n.headerBand,O,null),r=st(t,m.colheaders,y,T,T,-et(E,"columnHeader"),Y,1,v,"y1",0,1,T,c)),m.rowfooters&&(c=et(n.footerBand,S,null),a=st(t,m.rowfooters,y,T,A,et(E,"rowFooter"),Z,0,v,"x2",T-1,T,1,c)),m.colfooters&&(c=et(n.footerBand,O,null),i=st(t,m.colfooters,y,T,T,et(E,"columnFooter"),Z,1,v,"y2",_-T,1,T,c)),m.rowtitle&&(s=et(n.titleAnchor,S),u=et(E,"rowTitle"),u=s===d?a+u:o-u,c=et(n.titleBand,S,.5),ct(t,m.rowtitle,u,0,z,c)),m.coltitle&&(s=et(n.titleAnchor,O),u=et(E,"columnTitle"),u=s===d?i+u:r-u,c=et(n.titleBand,O,.5),ct(t,m.coltitle,u,1,z,c))}function at(t,e){return"x1"===e?t.x||0:"y1"===e?t.y||0:"x2"===e?(t.x||0)+(t.width||0):"y2"===e?(t.y||0)+(t.height||0):void 0}function it(t,e){return t.bounds[e]}function st(t,e,n,o,r,a,i,s,c,u,d,l,h,f){var m,y,b,x,g,p,w,k,M,v=n.length,E=0,T=0;if(!v)return E;for(m=d;m<v;m+=l)n[m]&&(E=i(E,c(n[m],u)));if(!e.length)return E;for(e.length>r&&(t.warn("Grid headers exceed limit: "+r),e=e.slice(0,r)),E+=a,y=0,x=e.length;y<x;++y)t.dirty(e[y]),e[y].mark.bounds.clear();for(m=d,y=0,x=e.length;y<x;++y,m+=l){for(g=(p=e[y]).mark.bounds,b=m;b>=0&&null==(w=n[b]);b-=h);s?(k=null==f?w.x:Math.round(w.bounds.x1+f*w.bounds.width()),M=E):(k=E,M=null==f?w.y:Math.round(w.bounds.y1+f*w.bounds.height())),g.union(p.bounds.translate(k-(p.x||0),M-(p.y||0))),p.x=k,p.y=M,t.dirty(p),T=i(T,g[u])}return T}function ct(t,e,n,o,r,a){if(e){t.dirty(e);var i=n,s=n;o?i=Math.round(r.x1+a*r.width()):s=Math.round(r.y1+a*r.height()),e.bounds.translate(i-(e.x||0),s-(e.y||0)),e.mark.bounds.clear().union(e.bounds),e.x=i,e.y=s,t.dirty(e)}}function ut(t,e,n,o,l,h,f){const m=function(t,e){const n=t[e]||{};return(e,o)=>null!=n[e]?n[e]:null!=t[e]?t[e]:o}(n,e),y=function(t,e){let n=-1/0;return t.forEach(t=>{null!=t.offset&&(n=Math.max(n,t.offset))}),n>-1/0?n:e}(t,m("offset",0)),b=m("anchor",c),x=b===d?1:b===u?.5:0,g={align:B,bounds:m("bounds",D),columns:"vertical"===m("direction")?1:t.length,padding:m("margin",8),center:m("center"),nodirty:!0};switch(e){case a:g.anchor={x:Math.floor(o.x1)-y,column:d,y:x*(f||o.height()+2*o.y1),row:b};break;case i:g.anchor={x:Math.ceil(o.x2)+y,y:x*(f||o.height()+2*o.y1),row:b};break;case r:g.anchor={y:Math.floor(l.y1)-y,row:d,x:x*(h||l.width()+2*l.x1),column:b};break;case s:g.anchor={y:Math.ceil(l.y2)+y,x:x*(h||l.width()+2*l.x1),column:b};break;case"top-left":g.anchor={x:y,y:y};break;case"top-right":g.anchor={x:h-y,y:y,column:d};break;case"bottom-left":g.anchor={x:y,y:f-y,row:d};break;case"bottom-right":g.anchor={x:h-y,y:f-y,column:d,row:d}}return g}function dt(t,e){var o,r,c=e.items[0],u=c.datum,l=c.orient,h=c.bounds,f=c.x,m=c.y;return c._bounds?c._bounds.clear().union(h):c._bounds=h.clone(),h.clear(),function(t,e,n){var o=e.padding,r=o-n.x,c=o-n.y;if(e.datum.title){var u=e.items[1].items[0],l=u.anchor,h=e.titlePadding||0,f=o-u.x,m=o-u.y;switch(u.orient){case a:r+=Math.ceil(u.bounds.width())+h;break;case i:case s:break;default:c+=u.bounds.height()+h}switch((r||c)&&ht(t,n,r,c),u.orient){case a:m+=lt(e,n,u,l,1,1);break;case i:f+=lt(e,n,u,d,0,0)+h,m+=lt(e,n,u,l,1,1);break;case s:f+=lt(e,n,u,l,0,0),m+=lt(e,n,u,d,-1,0,1)+h;break;default:f+=lt(e,n,u,l,0,0)}(f||m)&&ht(t,u,f,m),(f=Math.round(u.bounds.x1-o))<0&&(ht(t,n,-f,0),ht(t,u,-f,0))}else(r||c)&&ht(t,n,r,c)}(t,c,c.items[0].items[0]),h=function(t,e){return t.items.forEach(t=>e.union(t.bounds)),e.x1=t.padding,e.y1=t.padding,e}(c,h),o=2*c.padding,r=2*c.padding,h.empty()||(o=Math.ceil(h.width()+o),r=Math.ceil(h.height()+r)),"symbol"===u.type&&function(t){const e=t.reduce((t,e)=>(t[e.column]=Math.max(e.bounds.x2-e.x,t[e.column]||0),t),{});t.forEach(t=>{t.width=e[t.column],t.height=t.bounds.y2-t.y})}(c.items[0].items[0].items[0].items),l!==_&&(c.x=f=0,c.y=m=0),c.width=o,c.height=r,n.boundStroke(h.set(f,m,f+o,m+r),c),c.mark.bounds.clear().union(h),c}function lt(t,e,o,r,a,i,s){const u="symbol"!==t.datum.type,l=o.datum.vgrad,h=(!u||!i&&l||s?e:e.items[0]).bounds[a?"y2":"x2"]-t.padding,f=l&&i?h:0,m=l&&i?0:h,y=a<=0?0:n.multiLineOffset(o);return Math.round(r===c?f:r===d?m-y:.5*(h-y))}function ht(t,e,n,o){e.x+=n,e.y+=o,e.bounds.translate(n,o),e.mark.bounds.translate(n,o),t.dirty(e)}function ft(t){e.Transform.call(this,null,t)}return o.inherits(ft,e.Transform,{transform(t,e){const o=e.dataflow;return t.mark.items.forEach(e=>{t.layout&&rt(o,e,t.layout),function(t,e,o){var u,z,B,D,O,S=e.items,L=Math.max(0,e.width||0),j=Math.max(0,e.height||0),I=(new n.Bounds).set(0,0,L,j),q=I.clone(),C=I.clone(),F=[];for(D=0,O=S.length;D<O;++D)switch((z=S[D]).role){case h:(N(z)?q:C).union(Q(t,z,L,j));break;case f:u=z;break;case b:F.push(dt(t,z));break;case m:case y:case x:case g:case p:case w:case k:case M:q.union(z.bounds),C.union(z.bounds);break;default:I.union(z.bounds)}if(F.length){const e={};F.forEach(t=>{(B=t.orient||i)!==_&&(e[B]||(e[B]=[])).push(t)});for(const n in e){const r=e[n];ot(t,r,ut(r,n,o.legends,q,C,L,j))}F.forEach(e=>{const n=e.bounds;if(n.equals(e._bounds)||(e.bounds=e._bounds,t.dirty(e),e.bounds=n,t.dirty(e)),o.autosize&&o.autosize.type===E)switch(e.orient){case a:case i:I.add(n.x1,0).add(n.x2,0);break;case r:case s:I.add(0,n.y1).add(0,n.y2)}else I.union(n)})}I.union(q).union(C),u&&I.union(function(t,e,n,o,u){var h,f=e.items[0],m=f.frame,y=f.orient,b=f.anchor,x=f.offset,g=f.padding,p=f.items[0].items[0],w=f.items[1]&&f.items[1].items[0],k=y===a||y===i?o:n,M=0,v=0,E=0,T=0,A=0;if(m!==l?y===a?(M=u.y2,k=u.y1):y===i?(M=u.y1,k=u.y2):(M=u.x1,k=u.x2):y===a&&(M=o,k=0),h=b===c?M:b===d?k:(M+k)/2,w&&w.text){switch(y){case r:case s:A=p.bounds.height()+g;break;case a:T=p.bounds.width()+g;break;case i:T=-p.bounds.width()-g}J.clear().union(w.bounds),J.translate(T-(w.x||0),A-(w.y||0)),K(w,"x",T)|K(w,"y",A)&&(t.dirty(w),w.bounds.clear().union(J),w.mark.bounds.clear().union(J),t.dirty(w)),J.clear().union(w.bounds)}else J.clear();switch(J.union(p.bounds),y){case r:v=h,E=u.y1-J.height()-x;break;case a:v=u.x1-J.width()-x,E=h;break;case i:v=u.x2+J.width()+x,E=h;break;case s:v=h,E=u.y2+x;break;default:v=f.x,E=f.y}return K(f,"x",v)|K(f,"y",E)&&(J.translate(v,E),t.dirty(f),f.bounds.clear().union(J),e.bounds.clear().union(J),t.dirty(f)),f.bounds}(t,u,L,j,I));e.clip&&I.set(0,0,e.width||0,e.height||0);!function(t,e,n,o){const r=o.autosize||{},a=r.type;if(t._autosize<1||!a)return;let i=t._width,s=t._height,c=Math.max(0,e.width||0),u=Math.max(0,Math.ceil(-n.x1)),d=Math.max(0,e.height||0),l=Math.max(0,Math.ceil(-n.y1));const h=Math.max(0,Math.ceil(n.x2-c)),f=Math.max(0,Math.ceil(n.y2-d));if(r.contains===v){const e=t.padding();i-=e.left+e.right,s-=e.top+e.bottom}a===_?(u=0,l=0,c=i,d=s):a===E?(c=Math.max(0,i-u-h),d=Math.max(0,s-l-f)):a===T?(c=Math.max(0,i-u-h),s=d+l+f):a===A?(i=c+u+h,d=Math.max(0,s-l-f)):"pad"===a&&(i=c+u+h,s=d+l+f);t._resizeView(i,s,c,d,[u,l],r.resize)}(t,e,I,o)}(o,e,t)}),(u=t.mark.group)&&"legend-entry"!==u.mark.role?e.reflow():e;var u}}),t.bound=L,t.identifier=q,t.mark=C,t.overlap=F,t.render=W,t.viewlayout=ft,t}({},vega,vega,vega); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega-dataflow"),require("vega-scenegraph"),require("vega-util")):"function"==typeof define&&define.amd?define(["exports","vega-dataflow","vega-scenegraph","vega-util"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).vega=e.vega||{},e.vega.transforms={}),e.vega,e.vega,e.vega)}(this,(function(e,t,n,o){"use strict";const r="top",a="left",i="right",s="bottom",c="top-left",u="top-right",d="bottom-left",l="bottom-right",h="start",f="middle",m="end",y="x",b="y",x="group",g="axis",p="title",w="frame",k="scope",M="legend",v="row-header",T="row-footer",E="row-title",z="column-header",A="column-footer",_="column-title",B="padding",D="symbol",O="fit",q="fit-x",S="fit-y",j="pad",L="none",I="all",C="each",F="flush",G="column",H="row";function P(e){t.Transform.call(this,null,e)}function R(e,t,n){return t(e.bounds.clear(),e,n)}o.inherits(P,t.Transform,{transform(e,t){const o=t.dataflow,r=e.mark,a=r.marktype,i=n.Marks[a],s=i.bound;let c,u=r.bounds;if(i.nested)r.items.length&&o.dirty(r.items[0]),u=R(r,s),r.items.forEach((e=>{e.bounds.clear().union(u)}));else if(a===x||e.modified())switch(t.visit(t.MOD,(e=>o.dirty(e))),u.clear(),r.items.forEach((e=>u.union(R(e,s)))),r.role){case g:case M:case p:t.reflow()}else c=t.changed(t.REM),t.visit(t.ADD,(e=>{u.union(R(e,s))})),t.visit(t.MOD,(e=>{c=c||u.alignsWith(e.bounds),o.dirty(e),u.union(R(e,s))})),c&&(u.clear(),r.items.forEach((e=>u.union(e.bounds))));return n.boundClip(r),t.modifies("bounds")}});const U=":vega_identifier:";function V(e){t.Transform.call(this,0,e)}function W(e){t.Transform.call(this,null,e)}function J(e){t.Transform.call(this,null,e)}V.Definition={type:"Identifier",metadata:{modifies:!0},params:[{name:"as",type:"string",required:!0}]},o.inherits(V,t.Transform,{transform(e,t){const n=(r=t.dataflow)._signals[U]||(r._signals[U]=r.add(0)),o=e.as;var r;let a=n.value;return t.visit(t.ADD,(e=>e[o]=e[o]||++a)),n.set(this.value=a),t}}),o.inherits(W,t.Transform,{transform(e,t){let o=this.value;o||(o=t.dataflow.scenegraph().mark(e.markdef,function(e){const t=e.groups,n=e.parent;return t&&1===t.size?t.get(Object.keys(t.object)[0]):t&&n?t.lookup(n):null}(e),e.index),o.group.context=e.context,e.context.group||(e.context.group=o.group),o.source=this.source,o.clip=e.clip,o.interactive=e.interactive,this.value=o);const r=o.marktype===x?n.GroupItem:n.Item;return t.visit(t.ADD,(e=>r.call(e,o))),(e.modified("clip")||e.modified("interactive"))&&(o.clip=e.clip,o.interactive=!!e.interactive,o.zdirty=!0,t.reflow()),o.items=t.source,t}});const K={parity:e=>e.filter(((e,t)=>t%2?e.opacity=0:1)),greedy:(e,t)=>{let n;return e.filter(((e,o)=>o&&N(n.bounds,e.bounds,t)?e.opacity=0:(n=e,1)))}},N=(e,t,n)=>n>Math.max(t.x1-e.x2,e.x1-t.x2,t.y1-e.y2,e.y1-t.y2),Q=(e,t)=>{for(var n,o=1,r=e.length,a=e[0].bounds;o<r;a=n,++o)if(N(a,n=e[o].bounds,t))return!0},X=e=>{const t=e.bounds;return t.width()>1&&t.height()>1},Y=e=>(e.forEach((e=>e.opacity=1)),e),Z=(e,t)=>e.reflow(t.modified()).modifies("opacity");function $(e){t.Transform.call(this,null,e)}o.inherits(J,t.Transform,{transform(e,t){const a=K[e.method]||K.parity,i=e.separation||0;let c,u,d=t.materialize(t.SOURCE).source;if(!d||!d.length)return;if(!e.method)return e.modified("method")&&(Y(d),t=Z(t,e)),t;if(d=d.filter(X),!d.length)return;if(e.sort&&(d=d.slice().sort(e.sort)),c=Y(d),t=Z(t,e),c.length>=3&&Q(c,i)){do{c=a(c,i)}while(c.length>=3&&Q(c,i));c.length<3&&!o.peek(d).opacity&&(c.length>1&&(o.peek(c).opacity=0),o.peek(d).opacity=1)}var l,h,f,m,y;e.boundScale&&e.boundTolerance>=0&&(l=e.boundScale,h=e.boundOrient,f=+e.boundTolerance,m=l.range(),y=new n.Bounds,h===r||h===s?y.set(m[0],-1/0,m[1],1/0):y.set(-1/0,m[0],1/0,m[1]),y.expand(f||1),u=e=>y.encloses(e.bounds),d.forEach((e=>{u(e)||(e.opacity=0)})));const b=c[0].mark.bounds.clear();return d.forEach((e=>{e.opacity&&b.union(e.bounds)})),t}}),o.inherits($,t.Transform,{transform(e,t){const n=t.dataflow;if(t.visit(t.ALL,(e=>n.dirty(e))),t.fields&&t.fields.zindex){const e=t.source&&t.source[0];e&&(e.mark.zdirty=!0)}}});const ee=new n.Bounds;function te(e,t,n){return e[t]===n?0:(e[t]=n,1)}function ne(e){var t=e.items[0].orient;return t===a||t===i}function oe(e,t,o,c){var u,d,l=t.items[0],h=l.datum,f=null!=l.translate?l.translate:.5,m=l.orient,y=function(e){let t=+e.grid;return[e.ticks?t++:-1,e.labels?t++:-1,t+ +e.domain]}(h),b=l.range,x=l.offset,g=l.position,p=l.minExtent,w=l.maxExtent,k=h.title&&l.items[y[2]].items[0],M=l.titlePadding,v=l.bounds,T=k&&n.multiLineOffset(k),E=0,z=0;switch(ee.clear().union(v),v.clear(),(u=y[0])>-1&&v.union(l.items[u].bounds),(u=y[1])>-1&&v.union(l.items[u].bounds),m){case r:E=g||0,z=-x,d=Math.max(p,Math.min(w,-v.y1)),v.add(0,-d).add(b,0),k&&re(e,k,d,M,T,0,-1,v);break;case a:E=-x,z=g||0,d=Math.max(p,Math.min(w,-v.x1)),v.add(-d,0).add(0,b),k&&re(e,k,d,M,T,1,-1,v);break;case i:E=o+x,z=g||0,d=Math.max(p,Math.min(w,v.x2)),v.add(0,0).add(d,b),k&&re(e,k,d,M,T,1,1,v);break;case s:E=g||0,z=c+x,d=Math.max(p,Math.min(w,v.y2)),v.add(0,0).add(b,d),k&&re(e,k,d,M,0,0,1,v);break;default:E=l.x,z=l.y}return n.boundStroke(v.translate(E,z),l),te(l,"x",E+f)|te(l,"y",z+f)&&(l.bounds=ee,e.dirty(l),l.bounds=v,e.dirty(l)),l.mark.bounds.clear().union(v)}function re(e,t,n,o,r,a,i,s){const c=t.bounds;if(t.auto){const s=i*(n+r+o);let u=0,d=0;e.dirty(t),a?u=(t.x||0)-(t.x=s):d=(t.y||0)-(t.y=s),t.mark.bounds.clear().union(c.translate(-u,-d)),e.dirty(t)}s.union(c)}const ae=(e,t)=>Math.floor(Math.min(e,t)),ie=(e,t)=>Math.ceil(Math.max(e,t));function se(e){return(new n.Bounds).set(0,0,e.width||0,e.height||0)}function ce(e){const t=e.bounds.clone();return t.empty()?t.set(0,0,0,0):t.translate(-(e.x||0),-(e.y||0))}function ue(e,t,n){const r=o.isObject(e)?e[t]:e;return null!=r?r:void 0!==n?n:0}function de(e){return e<0?Math.ceil(-e):0}function le(e,t,n){var o,r,a,i,s,c,u,d,l,h,x,g=!n.nodirty,p=n.bounds===F?se:ce,w=ee.set(0,0,0,0),k=ue(n.align,G),M=ue(n.align,H),v=ue(n.padding,G),T=ue(n.padding,H),E=n.columns||t.length,z=E<=0?1:Math.ceil(t.length/E),A=t.length,_=Array(A),B=Array(E),D=0,O=Array(A),q=Array(z),S=0,j=Array(A),L=Array(A),P=Array(A);for(r=0;r<E;++r)B[r]=0;for(r=0;r<z;++r)q[r]=0;for(r=0;r<A;++r)c=t[r],s=P[r]=p(c),c.x=c.x||0,j[r]=0,c.y=c.y||0,L[r]=0,a=r%E,i=~~(r/E),D=Math.max(D,u=Math.ceil(s.x2)),S=Math.max(S,d=Math.ceil(s.y2)),B[a]=Math.max(B[a],u),q[i]=Math.max(q[i],d),_[r]=v+de(s.x1),O[r]=T+de(s.y1),g&&e.dirty(t[r]);for(r=0;r<A;++r)r%E==0&&(_[r]=0),r<E&&(O[r]=0);if(k===C)for(a=1;a<E;++a){for(x=0,r=a;r<A;r+=E)x<_[r]&&(x=_[r]);for(r=a;r<A;r+=E)_[r]=x+B[a-1]}else if(k===I){for(x=0,r=0;r<A;++r)r%E&&x<_[r]&&(x=_[r]);for(r=0;r<A;++r)r%E&&(_[r]=x+D)}else for(k=!1,a=1;a<E;++a)for(r=a;r<A;r+=E)_[r]+=B[a-1];if(M===C)for(i=1;i<z;++i){for(x=0,o=(r=i*E)+E;r<o;++r)x<O[r]&&(x=O[r]);for(r=i*E;r<o;++r)O[r]=x+q[i-1]}else if(M===I){for(x=0,r=E;r<A;++r)x<O[r]&&(x=O[r]);for(r=E;r<A;++r)O[r]=x+S}else for(M=!1,i=1;i<z;++i)for(o=(r=i*E)+E;r<o;++r)O[r]+=q[i-1];for(l=0,r=0;r<A;++r)l=_[r]+(r%E?l:0),j[r]+=l-t[r].x;for(a=0;a<E;++a)for(h=0,r=a;r<A;r+=E)h+=O[r],L[r]+=h-t[r].y;if(k&&ue(n.center,G)&&z>1)for(r=0;r<A;++r)(l=(s=k===I?D:B[r%E])-P[r].x2-t[r].x-j[r])>0&&(j[r]+=l/2);if(M&&ue(n.center,H)&&1!==E)for(r=0;r<A;++r)(h=(s=M===I?S:q[~~(r/E)])-P[r].y2-t[r].y-L[r])>0&&(L[r]+=h/2);for(r=0;r<A;++r)w.union(P[r].translate(j[r],L[r]));switch(l=ue(n.anchor,y),h=ue(n.anchor,b),ue(n.anchor,G)){case m:l-=w.width();break;case f:l-=w.width()/2}switch(ue(n.anchor,H)){case m:h-=w.height();break;case f:h-=w.height()/2}for(l=Math.round(l),h=Math.round(h),w.clear(),r=0;r<A;++r)t[r].mark.bounds.clear();for(r=0;r<A;++r)(c=t[r]).x+=j[r]+=l,c.y+=L[r]+=h,w.union(c.mark.bounds.union(c.bounds.translate(j[r],L[r]))),g&&e.dirty(c);return w}function he(e,t,n){var o,r,a,i,s,c,u,d=function(e){var t,n,o=e.items,r=o.length,a=0;const i={marks:[],rowheaders:[],rowfooters:[],colheaders:[],colfooters:[],rowtitle:null,coltitle:null};for(;a<r;++a)if(n=(t=o[a]).items,t.marktype===x)switch(t.role){case g:case M:case p:break;case v:i.rowheaders.push(...n);break;case T:i.rowfooters.push(...n);break;case z:i.colheaders.push(...n);break;case A:i.colfooters.push(...n);break;case E:i.rowtitle=n[0];break;case _:i.coltitle=n[0];break;default:i.marks.push(...n)}return i}(t),l=d.marks,h=n.bounds===F?fe:me,f=n.offset,y=n.columns||l.length,b=y<=0?1:Math.ceil(l.length/y),w=b*y;const k=le(e,l,n);k.empty()&&k.set(0,0,0,0),d.rowheaders&&(c=ue(n.headerBand,H,null),o=ye(e,d.rowheaders,l,y,b,-ue(f,"rowHeader"),ae,0,h,"x1",0,y,1,c)),d.colheaders&&(c=ue(n.headerBand,G,null),r=ye(e,d.colheaders,l,y,y,-ue(f,"columnHeader"),ae,1,h,"y1",0,1,y,c)),d.rowfooters&&(c=ue(n.footerBand,H,null),a=ye(e,d.rowfooters,l,y,b,ue(f,"rowFooter"),ie,0,h,"x2",y-1,y,1,c)),d.colfooters&&(c=ue(n.footerBand,G,null),i=ye(e,d.colfooters,l,y,y,ue(f,"columnFooter"),ie,1,h,"y2",w-y,1,y,c)),d.rowtitle&&(s=ue(n.titleAnchor,H),u=ue(f,"rowTitle"),u=s===m?a+u:o-u,c=ue(n.titleBand,H,.5),be(e,d.rowtitle,u,0,k,c)),d.coltitle&&(s=ue(n.titleAnchor,G),u=ue(f,"columnTitle"),u=s===m?i+u:r-u,c=ue(n.titleBand,G,.5),be(e,d.coltitle,u,1,k,c))}function fe(e,t){return"x1"===t?e.x||0:"y1"===t?e.y||0:"x2"===t?(e.x||0)+(e.width||0):"y2"===t?(e.y||0)+(e.height||0):void 0}function me(e,t){return e.bounds[t]}function ye(e,t,n,o,r,a,i,s,c,u,d,l,h,f){var m,y,b,x,g,p,w,k,M,v=n.length,T=0,E=0;if(!v)return T;for(m=d;m<v;m+=l)n[m]&&(T=i(T,c(n[m],u)));if(!t.length)return T;for(t.length>r&&(e.warn("Grid headers exceed limit: "+r),t=t.slice(0,r)),T+=a,y=0,x=t.length;y<x;++y)e.dirty(t[y]),t[y].mark.bounds.clear();for(m=d,y=0,x=t.length;y<x;++y,m+=l){for(g=(p=t[y]).mark.bounds,b=m;b>=0&&null==(w=n[b]);b-=h);s?(k=null==f?w.x:Math.round(w.bounds.x1+f*w.bounds.width()),M=T):(k=T,M=null==f?w.y:Math.round(w.bounds.y1+f*w.bounds.height())),g.union(p.bounds.translate(k-(p.x||0),M-(p.y||0))),p.x=k,p.y=M,e.dirty(p),E=i(E,g[u])}return E}function be(e,t,n,o,r,a){if(t){e.dirty(t);var i=n,s=n;o?i=Math.round(r.x1+a*r.width()):s=Math.round(r.y1+a*r.height()),t.bounds.translate(i-(t.x||0),s-(t.y||0)),t.mark.bounds.clear().union(t.bounds),t.x=i,t.y=s,e.dirty(t)}}function xe(e,t,n,o,y,b,x){const g=function(e,t){const n=e[t]||{};return(t,o)=>null!=n[t]?n[t]:null!=e[t]?e[t]:o}(n,t),p=function(e,t){let n=-1/0;return e.forEach((e=>{null!=e.offset&&(n=Math.max(n,e.offset))})),n>-1/0?n:t}(e,g("offset",0)),w=g("anchor",h),k=w===m?1:w===f?.5:0,M={align:C,bounds:g("bounds",F),columns:"vertical"===g("direction")?1:e.length,padding:g("margin",8),center:g("center"),nodirty:!0};switch(t){case a:M.anchor={x:Math.floor(o.x1)-p,column:m,y:k*(x||o.height()+2*o.y1),row:w};break;case i:M.anchor={x:Math.ceil(o.x2)+p,y:k*(x||o.height()+2*o.y1),row:w};break;case r:M.anchor={y:Math.floor(y.y1)-p,row:m,x:k*(b||y.width()+2*y.x1),column:w};break;case s:M.anchor={y:Math.ceil(y.y2)+p,x:k*(b||y.width()+2*y.x1),column:w};break;case c:M.anchor={x:p,y:p};break;case u:M.anchor={x:b-p,y:p,column:m};break;case d:M.anchor={x:p,y:x-p,row:m};break;case l:M.anchor={x:b-p,y:x-p,column:m,row:m}}return M}function ge(e,t){var o,r,c=t.items[0],u=c.datum,d=c.orient,l=c.bounds,h=c.x,f=c.y;return c._bounds?c._bounds.clear().union(l):c._bounds=l.clone(),l.clear(),function(e,t,n){var o=t.padding,r=o-n.x,c=o-n.y;if(t.datum.title){var u=t.items[1].items[0],d=u.anchor,l=t.titlePadding||0,h=o-u.x,f=o-u.y;switch(u.orient){case a:r+=Math.ceil(u.bounds.width())+l;break;case i:case s:break;default:c+=u.bounds.height()+l}switch((r||c)&&we(e,n,r,c),u.orient){case a:f+=pe(t,n,u,d,1,1);break;case i:h+=pe(t,n,u,m,0,0)+l,f+=pe(t,n,u,d,1,1);break;case s:h+=pe(t,n,u,d,0,0),f+=pe(t,n,u,m,-1,0,1)+l;break;default:h+=pe(t,n,u,d,0,0)}(h||f)&&we(e,u,h,f),(h=Math.round(u.bounds.x1-o))<0&&(we(e,n,-h,0),we(e,u,-h,0))}else(r||c)&&we(e,n,r,c)}(e,c,c.items[0].items[0]),l=function(e,t){return e.items.forEach((e=>t.union(e.bounds))),t.x1=e.padding,t.y1=e.padding,t}(c,l),o=2*c.padding,r=2*c.padding,l.empty()||(o=Math.ceil(l.width()+o),r=Math.ceil(l.height()+r)),u.type===D&&function(e){const t=e.reduce(((e,t)=>(e[t.column]=Math.max(t.bounds.x2-t.x,e[t.column]||0),e)),{});e.forEach((e=>{e.width=t[e.column],e.height=e.bounds.y2-e.y}))}(c.items[0].items[0].items[0].items),d!==L&&(c.x=h=0,c.y=f=0),c.width=o,c.height=r,n.boundStroke(l.set(h,f,h+o,f+r),c),c.mark.bounds.clear().union(l),c}function pe(e,t,o,r,a,i,s){const c="symbol"!==e.datum.type,u=o.datum.vgrad,d=(!c||!i&&u||s?t:t.items[0]).bounds[a?"y2":"x2"]-e.padding,l=u&&i?d:0,f=u&&i?0:d,y=a<=0?0:n.multiLineOffset(o);return Math.round(r===h?l:r===m?f-y:.5*(d-y))}function we(e,t,n,o){t.x+=n,t.y+=o,t.bounds.translate(n,o),t.mark.bounds.translate(n,o),e.dirty(t)}function ke(e){t.Transform.call(this,null,e)}o.inherits(ke,t.Transform,{transform(e,t){const o=t.dataflow;return e.mark.items.forEach((t=>{e.layout&&he(o,t,e.layout),function(e,t,o){var c,u,d,l,f,y=t.items,b=Math.max(0,t.width||0),D=Math.max(0,t.height||0),I=(new n.Bounds).set(0,0,b,D),C=I.clone(),F=I.clone(),G=[];for(l=0,f=y.length;l<f;++l)switch((u=y[l]).role){case g:(ne(u)?C:F).union(oe(e,u,b,D));break;case p:c=u;break;case M:G.push(ge(e,u));break;case w:case k:case v:case T:case E:case z:case A:case _:C.union(u.bounds),F.union(u.bounds);break;default:I.union(u.bounds)}if(G.length){const t={};G.forEach((e=>{(d=e.orient||i)!==L&&(t[d]||(t[d]=[])).push(e)}));for(const n in t){const r=t[n];le(e,r,xe(r,n,o.legends,C,F,b,D))}G.forEach((t=>{const n=t.bounds;if(n.equals(t._bounds)||(t.bounds=t._bounds,e.dirty(t),t.bounds=n,e.dirty(t)),!o.autosize||o.autosize.type!==O&&o.autosize.type!==q&&o.autosize.type!==S)I.union(n);else switch(t.orient){case a:case i:I.add(n.x1,0).add(n.x2,0);break;case r:case s:I.add(0,n.y1).add(0,n.y2)}}))}I.union(C).union(F),c&&I.union(function(e,t,n,o,c){var u,d=t.items[0],l=d.frame,f=d.orient,y=d.anchor,b=d.offset,g=d.padding,p=d.items[0].items[0],w=d.items[1]&&d.items[1].items[0],k=f===a||f===i?o:n,M=0,v=0,T=0,E=0,z=0;if(l!==x?f===a?(M=c.y2,k=c.y1):f===i?(M=c.y1,k=c.y2):(M=c.x1,k=c.x2):f===a&&(M=o,k=0),u=y===h?M:y===m?k:(M+k)/2,w&&w.text){switch(f){case r:case s:z=p.bounds.height()+g;break;case a:E=p.bounds.width()+g;break;case i:E=-p.bounds.width()-g}ee.clear().union(w.bounds),ee.translate(E-(w.x||0),z-(w.y||0)),te(w,"x",E)|te(w,"y",z)&&(e.dirty(w),w.bounds.clear().union(ee),w.mark.bounds.clear().union(ee),e.dirty(w)),ee.clear().union(w.bounds)}else ee.clear();switch(ee.union(p.bounds),f){case r:v=u,T=c.y1-ee.height()-b;break;case a:v=c.x1-ee.width()-b,T=u;break;case i:v=c.x2+ee.width()+b,T=u;break;case s:v=u,T=c.y2+b;break;default:v=d.x,T=d.y}return te(d,"x",v)|te(d,"y",T)&&(ee.translate(v,T),e.dirty(d),d.bounds.clear().union(ee),t.bounds.clear().union(ee),e.dirty(d)),d.bounds}(e,c,b,D,I));t.clip&&I.set(0,0,t.width||0,t.height||0);!function(e,t,n,o){const r=o.autosize||{},a=r.type;if(e._autosize<1||!a)return;let i=e._width,s=e._height,c=Math.max(0,t.width||0),u=Math.max(0,Math.ceil(-n.x1)),d=Math.max(0,t.height||0),l=Math.max(0,Math.ceil(-n.y1));const h=Math.max(0,Math.ceil(n.x2-c)),f=Math.max(0,Math.ceil(n.y2-d));if(r.contains===B){const t=e.padding();i-=t.left+t.right,s-=t.top+t.bottom}a===L?(u=0,l=0,c=i,d=s):a===O?(c=Math.max(0,i-u-h),d=Math.max(0,s-l-f)):a===q?(c=Math.max(0,i-u-h),s=d+l+f):a===S?(i=c+u+h,d=Math.max(0,s-l-f)):a===j&&(i=c+u+h,s=d+l+f);e._resizeView(i,s,c,d,[u,l],r.resize)}(e,t,I,o)}(o,t,e)})),(c=e.mark.group)&&"legend-entry"!==c.mark.role?t.reflow():t;var c}}),e.bound=P,e.identifier=V,e.mark=W,e.overlap=J,e.render=$,e.viewlayout=ke})); | ||
//# sourceMappingURL=vega-view-transforms.min.js.map |
@@ -49,3 +49,2 @@ import { Transform } from 'vega-dataflow'; | ||
*/ | ||
function Bound(params) { | ||
@@ -57,9 +56,8 @@ Transform.call(this, null, params); | ||
const view = pulse.dataflow, | ||
mark = _.mark, | ||
type = mark.marktype, | ||
entry = Marks[type], | ||
bound = entry.bound; | ||
mark = _.mark, | ||
type = mark.marktype, | ||
entry = Marks[type], | ||
bound = entry.bound; | ||
let markBounds = mark.bounds, | ||
rebound; | ||
rebound; | ||
if (entry.nested) { | ||
@@ -77,4 +75,5 @@ // multi-item marks have a single bounds instance | ||
markBounds.clear(); | ||
mark.items.forEach(item => markBounds.union(boundItem(item, bound))); // force reflow for axes/legends/titles to propagate any layout changes | ||
mark.items.forEach(item => markBounds.union(boundItem(item, bound))); | ||
// force reflow for axes/legends/titles to propagate any layout changes | ||
switch (mark.role) { | ||
@@ -97,3 +96,2 @@ case AxisRole: | ||
}); | ||
if (rebound) { | ||
@@ -103,11 +101,9 @@ markBounds.clear(); | ||
} | ||
} // ensure mark bounds do not exceed any clipping region | ||
} | ||
// ensure mark bounds do not exceed any clipping region | ||
boundClip(mark); | ||
return pulse.modifies('bounds'); | ||
} | ||
}); | ||
function boundItem(item, bound, opt) { | ||
@@ -118,2 +114,3 @@ return bound(item.bounds.clear(), item, opt); | ||
const COUNTER_NAME = ':vega_identifier:'; | ||
/** | ||
@@ -130,3 +127,2 @@ * Adds a unique identifier to all added tuples. | ||
*/ | ||
function Identifier(params) { | ||
@@ -149,3 +145,3 @@ Transform.call(this, 0, params); | ||
const counter = getCounter(pulse.dataflow), | ||
as = _.as; | ||
as = _.as; | ||
let id = counter.value; | ||
@@ -156,5 +152,3 @@ pulse.visit(pulse.ADD, t => t[as] = t[as] || ++id); | ||
} | ||
}); | ||
function getCounter(view) { | ||
@@ -172,3 +166,2 @@ return view._signals[COUNTER_NAME] || (view._signals[COUNTER_NAME] = view.add(0)); | ||
*/ | ||
function Mark(params) { | ||
@@ -179,19 +172,20 @@ Transform.call(this, null, params); | ||
transform(_, pulse) { | ||
let mark = this.value; // acquire mark on first invocation, bind context and group | ||
let mark = this.value; | ||
// acquire mark on first invocation, bind context and group | ||
if (!mark) { | ||
mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup(_), _.index); | ||
mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup$1(_), _.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 | ||
} | ||
// initialize entering items | ||
const Init = mark.marktype === Group ? GroupItem : Item; | ||
pulse.visit(pulse.ADD, item => Init.call(item, mark)); // update clipping and/or interactive status | ||
pulse.visit(pulse.ADD, item => Init.call(item, mark)); | ||
// update clipping and/or interactive status | ||
if (_.modified('clip') || _.modified('interactive')) { | ||
@@ -201,16 +195,13 @@ mark.clip = _.clip; | ||
mark.zdirty = true; // force scenegraph re-eval | ||
pulse.reflow(); | ||
} // bind items array to scenegraph mark | ||
} | ||
// bind items array to scenegraph mark | ||
mark.items = pulse.source; | ||
return pulse; | ||
} | ||
}); | ||
function lookup(_) { | ||
function lookup$1(_) { | ||
const g = _.groups, | ||
p = _.parent; | ||
p = _.parent; | ||
return g && g.size === 1 ? g.get(Object.keys(g.object)[0]) : g && p ? g.lookup(p) : null; | ||
@@ -242,3 +233,2 @@ } | ||
*/ | ||
function Overlap(params) { | ||
@@ -253,7 +243,7 @@ Transform.call(this, null, params); | ||
} | ||
}; // compute bounding box intersection | ||
}; | ||
// compute bounding box intersection | ||
// including padding pixels of separation | ||
const intersect = (a, b, sep) => sep > Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2); | ||
const hasOverlap = (items, pad) => { | ||
@@ -264,3 +254,2 @@ for (var i = 1, n = items.length, a = items[0].bounds, b; i < n; a = b, ++i) { | ||
}; | ||
const hasBounds = item => { | ||
@@ -270,7 +259,5 @@ const b = item.bounds; | ||
}; | ||
const boundTest = (scale, orient, tolerance) => { | ||
var range = scale.range(), | ||
b = new Bounds(); | ||
b = new Bounds(); | ||
if (orient === Top || orient === Bottom) { | ||
@@ -281,26 +268,23 @@ b.set(range[0], -Infinity, range[1], +Infinity); | ||
} | ||
b.expand(tolerance || 1); | ||
return item => b.encloses(item.bounds); | ||
}; // reset all items to be fully opaque | ||
}; | ||
// reset all items to be fully opaque | ||
const reset = source => { | ||
source.forEach(item => item.opacity = 1); | ||
return source; | ||
}; // add all tuples to mod, fork pulse if parameters were modified | ||
}; | ||
// add all tuples to mod, fork pulse if parameters were modified | ||
// fork prevents cross-stream tuple pollution (e.g., pulse from scale) | ||
const reflow = (pulse, _) => pulse.reflow(_.modified()).modifies('opacity'); | ||
inherits(Overlap, Transform, { | ||
transform(_, pulse) { | ||
const reduce = methods[_.method] || methods.parity, | ||
sep = _.separation || 0; | ||
sep = _.separation || 0; | ||
let source = pulse.materialize(pulse.SOURCE).source, | ||
items, | ||
test; | ||
items, | ||
test; | ||
if (!source || !source.length) return; | ||
if (!_.method) { | ||
@@ -312,18 +296,15 @@ // early exit if method is falsy | ||
} | ||
return pulse; | ||
} // skip labels with no content | ||
} | ||
// skip labels with no content | ||
source = source.filter(hasBounds); | ||
source = source.filter(hasBounds); // early exit, nothing to do | ||
// early exit, nothing to do | ||
if (!source.length) return; | ||
if (_.sort) { | ||
source = source.slice().sort(_.sort); | ||
} | ||
items = reset(source); | ||
pulse = reflow(pulse, _); | ||
if (items.length >= 3 && hasOverlap(items, sep)) { | ||
@@ -333,3 +314,2 @@ do { | ||
} while (items.length >= 3 && hasOverlap(items, sep)); | ||
if (items.length < 3 && !peek(source).opacity) { | ||
@@ -340,3 +320,2 @@ if (items.length > 1) peek(items).opacity = 0; | ||
} | ||
if (_.boundScale && _.boundTolerance >= 0) { | ||
@@ -347,5 +326,5 @@ test = boundTest(_.boundScale, _.boundOrient, +_.boundTolerance); | ||
}); | ||
} // re-calculate mark bounds | ||
} | ||
// re-calculate mark bounds | ||
const bounds = items[0].mark.bounds.clear(); | ||
@@ -357,3 +336,2 @@ source.forEach(item => { | ||
} | ||
}); | ||
@@ -365,3 +343,2 @@ | ||
*/ | ||
function Render(params) { | ||
@@ -373,4 +350,5 @@ Transform.call(this, null, params); | ||
const view = pulse.dataflow; | ||
pulse.visit(pulse.ALL, item => view.dirty(item)); // set z-index dirty flag as needed | ||
pulse.visit(pulse.ALL, item => view.dirty(item)); | ||
// set z-index dirty flag as needed | ||
if (pulse.fields && pulse.fields['zindex']) { | ||
@@ -381,3 +359,2 @@ const item = pulse.source && pulse.source[0]; | ||
} | ||
}); | ||
@@ -394,7 +371,8 @@ | ||
} | ||
function axisIndices(datum) { | ||
let index = +datum.grid; | ||
return [datum.ticks ? index++ : -1, // ticks index | ||
datum.labels ? index++ : -1, // labels index | ||
return [datum.ticks ? index++ : -1, | ||
// ticks index | ||
datum.labels ? index++ : -1, | ||
// labels index | ||
index + +datum.domain // title index | ||
@@ -406,24 +384,25 @@ ]; | ||
var item = axis.items[0], | ||
datum = item.datum, | ||
delta = item.translate != null ? item.translate : 0.5, | ||
orient = item.orient, | ||
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 && multiLineOffset(title), | ||
x = 0, | ||
y = 0, | ||
i, | ||
s; | ||
datum = item.datum, | ||
delta = item.translate != null ? item.translate : 0.5, | ||
orient = item.orient, | ||
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 && 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 | ||
if ((i = indices[1]) > -1) bounds.union(item.items[i].bounds); | ||
// position axis group and title | ||
switch (orient) { | ||
@@ -437,3 +416,2 @@ case Top: | ||
break; | ||
case Left: | ||
@@ -446,3 +424,2 @@ x = -offset; | ||
break; | ||
case Right: | ||
@@ -455,3 +432,2 @@ x = width + offset; | ||
break; | ||
case Bottom: | ||
@@ -464,11 +440,9 @@ x = position || 0; | ||
break; | ||
default: | ||
x = item.x; | ||
y = item.y; | ||
} // update bounds | ||
} | ||
// update bounds | ||
boundStroke(bounds.translate(x, y), item); | ||
if (set(item, 'x', x + delta) | set(item, 'y', y + delta)) { | ||
@@ -480,13 +454,10 @@ item.bounds = tempBounds; | ||
} | ||
return item.mark.bounds.clear().union(bounds); | ||
} | ||
function axisTitleLayout(view, title, offset, pad, dl, isYAxis, sign, bounds) { | ||
const b = title.bounds; | ||
if (title.auto) { | ||
const v = sign * (offset + dl + pad); | ||
let dx = 0, | ||
dy = 0; | ||
dy = 0; | ||
view.dirty(title); | ||
@@ -497,16 +468,14 @@ isYAxis ? dx = (title.x || 0) - (title.x = v) : dy = (title.y || 0) - (title.y = v); | ||
} | ||
bounds.union(b); | ||
} | ||
// aggregation functions for grid margin determination | ||
const min = (a, b) => Math.floor(Math.min(a, b)); | ||
const max = (a, b) => Math.ceil(Math.max(a, b)); | ||
function gridLayoutGroups(group) { | ||
var groups = group.items, | ||
n = groups.length, | ||
i = 0, | ||
mark, | ||
items; | ||
n = groups.length, | ||
i = 0, | ||
mark, | ||
items; | ||
const views = { | ||
@@ -520,8 +489,8 @@ marks: [], | ||
coltitle: null | ||
}; // layout axes, gather legends, collect bounds | ||
}; | ||
// layout axes, gather legends, collect bounds | ||
for (; i < n; ++i) { | ||
mark = groups[i]; | ||
items = mark.items; | ||
if (mark.marktype === Group) { | ||
@@ -533,27 +502,20 @@ switch (mark.role) { | ||
break; | ||
case RowHeader: | ||
views.rowheaders.push(...items); | ||
break; | ||
case RowFooter: | ||
views.rowfooters.push(...items); | ||
break; | ||
case ColHeader: | ||
views.colheaders.push(...items); | ||
break; | ||
case ColFooter: | ||
views.colfooters.push(...items); | ||
break; | ||
case RowTitle: | ||
views.rowtitle = items[0]; | ||
break; | ||
case ColTitle: | ||
views.coltitle = items[0]; | ||
break; | ||
default: | ||
@@ -564,10 +526,7 @@ views.marks.push(...items); | ||
} | ||
return views; | ||
} | ||
function bboxFlush(item) { | ||
return new Bounds().set(0, 0, item.width || 0, item.height || 0); | ||
} | ||
function bboxFull(item) { | ||
@@ -577,3 +536,2 @@ const b = item.bounds.clone(); | ||
} | ||
function get(opt, key, d) { | ||
@@ -583,44 +541,40 @@ const v = isObject(opt) ? opt[key] : opt; | ||
} | ||
function offsetValue(v) { | ||
return v < 0 ? Math.ceil(-v) : 0; | ||
} | ||
function gridLayout(view, groups, opt) { | ||
var dirty = !opt.nodirty, | ||
bbox = opt.bounds === Flush ? bboxFlush : bboxFull, | ||
bounds = tempBounds.set(0, 0, 0, 0), | ||
alignCol = get(opt.align, Column), | ||
alignRow = get(opt.align, Row), | ||
padCol = get(opt.padding, Column), | ||
padRow = get(opt.padding, Row), | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
n = groups.length, | ||
xOffset = Array(n), | ||
xExtent = Array(ncols), | ||
xMax = 0, | ||
yOffset = Array(n), | ||
yExtent = Array(nrows), | ||
yMax = 0, | ||
dx = Array(n), | ||
dy = Array(n), | ||
boxes = Array(n), | ||
m, | ||
i, | ||
c, | ||
r, | ||
b, | ||
g, | ||
px, | ||
py, | ||
x, | ||
y, | ||
offset; | ||
bbox = opt.bounds === Flush ? bboxFlush : bboxFull, | ||
bounds = tempBounds.set(0, 0, 0, 0), | ||
alignCol = get(opt.align, Column), | ||
alignRow = get(opt.align, Row), | ||
padCol = get(opt.padding, Column), | ||
padRow = get(opt.padding, Row), | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
n = groups.length, | ||
xOffset = Array(n), | ||
xExtent = Array(ncols), | ||
xMax = 0, | ||
yOffset = Array(n), | ||
yExtent = Array(nrows), | ||
yMax = 0, | ||
dx = Array(n), | ||
dy = Array(n), | ||
boxes = Array(n), | ||
m, | ||
i, | ||
c, | ||
r, | ||
b, | ||
g, | ||
px, | ||
py, | ||
x, | ||
y, | ||
offset; | ||
for (i = 0; i < ncols; ++i) xExtent[i] = 0; | ||
for (i = 0; i < nrows; ++i) yExtent[i] = 0; | ||
for (i = 0; i < nrows; ++i) yExtent[i] = 0; // determine offsets for each group | ||
// determine offsets for each group | ||
for (i = 0; i < n; ++i) { | ||
@@ -642,11 +596,11 @@ g = groups[i]; | ||
if (dirty) view.dirty(groups[i]); | ||
} // set initial alignment offsets | ||
} | ||
// set initial alignment offsets | ||
for (i = 0; i < n; ++i) { | ||
if (i % ncols === 0) xOffset[i] = 0; | ||
if (i < ncols) yOffset[i] = 0; | ||
} // enforce column alignment constraints | ||
} | ||
// enforce column alignment constraints | ||
if (alignCol === Each) { | ||
@@ -657,3 +611,2 @@ for (c = 1; c < ncols; ++c) { | ||
} | ||
for (i = c; i < n; i += ncols) { | ||
@@ -667,3 +620,2 @@ xOffset[i] = offset + xExtent[c - 1]; | ||
} | ||
for (i = 0; i < n; ++i) { | ||
@@ -678,5 +630,5 @@ if (i % ncols) xOffset[i] = offset + xMax; | ||
} | ||
} // enforce row alignment constraints | ||
} | ||
// enforce row alignment constraints | ||
if (alignRow === Each) { | ||
@@ -687,3 +639,2 @@ for (r = 1; r < nrows; ++r) { | ||
} | ||
for (i = r * ncols; i < m; ++i) { | ||
@@ -697,3 +648,2 @@ yOffset[i] = offset + yExtent[r - 1]; | ||
} | ||
for (i = ncols; i < n; ++i) { | ||
@@ -708,11 +658,11 @@ yOffset[i] = offset + yMax; | ||
} | ||
} // perform horizontal grid layout | ||
} | ||
// perform horizontal grid layout | ||
for (x = 0, i = 0; i < n; ++i) { | ||
x = xOffset[i] + (i % ncols ? x : 0); | ||
dx[i] += x - groups[i].x; | ||
} // perform vertical grid layout | ||
} | ||
// perform vertical grid layout | ||
for (c = 0; c < ncols; ++c) { | ||
@@ -723,5 +673,5 @@ for (y = 0, i = c; i < n; i += ncols) { | ||
} | ||
} // perform horizontal centering | ||
} | ||
// perform horizontal centering | ||
if (alignCol && get(opt.center, Column) && nrows > 1) { | ||
@@ -733,5 +683,5 @@ for (i = 0; i < n; ++i) { | ||
} | ||
} // perform vertical centering | ||
} | ||
// perform vertical centering | ||
if (alignRow && get(opt.center, Row) && ncols !== 1) { | ||
@@ -743,12 +693,10 @@ for (i = 0; i < n; ++i) { | ||
} | ||
} // position grid relative to anchor | ||
} | ||
// position grid relative to anchor | ||
for (i = 0; i < n; ++i) { | ||
bounds.union(boxes[i].translate(dx[i], dy[i])); | ||
} | ||
x = get(opt.anchor, X); | ||
y = get(opt.anchor, Y); | ||
switch (get(opt.anchor, Column)) { | ||
@@ -758,7 +706,5 @@ case End: | ||
break; | ||
case Middle: | ||
x -= bounds.width() / 2; | ||
} | ||
switch (get(opt.anchor, Row)) { | ||
@@ -768,16 +714,13 @@ case End: | ||
break; | ||
case Middle: | ||
y -= bounds.height() / 2; | ||
} | ||
x = Math.round(x); | ||
y = Math.round(y); // update mark positions, bounds, dirty | ||
y = Math.round(y); | ||
// update mark positions, bounds, dirty | ||
bounds.clear(); | ||
for (i = 0; i < n; ++i) { | ||
groups[i].mark.bounds.clear(); | ||
} | ||
for (i = 0; i < n; ++i) { | ||
@@ -790,3 +733,2 @@ g = groups[i]; | ||
} | ||
return bounds; | ||
@@ -796,45 +738,47 @@ } | ||
var views = gridLayoutGroups(group), | ||
groups = views.marks, | ||
bbox = opt.bounds === Flush ? boundFlush : boundFull, | ||
off = opt.offset, | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
cells = nrows * ncols, | ||
x, | ||
y, | ||
x2, | ||
y2, | ||
anchor, | ||
band, | ||
offset; // -- initial grid layout | ||
groups = views.marks, | ||
bbox = opt.bounds === Flush ? boundFlush : boundFull, | ||
off = opt.offset, | ||
ncols = opt.columns || groups.length, | ||
nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols), | ||
cells = nrows * ncols, | ||
x, | ||
y, | ||
x2, | ||
y2, | ||
anchor, | ||
band, | ||
offset; | ||
// -- initial grid layout | ||
const bounds = gridLayout(view, groups, opt); | ||
if (bounds.empty()) bounds.set(0, 0, 0, 0); // empty grid | ||
// -- layout grid headers and footers -- | ||
// perform row header layout | ||
if (views.rowheaders) { | ||
band = get(opt.headerBand, Row, null); | ||
x = layoutHeaders(view, views.rowheaders, groups, ncols, nrows, -get(off, 'rowHeader'), min, 0, bbox, 'x1', 0, ncols, 1, band); | ||
} // perform column header layout | ||
} | ||
// perform column header layout | ||
if (views.colheaders) { | ||
band = get(opt.headerBand, Column, null); | ||
y = layoutHeaders(view, views.colheaders, groups, ncols, ncols, -get(off, 'columnHeader'), min, 1, bbox, 'y1', 0, 1, ncols, band); | ||
} // perform row footer layout | ||
} | ||
// perform row footer layout | ||
if (views.rowfooters) { | ||
band = get(opt.footerBand, Row, null); | ||
x2 = layoutHeaders(view, views.rowfooters, groups, ncols, nrows, get(off, 'rowFooter'), max, 0, bbox, 'x2', ncols - 1, ncols, 1, band); | ||
} // perform column footer layout | ||
} | ||
// perform column footer layout | ||
if (views.colfooters) { | ||
band = get(opt.footerBand, Column, null); | ||
y2 = layoutHeaders(view, views.colfooters, groups, ncols, ncols, get(off, 'columnFooter'), max, 1, bbox, 'y2', cells - ncols, 1, ncols, band); | ||
} // perform row title layout | ||
} | ||
// perform row title layout | ||
if (views.rowtitle) { | ||
@@ -846,5 +790,5 @@ anchor = get(opt.titleAnchor, Row); | ||
layoutTitle(view, views.rowtitle, offset, 0, bounds, band); | ||
} // perform column title layout | ||
} | ||
// perform column title layout | ||
if (views.coltitle) { | ||
@@ -858,56 +802,58 @@ anchor = get(opt.titleAnchor, Column); | ||
} | ||
function boundFlush(item, field) { | ||
return field === 'x1' ? item.x || 0 : field === 'y1' ? item.y || 0 : field === 'x2' ? (item.x || 0) + (item.width || 0) : field === 'y2' ? (item.y || 0) + (item.height || 0) : undefined; | ||
} | ||
function boundFull(item, field) { | ||
return item.bounds[field]; | ||
} | ||
function layoutHeaders(view, headers, groups, ncols, limit, offset, agg, isX, bound, bf, start, stride, back, band) { | ||
var n = groups.length, | ||
init = 0, | ||
edge = 0, | ||
i, | ||
j, | ||
k, | ||
m, | ||
b, | ||
h, | ||
g, | ||
x, | ||
y; // if no groups, early exit and return 0 | ||
init = 0, | ||
edge = 0, | ||
i, | ||
j, | ||
k, | ||
m, | ||
b, | ||
h, | ||
g, | ||
x, | ||
y; | ||
if (!n) return init; // compute margin | ||
// if no groups, early exit and return 0 | ||
if (!n) return init; | ||
// compute margin | ||
for (i = start; i < n; i += stride) { | ||
if (groups[i]) init = agg(init, bound(groups[i], bf)); | ||
} // if no headers, return margin calculation | ||
} | ||
// if no headers, return margin calculation | ||
if (!headers.length) return init; | ||
if (!headers.length) return init; // check if number of headers exceeds number of rows or columns | ||
// check if number of headers exceeds number of rows or columns | ||
if (headers.length > limit) { | ||
view.warn('Grid headers exceed limit: ' + limit); | ||
headers = headers.slice(0, limit); | ||
} // apply offset | ||
} | ||
// apply offset | ||
init += offset; | ||
init += offset; // clear mark bounds for all headers | ||
// clear mark bounds for all headers | ||
for (j = 0, m = headers.length; j < m; ++j) { | ||
view.dirty(headers[j]); | ||
headers[j].mark.bounds.clear(); | ||
} // layout each header | ||
} | ||
// layout each header | ||
for (i = start, j = 0, m = headers.length; j < m; ++j, i += stride) { | ||
h = headers[j]; | ||
b = h.mark.bounds; // search for nearest group to align to | ||
b = h.mark.bounds; | ||
// search for nearest group to align to | ||
// necessary if table has empty cells | ||
for (k = i; k >= 0 && (g = groups[k]) == null; k -= back); | ||
for (k = i; k >= 0 && (g = groups[k]) == null; k -= back); // assign coordinates and update bounds | ||
// assign coordinates and update bounds | ||
if (isX) { | ||
@@ -920,36 +866,38 @@ x = band == null ? g.x : Math.round(g.bounds.x1 + band * g.bounds.width()); | ||
} | ||
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 | ||
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 | ||
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 | ||
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 | ||
g.y = y; | ||
// queue title for redraw | ||
view.dirty(g); | ||
} | ||
function lookup$1(config, orient) { | ||
// utility for looking up legend layout configuration | ||
function lookup(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 | ||
} | ||
// if legends specify offset directly, use the maximum specified value | ||
function offsets(legends, value) { | ||
@@ -962,9 +910,7 @@ let max = -Infinity; | ||
} | ||
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 _ = lookup(config, orient), | ||
offset = offsets(g, _('offset', 0)), | ||
anchor = _('anchor', Start), | ||
mult = anchor === End ? 1 : anchor === Middle ? 0.5 : 0; | ||
const p = { | ||
@@ -978,3 +924,2 @@ align: Each, | ||
}; | ||
switch (orient) { | ||
@@ -989,3 +934,2 @@ case Left: | ||
break; | ||
case Right: | ||
@@ -998,3 +942,2 @@ p.anchor = { | ||
break; | ||
case Top: | ||
@@ -1008,3 +951,2 @@ p.anchor = { | ||
break; | ||
case Bottom: | ||
@@ -1017,3 +959,2 @@ p.anchor = { | ||
break; | ||
case TopLeft: | ||
@@ -1025,3 +966,2 @@ p.anchor = { | ||
break; | ||
case TopRight: | ||
@@ -1034,3 +974,2 @@ p.anchor = { | ||
break; | ||
case BottomLeft: | ||
@@ -1043,3 +982,2 @@ p.anchor = { | ||
break; | ||
case BottomRight: | ||
@@ -1054,3 +992,2 @@ p.anchor = { | ||
} | ||
return p; | ||
@@ -1060,19 +997,21 @@ } | ||
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 | ||
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 | ||
bounds.clear(); | ||
legendGroupLayout(view, item, item.items[0].items[0]); // aggregate bounds to determine size, and include origin | ||
// 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()) { | ||
@@ -1082,7 +1021,5 @@ w = Math.ceil(bounds.width() + w); | ||
} | ||
if (datum.type === Symbols) { | ||
legendEntryLayout(item.items[0].items[0].items[0].items); | ||
} | ||
if (orient !== None) { | ||
@@ -1092,3 +1029,2 @@ item.x = x = 0; | ||
} | ||
item.width = w; | ||
@@ -1100,7 +1036,7 @@ item.height = h; | ||
} | ||
function legendBounds(item, b) { | ||
// aggregate item bounds | ||
item.items.forEach(_ => b.union(_.bounds)); // anchor to legend origin | ||
item.items.forEach(_ => b.union(_.bounds)); | ||
// anchor to legend origin | ||
b.x1 = item.padding; | ||
@@ -1110,8 +1046,6 @@ b.y1 = item.padding; | ||
} | ||
function legendGroupLayout(view, item, entry) { | ||
var pad = item.padding, | ||
ex = pad - entry.x, | ||
ey = pad - entry.y; | ||
ex = pad - entry.x, | ||
ey = pad - entry.y; | ||
if (!item.datum.title) { | ||
@@ -1121,7 +1055,6 @@ if (ex || ey) translate(view, entry, ex, ey); | ||
var title = item.items[1].items[0], | ||
anchor = title.anchor, | ||
tpad = item.titlePadding || 0, | ||
tx = pad - title.x, | ||
ty = pad - title.y; | ||
anchor = title.anchor, | ||
tpad = item.titlePadding || 0, | ||
tx = pad - title.x, | ||
ty = pad - title.y; | ||
switch (title.orient) { | ||
@@ -1131,13 +1064,9 @@ case Left: | ||
break; | ||
case Right: | ||
case Bottom: | ||
break; | ||
default: | ||
ey += title.bounds.height() + tpad; | ||
} | ||
if (ex || ey) translate(view, entry, ex, ey); | ||
switch (title.orient) { | ||
@@ -1147,3 +1076,2 @@ case Left: | ||
break; | ||
case Right: | ||
@@ -1153,3 +1081,2 @@ tx += legendTitleOffset(item, entry, title, End, 0, 0) + tpad; | ||
break; | ||
case Bottom: | ||
@@ -1159,9 +1086,8 @@ tx += legendTitleOffset(item, entry, title, anchor, 0, 0); | ||
break; | ||
default: | ||
tx += legendTitleOffset(item, entry, title, anchor, 0, 0); | ||
} | ||
if (tx || ty) translate(view, title, tx, ty); | ||
if (tx || ty) translate(view, title, tx, ty); // translate legend if title pushes into negative coordinates | ||
// translate legend if title pushes into negative coordinates | ||
if ((tx = Math.round(title.bounds.x1 - pad)) < 0) { | ||
@@ -1173,14 +1099,12 @@ translate(view, entry, -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 : multiLineOffset(title); | ||
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 : multiLineOffset(title); | ||
return Math.round(anchor === Start ? u : anchor === End ? v - o : 0.5 * (s - o)); | ||
} | ||
function translate(view, item, dx, dy) { | ||
@@ -1193,3 +1117,2 @@ item.x += dx; | ||
} | ||
function legendEntryLayout(entries) { | ||
@@ -1200,4 +1123,5 @@ // get max widths for each column | ||
return w; | ||
}, {}); // set dimensions of legend entry groups | ||
}, {}); | ||
// set dimensions of legend entry groups | ||
entries.forEach(g => { | ||
@@ -1211,17 +1135,16 @@ g.width = widths[g.column]; | ||
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; | ||
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) { | ||
@@ -1232,5 +1155,3 @@ orient === Left ? (start = viewBounds.y2, end = viewBounds.y1) : orient === Right ? (start = viewBounds.y1, end = viewBounds.y2) : (start = viewBounds.x1, end = viewBounds.x2); | ||
} | ||
pos = anchor === Start ? start : anchor === End ? end : (start + end) / 2; | ||
if (subtitle && subtitle.text) { | ||
@@ -1243,7 +1164,5 @@ // position subtitle | ||
break; | ||
case Left: | ||
sx = title.bounds.width() + padding; | ||
break; | ||
case Right: | ||
@@ -1253,6 +1172,4 @@ sx = -title.bounds.width() - padding; | ||
} | ||
tempBounds.clear().union(subtitle.bounds); | ||
tempBounds.translate(sx - (subtitle.x || 0), sy - (subtitle.y || 0)); | ||
if (set(subtitle, 'x', sx) | set(subtitle, 'y', sy)) { | ||
@@ -1264,3 +1181,2 @@ view.dirty(subtitle); | ||
} | ||
tempBounds.clear().union(subtitle.bounds); | ||
@@ -1270,5 +1186,5 @@ } else { | ||
} | ||
tempBounds.union(title.bounds); | ||
tempBounds.union(title.bounds); // position title group | ||
// position title group | ||
switch (orient) { | ||
@@ -1279,3 +1195,2 @@ case Top: | ||
break; | ||
case Left: | ||
@@ -1285,3 +1200,2 @@ x = viewBounds.x1 - tempBounds.width() - offset; | ||
break; | ||
case Right: | ||
@@ -1291,3 +1205,2 @@ x = viewBounds.x2 + tempBounds.width() + offset; | ||
break; | ||
case Bottom: | ||
@@ -1297,3 +1210,2 @@ x = pos; | ||
break; | ||
default: | ||
@@ -1303,3 +1215,2 @@ x = group.x; | ||
} | ||
if (set(group, 'x', x) | set(group, 'y', y)) { | ||
@@ -1312,3 +1223,2 @@ tempBounds.translate(x, y); | ||
} | ||
return group.bounds; | ||
@@ -1324,3 +1234,2 @@ } | ||
*/ | ||
function ViewLayout(params) { | ||
@@ -1332,3 +1241,2 @@ Transform.call(this, null, params); | ||
const view = pulse.dataflow; | ||
_.mark.items.forEach(group => { | ||
@@ -1338,8 +1246,5 @@ if (_.layout) trellisLayout(view, group, _.layout); | ||
}); | ||
return shouldReflow(_.mark.group) ? pulse.reflow() : pulse; | ||
} | ||
}); | ||
function shouldReflow(group) { | ||
@@ -1353,21 +1258,20 @@ // We typically should reflow if layout is invoked (#2568), as child items | ||
} | ||
function layoutGroup(view, group, _) { | ||
var items = group.items, | ||
width = Math.max(0, group.width || 0), | ||
height = Math.max(0, group.height || 0), | ||
viewBounds = new 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 | ||
width = Math.max(0, group.width || 0), | ||
height = Math.max(0, group.height || 0), | ||
viewBounds = new 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 < n; ++i) { | ||
mark = items[i]; | ||
switch (mark.role) { | ||
@@ -1378,11 +1282,8 @@ case AxisRole: | ||
break; | ||
case TitleRole: | ||
title = mark; | ||
break; | ||
case LegendRole: | ||
legends.push(legendLayout(view, mark)); | ||
break; | ||
case FrameRole: | ||
@@ -1399,9 +1300,8 @@ case ScopeRole: | ||
break; | ||
default: | ||
viewBounds.union(mark.bounds); | ||
} | ||
} // layout legends, adjust viewBounds | ||
} | ||
// layout legends, adjust viewBounds | ||
if (legends.length) { | ||
@@ -1413,22 +1313,20 @@ // group legends by orient | ||
if (orient !== None) (l[orient] || (l[orient] = [])).push(item); | ||
}); // perform grid layout for each orient group | ||
}); | ||
// perform grid layout for each orient group | ||
for (const orient in l) { | ||
const g = l[orient]; | ||
gridLayout(view, g, legendParams(g, orient, _.legends, xBounds, yBounds, width, height)); | ||
} // update view bounds | ||
} | ||
// 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) { | ||
if (_.autosize && (_.autosize.type === Fit || _.autosize.type === FitX || _.autosize.type === FitY)) { | ||
// For autosize fit, incorporate the orthogonal dimension only. | ||
@@ -1442,3 +1340,2 @@ // Legends that overrun the chart area will then be clipped; | ||
break; | ||
case Top: | ||
@@ -1452,33 +1349,32 @@ case Bottom: | ||
}); | ||
} // combine bounding boxes | ||
} | ||
// combine bounding boxes | ||
viewBounds.union(xBounds).union(yBounds); | ||
viewBounds.union(xBounds).union(yBounds); // layout title, adjust bounds | ||
// layout title, adjust bounds | ||
if (title) { | ||
viewBounds.union(titleLayout(view, title, width, height, viewBounds)); | ||
} // override aggregated view bounds if content is clipped | ||
} | ||
// override aggregated view bounds if content is clipped | ||
if (group.clip) { | ||
viewBounds.set(0, 0, group.width || 0, group.height || 0); | ||
} // perform size adjustment | ||
} | ||
// perform size adjustment | ||
viewSizeLayout(view, group, viewBounds, _); | ||
} | ||
function viewSizeLayout(view, group, viewBounds, _) { | ||
const auto = _.autosize || {}, | ||
type = auto.type; | ||
type = auto.type; | ||
if (view._autosize < 1 || !type) return; | ||
let viewWidth = view._width, | ||
viewHeight = view._height, | ||
width = Math.max(0, group.width || 0), | ||
left = Math.max(0, Math.ceil(-viewBounds.x1)), | ||
height = Math.max(0, group.height || 0), | ||
top = Math.max(0, Math.ceil(-viewBounds.y1)); | ||
viewHeight = view._height, | ||
width = Math.max(0, group.width || 0), | ||
left = Math.max(0, Math.ceil(-viewBounds.x1)), | ||
height = Math.max(0, group.height || 0), | ||
top = Math.max(0, Math.ceil(-viewBounds.y1)); | ||
const right = Math.max(0, Math.ceil(viewBounds.x2 - width)), | ||
bottom = Math.max(0, Math.ceil(viewBounds.y2 - height)); | ||
bottom = Math.max(0, Math.ceil(viewBounds.y2 - height)); | ||
if (auto.contains === Padding) { | ||
@@ -1489,3 +1385,2 @@ const padding = view.padding(); | ||
} | ||
if (type === None) { | ||
@@ -1509,3 +1404,2 @@ left = 0; | ||
} | ||
view._resizeView(viewWidth, viewHeight, width, height, [left, top], auto.resize); | ||
@@ -1512,0 +1406,0 @@ } |
{ | ||
"name": "vega-view-transforms", | ||
"version": "4.5.8", | ||
"version": "4.5.9", | ||
"description": "View-specific transforms for Vega dataflows.", | ||
@@ -18,3 +18,3 @@ "keywords": [ | ||
"prebuild": "rimraf build", | ||
"build": "rollup -c --config-transform", | ||
"build": "rollup -c rollup.config.mjs --config-transform", | ||
"pretest": "yarn build --config-test", | ||
@@ -25,5 +25,5 @@ "test": "tape 'test/**/*-test.js'", | ||
"dependencies": { | ||
"vega-dataflow": "^5.7.3", | ||
"vega-scenegraph": "^4.9.2", | ||
"vega-util": "^1.15.2" | ||
"vega-dataflow": "^5.7.5", | ||
"vega-scenegraph": "^4.10.2", | ||
"vega-util": "^1.17.1" | ||
}, | ||
@@ -33,3 +33,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "4affcbedb9d14815dbb6d3b250ed231b54fc95c0" | ||
"gitHead": "fb1092f6b931d450f9c210b67ae4752bd3dd461b" | ||
} |
@@ -116,3 +116,5 @@ import { | ||
if (_.autosize && _.autosize.type === Fit) { | ||
if (_.autosize && (_.autosize.type === Fit || | ||
_.autosize.type === FitX || | ||
_.autosize.type === FitY )) { | ||
// For autosize fit, incorporate the orthogonal dimension only. | ||
@@ -119,0 +121,0 @@ // Legends that overrun the chart area will then be clipped; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
210846
3752
2
Updatedvega-dataflow@^5.7.5
Updatedvega-scenegraph@^4.10.2
Updatedvega-util@^1.17.1