Skip to content

Commit

Permalink
fix: support "container" for facet autosize
Browse files Browse the repository at this point in the history
  • Loading branch information
drgould authored and BradyJ27 committed Oct 19, 2023
1 parent af24c0f commit da5e223
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 187 deletions.
244 changes: 122 additions & 122 deletions build/vega-lite-schema.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions src/compile/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {Dict, keys} from '../util';
import {buildModel} from './buildmodel';
import {assembleRootData} from './data/assemble';
import {optimizeDataflow} from './data/optimize';
import {isFacetModel, Model} from './model';
import {Model} from './model';

export interface CompileOptions {
/**
Expand Down Expand Up @@ -182,7 +182,6 @@ function getTopLevelProperties(
? {}
: {autosize: autosize.type}
: {autosize}),
...(isFacetModel(model) && typeof width == 'number' && typeof height == 'number' ? {width, height} : {}),
...extractTopLevelProperties(config, false),
...extractTopLevelProperties(inputSpec, true)
};
Expand Down
2 changes: 2 additions & 0 deletions src/compile/facet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {hasDiscreteDomain} from '../scale';
import {DEFAULT_SORT_OP, EncodingSortField, isSortField, SortOrder} from '../sort';
import {NormalizedFacetSpec} from '../spec';
import {isStep} from '../spec/base';
import {isStep} from '../spec/base';
import {EncodingFacetMapping, FacetFieldDef, FacetMapping, isFacetMapping} from '../spec/facet';
import {keys} from '../util';
import {isVgRangeStep, VgData, VgLayout, VgMarkGroup} from '../vega.schema';
Expand All @@ -22,6 +23,7 @@ import {getHeaderChannel, getHeaderProperty} from './header/common';
import {HEADER_CHANNELS, HEADER_TYPES} from './header/component';
import {parseFacetHeaders} from './header/parse';
import {assembleLayoutSignals} from './layoutsize/assemble';
import {assembleLayoutSignals} from './layoutsize/assemble';
import {parseFacetLayoutSize} from './layoutsize/parse';
import {Model, ModelWithField} from './model';
import {assembleDomain, getFieldFromDomain} from './scale/domain';
Expand Down
22 changes: 11 additions & 11 deletions src/compile/layoutsize/assemble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {ScaleComponent} from '../scale/component';
import {getSizeTypeFromLayoutSizeType, LayoutSizeType} from './component';
import {isFacetMapping} from '../../spec/facet';
import {FacetModel} from '../facet';
import {getFacetModel} from '../selection';
import {getFacetParentModel} from '../selection';

export function assembleLayoutSignals(model: Model): NewSignal[] {
return [
Expand All @@ -30,16 +30,8 @@ export function sizeSignals(model: Model, sizeType: LayoutSizeType): (NewSignal

// Read size signal name from name map, just in case it is the top-level size signal that got renamed.
const name = model.getSizeSignalRef(sizeType).signal;
const facetModel = getFacetModel(model);

if (isFacetModel(facetModel) && facetModel.hasStaticOuterDimension(getSizeTypeFromLayoutSizeType(sizeType))) {
return [
{
name,
update: autosizedFacetExpr(facetModel, sizeType)
}
];
} else if (size === 'step') {
if (size === 'step') {
const scaleComponent = model.getScaleComponent(channel);

if (scaleComponent) {
Expand All @@ -49,7 +41,7 @@ export function sizeSignals(model: Model, sizeType: LayoutSizeType): (NewSignal
if (hasDiscreteDomain(type) && isVgRangeStep(range)) {
const scaleName = model.scaleName(channel);

if (isFacetModel(facetModel)) {
if (facetParent) {
// If parent is facet and this is an independent scale, return only signal signal
// as the width/height will be calculated using the cardinality from
// facet's aggregate rather than reading from scale domain
Expand All @@ -76,6 +68,14 @@ export function sizeSignals(model: Model, sizeType: LayoutSizeType): (NewSignal
const defaultValue = getViewConfigContinuousSize(model.config.view, isWidth ? 'width' : 'height');
const safeExpr = `isFinite(${expr}) ? ${expr} : ${defaultValue}`;
return [{name, init: safeExpr, on: [{update: safeExpr, events: 'window:resize'}]}];
} else if (facetParent?.hasStaticOuterDimension(getSizeTypeFromLayoutSizeType(sizeType))) {
// this disregards any sizing directly set for the facet child which has already been set on the facet parent
return [
{
name,
update: autosizedFacetExpr(facetParent, sizeType)
}
];
} else {
return [
{
Expand Down
14 changes: 2 additions & 12 deletions src/compile/layoutsize/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,14 @@ import {getSizeTypeFromLayoutSizeType, LayoutSize, LayoutSizeIndex, LayoutSizeTy
import {FacetModel} from '../facet';

export function parseFacetLayoutSize(model: FacetModel) {
const {size, component} = model;
parseChildrenLayoutSize(model);

const {size, component} = model;
for (const dimension of ['width', 'height']) {
if (size[dimension] && !isStep(size[dimension])) {
component.layoutSize.set(dimension as LayoutSizeType, size[dimension], true);
}
}
// parse top level facet size
if (size.width) {
component.layoutSize.set('width', isStep(size.width) ? 'step' : size.width, true);
}

if (size.height) {
component.layoutSize.set('height', isStep(size.height) ? 'step' : size.height, true);
}

// parse children
parseChildrenLayoutSize(model);
}

export function parseLayerLayoutSize(model: Model) {
Expand Down
9 changes: 4 additions & 5 deletions src/compile/scale/range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ import {UnitModel} from '../unit';
import {ScaleComponentIndex} from './component';
import {getFacetParentModel} from '../selection';
import {durationExpr} from '../../timeunit';
import {isFacetModel} from '../model';
import {getFacetModel} from '../selection';
import {getFacetParentModel} from '../selection';

export const RANGE_PROPERTIES: (keyof Scale)[] = ['range', 'scheme'];

Expand Down Expand Up @@ -264,7 +263,7 @@ function defaultRange(channel: ScaleChannel, model: UnitModel): VgRange {

const {domain, domainMid} = model.specifiedScales[channel];

const facetModel = getFacetModel(model);
const facetParent = getFacetParentModel(model);

switch (channel) {
case X:
Expand All @@ -273,12 +272,12 @@ function defaultRange(channel: ScaleChannel, model: UnitModel): VgRange {
if (util.contains(['point', 'band'], scaleType)) {
if (channel === X && !size.width) {
const w = getViewConfigDiscreteSize(config.view, 'width');
if (isStep(w) && (!isFacetModel(facetModel) || !facetModel.hasStaticOuterDimension('width'))) {
if (isStep(w) && !facetParent?.hasStaticOuterDimension('width')) {
return w;
}
} else if (channel === Y && !size.height) {
const h = getViewConfigDiscreteSize(config.view, 'height');
if (isStep(h) && (!isFacetModel(facetModel) || !facetModel.hasStaticOuterDimension('height'))) {
if (isStep(h) && !facetParent?.hasStaticOuterDimension('height')) {
return h;
}
}
Expand Down
13 changes: 3 additions & 10 deletions src/compile/selection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,14 @@ export const selectionCompilers: SelectionCompiler[] = [
nearest
];

export function getFacetModel(model: Model): FacetModel {
let parent = model.parent;
while (parent) {
if (isFacetModel(parent)) {
return parent;
}
parent = parent.parent;
}

return null;
export function getFacetParentModel(model: Model): FacetModel | null {
return isFacetModel(model.parent) ? model.parent : null;
}

export function unitName(model: Model, {escape} = {escape: true}) {
let name = escape ? stringValue(model.name) : model.name;
const facetModel = getFacetParentModel(model);
const facetModel = getFacetParentModel(model);
if (facetModel) {
const {facet} = facetModel;
for (const channel of FACET_CHANNELS) {
Expand Down
25 changes: 2 additions & 23 deletions src/spec/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export interface LayoutSizeMixins {
* __Default value:__
* Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.
*
* __Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `"container"` option cannot be used. However, if the [`facet`](https://vega.github.io/vega-lite/docs/facet.html#facet-operator) operator is used directly this represents the width of all facets combined. As such, `"container"` can be used and the behavior specified by the [`autosize`](https://vega.github.io/vega-lite/docs/size.html#autosize) property is honored.
* __Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `"container"` option cannot be used. However, if the [`facet`](facet.html#facet-operator) operator is used directly this represents the width of all facets combined. As such, `"container"` can be used and the behavior specified by the [`autosize`](size.html#autosize) property is honored.
*
* __See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.
*/
Expand All @@ -107,36 +107,15 @@ export interface LayoutSizeMixins {
*
* __Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.
*
* __Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `"container"` option cannot be used. However, if the [`facet`](https://vega.github.io/vega-lite/docs/facet.html#facet-operator) operator is used directly this represents the height of all facets combined. As such, `"container"` can be used and honors the behavior specified by the [`autosize`](https://vega.github.io/vega-lite/docs/size.html#autosize) property is honored.
* __Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `"container"` option cannot be used. However, if the [`facet`](facet.html#facet-operator) operator is used directly this represents the height of all facets combined. As such, `"container"` can be used and honors the behavior specified by the [`autosize`](size.html#autosize) property is honored.
*
* __See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.
*/
height?: number | 'container' | Step; // Vega also supports SignalRef for width and height. However, we need to know if width is a step or not in VL and it's very difficult to check this at runtime, so we intentionally do not support SignalRef here.
}

export interface LayoutSizeNoStepMixins extends LayoutSizeMixins {
/**
* The combined width of all children of this visualization.
*
* - For all plots, width should be a number.
* - To enable responsive sizing on width, it should be set to `"container"`.
*
* __Default value:__ The sum of all child plot widths.
*
* __See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.
*/
width?: number | 'container';

/**
* The combined height of all children of this visualization.
*
* - For all plots, height should be a number.
* - To enable responsive sizing on height, it should be set to `"container"`.
*
* __Default value:__ THe sum of all child plot heights.
*
* __See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.
*/
height?: number | 'container';
}

Expand Down
4 changes: 2 additions & 2 deletions src/spec/facet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {ExprRef} from '../expr';
import {Header} from '../header';
import {EncodingSortField, SortArray, SortOrder} from '../sort';
import {StandardType} from '../type';
import {BaseSpec, GenericCompositionLayoutWithColumns, LayoutSizeMixins, ResolveMixins} from './base';
import {BaseSpec, GenericCompositionLayoutWithColumns, LayoutSizeNoStepMixins, ResolveMixins} from './base';
import {GenericLayerSpec, NormalizedLayerSpec} from './layer';
import {GenericUnitSpec, NormalizedUnitSpec} from './unit';

Expand Down Expand Up @@ -117,7 +117,7 @@ export interface GenericFacetSpec<U extends GenericUnitSpec<any, any>, L extends
extends BaseSpec,
GenericCompositionLayoutWithColumns,
ResolveMixins,
LayoutSizeMixins {
LayoutSizeNoStepMixins {
/**
* Definition for how to facet the data. One of:
* 1) [a field definition for faceting the plot by one field](https://vega.github.io/vega-lite/docs/facet.html#field-def)
Expand Down

0 comments on commit da5e223

Please sign in to comment.