@uwdata/mosaic-plot 0.5.0 → 0.6.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.
@@ -12810,8 +12810,7 @@ var castDouble = (expr) => cast(expr, "DOUBLE");
12810
12810
 
12811
12811
  // ../sql/src/datetime.js
12812
12812
  var epoch_ms = (expr) => {
12813
- const d = asColumn(expr);
12814
- return sql`(1000 * (epoch(${d}) - second(${d})) + millisecond(${d}))::DOUBLE`;
12813
+ return sql`epoch_ms(${asColumn(expr)})`;
12815
12814
  };
12816
12815
 
12817
12816
  // ../sql/src/spatial.js
@@ -13218,6 +13217,89 @@ function isDoubleQuoted(s2) {
13218
13217
  return s2[0] === '"' && s2[s2.length - 1] === '"';
13219
13218
  }
13220
13219
 
13220
+ // ../sql/src/scales.js
13221
+ var identity = (x3) => x3;
13222
+ function scaleLinear() {
13223
+ return {
13224
+ apply: identity,
13225
+ invert: identity,
13226
+ sqlApply: asColumn,
13227
+ sqlInvert: identity
13228
+ };
13229
+ }
13230
+ function scaleLog({ base } = {}) {
13231
+ if (base == null || base === Math.E) {
13232
+ return {
13233
+ apply: Math.log,
13234
+ invert: Math.exp,
13235
+ sqlApply: (c4) => sql`LN(${asColumn(c4)})`,
13236
+ sqlInvert: (c4) => sql`EXP(${c4})`
13237
+ };
13238
+ } else if (base === 10) {
13239
+ return {
13240
+ apply: Math.log10,
13241
+ invert: (x3) => Math.pow(10, x3),
13242
+ sqlApply: (c4) => sql`LOG(${asColumn(c4)})`,
13243
+ sqlInvert: (c4) => sql`POW(10, ${c4})`
13244
+ };
13245
+ } else {
13246
+ const b = +base;
13247
+ return {
13248
+ apply: (x3) => Math.log(x3) / Math.log(b),
13249
+ invert: (x3) => Math.pow(b, x3),
13250
+ sqlApply: (c4) => sql`LN(${asColumn(c4)}) / LN(${b})`,
13251
+ sqlInvert: (c4) => sql`POW(${b}, ${c4})`
13252
+ };
13253
+ }
13254
+ }
13255
+ function scaleSymlog({ constant: constant2 = 1 } = {}) {
13256
+ const _ = +constant2;
13257
+ return {
13258
+ apply: (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3)),
13259
+ invert: (x3) => Math.sign(x3) * Math.exp(Math.abs(x3) - _),
13260
+ sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(${_} + ABS(${c4}))`),
13261
+ sqlInvert: (c4) => sql`SIGN(${c4}) * (EXP(ABS(${c4})) - ${_})`
13262
+ };
13263
+ }
13264
+ function scaleSqrt() {
13265
+ return {
13266
+ apply: (x3) => Math.sign(x3) * Math.sqrt(Math.abs(x3)),
13267
+ invert: (x3) => Math.sign(x3) * x3 * x3,
13268
+ sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * SQRT(ABS(${c4}))`),
13269
+ sqlInvert: (c4) => sql`SIGN(${c4}) * (${c4}) ** 2`
13270
+ };
13271
+ }
13272
+ function scalePow({ exponent = 1 } = {}) {
13273
+ const e = +exponent;
13274
+ return {
13275
+ apply: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), e),
13276
+ invert: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), 1 / e),
13277
+ sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * POW(ABS(${c4}), ${e})`),
13278
+ sqlInvert: (c4) => sql`SIGN(${c4}) * POW(ABS(${c4}), 1/${e})`
13279
+ };
13280
+ }
13281
+ function scaleTime() {
13282
+ return {
13283
+ apply: (x3) => +x3,
13284
+ invert: (x3) => new Date(x3),
13285
+ sqlApply: (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4)),
13286
+ sqlInvert: identity
13287
+ };
13288
+ }
13289
+ var scales = {
13290
+ linear: scaleLinear,
13291
+ log: scaleLog,
13292
+ symlog: scaleSymlog,
13293
+ sqrt: scaleSqrt,
13294
+ pow: scalePow,
13295
+ time: scaleTime,
13296
+ utc: scaleTime
13297
+ };
13298
+ function scaleTransform(options) {
13299
+ const scale3 = scales[options.type];
13300
+ return scale3 ? { ...options, ...scale3(options) } : null;
13301
+ }
13302
+
13221
13303
  // ../sql/src/load/create.js
13222
13304
  function create(name, query, {
13223
13305
  replace = false,
@@ -13377,7 +13459,6 @@ function fnv_mix(a2) {
13377
13459
  }
13378
13460
 
13379
13461
  // ../core/src/DataCubeIndexer.js
13380
- var identity = (x3) => x3;
13381
13462
  var DataCubeIndexer = class {
13382
13463
  /**
13383
13464
  *
@@ -13470,10 +13551,10 @@ function getActiveView(clause) {
13470
13551
  let columns = clause.predicate?.columns;
13471
13552
  if (!schema || !columns)
13472
13553
  return null;
13473
- const { type: type2, scales, pixelSize = 1 } = schema;
13554
+ const { type: type2, scales: scales2, pixelSize = 1 } = schema;
13474
13555
  let predicate;
13475
- if (type2 === "interval" && scales) {
13476
- const bins2 = scales.map((s2) => binInterval(s2, pixelSize));
13556
+ if (type2 === "interval" && scales2) {
13557
+ const bins2 = scales2.map((s2) => binInterval(s2, pixelSize));
13477
13558
  if (bins2.some((b) => b == null))
13478
13559
  return null;
13479
13560
  if (bins2.length === 1) {
@@ -13486,7 +13567,7 @@ function getActiveView(clause) {
13486
13567
  );
13487
13568
  }
13488
13569
  } else if (type2 === "point") {
13489
- predicate = identity;
13570
+ predicate = (x3) => x3;
13490
13571
  columns = Object.fromEntries(columns.map((col) => [col.toString(), col]));
13491
13572
  } else {
13492
13573
  return null;
@@ -13494,39 +13575,15 @@ function getActiveView(clause) {
13494
13575
  return { source, columns, predicate };
13495
13576
  }
13496
13577
  function binInterval(scale3, pixelSize) {
13497
- const { type: type2, domain, range: range3 } = scale3;
13498
- let lift, toSql;
13499
- switch (type2) {
13500
- case "linear":
13501
- lift = identity;
13502
- toSql = asColumn;
13503
- break;
13504
- case "log":
13505
- lift = Math.log;
13506
- toSql = (c4) => sql`LN(${asColumn(c4)})`;
13507
- break;
13508
- case "symlog":
13509
- lift = (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3));
13510
- toSql = (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(1 + ABS(${c4}))`);
13511
- break;
13512
- case "sqrt":
13513
- lift = Math.sqrt;
13514
- toSql = (c4) => sql`SQRT(${asColumn(c4)})`;
13515
- break;
13516
- case "utc":
13517
- case "time":
13518
- lift = (x3) => +x3;
13519
- toSql = (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4));
13520
- break;
13578
+ const { apply: apply2, sqlApply } = scaleTransform(scale3);
13579
+ if (apply2) {
13580
+ const { domain, range: range3 } = scale3;
13581
+ const lo = apply2(Math.min(...domain));
13582
+ const hi = apply2(Math.max(...domain));
13583
+ const a2 = Math.abs(range3[1] - range3[0]) / (hi - lo) / pixelSize;
13584
+ const s2 = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
13585
+ return (value) => sql`${s2}FLOOR(${a2}::DOUBLE * (${sqlApply(value)} - ${lo}::DOUBLE))::INTEGER`;
13521
13586
  }
13522
- return lift ? binFunction(domain, range3, pixelSize, lift, toSql) : null;
13523
- }
13524
- function binFunction(domain, range3, pixelSize, lift, toSql) {
13525
- const lo = lift(Math.min(domain[0], domain[1]));
13526
- const hi = lift(Math.max(domain[0], domain[1]));
13527
- const a2 = Math.abs(lift(range3[1]) - lift(range3[0])) / (hi - lo) / pixelSize;
13528
- const s2 = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
13529
- return (value) => sql`${s2}FLOOR(${a2}::DOUBLE * (${toSql(value)} - ${lo}::DOUBLE))::INTEGER`;
13530
13587
  }
13531
13588
  var NO_INDEX = { from: NaN };
13532
13589
  function getIndexColumns(client) {
@@ -29271,10 +29328,10 @@ function createChannels(channels, data) {
29271
29328
  Object.entries(channels).map(([name, channel]) => [name, createChannel(data, channel, name)])
29272
29329
  );
29273
29330
  }
29274
- function valueObject(channels, scales) {
29331
+ function valueObject(channels, scales2) {
29275
29332
  const values2 = Object.fromEntries(
29276
29333
  Object.entries(channels).map(([name, { scale: scaleName, value }]) => {
29277
- const scale3 = scaleName == null ? null : scales[scaleName];
29334
+ const scale3 = scaleName == null ? null : scales2[scaleName];
29278
29335
  return [name, scale3 == null ? value : map2(value, scale3)];
29279
29336
  })
29280
29337
  );
@@ -30076,14 +30133,14 @@ function projectionAspectRatio(projection3) {
30076
30133
  }
30077
30134
  return defaultAspectRatio;
30078
30135
  }
30079
- function applyPosition(channels, scales, { projection: projection3 }) {
30136
+ function applyPosition(channels, scales2, { projection: projection3 }) {
30080
30137
  const { x: x3, y: y3 } = channels;
30081
30138
  let position3 = {};
30082
30139
  if (x3)
30083
30140
  position3.x = x3;
30084
30141
  if (y3)
30085
30142
  position3.y = y3;
30086
- position3 = valueObject(position3, scales);
30143
+ position3 = valueObject(position3, scales2);
30087
30144
  if (projection3 && x3?.scale === "x" && y3?.scale === "y")
30088
30145
  project("x", "y", position3, projection3);
30089
30146
  if (x3)
@@ -30821,7 +30878,7 @@ function createScales(channelsByScale, {
30821
30878
  facet: { label: facetLabel = globalLabel } = {},
30822
30879
  ...options
30823
30880
  } = {}) {
30824
- const scales = {};
30881
+ const scales2 = {};
30825
30882
  for (const [key, channels] of channelsByScale) {
30826
30883
  const scaleOptions = options[key];
30827
30884
  const scale3 = createScale(key, channels, {
@@ -30864,17 +30921,17 @@ function createScales(channelsByScale, {
30864
30921
  scale3.insetTop = +insetTop;
30865
30922
  scale3.insetBottom = +insetBottom;
30866
30923
  }
30867
- scales[key] = scale3;
30924
+ scales2[key] = scale3;
30868
30925
  }
30869
30926
  }
30870
- return scales;
30927
+ return scales2;
30871
30928
  }
30872
30929
  function createScaleFunctions(descriptors) {
30873
- const scales = {};
30874
- const scaleFunctions = { scales };
30930
+ const scales2 = {};
30931
+ const scaleFunctions = { scales: scales2 };
30875
30932
  for (const [key, descriptor] of Object.entries(descriptors)) {
30876
30933
  const { scale: scale3, type: type2, interval: interval2, label } = descriptor;
30877
- scales[key] = exposeScale(descriptor);
30934
+ scales2[key] = exposeScale(descriptor);
30878
30935
  scaleFunctions[key] = scale3;
30879
30936
  scale3.type = type2;
30880
30937
  if (interval2 != null)
@@ -30884,14 +30941,14 @@ function createScaleFunctions(descriptors) {
30884
30941
  }
30885
30942
  return scaleFunctions;
30886
30943
  }
30887
- function autoScaleRange(scales, dimensions) {
30888
- const { x: x3, y: y3, fx, fy } = scales;
30944
+ function autoScaleRange(scales2, dimensions) {
30945
+ const { x: x3, y: y3, fx, fy } = scales2;
30889
30946
  const superdimensions = fx || fy ? outerDimensions(dimensions) : dimensions;
30890
30947
  if (fx)
30891
30948
  autoScaleRangeX(fx, superdimensions);
30892
30949
  if (fy)
30893
30950
  autoScaleRangeY(fy, superdimensions);
30894
- const subdimensions = fx || fy ? innerDimensions(scales, dimensions) : dimensions;
30951
+ const subdimensions = fx || fy ? innerDimensions(scales2, dimensions) : dimensions;
30895
30952
  if (x3)
30896
30953
  autoScaleRangeX(x3, subdimensions);
30897
30954
  if (y3)
@@ -31234,11 +31291,11 @@ function scale2(options = {}) {
31234
31291
  throw new Error("invalid scale definition; no scale found");
31235
31292
  return scale3;
31236
31293
  }
31237
- function exposeScales(scales) {
31294
+ function exposeScales(scales2) {
31238
31295
  return (key) => {
31239
31296
  if (!registry.has(key = `${key}`))
31240
31297
  throw new Error(`unknown scale: ${key}`);
31241
- return scales[key];
31298
+ return scales2[key];
31242
31299
  };
31243
31300
  }
31244
31301
  function exposeScale({ scale: scale3, type: type2, domain, range: range3, interpolate, interval: interval2, transform: transform3, percent, pivot }) {
@@ -31278,7 +31335,7 @@ function exposeScale({ scale: scale3, type: type2, domain, range: range3, interp
31278
31335
  }
31279
31336
 
31280
31337
  // ../../node_modules/@observablehq/plot/src/dimensions.js
31281
- function createDimensions(scales, marks2, options = {}) {
31338
+ function createDimensions(scales2, marks2, options = {}) {
31282
31339
  let marginTopDefault = 0.5 - offset, marginRightDefault = 0.5 + offset, marginBottomDefault = 0.5 + offset, marginLeftDefault = 0.5 - offset;
31283
31340
  for (const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } of marks2) {
31284
31341
  if (marginTop2 > marginTopDefault)
@@ -31303,7 +31360,7 @@ function createDimensions(scales, marks2, options = {}) {
31303
31360
  marginLeft = +marginLeft;
31304
31361
  let {
31305
31362
  width = 640,
31306
- height = autoHeight(scales, options, {
31363
+ height = autoHeight(scales2, options, {
31307
31364
  width,
31308
31365
  marginTopDefault,
31309
31366
  marginRightDefault,
@@ -31321,7 +31378,7 @@ function createDimensions(scales, marks2, options = {}) {
31321
31378
  marginBottom,
31322
31379
  marginLeft
31323
31380
  };
31324
- if (scales.fx || scales.fy) {
31381
+ if (scales2.fx || scales2.fy) {
31325
31382
  let {
31326
31383
  margin: facetMargin,
31327
31384
  marginTop: facetMarginTop = facetMargin !== void 0 ? facetMargin : marginTop,
@@ -31667,8 +31724,8 @@ var Mark = class {
31667
31724
  }
31668
31725
  }
31669
31726
  }
31670
- scale(channels, scales, context) {
31671
- const values2 = valueObject(channels, scales);
31727
+ scale(channels, scales2, context) {
31728
+ const values2 = valueObject(channels, scales2);
31672
31729
  if (context.projection)
31673
31730
  this.project(channels, values2, context);
31674
31731
  return values2;
@@ -31726,7 +31783,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
31726
31783
  // Unlike other composed transforms, the render transform must be the
31727
31784
  // outermost render function because it will re-render dynamically in
31728
31785
  // response to pointer events.
31729
- render: composeRender(function(index2, scales, values2, dimensions, context, next) {
31786
+ render: composeRender(function(index2, scales2, values2, dimensions, context, next) {
31730
31787
  context = { ...context, pointerSticky: false };
31731
31788
  const svg = context.ownerSVGElement;
31732
31789
  const { data } = context.getMarkState(this);
@@ -31734,7 +31791,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
31734
31791
  if (!state)
31735
31792
  states.set(svg, state = { sticky: false, roots: [], renders: [] });
31736
31793
  let renderIndex = state.renders.push(render2) - 1;
31737
- const { x: x4, y: y4, fx, fy } = scales;
31794
+ const { x: x4, y: y4, fx, fy } = scales2;
31738
31795
  let tx = fx ? fx(index2.fx) - dimensions.marginLeft : 0;
31739
31796
  let ty = fy ? fy(index2.fy) - dimensions.marginTop : 0;
31740
31797
  if (x4?.bandwidth)
@@ -31790,7 +31847,7 @@ function pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, re
31790
31847
  const I = i == null ? [] : [i];
31791
31848
  if (faceted)
31792
31849
  I.fx = index2.fx, I.fy = index2.fy, I.fi = index2.fi;
31793
- const r = next(I, scales, values2, dimensions, context);
31850
+ const r = next(I, scales2, values2, dimensions, context);
31794
31851
  if (g) {
31795
31852
  if (faceted) {
31796
31853
  const p = g.parentNode;
@@ -32162,8 +32219,8 @@ var RuleX = class extends Mark {
32162
32219
  this.insetBottom = number5(insetBottom);
32163
32220
  markers(this, options);
32164
32221
  }
32165
- render(index2, scales, channels, dimensions, context) {
32166
- const { x: x3, y: y3 } = scales;
32222
+ render(index2, scales2, channels, dimensions, context) {
32223
+ const { x: x3, y: y3 } = scales2;
32167
32224
  const { x: X3, y1: Y13, y2: Y23 } = channels;
32168
32225
  const { width, height, marginTop, marginRight, marginLeft, marginBottom } = dimensions;
32169
32226
  const { insetTop, insetBottom } = this;
@@ -32192,8 +32249,8 @@ var RuleY = class extends Mark {
32192
32249
  this.insetLeft = number5(insetLeft);
32193
32250
  markers(this, options);
32194
32251
  }
32195
- render(index2, scales, channels, dimensions, context) {
32196
- const { x: x3, y: y3 } = scales;
32252
+ render(index2, scales2, channels, dimensions, context) {
32253
+ const { x: x3, y: y3 } = scales2;
32197
32254
  const { y: Y3, x1: X13, x2: X23 } = channels;
32198
32255
  const { width, height, marginTop, marginRight, marginLeft, marginBottom } = dimensions;
32199
32256
  const { insetLeft, insetRight } = this;
@@ -32315,8 +32372,8 @@ var Text = class extends Mark {
32315
32372
  this.splitLines = splitter2(this);
32316
32373
  this.clipLine = clipper(this);
32317
32374
  }
32318
- render(index2, scales, channels, dimensions, context) {
32319
- const { x: x3, y: y3 } = scales;
32375
+ render(index2, scales2, channels, dimensions, context) {
32376
+ const { x: x3, y: y3 } = scales2;
32320
32377
  const { x: X3, y: Y3, rotate: R, text: T, title: TL, fontSize: FS } = channels;
32321
32378
  const { rotate } = this;
32322
32379
  const [cx, cy] = applyFrameAnchor(this, dimensions);
@@ -32739,8 +32796,8 @@ var Vector2 = class extends Mark {
32739
32796
  this.anchor = keyword(anchor, "anchor", ["start", "middle", "end"]);
32740
32797
  this.frameAnchor = maybeFrameAnchor(frameAnchor);
32741
32798
  }
32742
- render(index2, scales, channels, dimensions, context) {
32743
- const { x: x3, y: y3 } = scales;
32799
+ render(index2, scales2, channels, dimensions, context) {
32800
+ const { x: x3, y: y3 } = scales2;
32744
32801
  const { x: X3, y: Y3, length: L, rotate: A5 } = channels;
32745
32802
  const { length: length4, rotate, anchor, shape, r } = this;
32746
32803
  const [cx, cy] = applyFrameAnchor(this, dimensions);
@@ -32892,8 +32949,8 @@ function axisKy(k2, anchor, data, {
32892
32949
  }) : null,
32893
32950
  !isNoneish(fill) && label !== null ? text(
32894
32951
  [],
32895
- labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales, dimensions) {
32896
- const scale3 = scales[k2];
32952
+ labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {
32953
+ const scale3 = scales2[k2];
32897
32954
  const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = k2 === "y" && dimensions.inset || dimensions;
32898
32955
  const cla = labelAnchor ?? (scale3.bandwidth ? "center" : "top");
32899
32956
  const clo = labelOffset ?? (anchor === "right" ? marginRight2 : marginLeft2) - 3;
@@ -32982,8 +33039,8 @@ function axisKx(k2, anchor, data, {
32982
33039
  }) : null,
32983
33040
  !isNoneish(fill) && label !== null ? text(
32984
33041
  [],
32985
- labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales, dimensions) {
32986
- const scale3 = scales[k2];
33042
+ labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {
33043
+ const scale3 = scales2[k2];
32987
33044
  const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = k2 === "x" && dimensions.inset || dimensions;
32988
33045
  const cla = labelAnchor ?? (scale3.bandwidth ? "center" : "right");
32989
33046
  const clo = labelOffset ?? (anchor === "top" ? marginTop2 : marginBottom2) - 3;
@@ -33227,9 +33284,9 @@ function labelOptions({
33227
33284
  }
33228
33285
  function axisMark(mark, k2, anchor, ariaLabel, data, options, initialize) {
33229
33286
  let channels;
33230
- function axisInitializer(data2, facets, _channels, scales, dimensions, context) {
33287
+ function axisInitializer(data2, facets, _channels, scales2, dimensions, context) {
33231
33288
  const initializeFacets = data2 == null && (k2 === "fx" || k2 === "fy");
33232
- const { [k2]: scale3 } = scales;
33289
+ const { [k2]: scale3 } = scales2;
33233
33290
  if (!scale3)
33234
33291
  throw new Error(`missing scale: ${k2}`);
33235
33292
  const domain = scale3.domain();
@@ -33516,13 +33573,13 @@ function legend(options = {}) {
33516
33573
  }
33517
33574
  throw new Error("unknown legend type; no scale found");
33518
33575
  }
33519
- function exposeLegends(scales, context, defaults23 = {}) {
33576
+ function exposeLegends(scales2, context, defaults23 = {}) {
33520
33577
  return (key, options) => {
33521
33578
  if (!legendRegistry.has(key))
33522
33579
  throw new Error(`unknown legend type: ${key}`);
33523
- if (!(key in scales))
33580
+ if (!(key in scales2))
33524
33581
  return;
33525
- return legendRegistry.get(key)(scales[key], legendOptions(context, defaults23[key], options), (key2) => scales[key2]);
33582
+ return legendRegistry.get(key)(scales2[key], legendOptions(context, defaults23[key], options), (key2) => scales2[key2]);
33526
33583
  };
33527
33584
  }
33528
33585
  function legendOptions({ className, ...context }, { label, ticks: ticks2, tickFormat: tickFormat2 } = {}, options) {
@@ -33555,12 +33612,12 @@ function interpolateOpacity(color3) {
33555
33612
  const { r, g, b } = rgb(color3) || rgb(0, 0, 0);
33556
33613
  return (t) => `rgba(${r},${g},${b},${t})`;
33557
33614
  }
33558
- function createLegends(scales, context, options) {
33615
+ function createLegends(scales2, context, options) {
33559
33616
  const legends = [];
33560
33617
  for (const [key, value] of legendRegistry) {
33561
33618
  const o = options[key];
33562
- if (o?.legend && key in scales) {
33563
- const legend2 = value(scales[key], legendOptions(context, scales[key], o), (key2) => scales[key2]);
33619
+ if (o?.legend && key in scales2) {
33620
+ const legend2 = value(scales2[key], legendOptions(context, scales2[key], o), (key2) => scales2[key2]);
33564
33621
  if (legend2 != null)
33565
33622
  legends.push(legend2);
33566
33623
  }
@@ -33603,7 +33660,7 @@ var Frame = class extends Mark {
33603
33660
  this.rx = number5(rx);
33604
33661
  this.ry = number5(ry);
33605
33662
  }
33606
- render(index2, scales, channels, dimensions, context) {
33663
+ render(index2, scales2, channels, dimensions, context) {
33607
33664
  const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
33608
33665
  const { anchor, insetTop, insetRight, insetBottom, insetLeft, rx, ry } = this;
33609
33666
  const x12 = marginLeft + insetLeft;
@@ -33698,9 +33755,9 @@ var Tip = class extends Mark {
33698
33755
  this.clipLine = clipper(this);
33699
33756
  this.format = { ...format3 };
33700
33757
  }
33701
- render(index2, scales, values2, dimensions, context) {
33758
+ render(index2, scales2, values2, dimensions, context) {
33702
33759
  const mark = this;
33703
- const { x: x3, y: y3, fx, fy } = scales;
33760
+ const { x: x3, y: y3, fx, fy } = scales2;
33704
33761
  const { ownerSVGElement: svg, document: document2 } = context;
33705
33762
  const { anchor, monospace, lineHeight, lineWidth } = this;
33706
33763
  const { textPadding: r, pointerSize: m, pathFilter } = this;
@@ -33718,7 +33775,7 @@ var Tip = class extends Mark {
33718
33775
  sources = values2.channels;
33719
33776
  format3 = formatTitle;
33720
33777
  } else {
33721
- sources = getSourceChannels.call(this, values2, scales);
33778
+ sources = getSourceChannels.call(this, values2, scales2);
33722
33779
  format3 = formatChannels;
33723
33780
  }
33724
33781
  const g = create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(
@@ -33728,7 +33785,7 @@ var Tip = class extends Mark {
33728
33785
  this.setAttribute("fill", "currentColor");
33729
33786
  this.setAttribute("fill-opacity", 1);
33730
33787
  this.setAttribute("stroke", "none");
33731
- const lines = format3.call(mark, i, index2, sources, scales, values2);
33788
+ const lines = format3.call(mark, i, index2, sources, scales2, values2);
33732
33789
  if (typeof lines === "string") {
33733
33790
  for (const line2 of mark.splitLines(lines)) {
33734
33791
  renderLine(that, { value: mark.clipLine(line2) });
@@ -33866,7 +33923,7 @@ function getPath(anchor, m, r, width, height) {
33866
33923
  return `M0,0l${m / 2},${-m / 2}v${m / 2 - h / 2}h${w}v${h}h${-w}v${m / 2 - h / 2}z`;
33867
33924
  }
33868
33925
  }
33869
- function getSourceChannels({ channels }, scales) {
33926
+ function getSourceChannels({ channels }, scales2) {
33870
33927
  const sources = {};
33871
33928
  let format3 = this.format;
33872
33929
  format3 = maybeExpandPairedFormat(format3, channels, "x");
@@ -33892,18 +33949,18 @@ function getSourceChannels({ channels }, scales) {
33892
33949
  sources[key] = source;
33893
33950
  }
33894
33951
  if (this.facet) {
33895
- if (scales.fx && !("fx" in format3))
33952
+ if (scales2.fx && !("fx" in format3))
33896
33953
  sources.fx = true;
33897
- if (scales.fy && !("fy" in format3))
33954
+ if (scales2.fy && !("fy" in format3))
33898
33955
  sources.fy = true;
33899
33956
  }
33900
33957
  for (const key in sources) {
33901
33958
  const format4 = this.format[key];
33902
33959
  if (typeof format4 === "string") {
33903
- const value = sources[key]?.value ?? scales[key]?.domain() ?? [];
33960
+ const value = sources[key]?.value ?? scales2[key]?.domain() ?? [];
33904
33961
  this.format[key] = (isTemporal(value) ? utcFormat : format)(format4);
33905
33962
  } else if (format4 === void 0 || format4 === true) {
33906
- const scale3 = scales[key];
33963
+ const scale3 = scales2[key];
33907
33964
  this.format[key] = scale3?.bandwidth ? inferTickFormat(scale3, scale3.domain()) : formatDefault;
33908
33965
  }
33909
33966
  }
@@ -33924,11 +33981,11 @@ function maybeExpandPairedFormat(format3, channels, key) {
33924
33981
  function formatTitle(i, index2, { title }) {
33925
33982
  return formatDefault(title.value[i], i);
33926
33983
  }
33927
- function* formatChannels(i, index2, channels, scales, values2) {
33984
+ function* formatChannels(i, index2, channels, scales2, values2) {
33928
33985
  for (const key in channels) {
33929
33986
  if (key === "fx" || key === "fy") {
33930
33987
  yield {
33931
- label: formatLabel(scales, channels, key),
33988
+ label: formatLabel(scales2, channels, key),
33932
33989
  value: this.format[key](index2[key], i)
33933
33990
  };
33934
33991
  continue;
@@ -33940,12 +33997,12 @@ function* formatChannels(i, index2, channels, scales, values2) {
33940
33997
  const channel = channels[key];
33941
33998
  if (key === "x2" && "x1" in channels) {
33942
33999
  yield {
33943
- label: formatPairLabel(scales, channels, "x"),
34000
+ label: formatPairLabel(scales2, channels, "x"),
33944
34001
  value: formatPair(this.format.x2, channels.x1, channel, i)
33945
34002
  };
33946
34003
  } else if (key === "y2" && "y1" in channels) {
33947
34004
  yield {
33948
- label: formatPairLabel(scales, channels, "y"),
34005
+ label: formatPairLabel(scales2, channels, "y"),
33949
34006
  value: formatPair(this.format.y2, channels.y1, channel, i)
33950
34007
  };
33951
34008
  } else {
@@ -33954,7 +34011,7 @@ function* formatChannels(i, index2, channels, scales, values2) {
33954
34011
  if (!defined(value) && scale3 == null)
33955
34012
  continue;
33956
34013
  yield {
33957
- label: formatLabel(scales, channels, key),
34014
+ label: formatLabel(scales2, channels, key),
33958
34015
  value: this.format[key](value, i),
33959
34016
  color: scale3 === "color" ? values2[key][i] : null,
33960
34017
  opacity: scale3 === "opacity" ? values2[key][i] : null
@@ -33965,14 +34022,14 @@ function* formatChannels(i, index2, channels, scales, values2) {
33965
34022
  function formatPair(formatValue, c1, c22, i) {
33966
34023
  return c22.hint?.length ? `${formatValue(c22.value[i] - c1.value[i], i)}` : `${formatValue(c1.value[i], i)}\u2013${formatValue(c22.value[i], i)}`;
33967
34024
  }
33968
- function formatPairLabel(scales, channels, key) {
33969
- const l1 = formatLabel(scales, channels, `${key}1`, key);
33970
- const l2 = formatLabel(scales, channels, `${key}2`, key);
34025
+ function formatPairLabel(scales2, channels, key) {
34026
+ const l1 = formatLabel(scales2, channels, `${key}1`, key);
34027
+ const l2 = formatLabel(scales2, channels, `${key}2`, key);
33971
34028
  return l1 === l2 ? l1 : `${l1}\u2013${l2}`;
33972
34029
  }
33973
- function formatLabel(scales, channels, key, defaultLabel = key) {
34030
+ function formatLabel(scales2, channels, key, defaultLabel = key) {
33974
34031
  const channel = channels[key];
33975
- const scale3 = scales[channel?.scale ?? key];
34032
+ const scale3 = scales2[channel?.scale ?? key];
33976
34033
  return String(scale3?.label ?? channel?.label ?? defaultLabel);
33977
34034
  }
33978
34035
 
@@ -34047,10 +34104,10 @@ function plot(options = {}) {
34047
34104
  const scaleDescriptors = createScales(addScaleChannels(channelsByScale, stateByMark, options), options);
34048
34105
  const dimensions = createDimensions(scaleDescriptors, marks2, options);
34049
34106
  autoScaleRange(scaleDescriptors, dimensions);
34050
- const scales = createScaleFunctions(scaleDescriptors);
34051
- const { fx, fy } = scales;
34107
+ const scales2 = createScaleFunctions(scaleDescriptors);
34108
+ const { fx, fy } = scales2;
34052
34109
  const subdimensions = fx || fy ? innerDimensions(scaleDescriptors, dimensions) : dimensions;
34053
- const superdimensions = fx || fy ? actualDimensions(scales, dimensions) : dimensions;
34110
+ const superdimensions = fx || fy ? actualDimensions(scales2, dimensions) : dimensions;
34054
34111
  const context = createContext(options);
34055
34112
  const document2 = context.document;
34056
34113
  const svg = creator_default("svg").call(document2.documentElement);
@@ -34076,7 +34133,7 @@ function plot(options = {}) {
34076
34133
  for (const [mark, state] of stateByMark) {
34077
34134
  if (mark.initializer != null) {
34078
34135
  const dimensions2 = mark.facet === "super" ? superdimensions : subdimensions;
34079
- const update2 = mark.initializer(state.data, state.facets, state.channels, scales, dimensions2, context);
34136
+ const update2 = mark.initializer(state.data, state.facets, state.channels, scales2, dimensions2, context);
34080
34137
  if (update2.data !== void 0) {
34081
34138
  state.data = update2.data;
34082
34139
  }
@@ -34106,8 +34163,8 @@ function plot(options = {}) {
34106
34163
  const newScaleDescriptors = inheritScaleLabels(createScales(newChannelsByScale, options), scaleDescriptors);
34107
34164
  const { scales: newExposedScales, ...newScales } = createScaleFunctions(newScaleDescriptors);
34108
34165
  Object.assign(scaleDescriptors, newScaleDescriptors);
34109
- Object.assign(scales, newScales);
34110
- Object.assign(scales.scales, newExposedScales);
34166
+ Object.assign(scales2, newScales);
34167
+ Object.assign(scales2.scales, newExposedScales);
34111
34168
  }
34112
34169
  let facetDomains, facetTranslate;
34113
34170
  if (facets !== void 0) {
@@ -34116,7 +34173,7 @@ function plot(options = {}) {
34116
34173
  facetTranslate = facetTranslator(fx, fy, dimensions);
34117
34174
  }
34118
34175
  for (const [mark, state] of stateByMark) {
34119
- state.values = mark.scale(state.channels, scales, context);
34176
+ state.values = mark.scale(state.channels, scales2, context);
34120
34177
  }
34121
34178
  const { width, height } = dimensions;
34122
34179
  select_default2(svg).attr("class", className).attr("fill", "currentColor").attr("font-family", "system-ui, sans-serif").attr("font-size", 10).attr("text-anchor", "middle").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("aria-label", ariaLabel).attr("aria-description", ariaDescription).call(
@@ -34147,7 +34204,7 @@ function plot(options = {}) {
34147
34204
  if (index2.length === 0)
34148
34205
  continue;
34149
34206
  }
34150
- const node = mark.render(index2, scales, values2, superdimensions, context);
34207
+ const node = mark.render(index2, scales2, values2, superdimensions, context);
34151
34208
  if (node == null)
34152
34209
  continue;
34153
34210
  svg.appendChild(node);
@@ -34167,7 +34224,7 @@ function plot(options = {}) {
34167
34224
  index2 = subarray(index2);
34168
34225
  index2.fx = f.x, index2.fy = f.y, index2.fi = f.i;
34169
34226
  }
34170
- const node = mark.render(index2, scales, values2, subdimensions, context);
34227
+ const node = mark.render(index2, scales2, values2, subdimensions, context);
34171
34228
  if (node == null)
34172
34229
  continue;
34173
34230
  (g ??= select_default2(svg).append("g")).append(() => node).datum(f);
@@ -34195,7 +34252,7 @@ function plot(options = {}) {
34195
34252
  if (caption != null)
34196
34253
  figure.append(createFigcaption(document2, caption));
34197
34254
  }
34198
- figure.scale = exposeScales(scales.scales);
34255
+ figure.scale = exposeScales(scales2.scales);
34199
34256
  figure.legend = exposeLegends(scaleDescriptors, context, options);
34200
34257
  figure.projection = context.projection;
34201
34258
  const w = consumeWarnings();
@@ -34342,7 +34399,7 @@ function maybeMarkFacet(mark, topFacetState, options) {
34342
34399
  }
34343
34400
  }
34344
34401
  function derive(mark, options = {}) {
34345
- return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales, dimensions, context) => {
34402
+ return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, context) => {
34346
34403
  return context.getMarkState(mark);
34347
34404
  });
34348
34405
  }
@@ -34517,10 +34574,10 @@ function hasPositionChannel(k2, marks2) {
34517
34574
  }
34518
34575
  return false;
34519
34576
  }
34520
- function inheritScaleLabels(newScales, scales) {
34577
+ function inheritScaleLabels(newScales, scales2) {
34521
34578
  for (const key in newScales) {
34522
34579
  const newScale = newScales[key];
34523
- const scale3 = scales[key];
34580
+ const scale3 = scales2[key];
34524
34581
  if (newScale.label === void 0 && scale3) {
34525
34582
  newScale.label = scale3.label;
34526
34583
  }
@@ -35408,9 +35465,9 @@ var Area = class extends Mark {
35408
35465
  filter(index2) {
35409
35466
  return index2;
35410
35467
  }
35411
- render(index2, scales, channels, dimensions, context) {
35468
+ render(index2, scales2, channels, dimensions, context) {
35412
35469
  const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;
35413
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales, 0, 0).call(
35470
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2, 0, 0).call(
35414
35471
  (g) => g.selectAll().data(groupIndex(index2, [X13, Y13, X23, Y23], this, channels)).enter().append("path").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).attr(
35415
35472
  "d",
35416
35473
  area_default3().curve(this.curve).defined((i) => i >= 0).x0((i) => X13[i]).y0((i) => Y13[i]).x1((i) => X23[i]).y1((i) => Y23[i])
@@ -35461,10 +35518,10 @@ var Link = class extends Mark {
35461
35518
  super.project(channels, values2, context);
35462
35519
  }
35463
35520
  }
35464
- render(index2, scales, channels, dimensions, context) {
35521
+ render(index2, scales2, channels, dimensions, context) {
35465
35522
  const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;
35466
35523
  const { curve } = this;
35467
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call(
35524
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
35468
35525
  (g) => g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr(
35469
35526
  "d",
35470
35527
  curve === curveAuto && context.projection ? sphereLink(context.projection, X13, Y13, X23, Y23) : (i) => {
@@ -35559,13 +35616,13 @@ var Arrow = class extends Mark {
35559
35616
  this.insetEnd = +insetEnd;
35560
35617
  this.sweep = maybeSweep(sweep);
35561
35618
  }
35562
- render(index2, scales, channels, dimensions, context) {
35619
+ render(index2, scales2, channels, dimensions, context) {
35563
35620
  const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13, SW } = channels;
35564
35621
  const { strokeWidth, bend, headAngle, headLength, insetStart, insetEnd } = this;
35565
35622
  const sw = SW ? (i) => SW[i] : constant(strokeWidth === void 0 ? 1 : strokeWidth);
35566
35623
  const wingAngle = headAngle * radians3 / 2;
35567
35624
  const wingScale = headLength / 1.5;
35568
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call(
35625
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
35569
35626
  (g) => g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", (i) => {
35570
35627
  let x12 = X13[i], y12 = Y13[i], x22 = X23[i], y22 = Y23[i];
35571
35628
  const lineLength = Math.hypot(x22 - x12, y22 - y12);
@@ -35654,17 +35711,17 @@ var AbstractBar = class extends Mark {
35654
35711
  this.rx = impliedString(rx, "auto");
35655
35712
  this.ry = impliedString(ry, "auto");
35656
35713
  }
35657
- render(index2, scales, channels, dimensions, context) {
35714
+ render(index2, scales2, channels, dimensions, context) {
35658
35715
  const { rx, ry } = this;
35659
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales).call(
35660
- (g) => g.selectAll().data(index2).enter().append("rect").call(applyDirectStyles, this).attr("x", this._x(scales, channels, dimensions)).attr("width", this._width(scales, channels, dimensions)).attr("y", this._y(scales, channels, dimensions)).attr("height", this._height(scales, channels, dimensions)).call(applyAttr, "rx", rx).call(applyAttr, "ry", ry).call(applyChannelStyles, this, channels)
35716
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(
35717
+ (g) => g.selectAll().data(index2).enter().append("rect").call(applyDirectStyles, this).attr("x", this._x(scales2, channels, dimensions)).attr("width", this._width(scales2, channels, dimensions)).attr("y", this._y(scales2, channels, dimensions)).attr("height", this._height(scales2, channels, dimensions)).call(applyAttr, "rx", rx).call(applyAttr, "ry", ry).call(applyChannelStyles, this, channels)
35661
35718
  ).node();
35662
35719
  }
35663
- _x(scales, { x: X3 }, { marginLeft }) {
35720
+ _x(scales2, { x: X3 }, { marginLeft }) {
35664
35721
  const { insetLeft } = this;
35665
35722
  return X3 ? (i) => X3[i] + insetLeft : marginLeft + insetLeft;
35666
35723
  }
35667
- _y(scales, { y: Y3 }, { marginTop }) {
35724
+ _y(scales2, { y: Y3 }, { marginTop }) {
35668
35725
  const { insetTop } = this;
35669
35726
  return Y3 ? (i) => Y3[i] + insetTop : marginTop + insetTop;
35670
35727
  }
@@ -35822,8 +35879,8 @@ var Dot = class extends Mark {
35822
35879
  };
35823
35880
  }
35824
35881
  }
35825
- render(index2, scales, channels, dimensions, context) {
35826
- const { x: x3, y: y3 } = scales;
35882
+ render(index2, scales2, channels, dimensions, context) {
35883
+ const { x: x3, y: y3 } = scales2;
35827
35884
  const { x: X3, y: Y3, r: R, rotate: A5, symbol: S } = channels;
35828
35885
  const { r, rotate, symbol: symbol2 } = this;
35829
35886
  const [cx, cy] = applyFrameAnchor(this, dimensions);
@@ -35917,10 +35974,10 @@ var Line = class extends Mark {
35917
35974
  super.project(channels, values2, context);
35918
35975
  }
35919
35976
  }
35920
- render(index2, scales, channels, dimensions, context) {
35977
+ render(index2, scales2, channels, dimensions, context) {
35921
35978
  const { x: X3, y: Y3 } = channels;
35922
35979
  const { curve } = this;
35923
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call(
35980
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
35924
35981
  (g) => g.selectAll().data(groupIndex(index2, [X3, Y3], this, channels)).enter().append("path").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).call(applyGroupedMarkers, this, channels, context).attr(
35925
35982
  "d",
35926
35983
  curve === curveAuto && context.projection ? sphereLine(context.projection, X3, Y3) : line_default2().curve(curve).defined((i) => i >= 0).x((i) => X3[i]).y((i) => Y3[i])
@@ -35994,8 +36051,8 @@ var Rect = class extends Mark {
35994
36051
  this.rx = impliedString(rx, "auto");
35995
36052
  this.ry = impliedString(ry, "auto");
35996
36053
  }
35997
- render(index2, scales, channels, dimensions, context) {
35998
- const { x: x3, y: y3 } = scales;
36054
+ render(index2, scales2, channels, dimensions, context) {
36055
+ const { x: x3, y: y3 } = scales2;
35999
36056
  const { x1: X13, y1: Y13, x2: X23, y2: Y23 } = channels;
36000
36057
  const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
36001
36058
  const { projection: projection3 } = context;
@@ -36771,9 +36828,9 @@ var AbstractTick = class extends Mark {
36771
36828
  super(data, channels, options, defaults15);
36772
36829
  markers(this, options);
36773
36830
  }
36774
- render(index2, scales, channels, dimensions, context) {
36775
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales).call(
36776
- (g) => g.selectAll().data(index2).enter().append("line").call(applyDirectStyles, this).attr("x1", this._x1(scales, channels, dimensions)).attr("x2", this._x2(scales, channels, dimensions)).attr("y1", this._y1(scales, channels, dimensions)).attr("y2", this._y2(scales, channels, dimensions)).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)
36831
+ render(index2, scales2, channels, dimensions, context) {
36832
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(
36833
+ (g) => g.selectAll().data(index2).enter().append("line").call(applyDirectStyles, this).attr("x1", this._x1(scales2, channels, dimensions)).attr("x2", this._x2(scales2, channels, dimensions)).attr("y1", this._y1(scales2, channels, dimensions)).attr("y2", this._y2(scales2, channels, dimensions)).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)
36777
36834
  ).node();
36778
36835
  }
36779
36836
  };
@@ -36794,10 +36851,10 @@ var TickX = class extends AbstractTick {
36794
36851
  _transform(selection2, mark, { x: x3 }) {
36795
36852
  selection2.call(applyTransform, mark, { x: x3 }, offset, 0);
36796
36853
  }
36797
- _x1(scales, { x: X3 }) {
36854
+ _x1(scales2, { x: X3 }) {
36798
36855
  return (i) => X3[i];
36799
36856
  }
36800
- _x2(scales, { x: X3 }) {
36857
+ _x2(scales2, { x: X3 }) {
36801
36858
  return (i) => X3[i];
36802
36859
  }
36803
36860
  _y1({ y: y3 }, { y: Y3 }, { marginTop }) {
@@ -36834,10 +36891,10 @@ var TickY = class extends AbstractTick {
36834
36891
  const { insetRight } = this;
36835
36892
  return X3 && x3 ? (i) => X3[i] + x3.bandwidth() - insetRight : width - marginRight - insetRight;
36836
36893
  }
36837
- _y1(scales, { y: Y3 }) {
36894
+ _y1(scales2, { y: Y3 }) {
36838
36895
  return (i) => Y3[i];
36839
36896
  }
36840
- _y2(scales, { y: Y3 }) {
36897
+ _y2(scales2, { y: Y3 }) {
36841
36898
  return (i) => Y3[i];
36842
36899
  }
36843
36900
  };
@@ -36997,11 +37054,11 @@ var Raster = class extends AbstractRaster {
36997
37054
  this.imageRendering = impliedString(imageRendering, "auto");
36998
37055
  }
36999
37056
  // Ignore the color scale, so the fill channel is returned unscaled.
37000
- scale(channels, { color: color3, ...scales }, context) {
37001
- return super.scale(channels, scales, context);
37057
+ scale(channels, { color: color3, ...scales2 }, context) {
37058
+ return super.scale(channels, scales2, context);
37002
37059
  }
37003
- render(index2, scales, values2, dimensions, context) {
37004
- const color3 = scales[values2.channels.fill?.scale] ?? ((x3) => x3);
37060
+ render(index2, scales2, values2, dimensions, context) {
37061
+ const color3 = scales2[values2.channels.fill?.scale] ?? ((x3) => x3);
37005
37062
  const { x: X3, y: Y3 } = values2;
37006
37063
  const { document: document2 } = context;
37007
37064
  const [x12, y12, x22, y22] = renderBounds(values2, dimensions, context);
@@ -37050,7 +37107,7 @@ var Raster = class extends AbstractRaster {
37050
37107
  if (this.blur > 0)
37051
37108
  blurImage(image2, this.blur);
37052
37109
  context2d.putImageData(image2, 0, 0);
37053
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call(
37110
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
37054
37111
  (g2) => g2.append("image").attr("transform", `translate(${x12},${y12}) scale(${Math.sign(x22 - x12)},${Math.sign(y22 - y12)})`).attr("width", Math.abs(dx)).attr("height", Math.abs(dy)).attr("preserveAspectRatio", "none").call(applyAttr, "image-rendering", this.imageRendering).call(applyDirectStyles, this).attr("xlink:href", canvas.toDataURL())
37055
37112
  ).node();
37056
37113
  }
@@ -37082,7 +37139,7 @@ function renderBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, dimensions, { proj
37082
37139
  y22 && projection3 == null ? y22[0] : height - marginBottom
37083
37140
  ];
37084
37141
  }
37085
- function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales, dimensions, context) {
37142
+ function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales2, dimensions, context) {
37086
37143
  const channels = {};
37087
37144
  if (x12)
37088
37145
  channels.x1 = x12;
@@ -37092,19 +37149,19 @@ function rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales, dimensions
37092
37149
  channels.x2 = x22;
37093
37150
  if (y22)
37094
37151
  channels.y2 = y22;
37095
- return renderBounds(valueObject(channels, scales), dimensions, context);
37152
+ return renderBounds(valueObject(channels, scales2), dimensions, context);
37096
37153
  }
37097
37154
  function sampler(name, options = {}) {
37098
37155
  const { [name]: value } = options;
37099
37156
  if (typeof value !== "function")
37100
37157
  throw new Error(`invalid ${name}: not a function`);
37101
- return initializer({ ...options, [name]: void 0 }, function(data, facets, channels, scales, dimensions, context) {
37102
- const { x: x3, y: y3 } = scales;
37158
+ return initializer({ ...options, [name]: void 0 }, function(data, facets, channels, scales2, dimensions, context) {
37159
+ const { x: x3, y: y3 } = scales2;
37103
37160
  if (!x3)
37104
37161
  throw new Error("missing scale: x");
37105
37162
  if (!y3)
37106
37163
  throw new Error("missing scale: y");
37107
- const [x12, y12, x22, y22] = rasterBounds(channels, scales, dimensions, context);
37164
+ const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);
37108
37165
  const dx = x22 - x12;
37109
37166
  const dy = y22 - y12;
37110
37167
  const { pixelSize: k2 } = this;
@@ -37414,18 +37471,18 @@ var Contour = class extends AbstractRaster {
37414
37471
  filter(index2, { x: x3, y: y3, value, ...channels }, values2) {
37415
37472
  return super.filter(index2, channels, values2);
37416
37473
  }
37417
- render(index2, scales, channels, dimensions, context) {
37474
+ render(index2, scales2, channels, dimensions, context) {
37418
37475
  const { geometry: G } = channels;
37419
37476
  const path2 = path_default();
37420
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call((g) => {
37477
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {
37421
37478
  g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", (i) => path2(G[i])).call(applyChannelStyles, this, channels);
37422
37479
  }).node();
37423
37480
  }
37424
37481
  };
37425
37482
  function contourGeometry({ thresholds, interval: interval2, ...options }) {
37426
37483
  thresholds = maybeThresholds(thresholds, interval2, thresholdSturges);
37427
- return initializer(options, function(data, facets, channels, scales, dimensions, context) {
37428
- const [x12, y12, x22, y22] = rasterBounds(channels, scales, dimensions, context);
37484
+ return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
37485
+ const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);
37429
37486
  const dx = x22 - x12;
37430
37487
  const dy = y22 - y12;
37431
37488
  const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;
@@ -37434,7 +37491,7 @@ function contourGeometry({ thresholds, interval: interval2, ...options }) {
37434
37491
  const V = channels.value.value;
37435
37492
  const VV = [];
37436
37493
  if (this.interpolate) {
37437
- const { x: X3, y: Y3 } = applyPosition(channels, scales, context);
37494
+ const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);
37438
37495
  const IX = map2(X3, (x3) => (x3 - x12) * kx2, Float64Array);
37439
37496
  const IY = map2(Y3, (y3) => (y3 - y12) * ky2, Float64Array);
37440
37497
  const ichannels = [channels.x, channels.y, channels.value];
@@ -37645,8 +37702,8 @@ var DelaunayLink = class extends Mark {
37645
37702
  this.curve = maybeCurve(curve, tension);
37646
37703
  markers(this, options);
37647
37704
  }
37648
- render(index2, scales, channels, dimensions, context) {
37649
- const { x: x3, y: y3 } = scales;
37705
+ render(index2, scales2, channels, dimensions, context) {
37706
+ const { x: x3, y: y3 } = scales2;
37650
37707
  const { x: X3, y: Y3, z: Z } = channels;
37651
37708
  const { curve } = this;
37652
37709
  const [cx, cy] = applyFrameAnchor(this, dimensions);
@@ -37712,8 +37769,8 @@ var AbstractDelaunayMark = class extends Mark {
37712
37769
  defaults23
37713
37770
  );
37714
37771
  }
37715
- render(index2, scales, channels, dimensions, context) {
37716
- const { x: x3, y: y3 } = scales;
37772
+ render(index2, scales2, channels, dimensions, context) {
37773
+ const { x: x3, y: y3 } = scales2;
37717
37774
  const { x: X3, y: Y3, z: Z } = channels;
37718
37775
  const [cx, cy] = applyFrameAnchor(this, dimensions);
37719
37776
  const xi = X3 ? (i) => X3[i] : constant(cx);
@@ -37759,8 +37816,8 @@ var Voronoi2 = class extends Mark {
37759
37816
  voronoiDefaults
37760
37817
  );
37761
37818
  }
37762
- render(index2, scales, channels, dimensions, context) {
37763
- const { x: x3, y: y3 } = scales;
37819
+ render(index2, scales2, channels, dimensions, context) {
37820
+ const { x: x3, y: y3 } = scales2;
37764
37821
  const { x: X3, y: Y3, z: Z } = channels;
37765
37822
  const [cx, cy] = applyFrameAnchor(this, dimensions);
37766
37823
  const xi = X3 ? (i) => X3[i] : constant(cx);
@@ -37840,7 +37897,7 @@ var Density = class extends Mark {
37840
37897
  filter(index2) {
37841
37898
  return index2;
37842
37899
  }
37843
- render(index2, scales, channels, dimensions, context) {
37900
+ render(index2, scales2, channels, dimensions, context) {
37844
37901
  const { contours } = channels;
37845
37902
  const path2 = path_default();
37846
37903
  return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}).call(
@@ -37858,13 +37915,13 @@ function densityInitializer(options, fillDensity, strokeDensity) {
37858
37915
  let { bandwidth, thresholds } = options;
37859
37916
  bandwidth = bandwidth === void 0 ? 20 : +bandwidth;
37860
37917
  thresholds = thresholds === void 0 ? 20 : typeof thresholds?.[Symbol.iterator] === "function" ? coerceNumbers(thresholds) : +thresholds;
37861
- return initializer(options, function(data, facets, channels, scales, dimensions, context) {
37918
+ return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
37862
37919
  const W = channels.weight ? coerceNumbers(channels.weight.value) : null;
37863
37920
  const Z = channels.z?.value;
37864
37921
  const { z } = this;
37865
37922
  const [cx, cy] = applyFrameAnchor(this, dimensions);
37866
37923
  const { width, height } = dimensions;
37867
- const { x: X3, y: Y3 } = applyPosition(channels, scales, context);
37924
+ const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);
37868
37925
  const newChannels = Object.fromEntries(
37869
37926
  Object.entries(channels).filter(([key]) => !dropChannels.has(key)).map(([key, channel]) => [key, { ...channel, value: [] }])
37870
37927
  );
@@ -38024,14 +38081,14 @@ function memo(v2) {
38024
38081
  return { transform: (data) => V || (V = valueof(data, value)), label };
38025
38082
  }
38026
38083
  function clipDifferenceY(positive2) {
38027
- return (index2, scales, channels, dimensions, context, next) => {
38084
+ return (index2, scales2, channels, dimensions, context, next) => {
38028
38085
  const { x1: x12, x2: x22 } = channels;
38029
38086
  const { height } = dimensions;
38030
38087
  const y12 = new Float32Array(x12.length);
38031
38088
  const y22 = new Float32Array(x22.length);
38032
- (positive2 === inferScaleOrder(scales.y) < 0 ? y12 : y22).fill(height);
38033
- const oc = next(index2, scales, { ...channels, x2: x12, y2: y22 }, dimensions, context);
38034
- const og = next(index2, scales, { ...channels, x1: x22, y1: y12 }, dimensions, context);
38089
+ (positive2 === inferScaleOrder(scales2.y) < 0 ? y12 : y22).fill(height);
38090
+ const oc = next(index2, scales2, { ...channels, x2: x12, y2: y22 }, dimensions, context);
38091
+ const og = next(index2, scales2, { ...channels, x1: x22, y1: y12 }, dimensions, context);
38035
38092
  const c4 = oc.querySelector("g") ?? oc;
38036
38093
  const g = og.querySelector("g") ?? og;
38037
38094
  for (let i = 0; c4.firstChild; i += 2) {
@@ -38069,15 +38126,15 @@ var Geo = class extends Mark {
38069
38126
  );
38070
38127
  this.r = cr;
38071
38128
  }
38072
- render(index2, scales, channels, dimensions, context) {
38129
+ render(index2, scales2, channels, dimensions, context) {
38073
38130
  const { geometry: G, r: R } = channels;
38074
- const path2 = path_default(context.projection ?? scaleProjection2(scales));
38131
+ const path2 = path_default(context.projection ?? scaleProjection2(scales2));
38075
38132
  const { r } = this;
38076
38133
  if (negative(r))
38077
38134
  index2 = [];
38078
38135
  else if (r !== void 0)
38079
38136
  path2.pointRadius(r);
38080
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call((g) => {
38137
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {
38081
38138
  g.selectAll().data(index2).enter().append("path").call(applyDirectStyles, this).attr("d", R ? (i) => path2.pointRadius(R[i])(G[i]) : (i) => path2(G[i])).call(applyChannelStyles, this, channels);
38082
38139
  }).node();
38083
38140
  }
@@ -38134,13 +38191,13 @@ function hexbin(outputs = { fill: "count" }, { binWidth, ...options } = {}) {
38134
38191
  options.symbol = "hexagon";
38135
38192
  if (options.r === void 0 && !hasOutput(outputs, "r"))
38136
38193
  options.r = binWidth / 2;
38137
- return initializer(options, (data, facets, channels, scales, _, context) => {
38194
+ return initializer(options, (data, facets, channels, scales2, _, context) => {
38138
38195
  let { x: X3, y: Y3, z: Z, fill: F, stroke: S, symbol: Q } = channels;
38139
38196
  if (X3 === void 0)
38140
38197
  throw new Error("missing channel: x");
38141
38198
  if (Y3 === void 0)
38142
38199
  throw new Error("missing channel: y");
38143
- ({ x: X3, y: Y3 } = applyPosition(channels, scales, context));
38200
+ ({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));
38144
38201
  Z = Z ? Z.value : valueof(data, z);
38145
38202
  F = F?.value;
38146
38203
  S = S?.value;
@@ -38182,8 +38239,8 @@ function hexbin(outputs = { fill: "count" }, { binWidth, ...options } = {}) {
38182
38239
  const sx = channels.x.scale;
38183
38240
  const sy = channels.y.scale;
38184
38241
  const binChannels = {
38185
- x: { value: BX, source: scales[sx] ? { value: map2(BX, scales[sx].invert), scale: sx } : null },
38186
- y: { value: BY, source: scales[sy] ? { value: map2(BY, scales[sy].invert), scale: sy } : null },
38242
+ x: { value: BX, source: scales2[sx] ? { value: map2(BX, scales2[sx].invert), scale: sx } : null },
38243
+ y: { value: BY, source: scales2[sy] ? { value: map2(BY, scales2[sy].invert), scale: sy } : null },
38187
38244
  ...Z && { z: { value: GZ } },
38188
38245
  ...F && { fill: { value: GF, scale: "auto" } },
38189
38246
  ...S && { stroke: { value: GS, scale: "auto" } },
@@ -38242,7 +38299,7 @@ var Hexgrid = class extends Mark {
38242
38299
  super(singleton, void 0, { clip, ...options }, defaults20);
38243
38300
  this.binWidth = number5(binWidth);
38244
38301
  }
38245
- render(index2, scales, channels, dimensions, context) {
38302
+ render(index2, scales2, channels, dimensions, context) {
38246
38303
  const { binWidth } = this;
38247
38304
  const { marginTop, marginRight, marginBottom, marginLeft, width, height } = dimensions;
38248
38305
  const x06 = marginLeft - ox, x12 = width - marginRight - ox, y06 = marginTop - oy, y12 = height - marginBottom - oy, rx = binWidth / 2, ry = rx * sqrt4_3, hy = ry / 2, wx = rx * 2, wy = ry * 1.5, i0 = Math.floor(x06 / wx), i1 = Math.ceil(x12 / wx), j0 = Math.floor((y06 + hy) / wy), j1 = Math.ceil((y12 - hy) / wy) + 1, path2 = `m0,${round(-ry)}l${round(rx)},${round(hy)}v${round(ry)}l${round(-rx)},${round(hy)}`;
@@ -38314,8 +38371,8 @@ var Image = class extends Mark {
38314
38371
  this.frameAnchor = maybeFrameAnchor(frameAnchor);
38315
38372
  this.imageRendering = impliedString(imageRendering, "auto");
38316
38373
  }
38317
- render(index2, scales, channels, dimensions, context) {
38318
- const { x: x3, y: y3 } = scales;
38374
+ render(index2, scales2, channels, dimensions, context) {
38375
+ const { x: x3, y: y3 } = scales2;
38319
38376
  const { x: X3, y: Y3, width: W, height: H, r: R, rotate: A5, src: S } = channels;
38320
38377
  const { r, width, height, rotate } = this;
38321
38378
  const [cx, cy] = applyFrameAnchor(this, dimensions);
@@ -38485,10 +38542,10 @@ var LinearRegression = class extends Mark {
38485
38542
  if (!(this.precision > 0))
38486
38543
  throw new Error(`invalid precision: ${precision}`);
38487
38544
  }
38488
- render(index2, scales, channels, dimensions, context) {
38545
+ render(index2, scales2, channels, dimensions, context) {
38489
38546
  const { x: X3, y: Y3, z: Z } = channels;
38490
38547
  const { ci } = this;
38491
- return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales).call(
38548
+ return create3("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(
38492
38549
  (g) => g.selectAll().data(Z ? groupZ2(index2, Z, this.z) : [index2]).enter().call(
38493
38550
  (enter) => enter.append("path").attr("fill", "none").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, { ...channels, fill: null, fillOpacity: null }).attr("d", (I) => this._renderLine(I, X3, Y3)).call(
38494
38551
  ci && !isNone(this.fill) ? (path2) => path2.select(pathBefore).attr("stroke", "none").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, {
@@ -39000,7 +39057,7 @@ function cluster(data, options) {
39000
39057
 
39001
39058
  // ../../node_modules/@observablehq/plot/src/transforms/centroid.js
39002
39059
  function centroid2({ geometry = identity7, ...options } = {}) {
39003
- return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales, dimensions, { projection: projection3 }) => {
39060
+ return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, { projection: projection3 }) => {
39004
39061
  const G = valueof(data, geometry);
39005
39062
  const n = G.length;
39006
39063
  const X3 = new Float64Array(n);
@@ -39090,14 +39147,14 @@ function dodge(y3, x3, anchor, padding, r, options) {
39090
39147
  if (sort3 === void 0 && reverse3 === void 0)
39091
39148
  options.sort = { channel: "-r" };
39092
39149
  }
39093
- return initializer(options, function(data, facets, channels, scales, dimensions, context) {
39150
+ return initializer(options, function(data, facets, channels, scales2, dimensions, context) {
39094
39151
  let { [x3]: X3, r: R } = channels;
39095
39152
  if (!channels[x3])
39096
39153
  throw new Error(`missing channel: ${x3}`);
39097
- ({ [x3]: X3 } = applyPosition(channels, scales, context));
39154
+ ({ [x3]: X3 } = applyPosition(channels, scales2, context));
39098
39155
  const cr = R ? void 0 : r !== void 0 ? number5(r) : this.r !== void 0 ? this.r : 3;
39099
39156
  if (R)
39100
- R = valueof(R.value, scales[R.scale] || identity7, Float64Array);
39157
+ R = valueof(R.value, scales2[R.scale] || identity7, Float64Array);
39101
39158
  let [ky2, ty] = anchor(dimensions);
39102
39159
  const compare = ky2 ? compareAscending : compareSymmetric;
39103
39160
  const Y3 = new Float64Array(X3.length);
@@ -39427,6 +39484,9 @@ var attributeMap = /* @__PURE__ */ new Map([
39427
39484
  ["xAriaDescription", "x.ariaDescription"],
39428
39485
  ["xReverse", "x.reverse"],
39429
39486
  ["xZero", "x.zero"],
39487
+ ["xBase", "x.base"],
39488
+ ["xExponent", "x.exponent"],
39489
+ ["xConstant", "x.constant"],
39430
39490
  ["yScale", "y.type"],
39431
39491
  ["yDomain", "y.domain"],
39432
39492
  ["yRange", "y.range"],
@@ -39457,6 +39517,9 @@ var attributeMap = /* @__PURE__ */ new Map([
39457
39517
  ["yAriaDescription", "y.ariaDescription"],
39458
39518
  ["yReverse", "y.reverse"],
39459
39519
  ["yZero", "y.zero"],
39520
+ ["yBase", "y.base"],
39521
+ ["yExponent", "y.exponent"],
39522
+ ["yConstant", "y.constant"],
39460
39523
  ["facetMargin", "facet.margin"],
39461
39524
  ["facetMarginTop", "facet.marginTop"],
39462
39525
  ["facetMarginBottom", "facet.marginBottom"],
@@ -39532,6 +39595,9 @@ var attributeMap = /* @__PURE__ */ new Map([
39532
39595
  ["colorReverse", "color.reverse"],
39533
39596
  ["colorZero", "color.zero"],
39534
39597
  ["colorTickFormat", "color.tickFormat"],
39598
+ ["colorBase", "color.base"],
39599
+ ["colorExponent", "color.exponent"],
39600
+ ["colorConstant", "color.constant"],
39535
39601
  ["opacityScale", "opacity.type"],
39536
39602
  ["opacityDomain", "opacity.domain"],
39537
39603
  ["opacityRange", "opacity.range"],
@@ -39541,18 +39607,27 @@ var attributeMap = /* @__PURE__ */ new Map([
39541
39607
  ["opacityReverse", "opacity.reverse"],
39542
39608
  ["opacityZero", "opacity.zero"],
39543
39609
  ["opacityTickFormat", "opacity.tickFormat"],
39610
+ ["opacityBase", "opacity.base"],
39611
+ ["opacityExponent", "opacity.exponent"],
39612
+ ["opacityConstant", "opacity.constant"],
39544
39613
  ["rScale", "r.type"],
39545
39614
  ["rDomain", "r.domain"],
39546
39615
  ["rRange", "r.range"],
39547
39616
  ["rClamp", "r.clamp"],
39548
39617
  ["rNice", "r.nice"],
39549
39618
  ["rZero", "r.zero"],
39619
+ ["rBase", "r.base"],
39620
+ ["rExponent", "r.exponent"],
39621
+ ["rConstant", "r.constant"],
39550
39622
  ["lengthScale", "length.type"],
39551
39623
  ["lengthDomain", "length.domain"],
39552
39624
  ["lengthRange", "length.range"],
39553
39625
  ["lengthClamp", "length.clamp"],
39554
39626
  ["lengthNice", "length.nice"],
39555
39627
  ["lengthZero", "length.zero"],
39628
+ ["lengthBase", "length.base"],
39629
+ ["lengthExponent", "length.exponent"],
39630
+ ["lengthConstant", "length.constant"],
39556
39631
  ["projectionType", "projection.type"],
39557
39632
  ["projectionParallels", "projection.parallels"],
39558
39633
  ["projectionPrecision", "projection.precision"],
@@ -39909,14 +39984,26 @@ function isSymbol2(value) {
39909
39984
  return symbols2.has(`${value}`.toLowerCase());
39910
39985
  }
39911
39986
 
39912
- // src/marks/util/is-arrow-table.js
39987
+ // src/marks/util/arrow.js
39988
+ var INTEGER = 2;
39989
+ var FLOAT = 3;
39990
+ var DECIMAL = 7;
39991
+ var TIMESTAMP = 10;
39913
39992
  function isArrowTable(values2) {
39914
39993
  return typeof values2?.getChild === "function";
39915
39994
  }
39995
+ function convertArrow(type2) {
39996
+ const { typeId } = type2;
39997
+ if (typeId === TIMESTAMP) {
39998
+ return (v2) => v2 == null ? v2 : new Date(v2);
39999
+ }
40000
+ if (typeId === INTEGER && type2.bitWidth >= 64) {
40001
+ return (v2) => v2 == null ? v2 : Number(v2);
40002
+ }
40003
+ return (v2) => v2;
40004
+ }
39916
40005
 
39917
40006
  // src/marks/util/to-data-array.js
39918
- var INTEGER = 2;
39919
- var TIMESTAMP = 10;
39920
40007
  function toDataArray(data) {
39921
40008
  return isArrowTable(data) ? arrowToObjects(data) : data;
39922
40009
  }
@@ -39931,7 +40018,7 @@ function arrowToObjects(data) {
39931
40018
  for (let j = 0; j < numCols; ++j) {
39932
40019
  const child = batch.getChildAt(j);
39933
40020
  const { name, type: type2 } = schema.fields[j];
39934
- const valueOf = convert(type2);
40021
+ const valueOf = convertArrow(type2);
39935
40022
  for (let o = k2, i = 0; i < numRows; ++i, ++o) {
39936
40023
  objects[o][name] = valueOf(child.get(i));
39937
40024
  }
@@ -39940,16 +40027,6 @@ function arrowToObjects(data) {
39940
40027
  }
39941
40028
  return objects;
39942
40029
  }
39943
- function convert(type2) {
39944
- const { typeId } = type2;
39945
- if (typeId === TIMESTAMP) {
39946
- return (v2) => v2 == null ? v2 : new Date(v2);
39947
- }
39948
- if (typeId === INTEGER && type2.bitWidth >= 64) {
39949
- return (v2) => v2 == null ? v2 : Number(v2);
39950
- }
39951
- return (v2) => v2;
39952
- }
39953
40030
 
39954
40031
  // src/marks/Mark.js
39955
40032
  var isColorChannel = (channel) => channel === "stroke" || channel === "fill";
@@ -40126,19 +40203,43 @@ function markQuery(channels, table, skip = []) {
40126
40203
  return q;
40127
40204
  }
40128
40205
 
40129
- // src/marks/util/bin-field.js
40130
- function binField(mark, channel, expr) {
40131
- if (!mark.stats)
40132
- return field2;
40206
+ // src/marks/util/channel-scale.js
40207
+ function channelScale(mark, channel) {
40208
+ const { plot: plot2 } = mark;
40209
+ let scaleType = plot2.getAttribute(`${channel}Scale`);
40210
+ if (!scaleType) {
40211
+ const { field: field2 } = mark.channelField(channel, `${channel}1`, `${channel}2`);
40212
+ const { type: type2 } = mark.stats[field2.column];
40213
+ scaleType = type2 === "date" ? "time" : "linear";
40214
+ }
40215
+ const options = { type: scaleType };
40216
+ switch (scaleType) {
40217
+ case "log":
40218
+ options.base = plot2.getAttribute(`${channel}Base`) ?? 10;
40219
+ break;
40220
+ case "pow":
40221
+ options.exponent = plot2.getAttribute(`${channel}Exponent`) ?? 1;
40222
+ break;
40223
+ case "symlog":
40224
+ options.constant = plot2.getAttribute(`${channel}Constant`) ?? 1;
40225
+ break;
40226
+ }
40227
+ return scaleTransform(options);
40228
+ }
40229
+
40230
+ // src/marks/util/bin-expr.js
40231
+ function binExpr(mark, channel, n, extent4, pad3 = 1, expr) {
40133
40232
  const { field: field2 } = mark.channelField(channel);
40134
- const { type: type2 } = mark.stats[field2.column];
40135
40233
  expr = expr ?? field2;
40136
- return type2 === "date" ? epoch_ms(expr) : expr;
40137
- }
40138
- function bin1d(x3, x06, x12, n, reverse3 = false, pad3 = 1) {
40139
- const d = (n - pad3) / (x12 - x06);
40140
- const f = d !== 1 ? ` * ${d}::DOUBLE` : "";
40141
- return reverse3 ? sql`(${+x12} - ${x3}::DOUBLE)${f}` : sql`(${x3}::DOUBLE - ${+x06})${f}`;
40234
+ const { type: type2, apply: apply2, sqlApply } = channelScale(mark, channel);
40235
+ const reverse3 = !!mark.plot.getAttribute(`${channel}Reverse`);
40236
+ const [lo, hi] = extent4.map((v3) => apply2(v3));
40237
+ const v2 = sqlApply(expr);
40238
+ const f = type2 === "time" || type2 === "utc" ? v2 : expr;
40239
+ const d = hi === lo ? 0 : (n - pad3) / (hi - lo);
40240
+ const s2 = d !== 1 ? ` * ${d}::DOUBLE` : "";
40241
+ const bin3 = reverse3 ? sql`(${hi} - ${v2}::DOUBLE)${s2}` : sql`(${v2}::DOUBLE - ${lo})${s2}`;
40242
+ return [bin3, f];
40142
40243
  }
40143
40244
 
40144
40245
  // src/marks/util/extent.js
@@ -40194,7 +40295,7 @@ function filteredExtent(filter3, column3) {
40194
40295
  var ConnectedMark = class extends Mark2 {
40195
40296
  constructor(type2, source, encodings) {
40196
40297
  const dim = type2.endsWith("X") ? "y" : type2.endsWith("Y") ? "x" : null;
40197
- const req = { [dim]: ["count", "min", "max"] };
40298
+ const req = { [dim]: ["min", "max"] };
40198
40299
  super(type2, source, encodings, req);
40199
40300
  this.dim = dim;
40200
40301
  }
@@ -40202,27 +40303,29 @@ var ConnectedMark = class extends Mark2 {
40202
40303
  const { plot: plot2, dim, source, stats } = this;
40203
40304
  const { optimize = true } = source.options || {};
40204
40305
  const q = super.query(filter3);
40205
- if (optimize && dim) {
40206
- const { field: field2, as } = this.channelField(dim);
40306
+ if (!dim)
40307
+ return q;
40308
+ const ortho = dim === "x" ? "y" : "x";
40309
+ const value = this.channelField(ortho)?.as;
40310
+ const { field: field2, as } = this.channelField(dim);
40311
+ const { type: type2 } = stats[field2.column];
40312
+ const isContinuous = type2 === "date" || type2 === "number";
40313
+ if (optimize && isContinuous && value) {
40207
40314
  const { column: column3 } = field2;
40208
- const { count: count4, max: max4, min: min5 } = stats[column3];
40315
+ const { max: max4, min: min5 } = stats[column3];
40209
40316
  const size = dim === "x" ? plot2.innerWidth() : plot2.innerHeight();
40210
40317
  const [lo, hi] = filteredExtent(filter3, column3) || [min5, max4];
40211
- const scale3 = (hi - lo) / (max4 - min5);
40212
- if (count4 * scale3 > size * 4) {
40213
- const dd = binField(this, dim, as);
40214
- const val = this.channelField(dim === "x" ? "y" : "x").as;
40215
- const cols = q.select().map((c4) => c4.as).filter((c4) => c4 !== as && c4 !== val);
40216
- return m4(q, dd, as, val, lo, hi, size, cols);
40217
- }
40218
- q.orderby(as);
40318
+ const [expr] = binExpr(this, dim, size, [lo, hi], 1, as);
40319
+ const cols = q.select().map((c4) => c4.as).filter((c4) => c4 !== as && c4 !== value);
40320
+ return m4(q, expr, as, value, cols);
40321
+ } else {
40322
+ return q.orderby(field2);
40219
40323
  }
40220
- return q;
40221
40324
  }
40222
40325
  };
40223
- function m4(input, bx, x3, y3, lo, hi, width, cols = []) {
40224
- const bins2 = sql`FLOOR(${width / (hi - lo)}::DOUBLE * (${bx} - ${+lo}::DOUBLE))::INTEGER`;
40225
- const q = (sel) => Query.from(input).select(sel).groupby(bins2, cols);
40326
+ function m4(input, bin3, x3, y3, cols = []) {
40327
+ const pixel = sql`FLOOR(${bin3})::INTEGER`;
40328
+ const q = (sel) => Query.from(input).select(sel).groupby(pixel, cols);
40226
40329
  return Query.union(
40227
40330
  q([{ [x3]: min(x3), [y3]: argmin(y3, x3) }, ...cols]),
40228
40331
  q([{ [x3]: max(x3), [y3]: argmax(y3, x3) }, ...cols]),
@@ -40231,6 +40334,120 @@ function m4(input, bx, x3, y3, lo, hi, width, cols = []) {
40231
40334
  ).orderby(cols, x3);
40232
40335
  }
40233
40336
 
40337
+ // src/marks/util/grid.js
40338
+ function arrayType(values2, name = "density") {
40339
+ if (isArrowTable(values2)) {
40340
+ const type2 = values2.getChild(name).type;
40341
+ switch (type2.typeId) {
40342
+ case INTEGER:
40343
+ case FLOAT:
40344
+ case DECIMAL:
40345
+ return Float64Array;
40346
+ default:
40347
+ return Array;
40348
+ }
40349
+ } else {
40350
+ return typeof values2[0][name] === "number" ? Float64Array : Array;
40351
+ }
40352
+ }
40353
+ function grid1d(n, values2) {
40354
+ const Type3 = arrayType(values2);
40355
+ return valuesToGrid(new Type3(n), values2);
40356
+ }
40357
+ function grid2d(m, n, values2, aggr, groupby = []) {
40358
+ if (groupby.length) {
40359
+ return groupedValuesToGrids(m * n, values2, aggr, groupby);
40360
+ } else {
40361
+ const cell2 = {};
40362
+ aggr.forEach((name) => {
40363
+ const Type3 = arrayType(values2, name);
40364
+ cell2[name] = valuesToGrid(new Type3(m * n), values2, name);
40365
+ });
40366
+ return [cell2];
40367
+ }
40368
+ }
40369
+ function valuesToGrid(grid, values2, name = "density") {
40370
+ if (isArrowTable(values2)) {
40371
+ const numRows = values2.numRows;
40372
+ if (numRows === 0)
40373
+ return grid;
40374
+ const index2 = values2.getChild("index").toArray();
40375
+ const value = values2.getChild(name).toArray();
40376
+ for (let row = 0; row < numRows; ++row) {
40377
+ grid[index2[row]] = value[row];
40378
+ }
40379
+ } else {
40380
+ for (const row of values2) {
40381
+ grid[row.index] = row[name];
40382
+ }
40383
+ }
40384
+ return grid;
40385
+ }
40386
+ function groupedValuesToGrids(size, values2, aggr, groupby) {
40387
+ const Types = aggr.map((name) => arrayType(values2, name));
40388
+ const numAggr = aggr.length;
40389
+ const cellMap = {};
40390
+ const getCell = (key) => {
40391
+ let cell2 = cellMap[key];
40392
+ if (!cell2) {
40393
+ cell2 = cellMap[key] = {};
40394
+ groupby.forEach((name, i) => cell2[name] = key[i]);
40395
+ aggr.forEach((name, i) => cell2[name] = new Types[i](size));
40396
+ }
40397
+ return cell2;
40398
+ };
40399
+ if (isArrowTable(values2)) {
40400
+ const numRows = values2.numRows;
40401
+ if (numRows === 0)
40402
+ return [];
40403
+ const index2 = values2.getChild("index").toArray();
40404
+ const value = aggr.map((name) => values2.getChild(name).toArray());
40405
+ const groups2 = groupby.map((name) => values2.getChild(name));
40406
+ for (let row = 0; row < numRows; ++row) {
40407
+ const key = groups2.map((vec2) => vec2.get(row));
40408
+ const cell2 = getCell(key);
40409
+ for (let i = 0; i < numAggr; ++i) {
40410
+ cell2[aggr[i]][index2[row]] = value[i][row];
40411
+ }
40412
+ }
40413
+ } else {
40414
+ for (const row of values2) {
40415
+ const key = groupby.map((col) => row[col]);
40416
+ const cell2 = getCell(key);
40417
+ for (let i = 0; i < numAggr; ++i) {
40418
+ cell2[aggr[i]][row.index] = row[aggr[i]];
40419
+ }
40420
+ }
40421
+ }
40422
+ return Object.values(cellMap);
40423
+ }
40424
+ function gridDomainContinuous(grids, prop) {
40425
+ let lo = 0, hi = 0;
40426
+ grids.forEach((cell2) => {
40427
+ const grid = cell2[prop];
40428
+ const n = grid.length;
40429
+ for (let i = 0; i < n; ++i) {
40430
+ const v2 = grid[i];
40431
+ if (v2 < lo)
40432
+ lo = v2;
40433
+ if (v2 > hi)
40434
+ hi = v2;
40435
+ }
40436
+ });
40437
+ return lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
40438
+ }
40439
+ function gridDomainDiscrete(grids, prop) {
40440
+ const values2 = new InternSet();
40441
+ grids.forEach((cell2) => {
40442
+ const grid = cell2[prop];
40443
+ const n = grid.length;
40444
+ for (let i = 0; i < n; ++i) {
40445
+ values2.add(grid[i]);
40446
+ }
40447
+ });
40448
+ return Array.from(values2).sort(ascending);
40449
+ }
40450
+
40234
40451
  // src/marks/util/handle-param.js
40235
40452
  function handleParam(client, key, param, update2) {
40236
40453
  if (isParam(param)) {
@@ -40415,64 +40632,17 @@ function dericheInitZeroPad(dest, src, N, stride, b, p, a2, q, sum5, h) {
40415
40632
  return;
40416
40633
  }
40417
40634
 
40418
- // src/marks/util/grid.js
40419
- function grid1d(n, values2) {
40420
- return valuesToGrid(new Float64Array(n), values2);
40421
- }
40422
- function grid2d(m, n, values2, groupby = []) {
40423
- return groupby.length ? Object.values(groupedValuesToGrids(m * n, values2, groupby)) : [{ grid: valuesToGrid(new Float64Array(m * n), values2) }];
40424
- }
40425
- function valuesToGrid(grid, values2) {
40426
- if (isArrowTable(values2)) {
40427
- const numRows = values2.numRows;
40428
- if (numRows === 0)
40429
- return grid;
40430
- const index2 = values2.getChild("index").toArray();
40431
- const value = values2.getChild("value").toArray();
40432
- for (let row = 0; row < numRows; ++row) {
40433
- grid[index2[row]] = value[row];
40434
- }
40435
- } else {
40436
- for (const row of values2) {
40437
- grid[row.index] = row.value;
40438
- }
40439
- }
40440
- return grid;
40441
- }
40442
- function groupedValuesToGrids(size, values2, groupby) {
40443
- const grids = {};
40444
- const getGrid = (key) => {
40445
- const cell2 = grids[key] || (grids[key] = { key, grid: new Float64Array(size) });
40446
- return cell2.grid;
40447
- };
40448
- if (isArrowTable(values2)) {
40449
- const numRows = values2.numRows;
40450
- if (numRows === 0)
40451
- return grids;
40452
- const index2 = values2.getChild("index").toArray();
40453
- const value = values2.getChild("value").toArray();
40454
- const groups2 = groupby.map((name) => values2.getChild(name));
40455
- for (let row = 0; row < numRows; ++row) {
40456
- const key = groups2.map((vec2) => vec2.get(row));
40457
- getGrid(key)[index2[row]] = value[row];
40458
- }
40459
- } else {
40460
- for (const row of values2) {
40461
- const key = groupby.map((col) => row[col]);
40462
- getGrid(key)[row.index] = row.value;
40463
- }
40464
- }
40465
- return grids;
40466
- }
40467
-
40468
40635
  // src/marks/Grid2DMark.js
40636
+ var DENSITY = "density";
40469
40637
  var Grid2DMark = class extends Mark2 {
40470
40638
  constructor(type2, source, options) {
40471
40639
  const {
40472
- bandwidth = 20,
40473
- binType = "linear",
40474
- binWidth = 2,
40475
- binPad = 1,
40640
+ bandwidth = 0,
40641
+ interpolate = "none",
40642
+ pixelSize = 1,
40643
+ pad: pad3 = 1,
40644
+ width,
40645
+ height,
40476
40646
  ...channels
40477
40647
  } = options;
40478
40648
  const densityMap = createDensityMap(channels);
@@ -40481,9 +40651,11 @@ var Grid2DMark = class extends Mark2 {
40481
40651
  handleParam(this, "bandwidth", bandwidth, () => {
40482
40652
  return this.grids ? this.convolve().update() : null;
40483
40653
  });
40484
- handleParam(this, "binWidth", binWidth);
40485
- handleParam(this, "binType", binType);
40486
- handleParam(this, "binPad", binPad);
40654
+ handleParam(this, "pixelSize", pixelSize);
40655
+ handleParam(this, "interpolate", interpolate);
40656
+ handleParam(this, "pad", pad3);
40657
+ handleParam(this, "width", width);
40658
+ handleParam(this, "height", height);
40487
40659
  }
40488
40660
  setPlot(plot2, index2) {
40489
40661
  const update2 = () => {
@@ -40500,64 +40672,80 @@ var Grid2DMark = class extends Mark2 {
40500
40672
  return xdom && ydom && !xdom[Transient] && !ydom[Transient];
40501
40673
  }
40502
40674
  query(filter3 = []) {
40503
- const { plot: plot2, binType, binPad, channels, densityMap, source } = this;
40675
+ const { interpolate, pad: pad3, channels, densityMap, source } = this;
40504
40676
  const [x06, x12] = this.extentX = extentX(this, filter3);
40505
40677
  const [y06, y12] = this.extentY = extentY(this, filter3);
40506
40678
  const [nx, ny] = this.bins = this.binDimensions(this);
40507
- const bx = binField(this, "x");
40508
- const by = binField(this, "y");
40509
- const rx = !!plot2.getAttribute("xReverse");
40510
- const ry = !!plot2.getAttribute("yReverse");
40511
- const x3 = bin1d2(bx, x06, x12, nx, rx, this.binPad);
40512
- const y3 = bin1d2(by, y06, y12, ny, ry, this.binPad);
40513
- const bounds = binPad ? [isBetween(bx, [x06, x12]), isBetween(by, [y06, y12])] : [lte(x06, bx), lt(bx, x12), lte(y06, by), lt(by, y12)];
40679
+ const [x3, bx] = binExpr(this, "x", nx, [x06, x12], pad3);
40680
+ const [y3, by] = binExpr(this, "y", ny, [y06, y12], pad3);
40681
+ const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];
40514
40682
  const q = Query.from(source.table).where(filter3.concat(bounds));
40515
40683
  const groupby = this.groupby = [];
40516
- let agg2 = count();
40684
+ const aggrMap = {};
40517
40685
  for (const c4 of channels) {
40518
40686
  if (Object.hasOwn(c4, "field")) {
40519
40687
  const { as, channel, field: field2 } = c4;
40520
40688
  if (field2.aggregate) {
40521
- agg2 = field2;
40689
+ aggrMap[channel] = field2;
40522
40690
  densityMap[channel] = true;
40523
40691
  } else if (channel === "weight") {
40524
- agg2 = sum2(field2);
40692
+ aggrMap[DENSITY] = sum2(field2);
40525
40693
  } else if (channel !== "x" && channel !== "y") {
40526
40694
  q.select({ [as]: field2 });
40527
40695
  groupby.push(as);
40528
40696
  }
40529
40697
  }
40530
40698
  }
40531
- return binType === "linear" ? binLinear2d(q, x3, y3, agg2, nx, groupby) : bin2d(q, x3, y3, agg2, nx, groupby);
40699
+ const aggr = this.aggr = Object.keys(aggrMap);
40700
+ if (aggrMap.density && aggr.length > 1) {
40701
+ throw new Error("Weight option can not be used with custom aggregates.");
40702
+ }
40703
+ if (!aggr.length) {
40704
+ aggr.push(DENSITY);
40705
+ aggrMap.density = count();
40706
+ }
40707
+ if (interpolate === "linear") {
40708
+ if (aggr.length > 1) {
40709
+ throw new Error("Linear binning not applicable to multiple aggregates.");
40710
+ }
40711
+ if (!aggrMap.density) {
40712
+ throw new Error("Linear binning not applicable to custom aggregates.");
40713
+ }
40714
+ return binLinear2d(q, x3, y3, aggrMap[DENSITY], nx, groupby);
40715
+ } else {
40716
+ return bin2d(q, x3, y3, aggrMap, nx, groupby);
40717
+ }
40532
40718
  }
40533
40719
  binDimensions() {
40534
- const { plot: plot2, binWidth } = this;
40720
+ const { plot: plot2, pixelSize, width, height } = this;
40535
40721
  return [
40536
- Math.round(plot2.innerWidth() / binWidth),
40537
- Math.round(plot2.innerHeight() / binWidth)
40722
+ width ?? Math.round(plot2.innerWidth() / pixelSize),
40723
+ height ?? Math.round(plot2.innerHeight() / pixelSize)
40538
40724
  ];
40539
40725
  }
40540
40726
  queryResult(data) {
40541
40727
  const [nx, ny] = this.bins;
40542
- this.grids = grid2d(nx, ny, data, this.groupby);
40728
+ this.grids = grid2d(nx, ny, data, this.aggr, this.groupby);
40543
40729
  return this.convolve();
40544
40730
  }
40545
40731
  convolve() {
40546
- const { bandwidth, bins: bins2, grids, plot: plot2 } = this;
40547
- if (bandwidth <= 0) {
40548
- this.kde = this.grids.map(({ key, grid }) => {
40549
- return grid.key = key, grid;
40550
- });
40551
- } else {
40732
+ const { aggr, bandwidth, bins: bins2, grids, plot: plot2 } = this;
40733
+ this.kde = this.grids;
40734
+ if (bandwidth > 0) {
40735
+ const gridProp = aggr.length === 1 ? aggr[0] : aggr.includes(DENSITY) ? DENSITY : null;
40736
+ if (!gridProp) {
40737
+ console.warn("No compatible grid found for smoothing.");
40738
+ return this;
40739
+ }
40552
40740
  const w = plot2.innerWidth();
40553
40741
  const h = plot2.innerHeight();
40554
40742
  const [nx, ny] = bins2;
40555
- const neg = grids.some(({ grid }) => grid.some((v2) => v2 < 0));
40743
+ const neg = grids.some((cell2) => cell2[gridProp].some((v2) => v2 < 0));
40556
40744
  const configX = dericheConfig(bandwidth * (nx - 1) / w, neg);
40557
40745
  const configY = dericheConfig(bandwidth * (ny - 1) / h, neg);
40558
- this.kde = this.grids.map(({ key, grid }) => {
40559
- const k2 = dericheConv2d(configX, configY, grid, bins2);
40560
- return k2.key = key, k2;
40746
+ this.kde = this.grids.map((grid) => {
40747
+ const density2 = dericheConv2d(configX, configY, grid[gridProp], bins2);
40748
+ return { ...grid, [gridProp]: density2 };
40561
40749
  });
40562
40750
  }
40563
40751
  return this;
@@ -40576,19 +40764,14 @@ function createDensityMap(channels) {
40576
40764
  }
40577
40765
  return densityMap;
40578
40766
  }
40579
- function bin1d2(x3, x06, x12, n, reverse3, pad3) {
40580
- const d = (n - pad3) / (x12 - x06);
40581
- const f = d !== 1 ? ` * ${d}::DOUBLE` : "";
40582
- return reverse3 ? sql`(${x12} - ${x3}::DOUBLE)${f}` : sql`(${x3}::DOUBLE - ${x06})${f}`;
40583
- }
40584
- function bin2d(q, xp, yp, value, xn, groupby) {
40767
+ function bin2d(q, xp, yp, aggs, xn, groupby) {
40585
40768
  return q.select({
40586
40769
  index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,
40587
- value
40770
+ ...aggs
40588
40771
  }).groupby("index", groupby);
40589
40772
  }
40590
- function binLinear2d(q, xp, yp, value, xn, groupby) {
40591
- const w = value.column ? `* ${value.column}` : "";
40773
+ function binLinear2d(q, xp, yp, density2, xn, groupby) {
40774
+ const w = density2?.column ? `* ${density2.column}` : "";
40592
40775
  const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });
40593
40776
  const a2 = subq(
40594
40777
  sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,
@@ -40606,14 +40789,19 @@ function binLinear2d(q, xp, yp, value, xn, groupby) {
40606
40789
  sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,
40607
40790
  sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`
40608
40791
  );
40609
- return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", value: sum2("w") }, groupby).groupby("index", groupby).having(gt("value", 0));
40792
+ return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", density: sum2("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
40610
40793
  }
40611
40794
 
40612
40795
  // src/marks/ContourMark.js
40613
40796
  var ContourMark = class extends Grid2DMark {
40614
40797
  constructor(source, options) {
40615
40798
  const { thresholds = 10, ...channels } = options;
40616
- super("geo", source, channels);
40799
+ super("geo", source, {
40800
+ bandwidth: 20,
40801
+ interpolate: "linear",
40802
+ pixelSize: 2,
40803
+ ...channels
40804
+ });
40617
40805
  handleParam(this, "thresholds", thresholds, () => {
40618
40806
  return this.grids ? this.contours().update() : null;
40619
40807
  });
@@ -40622,11 +40810,11 @@ var ContourMark = class extends Grid2DMark {
40622
40810
  return super.convolve().contours();
40623
40811
  }
40624
40812
  contours() {
40625
- const { bins: bins2, densityMap, kde, thresholds, groupby, plot: plot2 } = this;
40813
+ const { bins: bins2, densityMap, kde, thresholds, plot: plot2 } = this;
40626
40814
  let tz = thresholds;
40627
40815
  if (!Array.isArray(tz)) {
40628
- const scale3 = max2(kde.map((k2) => max2(k2)));
40629
- tz = Array.from({ length: tz - 1 }, (_, i) => scale3 * (i + 1) / tz);
40816
+ const [, hi] = gridDomainContinuous(kde, "density");
40817
+ tz = Array.from({ length: tz - 1 }, (_, i) => hi * (i + 1) / tz);
40630
40818
  }
40631
40819
  if (densityMap.fill || densityMap.stroke) {
40632
40820
  if (this.plot.getAttribute("colorScale") !== "log") {
@@ -40643,11 +40831,11 @@ var ContourMark = class extends Grid2DMark {
40643
40831
  const x3 = (v2) => xo + v2 * sx;
40644
40832
  const y3 = (v2) => yo + v2 * sy;
40645
40833
  const contour2 = contours_default().size(bins2);
40646
- this.data = kde.flatMap((k2) => tz.map((t) => {
40647
- const c4 = transform2(contour2.contour(k2, t), x3, y3);
40648
- groupby.forEach((name, i) => c4[name] = k2.key[i]);
40649
- c4.density = t;
40650
- return c4;
40834
+ this.data = kde.flatMap((cell2) => tz.map((t) => {
40835
+ return Object.assign(
40836
+ transform2(contour2.contour(cell2.density, t), x3, y3),
40837
+ { ...cell2, density: t }
40838
+ );
40651
40839
  }));
40652
40840
  return this;
40653
40841
  }
@@ -40683,23 +40871,95 @@ function transform2(geometry, x3, y3) {
40683
40871
  }
40684
40872
 
40685
40873
  // src/marks/util/raster.js
40686
- function raster2(grid, data, w, h, scale3, scheme28) {
40687
- const n = (scheme28.length >> 2) - 1;
40688
- for (let j = 0, k2 = 0; j < h; ++j) {
40689
- for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
40690
- const c4 = n * scale3(grid[i + row]) << 2;
40691
- data[k2 + 0] = scheme28[c4 + 0];
40692
- data[k2 + 1] = scheme28[c4 + 1];
40693
- data[k2 + 2] = scheme28[c4 + 2];
40694
- data[k2 + 3] = scheme28[c4 + 3];
40695
- }
40874
+ function createCanvas(w, h) {
40875
+ if (typeof document !== "undefined") {
40876
+ const c4 = document.createElement("canvas");
40877
+ c4.setAttribute("width", w);
40878
+ c4.setAttribute("height", h);
40879
+ return c4;
40696
40880
  }
40881
+ throw new Error("Can not create a canvas instance.");
40882
+ }
40883
+ function alphaConstant(v2 = 1) {
40884
+ const a2 = 255 * v2 | 0;
40885
+ return (data, w, h) => {
40886
+ for (let j = 0, k2 = 0; j < h; ++j) {
40887
+ for (let i = 0; i < w; ++i, k2 += 4) {
40888
+ data[k2 + 3] = a2;
40889
+ }
40890
+ }
40891
+ };
40892
+ }
40893
+ function alphaScheme(scale3) {
40894
+ const { apply: apply2 } = scale3;
40895
+ return (data, w, h, grid) => {
40896
+ for (let j = 0, k2 = 0; j < h; ++j) {
40897
+ for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
40898
+ data[k2 + 3] = 255 * apply2(grid[i + row]) | 0;
40899
+ }
40900
+ }
40901
+ };
40902
+ }
40903
+ function colorConstant(v2 = {}) {
40904
+ const { r = 0, g = 0, b = 0, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
40905
+ const c4 = new Uint8ClampedArray([r, g, b, 255 * opacity2 | 0]);
40906
+ return (data, w, h) => {
40907
+ for (let j = 0, k2 = 0; j < h; ++j) {
40908
+ for (let i = 0; i < w; ++i, k2 += 4) {
40909
+ data[k2 + 0] = c4[0];
40910
+ data[k2 + 1] = c4[1];
40911
+ data[k2 + 2] = c4[2];
40912
+ data[k2 + 3] = c4[3];
40913
+ }
40914
+ }
40915
+ };
40697
40916
  }
40698
- function palette(size, interp) {
40917
+ function colorCategory(scale3) {
40918
+ const { domain, range: range3 } = scale3;
40919
+ const idx = /* @__PURE__ */ Object.create(null);
40920
+ const p = new Uint8ClampedArray(4 * domain.length);
40921
+ const n = domain.length - 1;
40922
+ const m = range3.length;
40923
+ for (let i = 0; i <= n; ++i) {
40924
+ const v2 = range3[i % m];
40925
+ const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
40926
+ const k2 = i << 2;
40927
+ p[k2 + 0] = r;
40928
+ p[k2 + 1] = g;
40929
+ p[k2 + 2] = b;
40930
+ p[k2 + 3] = 255 * opacity2 | 0;
40931
+ idx[domain[i]] = k2;
40932
+ }
40933
+ return (data, w, h, grid) => {
40934
+ if (grid.map) {
40935
+ for (let j = 0, k2 = 0; j < h; ++j) {
40936
+ for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
40937
+ const c4 = idx[grid[i + row]];
40938
+ data[k2 + 0] = p[c4 + 0];
40939
+ data[k2 + 1] = p[c4 + 1];
40940
+ data[k2 + 2] = p[c4 + 2];
40941
+ data[k2 + 3] = p[c4 + 3];
40942
+ }
40943
+ }
40944
+ } else {
40945
+ const c4 = idx[grid];
40946
+ for (let j = 0, k2 = 0; j < h; ++j) {
40947
+ for (let i = 0; i < w; ++i, k2 += 4) {
40948
+ data[k2 + 0] = p[c4 + 0];
40949
+ data[k2 + 1] = p[c4 + 1];
40950
+ data[k2 + 2] = p[c4 + 2];
40951
+ data[k2 + 3] = p[c4 + 3];
40952
+ }
40953
+ }
40954
+ }
40955
+ };
40956
+ }
40957
+ function colorScheme(size, scale3, frac) {
40958
+ const { interpolate } = scale3;
40699
40959
  const p = new Uint8ClampedArray(4 * size);
40700
40960
  const n = size - 1;
40701
40961
  for (let i = 0; i <= n; ++i) {
40702
- const v2 = interp(i / n);
40962
+ const v2 = interpolate(i / n);
40703
40963
  const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === "string" ? rgb(v2) : v2;
40704
40964
  const k2 = i << 2;
40705
40965
  p[k2 + 0] = r;
@@ -40707,20 +40967,17 @@ function palette(size, interp) {
40707
40967
  p[k2 + 2] = b;
40708
40968
  p[k2 + 3] = 255 * opacity2 | 0;
40709
40969
  }
40710
- return p;
40711
- }
40712
- function createCanvas(w, h) {
40713
- if (typeof document !== "undefined") {
40714
- const c4 = document.createElement("canvas");
40715
- c4.setAttribute("width", w);
40716
- c4.setAttribute("height", h);
40717
- return c4;
40718
- }
40719
- throw new Error("Can not create a canvas instance.");
40720
- }
40721
- function opacityMap(color3 = "black") {
40722
- const { r, g, b } = rgb(color3);
40723
- return (opacity2) => ({ r, g, b, opacity: opacity2 });
40970
+ return (data, w, h, grid) => {
40971
+ for (let j = 0, k2 = 0; j < h; ++j) {
40972
+ for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {
40973
+ const c4 = n * frac(grid[i + row]) << 2;
40974
+ data[k2 + 0] = p[c4 + 0];
40975
+ data[k2 + 1] = p[c4 + 1];
40976
+ data[k2 + 2] = p[c4 + 2];
40977
+ data[k2 + 3] = p[c4 + 3];
40978
+ }
40979
+ }
40980
+ };
40724
40981
  }
40725
40982
 
40726
40983
  // src/marks/RasterMark.js
@@ -40740,15 +40997,13 @@ var RasterMark = class extends Grid2DMark {
40740
40997
  return super.convolve().rasterize();
40741
40998
  }
40742
40999
  rasterize() {
40743
- const { bins: bins2, kde, groupby } = this;
41000
+ const { bins: bins2, kde } = this;
40744
41001
  const [w, h] = bins2;
40745
41002
  const { canvas, ctx, img } = imageData(this, w, h);
40746
- const s2 = imageScale(this);
40747
- const idx = groupby.indexOf(this.channelField("fill")?.as);
40748
- const domain = idx < 0 ? [] : kde.map(({ key }) => key[idx]);
40749
- this.data = kde.map((grid) => {
40750
- const palette2 = imagePalette(this, domain, grid.key?.[idx]);
40751
- raster2(grid, img.data, w, h, s2, palette2);
41003
+ const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);
41004
+ this.data = kde.map((cell2) => {
41005
+ color3?.(img.data, w, h, cell2[colorProp]);
41006
+ alpha?.(img.data, w, h, cell2[alphaProp]);
40752
41007
  ctx.putImageData(img, 0, 0);
40753
41008
  return { src: canvas.toDataURL() };
40754
41009
  });
@@ -40767,6 +41022,128 @@ var RasterMark = class extends Grid2DMark {
40767
41022
  return [{ type: type2, data, options }];
40768
41023
  }
40769
41024
  };
41025
+ var HeatmapMark = class extends RasterMark {
41026
+ constructor(source, options) {
41027
+ super(source, {
41028
+ bandwidth: 20,
41029
+ interpolate: "linear",
41030
+ pixelSize: 2,
41031
+ ...options
41032
+ });
41033
+ }
41034
+ };
41035
+ function rasterEncoding(mark) {
41036
+ const { aggr, densityMap, groupby, plot: plot2 } = mark;
41037
+ const hasDensity = aggr.includes(DENSITY);
41038
+ const hasFillOpacity = aggr.includes("fillOpacity");
41039
+ const fillEntry = mark.channel("fill");
41040
+ const opacEntry = mark.channel("fillOpacity");
41041
+ if (aggr.length > 2 || hasDensity && hasFillOpacity) {
41042
+ throw new Error("Invalid raster encodings. Try dropping an aggregate?");
41043
+ }
41044
+ if (groupby.includes(opacEntry?.as)) {
41045
+ throw new Error("Raster fillOpacity must be an aggregate or constant.");
41046
+ }
41047
+ const fill = densityMap.fill || aggr.includes("fill") ? "grid" : groupby.includes(fillEntry?.as) ? "group" : isColor2(fillEntry?.value) ? fillEntry.value : hasDensity && plot2.getAttribute("colorScheme") ? "grid" : void 0;
41048
+ const opac = densityMap.fillOpacity || aggr.includes("fillOpacity") ? "grid" : typeof opacEntry?.value === "number" ? opacEntry.value : hasDensity && fill !== "grid" ? "grid" : void 0;
41049
+ if (fill !== "grid" && opac !== "grid") {
41050
+ throw new Error("Raster mark missing density values.");
41051
+ }
41052
+ const colorProp = fillEntry?.as ?? (fill === "grid" ? DENSITY : null);
41053
+ const alphaProp = opacEntry?.as ?? (opac === "grid" ? DENSITY : null);
41054
+ const color3 = fill !== "grid" && fill !== "group" ? colorConstant(fill) : colorScale(mark, colorProp);
41055
+ const alpha = opac !== "grid" ? alphaConstant(opac) : alphaScale(mark, alphaProp);
41056
+ return { alphaProp, colorProp, alpha, color: color3 };
41057
+ }
41058
+ function alphaScale(mark, prop) {
41059
+ const { plot: plot2, kde: grids } = mark;
41060
+ const domainAttr = plot2.getAttribute("opacityDomain");
41061
+ const domainFixed = domainAttr === Fixed;
41062
+ const domainTransient = domainAttr?.[Transient];
41063
+ const domain = !domainFixed && !domainTransient && domainAttr || gridDomainContinuous(grids, prop);
41064
+ if (domainFixed || domainTransient) {
41065
+ if (domainTransient)
41066
+ domain[Transient] = true;
41067
+ plot2.setAttribute("colorDomain", domain);
41068
+ }
41069
+ const s2 = scale2({
41070
+ opacity: {
41071
+ type: plot2.getAttribute("opacityScale"),
41072
+ domain,
41073
+ clamp: plot2.getAttribute("opacityClamp"),
41074
+ nice: plot2.getAttribute("opacityNice"),
41075
+ reverse: plot2.getAttribute("opacityReverse"),
41076
+ zero: plot2.getAttribute("opacityZero"),
41077
+ base: plot2.getAttribute("opacityBase"),
41078
+ exponent: plot2.getAttribute("opacityExponent"),
41079
+ constant: plot2.getAttribute("opacityConstant")
41080
+ }
41081
+ });
41082
+ return alphaScheme(s2);
41083
+ }
41084
+ function colorScale(mark, prop) {
41085
+ const { plot: plot2, kde: grids } = mark;
41086
+ const flat = !grids[0][prop]?.map;
41087
+ const discrete = flat || Array.isArray(grids[0][prop]);
41088
+ const domainAttr = plot2.getAttribute("colorDomain");
41089
+ const domainFixed = domainAttr === Fixed;
41090
+ const domainTransient = domainAttr?.[Transient];
41091
+ const domain = !domainFixed && !domainTransient && domainAttr || (flat ? grids.map((cell2) => cell2[prop]).sort(ascending) : discrete ? gridDomainDiscrete(grids, prop) : gridDomainContinuous(grids, prop));
41092
+ if (domainFixed || domainTransient) {
41093
+ if (domainTransient)
41094
+ domain[Transient] = true;
41095
+ plot2.setAttribute("colorDomain", domain);
41096
+ }
41097
+ const s2 = scale2({
41098
+ color: {
41099
+ type: plot2.getAttribute("colorScale"),
41100
+ domain,
41101
+ range: plot2.getAttribute("colorRange"),
41102
+ clamp: plot2.getAttribute("colorClamp"),
41103
+ n: plot2.getAttribute("colorN"),
41104
+ nice: plot2.getAttribute("colorNice"),
41105
+ reverse: plot2.getAttribute("colorReverse"),
41106
+ scheme: plot2.getAttribute("colorScheme"),
41107
+ interpolate: plot2.getAttribute("colorInterpolate"),
41108
+ pivot: plot2.getAttribute("colorPivot"),
41109
+ symmetric: plot2.getAttribute("colorSymmetric"),
41110
+ zero: plot2.getAttribute("colorZero"),
41111
+ base: plot2.getAttribute("colorBase"),
41112
+ exponent: plot2.getAttribute("colorExponent"),
41113
+ constant: plot2.getAttribute("colorConstant")
41114
+ }
41115
+ });
41116
+ if (discrete) {
41117
+ return colorCategory(s2);
41118
+ } else {
41119
+ const frac = scale2({
41120
+ x: {
41121
+ type: inferScaleType2(s2.type),
41122
+ domain: s2.domain,
41123
+ reverse: s2.reverse,
41124
+ range: [0, 1],
41125
+ clamp: s2.clamp,
41126
+ base: s2.base,
41127
+ exponent: s2.exponent,
41128
+ constant: s2.constant
41129
+ }
41130
+ });
41131
+ return colorScheme(1024, s2, frac.apply);
41132
+ }
41133
+ }
41134
+ function inferScaleType2(type2) {
41135
+ if (type2.endsWith("symlog"))
41136
+ return "symlog";
41137
+ if (type2.endsWith("log"))
41138
+ return "log";
41139
+ if (type2.endsWith("pow"))
41140
+ return "pow";
41141
+ if (type2.endsWith("sqrt"))
41142
+ return "sqrt";
41143
+ if (type2 === "diverging")
41144
+ return "linear";
41145
+ return type2;
41146
+ }
40770
41147
  function imageData(mark, w, h) {
40771
41148
  if (!mark.image || mark.image.w !== w || mark.image.h !== h) {
40772
41149
  const canvas = createCanvas(w, h);
@@ -40776,71 +41153,21 @@ function imageData(mark, w, h) {
40776
41153
  }
40777
41154
  return mark.image;
40778
41155
  }
40779
- function imageScale(mark) {
40780
- const { densityMap, kde, plot: plot2 } = mark;
40781
- let domain = densityMap.fill && plot2.getAttribute("colorDomain");
40782
- if (!domain) {
40783
- let lo = 0, hi = 0;
40784
- kde.forEach((grid) => {
40785
- for (const v2 of grid) {
40786
- if (v2 < lo)
40787
- lo = v2;
40788
- if (v2 > hi)
40789
- hi = v2;
40790
- }
40791
- });
40792
- domain = lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
40793
- }
40794
- const type2 = plot2.getAttribute("colorScale");
40795
- return scale2({ x: { type: type2, domain, range: [0, 1] } }).apply;
40796
- }
40797
- function imagePalette(mark, domain, value, steps = 1024) {
40798
- const { densityMap, plot: plot2 } = mark;
40799
- const scheme28 = plot2.getAttribute("colorScheme");
40800
- const fill = mark.channel("fill");
40801
- let color3 = isColor2(fill?.value) ? fill.value : void 0;
40802
- if (densityMap.fill || scheme28 && !color3) {
40803
- if (scheme28) {
40804
- try {
40805
- return palette(
40806
- steps,
40807
- scale2({ color: { scheme: scheme28, domain: [0, 1] } }).interpolate
40808
- );
40809
- } catch (err) {
40810
- console.warn(err);
40811
- }
40812
- }
40813
- } else if (domain.length) {
40814
- const range3 = plot2.getAttribute("colorRange");
40815
- const spec = {
40816
- domain,
40817
- range: range3,
40818
- scheme: scheme28 || (range3 ? void 0 : "tableau10")
40819
- };
40820
- color3 = scale2({ color: spec }).apply(value);
40821
- }
40822
- return palette(steps, opacityMap(color3));
40823
- }
40824
41156
 
40825
41157
  // src/marks/DenseLineMark.js
40826
41158
  var DenseLineMark = class extends RasterMark {
40827
41159
  constructor(source, options) {
40828
41160
  const { normalize: normalize4 = true, ...rest } = options;
40829
- super(source, { bandwidth: 0, ...rest });
41161
+ super(source, rest);
40830
41162
  handleParam(this, "normalize", normalize4);
40831
41163
  }
40832
41164
  query(filter3 = []) {
40833
- const { plot: plot2, channels, normalize: normalize4, source } = this;
40834
- const [x06, x12] = extentX(this, filter3);
40835
- const [y06, y12] = extentY(this, filter3);
41165
+ const { channels, normalize: normalize4, source, binPad } = this;
40836
41166
  const [nx, ny] = this.bins = this.binDimensions(this);
40837
- const bx = binField(this, "x");
40838
- const by = binField(this, "y");
40839
- const rx = !!plot2.getAttribute("xReverse");
40840
- const ry = !!plot2.getAttribute("yReverse");
40841
- const x3 = bin1d(bx, x06, x12, nx, rx, this.binPad);
40842
- const y3 = bin1d(by, y06, y12, ny, ry, this.binPad);
41167
+ const [x3] = binExpr(this, "x", nx, extentX(this, filter3), binPad);
41168
+ const [y3] = binExpr(this, "y", ny, extentY(this, filter3), binPad);
40843
41169
  const q = Query.from(source.table).where(stripXY(this, filter3));
41170
+ this.aggr = ["density"];
40844
41171
  const groupby = this.groupby = [];
40845
41172
  const z = [];
40846
41173
  for (const c4 of channels) {
@@ -40887,7 +41214,7 @@ function lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {
40887
41214
  ));
40888
41215
  const num = Query.select({ x: sql`GREATEST(MAX(ABS(dx)), MAX(ABS(dy)))` }).from("pairs");
40889
41216
  const indices = Query.select({ i: sql`UNNEST(range((${num})))::INTEGER` });
40890
- const raster3 = Query.unionAll(
41217
+ const raster2 = Query.unionAll(
40891
41218
  Query.select(groups2, {
40892
41219
  x: sql`x0 + i`,
40893
41220
  y: sql`y0 + ROUND(i * dy / dx::FLOAT)::INTEGER`
@@ -40904,10 +41231,10 @@ function lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {
40904
41231
  "x",
40905
41232
  "y",
40906
41233
  normalize4 ? { w: sql`1.0 / COUNT(*) OVER (PARTITION BY ${pointPart})` } : null
40907
- ).where(and(isBetween("x", [0, xn]), isBetween("y", [0, yn])));
40908
- return Query.with({ pairs: pairs2, indices, raster: raster3, points: points2 }).from("points").select(groupby, {
41234
+ ).where(and(isBetween("x", [0, xn], true), isBetween("y", [0, yn], true)));
41235
+ return Query.with({ pairs: pairs2, indices, raster: raster2, points: points2 }).from("points").select(groupby, {
40909
41236
  index: sql`x + y * ${xn}::INTEGER`,
40910
- value: normalize4 ? sum2("w") : count()
41237
+ density: normalize4 ? sum2("w") : count()
40911
41238
  }).groupby("index", groupby);
40912
41239
  }
40913
41240
 
@@ -40932,13 +41259,11 @@ var Density1DMark = class extends Mark2 {
40932
41259
  if (this.hasOwnData())
40933
41260
  throw new Error("Density1DMark requires a data source");
40934
41261
  const { bins: bins2, channels, dim, source: { table } } = this;
40935
- const [lo, hi] = this.extent = (dim === "x" ? extentX : extentY)(this, filter3);
40936
- const bx = binField(this, dim);
40937
- return binLinear1d(
40938
- markQuery(channels, table, [dim]).where(filter3.concat(isBetween(bx, [lo, hi]))),
40939
- bin1d(bx, lo, hi, bins2),
40940
- this.channelField("weight") ? "weight" : null
40941
- );
41262
+ const extent4 = this.extent = (dim === "x" ? extentX : extentY)(this, filter3);
41263
+ const [x3, bx] = binExpr(this, dim, bins2, extent4);
41264
+ const q = markQuery(channels, table, [dim]).where(filter3.concat(isBetween(bx, extent4)));
41265
+ const v2 = this.channelField("weight") ? "weight" : null;
41266
+ return binLinear1d(q, x3, v2);
40942
41267
  }
40943
41268
  queryResult(data) {
40944
41269
  this.grid = grid1d(this.bins, data);
@@ -40973,8 +41298,8 @@ var Density1DMark = class extends Mark2 {
40973
41298
  return [{ type: type2, data, options }];
40974
41299
  }
40975
41300
  };
40976
- function binLinear1d(q, p, value) {
40977
- const w = value ? `* ${value}` : "";
41301
+ function binLinear1d(q, p, density2) {
41302
+ const w = density2 ? `* ${density2}` : "";
40978
41303
  const u4 = q.clone().select({
40979
41304
  p,
40980
41305
  i: sql`FLOOR(p)::INTEGER`,
@@ -40985,37 +41310,45 @@ function binLinear1d(q, p, value) {
40985
41310
  i: sql`FLOOR(p)::INTEGER + 1`,
40986
41311
  w: sql`(p - FLOOR(p))${w}`
40987
41312
  });
40988
- return Query.from(Query.unionAll(u4, v2)).select({ index: "i", value: sum2("w") }).groupby("index").having(gt("value", 0));
41313
+ return Query.from(Query.unionAll(u4, v2)).select({ index: "i", density: sum2("w") }).groupby("index").having(gt("density", 0));
40989
41314
  }
40990
41315
 
40991
41316
  // src/marks/Density2DMark.js
40992
41317
  var Density2DMark = class extends Grid2DMark {
40993
41318
  constructor(source, options) {
40994
- const { type: type2 = "dot", binsX, binsY, ...channels } = options;
40995
- channels.binPad = channels.binPad ?? 0;
40996
- super(type2, source, channels);
40997
- handleParam(this, "binsX", binsX);
40998
- handleParam(this, "binsY", binsY);
41319
+ const { type: type2 = "dot", ...channels } = options;
41320
+ super(type2, source, {
41321
+ bandwidth: 20,
41322
+ interpolate: "linear",
41323
+ pad: 0,
41324
+ pixelSize: 2,
41325
+ ...channels
41326
+ });
40999
41327
  }
41000
41328
  convolve() {
41001
41329
  super.convolve();
41002
- const { bins: bins2, binPad, extentX: extentX2, extentY: extentY2 } = this;
41330
+ const { bins: bins2, pad: pad3, extentX: extentX2, extentY: extentY2 } = this;
41003
41331
  const [nx, ny] = bins2;
41004
- const [x06, x12] = extentX2;
41005
- const [y06, y12] = extentY2;
41006
- const deltaX = (x12 - x06) / (nx - binPad);
41007
- const deltaY = (y12 - y06) / (ny - binPad);
41008
- const offset2 = binPad ? 0 : 0.5;
41009
- this.data = points(this.kde, bins2, x06, y06, deltaX, deltaY, offset2);
41332
+ const scaleX = channelScale(this, "x");
41333
+ const scaleY = channelScale(this, "y");
41334
+ const [x06, x12] = extentX2.map((v2) => scaleX.apply(v2));
41335
+ const [y06, y12] = extentY2.map((v2) => scaleY.apply(v2));
41336
+ const deltaX = (x12 - x06) / (nx - pad3);
41337
+ const deltaY = (y12 - y06) / (ny - pad3);
41338
+ const offset2 = pad3 ? 0 : 0.5;
41339
+ this.data = points(
41340
+ this.kde,
41341
+ bins2,
41342
+ x06,
41343
+ y06,
41344
+ deltaX,
41345
+ deltaY,
41346
+ scaleX.invert,
41347
+ scaleY.invert,
41348
+ offset2
41349
+ );
41010
41350
  return this;
41011
41351
  }
41012
- binDimensions() {
41013
- const { plot: plot2, binWidth, binsX, binsY } = this;
41014
- return [
41015
- binsX ?? Math.round(plot2.innerWidth() / binWidth),
41016
- binsY ?? Math.round(plot2.innerHeight() / binWidth)
41017
- ];
41018
- }
41019
41352
  plotSpecs() {
41020
41353
  const { type: type2, channels, densityMap, data } = this;
41021
41354
  const options = {};
@@ -41031,16 +41364,18 @@ var Density2DMark = class extends Grid2DMark {
41031
41364
  return [{ type: type2, data, options }];
41032
41365
  }
41033
41366
  };
41034
- function points(kde, bins2, x06, y06, deltaX, deltaY, offset2) {
41367
+ function points(kde, bins2, x06, y06, deltaX, deltaY, invertX, invertY, offset2) {
41035
41368
  const scale3 = 1 / (deltaX * deltaY);
41036
41369
  const [nx, ny] = bins2;
41037
41370
  const data = [];
41038
- for (const grid of kde) {
41371
+ for (const cell2 of kde) {
41372
+ const grid = cell2.density;
41039
41373
  for (let k2 = 0, j = 0; j < ny; ++j) {
41040
41374
  for (let i = 0; i < nx; ++i, ++k2) {
41041
41375
  data.push({
41042
- x: x06 + (i + offset2) * deltaX,
41043
- y: y06 + (j + offset2) * deltaY,
41376
+ ...cell2,
41377
+ x: invertX(x06 + (i + offset2) * deltaX),
41378
+ y: invertY(y06 + (j + offset2) * deltaY),
41044
41379
  density: grid[k2] * scale3
41045
41380
  });
41046
41381
  }
@@ -41158,34 +41493,48 @@ var RasterTileMark = class extends Grid2DMark {
41158
41493
  return null;
41159
41494
  }
41160
41495
  tileQuery(extent4) {
41161
- const { plot: plot2, binType, binPad, channels, densityMap, source } = this;
41496
+ const { binType, binPad, channels, densityMap, source } = this;
41162
41497
  const [[x06, x12], [y06, y12]] = extent4;
41163
41498
  const [nx, ny] = this.bins;
41164
- const bx = binField(this, "x");
41165
- const by = binField(this, "y");
41166
- const rx = !!plot2.getAttribute("xReverse");
41167
- const ry = !!plot2.getAttribute("yReverse");
41168
- const x3 = bin1d3(bx, x06, x12, nx, rx, binPad);
41169
- const y3 = bin1d3(by, y06, y12, ny, ry, binPad);
41170
- const bounds = binPad ? [isBetween(bx, [x06, x12]), isBetween(by, [y06, y12])] : [lte(x06, bx), lt(bx, x12), lte(y06, by), lt(by, y12)];
41499
+ const [x3, bx] = binExpr(this, "x", nx, [x06, x12], binPad);
41500
+ const [y3, by] = binExpr(this, "y", ny, [y06, y12], binPad);
41501
+ const bounds = binPad ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];
41171
41502
  const q = Query.from(source.table).where(bounds);
41172
41503
  const groupby = this.groupby = [];
41173
- let agg2 = count();
41504
+ const aggrMap = {};
41174
41505
  for (const c4 of channels) {
41175
41506
  if (Object.hasOwn(c4, "field")) {
41176
- const { channel, field: field2 } = c4;
41507
+ const { as, channel, field: field2 } = c4;
41177
41508
  if (field2.aggregate) {
41178
- agg2 = field2;
41509
+ aggrMap[channel] = field2;
41179
41510
  densityMap[channel] = true;
41180
41511
  } else if (channel === "weight") {
41181
- agg2 = sum2(field2);
41512
+ aggrMap.density = sum2(field2);
41182
41513
  } else if (channel !== "x" && channel !== "y") {
41183
- q.select({ [channel]: field2 });
41184
- groupby.push(channel);
41514
+ q.select({ [as]: field2 });
41515
+ groupby.push(as);
41185
41516
  }
41186
41517
  }
41187
41518
  }
41188
- return binType === "linear" ? binLinear2d2(q, x3, y3, agg2, nx, groupby) : bin2d2(q, x3, y3, agg2, nx, groupby);
41519
+ const aggr = this.aggr = Object.keys(aggrMap);
41520
+ if (aggrMap.density && aggr.length > 1) {
41521
+ throw new Error("Weight option can not be used with custom aggregates.");
41522
+ }
41523
+ if (!aggr.length) {
41524
+ aggr.push("density");
41525
+ aggrMap.density = count();
41526
+ }
41527
+ if (binType === "linear") {
41528
+ if (aggr.length > 1) {
41529
+ throw new Error("Linear binning not applicable to multiple aggregates.");
41530
+ }
41531
+ if (!aggrMap.density) {
41532
+ throw new Error("Linear binning not applicable to custom aggregates.");
41533
+ }
41534
+ return binLinear2d2(q, x3, y3, aggrMap.density, nx, groupby);
41535
+ } else {
41536
+ return bin2d2(q, x3, y3, aggrMap, nx, groupby);
41537
+ }
41189
41538
  }
41190
41539
  async requestTiles() {
41191
41540
  const mc = coordinator();
@@ -41235,22 +41584,20 @@ var RasterTileMark = class extends Grid2DMark {
41235
41584
  ([i, j]) => mc.prefetch(this.tileQuery(tileExtent(i, j)))
41236
41585
  );
41237
41586
  const tiles = await Promise.all(queries);
41238
- this.grids = [{ grid: processTiles(m, n, xx, yy, coords, tiles) }];
41587
+ this.grids = [{ density: processTiles(m, n, xx, yy, coords, tiles) }];
41239
41588
  this.convolve().update();
41240
41589
  }
41241
41590
  convolve() {
41242
41591
  return super.convolve().rasterize();
41243
41592
  }
41244
41593
  rasterize() {
41245
- const { bins: bins2, kde, groupby } = this;
41594
+ const { bins: bins2, kde } = this;
41246
41595
  const [w, h] = bins2;
41247
41596
  const { canvas, ctx, img } = imageData2(this, w, h);
41248
- const s2 = imageScale2(this);
41249
- const idx = groupby.indexOf(this.channelField("fill")?.as);
41250
- const domain = idx < 0 ? [] : kde.map(({ key }) => key[idx]);
41251
- this.data = kde.map((grid) => {
41252
- const palette2 = imagePalette2(this, domain, grid.key?.[idx]);
41253
- raster2(grid, img.data, w, h, s2, palette2);
41597
+ const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);
41598
+ this.data = kde.map((cell2) => {
41599
+ color3?.(img.data, w, h, cell2[colorProp]);
41600
+ alpha?.(img.data, w, h, cell2[alphaProp]);
41254
41601
  ctx.putImageData(img, 0, 0);
41255
41602
  return { src: canvas.toDataURL() };
41256
41603
  });
@@ -41284,7 +41631,7 @@ function copy3(m, n, grid, values2, tx, ty) {
41284
41631
  if (num === 0)
41285
41632
  return;
41286
41633
  const index2 = values2.getChild("index").toArray();
41287
- const value = values2.getChild("value").toArray();
41634
+ const value = values2.getChild("density").toArray();
41288
41635
  for (let row = 0; row < num; ++row) {
41289
41636
  const idx = index2[row];
41290
41637
  const i = tx + idx % m;
@@ -41303,60 +41650,10 @@ function imageData2(mark, w, h) {
41303
41650
  }
41304
41651
  return mark.image;
41305
41652
  }
41306
- function imageScale2(mark) {
41307
- const { densityMap, kde, plot: plot2 } = mark;
41308
- let domain = densityMap.fill && plot2.getAttribute("colorDomain");
41309
- if (!domain) {
41310
- let lo = 0, hi = 0;
41311
- kde.forEach((grid) => {
41312
- for (const v2 of grid) {
41313
- if (v2 < lo)
41314
- lo = v2;
41315
- if (v2 > hi)
41316
- hi = v2;
41317
- }
41318
- });
41319
- domain = lo === 0 && hi === 0 ? [0, 1] : [lo, hi];
41320
- }
41321
- const type2 = plot2.getAttribute("colorScale");
41322
- return scale2({ x: { type: type2, domain, range: [0, 1] } }).apply;
41323
- }
41324
- function imagePalette2(mark, domain, value, steps = 1024) {
41325
- const { densityMap, plot: plot2 } = mark;
41326
- const scheme28 = plot2.getAttribute("colorScheme");
41327
- const fill = mark.channel("fill");
41328
- let color3 = isColor2(fill?.value) ? fill.value : void 0;
41329
- if (densityMap.fill || scheme28 && !color3) {
41330
- if (scheme28) {
41331
- try {
41332
- return palette(
41333
- steps,
41334
- scale2({ color: { scheme: scheme28, domain: [0, 1] } }).interpolate
41335
- );
41336
- } catch (err) {
41337
- console.warn(err);
41338
- }
41339
- }
41340
- } else if (domain.length) {
41341
- const range3 = plot2.getAttribute("colorRange");
41342
- const spec = {
41343
- domain,
41344
- range: range3,
41345
- scheme: scheme28 || (range3 ? void 0 : "tableau10")
41346
- };
41347
- color3 = scale2({ color: spec }).apply(value);
41348
- }
41349
- return palette(steps, opacityMap(color3));
41350
- }
41351
- function bin1d3(x3, x06, x12, n, reverse3, pad3) {
41352
- const d = (n - pad3) / (x12 - x06);
41353
- const f = d !== 1 ? ` * ${d}::DOUBLE` : "";
41354
- return reverse3 ? sql`(${x12} - ${x3}::DOUBLE)${f}` : sql`(${x3}::DOUBLE - ${x06})${f}`;
41355
- }
41356
- function bin2d2(q, xp, yp, value, xn, groupby) {
41653
+ function bin2d2(q, xp, yp, aggs, xn, groupby) {
41357
41654
  return q.select({
41358
41655
  index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,
41359
- value
41656
+ ...aggs
41360
41657
  }).groupby("index", groupby);
41361
41658
  }
41362
41659
  function binLinear2d2(q, xp, yp, value, xn, groupby) {
@@ -41378,7 +41675,7 @@ function binLinear2d2(q, xp, yp, value, xn, groupby) {
41378
41675
  sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,
41379
41676
  sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`
41380
41677
  );
41381
- return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", value: sum2("w") }, groupby).groupby("index", groupby).having(neq("value", 0));
41678
+ return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: "i", density: sum2("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
41382
41679
  }
41383
41680
  function tileFloor(value) {
41384
41681
  const floored = Math.floor(value);
@@ -42209,28 +42506,24 @@ function findMark({ marks: marks2 }, channel) {
42209
42506
  }
42210
42507
 
42211
42508
  // src/transforms/bin.js
42212
- var EXTENT = [
42213
- "rectY-x",
42214
- "rectX-y",
42215
- "rect-x",
42216
- "rect-y"
42217
- ];
42218
- function hasExtent(channel, type2) {
42219
- return EXTENT.includes(`${type2}-${channel}`);
42220
- }
42509
+ var EXTENT = /* @__PURE__ */ new Set(["rectY-x", "rectX-y", "rect-x", "rect-y"]);
42221
42510
  function bin2(field2, options = { steps: 25 }) {
42222
42511
  const fn = (mark, channel) => {
42223
- return hasExtent(channel, mark.type) ? {
42224
- [`${channel}1`]: binField2(mark, field2, options),
42225
- [`${channel}2`]: binField2(mark, field2, { ...options, offset: 1 })
42226
- } : {
42227
- [channel]: binField2(mark, field2, options)
42228
- };
42512
+ if (EXTENT.has(`${mark.type}-${channel}`)) {
42513
+ return {
42514
+ [`${channel}1`]: binField(mark, channel, field2, options),
42515
+ [`${channel}2`]: binField(mark, channel, field2, { ...options, offset: 1 })
42516
+ };
42517
+ } else {
42518
+ return {
42519
+ [channel]: binField(mark, channel, field2, options)
42520
+ };
42521
+ }
42229
42522
  };
42230
42523
  fn[Transform] = true;
42231
42524
  return fn;
42232
42525
  }
42233
- function binField2(mark, column3, options) {
42526
+ function binField(mark, channel, column3, options) {
42234
42527
  return {
42235
42528
  column: column3,
42236
42529
  label: column3,
@@ -42244,13 +42537,15 @@ function binField2(mark, column3, options) {
42244
42537
  return column3;
42245
42538
  },
42246
42539
  toString() {
42540
+ const { apply: apply2, sqlApply, sqlInvert } = channelScale(mark, channel);
42247
42541
  const { min: min5, max: max4 } = mark.stats[column3];
42248
- const b = bins(min5, max4, options);
42249
- const col = asColumn(column3);
42542
+ const b = bins(apply2(min5), apply2(max4), options);
42543
+ const col = sqlApply(column3);
42250
42544
  const base = b.min === 0 ? col : `(${col} - ${b.min})`;
42251
42545
  const alpha = `${(b.max - b.min) / b.steps}::DOUBLE`;
42252
42546
  const off = options.offset ? `${options.offset} + ` : "";
42253
- return `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha})::INTEGER)`;
42547
+ const expr = `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha}))`;
42548
+ return `${sqlInvert(expr)}`;
42254
42549
  }
42255
42550
  };
42256
42551
  }
@@ -42294,6 +42589,7 @@ export {
42294
42589
  Fixed,
42295
42590
  GeoMark,
42296
42591
  Grid2DMark,
42592
+ HeatmapMark,
42297
42593
  HexbinMark,
42298
42594
  Highlight,
42299
42595
  Interval1D,