@uwdata/vgplot 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # vgplot: A Mosaic-powered Visualization Grammar
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@uwdata/vgplot.svg)](https://www.npmjs.com/package/@uwdata/vgplot)
4
+
3
5
  A **v**isualization **g**rammar for interactive Mosaic-powered visualizations and dashboards. This package provides convenient, composable methods that combines multiple Mosaic packages (core, inputs, plot, etc.) in an integrated API.
4
6
 
5
7
  vgplot is a JavaScript API for creating visualizations and dashboards. See the [mosaic-spec](https://github.com/uwdata/mosaic/tree/main/packages/spec) package to instead use declarative specifications in JSON or YAML format.
package/dist/vgplot.js CHANGED
@@ -103,7 +103,7 @@ var require_search_bounds = __commonJS({
103
103
  }
104
104
  return -1;
105
105
  }
106
- function norm(a2, y4, c4, l, h2, f2) {
106
+ function norm2(a2, y4, c4, l, h2, f2) {
107
107
  if (typeof c4 === "function") {
108
108
  return f2(a2, y4, c4, l === void 0 ? 0 : l | 0, h2 === void 0 ? a2.length - 1 : h2 | 0);
109
109
  }
@@ -111,19 +111,19 @@ var require_search_bounds = __commonJS({
111
111
  }
112
112
  module.exports = {
113
113
  ge: function(a2, y4, c4, l, h2) {
114
- return norm(a2, y4, c4, l, h2, ge);
114
+ return norm2(a2, y4, c4, l, h2, ge);
115
115
  },
116
116
  gt: function(a2, y4, c4, l, h2) {
117
- return norm(a2, y4, c4, l, h2, gt2);
117
+ return norm2(a2, y4, c4, l, h2, gt2);
118
118
  },
119
119
  lt: function(a2, y4, c4, l, h2) {
120
- return norm(a2, y4, c4, l, h2, lt2);
120
+ return norm2(a2, y4, c4, l, h2, lt2);
121
121
  },
122
122
  le: function(a2, y4, c4, l, h2) {
123
- return norm(a2, y4, c4, l, h2, le);
123
+ return norm2(a2, y4, c4, l, h2, le);
124
124
  },
125
125
  eq: function(a2, y4, c4, l, h2) {
126
- return norm(a2, y4, c4, l, h2, eq2);
126
+ return norm2(a2, y4, c4, l, h2, eq2);
127
127
  }
128
128
  };
129
129
  }
@@ -563,14 +563,15 @@ var MosaicClient = class {
563
563
  }
564
564
  /**
565
565
  * Return an array of fields queried by this client.
566
- * @returns {object[]|null} The fields to retrieve info for.
566
+ * @returns {import('./types.js').FieldInfoRequest[] | null}
567
+ * The fields to retrieve info for.
567
568
  */
568
569
  fields() {
569
570
  return null;
570
571
  }
571
572
  /**
572
573
  * Called by the coordinator to set the field info for this client.
573
- * @param {*} info The field info result.
574
+ * @param {import('./types.js').FieldInfo[]} info The field info result.
574
575
  * @returns {this}
575
576
  */
576
577
  fieldInfo(info) {
@@ -3451,6 +3452,9 @@ var ColumnNameRefNode = class extends ColumnRefNode {
3451
3452
  };
3452
3453
 
3453
3454
  // ../sql/src/ast/column-param.js
3455
+ function isColumnParam(value) {
3456
+ return value instanceof ColumnParamNode;
3457
+ }
3454
3458
  var ColumnParamNode = class extends ColumnRefNode {
3455
3459
  /**
3456
3460
  * Instantiate a column param node.
@@ -5039,7 +5043,7 @@ function collectAggregates(root2) {
5039
5043
  function collectColumns(root2) {
5040
5044
  const cols = {};
5041
5045
  walk(root2, (node) => {
5042
- if (node.type === COLUMN_REF) {
5046
+ if (node.type === COLUMN_REF || node.type === COLUMN_PARAM) {
5043
5047
  cols[node] = node;
5044
5048
  }
5045
5049
  });
@@ -5170,21 +5174,21 @@ function bin2d(q2, xp, yp, aggs, xn, groupby) {
5170
5174
  }
5171
5175
 
5172
5176
  // ../sql/src/transforms/bin-linear-1d.js
5173
- function binLinear1d(query, x4, weight) {
5177
+ function binLinear1d(query, x4, weight = void 0, groupby = []) {
5174
5178
  const w = weight ? (x5) => mul(x5, weight) : (x5) => x5;
5175
5179
  const p0 = floor(x4);
5176
5180
  const p1 = add(p0, 1);
5177
5181
  return Query.from(Query.unionAll(
5178
5182
  query.clone().select({ i: int322(p0), w: w(sub(p1, x4)) }),
5179
5183
  query.clone().select({ i: int322(p1), w: w(sub(x4, p0)) })
5180
- )).select({ index: "i", density: sum("w") }).groupby("index").having(neq("density", 0));
5184
+ )).select({ index: "i", density: sum("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
5181
5185
  }
5182
5186
 
5183
5187
  // ../sql/src/transforms/bin-linear-2d.js
5184
5188
  function identity(x4) {
5185
5189
  return x4;
5186
5190
  }
5187
- function binLinear2d(q2, xp, yp, weight, xn, groupby) {
5191
+ function binLinear2d(q2, xp, yp, weight, xn, groupby = []) {
5188
5192
  const w = weight ? (x4) => mul(x4, weight) : identity;
5189
5193
  const subq = (i, w2) => q2.clone().select({ xp, yp, i, w: w2 });
5190
5194
  const index2 = (x4, y4) => add(x4, mul(y4, xn));
@@ -5914,7 +5918,7 @@ var statMap = {
5914
5918
  [Min]: min,
5915
5919
  [Nulls]: (column3) => count().where(isNull(column3))
5916
5920
  };
5917
- function summarize(table3, column3, stats) {
5921
+ function summarize({ table: table3, column: column3, stats }) {
5918
5922
  return Query.from(table3).select(Array.from(stats, (s2) => ({ [s2]: statMap[s2](column3) })));
5919
5923
  }
5920
5924
  async function queryFieldInfo(mc, fields) {
@@ -5925,7 +5929,7 @@ async function queryFieldInfo(mc, fields) {
5925
5929
  }
5926
5930
  }
5927
5931
  async function getFieldInfo(mc, { table: table3, column: column3, stats }) {
5928
- const q2 = Query.from({ source: table3 }).select({ column: column3 }).groupby(column3.aggregate ? sql`ALL` : []);
5932
+ const q2 = Query.from({ source: table3 }).select({ column: column3 }).groupby(isNode(column3) && isAggregateExpression(column3) ? sql`ALL` : []);
5929
5933
  const [desc2] = Array.from(await mc.query(Query.describe(q2)));
5930
5934
  const info = {
5931
5935
  table: table3,
@@ -5934,16 +5938,16 @@ async function getFieldInfo(mc, { table: table3, column: column3, stats }) {
5934
5938
  type: jsType(desc2.column_type),
5935
5939
  nullable: desc2.null === "YES"
5936
5940
  };
5937
- if (!(stats?.length || stats?.size)) return info;
5941
+ if (!stats?.length) return info;
5938
5942
  const [result] = await mc.query(
5939
- summarize(table3, column3, stats),
5943
+ summarize({ table: table3, column: column3, stats }),
5940
5944
  { persist: true }
5941
5945
  );
5942
5946
  return Object.assign(info, result);
5943
5947
  }
5944
5948
  async function getTableInfo(mc, table3) {
5945
- const result = await mc.query(`DESCRIBE ${asTableRef(table3)}`);
5946
- return Array.from(result).map((desc2) => ({
5949
+ const result = Array.from(await mc.query(`DESCRIBE ${asTableRef(table3)}`));
5950
+ return result.map((desc2) => ({
5947
5951
  table: table3,
5948
5952
  column: desc2.column_name,
5949
5953
  sqlType: desc2.column_type,
@@ -6559,7 +6563,10 @@ var Coordinator = class {
6559
6563
  * or a SQL string.
6560
6564
  * @param {object} [options] An options object.
6561
6565
  * @param {'arrow' | 'json'} [options.type] The query result format type.
6562
- * @param {boolean} [options.cache=true] If true, cache the query result.
6566
+ * @param {boolean} [options.cache=true] If true, cache the query result
6567
+ * client-side within the QueryManager.
6568
+ * @param {boolean} [options.persist] If true, request the database
6569
+ * server to persist a cached query server-side.
6563
6570
  * @param {number} [options.priority] The query priority, defaults to
6564
6571
  * `Priority.Normal`.
6565
6572
  * @returns {QueryResult} A query result promise.
@@ -19664,7 +19671,7 @@ function clausePoint(field3, value, {
19664
19671
  source,
19665
19672
  clients = source ? /* @__PURE__ */ new Set([source]) : void 0
19666
19673
  }) {
19667
- const predicate = value !== void 0 ? isNotDistinct(field3, literal(value)) : null;
19674
+ const predicate = value !== void 0 ? isIn(field3, [literal(value)]) : null;
19668
19675
  return {
19669
19676
  meta: { type: "point" },
19670
19677
  source,
@@ -20118,6 +20125,8 @@ __export(api_exports, {
20118
20125
  voronoi: () => voronoi2,
20119
20126
  voronoiMesh: () => voronoiMesh2,
20120
20127
  vspace: () => vspace,
20128
+ waffleX: () => waffleX2,
20129
+ waffleY: () => waffleY2,
20121
20130
  width: () => width,
20122
20131
  xAlign: () => xAlign,
20123
20132
  xAriaDescription: () => xAriaDescription,
@@ -44193,7 +44202,9 @@ function isColor2(value) {
44193
44202
 
44194
44203
  // ../plot/src/marks/util/is-constant-option.js
44195
44204
  var constantOptions = /* @__PURE__ */ new Set([
44205
+ "offset",
44196
44206
  "order",
44207
+ "reverse",
44197
44208
  "sort",
44198
44209
  "label",
44199
44210
  "anchor",
@@ -44265,7 +44276,7 @@ var isFieldObject = (channel, field3) => {
44265
44276
  var fieldEntry = (channel, field3) => ({
44266
44277
  channel,
44267
44278
  field: field3,
44268
- as: isColumnRef(field3) ? field3.column : channel
44279
+ as: isColumnRef(field3) && !isColumnParam(field3) ? field3.column : channel
44269
44280
  });
44270
44281
  var valueEntry = (channel, value) => ({ channel, value });
44271
44282
  var isDataArray = (source) => Array.isArray(source);
@@ -44361,7 +44372,11 @@ var Mark2 = class extends MosaicClient {
44361
44372
  reqs[channel]?.forEach((s2) => entry.add(s2));
44362
44373
  }
44363
44374
  const table3 = this.sourceTable();
44364
- return Array.from(fields, ([c4, s2]) => ({ table: table3, column: c4, stats: s2 }));
44375
+ return Array.from(fields, ([c4, s2]) => ({
44376
+ table: table3,
44377
+ column: c4,
44378
+ stats: Array.from(s2)
44379
+ }));
44365
44380
  }
44366
44381
  fieldInfo(info) {
44367
44382
  const lookup = Object.fromEntries(info.map((x4) => [x4.column, x4]));
@@ -44559,13 +44574,33 @@ var ConnectedMark = class extends Mark2 {
44559
44574
  function array3(size, proto = []) {
44560
44575
  return new proto.constructor(size);
44561
44576
  }
44562
- function grid1d(size, index2, value) {
44563
- const G = array3(size, value);
44564
- const n = value.length;
44565
- for (let i = 0; i < n; ++i) {
44566
- G[index2[i]] = value[i];
44577
+ function grid1d(size, index2, value, columns, groupby) {
44578
+ const numRows = index2.length;
44579
+ const result = {};
44580
+ const cells = [];
44581
+ if (groupby?.length) {
44582
+ const group3 = new Int32Array(numRows);
44583
+ const gvalues = groupby.map((name2) => columns[name2]);
44584
+ const cellMap = {};
44585
+ for (let row = 0; row < numRows; ++row) {
44586
+ const key = gvalues.map((group4) => group4[row]);
44587
+ group3[row] = cellMap[key] ??= cells.push(key) - 1;
44588
+ }
44589
+ for (let i = 0; i < groupby.length; ++i) {
44590
+ result[groupby[i]] = cells.map((cell3) => cell3[i]);
44591
+ }
44592
+ const G = result._grid = cells.map(() => array3(size, value));
44593
+ for (let row = 0; row < numRows; ++row) {
44594
+ G[group3[row]][index2[row]] = value[row];
44595
+ }
44596
+ } else {
44597
+ cells.push([]);
44598
+ const [G] = result._grid = [array3(size, value)];
44599
+ for (let row = 0; row < numRows; ++row) {
44600
+ G[index2[row]] = value[row];
44601
+ }
44567
44602
  }
44568
- return G;
44603
+ return { numRows: cells.length, columns: result };
44569
44604
  }
44570
44605
  function grid2d(w, h2, index2, columns, aggregates, groupby, interpolate) {
44571
44606
  const numRows = index2.length;
@@ -45423,9 +45458,16 @@ function stripXY(mark2, filter3) {
45423
45458
  }
45424
45459
 
45425
45460
  // ../plot/src/marks/Density1DMark.js
45461
+ var GROUPBY = { fill: 1, stroke: 1, z: 1 };
45426
45462
  var Density1DMark = class extends Mark2 {
45427
45463
  constructor(type2, source, options) {
45428
- const { bins: bins2 = 1024, bandwidth = 20, ...channels } = options;
45464
+ const {
45465
+ bins: bins2 = 1024,
45466
+ bandwidth = 20,
45467
+ normalize: normalize4 = false,
45468
+ stack: stack2 = false,
45469
+ ...channels
45470
+ } = options;
45429
45471
  const dim = type2.endsWith("X") ? "y" : "x";
45430
45472
  super(type2, source, channels, dim === "x" ? xext : yext);
45431
45473
  this.dim = dim;
@@ -45434,7 +45476,13 @@ var Density1DMark = class extends Mark2 {
45434
45476
  });
45435
45477
  this.bandwidth = handleParam(bandwidth, (value) => {
45436
45478
  this.bandwidth = value;
45437
- return this.grid ? this.convolve().update() : null;
45479
+ return this.grids ? this.convolve().update() : null;
45480
+ });
45481
+ this.normalize = handleParam(normalize4, (value) => {
45482
+ return this.normalize = value, this.convolve().update();
45483
+ });
45484
+ this.stack = handleParam(stack2, (value) => {
45485
+ return this.stack = value, this.update();
45438
45486
  });
45439
45487
  }
45440
45488
  get filterStable() {
@@ -45449,42 +45497,67 @@ var Density1DMark = class extends Mark2 {
45449
45497
  const [x4, bx] = binExpr(this, dim, bins2, extent4);
45450
45498
  const q2 = markQuery(channels, this.sourceTable(), [dim]).where(filter3.concat(isBetween(bx, extent4)));
45451
45499
  const v3 = this.channelField("weight") ? "weight" : null;
45452
- return binLinear1d(q2, x4, v3);
45500
+ const g2 = this.groupby = channels.flatMap((c4) => {
45501
+ return GROUPBY[c4.channel] && c4.field ? c4.as : [];
45502
+ });
45503
+ return binLinear1d(q2, x4, v3, g2);
45453
45504
  }
45454
45505
  queryResult(data) {
45455
- const { columns: { index: index2, density: density3 } } = toDataColumns(data);
45456
- this.grid = grid1d(this.bins, index2, density3);
45506
+ const c4 = toDataColumns(data).columns;
45507
+ this.grids = grid1d(this.bins, c4.index, c4.density, c4, this.groupby);
45457
45508
  return this.convolve();
45458
45509
  }
45459
45510
  convolve() {
45460
- const { bins: bins2, bandwidth, dim, grid: grid2, plot: plot3, extent: [lo, hi] } = this;
45461
- const neg = grid2.some((v4) => v4 < 0);
45511
+ const {
45512
+ bins: bins2,
45513
+ bandwidth,
45514
+ normalize: normalize4,
45515
+ dim,
45516
+ grids,
45517
+ groupby,
45518
+ plot: plot3,
45519
+ extent: [lo, hi]
45520
+ } = this;
45521
+ const cols = grids.columns;
45522
+ const numGrids = grids.numRows;
45523
+ const b2 = this.channelField(dim).as;
45524
+ const v3 = dim === "x" ? "y" : "x";
45462
45525
  const size = dim === "x" ? plot3.innerWidth() : plot3.innerHeight();
45526
+ const neg = cols._grid.some((grid2) => grid2.some((v4) => v4 < 0));
45463
45527
  const config = dericheConfig(bandwidth * (bins2 - 1) / size, neg);
45464
- const result = dericheConv1d(config, grid2, bins2);
45465
- const v3 = dim === "x" ? "y" : "x";
45466
- const b2 = this.channelField(dim).as;
45467
45528
  const b0 = +lo;
45468
45529
  const delta = (hi - b0) / (bins2 - 1);
45469
- const scale3 = 1 / delta;
45470
- const _b2 = new Float64Array(bins2);
45471
- const _v2 = new Float64Array(bins2);
45472
- for (let i = 0; i < bins2; ++i) {
45473
- _b2[i] = b0 + i * delta;
45474
- _v2[i] = result[i] * scale3;
45475
- }
45476
- this.data = { numRows: bins2, columns: { [b2]: _b2, [v3]: _v2 } };
45530
+ const numRows = bins2 * numGrids;
45531
+ const _b2 = new Float64Array(numRows);
45532
+ const _v2 = new Float64Array(numRows);
45533
+ const _g2 = groupby.reduce((m2, name2) => (m2[name2] = Array(numRows), m2), {});
45534
+ for (let k3 = 0, g2 = 0; g2 < numGrids; ++g2) {
45535
+ groupby.forEach((name2) => _g2[name2].fill(cols[name2][g2], k3, k3 + bins2));
45536
+ const grid2 = cols._grid[g2];
45537
+ const result = dericheConv1d(config, grid2, bins2);
45538
+ const scale3 = 1 / norm(grid2, result, delta, normalize4);
45539
+ for (let i = 0; i < bins2; ++i, ++k3) {
45540
+ _b2[k3] = b0 + i * delta;
45541
+ _v2[k3] = result[i] * scale3;
45542
+ }
45543
+ }
45544
+ this.data = { numRows, columns: { [b2]: _b2, [v3]: _v2, ..._g2 } };
45477
45545
  return this;
45478
45546
  }
45479
45547
  plotSpecs() {
45480
- const { type: type2, data: { numRows: length4, columns }, channels, dim } = this;
45481
- const options = dim === "x" ? { y: columns.y } : { x: columns.x };
45548
+ const { type: type2, data: { numRows: length4, columns }, channels, dim, stack: stack2 } = this;
45549
+ const _2 = type2.startsWith("area") && !stack2 ? "2" : "";
45550
+ const options = dim === "x" ? { [`y${_2}`]: columns.y } : { [`x${_2}`]: columns.x };
45482
45551
  for (const c4 of channels) {
45483
45552
  options[c4.channel] = channelOption(c4, columns);
45484
45553
  }
45485
45554
  return [{ type: type2, data: { length: length4 }, options }];
45486
45555
  }
45487
45556
  };
45557
+ function norm(grid2, smoothed, delta, type2) {
45558
+ const value = type2 === true || type2 === "sum" ? sum2(grid2) : type2 === "max" ? max2(smoothed) : delta;
45559
+ return value || 1;
45560
+ }
45488
45561
 
45489
45562
  // ../plot/src/marks/Density2DMark.js
45490
45563
  var Density2DMark = class extends Grid2DMark {
@@ -45856,13 +45929,16 @@ var HexbinMark = class extends Mark2 {
45856
45929
  float642(x12),
45857
45930
  div(add(mul(add(x4, mul(0.5, bitAnd(y4, 1))), dx), ox2), xr)
45858
45931
  ),
45859
- [yc.as]: sub(float642(y22), div(add(mul(y4, dy), oy2), yr)),
45932
+ [yc.as]: sub(
45933
+ float642(y22),
45934
+ div(add(mul(y4, dy), oy2), yr)
45935
+ ),
45860
45936
  ...cols
45861
45937
  }).groupby(x4, y4, ...dims).from(
45862
45938
  // Subquery performs hex binning in screen space and also passes
45863
45939
  // original columns through (the DB should optimize this).
45864
45940
  Query.select({
45865
- [py]: div(mul(yr, sub(sub(y22, yc.field), oy2)), dy),
45941
+ [py]: div(sub(mul(yr, sub(y22, yc.field)), oy2), dy),
45866
45942
  [pj]: int322(round(py)),
45867
45943
  [px]: sub(
45868
45944
  div(sub(mul(xr, sub(xc.field, x12)), ox2), dx),
@@ -47549,6 +47625,7 @@ var Menu = class extends MosaicClient {
47549
47625
  constructor({
47550
47626
  element,
47551
47627
  filterBy,
47628
+ as,
47552
47629
  from: from2,
47553
47630
  column: column3,
47554
47631
  label = column3,
@@ -47556,8 +47633,7 @@ var Menu = class extends MosaicClient {
47556
47633
  // TODO
47557
47634
  options,
47558
47635
  value,
47559
- field: field3 = column3,
47560
- as
47636
+ field: field3 = column3
47561
47637
  } = {}) {
47562
47638
  super(filterBy);
47563
47639
  this.from = from2;
@@ -47574,8 +47650,8 @@ var Menu = class extends MosaicClient {
47574
47650
  this.select = document.createElement("select");
47575
47651
  this.element.appendChild(this.select);
47576
47652
  if (options) {
47577
- this.data = options.map((value2) => isObject3(value2) ? value2 : { value: value2 });
47578
- this.selectedValue(value ?? "");
47653
+ this.data = options.map((opt) => isObject3(opt) ? opt : { value: opt });
47654
+ this.selectedValue(value === void 0 ? "" : value);
47579
47655
  this.update();
47580
47656
  }
47581
47657
  if (selection2) {
@@ -47592,6 +47668,11 @@ var Menu = class extends MosaicClient {
47592
47668
  this.selectedValue(value2);
47593
47669
  }
47594
47670
  });
47671
+ } else {
47672
+ this.select.addEventListener("pointerenter", (evt) => {
47673
+ if (!evt.buttons) this.activate();
47674
+ });
47675
+ this.select.addEventListener("focus", () => this.activate());
47595
47676
  }
47596
47677
  }
47597
47678
  }
@@ -47611,6 +47692,9 @@ var Menu = class extends MosaicClient {
47611
47692
  reset() {
47612
47693
  this.select.selectedIndex = this.from ? 0 : -1;
47613
47694
  }
47695
+ activate() {
47696
+ this.selection.activate(clausePoint(this.field, 0, { source: this }));
47697
+ }
47614
47698
  publish(value) {
47615
47699
  const { selection: selection2, field: field3 } = this;
47616
47700
  if (isSelection(selection2)) {
@@ -47641,7 +47725,7 @@ var Menu = class extends MosaicClient {
47641
47725
  }
47642
47726
  if (selection2) {
47643
47727
  const value = isSelection(selection2) ? selection2.valueFor(this) : selection2.value;
47644
- this.selectedValue(value ?? "");
47728
+ this.selectedValue(value === void 0 ? "" : value);
47645
47729
  }
47646
47730
  return this;
47647
47731
  }
@@ -47716,17 +47800,28 @@ var Search = class extends MosaicClient {
47716
47800
  this.searchbox.value = value;
47717
47801
  }
47718
47802
  });
47803
+ } else {
47804
+ this.searchbox.addEventListener("pointerenter", (evt) => {
47805
+ if (!evt.buttons) this.activate();
47806
+ });
47807
+ this.searchbox.addEventListener("focus", () => this.activate());
47719
47808
  }
47720
47809
  }
47721
47810
  }
47722
47811
  reset() {
47723
47812
  this.searchbox.value = "";
47724
47813
  }
47814
+ clause(value) {
47815
+ const { field: field3, type: type2 } = this;
47816
+ return clauseMatch(field3, value, { source: this, method: type2 });
47817
+ }
47818
+ activate() {
47819
+ this.selection.activate(this.clause(""));
47820
+ }
47725
47821
  publish(value) {
47726
- const { selection: selection2, field: field3, type: type2 } = this;
47822
+ const { selection: selection2 } = this;
47727
47823
  if (isSelection(selection2)) {
47728
- const clause = clauseMatch(field3, value, { source: this, method: type2 });
47729
- selection2.update(clause);
47824
+ selection2.update(this.clause(value));
47730
47825
  } else if (isParam(selection2)) {
47731
47826
  selection2.update(value);
47732
47827
  }
@@ -47845,13 +47940,20 @@ var Slider = class extends MosaicClient {
47845
47940
  this.curval.innerText = value2;
47846
47941
  if (this.selection) this.publish(+value2);
47847
47942
  });
47848
- if (this.selection && !isSelection(this.selection)) {
47849
- this.selection.addEventListener("value", (value2) => {
47850
- if (value2 !== +this.slider.value) {
47851
- this.slider.value = value2;
47852
- this.curval.innerText = value2;
47853
- }
47854
- });
47943
+ if (this.selection) {
47944
+ if (!isSelection(this.selection)) {
47945
+ this.selection.addEventListener("value", (value2) => {
47946
+ if (value2 !== +this.slider.value) {
47947
+ this.slider.value = value2;
47948
+ this.curval.innerText = value2;
47949
+ }
47950
+ });
47951
+ } else {
47952
+ this.slider.addEventListener("pointerenter", (evt) => {
47953
+ if (!evt.buttons) this.activate();
47954
+ });
47955
+ this.slider.addEventListener("focus", () => this.activate());
47956
+ }
47855
47957
  }
47856
47958
  }
47857
47959
  query(filter3 = []) {
@@ -47875,20 +47977,27 @@ var Slider = class extends MosaicClient {
47875
47977
  }
47876
47978
  return this;
47877
47979
  }
47980
+ clause(value) {
47981
+ const { field: field3, selectionType } = this;
47982
+ if (selectionType === "interval") {
47983
+ const domain = [this.min ?? 0, value];
47984
+ return clauseInterval(field3, domain, {
47985
+ source: this,
47986
+ bin: "ceil",
47987
+ scale: { type: "identity", domain },
47988
+ pixelSize: this.step
47989
+ });
47990
+ } else {
47991
+ return clausePoint(field3, value, { source: this });
47992
+ }
47993
+ }
47994
+ activate() {
47995
+ this.selection.activate(this.clause(0));
47996
+ }
47878
47997
  publish(value) {
47879
- const { field: field3, selectionType, selection: selection2 } = this;
47998
+ const { selection: selection2 } = this;
47880
47999
  if (isSelection(selection2)) {
47881
- if (selectionType === "interval") {
47882
- const domain = [this.min ?? 0, value];
47883
- selection2.update(clauseInterval(field3, domain, {
47884
- source: this,
47885
- bin: "ceil",
47886
- scale: { type: "identity", domain },
47887
- pixelSize: this.step
47888
- }));
47889
- } else {
47890
- selection2.update(clausePoint(field3, value, { source: this }));
47891
- }
48000
+ selection2.update(this.clause(value));
47892
48001
  } else if (isParam(this.selection)) {
47893
48002
  selection2.update(value);
47894
48003
  }
@@ -48012,8 +48121,8 @@ var Table3 = class extends MosaicClient {
48012
48121
  coordinator().prefetch(query.clone().offset(offset2 + this.limit));
48013
48122
  }
48014
48123
  fields() {
48015
- const from2 = this.sourceTable();
48016
- return this.columns.map((name2) => column(name2, from2));
48124
+ const table3 = this.sourceTable();
48125
+ return this.columns.map((column3) => ({ column: column3, table: table3 }));
48017
48126
  }
48018
48127
  fieldInfo(info) {
48019
48128
  this.schema = info;
@@ -48791,7 +48900,9 @@ __export(marks_exports, {
48791
48900
  vectorX: () => vectorX2,
48792
48901
  vectorY: () => vectorY2,
48793
48902
  voronoi: () => voronoi2,
48794
- voronoiMesh: () => voronoiMesh2
48903
+ voronoiMesh: () => voronoiMesh2,
48904
+ waffleX: () => waffleX2,
48905
+ waffleY: () => waffleY2
48795
48906
  });
48796
48907
  var decorators = /* @__PURE__ */ new Set([
48797
48908
  "frame",
@@ -48888,6 +48999,8 @@ var gridFy2 = (...args) => mark("gridFy", ...args);
48888
48999
  var geo2 = (...args) => implicitType(GeoMark, ...args);
48889
49000
  var sphere2 = (...args) => mark("sphere", ...args);
48890
49001
  var graticule3 = (...args) => mark("graticule", ...args);
49002
+ var waffleX2 = (...args) => mark("waffleX", ...args);
49003
+ var waffleY2 = (...args) => mark("waffleY", ...args);
48891
49004
 
48892
49005
  // src/plot/interactors.js
48893
49006
  var interactors_exports = {};
@@ -49369,6 +49482,8 @@ export {
49369
49482
  voronoi2 as voronoi,
49370
49483
  voronoiMesh2 as voronoiMesh,
49371
49484
  vspace,
49485
+ waffleX2 as waffleX,
49486
+ waffleY2 as waffleY,
49372
49487
  wasmConnector,
49373
49488
  width,
49374
49489
  xAlign,