@vitessce/gl 4.0.4 → 4.0.6
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/{deflate-M1pBMBic.js → deflate-DNngSh3q.js} +1 -1
- package/dist/{index-D4_i_p4Y.js → index-_UASQg2S.js} +31 -11
- package/dist/index.js +2 -2
- package/dist/{jpeg-B0R_2GXY.js → jpeg-BrGNk507.js} +1 -1
- package/dist/{lerc-B3-C5ALH.js → lerc-A9bnCzoN.js} +1 -1
- package/dist/{lzw-CIZFFT4X.js → lzw-_IYIPfiq.js} +1 -1
- package/dist/{packbits-C8FGPd9t.js → packbits-CxQQOChS.js} +1 -1
- package/dist/{raw-Bj2SZ3rC.js → raw-ti2YIR09.js} +1 -1
- package/dist/{webimage-DficvJzn.js → webimage-DgRcFzf_.js} +1 -1
- package/dist-tsc/SelectionLayer.d.ts +1 -0
- package/dist-tsc/SelectionLayer.d.ts.map +1 -1
- package/dist-tsc/SelectionLayer.js +5 -2
- package/dist-tsc/SelectionLayer.js.map +1 -1
- package/dist-tsc/selection-busy.d.ts +13 -0
- package/dist-tsc/selection-busy.d.ts.map +1 -0
- package/dist-tsc/selection-busy.js +30 -0
- package/dist-tsc/selection-busy.js.map +1 -0
- package/dist-tsc/selection-busy.test.d.ts +2 -0
- package/dist-tsc/selection-busy.test.d.ts.map +1 -0
- package/dist-tsc/selection-busy.test.js +40 -0
- package/dist-tsc/selection-busy.test.js.map +1 -0
- package/dist-tsc/selection-utils.d.ts +5 -1
- package/dist-tsc/selection-utils.d.ts.map +1 -1
- package/dist-tsc/selection-utils.js +6 -1
- package/dist-tsc/selection-utils.js.map +1 -1
- package/package.json +3 -3
- package/src/SelectionLayer.js +7 -2
- package/src/selection-busy.js +28 -0
- package/src/selection-busy.test.js +45 -0
- package/src/selection-utils.js +6 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as inflate_1 } from "./pako.esm-SxljTded.js";
|
|
2
|
-
import { B as BaseDecoder } from "./index-
|
|
2
|
+
import { B as BaseDecoder } from "./index-_UASQg2S.js";
|
|
3
3
|
class DeflateDecoder extends BaseDecoder {
|
|
4
4
|
decodeBlock(buffer) {
|
|
5
5
|
return inflate_1(new Uint8Array(buffer)).buffer;
|
|
@@ -103511,6 +103511,20 @@ function requireDistEs6() {
|
|
|
103511
103511
|
var distEs6Exports$2 = requireDistEs6();
|
|
103512
103512
|
var distEs6Exports$1 = requireDistEs6$1();
|
|
103513
103513
|
var distEs6Exports = requireDistEs6$2();
|
|
103514
|
+
function runSelectionWithBusySignal(onBusy, work) {
|
|
103515
|
+
if (typeof onBusy !== "function" || typeof requestAnimationFrame !== "function") {
|
|
103516
|
+
work();
|
|
103517
|
+
return;
|
|
103518
|
+
}
|
|
103519
|
+
onBusy(true);
|
|
103520
|
+
requestAnimationFrame(() => setTimeout(() => {
|
|
103521
|
+
try {
|
|
103522
|
+
work();
|
|
103523
|
+
} finally {
|
|
103524
|
+
onBusy(false);
|
|
103525
|
+
}
|
|
103526
|
+
}, 0));
|
|
103527
|
+
}
|
|
103514
103528
|
const EDIT_TYPE_ADD = "addFeature";
|
|
103515
103529
|
const EDIT_TYPE_CLEAR = "clearFeatures";
|
|
103516
103530
|
class ClickableDrawPolygonByDraggingMode extends distEs6Exports.DrawPolygonByDraggingMode {
|
|
@@ -103525,7 +103539,8 @@ const MODE_MAP = {
|
|
|
103525
103539
|
const defaultProps$f = {
|
|
103526
103540
|
layerIds: [],
|
|
103527
103541
|
onSelect: () => {
|
|
103528
|
-
}
|
|
103542
|
+
},
|
|
103543
|
+
onSelectionBusy: null
|
|
103529
103544
|
};
|
|
103530
103545
|
const EMPTY_DATA = {
|
|
103531
103546
|
type: "FeatureCollection",
|
|
@@ -103625,11 +103640,15 @@ class SelectionLayer extends CompositeLayer {
|
|
|
103625
103640
|
selectedFeatureIndexes: [],
|
|
103626
103641
|
data: EMPTY_DATA,
|
|
103627
103642
|
onEdit: ({ updatedData, editType }) => {
|
|
103643
|
+
const { onSelectionBusy } = this.props;
|
|
103628
103644
|
if (editType === EDIT_TYPE_ADD) {
|
|
103629
103645
|
const { coordinates: coordinates2 } = updatedData.features[0].geometry;
|
|
103630
|
-
|
|
103646
|
+
runSelectionWithBusySignal(
|
|
103647
|
+
onSelectionBusy,
|
|
103648
|
+
() => this._selectPolygonObjects(coordinates2)
|
|
103649
|
+
);
|
|
103631
103650
|
} else if (editType === EDIT_TYPE_CLEAR) {
|
|
103632
|
-
this._selectEmpty();
|
|
103651
|
+
runSelectionWithBusySignal(onSelectionBusy, () => this._selectEmpty());
|
|
103633
103652
|
}
|
|
103634
103653
|
},
|
|
103635
103654
|
_subLayerProps: {
|
|
@@ -103664,7 +103683,7 @@ function getBaseLayerId(layerId) {
|
|
|
103664
103683
|
}
|
|
103665
103684
|
const onSelectNoop = ({ pickingInfos }) => {
|
|
103666
103685
|
};
|
|
103667
|
-
function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false) {
|
|
103686
|
+
function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false, onSelectionBusy = null) {
|
|
103668
103687
|
if (!tool) {
|
|
103669
103688
|
return [];
|
|
103670
103689
|
}
|
|
@@ -103674,6 +103693,7 @@ function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false) {
|
|
|
103674
103693
|
id: "selection",
|
|
103675
103694
|
flipY,
|
|
103676
103695
|
obsLayers,
|
|
103696
|
+
onSelectionBusy,
|
|
103677
103697
|
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
103678
103698
|
selectionType: tool,
|
|
103679
103699
|
// This onSelect is no longer used since
|
|
@@ -105568,22 +105588,22 @@ async function getDecoder(fileDirectory) {
|
|
|
105568
105588
|
const Decoder = await importFn();
|
|
105569
105589
|
return new Decoder(fileDirectory);
|
|
105570
105590
|
}
|
|
105571
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
105572
|
-
addDecoder(5, () => import("./lzw-
|
|
105591
|
+
addDecoder([void 0, 1], () => import("./raw-ti2YIR09.js").then((m) => m.default));
|
|
105592
|
+
addDecoder(5, () => import("./lzw-_IYIPfiq.js").then((m) => m.default));
|
|
105573
105593
|
addDecoder(6, () => {
|
|
105574
105594
|
throw new Error("old style JPEG compression is not supported.");
|
|
105575
105595
|
});
|
|
105576
|
-
addDecoder(7, () => import("./jpeg-
|
|
105577
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
105578
|
-
addDecoder(32773, () => import("./packbits-
|
|
105596
|
+
addDecoder(7, () => import("./jpeg-BrGNk507.js").then((m) => m.default));
|
|
105597
|
+
addDecoder([8, 32946], () => import("./deflate-DNngSh3q.js").then((m) => m.default));
|
|
105598
|
+
addDecoder(32773, () => import("./packbits-CxQQOChS.js").then((m) => m.default));
|
|
105579
105599
|
addDecoder(
|
|
105580
105600
|
34887,
|
|
105581
|
-
() => import("./lerc-
|
|
105601
|
+
() => import("./lerc-A9bnCzoN.js").then(async (m) => {
|
|
105582
105602
|
await m.zstd.init();
|
|
105583
105603
|
return m;
|
|
105584
105604
|
}).then((m) => m.default)
|
|
105585
105605
|
);
|
|
105586
|
-
addDecoder(50001, () => import("./webimage-
|
|
105606
|
+
addDecoder(50001, () => import("./webimage-DgRcFzf_.js").then((m) => m.default));
|
|
105587
105607
|
function copyNewSize(array, width, height, samplesPerPixel = 1) {
|
|
105588
105608
|
return new (Object.getPrototypeOf(array)).constructor(width * height * samplesPerPixel);
|
|
105589
105609
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { f as distEs6Exports } from "./index-
|
|
2
|
-
import { q, p, A, t, s, r, j, k, m, C, n, D, G, e, H, c, M, l, o, d, P, S, i, T, h, w, b, u, x, v } from "./index-
|
|
1
|
+
import { f as distEs6Exports } from "./index-_UASQg2S.js";
|
|
2
|
+
import { q, p, A, t, s, r, j, k, m, C, n, D, G, e, H, c, M, l, o, d, P, S, i, T, h, w, b, u, x, v } from "./index-_UASQg2S.js";
|
|
3
3
|
const SELECTION_TYPE = distEs6Exports.SELECTION_TYPE;
|
|
4
4
|
export {
|
|
5
5
|
q as AXIS_FONT_FAMILY,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as inflate_1 } from "./pako.esm-SxljTded.js";
|
|
2
|
-
import { g as getDefaultExportFromCjs, B as BaseDecoder, L as LercParameters, a as LercAddCompression } from "./index-
|
|
2
|
+
import { g as getDefaultExportFromCjs, B as BaseDecoder, L as LercParameters, a as LercAddCompression } from "./index-_UASQg2S.js";
|
|
3
3
|
var LercDecode = { exports: {} };
|
|
4
4
|
var hasRequiredLercDecode;
|
|
5
5
|
function requireLercDecode() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionLayer.d.ts","sourceRoot":"","sources":["../src/SelectionLayer.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SelectionLayer.d.ts","sourceRoot":"","sources":["../src/SelectionLayer.js"],"names":[],"mappings":"AAuEA;IACE,8CAsEC;IAED,qBAMC;IAED,uCAsDC;CACF;;;;;;qCAnMoC,mBAAmB;;;IAoB5C,0BAAQ"}
|
|
@@ -12,6 +12,7 @@ import { ScatterplotLayer } from '@deck.gl/layers';
|
|
|
12
12
|
import { SELECTION_TYPE } from 'nebula.gl';
|
|
13
13
|
import { EditableGeoJsonLayer } from '@nebula.gl/layers';
|
|
14
14
|
import { DrawPolygonByDraggingMode, ViewMode } from '@nebula.gl/edit-modes';
|
|
15
|
+
import { runSelectionWithBusySignal } from './selection-busy.js';
|
|
15
16
|
const EDIT_TYPE_ADD = 'addFeature';
|
|
16
17
|
const EDIT_TYPE_CLEAR = 'clearFeatures';
|
|
17
18
|
class ClickableDrawPolygonByDraggingMode extends DrawPolygonByDraggingMode {
|
|
@@ -26,6 +27,7 @@ const MODE_MAP = {
|
|
|
26
27
|
const defaultProps = {
|
|
27
28
|
layerIds: [],
|
|
28
29
|
onSelect: () => { },
|
|
30
|
+
onSelectionBusy: null,
|
|
29
31
|
};
|
|
30
32
|
const EMPTY_DATA = {
|
|
31
33
|
type: 'FeatureCollection',
|
|
@@ -138,13 +140,14 @@ export default class SelectionLayer extends CompositeLayer {
|
|
|
138
140
|
selectedFeatureIndexes: [],
|
|
139
141
|
data: EMPTY_DATA,
|
|
140
142
|
onEdit: ({ updatedData, editType }) => {
|
|
143
|
+
const { onSelectionBusy } = this.props;
|
|
141
144
|
if (editType === EDIT_TYPE_ADD) {
|
|
142
145
|
const { coordinates } = updatedData.features[0].geometry;
|
|
143
|
-
this._selectPolygonObjects(coordinates);
|
|
146
|
+
runSelectionWithBusySignal(onSelectionBusy, () => this._selectPolygonObjects(coordinates));
|
|
144
147
|
}
|
|
145
148
|
else if (editType === EDIT_TYPE_CLEAR) {
|
|
146
149
|
// We want to select an empty array to clear any previous selection.
|
|
147
|
-
this._selectEmpty();
|
|
150
|
+
runSelectionWithBusySignal(onSelectionBusy, () => this._selectEmpty());
|
|
148
151
|
}
|
|
149
152
|
},
|
|
150
153
|
_subLayerProps: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionLayer.js","sourceRoot":"","sources":["../src/SelectionLayer.js"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,yCAAyC;AACzC,+CAA+C;AAC/C,+HAA+H;AAC/H,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"SelectionLayer.js","sourceRoot":"","sources":["../src/SelectionLayer.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run selection work that will block the main thread (a quadtree hit test over
|
|
3
|
+
* millions of observations plus the selection-driven re-render), signaling a
|
|
4
|
+
* busy indicator first and letting the browser paint it before the block
|
|
5
|
+
* starts. The false signal is emitted in the same task as the work, so React
|
|
6
|
+
* batches it with the state updates the work makes: the indicator disappears
|
|
7
|
+
* in the same commit that shows the applied selection.
|
|
8
|
+
* @param {null|((isBusy: boolean) => void)} onBusy The busy signal, or
|
|
9
|
+
* null/undefined to run the work inline.
|
|
10
|
+
* @param {() => void} work The blocking work.
|
|
11
|
+
*/
|
|
12
|
+
export function runSelectionWithBusySignal(onBusy: null | ((isBusy: boolean) => void), work: () => void): void;
|
|
13
|
+
//# sourceMappingURL=selection-busy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-busy.d.ts","sourceRoot":"","sources":["../src/selection-busy.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,mDAJW,IAAI,GAAC,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,QAEhC,MAAM,IAAI,QAkBpB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run selection work that will block the main thread (a quadtree hit test over
|
|
3
|
+
* millions of observations plus the selection-driven re-render), signaling a
|
|
4
|
+
* busy indicator first and letting the browser paint it before the block
|
|
5
|
+
* starts. The false signal is emitted in the same task as the work, so React
|
|
6
|
+
* batches it with the state updates the work makes: the indicator disappears
|
|
7
|
+
* in the same commit that shows the applied selection.
|
|
8
|
+
* @param {null|((isBusy: boolean) => void)} onBusy The busy signal, or
|
|
9
|
+
* null/undefined to run the work inline.
|
|
10
|
+
* @param {() => void} work The blocking work.
|
|
11
|
+
*/
|
|
12
|
+
export function runSelectionWithBusySignal(onBusy, work) {
|
|
13
|
+
if (typeof onBusy !== 'function' || typeof requestAnimationFrame !== 'function') {
|
|
14
|
+
work();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
onBusy(true);
|
|
18
|
+
// requestAnimationFrame fires just before the next paint, so a timeout
|
|
19
|
+
// scheduled inside it runs just after: the indicator is on screen before
|
|
20
|
+
// the main thread blocks.
|
|
21
|
+
requestAnimationFrame(() => setTimeout(() => {
|
|
22
|
+
try {
|
|
23
|
+
work();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
onBusy(false);
|
|
27
|
+
}
|
|
28
|
+
}, 0));
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=selection-busy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-busy.js","sourceRoot":"","sources":["../src/selection-busy.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAM,EAAE,IAAI;IACrD,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,OAAO,qBAAqB,KAAK,UAAU,EAAE,CAAC;QAChF,IAAI,EAAE,CAAC;QACP,OAAO;IACT,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC;IACb,uEAAuE;IACvE,yEAAyE;IACzE,0BAA0B;IAC1B,qBAAqB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE;QAC1C,IAAI,CAAC;YACH,IAAI,EAAE,CAAC;QACT,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-busy.test.d.ts","sourceRoot":"","sources":["../src/selection-busy.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach, } from 'vitest';
|
|
2
|
+
import { runSelectionWithBusySignal } from './selection-busy.js';
|
|
3
|
+
describe('runSelectionWithBusySignal', () => {
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
vi.unstubAllGlobals();
|
|
6
|
+
vi.useRealTimers();
|
|
7
|
+
});
|
|
8
|
+
it('runs the work inline without a busy signal', () => {
|
|
9
|
+
const work = vi.fn();
|
|
10
|
+
runSelectionWithBusySignal(null, work);
|
|
11
|
+
expect(work).toHaveBeenCalledTimes(1);
|
|
12
|
+
});
|
|
13
|
+
it('signals busy, lets a frame paint, then runs the work and clears', () => {
|
|
14
|
+
vi.useFakeTimers();
|
|
15
|
+
const rafCallbacks = [];
|
|
16
|
+
vi.stubGlobal('requestAnimationFrame', cb => rafCallbacks.push(cb));
|
|
17
|
+
const calls = [];
|
|
18
|
+
const onBusy = isBusy => calls.push(['busy', isBusy]);
|
|
19
|
+
const work = () => calls.push(['work']);
|
|
20
|
+
runSelectionWithBusySignal(onBusy, work);
|
|
21
|
+
// The work is deferred until after the frame that paints the indicator.
|
|
22
|
+
expect(calls).toEqual([['busy', true]]);
|
|
23
|
+
rafCallbacks.forEach(cb => cb());
|
|
24
|
+
expect(calls).toEqual([['busy', true]]);
|
|
25
|
+
vi.runAllTimers();
|
|
26
|
+
expect(calls).toEqual([['busy', true], ['work'], ['busy', false]]);
|
|
27
|
+
});
|
|
28
|
+
it('clears the busy signal when the work throws', () => {
|
|
29
|
+
vi.useFakeTimers();
|
|
30
|
+
vi.stubGlobal('requestAnimationFrame', cb => cb());
|
|
31
|
+
const onBusy = vi.fn();
|
|
32
|
+
expect(() => {
|
|
33
|
+
runSelectionWithBusySignal(onBusy, () => { throw new Error('boom'); });
|
|
34
|
+
vi.runAllTimers();
|
|
35
|
+
}).toThrow('boom');
|
|
36
|
+
expect(onBusy).toHaveBeenNthCalledWith(1, true);
|
|
37
|
+
expect(onBusy).toHaveBeenNthCalledWith(2, false);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=selection-busy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-busy.test.js","sourceRoot":"","sources":["../src/selection-busy.test.js"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GACpC,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACrB,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,YAAY,GAAG,EAAE,CAAC;QACxB,EAAE,CAAC,UAAU,CAAC,uBAAuB,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACxC,0BAA0B,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,wEAAwE;QACxE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACxC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACxC,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,EAAE,CAAC,UAAU,CAAC,uBAAuB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,EAAE;YACV,0BAA0B,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,EAAE,CAAC,YAAY,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnB,MAAM,CAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
* @param {string} cellBaseLayerId
|
|
6
6
|
* @param {object[]} obsLayers Objects with properties
|
|
7
7
|
* getObsCoords, obsIndex, obsQuadTree, onSelect.
|
|
8
|
+
* @param {boolean} flipY
|
|
9
|
+
* @param {null|((isBusy: boolean) => void)} onSelectionBusy Called with true
|
|
10
|
+
* just before a drawn selection's blocking hit test and application begin,
|
|
11
|
+
* and with false once they finish, so views can show a busy indicator.
|
|
8
12
|
* @returns {object[]} The array of DeckGL selection layers.
|
|
9
13
|
*/
|
|
10
|
-
export function getSelectionLayer(tool: string, zoom: number, layerId: any, obsLayers: object[], flipY?: boolean): object[];
|
|
14
|
+
export function getSelectionLayer(tool: string, zoom: number, layerId: any, obsLayers: object[], flipY?: boolean, onSelectionBusy?: null | ((isBusy: boolean) => void)): object[];
|
|
11
15
|
/**
|
|
12
16
|
* Get deck.gl layer props for selection overlays.
|
|
13
17
|
* @param {object} props
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-utils.d.ts","sourceRoot":"","sources":["../src/selection-utils.js"],"names":[],"mappings":"AAyBA
|
|
1
|
+
{"version":3,"file":"selection-utils.d.ts","sourceRoot":"","sources":["../src/selection-utils.js"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;GAYG;AACH,wCAXW,MAAM,QACN,MAAM,2BAEN,MAAM,EAAE,UAER,OAAO,oBACP,IAAI,GAAC,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,GAG9B,MAAM,EAAE,CAuCpB;AAED;;;;;;GAMG;AACH,wCALW,MAAM,GACJ,MAAM,CA8BlB"}
|
|
@@ -26,9 +26,13 @@ const onSelectNoop = ({ pickingInfos }) => { };
|
|
|
26
26
|
* @param {string} cellBaseLayerId
|
|
27
27
|
* @param {object[]} obsLayers Objects with properties
|
|
28
28
|
* getObsCoords, obsIndex, obsQuadTree, onSelect.
|
|
29
|
+
* @param {boolean} flipY
|
|
30
|
+
* @param {null|((isBusy: boolean) => void)} onSelectionBusy Called with true
|
|
31
|
+
* just before a drawn selection's blocking hit test and application begin,
|
|
32
|
+
* and with false once they finish, so views can show a busy indicator.
|
|
29
33
|
* @returns {object[]} The array of DeckGL selection layers.
|
|
30
34
|
*/
|
|
31
|
-
export function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false) {
|
|
35
|
+
export function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false, onSelectionBusy = null) {
|
|
32
36
|
if (!tool) {
|
|
33
37
|
return [];
|
|
34
38
|
}
|
|
@@ -38,6 +42,7 @@ export function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false)
|
|
|
38
42
|
id: 'selection',
|
|
39
43
|
flipY,
|
|
40
44
|
obsLayers,
|
|
45
|
+
onSelectionBusy,
|
|
41
46
|
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
42
47
|
selectionType: tool,
|
|
43
48
|
// This onSelect is no longer used since
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-utils.js","sourceRoot":"","sources":["../src/selection-utils.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC,CAAC,wDAAwD;AAC3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC,CAAC,wDAAwD;AACnH,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAO;IAC7B,OAAO,QAAQ,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,OAAO;IACjC,OAAO,YAAY,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,0CAA0C;AAC1C,MAAM,YAAY,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,GAAE,CAAC,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"selection-utils.js","sourceRoot":"","sources":["../src/selection-utils.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC,CAAC,wDAAwD;AAC3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC,CAAC,wDAAwD;AACnH,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAO;IAC7B,OAAO,QAAQ,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,OAAO;IACjC,OAAO,YAAY,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,0CAA0C;AAC1C,MAAM,YAAY,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,GAAE,CAAC,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,GAAG,KAAK,EACb,eAAe,GAAG,IAAI;IAEtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,qBAAqB,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAE9C,OAAO,IAAI,cAAc,CAAC;QACxB,EAAE,EAAE,WAAW;QACf,KAAK;QACL,SAAS;QACT,eAAe;QACf,gBAAgB,EAAE,iBAAiB,CAAC,SAAS;QAC7C,aAAa,EAAE,IAAI;QACnB,wCAAwC;QACxC,8CAA8C;QAC9C,QAAQ,EAAE,YAAY;QACtB,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QAChD,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;QACjD,yBAAyB,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvC,kBAAkB,EAAE,CAAC;QACrB,kBAAkB,EAAE,CAAC;QACrB,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACvD,wBAAwB,EAAE,GAAG,EAAE,CAAC,qBAAqB;QACrD,0BAA0B,EAAE,CAAC;QAC7B,8BAA8B,EAAE,qBAAqB;QACrD,8BAA8B,EAAE,CAAC,GAAG,qBAAqB;KAC1D,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAK;IACpC,MAAM,EACJ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,EACxC,GAAG,KAAK,CAAC;IACV,OAAO;QACL,OAAO,EAAE;YACP,EAAE,EAAE,kBAAkB,CAAC,EAAE,CAAC;YAC1B,YAAY,EAAE,QAAQ;YACtB,YAAY,EAAE,QAAQ;YACtB,IAAI;YACJ,cAAc,EAAE,UAAU;YAC1B,UAAU,EAAE,CAAC,IAAI,mBAAmB,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;YACxD,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACnB,GAAG,IAAI;SACR;QACD,IAAI,EAAE;YACJ,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC;YACtB,YAAY,EAAE,QAAQ;YACtB,YAAY,EAAE,QAAQ;YACtB,gDAAgD;YAChD,0BAA0B;YAC1B,iCAAiC;YACjC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE;YAClB,GAAG,IAAI;SACR;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/gl",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.6",
|
|
4
4
|
"author": "HIDIVE Lab at HMS",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"math.gl": "^3.5.6",
|
|
57
57
|
"mathjs": "^9.2.0",
|
|
58
58
|
"nebula.gl": "0.23.8",
|
|
59
|
-
"@vitessce/utils": "4.0.
|
|
60
|
-
"@vitessce/globals": "4.0.
|
|
59
|
+
"@vitessce/utils": "4.0.6",
|
|
60
|
+
"@vitessce/globals": "4.0.6"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"glsl-colormap": "^1.0.1",
|
package/src/SelectionLayer.js
CHANGED
|
@@ -12,6 +12,7 @@ import { ScatterplotLayer } from '@deck.gl/layers';
|
|
|
12
12
|
import { SELECTION_TYPE } from 'nebula.gl';
|
|
13
13
|
import { EditableGeoJsonLayer } from '@nebula.gl/layers';
|
|
14
14
|
import { DrawPolygonByDraggingMode, ViewMode } from '@nebula.gl/edit-modes';
|
|
15
|
+
import { runSelectionWithBusySignal } from './selection-busy.js';
|
|
15
16
|
|
|
16
17
|
const EDIT_TYPE_ADD = 'addFeature';
|
|
17
18
|
const EDIT_TYPE_CLEAR = 'clearFeatures';
|
|
@@ -30,6 +31,7 @@ const MODE_MAP = {
|
|
|
30
31
|
const defaultProps = {
|
|
31
32
|
layerIds: [],
|
|
32
33
|
onSelect: () => {},
|
|
34
|
+
onSelectionBusy: null,
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
const EMPTY_DATA = {
|
|
@@ -167,12 +169,15 @@ export default class SelectionLayer extends CompositeLayer {
|
|
|
167
169
|
selectedFeatureIndexes: [],
|
|
168
170
|
data: EMPTY_DATA,
|
|
169
171
|
onEdit: ({ updatedData, editType }) => {
|
|
172
|
+
const { onSelectionBusy } = this.props;
|
|
170
173
|
if (editType === EDIT_TYPE_ADD) {
|
|
171
174
|
const { coordinates } = updatedData.features[0].geometry;
|
|
172
|
-
|
|
175
|
+
runSelectionWithBusySignal(
|
|
176
|
+
onSelectionBusy, () => this._selectPolygonObjects(coordinates),
|
|
177
|
+
);
|
|
173
178
|
} else if (editType === EDIT_TYPE_CLEAR) {
|
|
174
179
|
// We want to select an empty array to clear any previous selection.
|
|
175
|
-
this._selectEmpty();
|
|
180
|
+
runSelectionWithBusySignal(onSelectionBusy, () => this._selectEmpty());
|
|
176
181
|
}
|
|
177
182
|
},
|
|
178
183
|
_subLayerProps: {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run selection work that will block the main thread (a quadtree hit test over
|
|
3
|
+
* millions of observations plus the selection-driven re-render), signaling a
|
|
4
|
+
* busy indicator first and letting the browser paint it before the block
|
|
5
|
+
* starts. The false signal is emitted in the same task as the work, so React
|
|
6
|
+
* batches it with the state updates the work makes: the indicator disappears
|
|
7
|
+
* in the same commit that shows the applied selection.
|
|
8
|
+
* @param {null|((isBusy: boolean) => void)} onBusy The busy signal, or
|
|
9
|
+
* null/undefined to run the work inline.
|
|
10
|
+
* @param {() => void} work The blocking work.
|
|
11
|
+
*/
|
|
12
|
+
export function runSelectionWithBusySignal(onBusy, work) {
|
|
13
|
+
if (typeof onBusy !== 'function' || typeof requestAnimationFrame !== 'function') {
|
|
14
|
+
work();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
onBusy(true);
|
|
18
|
+
// requestAnimationFrame fires just before the next paint, so a timeout
|
|
19
|
+
// scheduled inside it runs just after: the indicator is on screen before
|
|
20
|
+
// the main thread blocks.
|
|
21
|
+
requestAnimationFrame(() => setTimeout(() => {
|
|
22
|
+
try {
|
|
23
|
+
work();
|
|
24
|
+
} finally {
|
|
25
|
+
onBusy(false);
|
|
26
|
+
}
|
|
27
|
+
}, 0));
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe, it, expect, vi, afterEach,
|
|
3
|
+
} from 'vitest';
|
|
4
|
+
import { runSelectionWithBusySignal } from './selection-busy.js';
|
|
5
|
+
|
|
6
|
+
describe('runSelectionWithBusySignal', () => {
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.unstubAllGlobals();
|
|
9
|
+
vi.useRealTimers();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('runs the work inline without a busy signal', () => {
|
|
13
|
+
const work = vi.fn();
|
|
14
|
+
runSelectionWithBusySignal(null, work);
|
|
15
|
+
expect(work).toHaveBeenCalledTimes(1);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('signals busy, lets a frame paint, then runs the work and clears', () => {
|
|
19
|
+
vi.useFakeTimers();
|
|
20
|
+
const rafCallbacks = [];
|
|
21
|
+
vi.stubGlobal('requestAnimationFrame', cb => rafCallbacks.push(cb));
|
|
22
|
+
const calls = [];
|
|
23
|
+
const onBusy = isBusy => calls.push(['busy', isBusy]);
|
|
24
|
+
const work = () => calls.push(['work']);
|
|
25
|
+
runSelectionWithBusySignal(onBusy, work);
|
|
26
|
+
// The work is deferred until after the frame that paints the indicator.
|
|
27
|
+
expect(calls).toEqual([['busy', true]]);
|
|
28
|
+
rafCallbacks.forEach(cb => cb());
|
|
29
|
+
expect(calls).toEqual([['busy', true]]);
|
|
30
|
+
vi.runAllTimers();
|
|
31
|
+
expect(calls).toEqual([['busy', true], ['work'], ['busy', false]]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('clears the busy signal when the work throws', () => {
|
|
35
|
+
vi.useFakeTimers();
|
|
36
|
+
vi.stubGlobal('requestAnimationFrame', cb => cb());
|
|
37
|
+
const onBusy = vi.fn();
|
|
38
|
+
expect(() => {
|
|
39
|
+
runSelectionWithBusySignal(onBusy, () => { throw new Error('boom'); });
|
|
40
|
+
vi.runAllTimers();
|
|
41
|
+
}).toThrow('boom');
|
|
42
|
+
expect(onBusy).toHaveBeenNthCalledWith(1, true);
|
|
43
|
+
expect(onBusy).toHaveBeenNthCalledWith(2, false);
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/selection-utils.js
CHANGED
|
@@ -30,6 +30,10 @@ const onSelectNoop = ({ pickingInfos }) => {};
|
|
|
30
30
|
* @param {string} cellBaseLayerId
|
|
31
31
|
* @param {object[]} obsLayers Objects with properties
|
|
32
32
|
* getObsCoords, obsIndex, obsQuadTree, onSelect.
|
|
33
|
+
* @param {boolean} flipY
|
|
34
|
+
* @param {null|((isBusy: boolean) => void)} onSelectionBusy Called with true
|
|
35
|
+
* just before a drawn selection's blocking hit test and application begin,
|
|
36
|
+
* and with false once they finish, so views can show a busy indicator.
|
|
33
37
|
* @returns {object[]} The array of DeckGL selection layers.
|
|
34
38
|
*/
|
|
35
39
|
export function getSelectionLayer(
|
|
@@ -38,6 +42,7 @@ export function getSelectionLayer(
|
|
|
38
42
|
layerId,
|
|
39
43
|
obsLayers,
|
|
40
44
|
flipY = false,
|
|
45
|
+
onSelectionBusy = null,
|
|
41
46
|
) {
|
|
42
47
|
if (!tool) {
|
|
43
48
|
return [];
|
|
@@ -50,6 +55,7 @@ export function getSelectionLayer(
|
|
|
50
55
|
id: 'selection',
|
|
51
56
|
flipY,
|
|
52
57
|
obsLayers,
|
|
58
|
+
onSelectionBusy,
|
|
53
59
|
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
54
60
|
selectionType: tool,
|
|
55
61
|
// This onSelect is no longer used since
|