genesys-spark-chart-components 4.202.0 → 4.203.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{color-palette-DOJh4cNZ.js → color-palette-CU1chhBt.js} +1 -1
- package/dist/cjs/gux-chart-column-beta.cjs.entry.js +1 -1
- package/dist/cjs/gux-chart-donut-beta.cjs.entry.js +1 -1
- package/dist/cjs/gux-chart-line-beta.cjs.entry.js +1 -1
- package/dist/cjs/gux-chart-pie-beta.cjs.entry.js +1 -1
- package/dist/cjs/gux-chart-scatter-plot-beta.cjs.entry.js +1 -1
- package/dist/cjs/gux-visualization-beta.cjs.entry.js +437 -298
- package/dist/esm/{color-palette-CqY6Km9m.js → color-palette-DyPalgli.js} +1 -1
- package/dist/esm/gux-chart-column-beta.entry.js +1 -1
- package/dist/esm/gux-chart-donut-beta.entry.js +1 -1
- package/dist/esm/gux-chart-line-beta.entry.js +1 -1
- package/dist/esm/gux-chart-pie-beta.entry.js +1 -1
- package/dist/esm/gux-chart-scatter-plot-beta.entry.js +1 -1
- package/dist/esm/gux-visualization-beta.entry.js +437 -298
- package/dist/genesys-chart-webcomponents/genesys-chart-webcomponents.esm.js +1 -1
- package/dist/genesys-chart-webcomponents/p-0613c0d5.entry.js +1 -0
- package/dist/genesys-chart-webcomponents/{p-4a5cb50a.entry.js → p-197db998.entry.js} +3 -3
- package/dist/genesys-chart-webcomponents/{p-ee1b963c.entry.js → p-39f1db9c.entry.js} +1 -1
- package/dist/genesys-chart-webcomponents/{p-eb769e31.entry.js → p-87dd0b8f.entry.js} +1 -1
- package/dist/genesys-chart-webcomponents/{p-CqY6Km9m.js → p-DyPalgli.js} +1 -1
- package/dist/genesys-chart-webcomponents/{p-5b977d65.entry.js → p-a7d9fe74.entry.js} +1 -1
- package/dist/genesys-chart-webcomponents/{p-0bd6f695.entry.js → p-da9e8b8c.entry.js} +1 -1
- package/package.json +7 -7
- package/dist/genesys-chart-webcomponents/p-b10de83b.entry.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index$2 = require('./index-DEg9dZRu.js');
|
|
4
|
-
var colorPalette = require('./color-palette-
|
|
4
|
+
var colorPalette = require('./color-palette-CU1chhBt.js');
|
|
5
5
|
|
|
6
6
|
// Note: This regex matches even invalid JSON strings, but since we’re
|
|
7
7
|
// working on the output of `JSON.stringify` we know that only valid strings
|
|
@@ -44674,7 +44674,7 @@ var expression$1 = {
|
|
|
44674
44674
|
}
|
|
44675
44675
|
};
|
|
44676
44676
|
|
|
44677
|
-
var version$1$1 = "6.4.
|
|
44677
|
+
var version$1$1 = "6.4.2";
|
|
44678
44678
|
var pkg$1 = {
|
|
44679
44679
|
version: version$1$1};
|
|
44680
44680
|
|
|
@@ -44906,6 +44906,12 @@ const entries$1 = Object.entries;
|
|
|
44906
44906
|
function isBoolean(b) {
|
|
44907
44907
|
return b === true || b === false;
|
|
44908
44908
|
}
|
|
44909
|
+
/**
|
|
44910
|
+
* Returns true if the value is a primitive type.
|
|
44911
|
+
*/
|
|
44912
|
+
function isPrimitive(v) {
|
|
44913
|
+
return isString(v) || isNumber$1(v) || isBoolean(v);
|
|
44914
|
+
}
|
|
44909
44915
|
/**
|
|
44910
44916
|
* Convert a string into a valid variable name
|
|
44911
44917
|
*/
|
|
@@ -46380,6 +46386,10 @@ const MORE_THAN_ONE_SORT = 'Domains that should be unioned has conflicting sort
|
|
|
46380
46386
|
const FACETED_INDEPENDENT_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect.';
|
|
46381
46387
|
const FACETED_INDEPENDENT_SAME_FIELDS_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect.';
|
|
46382
46388
|
const FACETED_INDEPENDENT_SAME_SOURCE = 'Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.';
|
|
46389
|
+
// LEGEND
|
|
46390
|
+
function legendValuesUnioned(channelA, channelB) {
|
|
46391
|
+
return `Unioning discrete legend values from ${channelA} and ${channelB}.`;
|
|
46392
|
+
}
|
|
46383
46393
|
// STACK
|
|
46384
46394
|
function cannotStackRangedMark(channel) {
|
|
46385
46395
|
return `Cannot stack "${channel}" if there is already "${channel}2".`;
|
|
@@ -48390,7 +48400,7 @@ function getFieldOrDatumDef(channelDef) {
|
|
|
48390
48400
|
* Convert type to full, lowercase type, or augment the fieldDef with a default type if missing.
|
|
48391
48401
|
*/
|
|
48392
48402
|
function initChannelDef(channelDef, channel, config, opt = {}) {
|
|
48393
|
-
if (
|
|
48403
|
+
if (isPrimitive(channelDef)) {
|
|
48394
48404
|
const primitiveType = isString(channelDef) ? 'string' : isNumber$1(channelDef) ? 'number' : 'boolean';
|
|
48395
48405
|
warn(primitiveChannelDef(channel, primitiveType, channelDef));
|
|
48396
48406
|
return { value: channelDef };
|
|
@@ -53963,8 +53973,11 @@ function tooltipRefForEncoding(encoding, stack, config, { reactiveGeom } = {}) {
|
|
|
53963
53973
|
* Transforms a tooltip value that is an array to a string with line breaks
|
|
53964
53974
|
*/
|
|
53965
53975
|
function addLineBreaksToTooltip(channelDef, config, expr = 'datum') {
|
|
53966
|
-
if (isFieldDef(channelDef) &&
|
|
53967
|
-
|
|
53976
|
+
if (isFieldDef(channelDef) &&
|
|
53977
|
+
isDiscrete$1(channelDef.type) &&
|
|
53978
|
+
!getFormatMixins(channelDef).format &&
|
|
53979
|
+
!getFormatMixins(channelDef).formatType) {
|
|
53980
|
+
const fieldString = `${expr}["${channelDef.field}"]`;
|
|
53968
53981
|
return {
|
|
53969
53982
|
signal: `isValid(${fieldString}) ? isArray(${fieldString}) ? join(${fieldString}, '\\n') : ${fieldString} : ""+${fieldString}`,
|
|
53970
53983
|
};
|
|
@@ -56985,298 +56998,6 @@ function mergeSymbolType(st1, st2) {
|
|
|
56985
56998
|
return st1;
|
|
56986
56999
|
}
|
|
56987
57000
|
|
|
56988
|
-
function setLegendEncode(legend, part, vgProp, vgRef) {
|
|
56989
|
-
legend.encode ??= {};
|
|
56990
|
-
legend.encode[part] ??= {};
|
|
56991
|
-
legend.encode[part].update ??= {};
|
|
56992
|
-
// @ts-expect-error expression is too complex for typescript to understand
|
|
56993
|
-
legend.encode[part].update[vgProp] = vgRef;
|
|
56994
|
-
}
|
|
56995
|
-
function assembleLegends(model) {
|
|
56996
|
-
const legendComponentIndex = model.component.legends;
|
|
56997
|
-
const legendByDomain = {};
|
|
56998
|
-
for (const channel of keys(legendComponentIndex)) {
|
|
56999
|
-
const scaleComponent = model.getScaleComponent(channel);
|
|
57000
|
-
const domainHash = stringify$1(scaleComponent.get('domains'));
|
|
57001
|
-
if (legendByDomain[domainHash]) {
|
|
57002
|
-
for (const mergedLegendComponent of legendByDomain[domainHash]) {
|
|
57003
|
-
const merged = mergeLegendComponent(mergedLegendComponent, legendComponentIndex[channel]);
|
|
57004
|
-
if (!merged) {
|
|
57005
|
-
// If cannot merge, need to add this legend separately
|
|
57006
|
-
legendByDomain[domainHash].push(legendComponentIndex[channel]);
|
|
57007
|
-
}
|
|
57008
|
-
}
|
|
57009
|
-
}
|
|
57010
|
-
else {
|
|
57011
|
-
legendByDomain[domainHash] = [legendComponentIndex[channel].clone()];
|
|
57012
|
-
}
|
|
57013
|
-
}
|
|
57014
|
-
const legends = vals(legendByDomain)
|
|
57015
|
-
.flat()
|
|
57016
|
-
.map((l) => assembleLegend(l, model.config))
|
|
57017
|
-
.filter((l) => l !== undefined);
|
|
57018
|
-
return legends;
|
|
57019
|
-
}
|
|
57020
|
-
function assembleLegend(legendCmpt, config) {
|
|
57021
|
-
const { disable, labelExpr, selections, ...legend } = legendCmpt.combine();
|
|
57022
|
-
if (disable) {
|
|
57023
|
-
return undefined;
|
|
57024
|
-
}
|
|
57025
|
-
if (config.aria === false && legend.aria == undefined) {
|
|
57026
|
-
legend.aria = false;
|
|
57027
|
-
}
|
|
57028
|
-
if (legend.encode?.symbols) {
|
|
57029
|
-
const out = legend.encode.symbols.update;
|
|
57030
|
-
if (out.fill && out.fill['value'] !== 'transparent' && !out.stroke && !legend.stroke) {
|
|
57031
|
-
// For non color channel's legend, we need to override symbol stroke config from Vega config if stroke channel is not used.
|
|
57032
|
-
out.stroke = { value: 'transparent' };
|
|
57033
|
-
}
|
|
57034
|
-
// Remove properties that the legend is encoding.
|
|
57035
|
-
for (const property of LEGEND_SCALE_CHANNELS) {
|
|
57036
|
-
if (legend[property]) {
|
|
57037
|
-
delete out[property];
|
|
57038
|
-
}
|
|
57039
|
-
}
|
|
57040
|
-
}
|
|
57041
|
-
if (!legend.title) {
|
|
57042
|
-
// title schema doesn't include null, ''
|
|
57043
|
-
delete legend.title;
|
|
57044
|
-
}
|
|
57045
|
-
if (labelExpr !== undefined) {
|
|
57046
|
-
let expr = labelExpr;
|
|
57047
|
-
if (legend.encode?.labels?.update && isSignalRef(legend.encode.labels.update.text)) {
|
|
57048
|
-
expr = replaceAll(labelExpr, 'datum.label', legend.encode.labels.update.text.signal);
|
|
57049
|
-
}
|
|
57050
|
-
setLegendEncode(legend, 'labels', 'text', { signal: expr });
|
|
57051
|
-
}
|
|
57052
|
-
return legend;
|
|
57053
|
-
}
|
|
57054
|
-
|
|
57055
|
-
function assembleProjections(model) {
|
|
57056
|
-
if (isLayerModel(model) || isConcatModel(model)) {
|
|
57057
|
-
return assembleProjectionsForModelAndChildren(model);
|
|
57058
|
-
}
|
|
57059
|
-
else {
|
|
57060
|
-
return assembleProjectionForModel(model);
|
|
57061
|
-
}
|
|
57062
|
-
}
|
|
57063
|
-
function assembleProjectionsForModelAndChildren(model) {
|
|
57064
|
-
return model.children.reduce((projections, child) => {
|
|
57065
|
-
return projections.concat(child.assembleProjections());
|
|
57066
|
-
}, assembleProjectionForModel(model));
|
|
57067
|
-
}
|
|
57068
|
-
function assembleProjectionForModel(model) {
|
|
57069
|
-
const component = model.component.projection;
|
|
57070
|
-
if (!component || component.merged) {
|
|
57071
|
-
return [];
|
|
57072
|
-
}
|
|
57073
|
-
const projection = component.combine();
|
|
57074
|
-
const { name } = projection; // we need to extract name so that it is always present in the output and pass TS type validation
|
|
57075
|
-
if (!component.data) {
|
|
57076
|
-
// generate custom projection, no automatic fitting
|
|
57077
|
-
return [
|
|
57078
|
-
{
|
|
57079
|
-
name,
|
|
57080
|
-
// translate to center by default
|
|
57081
|
-
translate: { signal: '[width / 2, height / 2]' },
|
|
57082
|
-
// parameters, overwrite default translate if specified
|
|
57083
|
-
...projection,
|
|
57084
|
-
},
|
|
57085
|
-
];
|
|
57086
|
-
}
|
|
57087
|
-
else {
|
|
57088
|
-
// generate projection that uses extent fitting
|
|
57089
|
-
const size = {
|
|
57090
|
-
signal: `[${component.size.map((ref) => ref.signal).join(', ')}]`,
|
|
57091
|
-
};
|
|
57092
|
-
const fits = component.data.reduce((sources, data) => {
|
|
57093
|
-
const source = isSignalRef(data) ? data.signal : `data('${model.lookupDataSource(data)}')`;
|
|
57094
|
-
if (!contains(sources, source)) {
|
|
57095
|
-
// build a unique list of sources
|
|
57096
|
-
sources.push(source);
|
|
57097
|
-
}
|
|
57098
|
-
return sources;
|
|
57099
|
-
}, []);
|
|
57100
|
-
if (fits.length <= 0) {
|
|
57101
|
-
throw new Error("Projection's fit didn't find any data sources");
|
|
57102
|
-
}
|
|
57103
|
-
return [
|
|
57104
|
-
{
|
|
57105
|
-
name,
|
|
57106
|
-
size,
|
|
57107
|
-
fit: {
|
|
57108
|
-
signal: fits.length > 1 ? `[${fits.join(', ')}]` : fits[0],
|
|
57109
|
-
},
|
|
57110
|
-
...projection,
|
|
57111
|
-
},
|
|
57112
|
-
];
|
|
57113
|
-
}
|
|
57114
|
-
}
|
|
57115
|
-
|
|
57116
|
-
const PROJECTION_PROPERTIES = [
|
|
57117
|
-
'type',
|
|
57118
|
-
'clipAngle',
|
|
57119
|
-
'clipExtent',
|
|
57120
|
-
'center',
|
|
57121
|
-
'rotate',
|
|
57122
|
-
'precision',
|
|
57123
|
-
'reflectX',
|
|
57124
|
-
'reflectY',
|
|
57125
|
-
'coefficient',
|
|
57126
|
-
'distance',
|
|
57127
|
-
'fraction',
|
|
57128
|
-
'lobes',
|
|
57129
|
-
'parallel',
|
|
57130
|
-
'radius',
|
|
57131
|
-
'ratio',
|
|
57132
|
-
'spacing',
|
|
57133
|
-
'tilt',
|
|
57134
|
-
];
|
|
57135
|
-
|
|
57136
|
-
class ProjectionComponent extends Split {
|
|
57137
|
-
specifiedProjection;
|
|
57138
|
-
size;
|
|
57139
|
-
data;
|
|
57140
|
-
merged = false;
|
|
57141
|
-
constructor(name, specifiedProjection, size, data) {
|
|
57142
|
-
super({ ...specifiedProjection }, // all explicit properties of projection
|
|
57143
|
-
{ name });
|
|
57144
|
-
this.specifiedProjection = specifiedProjection;
|
|
57145
|
-
this.size = size;
|
|
57146
|
-
this.data = data;
|
|
57147
|
-
}
|
|
57148
|
-
/**
|
|
57149
|
-
* Whether the projection parameters should fit provided data.
|
|
57150
|
-
*/
|
|
57151
|
-
get isFit() {
|
|
57152
|
-
return !!this.data;
|
|
57153
|
-
}
|
|
57154
|
-
}
|
|
57155
|
-
|
|
57156
|
-
function parseProjection(model) {
|
|
57157
|
-
model.component.projection = isUnitModel(model) ? parseUnitProjection(model) : parseNonUnitProjections(model);
|
|
57158
|
-
}
|
|
57159
|
-
function parseUnitProjection(model) {
|
|
57160
|
-
if (model.hasProjection) {
|
|
57161
|
-
const proj = replaceExprRef(model.specifiedProjection);
|
|
57162
|
-
const fit = !(proj && (proj.scale != null || proj.translate != null));
|
|
57163
|
-
const size = fit ? [model.getSizeSignalRef('width'), model.getSizeSignalRef('height')] : undefined;
|
|
57164
|
-
const data = fit ? gatherFitData(model) : undefined;
|
|
57165
|
-
const projComp = new ProjectionComponent(model.projectionName(true), {
|
|
57166
|
-
...replaceExprRef(model.config.projection),
|
|
57167
|
-
...proj,
|
|
57168
|
-
}, size, data);
|
|
57169
|
-
if (!projComp.get('type')) {
|
|
57170
|
-
projComp.set('type', 'equalEarth', false);
|
|
57171
|
-
}
|
|
57172
|
-
return projComp;
|
|
57173
|
-
}
|
|
57174
|
-
return undefined;
|
|
57175
|
-
}
|
|
57176
|
-
function gatherFitData(model) {
|
|
57177
|
-
const data = [];
|
|
57178
|
-
const { encoding } = model;
|
|
57179
|
-
for (const posssiblePair of [
|
|
57180
|
-
[LONGITUDE, LATITUDE],
|
|
57181
|
-
[LONGITUDE2, LATITUDE2],
|
|
57182
|
-
]) {
|
|
57183
|
-
if (getFieldOrDatumDef(encoding[posssiblePair[0]]) || getFieldOrDatumDef(encoding[posssiblePair[1]])) {
|
|
57184
|
-
data.push({
|
|
57185
|
-
signal: model.getName(`geojson_${data.length}`),
|
|
57186
|
-
});
|
|
57187
|
-
}
|
|
57188
|
-
}
|
|
57189
|
-
if (model.channelHasField(SHAPE) && model.typedFieldDef(SHAPE).type === GEOJSON) {
|
|
57190
|
-
data.push({
|
|
57191
|
-
signal: model.getName(`geojson_${data.length}`),
|
|
57192
|
-
});
|
|
57193
|
-
}
|
|
57194
|
-
if (data.length === 0) {
|
|
57195
|
-
// main source is geojson, so we can just use that
|
|
57196
|
-
data.push(model.requestDataName(DataSourceType.Main));
|
|
57197
|
-
}
|
|
57198
|
-
return data;
|
|
57199
|
-
}
|
|
57200
|
-
function mergeIfNoConflict(first, second) {
|
|
57201
|
-
const allPropertiesShared = every(PROJECTION_PROPERTIES, (prop) => {
|
|
57202
|
-
// neither has the property
|
|
57203
|
-
if (!has$1(first.explicit, prop) && !has$1(second.explicit, prop)) {
|
|
57204
|
-
return true;
|
|
57205
|
-
}
|
|
57206
|
-
// both have property and an equal value for property
|
|
57207
|
-
if (has$1(first.explicit, prop) &&
|
|
57208
|
-
has$1(second.explicit, prop) &&
|
|
57209
|
-
// some properties might be signals or objects and require hashing for comparison
|
|
57210
|
-
deepEqual(first.get(prop), second.get(prop))) {
|
|
57211
|
-
return true;
|
|
57212
|
-
}
|
|
57213
|
-
return false;
|
|
57214
|
-
});
|
|
57215
|
-
const size = deepEqual(first.size, second.size);
|
|
57216
|
-
if (size) {
|
|
57217
|
-
if (allPropertiesShared) {
|
|
57218
|
-
return first;
|
|
57219
|
-
}
|
|
57220
|
-
else if (deepEqual(first.explicit, {})) {
|
|
57221
|
-
return second;
|
|
57222
|
-
}
|
|
57223
|
-
else if (deepEqual(second.explicit, {})) {
|
|
57224
|
-
return first;
|
|
57225
|
-
}
|
|
57226
|
-
}
|
|
57227
|
-
// if all properties don't match, let each unit spec have its own projection
|
|
57228
|
-
return null;
|
|
57229
|
-
}
|
|
57230
|
-
function parseNonUnitProjections(model) {
|
|
57231
|
-
if (model.children.length === 0) {
|
|
57232
|
-
return undefined;
|
|
57233
|
-
}
|
|
57234
|
-
let nonUnitProjection;
|
|
57235
|
-
// parse all children first
|
|
57236
|
-
for (const child of model.children) {
|
|
57237
|
-
parseProjection(child);
|
|
57238
|
-
}
|
|
57239
|
-
// analyze parsed projections, attempt to merge
|
|
57240
|
-
const mergable = every(model.children, (child) => {
|
|
57241
|
-
const projection = child.component.projection;
|
|
57242
|
-
if (!projection) {
|
|
57243
|
-
// child layer does not use a projection
|
|
57244
|
-
return true;
|
|
57245
|
-
}
|
|
57246
|
-
else if (!nonUnitProjection) {
|
|
57247
|
-
// cached 'projection' is null, cache this one
|
|
57248
|
-
nonUnitProjection = projection;
|
|
57249
|
-
return true;
|
|
57250
|
-
}
|
|
57251
|
-
else {
|
|
57252
|
-
const merge = mergeIfNoConflict(nonUnitProjection, projection);
|
|
57253
|
-
if (merge) {
|
|
57254
|
-
nonUnitProjection = merge;
|
|
57255
|
-
}
|
|
57256
|
-
return !!merge;
|
|
57257
|
-
}
|
|
57258
|
-
});
|
|
57259
|
-
// if cached one and all other children share the same projection,
|
|
57260
|
-
if (nonUnitProjection && mergable) {
|
|
57261
|
-
// so we can elevate it to the layer level
|
|
57262
|
-
const name = model.projectionName(true);
|
|
57263
|
-
const modelProjection = new ProjectionComponent(name, nonUnitProjection.specifiedProjection, nonUnitProjection.size, duplicate(nonUnitProjection.data));
|
|
57264
|
-
// rename and assign all others as merged
|
|
57265
|
-
for (const child of model.children) {
|
|
57266
|
-
const projection = child.component.projection;
|
|
57267
|
-
if (projection) {
|
|
57268
|
-
if (projection.isFit) {
|
|
57269
|
-
modelProjection.data.push(...child.component.projection.data);
|
|
57270
|
-
}
|
|
57271
|
-
child.renameProjection(projection.get('name'), name);
|
|
57272
|
-
projection.merged = true;
|
|
57273
|
-
}
|
|
57274
|
-
}
|
|
57275
|
-
return modelProjection;
|
|
57276
|
-
}
|
|
57277
|
-
return undefined;
|
|
57278
|
-
}
|
|
57279
|
-
|
|
57280
57001
|
function rangeFormula(model, fieldDef, channel, config) {
|
|
57281
57002
|
if (binRequiresRange(fieldDef, channel)) {
|
|
57282
57003
|
// read format from axis or legend, if there is no format then use config.numberFormat
|
|
@@ -59503,7 +59224,7 @@ function parseSingleChannelDomain(scaleType, domain, model, channel) {
|
|
|
59503
59224
|
sort: sort === true || !isObject(sort)
|
|
59504
59225
|
? {
|
|
59505
59226
|
field: model.vgField(channel, {}),
|
|
59506
|
-
op: 'min',
|
|
59227
|
+
op: 'min',
|
|
59507
59228
|
}
|
|
59508
59229
|
: sort,
|
|
59509
59230
|
},
|
|
@@ -59835,6 +59556,423 @@ function assembleDomain(model, channel) {
|
|
|
59835
59556
|
return mergeDomains(domains);
|
|
59836
59557
|
}
|
|
59837
59558
|
|
|
59559
|
+
function setLegendEncode(legend, part, vgProp, vgRef) {
|
|
59560
|
+
legend.encode ??= {};
|
|
59561
|
+
legend.encode[part] ??= {};
|
|
59562
|
+
legend.encode[part].update ??= {};
|
|
59563
|
+
// @ts-expect-error expression is too complex for typescript to understand
|
|
59564
|
+
legend.encode[part].update[vgProp] = vgRef;
|
|
59565
|
+
}
|
|
59566
|
+
/**
|
|
59567
|
+
* Determines the underlying field name for a given scale channel within a model hierarchy.
|
|
59568
|
+
* @param model - The model to search for the field definition
|
|
59569
|
+
* @param channel - The scale channel (e.g., 'color', 'size', 'shape') to find the field for
|
|
59570
|
+
* @returns The field name if found; otherwise undefined
|
|
59571
|
+
*/
|
|
59572
|
+
function getFieldKeyForChannel(model, channel) {
|
|
59573
|
+
if (isUnitModel(model)) {
|
|
59574
|
+
const fd = model.fieldDef(channel);
|
|
59575
|
+
if (fd?.field) {
|
|
59576
|
+
return fd.field;
|
|
59577
|
+
}
|
|
59578
|
+
}
|
|
59579
|
+
// Use explicit fields from children
|
|
59580
|
+
const childFields = (model.children ?? [])
|
|
59581
|
+
.map((child) => getFieldKeyForChannel(child, channel))
|
|
59582
|
+
.filter((f) => !!f);
|
|
59583
|
+
if (childFields.length > 0) {
|
|
59584
|
+
const unique$1 = unique(childFields, hash);
|
|
59585
|
+
if (unique$1.length === 1) {
|
|
59586
|
+
return unique$1[0];
|
|
59587
|
+
}
|
|
59588
|
+
return undefined;
|
|
59589
|
+
}
|
|
59590
|
+
return undefined;
|
|
59591
|
+
}
|
|
59592
|
+
function legendsAreMergeCompatible(model, channelA, channelB) {
|
|
59593
|
+
if (channelA === channelB)
|
|
59594
|
+
return true;
|
|
59595
|
+
const typeA = model.getScaleType(channelA);
|
|
59596
|
+
const typeB = model.getScaleType(channelB);
|
|
59597
|
+
if (!typeA || !typeB)
|
|
59598
|
+
return false;
|
|
59599
|
+
// Only require discrete/continuous compatibility here. Domain handling is done later.
|
|
59600
|
+
const aIsDiscrete = hasDiscreteDomain(typeA);
|
|
59601
|
+
const bIsDiscrete = hasDiscreteDomain(typeB);
|
|
59602
|
+
return aIsDiscrete === bIsDiscrete;
|
|
59603
|
+
}
|
|
59604
|
+
function getLegendGroupKey(fieldKey, channel) {
|
|
59605
|
+
return fieldKey ? `field:${fieldKey}` : `channel:${String(channel)}`;
|
|
59606
|
+
}
|
|
59607
|
+
function extractDiscreteValuesFromDomain(domain) {
|
|
59608
|
+
if (isArray(domain)) {
|
|
59609
|
+
const primitives = domain.filter(isPrimitive);
|
|
59610
|
+
return primitives.length > 0 ? primitives : null;
|
|
59611
|
+
}
|
|
59612
|
+
if (isDataRefUnionedDomain(domain)) {
|
|
59613
|
+
const values = [];
|
|
59614
|
+
values.push(...domain.fields.flatMap((f) => (isArray(f) ? f.filter(isPrimitive) : [])));
|
|
59615
|
+
if (values.length > 0) {
|
|
59616
|
+
return unique(values, hash);
|
|
59617
|
+
}
|
|
59618
|
+
}
|
|
59619
|
+
return null;
|
|
59620
|
+
}
|
|
59621
|
+
/**
|
|
59622
|
+
* Compute the union of discrete values from the domains of two channels.
|
|
59623
|
+
*
|
|
59624
|
+
* @param model - The model to compute the union of discrete values for
|
|
59625
|
+
* @param channelA - The first channel to compute the union of discrete values for
|
|
59626
|
+
* @param channelB - The second channel to compute the union of discrete values for
|
|
59627
|
+
* @returns The union of discrete values
|
|
59628
|
+
*/
|
|
59629
|
+
function getDiscreteValuesForChannel(model, channel) {
|
|
59630
|
+
try {
|
|
59631
|
+
const domain = assembleDomain(model, channel);
|
|
59632
|
+
return extractDiscreteValuesFromDomain(domain);
|
|
59633
|
+
}
|
|
59634
|
+
catch {
|
|
59635
|
+
return null;
|
|
59636
|
+
}
|
|
59637
|
+
}
|
|
59638
|
+
function unionDiscreteValuesForChannels(model, channelA, channelB) {
|
|
59639
|
+
const vA = getDiscreteValuesForChannel(model, channelA);
|
|
59640
|
+
const vB = getDiscreteValuesForChannel(model, channelB);
|
|
59641
|
+
return vA && vB ? unique([...vA, ...vB], hash) : null;
|
|
59642
|
+
}
|
|
59643
|
+
function setImplicitLegendValues(cmpt, values, warnMessage) {
|
|
59644
|
+
if (values && values.length > 0) {
|
|
59645
|
+
const valuesProp = cmpt.getWithExplicit('values');
|
|
59646
|
+
if (!valuesProp?.explicit) {
|
|
59647
|
+
if (warnMessage) {
|
|
59648
|
+
warn(warnMessage);
|
|
59649
|
+
}
|
|
59650
|
+
cmpt.set('values', values, false);
|
|
59651
|
+
}
|
|
59652
|
+
}
|
|
59653
|
+
}
|
|
59654
|
+
function domainsExplicitAndEqual(model, channelA, channelB) {
|
|
59655
|
+
const scA = model.getScaleComponent(channelA);
|
|
59656
|
+
const scB = model.getScaleComponent(channelB);
|
|
59657
|
+
if (!scA || !scB)
|
|
59658
|
+
return false;
|
|
59659
|
+
const dA = scA.getWithExplicit('domains');
|
|
59660
|
+
const dB = scB.getWithExplicit('domains');
|
|
59661
|
+
if (!(dA?.explicit && dB?.explicit))
|
|
59662
|
+
return false;
|
|
59663
|
+
const assembledA = assembleDomain(model, channelA);
|
|
59664
|
+
const assembledB = assembleDomain(model, channelB);
|
|
59665
|
+
return hash(assembledA) === hash(assembledB);
|
|
59666
|
+
}
|
|
59667
|
+
/**
|
|
59668
|
+
* Assemble legends for a model. We group legends by the underlying field used by the encoding.
|
|
59669
|
+
*
|
|
59670
|
+
* @param model - The model to assemble legends for
|
|
59671
|
+
* @returns The assembled legends
|
|
59672
|
+
*/
|
|
59673
|
+
function assembleLegends(model) {
|
|
59674
|
+
const legendComponentIndex = model.component.legends;
|
|
59675
|
+
const legendsByGroup = {};
|
|
59676
|
+
for (const channel of keys(legendComponentIndex)) {
|
|
59677
|
+
const fieldKey = getFieldKeyForChannel(model, channel);
|
|
59678
|
+
const groupKey = getLegendGroupKey(fieldKey, channel);
|
|
59679
|
+
if (!legendsByGroup[groupKey]) {
|
|
59680
|
+
legendsByGroup[groupKey] = [{ channel, cmpt: legendComponentIndex[channel].clone() }];
|
|
59681
|
+
continue;
|
|
59682
|
+
}
|
|
59683
|
+
let mergedIntoExisting = false;
|
|
59684
|
+
for (const existing of legendsByGroup[groupKey]) {
|
|
59685
|
+
if (!legendsAreMergeCompatible(model, existing.channel, channel)) {
|
|
59686
|
+
continue;
|
|
59687
|
+
}
|
|
59688
|
+
const merged = mergeLegendComponent(existing.cmpt, legendComponentIndex[channel]);
|
|
59689
|
+
if (merged) {
|
|
59690
|
+
const typeA = model.getScaleType(existing.channel);
|
|
59691
|
+
const typeB = model.getScaleType(channel);
|
|
59692
|
+
if (typeA && typeB && hasDiscreteDomain(typeA) && hasDiscreteDomain(typeB)) {
|
|
59693
|
+
if (domainsExplicitAndEqual(model, existing.channel, channel)) {
|
|
59694
|
+
setImplicitLegendValues(existing.cmpt, getDiscreteValuesForChannel(model, existing.channel));
|
|
59695
|
+
}
|
|
59696
|
+
else {
|
|
59697
|
+
setImplicitLegendValues(existing.cmpt, unionDiscreteValuesForChannels(model, existing.channel, channel),
|
|
59698
|
+
// Warn when unioning discrete legend values so that users are aware
|
|
59699
|
+
legendValuesUnioned(existing.channel, channel));
|
|
59700
|
+
}
|
|
59701
|
+
}
|
|
59702
|
+
mergedIntoExisting = true;
|
|
59703
|
+
break;
|
|
59704
|
+
}
|
|
59705
|
+
}
|
|
59706
|
+
if (!mergedIntoExisting) {
|
|
59707
|
+
legendsByGroup[groupKey].push({ channel, cmpt: legendComponentIndex[channel].clone() });
|
|
59708
|
+
}
|
|
59709
|
+
}
|
|
59710
|
+
const legends = vals(legendsByGroup)
|
|
59711
|
+
.flat()
|
|
59712
|
+
.map((entry) => assembleLegend(entry.cmpt, model.config))
|
|
59713
|
+
.filter((l) => l !== undefined);
|
|
59714
|
+
return legends;
|
|
59715
|
+
}
|
|
59716
|
+
function assembleLegend(legendCmpt, config) {
|
|
59717
|
+
const { disable, labelExpr, selections, ...legend } = legendCmpt.combine();
|
|
59718
|
+
if (disable) {
|
|
59719
|
+
return undefined;
|
|
59720
|
+
}
|
|
59721
|
+
if (config.aria === false && legend.aria == undefined) {
|
|
59722
|
+
legend.aria = false;
|
|
59723
|
+
}
|
|
59724
|
+
if (legend.encode?.symbols) {
|
|
59725
|
+
const out = legend.encode.symbols.update;
|
|
59726
|
+
if (out.fill && out.fill['value'] !== 'transparent' && !out.stroke && !legend.stroke) {
|
|
59727
|
+
// For non color channel's legend, we need to override symbol stroke config from Vega config if stroke channel is not used.
|
|
59728
|
+
out.stroke = { value: 'transparent' };
|
|
59729
|
+
}
|
|
59730
|
+
// Remove properties that the legend is encoding.
|
|
59731
|
+
for (const property of LEGEND_SCALE_CHANNELS) {
|
|
59732
|
+
if (legend[property]) {
|
|
59733
|
+
delete out[property];
|
|
59734
|
+
}
|
|
59735
|
+
}
|
|
59736
|
+
}
|
|
59737
|
+
if (!legend.title) {
|
|
59738
|
+
// title schema doesn't include null, ''
|
|
59739
|
+
delete legend.title;
|
|
59740
|
+
}
|
|
59741
|
+
if (labelExpr !== undefined) {
|
|
59742
|
+
let expr = labelExpr;
|
|
59743
|
+
if (legend.encode?.labels?.update && isSignalRef(legend.encode.labels.update.text)) {
|
|
59744
|
+
expr = replaceAll(labelExpr, 'datum.label', legend.encode.labels.update.text.signal);
|
|
59745
|
+
}
|
|
59746
|
+
setLegendEncode(legend, 'labels', 'text', { signal: expr });
|
|
59747
|
+
}
|
|
59748
|
+
return legend;
|
|
59749
|
+
}
|
|
59750
|
+
|
|
59751
|
+
function assembleProjections(model) {
|
|
59752
|
+
if (isLayerModel(model) || isConcatModel(model)) {
|
|
59753
|
+
return assembleProjectionsForModelAndChildren(model);
|
|
59754
|
+
}
|
|
59755
|
+
else {
|
|
59756
|
+
return assembleProjectionForModel(model);
|
|
59757
|
+
}
|
|
59758
|
+
}
|
|
59759
|
+
function assembleProjectionsForModelAndChildren(model) {
|
|
59760
|
+
return model.children.reduce((projections, child) => {
|
|
59761
|
+
return projections.concat(child.assembleProjections());
|
|
59762
|
+
}, assembleProjectionForModel(model));
|
|
59763
|
+
}
|
|
59764
|
+
function assembleProjectionForModel(model) {
|
|
59765
|
+
const component = model.component.projection;
|
|
59766
|
+
if (!component || component.merged) {
|
|
59767
|
+
return [];
|
|
59768
|
+
}
|
|
59769
|
+
const projection = component.combine();
|
|
59770
|
+
const { name } = projection; // we need to extract name so that it is always present in the output and pass TS type validation
|
|
59771
|
+
if (!component.data) {
|
|
59772
|
+
// generate custom projection, no automatic fitting
|
|
59773
|
+
return [
|
|
59774
|
+
{
|
|
59775
|
+
name,
|
|
59776
|
+
// translate to center by default
|
|
59777
|
+
translate: { signal: '[width / 2, height / 2]' },
|
|
59778
|
+
// parameters, overwrite default translate if specified
|
|
59779
|
+
...projection,
|
|
59780
|
+
},
|
|
59781
|
+
];
|
|
59782
|
+
}
|
|
59783
|
+
else {
|
|
59784
|
+
// generate projection that uses extent fitting
|
|
59785
|
+
const size = {
|
|
59786
|
+
signal: `[${component.size.map((ref) => ref.signal).join(', ')}]`,
|
|
59787
|
+
};
|
|
59788
|
+
const fits = component.data.reduce((sources, data) => {
|
|
59789
|
+
const source = isSignalRef(data) ? data.signal : `data('${model.lookupDataSource(data)}')`;
|
|
59790
|
+
if (!contains(sources, source)) {
|
|
59791
|
+
// build a unique list of sources
|
|
59792
|
+
sources.push(source);
|
|
59793
|
+
}
|
|
59794
|
+
return sources;
|
|
59795
|
+
}, []);
|
|
59796
|
+
if (fits.length <= 0) {
|
|
59797
|
+
throw new Error("Projection's fit didn't find any data sources");
|
|
59798
|
+
}
|
|
59799
|
+
return [
|
|
59800
|
+
{
|
|
59801
|
+
name,
|
|
59802
|
+
size,
|
|
59803
|
+
fit: {
|
|
59804
|
+
signal: fits.length > 1 ? `[${fits.join(', ')}]` : fits[0],
|
|
59805
|
+
},
|
|
59806
|
+
...projection,
|
|
59807
|
+
},
|
|
59808
|
+
];
|
|
59809
|
+
}
|
|
59810
|
+
}
|
|
59811
|
+
|
|
59812
|
+
const PROJECTION_PROPERTIES = [
|
|
59813
|
+
'type',
|
|
59814
|
+
'clipAngle',
|
|
59815
|
+
'clipExtent',
|
|
59816
|
+
'center',
|
|
59817
|
+
'rotate',
|
|
59818
|
+
'precision',
|
|
59819
|
+
'reflectX',
|
|
59820
|
+
'reflectY',
|
|
59821
|
+
'coefficient',
|
|
59822
|
+
'distance',
|
|
59823
|
+
'fraction',
|
|
59824
|
+
'lobes',
|
|
59825
|
+
'parallel',
|
|
59826
|
+
'radius',
|
|
59827
|
+
'ratio',
|
|
59828
|
+
'spacing',
|
|
59829
|
+
'tilt',
|
|
59830
|
+
];
|
|
59831
|
+
|
|
59832
|
+
class ProjectionComponent extends Split {
|
|
59833
|
+
specifiedProjection;
|
|
59834
|
+
size;
|
|
59835
|
+
data;
|
|
59836
|
+
merged = false;
|
|
59837
|
+
constructor(name, specifiedProjection, size, data) {
|
|
59838
|
+
super({ ...specifiedProjection }, // all explicit properties of projection
|
|
59839
|
+
{ name });
|
|
59840
|
+
this.specifiedProjection = specifiedProjection;
|
|
59841
|
+
this.size = size;
|
|
59842
|
+
this.data = data;
|
|
59843
|
+
}
|
|
59844
|
+
/**
|
|
59845
|
+
* Whether the projection parameters should fit provided data.
|
|
59846
|
+
*/
|
|
59847
|
+
get isFit() {
|
|
59848
|
+
return !!this.data;
|
|
59849
|
+
}
|
|
59850
|
+
}
|
|
59851
|
+
|
|
59852
|
+
function parseProjection(model) {
|
|
59853
|
+
model.component.projection = isUnitModel(model) ? parseUnitProjection(model) : parseNonUnitProjections(model);
|
|
59854
|
+
}
|
|
59855
|
+
function parseUnitProjection(model) {
|
|
59856
|
+
if (model.hasProjection) {
|
|
59857
|
+
const proj = replaceExprRef(model.specifiedProjection);
|
|
59858
|
+
const fit = !(proj && (proj.scale != null || proj.translate != null));
|
|
59859
|
+
const size = fit ? [model.getSizeSignalRef('width'), model.getSizeSignalRef('height')] : undefined;
|
|
59860
|
+
const data = fit ? gatherFitData(model) : undefined;
|
|
59861
|
+
const projComp = new ProjectionComponent(model.projectionName(true), {
|
|
59862
|
+
...replaceExprRef(model.config.projection),
|
|
59863
|
+
...proj,
|
|
59864
|
+
}, size, data);
|
|
59865
|
+
if (!projComp.get('type')) {
|
|
59866
|
+
projComp.set('type', 'equalEarth', false);
|
|
59867
|
+
}
|
|
59868
|
+
return projComp;
|
|
59869
|
+
}
|
|
59870
|
+
return undefined;
|
|
59871
|
+
}
|
|
59872
|
+
function gatherFitData(model) {
|
|
59873
|
+
const data = [];
|
|
59874
|
+
const { encoding } = model;
|
|
59875
|
+
for (const posssiblePair of [
|
|
59876
|
+
[LONGITUDE, LATITUDE],
|
|
59877
|
+
[LONGITUDE2, LATITUDE2],
|
|
59878
|
+
]) {
|
|
59879
|
+
if (getFieldOrDatumDef(encoding[posssiblePair[0]]) || getFieldOrDatumDef(encoding[posssiblePair[1]])) {
|
|
59880
|
+
data.push({
|
|
59881
|
+
signal: model.getName(`geojson_${data.length}`),
|
|
59882
|
+
});
|
|
59883
|
+
}
|
|
59884
|
+
}
|
|
59885
|
+
if (model.channelHasField(SHAPE) && model.typedFieldDef(SHAPE).type === GEOJSON) {
|
|
59886
|
+
data.push({
|
|
59887
|
+
signal: model.getName(`geojson_${data.length}`),
|
|
59888
|
+
});
|
|
59889
|
+
}
|
|
59890
|
+
if (data.length === 0) {
|
|
59891
|
+
// main source is geojson, so we can just use that
|
|
59892
|
+
data.push(model.requestDataName(DataSourceType.Main));
|
|
59893
|
+
}
|
|
59894
|
+
return data;
|
|
59895
|
+
}
|
|
59896
|
+
function mergeIfNoConflict(first, second) {
|
|
59897
|
+
const allPropertiesShared = every(PROJECTION_PROPERTIES, (prop) => {
|
|
59898
|
+
// neither has the property
|
|
59899
|
+
if (!has$1(first.explicit, prop) && !has$1(second.explicit, prop)) {
|
|
59900
|
+
return true;
|
|
59901
|
+
}
|
|
59902
|
+
// both have property and an equal value for property
|
|
59903
|
+
if (has$1(first.explicit, prop) &&
|
|
59904
|
+
has$1(second.explicit, prop) &&
|
|
59905
|
+
// some properties might be signals or objects and require hashing for comparison
|
|
59906
|
+
deepEqual(first.get(prop), second.get(prop))) {
|
|
59907
|
+
return true;
|
|
59908
|
+
}
|
|
59909
|
+
return false;
|
|
59910
|
+
});
|
|
59911
|
+
const size = deepEqual(first.size, second.size);
|
|
59912
|
+
if (size) {
|
|
59913
|
+
if (allPropertiesShared) {
|
|
59914
|
+
return first;
|
|
59915
|
+
}
|
|
59916
|
+
else if (deepEqual(first.explicit, {})) {
|
|
59917
|
+
return second;
|
|
59918
|
+
}
|
|
59919
|
+
else if (deepEqual(second.explicit, {})) {
|
|
59920
|
+
return first;
|
|
59921
|
+
}
|
|
59922
|
+
}
|
|
59923
|
+
// if all properties don't match, let each unit spec have its own projection
|
|
59924
|
+
return null;
|
|
59925
|
+
}
|
|
59926
|
+
function parseNonUnitProjections(model) {
|
|
59927
|
+
if (model.children.length === 0) {
|
|
59928
|
+
return undefined;
|
|
59929
|
+
}
|
|
59930
|
+
let nonUnitProjection;
|
|
59931
|
+
// parse all children first
|
|
59932
|
+
for (const child of model.children) {
|
|
59933
|
+
parseProjection(child);
|
|
59934
|
+
}
|
|
59935
|
+
// analyze parsed projections, attempt to merge
|
|
59936
|
+
const mergable = every(model.children, (child) => {
|
|
59937
|
+
const projection = child.component.projection;
|
|
59938
|
+
if (!projection) {
|
|
59939
|
+
// child layer does not use a projection
|
|
59940
|
+
return true;
|
|
59941
|
+
}
|
|
59942
|
+
else if (!nonUnitProjection) {
|
|
59943
|
+
// cached 'projection' is null, cache this one
|
|
59944
|
+
nonUnitProjection = projection;
|
|
59945
|
+
return true;
|
|
59946
|
+
}
|
|
59947
|
+
else {
|
|
59948
|
+
const merge = mergeIfNoConflict(nonUnitProjection, projection);
|
|
59949
|
+
if (merge) {
|
|
59950
|
+
nonUnitProjection = merge;
|
|
59951
|
+
}
|
|
59952
|
+
return !!merge;
|
|
59953
|
+
}
|
|
59954
|
+
});
|
|
59955
|
+
// if cached one and all other children share the same projection,
|
|
59956
|
+
if (nonUnitProjection && mergable) {
|
|
59957
|
+
// so we can elevate it to the layer level
|
|
59958
|
+
const name = model.projectionName(true);
|
|
59959
|
+
const modelProjection = new ProjectionComponent(name, nonUnitProjection.specifiedProjection, nonUnitProjection.size, duplicate(nonUnitProjection.data));
|
|
59960
|
+
// rename and assign all others as merged
|
|
59961
|
+
for (const child of model.children) {
|
|
59962
|
+
const projection = child.component.projection;
|
|
59963
|
+
if (projection) {
|
|
59964
|
+
if (projection.isFit) {
|
|
59965
|
+
modelProjection.data.push(...child.component.projection.data);
|
|
59966
|
+
}
|
|
59967
|
+
child.renameProjection(projection.get('name'), name);
|
|
59968
|
+
projection.merged = true;
|
|
59969
|
+
}
|
|
59970
|
+
}
|
|
59971
|
+
return modelProjection;
|
|
59972
|
+
}
|
|
59973
|
+
return undefined;
|
|
59974
|
+
}
|
|
59975
|
+
|
|
59838
59976
|
function assembleScales(model) {
|
|
59839
59977
|
if (isLayerModel(model) || isConcatModel(model)) {
|
|
59840
59978
|
// For concat and layer, include scales of children too
|
|
@@ -64803,6 +64941,7 @@ var vegaLiteImport = /*#__PURE__*/Object.freeze({
|
|
|
64803
64941
|
isInternalField: isInternalField,
|
|
64804
64942
|
isNullOrFalse: isNullOrFalse,
|
|
64805
64943
|
isNumeric: isNumeric,
|
|
64944
|
+
isPrimitive: isPrimitive,
|
|
64806
64945
|
keys: keys,
|
|
64807
64946
|
logicalExpr: logicalExpr,
|
|
64808
64947
|
mergeDeep: mergeDeep$1,
|