@uwdata/mosaic-plot 0.12.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mosaic-plot.js +225 -195
- package/dist/mosaic-plot.min.js +8 -8
- package/package.json +9 -12
- package/src/interactors/Interval1D.js +4 -0
- package/src/interactors/Interval2D.js +4 -0
- package/src/interactors/Nearest.js +10 -4
- package/src/interactors/PanZoom.js +17 -10
- package/src/interactors/Region.js +4 -0
- package/src/interactors/Toggle.js +10 -3
- package/src/marks/ConnectedMark.js +1 -1
- package/src/marks/Mark.js +1 -1
- package/src/plot.js +14 -3
- package/src/transforms/bin.js +7 -26
- package/vitest.config.ts +3 -0
- package/src/transforms/bin-step.js +0 -43
- package/src/transforms/time-interval.js +0 -53
package/dist/mosaic-plot.js
CHANGED
|
@@ -489,169 +489,9 @@ var Fixed = Symbol("Fixed");
|
|
|
489
489
|
var Transient = Symbol("Transient");
|
|
490
490
|
var Transform = Symbol("Transform");
|
|
491
491
|
|
|
492
|
-
// ../core/src/util/throttle.js
|
|
493
|
-
var NIL = {};
|
|
494
|
-
function throttle(callback, debounce = false) {
|
|
495
|
-
let curr;
|
|
496
|
-
let next;
|
|
497
|
-
let pending = NIL;
|
|
498
|
-
function invoke(event) {
|
|
499
|
-
curr = callback(event).catch(() => {
|
|
500
|
-
}).finally(() => {
|
|
501
|
-
if (next) {
|
|
502
|
-
const { value } = next;
|
|
503
|
-
next = null;
|
|
504
|
-
invoke(value);
|
|
505
|
-
} else {
|
|
506
|
-
curr = null;
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
function enqueue(event) {
|
|
511
|
-
next = { event };
|
|
512
|
-
}
|
|
513
|
-
function process(event) {
|
|
514
|
-
curr ? enqueue(event) : invoke(event);
|
|
515
|
-
}
|
|
516
|
-
function delay(event) {
|
|
517
|
-
if (pending !== event) {
|
|
518
|
-
requestAnimationFrame(() => {
|
|
519
|
-
const e = pending;
|
|
520
|
-
pending = NIL;
|
|
521
|
-
process(e);
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
pending = event;
|
|
525
|
-
}
|
|
526
|
-
return debounce ? delay : process;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// ../core/src/MosaicClient.js
|
|
530
|
-
var MosaicClient = class {
|
|
531
|
-
/**
|
|
532
|
-
* Constructor.
|
|
533
|
-
* @param {*} filterSelection An optional selection to interactively filter
|
|
534
|
-
* this client's data. If provided, a coordinator will re-query and update
|
|
535
|
-
* the client when the selection updates.
|
|
536
|
-
*/
|
|
537
|
-
constructor(filterSelection) {
|
|
538
|
-
this._filterBy = filterSelection;
|
|
539
|
-
this._requestUpdate = throttle(() => this.requestQuery(), true);
|
|
540
|
-
this._coordinator = null;
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Return this client's connected coordinator.
|
|
544
|
-
*/
|
|
545
|
-
get coordinator() {
|
|
546
|
-
return this._coordinator;
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Set this client's connected coordinator.
|
|
550
|
-
*/
|
|
551
|
-
set coordinator(coordinator2) {
|
|
552
|
-
this._coordinator = coordinator2;
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Return this client's filter selection.
|
|
556
|
-
*/
|
|
557
|
-
get filterBy() {
|
|
558
|
-
return this._filterBy;
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* Return a boolean indicating if the client query can be sped up with
|
|
562
|
-
* materialized views of pre-aggregated data. Should return true if changes to
|
|
563
|
-
* the filterBy selection does not change the groupby domain of the client
|
|
564
|
-
* query.
|
|
565
|
-
*/
|
|
566
|
-
get filterStable() {
|
|
567
|
-
return true;
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Return an array of fields queried by this client.
|
|
571
|
-
* @returns {import('./types.js').FieldInfoRequest[] | null}
|
|
572
|
-
* The fields to retrieve info for.
|
|
573
|
-
*/
|
|
574
|
-
fields() {
|
|
575
|
-
return null;
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* Called by the coordinator to set the field info for this client.
|
|
579
|
-
* @param {import('./types.js').FieldInfo[]} info The field info result.
|
|
580
|
-
* @returns {this}
|
|
581
|
-
*/
|
|
582
|
-
fieldInfo(info) {
|
|
583
|
-
return this;
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Return a query specifying the data needed by this client.
|
|
587
|
-
* @param {*} [filter] The filtering criteria to apply in the query.
|
|
588
|
-
* @returns {*} The client query
|
|
589
|
-
*/
|
|
590
|
-
query(filter3) {
|
|
591
|
-
return null;
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Called by the coordinator to inform the client that a query is pending.
|
|
595
|
-
* @returns {this}
|
|
596
|
-
*/
|
|
597
|
-
queryPending() {
|
|
598
|
-
return this;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Called by the coordinator to return a query result.
|
|
602
|
-
* @param {*} data The query result.
|
|
603
|
-
* @returns {this}
|
|
604
|
-
*/
|
|
605
|
-
queryResult(data) {
|
|
606
|
-
return this;
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Called by the coordinator to report a query execution error.
|
|
610
|
-
* @param {*} error
|
|
611
|
-
* @returns {this}
|
|
612
|
-
*/
|
|
613
|
-
queryError(error) {
|
|
614
|
-
return this;
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* Request the coordinator to execute a query for this client.
|
|
618
|
-
* If an explicit query is not provided, the client query method will
|
|
619
|
-
* be called, filtered by the current filterBy selection.
|
|
620
|
-
* @returns {Promise}
|
|
621
|
-
*/
|
|
622
|
-
requestQuery(query) {
|
|
623
|
-
const q = query || this.query(this.filterBy?.predicate(this));
|
|
624
|
-
return this._coordinator.requestQuery(this, q);
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
|
-
* Request that the coordinator perform a throttled update of this client
|
|
628
|
-
* using the default query. Unlike requestQuery, for which every call will
|
|
629
|
-
* result in an executed query, multiple calls to requestUpdate may be
|
|
630
|
-
* consolidated into a single update.
|
|
631
|
-
*/
|
|
632
|
-
requestUpdate() {
|
|
633
|
-
this._requestUpdate();
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Reset this client, initiating new field info and query requests.
|
|
637
|
-
* @returns {Promise}
|
|
638
|
-
*/
|
|
639
|
-
initialize() {
|
|
640
|
-
return this._coordinator.initializeClient(this);
|
|
641
|
-
}
|
|
642
|
-
/**
|
|
643
|
-
* Requests a client update.
|
|
644
|
-
* For example to (re-)render an interface component.
|
|
645
|
-
*
|
|
646
|
-
* @returns {this | Promise<any>}
|
|
647
|
-
*/
|
|
648
|
-
update() {
|
|
649
|
-
return this;
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
|
|
653
492
|
// ../../node_modules/@uwdata/flechette/src/constants.js
|
|
654
493
|
var MAGIC = Uint8Array.of(65, 82, 82, 79, 87, 49);
|
|
494
|
+
var EOS = Uint8Array.of(255, 255, 255, 255, 0, 0, 0, 0);
|
|
655
495
|
var Version = (
|
|
656
496
|
/** @type {const} */
|
|
657
497
|
{
|
|
@@ -3066,7 +2906,7 @@ function literalToSQL(value) {
|
|
|
3066
2906
|
case "number":
|
|
3067
2907
|
return Number.isFinite(value) ? `${value}` : "NULL";
|
|
3068
2908
|
case "string":
|
|
3069
|
-
return `'${value.
|
|
2909
|
+
return `'${value.replaceAll(`'`, `''`)}'`;
|
|
3070
2910
|
case "boolean":
|
|
3071
2911
|
return value ? "TRUE" : "FALSE";
|
|
3072
2912
|
default:
|
|
@@ -5140,6 +4980,8 @@ function sufficientStatistics(node, preagg, avg2) {
|
|
|
5140
4980
|
return sumExpr(preagg, node);
|
|
5141
4981
|
case "avg":
|
|
5142
4982
|
return avgExpr(preagg, node);
|
|
4983
|
+
case "geomean":
|
|
4984
|
+
return geomeanExpr(preagg, node);
|
|
5143
4985
|
case "arg_max":
|
|
5144
4986
|
return argmaxExpr(preagg, node);
|
|
5145
4987
|
case "arg_min":
|
|
@@ -5223,6 +5065,12 @@ function avgExpr(preagg, node) {
|
|
|
5223
5065
|
const { expr, name } = countExpr(preagg, node);
|
|
5224
5066
|
return div(sum(mul(as, name)), expr);
|
|
5225
5067
|
}
|
|
5068
|
+
function geomeanExpr(preagg, node) {
|
|
5069
|
+
const x3 = node.args[0];
|
|
5070
|
+
const expr = addStat(preagg, sum(ln(x3)), node);
|
|
5071
|
+
const { expr: n } = countExpr(preagg, node);
|
|
5072
|
+
return exp(div(sum(expr), n));
|
|
5073
|
+
}
|
|
5226
5074
|
function argmaxExpr(preagg, node) {
|
|
5227
5075
|
const expr = addStat(preagg, node);
|
|
5228
5076
|
const maxy = addStat(preagg, max(node.args[1]), node);
|
|
@@ -6295,13 +6143,13 @@ var Coordinator = class {
|
|
|
6295
6143
|
}
|
|
6296
6144
|
/**
|
|
6297
6145
|
* Issue a query for which no result (return value) is needed.
|
|
6298
|
-
* @param {
|
|
6146
|
+
* @param { import('./types.js').QueryType[] |
|
|
6147
|
+
* import('./types.js').QueryType} query The query or an array of queries.
|
|
6299
6148
|
* Each query should be either a Query builder object or a SQL string.
|
|
6300
6149
|
* @param {object} [options] An options object.
|
|
6301
6150
|
* @param {number} [options.priority] The query priority, defaults to
|
|
6302
6151
|
* `Priority.Normal`.
|
|
6303
|
-
* @returns {QueryResult} A query result
|
|
6304
|
-
* promise.
|
|
6152
|
+
* @returns {QueryResult} A query result promise.
|
|
6305
6153
|
*/
|
|
6306
6154
|
exec(query, { priority = Priority.Normal } = {}) {
|
|
6307
6155
|
query = Array.isArray(query) ? query.filter((x3) => x3).join(";\n") : query;
|
|
@@ -6310,8 +6158,8 @@ var Coordinator = class {
|
|
|
6310
6158
|
/**
|
|
6311
6159
|
* Issue a query to the backing database. The submitted query may be
|
|
6312
6160
|
* consolidate with other queries and its results may be cached.
|
|
6313
|
-
* @param {QueryType} query The query as either a Query
|
|
6314
|
-
* or a SQL string.
|
|
6161
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
6162
|
+
* builder object or a SQL string.
|
|
6315
6163
|
* @param {object} [options] An options object.
|
|
6316
6164
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
6317
6165
|
* @param {boolean} [options.cache=true] If true, cache the query result
|
|
@@ -6333,8 +6181,8 @@ var Coordinator = class {
|
|
|
6333
6181
|
/**
|
|
6334
6182
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
6335
6183
|
* for efficient future access.
|
|
6336
|
-
* @param {QueryType} query The query as either a Query
|
|
6337
|
-
* or a SQL string.
|
|
6184
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
6185
|
+
* builder object or a SQL string.
|
|
6338
6186
|
* @param {object} [options] An options object.
|
|
6339
6187
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
6340
6188
|
* @returns {QueryResult} A query result promise.
|
|
@@ -6369,13 +6217,13 @@ var Coordinator = class {
|
|
|
6369
6217
|
* Update client data by submitting the given query and returning the
|
|
6370
6218
|
* data (or error) to the client.
|
|
6371
6219
|
* @param {MosaicClient} client A Mosaic client.
|
|
6372
|
-
* @param {QueryType} query The data query.
|
|
6220
|
+
* @param {import('./types.js').QueryType} query The data query.
|
|
6373
6221
|
* @param {number} [priority] The query priority.
|
|
6374
6222
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
6375
6223
|
*/
|
|
6376
6224
|
updateClient(client, query, priority = Priority.Normal) {
|
|
6377
6225
|
client.queryPending();
|
|
6378
|
-
return this.query(query, { priority }).then(
|
|
6226
|
+
return client._pending = this.query(query, { priority }).then(
|
|
6379
6227
|
(data) => client.queryResult(data).update(),
|
|
6380
6228
|
(err) => {
|
|
6381
6229
|
this._logger.error(err);
|
|
@@ -6388,7 +6236,7 @@ var Coordinator = class {
|
|
|
6388
6236
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
6389
6237
|
* side effect, this method clears the current preaggregator state.
|
|
6390
6238
|
* @param {MosaicClient} client The client to update.
|
|
6391
|
-
* @param {QueryType | null} [query] The query to issue.
|
|
6239
|
+
* @param {import('./types.js').QueryType | null} [query] The query to issue.
|
|
6392
6240
|
*/
|
|
6393
6241
|
requestQuery(client, query) {
|
|
6394
6242
|
this.preaggregator.clear();
|
|
@@ -6405,7 +6253,7 @@ var Coordinator = class {
|
|
|
6405
6253
|
}
|
|
6406
6254
|
clients.add(client);
|
|
6407
6255
|
client.coordinator = this;
|
|
6408
|
-
this.initializeClient(client);
|
|
6256
|
+
client._pending = this.initializeClient(client);
|
|
6409
6257
|
connectSelection(this, client.filterBy, client);
|
|
6410
6258
|
}
|
|
6411
6259
|
async initializeClient(client) {
|
|
@@ -6413,6 +6261,7 @@ var Coordinator = class {
|
|
|
6413
6261
|
if (fields?.length) {
|
|
6414
6262
|
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
6415
6263
|
}
|
|
6264
|
+
await client.prepare();
|
|
6416
6265
|
return client.requestQuery();
|
|
6417
6266
|
}
|
|
6418
6267
|
/**
|
|
@@ -7032,6 +6881,179 @@ var SelectionResolver = class {
|
|
|
7032
6881
|
}
|
|
7033
6882
|
};
|
|
7034
6883
|
|
|
6884
|
+
// ../core/src/util/throttle.js
|
|
6885
|
+
var NIL = {};
|
|
6886
|
+
function throttle(callback, debounce = false) {
|
|
6887
|
+
let curr;
|
|
6888
|
+
let next;
|
|
6889
|
+
let pending = NIL;
|
|
6890
|
+
function invoke(event) {
|
|
6891
|
+
curr = callback(event).catch(() => {
|
|
6892
|
+
}).finally(() => {
|
|
6893
|
+
if (next) {
|
|
6894
|
+
const { value } = next;
|
|
6895
|
+
next = null;
|
|
6896
|
+
invoke(value);
|
|
6897
|
+
} else {
|
|
6898
|
+
curr = null;
|
|
6899
|
+
}
|
|
6900
|
+
});
|
|
6901
|
+
}
|
|
6902
|
+
function enqueue(event) {
|
|
6903
|
+
next = { event };
|
|
6904
|
+
}
|
|
6905
|
+
function process(event) {
|
|
6906
|
+
curr ? enqueue(event) : invoke(event);
|
|
6907
|
+
}
|
|
6908
|
+
function delay(event) {
|
|
6909
|
+
if (pending !== event) {
|
|
6910
|
+
requestAnimationFrame(() => {
|
|
6911
|
+
const e = pending;
|
|
6912
|
+
pending = NIL;
|
|
6913
|
+
process(e);
|
|
6914
|
+
});
|
|
6915
|
+
}
|
|
6916
|
+
pending = event;
|
|
6917
|
+
}
|
|
6918
|
+
return debounce ? delay : process;
|
|
6919
|
+
}
|
|
6920
|
+
|
|
6921
|
+
// ../core/src/MosaicClient.js
|
|
6922
|
+
var MosaicClient = class {
|
|
6923
|
+
/**
|
|
6924
|
+
* Constructor.
|
|
6925
|
+
* @param {*} filterSelection An optional selection to interactively filter
|
|
6926
|
+
* this client's data. If provided, a coordinator will re-query and update
|
|
6927
|
+
* the client when the selection updates.
|
|
6928
|
+
*/
|
|
6929
|
+
constructor(filterSelection) {
|
|
6930
|
+
this._filterBy = filterSelection;
|
|
6931
|
+
this._requestUpdate = throttle(() => this.requestQuery(), true);
|
|
6932
|
+
this._coordinator = null;
|
|
6933
|
+
this._pending = Promise.resolve();
|
|
6934
|
+
}
|
|
6935
|
+
/**
|
|
6936
|
+
* Return this client's connected coordinator.
|
|
6937
|
+
*/
|
|
6938
|
+
get coordinator() {
|
|
6939
|
+
return this._coordinator;
|
|
6940
|
+
}
|
|
6941
|
+
/**
|
|
6942
|
+
* Set this client's connected coordinator.
|
|
6943
|
+
*/
|
|
6944
|
+
set coordinator(coordinator2) {
|
|
6945
|
+
this._coordinator = coordinator2;
|
|
6946
|
+
}
|
|
6947
|
+
/**
|
|
6948
|
+
* Return a Promise that resolves once the client has updated.
|
|
6949
|
+
*/
|
|
6950
|
+
get pending() {
|
|
6951
|
+
return this._pending;
|
|
6952
|
+
}
|
|
6953
|
+
/**
|
|
6954
|
+
* Return this client's filter selection.
|
|
6955
|
+
*/
|
|
6956
|
+
get filterBy() {
|
|
6957
|
+
return this._filterBy;
|
|
6958
|
+
}
|
|
6959
|
+
/**
|
|
6960
|
+
* Return a boolean indicating if the client query can be sped up with
|
|
6961
|
+
* materialized views of pre-aggregated data. Should return true if changes to
|
|
6962
|
+
* the filterBy selection does not change the groupby domain of the client
|
|
6963
|
+
* query.
|
|
6964
|
+
*/
|
|
6965
|
+
get filterStable() {
|
|
6966
|
+
return true;
|
|
6967
|
+
}
|
|
6968
|
+
/**
|
|
6969
|
+
* Return an array of fields queried by this client.
|
|
6970
|
+
* @returns {import('./types.js').FieldInfoRequest[] | null}
|
|
6971
|
+
* The fields to retrieve info for.
|
|
6972
|
+
*/
|
|
6973
|
+
fields() {
|
|
6974
|
+
return null;
|
|
6975
|
+
}
|
|
6976
|
+
/**
|
|
6977
|
+
* Called by the coordinator to set the field info for this client.
|
|
6978
|
+
* @param {import('./types.js').FieldInfo[]} info The field info result.
|
|
6979
|
+
* @returns {this}
|
|
6980
|
+
*/
|
|
6981
|
+
fieldInfo(info) {
|
|
6982
|
+
return this;
|
|
6983
|
+
}
|
|
6984
|
+
/**
|
|
6985
|
+
* Prepare the client before the query() method is called.
|
|
6986
|
+
*/
|
|
6987
|
+
async prepare() {
|
|
6988
|
+
}
|
|
6989
|
+
/**
|
|
6990
|
+
* Return a query specifying the data needed by this client.
|
|
6991
|
+
* @param {*} [filter] The filtering criteria to apply in the query.
|
|
6992
|
+
* @returns {*} The client query
|
|
6993
|
+
*/
|
|
6994
|
+
query(filter3) {
|
|
6995
|
+
return null;
|
|
6996
|
+
}
|
|
6997
|
+
/**
|
|
6998
|
+
* Called by the coordinator to inform the client that a query is pending.
|
|
6999
|
+
* @returns {this}
|
|
7000
|
+
*/
|
|
7001
|
+
queryPending() {
|
|
7002
|
+
return this;
|
|
7003
|
+
}
|
|
7004
|
+
/**
|
|
7005
|
+
* Called by the coordinator to return a query result.
|
|
7006
|
+
* @param {*} data The query result.
|
|
7007
|
+
* @returns {this}
|
|
7008
|
+
*/
|
|
7009
|
+
queryResult(data) {
|
|
7010
|
+
return this;
|
|
7011
|
+
}
|
|
7012
|
+
/**
|
|
7013
|
+
* Called by the coordinator to report a query execution error.
|
|
7014
|
+
* @param {*} error
|
|
7015
|
+
* @returns {this}
|
|
7016
|
+
*/
|
|
7017
|
+
queryError(error) {
|
|
7018
|
+
return this;
|
|
7019
|
+
}
|
|
7020
|
+
/**
|
|
7021
|
+
* Request the coordinator to execute a query for this client.
|
|
7022
|
+
* If an explicit query is not provided, the client query method will
|
|
7023
|
+
* be called, filtered by the current filterBy selection.
|
|
7024
|
+
* @returns {Promise}
|
|
7025
|
+
*/
|
|
7026
|
+
requestQuery(query) {
|
|
7027
|
+
const q = query || this.query(this.filterBy?.predicate(this));
|
|
7028
|
+
return this._coordinator.requestQuery(this, q);
|
|
7029
|
+
}
|
|
7030
|
+
/**
|
|
7031
|
+
* Request that the coordinator perform a throttled update of this client
|
|
7032
|
+
* using the default query. Unlike requestQuery, for which every call will
|
|
7033
|
+
* result in an executed query, multiple calls to requestUpdate may be
|
|
7034
|
+
* consolidated into a single update.
|
|
7035
|
+
*/
|
|
7036
|
+
requestUpdate() {
|
|
7037
|
+
this._requestUpdate();
|
|
7038
|
+
}
|
|
7039
|
+
/**
|
|
7040
|
+
* Reset this client, initiating new field info, call the prepare method, and query requests.
|
|
7041
|
+
* @returns {Promise}
|
|
7042
|
+
*/
|
|
7043
|
+
initialize() {
|
|
7044
|
+
return this._coordinator.initializeClient(this);
|
|
7045
|
+
}
|
|
7046
|
+
/**
|
|
7047
|
+
* Requests a client update.
|
|
7048
|
+
* For example to (re-)render an interface component.
|
|
7049
|
+
*
|
|
7050
|
+
* @returns {this | Promise<any>}
|
|
7051
|
+
*/
|
|
7052
|
+
update() {
|
|
7053
|
+
return this;
|
|
7054
|
+
}
|
|
7055
|
+
};
|
|
7056
|
+
|
|
7035
7057
|
// ../core/src/SelectionClause.js
|
|
7036
7058
|
function clausePoint(field3, value, {
|
|
7037
7059
|
source,
|
|
@@ -30999,6 +31021,9 @@ var DEFAULT_ATTRIBUTES = {
|
|
|
30999
31021
|
marginBottom: 30
|
|
31000
31022
|
};
|
|
31001
31023
|
var Plot = class {
|
|
31024
|
+
/**
|
|
31025
|
+
* @param {HTMLElement} [element]
|
|
31026
|
+
*/
|
|
31002
31027
|
constructor(element) {
|
|
31003
31028
|
this.attributes = { ...DEFAULT_ATTRIBUTES };
|
|
31004
31029
|
this.listeners = null;
|
|
@@ -31006,12 +31031,12 @@ var Plot = class {
|
|
|
31006
31031
|
this.legends = [];
|
|
31007
31032
|
this.marks = [];
|
|
31008
31033
|
this.markset = null;
|
|
31034
|
+
this.params = /* @__PURE__ */ new Map();
|
|
31035
|
+
this.synch = synchronizer();
|
|
31009
31036
|
this.element = element || document.createElement("div");
|
|
31010
31037
|
this.element.setAttribute("class", "plot");
|
|
31011
31038
|
this.element.style.display = "flex";
|
|
31012
|
-
this.element
|
|
31013
|
-
this.params = /* @__PURE__ */ new Map();
|
|
31014
|
-
this.synch = synchronizer();
|
|
31039
|
+
Object.assign(this.element, { value: this });
|
|
31015
31040
|
}
|
|
31016
31041
|
margins() {
|
|
31017
31042
|
return {
|
|
@@ -31386,7 +31411,7 @@ function markQuery(channels, table, skip = []) {
|
|
|
31386
31411
|
const { channel, field: field3, as } = c4;
|
|
31387
31412
|
if (skip.includes(channel)) continue;
|
|
31388
31413
|
if (channel === "orderby") {
|
|
31389
|
-
q.orderby(c4.value);
|
|
31414
|
+
q.orderby(c4.value ?? field3);
|
|
31390
31415
|
} else if (field3) {
|
|
31391
31416
|
if (isAggregateExpression(field3)) {
|
|
31392
31417
|
aggr = true;
|
|
@@ -31518,7 +31543,7 @@ var ConnectedMark = class extends Mark2 {
|
|
|
31518
31543
|
const cols = q._select.map((c4) => c4.alias).filter((c4) => c4 !== as && c4 !== value);
|
|
31519
31544
|
return m4(q, expr, as, value, cols);
|
|
31520
31545
|
} else {
|
|
31521
|
-
return q.orderby(
|
|
31546
|
+
return q.orderby(as);
|
|
31522
31547
|
}
|
|
31523
31548
|
}
|
|
31524
31549
|
};
|
|
@@ -33678,12 +33703,13 @@ var Nearest = class {
|
|
|
33678
33703
|
selection2.update(that.clause(void 0));
|
|
33679
33704
|
});
|
|
33680
33705
|
svg.addEventListener("pointerenter", (evt) => {
|
|
33681
|
-
if (!evt.buttons)
|
|
33682
|
-
const v2 = this.channels.map(() => 0);
|
|
33683
|
-
selection2.activate(this.clause(v2));
|
|
33684
|
-
}
|
|
33706
|
+
if (!evt.buttons) this.activate();
|
|
33685
33707
|
});
|
|
33686
33708
|
}
|
|
33709
|
+
activate() {
|
|
33710
|
+
const v2 = this.channels.map(() => 0);
|
|
33711
|
+
this.selection.activate(this.clause(v2));
|
|
33712
|
+
}
|
|
33687
33713
|
};
|
|
33688
33714
|
function calculateXY(svg, mark) {
|
|
33689
33715
|
const { data: { columns } } = mark;
|
|
@@ -33779,7 +33805,7 @@ var PanZoom = class {
|
|
|
33779
33805
|
this.svg = svg;
|
|
33780
33806
|
if (this.initialized) return;
|
|
33781
33807
|
else this.initialized = true;
|
|
33782
|
-
const { panx, pany, mark: { plot: { element } }
|
|
33808
|
+
const { panx, pany, mark: { plot: { element } } } = this;
|
|
33783
33809
|
this.xscale = svg.scale("x");
|
|
33784
33810
|
this.yscale = svg.scale("y");
|
|
33785
33811
|
const rx = this.xscale.range.slice().sort(asc2);
|
|
@@ -33796,19 +33822,21 @@ var PanZoom = class {
|
|
|
33796
33822
|
element.addEventListener("pointerenter", (evt) => {
|
|
33797
33823
|
if (enter) return;
|
|
33798
33824
|
else enter = true;
|
|
33799
|
-
if (evt.buttons)
|
|
33800
|
-
if (panx) {
|
|
33801
|
-
const { xscale, xfield } = this;
|
|
33802
|
-
xsel.activate(this.clause(xscale.domain, xfield, xscale));
|
|
33803
|
-
}
|
|
33804
|
-
if (pany) {
|
|
33805
|
-
const { yscale, yfield } = this;
|
|
33806
|
-
ysel.activate(this.clause(yscale.domain, yfield, yscale));
|
|
33807
|
-
}
|
|
33825
|
+
if (!evt.buttons) this.activate();
|
|
33808
33826
|
});
|
|
33809
33827
|
element.addEventListener("pointerleave", () => enter = false);
|
|
33810
33828
|
}
|
|
33811
33829
|
}
|
|
33830
|
+
activate() {
|
|
33831
|
+
if (this.panx) {
|
|
33832
|
+
const { xscale, xfield } = this;
|
|
33833
|
+
this.xsel.activate(this.clause(xscale.domain, xfield, xscale));
|
|
33834
|
+
}
|
|
33835
|
+
if (this.pany) {
|
|
33836
|
+
const { yscale, yfield } = this;
|
|
33837
|
+
this.ysel.activate(this.clause(yscale.domain, yfield, yscale));
|
|
33838
|
+
}
|
|
33839
|
+
}
|
|
33812
33840
|
};
|
|
33813
33841
|
function extent3(ext, defaultTrue, defaultFalse) {
|
|
33814
33842
|
return ext ? Array.isArray(ext) ? ext : defaultTrue : defaultFalse;
|
|
@@ -34193,8 +34221,8 @@ var Toggle = class {
|
|
|
34193
34221
|
channels,
|
|
34194
34222
|
peers = true
|
|
34195
34223
|
}) {
|
|
34196
|
-
this.value = null;
|
|
34197
34224
|
this.mark = mark;
|
|
34225
|
+
this.value = null;
|
|
34198
34226
|
this.selection = selection2;
|
|
34199
34227
|
this.peers = peers;
|
|
34200
34228
|
const fields = this.fields = [];
|
|
@@ -34246,10 +34274,12 @@ var Toggle = class {
|
|
|
34246
34274
|
}
|
|
34247
34275
|
});
|
|
34248
34276
|
svg.addEventListener("pointerenter", (evt) => {
|
|
34249
|
-
if (evt.buttons)
|
|
34250
|
-
this.selection.activate(this.clause([this.fields.map(() => 0)]));
|
|
34277
|
+
if (!evt.buttons) this.activate();
|
|
34251
34278
|
});
|
|
34252
34279
|
}
|
|
34280
|
+
activate() {
|
|
34281
|
+
this.selection.activate(this.clause([this.fields.map(() => 0)]));
|
|
34282
|
+
}
|
|
34253
34283
|
};
|
|
34254
34284
|
function isTargetElement(groups2, node) {
|
|
34255
34285
|
return groups2.some((g) => g.contains(node));
|