@vertexvis/viewer 0.20.1-testing.0 → 0.20.1

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.
Files changed (68) hide show
  1. package/dist/cjs/index.cjs.js +3 -2
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/cjs/{controller-0155a10a.js → model-2105e63b.js} +85 -1
  4. package/dist/cjs/model-2105e63b.js.map +1 -0
  5. package/dist/cjs/vertex-viewer-box-query-tool.cjs.entry.js +7 -87
  6. package/dist/cjs/vertex-viewer-box-query-tool.cjs.entry.js.map +1 -1
  7. package/dist/cjs/vertex-viewer.cjs.entry.js +90 -24
  8. package/dist/cjs/vertex-viewer.cjs.entry.js.map +1 -1
  9. package/dist/collection/components/viewer-box-query-tool/viewer-box-query-tool.js +23 -1
  10. package/dist/collection/components/viewer-box-query-tool/viewer-box-query-tool.js.map +1 -1
  11. package/dist/collection/lib/interactions/multiPointerInteractionHandler.js +4 -2
  12. package/dist/collection/lib/interactions/multiPointerInteractionHandler.js.map +1 -1
  13. package/dist/collection/lib/interactions/multiTouchInteractionHandler.js +79 -17
  14. package/dist/collection/lib/interactions/multiTouchInteractionHandler.js.map +1 -1
  15. package/dist/collection/lib/interactions/touchInteractionHandler.js +4 -5
  16. package/dist/collection/lib/interactions/touchInteractionHandler.js.map +1 -1
  17. package/dist/collection/lib/volume-intersection/index.js +1 -0
  18. package/dist/collection/lib/volume-intersection/index.js.map +1 -1
  19. package/dist/collection/lib/window.js +7 -0
  20. package/dist/collection/lib/window.js.map +1 -0
  21. package/dist/components/index.js +1 -1
  22. package/dist/components/model2.js +165 -128
  23. package/dist/components/model2.js.map +1 -1
  24. package/dist/components/model3.js +157 -0
  25. package/dist/components/model3.js.map +1 -0
  26. package/dist/components/vertex-viewer-box-query-tool.js +4 -86
  27. package/dist/components/vertex-viewer-box-query-tool.js.map +1 -1
  28. package/dist/components/vertex-viewer-pin-tool.js +1 -1
  29. package/dist/components/vertex-viewer.js +91 -25
  30. package/dist/components/vertex-viewer.js.map +1 -1
  31. package/dist/components/viewer-pin-group.js +1 -1
  32. package/dist/components/viewer-pin-label-line.js +1 -1
  33. package/dist/components/viewer-pin-label.js +1 -1
  34. package/dist/esm/index.js +1 -1
  35. package/dist/esm/index.mjs +1 -1
  36. package/dist/esm/{controller-f0d7a836.js → model-4ba9fc30.js} +85 -2
  37. package/dist/esm/model-4ba9fc30.js.map +1 -0
  38. package/dist/esm/vertex-viewer-box-query-tool.entry.js +6 -86
  39. package/dist/esm/vertex-viewer-box-query-tool.entry.js.map +1 -1
  40. package/dist/esm/vertex-viewer.entry.js +91 -25
  41. package/dist/esm/vertex-viewer.entry.js.map +1 -1
  42. package/dist/types/components/viewer-box-query-tool/viewer-box-query-tool.d.ts +5 -1
  43. package/dist/types/components.d.ts +8 -0
  44. package/dist/types/lib/interactions/multiTouchInteractionHandler.d.ts +7 -2
  45. package/dist/types/lib/interactions/touchInteractionHandler.d.ts +1 -0
  46. package/dist/types/lib/volume-intersection/index.d.ts +1 -0
  47. package/dist/types/lib/window.d.ts +1 -0
  48. package/dist/viewer/index.esm.js +1 -1
  49. package/dist/viewer/index.esm.js.map +1 -1
  50. package/dist/viewer/p-12a301e0.entry.js +5 -0
  51. package/dist/viewer/p-12a301e0.entry.js.map +1 -0
  52. package/dist/viewer/p-4c4019b2.entry.js +5 -0
  53. package/dist/viewer/p-4c4019b2.entry.js.map +1 -0
  54. package/dist/viewer/p-ee0c9d33.js +5 -0
  55. package/dist/viewer/p-ee0c9d33.js.map +1 -0
  56. package/dist/viewer/viewer.esm.js +1 -1
  57. package/package.json +7 -7
  58. package/readme.md +4 -4
  59. package/dist/cjs/controller-0155a10a.js.map +0 -1
  60. package/dist/components/controller3.js +0 -111
  61. package/dist/components/controller3.js.map +0 -1
  62. package/dist/esm/controller-f0d7a836.js.map +0 -1
  63. package/dist/viewer/p-b50678f0.js +0 -5
  64. package/dist/viewer/p-b50678f0.js.map +0 -1
  65. package/dist/viewer/p-c6e12cf7.entry.js +0 -5
  66. package/dist/viewer/p-c6e12cf7.entry.js.map +0 -1
  67. package/dist/viewer/p-cfa05845.entry.js +0 -5
  68. package/dist/viewer/p-cfa05845.entry.js.map +0 -1
@@ -11,7 +11,7 @@ import './streamAttributes.js';
11
11
  import { V as Viewport } from './viewport.js';
12
12
  import './representation_pb.js';
13
13
  import { P as PinController, t as translatePointToScreen, d as defineCustomElement$2 } from './viewer-pin-label.js';
14
- import { g as getPinColors, i as isTextPin, a as isIconPin, P as PinModel } from './model2.js';
14
+ import { g as getPinColors, i as isTextPin, a as isIconPin, P as PinModel } from './model3.js';
15
15
  import { c as classnames } from './index2.js';
16
16
  import { d as defineCustomElement$4 } from './viewer-dom-element.js';
17
17
  import { d as defineCustomElement$3 } from './viewer-icon.js';
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2024 Vertex Software LLC. All rights reserved.
3
3
  */
4
4
  import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
5
- import { g as getPinColors } from './model2.js';
5
+ import { g as getPinColors } from './model3.js';
6
6
 
7
7
  const viewerPinLabelLineCss = ":host{--viewer-annotations-pin-label-line-color:var(--viewer-annotations-pin-primary-color);--viewer-annotations-pin-label-line-width:1\n\n overflow: hidden;pointer-events:none}.label-line{pointer-events:auto;stroke:var(--viewer-annotations-pin-label-line-color);stroke-width:var( --viewer-annotations-pin-label-line-width);cursor:default}.svg{position:absolute;top:0;bottom:0;left:0;right:0;overflow:hidden;pointer-events:none;height:100%;width:100%}";
8
8
 
@@ -5,7 +5,7 @@ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/
5
5
  import { p as point, d as dimensions } from './bundle.esm.js';
6
6
  import { c as classnames } from './index2.js';
7
7
  import { g as getMouseClientPosition } from './dom.js';
8
- import { P as PinModel, g as getPinColors, i as isTextPin } from './model2.js';
8
+ import { P as PinModel, g as getPinColors, i as isTextPin } from './model3.js';
9
9
  import { r as readDOM } from './stencil.js';
10
10
  import { r as range } from './browser.esm.js';
11
11
 
package/dist/esm/index.js CHANGED
@@ -15,7 +15,7 @@ export { A as AngleUnits, g as AreaUnits, c as CrossSectioning, D as DistanceUni
15
15
  export { E as EntityType } from './entities-0a248a42.js';
16
16
  export { A as ArrowMarkup, C as CircleMarkup, F as FreeformMarkup } from './markup-de28aeff.js';
17
17
  export { V as Viewport } from './viewport-4ab005ad.js';
18
- export { V as VolumeIntersectionQueryController } from './controller-f0d7a836.js';
18
+ export { V as VolumeIntersectionQueryController, a as VolumeIntersectionQueryModel } from './model-4ba9fc30.js';
19
19
  import './browser.esm-e0ef86ec.js';
20
20
  import './errors-3ffaf550.js';
21
21
  import './representation_pb-efee7a8e.js';
@@ -15,7 +15,7 @@ export { A as AngleUnits, g as AreaUnits, c as CrossSectioning, D as DistanceUni
15
15
  export { E as EntityType } from './entities-0a248a42.js';
16
16
  export { A as ArrowMarkup, C as CircleMarkup, F as FreeformMarkup } from './markup-de28aeff.js';
17
17
  export { V as Viewport } from './viewport-4ab005ad.js';
18
- export { V as VolumeIntersectionQueryController } from './controller-f0d7a836.js';
18
+ export { V as VolumeIntersectionQueryController, a as VolumeIntersectionQueryModel } from './model-4ba9fc30.js';
19
19
  import './browser.esm-e0ef86ec.js';
20
20
  import './errors-3ffaf550.js';
21
21
  import './representation_pb-efee7a8e.js';
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { S as StreamRequestError } from './bundle.esm-6602f71c.js';
5
5
  import { E as EventDispatcher } from './browser.esm-e0ef86ec.js';
6
+ import { p as point, e as rectangle } from './bundle.esm-77ed5eae.js';
6
7
 
7
8
  class VolumeIntersectionQueryController {
8
9
  constructor(model, viewer) {
@@ -106,6 +107,88 @@ class VolumeIntersectionQueryController {
106
107
  }
107
108
  }
108
109
 
109
- export { VolumeIntersectionQueryController as V };
110
+ class VolumeIntersectionQueryModel {
111
+ constructor(mode) {
112
+ this.mode = mode;
113
+ this.dragStarted = new EventDispatcher();
114
+ this.dragComplete = new EventDispatcher();
115
+ this.dragCancelled = new EventDispatcher();
116
+ this.screenBoundsChanged = new EventDispatcher();
117
+ }
118
+ setStartPoint(point) {
119
+ this.startPoint = point;
120
+ this.dragStarted.emit();
121
+ }
122
+ setEndPoint(point$1) {
123
+ if (this.startPoint != null &&
124
+ point.distance(this.startPoint, point$1) >= 2) {
125
+ this.endPoint = point$1;
126
+ this.updateQueryType();
127
+ this.screenBoundsChanged.emit(this.getQueryDetails());
128
+ }
129
+ }
130
+ setMode(mode) {
131
+ this.mode = mode;
132
+ }
133
+ complete() {
134
+ if (this.startPoint != null && this.endPoint != null) {
135
+ this.screenBoundsChanged.emit(undefined);
136
+ this.dragComplete.emit(this.getQueryDetails());
137
+ this.reset();
138
+ }
139
+ }
140
+ cancel() {
141
+ this.screenBoundsChanged.emit(undefined);
142
+ this.dragCancelled.emit();
143
+ this.reset();
144
+ }
145
+ reset() {
146
+ this.startPoint = undefined;
147
+ this.endPoint = undefined;
148
+ this.type = undefined;
149
+ }
150
+ getScreenBounds() {
151
+ return this.startPoint != null && this.endPoint != null
152
+ ? rectangle.fromPoints(this.startPoint, this.endPoint)
153
+ : undefined;
154
+ }
155
+ getType() {
156
+ return this.type;
157
+ }
158
+ onScreenBoundsChanged(listener) {
159
+ return this.screenBoundsChanged.on(listener);
160
+ }
161
+ onDragStarted(listener) {
162
+ return this.dragStarted.on(listener);
163
+ }
164
+ onDragComplete(listener) {
165
+ return this.dragComplete.on(listener);
166
+ }
167
+ onDragCancelled(listener) {
168
+ return this.dragCancelled.on(listener);
169
+ }
170
+ getQueryDetails() {
171
+ if (this.startPoint != null && this.endPoint != null && this.type != null) {
172
+ return {
173
+ screenBounds: rectangle.fromPoints(this.startPoint, this.endPoint),
174
+ type: this.type,
175
+ };
176
+ }
177
+ else {
178
+ throw new Error('Failed to create query details, the start and end points must be set.');
179
+ }
180
+ }
181
+ updateQueryType() {
182
+ var _a;
183
+ if (this.startPoint != null && this.endPoint != null) {
184
+ const directionalType = point.subtract(this.endPoint, this.startPoint).x > 0
185
+ ? 'exclusive'
186
+ : 'inclusive';
187
+ this.type = (_a = this.mode) !== null && _a !== void 0 ? _a : directionalType;
188
+ }
189
+ }
190
+ }
191
+
192
+ export { VolumeIntersectionQueryController as V, VolumeIntersectionQueryModel as a };
110
193
 
111
- //# sourceMappingURL=controller-f0d7a836.js.map
194
+ //# sourceMappingURL=model-4ba9fc30.js.map
@@ -0,0 +1 @@
1
+ {"file":"model-4ba9fc30.js","mappings":"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","names":["point","Point","Rectangle"],"sources":["./src/lib/volume-intersection/controller.ts","./src/lib/volume-intersection/model.ts"],"sourcesContent":["import { Point } from '@vertexvis/geometry';\nimport { StreamRequestError } from '@vertexvis/stream-api';\nimport { Disposable, EventDispatcher, Listener } from '@vertexvis/utils';\n\nimport {\n SceneItemOperationsBuilder,\n TerminalItemOperationBuilder,\n} from '../scenes';\nimport { SceneItemQueryExecutor } from '../scenes/queries';\nimport { VolumeIntersectionQueryModel } from './model';\n\nexport type OperationTransform = (\n builder: SceneItemOperationsBuilder\n) => TerminalItemOperationBuilder;\nexport type AdditionalTransform = (\n executor: SceneItemQueryExecutor\n) => TerminalItemOperationBuilder;\n\nexport interface CompleteExecutionDetails {\n aborted: boolean;\n}\n\nexport class VolumeIntersectionQueryController {\n private previousViewerCameraControls?: boolean;\n private operationTransform: OperationTransform;\n private additionalTransforms: AdditionalTransform[] = [];\n private operationInFlight = false;\n private operationAborted = false;\n\n private executeStarted = new EventDispatcher<void>();\n private executeComplete = new EventDispatcher<CompleteExecutionDetails>();\n private executeAborted = new EventDispatcher<StreamRequestError>();\n\n public constructor(\n private model: VolumeIntersectionQueryModel,\n private viewer: HTMLVertexViewerElement\n ) {\n this.additionalTransforms = [(op) => op.where((q) => q.all()).deselect()];\n this.operationTransform = (builder) => builder.select();\n }\n\n public setStartPoint(point: Point.Point): void {\n this.previousViewerCameraControls = this.viewer.cameraControls;\n this.viewer.cameraControls = false;\n\n this.model.setStartPoint(point);\n }\n\n public setEndPoint(point: Point.Point): void {\n this.model.setEndPoint(point);\n }\n\n /**\n * Updates the operation that will be applied based on the volume intersection\n * query. Defaults to `(builder) => builder.select()`, which will select any\n * of the results of the query.\n */\n public setOperationTransform(operationTransform: OperationTransform): void {\n this.operationTransform = operationTransform;\n }\n\n /**\n * Updates any additional operations that should be performed independent of\n * the volume intersection query. This can be used to perform an operation on\n * the entirety of the scene prior to the operation on the result of the\n * volume intersection query.\n * Defaults to `[(op) => op.where((q) => q.all()).deselect()]`, which will\n * clear any prior selection before the default selection.\n */\n public setAdditionalTransforms(\n additionalTransforms: AdditionalTransform[]\n ): void {\n this.additionalTransforms = additionalTransforms;\n }\n\n public onExecuteStarted(listener: Listener<void>): Disposable {\n return this.executeStarted.on(listener);\n }\n\n public onExecuteComplete(\n listener: Listener<CompleteExecutionDetails>\n ): Disposable {\n return this.executeComplete.on(listener);\n }\n\n public onExecuteAborted(listener: Listener<StreamRequestError>): Disposable {\n return this.executeAborted.on(listener);\n }\n\n public async execute(): Promise<void> {\n const screenBounds = this.model.getScreenBounds();\n const type = this.model.getType();\n\n if (screenBounds != null && !this.operationInFlight) {\n this.model.complete();\n\n try {\n this.operationInFlight = true;\n this.executeStarted.emit();\n\n const additionalTransforms = (\n op: SceneItemQueryExecutor\n ): SceneItemOperationsBuilder[] =>\n this.additionalTransforms.map((t) => t(op)).flat();\n const operationTransforms = (\n op: SceneItemQueryExecutor\n ): SceneItemOperationsBuilder[] =>\n [\n this.operationTransform(\n op.where((q) =>\n q.withVolumeIntersection(screenBounds, type === 'exclusive')\n )\n ),\n ].flat();\n\n const scene = await this.viewer.scene();\n await scene\n .items((op) => [\n ...additionalTransforms(op),\n ...operationTransforms(op),\n ])\n .execute();\n } catch (e) {\n if (\n e instanceof StreamRequestError &&\n e.summary?.toLocaleLowerCase().includes('operation aborted')\n ) {\n this.executeAborted.emit(e);\n this.operationAborted = true;\n } else {\n console.error('Failed to perform volume intersection query', e);\n throw e;\n }\n } finally {\n this.viewer.cameraControls = this.previousViewerCameraControls ?? true;\n this.previousViewerCameraControls = undefined;\n this.operationInFlight = false;\n this.executeComplete.emit({\n aborted: this.operationAborted,\n });\n this.operationAborted = false;\n }\n } else if (this.operationInFlight) {\n this.model.cancel();\n\n throw new Error(\n `Unable to perform volume intersection query as there is already one in-flight.`\n );\n } else {\n this.model.cancel();\n\n this.viewer.cameraControls = this.previousViewerCameraControls ?? true;\n }\n }\n}\n","import { Point, Rectangle } from '@vertexvis/geometry';\nimport { Disposable, EventDispatcher, Listener } from '@vertexvis/utils';\n\nimport { VolumeIntersectionQueryMode } from '../../components/viewer-box-query-tool/types';\n\nexport type QueryType = 'inclusive' | 'exclusive';\n\nexport interface VolumeIntersectionQueryDetails {\n screenBounds: Rectangle.Rectangle;\n type: QueryType;\n}\n\nexport class VolumeIntersectionQueryModel {\n private startPoint?: Point.Point;\n private endPoint?: Point.Point;\n private type?: QueryType;\n\n private dragStarted = new EventDispatcher<void>();\n private dragComplete = new EventDispatcher<VolumeIntersectionQueryDetails>();\n private dragCancelled = new EventDispatcher<void>();\n\n private screenBoundsChanged = new EventDispatcher<\n VolumeIntersectionQueryDetails | undefined\n >();\n\n public constructor(private mode?: VolumeIntersectionQueryMode) {}\n\n public setStartPoint(point: Point.Point): void {\n this.startPoint = point;\n\n this.dragStarted.emit();\n }\n\n public setEndPoint(point: Point.Point): void {\n if (\n this.startPoint != null &&\n Point.distance(this.startPoint, point) >= 2\n ) {\n this.endPoint = point;\n\n this.updateQueryType();\n this.screenBoundsChanged.emit(this.getQueryDetails());\n }\n }\n\n public setMode(mode?: VolumeIntersectionQueryMode): void {\n this.mode = mode;\n }\n\n public complete(): void {\n if (this.startPoint != null && this.endPoint != null) {\n this.screenBoundsChanged.emit(undefined);\n this.dragComplete.emit(this.getQueryDetails());\n this.reset();\n }\n }\n\n public cancel(): void {\n this.screenBoundsChanged.emit(undefined);\n this.dragCancelled.emit();\n this.reset();\n }\n\n public reset(): void {\n this.startPoint = undefined;\n this.endPoint = undefined;\n this.type = undefined;\n }\n\n public getScreenBounds(): Rectangle.Rectangle | undefined {\n return this.startPoint != null && this.endPoint != null\n ? Rectangle.fromPoints(this.startPoint, this.endPoint)\n : undefined;\n }\n\n public getType(): QueryType | undefined {\n return this.type;\n }\n\n public onScreenBoundsChanged(\n listener: Listener<VolumeIntersectionQueryDetails | undefined>\n ): Disposable {\n return this.screenBoundsChanged.on(listener);\n }\n\n public onDragStarted(listener: Listener<void>): Disposable {\n return this.dragStarted.on(listener);\n }\n\n public onDragComplete(\n listener: Listener<VolumeIntersectionQueryDetails>\n ): Disposable {\n return this.dragComplete.on(listener);\n }\n\n public onDragCancelled(listener: Listener<void>): Disposable {\n return this.dragCancelled.on(listener);\n }\n\n private getQueryDetails(): VolumeIntersectionQueryDetails {\n if (this.startPoint != null && this.endPoint != null && this.type != null) {\n return {\n screenBounds: Rectangle.fromPoints(this.startPoint, this.endPoint),\n type: this.type,\n };\n } else {\n throw new Error(\n 'Failed to create query details, the start and end points must be set.'\n );\n }\n }\n\n private updateQueryType(): void {\n if (this.startPoint != null && this.endPoint != null) {\n const directionalType =\n Point.subtract(this.endPoint, this.startPoint).x > 0\n ? 'exclusive'\n : 'inclusive';\n\n this.type = this.mode ?? directionalType;\n }\n }\n}\n"],"version":3}
@@ -1,13 +1,13 @@
1
1
  /*!
2
2
  * Copyright (c) 2024 Vertex Software LLC. All rights reserved.
3
3
  */
4
- import { r as registerInstance, h, H as Host, g as getElement } from './index-4611b0d5.js';
5
- import { V as VolumeIntersectionQueryController } from './controller-f0d7a836.js';
4
+ import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-4611b0d5.js';
5
+ import { a as VolumeIntersectionQueryModel, V as VolumeIntersectionQueryController } from './model-4ba9fc30.js';
6
6
  import { b as boxQueryCursor } from './cursors-aad0bebb.js';
7
7
  import { g as getMouseClientPosition } from './dom-2ca82d60.js';
8
- import { p as point, e as rectangle } from './bundle.esm-77ed5eae.js';
9
- import { E as EventDispatcher } from './browser.esm-e0ef86ec.js';
10
8
  import './bundle.esm-6602f71c.js';
9
+ import './bundle.esm-77ed5eae.js';
10
+ import './browser.esm-e0ef86ec.js';
11
11
 
12
12
  class VolumeIntersectionQueryInteractionHandler {
13
13
  constructor(controller) {
@@ -89,93 +89,12 @@ class VolumeIntersectionQueryInteractionHandler {
89
89
  }
90
90
  }
91
91
 
92
- class VolumeIntersectionQueryModel {
93
- constructor(mode) {
94
- this.mode = mode;
95
- this.dragStarted = new EventDispatcher();
96
- this.dragComplete = new EventDispatcher();
97
- this.dragCancelled = new EventDispatcher();
98
- this.screenBoundsChanged = new EventDispatcher();
99
- }
100
- setStartPoint(point) {
101
- this.startPoint = point;
102
- this.dragStarted.emit();
103
- }
104
- setEndPoint(point$1) {
105
- if (this.startPoint != null &&
106
- point.distance(this.startPoint, point$1) >= 2) {
107
- this.endPoint = point$1;
108
- this.updateQueryType();
109
- this.screenBoundsChanged.emit(this.getQueryDetails());
110
- }
111
- }
112
- setMode(mode) {
113
- this.mode = mode;
114
- }
115
- complete() {
116
- if (this.startPoint != null && this.endPoint != null) {
117
- this.screenBoundsChanged.emit(undefined);
118
- this.dragComplete.emit(this.getQueryDetails());
119
- this.reset();
120
- }
121
- }
122
- cancel() {
123
- this.screenBoundsChanged.emit(undefined);
124
- this.dragCancelled.emit();
125
- this.reset();
126
- }
127
- reset() {
128
- this.startPoint = undefined;
129
- this.endPoint = undefined;
130
- this.type = undefined;
131
- }
132
- getScreenBounds() {
133
- return this.startPoint != null && this.endPoint != null
134
- ? rectangle.fromPoints(this.startPoint, this.endPoint)
135
- : undefined;
136
- }
137
- getType() {
138
- return this.type;
139
- }
140
- onScreenBoundsChanged(listener) {
141
- return this.screenBoundsChanged.on(listener);
142
- }
143
- onDragStarted(listener) {
144
- return this.dragStarted.on(listener);
145
- }
146
- onDragComplete(listener) {
147
- return this.dragComplete.on(listener);
148
- }
149
- onDragCancelled(listener) {
150
- return this.dragCancelled.on(listener);
151
- }
152
- getQueryDetails() {
153
- if (this.startPoint != null && this.endPoint != null && this.type != null) {
154
- return {
155
- screenBounds: rectangle.fromPoints(this.startPoint, this.endPoint),
156
- type: this.type,
157
- };
158
- }
159
- else {
160
- throw new Error('Failed to create query details, the start and end points must be set.');
161
- }
162
- }
163
- updateQueryType() {
164
- var _a;
165
- if (this.startPoint != null && this.endPoint != null) {
166
- const directionalType = point.subtract(this.endPoint, this.startPoint).x > 0
167
- ? 'exclusive'
168
- : 'inclusive';
169
- this.type = (_a = this.mode) !== null && _a !== void 0 ? _a : directionalType;
170
- }
171
- }
172
- }
173
-
174
92
  const viewerBoxQueryToolCss = ":host{--viewer-box-query-outline-exclusive-color:#0099cc;--viewer-box-query-outline-exclusive-border-style:solid;--viewer-box-query-outline-inclusive-color:#00cc00;--viewer-box-query-outline-inclusive-border-style:dashed;--viewer-box-query-outline-border-radius:0.25rem;--viewer-box-query-outline-fill-opacity:0.25}.bounds{position:absolute}.outline{position:absolute;top:0;left:0;width:100%;height:100%;box-sizing:border-box;border-radius:var(--viewer-box-query-outline-border-radius)}:host([exclusive=\"true\"]) .outline{border:3px var(--viewer-box-query-outline-exclusive-border-style) var(--viewer-box-query-outline-exclusive-color)}:host([inclusive=\"true\"]) .outline{border:3px var(--viewer-box-query-outline-inclusive-border-style) var(--viewer-box-query-outline-inclusive-color)}.fill{position:absolute;top:0;left:0;width:100%;height:100%;opacity:var(--viewer-box-query-outline-fill-opacity);border-radius:var(--viewer-box-query-outline-border-radius)}:host([exclusive=\"true\"]) .fill{background-color:var(--viewer-box-query-outline-exclusive-color)}:host([inclusive=\"true\"]) .fill{background-color:var(--viewer-box-query-outline-inclusive-color)}";
175
93
 
176
94
  const ViewerBoxQueryTool = class {
177
95
  constructor(hostRef) {
178
96
  registerInstance(this, hostRef);
97
+ this.controllerChanged = createEvent(this, "controllerChanged", 7);
179
98
  /**
180
99
  * The default operation to perform when a drag has completed and the intersection
181
100
  * query will be run. Defaults to `clearAndSelect`, and can be changed to `select` or `deselect`.
@@ -252,6 +171,7 @@ const ViewerBoxQueryTool = class {
252
171
  (_b = this.operationCompleteDisposable) === null || _b === void 0 ? void 0 : _b.dispose();
253
172
  this.operationStartedDisposable = controller === null || controller === void 0 ? void 0 : controller.onExecuteStarted(this.handleExecuteStarted);
254
173
  this.operationStartedDisposable = controller === null || controller === void 0 ? void 0 : controller.onExecuteComplete(this.handleExecuteComplete);
174
+ this.controllerChanged.emit(this.controller);
255
175
  }
256
176
  /**
257
177
  * @ignore
@@ -1 +1 @@
1
- {"file":"vertex-viewer-box-query-tool.entry.js","mappings":"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","names":["point","Point","Rectangle"],"sources":["./src/lib/volume-intersection/interactions.ts","./src/lib/volume-intersection/model.ts","./src/components/viewer-box-query-tool/viewer-box-query-tool.css?tag=vertex-viewer-box-query-tool&encapsulation=shadow","./src/components/viewer-box-query-tool/viewer-box-query-tool.tsx"],"sourcesContent":["import { Disposable } from '@vertexvis/utils';\n\nimport { boxQueryCursor } from '../cursors';\nimport { getMouseClientPosition } from '../dom';\nimport { InteractionApi } from '../interactions';\nimport { InteractionHandler } from '../interactions/interactionHandler';\nimport { VolumeIntersectionQueryController } from './controller';\n\nexport class VolumeIntersectionQueryInteractionHandler\n implements InteractionHandler\n{\n private element?: HTMLElement;\n private api?: InteractionApi;\n private isInteracting?: boolean;\n private enabled?: boolean;\n private elementBounds?: DOMRect;\n private crosshairCursorDisposable?: Disposable;\n private waitCursorDisposable?: Disposable;\n\n public constructor(private controller: VolumeIntersectionQueryController) {\n this.handleDragBegin = this.handleDragBegin.bind(this);\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDragEnd = this.handleDragEnd.bind(this);\n\n this.enabled = true;\n }\n\n public initialize(element: HTMLElement, api: InteractionApi): void {\n this.element = element;\n this.api = api;\n\n this.element.addEventListener('pointerdown', this.handleDragBegin);\n this.addCrosshairCursor();\n }\n\n public dispose(): void {\n this.element?.removeEventListener('pointerdown', this.handleDragBegin);\n window.removeEventListener('pointermove', this.handleDrag);\n window.removeEventListener('pointerup', this.handleDragEnd);\n this.crosshairCursorDisposable?.dispose();\n this.waitCursorDisposable?.dispose();\n\n this.element = undefined;\n this.api = undefined;\n this.enabled = true;\n }\n\n public disable(): void {\n this.enabled = false;\n }\n\n public enable(): void {\n this.enabled = true;\n }\n\n private handleDragBegin(event: PointerEvent): void {\n if (\n this.enabled &&\n this.isPrimaryMouseButtonClick(event) &&\n !this.isInteracting\n ) {\n this.elementBounds = this.element?.getBoundingClientRect();\n this.isInteracting = true;\n this.controller.setStartPoint(\n getMouseClientPosition(event, this.elementBounds)\n );\n\n window.addEventListener('pointermove', this.handleDrag);\n window.addEventListener('pointerup', this.handleDragEnd);\n }\n }\n\n private handleDrag(event: PointerEvent): void {\n if (this.enabled) {\n this.controller.setEndPoint(\n getMouseClientPosition(event, this.elementBounds)\n );\n }\n }\n\n private async handleDragEnd(): Promise<void> {\n this.isInteracting = false;\n\n window.removeEventListener('pointermove', this.handleDrag);\n window.removeEventListener('pointerup', this.handleDragEnd);\n\n this.crosshairCursorDisposable?.dispose();\n if (this.enabled) {\n this.addWaitCursor();\n try {\n await this.controller.execute();\n } finally {\n this.waitCursorDisposable?.dispose();\n this.addCrosshairCursor();\n }\n }\n }\n\n private isPrimaryMouseButtonClick(event: PointerEvent): boolean {\n return event.buttons === 1;\n }\n\n private addCrosshairCursor(): void {\n this.crosshairCursorDisposable?.dispose();\n this.crosshairCursorDisposable = this.api?.addCursor(boxQueryCursor);\n }\n\n private addWaitCursor(): void {\n this.waitCursorDisposable?.dispose();\n this.waitCursorDisposable = this.api?.addCursor('wait');\n }\n}\n","import { Point, Rectangle } from '@vertexvis/geometry';\nimport { Disposable, EventDispatcher, Listener } from '@vertexvis/utils';\n\nimport { VolumeIntersectionQueryMode } from '../../components/viewer-box-query-tool/types';\n\nexport type QueryType = 'inclusive' | 'exclusive';\n\nexport interface VolumeIntersectionQueryDetails {\n screenBounds: Rectangle.Rectangle;\n type: QueryType;\n}\n\nexport class VolumeIntersectionQueryModel {\n private startPoint?: Point.Point;\n private endPoint?: Point.Point;\n private type?: QueryType;\n\n private dragStarted = new EventDispatcher<void>();\n private dragComplete = new EventDispatcher<VolumeIntersectionQueryDetails>();\n private dragCancelled = new EventDispatcher<void>();\n\n private screenBoundsChanged = new EventDispatcher<\n VolumeIntersectionQueryDetails | undefined\n >();\n\n public constructor(private mode?: VolumeIntersectionQueryMode) {}\n\n public setStartPoint(point: Point.Point): void {\n this.startPoint = point;\n\n this.dragStarted.emit();\n }\n\n public setEndPoint(point: Point.Point): void {\n if (\n this.startPoint != null &&\n Point.distance(this.startPoint, point) >= 2\n ) {\n this.endPoint = point;\n\n this.updateQueryType();\n this.screenBoundsChanged.emit(this.getQueryDetails());\n }\n }\n\n public setMode(mode?: VolumeIntersectionQueryMode): void {\n this.mode = mode;\n }\n\n public complete(): void {\n if (this.startPoint != null && this.endPoint != null) {\n this.screenBoundsChanged.emit(undefined);\n this.dragComplete.emit(this.getQueryDetails());\n this.reset();\n }\n }\n\n public cancel(): void {\n this.screenBoundsChanged.emit(undefined);\n this.dragCancelled.emit();\n this.reset();\n }\n\n public reset(): void {\n this.startPoint = undefined;\n this.endPoint = undefined;\n this.type = undefined;\n }\n\n public getScreenBounds(): Rectangle.Rectangle | undefined {\n return this.startPoint != null && this.endPoint != null\n ? Rectangle.fromPoints(this.startPoint, this.endPoint)\n : undefined;\n }\n\n public getType(): QueryType | undefined {\n return this.type;\n }\n\n public onScreenBoundsChanged(\n listener: Listener<VolumeIntersectionQueryDetails | undefined>\n ): Disposable {\n return this.screenBoundsChanged.on(listener);\n }\n\n public onDragStarted(listener: Listener<void>): Disposable {\n return this.dragStarted.on(listener);\n }\n\n public onDragComplete(\n listener: Listener<VolumeIntersectionQueryDetails>\n ): Disposable {\n return this.dragComplete.on(listener);\n }\n\n public onDragCancelled(listener: Listener<void>): Disposable {\n return this.dragCancelled.on(listener);\n }\n\n private getQueryDetails(): VolumeIntersectionQueryDetails {\n if (this.startPoint != null && this.endPoint != null && this.type != null) {\n return {\n screenBounds: Rectangle.fromPoints(this.startPoint, this.endPoint),\n type: this.type,\n };\n } else {\n throw new Error(\n 'Failed to create query details, the start and end points must be set.'\n );\n }\n }\n\n private updateQueryType(): void {\n if (this.startPoint != null && this.endPoint != null) {\n const directionalType =\n Point.subtract(this.endPoint, this.startPoint).x > 0\n ? 'exclusive'\n : 'inclusive';\n\n this.type = this.mode ?? directionalType;\n }\n }\n}\n",":host {\n /**\n * @prop --viewer-box-query-outline-exclusive-color: A CSS color that\n * specifies the color of box for an exclusive query. This will\n * be used in combination with `--viewer-box-query-outline-fill-opacity`\n * for the background color of the box. Defaults to `#0099cc`.\n */\n --viewer-box-query-outline-exclusive-color: #0099cc;\n /**\n * @prop --viewer-box-query-outline-exclusive-border-style: A border\n * style that specifies the type of border to display around the box for an\n * exclusive query. Defaults to `solid`.\n */\n --viewer-box-query-outline-exclusive-border-style: solid;\n /**\n * @prop --viewer-box-query-outline-inclusive-color: A CSS color that\n * specifies the color of box for an inclusive query. This will\n * be used in combination with `--viewer-box-query-outline-fill-opacity`\n * for the background color of the box. Defaults to `#00cc00`.\n */\n --viewer-box-query-outline-inclusive-color: #00cc00;\n /**\n * @prop --viewer-box-query-outline-inclusive-border-style: A border\n * style that specifies the type of border to display around the box for an\n * inclusive query. Defaults to `dashed`.\n */\n --viewer-box-query-outline-inclusive-border-style: dashed;\n /**\n * @prop --viewer-box-query-outline-border-radius: A CSS length that\n * specifies the border radius of the drawn box. Defaults to `0.25rem`.\n */\n --viewer-box-query-outline-border-radius: 0.25rem;\n /**\n * @prop--viewer-box-query-outline-fill-opacity: A number between \n * 0 and 1 that specifies the opacity of the background of the drawn box.\n * Defaults to `0.25`.\n */\n --viewer-box-query-outline-fill-opacity: 0.25;\n}\n\n.bounds {\n position: absolute;\n}\n\n.outline {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n border-radius: var(--viewer-box-query-outline-border-radius);\n}\n\n:host([exclusive=\"true\"]) .outline {\n border: 3px var(--viewer-box-query-outline-exclusive-border-style) var(--viewer-box-query-outline-exclusive-color);\n}\n\n:host([inclusive=\"true\"]) .outline {\n border: 3px var(--viewer-box-query-outline-inclusive-border-style) var(--viewer-box-query-outline-inclusive-color);\n}\n\n.fill {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n opacity: var(--viewer-box-query-outline-fill-opacity);\n border-radius: var(--viewer-box-query-outline-border-radius);\n}\n\n:host([exclusive=\"true\"]) .fill {\n background-color: var(--viewer-box-query-outline-exclusive-color);\n}\n\n:host([inclusive=\"true\"]) .fill {\n background-color: var(--viewer-box-query-outline-inclusive-color);\n}","import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';\nimport { Disposable } from '@vertexvis/utils';\n\nimport { VolumeIntersectionQueryController } from '../../lib/volume-intersection/controller';\nimport { VolumeIntersectionQueryInteractionHandler } from '../../lib/volume-intersection/interactions';\nimport {\n QueryType,\n VolumeIntersectionQueryDetails,\n VolumeIntersectionQueryModel,\n} from '../../lib/volume-intersection/model';\nimport {\n VolumeIntersectionQueryMode,\n VolumeIntersectionQueryType,\n} from './types';\n\n/**\n * The `ViewerBoxQueryTool` allows for the drawing of a \"box\" on screen to represent\n * a query for items in a specific area of the viewer. This tool then allows for an\n * operation to be performed on the items contained (exclusive) by the box or both\n * contained by and intersecting with (inclusive) the box.\n */\n@Component({\n tag: 'vertex-viewer-box-query-tool',\n styleUrl: 'viewer-box-query-tool.css',\n shadow: true,\n})\nexport class ViewerBoxQueryTool {\n /**\n * The viewer that this component is bound to. This is automatically assigned\n * if added to the light-dom of a parent viewer element.\n */\n @Prop()\n public viewer?: HTMLVertexViewerElement;\n\n /**\n * The controller that is responsible for performing operations using the\n * volume intersection query defined by the drawn box and updating the model.\n */\n @Prop({ mutable: true })\n public controller?: VolumeIntersectionQueryController;\n\n /**\n * The model that contains the points representing the corners of the box\n * displayed on screen, the type of the query to be performed, and methods\n * for setting these values.\n */\n @Prop({ mutable: true })\n public model?: VolumeIntersectionQueryModel;\n\n /**\n * The default operation to perform when a drag has completed and the intersection\n * query will be run. Defaults to `clearAndSelect`, and can be changed to `select` or `deselect`.\n *\n * `clearAndSelect` will clear all existing selection, and select the results of the query.\n * `select` will maintain existing selection, and select the results of the query.\n * `deselect` will maintain existing selection, and deselect the results of the query.\n *\n * The operation behavior for this intersection query tool can also be changed by\n * providing a custom implementation of the `VolumeIntersectionQueryController`, or\n * by using the `setOperationTransform` method of the default controller.\n */\n @Prop()\n public operationType: VolumeIntersectionQueryType = 'clearAndSelect';\n\n /**\n * An optional value to specify a singular mode of intersection query. This value\n * defaults to `undefined`, which will indicate that both `exclusive` and `inclusive`\n * queries should be made, with `inclusive` being represented by a left to right\n * drag behavior and `exclusive` being represented by a right to left drag.\n *\n * Setting this value to `inclusive` will cause dragging left to right and left to right\n * to result in an `inclusive` query, and the box will only be styled for `inclusive` queries.\n *\n * Setting this value to `exclusive` will cause dragging left to right and left to right\n * to result in an `exclusive` query, and the box will only be styled for `exclusive` queries.\n */\n @Prop()\n public mode?: VolumeIntersectionQueryMode;\n\n @State()\n private details?: VolumeIntersectionQueryDetails;\n\n @Element()\n private hostEl!: HTMLVertexViewerBoxQueryToolElement;\n\n private interactionHandler?: VolumeIntersectionQueryInteractionHandler;\n private interactionHandlerDisposable?: Disposable;\n\n private operationStartedDisposable?: Disposable;\n private operationCompleteDisposable?: Disposable;\n private screenBoundsChangedDisposable?: Disposable;\n\n public constructor() {\n this.handleScreenBoundsChanged = this.handleScreenBoundsChanged.bind(this);\n this.handleExecuteStarted = this.handleExecuteStarted.bind(this);\n this.handleExecuteComplete = this.handleExecuteComplete.bind(this);\n }\n\n public componentWillLoad(): void {\n this.model = this.model ?? new VolumeIntersectionQueryModel(this.mode);\n\n this.screenBoundsChangedDisposable = this.model.onScreenBoundsChanged(\n this.handleScreenBoundsChanged\n );\n\n this.handleViewerChanged(this.viewer);\n this.handleControllerChange(this.controller);\n this.handleDefaultOperationChange(this.operationType);\n }\n\n public disconnectedCallback(): void {\n this.model?.reset();\n this.screenBoundsChangedDisposable?.dispose();\n this.operationStartedDisposable?.dispose();\n this.operationCompleteDisposable?.dispose();\n this.deregisterInteractionHandler();\n }\n\n /**\n * @ignore\n */\n @Watch('viewer')\n protected handleViewerChanged(newViewer?: HTMLVertexViewerElement): void {\n this.deregisterInteractionHandler();\n\n if (this.model != null && newViewer != null) {\n this.controller = new VolumeIntersectionQueryController(\n this.model,\n newViewer\n );\n this.handleDefaultOperationChange(this.operationType);\n this.registerInteractionHandler(this.controller, newViewer);\n }\n }\n\n /**\n * @ignore\n */\n @Watch('operationType')\n protected handleDefaultOperationChange(\n updatedOperationType: VolumeIntersectionQueryType\n ): void {\n switch (updatedOperationType) {\n case 'clearAndSelect':\n this.setDefaultClearAndSelectOperation();\n break;\n case 'select':\n this.setDefaultSelectOperation();\n break;\n case 'deselect':\n this.setDefaultDeselectOperation();\n break;\n }\n }\n\n /**\n * @ignore\n */\n @Watch('mode')\n protected handleModeChange(updatedMode?: VolumeIntersectionQueryMode): void {\n this.model?.setMode(updatedMode);\n }\n\n /**\n * @ignore\n */\n @Watch('controller')\n protected handleControllerChange(\n controller?: VolumeIntersectionQueryController\n ): void {\n this.operationStartedDisposable?.dispose();\n this.operationCompleteDisposable?.dispose();\n\n this.operationStartedDisposable = controller?.onExecuteStarted(\n this.handleExecuteStarted\n );\n this.operationStartedDisposable = controller?.onExecuteComplete(\n this.handleExecuteComplete\n );\n }\n\n /**\n * @ignore\n */\n protected render(): h.JSX.IntrinsicElements {\n return (\n <Host>\n <vertex-viewer-layer>\n {this.details != null && (\n <div\n class=\"bounds\"\n style={{\n left: `${this.details.screenBounds.x}px`,\n top: `${this.details.screenBounds.y}px`,\n width: `${this.details.screenBounds.width}px`,\n height: `${this.details.screenBounds.height}px`,\n }}\n >\n <slot name=\"bounds\">\n <div class=\"outline\"></div>\n <div class=\"fill\"></div>\n </slot>\n </div>\n )}\n </vertex-viewer-layer>\n </Host>\n );\n }\n\n private handleScreenBoundsChanged(\n details?: VolumeIntersectionQueryDetails\n ): void {\n this.details = details;\n\n this.updateTypeAttribute(details?.type);\n }\n\n private handleExecuteStarted(): void {\n this.interactionHandler?.disable();\n }\n\n private handleExecuteComplete(): void {\n this.interactionHandler?.enable();\n }\n\n private async registerInteractionHandler(\n controller: VolumeIntersectionQueryController,\n viewer: HTMLVertexViewerElement\n ): Promise<void> {\n this.interactionHandler = new VolumeIntersectionQueryInteractionHandler(\n controller\n );\n this.interactionHandlerDisposable = await viewer.registerInteractionHandler(\n this.interactionHandler\n );\n }\n\n private deregisterInteractionHandler(): void {\n this.interactionHandlerDisposable?.dispose();\n this.interactionHandler?.dispose();\n this.interactionHandler = undefined;\n }\n\n private updateTypeAttribute(type?: QueryType): void {\n this.hostEl.setAttribute('inclusive', `${type === 'inclusive'}`);\n this.hostEl.setAttribute('exclusive', `${type === 'exclusive'}`);\n }\n\n private setDefaultClearAndSelectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.select());\n this.controller?.setAdditionalTransforms([\n (op) => op.where((q) => q.withSelected()).deselect(),\n ]);\n }\n\n private setDefaultSelectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.select());\n this.controller?.setAdditionalTransforms([]);\n }\n\n private setDefaultDeselectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.deselect());\n this.controller?.setAdditionalTransforms([]);\n }\n}\n"],"version":3}
1
+ {"file":"vertex-viewer-box-query-tool.entry.js","mappings":"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","names":[],"sources":["./src/lib/volume-intersection/interactions.ts","./src/components/viewer-box-query-tool/viewer-box-query-tool.css?tag=vertex-viewer-box-query-tool&encapsulation=shadow","./src/components/viewer-box-query-tool/viewer-box-query-tool.tsx"],"sourcesContent":["import { Disposable } from '@vertexvis/utils';\n\nimport { boxQueryCursor } from '../cursors';\nimport { getMouseClientPosition } from '../dom';\nimport { InteractionApi } from '../interactions';\nimport { InteractionHandler } from '../interactions/interactionHandler';\nimport { VolumeIntersectionQueryController } from './controller';\n\nexport class VolumeIntersectionQueryInteractionHandler\n implements InteractionHandler\n{\n private element?: HTMLElement;\n private api?: InteractionApi;\n private isInteracting?: boolean;\n private enabled?: boolean;\n private elementBounds?: DOMRect;\n private crosshairCursorDisposable?: Disposable;\n private waitCursorDisposable?: Disposable;\n\n public constructor(private controller: VolumeIntersectionQueryController) {\n this.handleDragBegin = this.handleDragBegin.bind(this);\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDragEnd = this.handleDragEnd.bind(this);\n\n this.enabled = true;\n }\n\n public initialize(element: HTMLElement, api: InteractionApi): void {\n this.element = element;\n this.api = api;\n\n this.element.addEventListener('pointerdown', this.handleDragBegin);\n this.addCrosshairCursor();\n }\n\n public dispose(): void {\n this.element?.removeEventListener('pointerdown', this.handleDragBegin);\n window.removeEventListener('pointermove', this.handleDrag);\n window.removeEventListener('pointerup', this.handleDragEnd);\n this.crosshairCursorDisposable?.dispose();\n this.waitCursorDisposable?.dispose();\n\n this.element = undefined;\n this.api = undefined;\n this.enabled = true;\n }\n\n public disable(): void {\n this.enabled = false;\n }\n\n public enable(): void {\n this.enabled = true;\n }\n\n private handleDragBegin(event: PointerEvent): void {\n if (\n this.enabled &&\n this.isPrimaryMouseButtonClick(event) &&\n !this.isInteracting\n ) {\n this.elementBounds = this.element?.getBoundingClientRect();\n this.isInteracting = true;\n this.controller.setStartPoint(\n getMouseClientPosition(event, this.elementBounds)\n );\n\n window.addEventListener('pointermove', this.handleDrag);\n window.addEventListener('pointerup', this.handleDragEnd);\n }\n }\n\n private handleDrag(event: PointerEvent): void {\n if (this.enabled) {\n this.controller.setEndPoint(\n getMouseClientPosition(event, this.elementBounds)\n );\n }\n }\n\n private async handleDragEnd(): Promise<void> {\n this.isInteracting = false;\n\n window.removeEventListener('pointermove', this.handleDrag);\n window.removeEventListener('pointerup', this.handleDragEnd);\n\n this.crosshairCursorDisposable?.dispose();\n if (this.enabled) {\n this.addWaitCursor();\n try {\n await this.controller.execute();\n } finally {\n this.waitCursorDisposable?.dispose();\n this.addCrosshairCursor();\n }\n }\n }\n\n private isPrimaryMouseButtonClick(event: PointerEvent): boolean {\n return event.buttons === 1;\n }\n\n private addCrosshairCursor(): void {\n this.crosshairCursorDisposable?.dispose();\n this.crosshairCursorDisposable = this.api?.addCursor(boxQueryCursor);\n }\n\n private addWaitCursor(): void {\n this.waitCursorDisposable?.dispose();\n this.waitCursorDisposable = this.api?.addCursor('wait');\n }\n}\n",":host {\n /**\n * @prop --viewer-box-query-outline-exclusive-color: A CSS color that\n * specifies the color of box for an exclusive query. This will\n * be used in combination with `--viewer-box-query-outline-fill-opacity`\n * for the background color of the box. Defaults to `#0099cc`.\n */\n --viewer-box-query-outline-exclusive-color: #0099cc;\n /**\n * @prop --viewer-box-query-outline-exclusive-border-style: A border\n * style that specifies the type of border to display around the box for an\n * exclusive query. Defaults to `solid`.\n */\n --viewer-box-query-outline-exclusive-border-style: solid;\n /**\n * @prop --viewer-box-query-outline-inclusive-color: A CSS color that\n * specifies the color of box for an inclusive query. This will\n * be used in combination with `--viewer-box-query-outline-fill-opacity`\n * for the background color of the box. Defaults to `#00cc00`.\n */\n --viewer-box-query-outline-inclusive-color: #00cc00;\n /**\n * @prop --viewer-box-query-outline-inclusive-border-style: A border\n * style that specifies the type of border to display around the box for an\n * inclusive query. Defaults to `dashed`.\n */\n --viewer-box-query-outline-inclusive-border-style: dashed;\n /**\n * @prop --viewer-box-query-outline-border-radius: A CSS length that\n * specifies the border radius of the drawn box. Defaults to `0.25rem`.\n */\n --viewer-box-query-outline-border-radius: 0.25rem;\n /**\n * @prop--viewer-box-query-outline-fill-opacity: A number between \n * 0 and 1 that specifies the opacity of the background of the drawn box.\n * Defaults to `0.25`.\n */\n --viewer-box-query-outline-fill-opacity: 0.25;\n}\n\n.bounds {\n position: absolute;\n}\n\n.outline {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n border-radius: var(--viewer-box-query-outline-border-radius);\n}\n\n:host([exclusive=\"true\"]) .outline {\n border: 3px var(--viewer-box-query-outline-exclusive-border-style) var(--viewer-box-query-outline-exclusive-color);\n}\n\n:host([inclusive=\"true\"]) .outline {\n border: 3px var(--viewer-box-query-outline-inclusive-border-style) var(--viewer-box-query-outline-inclusive-color);\n}\n\n.fill {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n opacity: var(--viewer-box-query-outline-fill-opacity);\n border-radius: var(--viewer-box-query-outline-border-radius);\n}\n\n:host([exclusive=\"true\"]) .fill {\n background-color: var(--viewer-box-query-outline-exclusive-color);\n}\n\n:host([inclusive=\"true\"]) .fill {\n background-color: var(--viewer-box-query-outline-inclusive-color);\n}","import {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport { Disposable } from '@vertexvis/utils';\n\nimport { VolumeIntersectionQueryController } from '../../lib/volume-intersection/controller';\nimport { VolumeIntersectionQueryInteractionHandler } from '../../lib/volume-intersection/interactions';\nimport {\n QueryType,\n VolumeIntersectionQueryDetails,\n VolumeIntersectionQueryModel,\n} from '../../lib/volume-intersection/model';\nimport {\n VolumeIntersectionQueryMode,\n VolumeIntersectionQueryType,\n} from './types';\n\n/**\n * The `ViewerBoxQueryTool` allows for the drawing of a \"box\" on screen to represent\n * a query for items in a specific area of the viewer. This tool then allows for an\n * operation to be performed on the items contained (exclusive) by the box or both\n * contained by and intersecting with (inclusive) the box.\n */\n@Component({\n tag: 'vertex-viewer-box-query-tool',\n styleUrl: 'viewer-box-query-tool.css',\n shadow: true,\n})\nexport class ViewerBoxQueryTool {\n /**\n * The viewer that this component is bound to. This is automatically assigned\n * if added to the light-dom of a parent viewer element.\n */\n @Prop()\n public viewer?: HTMLVertexViewerElement;\n\n /**\n * The controller that is responsible for performing operations using the\n * volume intersection query defined by the drawn box and updating the model.\n */\n @Prop({ mutable: true })\n public controller?: VolumeIntersectionQueryController;\n\n /**\n * The model that contains the points representing the corners of the box\n * displayed on screen, the type of the query to be performed, and methods\n * for setting these values.\n */\n @Prop({ mutable: true })\n public model?: VolumeIntersectionQueryModel;\n\n /**\n * The default operation to perform when a drag has completed and the intersection\n * query will be run. Defaults to `clearAndSelect`, and can be changed to `select` or `deselect`.\n *\n * `clearAndSelect` will clear all existing selection, and select the results of the query.\n * `select` will maintain existing selection, and select the results of the query.\n * `deselect` will maintain existing selection, and deselect the results of the query.\n *\n * The operation behavior for this intersection query tool can also be changed by\n * providing a custom implementation of the `VolumeIntersectionQueryController`, or\n * by using the `setOperationTransform` method of the default controller.\n */\n @Prop()\n public operationType: VolumeIntersectionQueryType = 'clearAndSelect';\n\n /**\n * An optional value to specify a singular mode of intersection query. This value\n * defaults to `undefined`, which will indicate that both `exclusive` and `inclusive`\n * queries should be made, with `inclusive` being represented by a left to right\n * drag behavior and `exclusive` being represented by a right to left drag.\n *\n * Setting this value to `inclusive` will cause dragging left to right and left to right\n * to result in an `inclusive` query, and the box will only be styled for `inclusive` queries.\n *\n * Setting this value to `exclusive` will cause dragging left to right and left to right\n * to result in an `exclusive` query, and the box will only be styled for `exclusive` queries.\n */\n @Prop()\n public mode?: VolumeIntersectionQueryMode;\n\n @State()\n private details?: VolumeIntersectionQueryDetails;\n\n /**\n * Event emitted when the `VolumeIntersectionQueryController` associated with this tool changes.\n */\n @Event()\n public controllerChanged!: EventEmitter<VolumeIntersectionQueryController>;\n\n @Element()\n private hostEl!: HTMLVertexViewerBoxQueryToolElement;\n\n private interactionHandler?: VolumeIntersectionQueryInteractionHandler;\n private interactionHandlerDisposable?: Disposable;\n\n private operationStartedDisposable?: Disposable;\n private operationCompleteDisposable?: Disposable;\n private screenBoundsChangedDisposable?: Disposable;\n\n public constructor() {\n this.handleScreenBoundsChanged = this.handleScreenBoundsChanged.bind(this);\n this.handleExecuteStarted = this.handleExecuteStarted.bind(this);\n this.handleExecuteComplete = this.handleExecuteComplete.bind(this);\n }\n\n public componentWillLoad(): void {\n this.model = this.model ?? new VolumeIntersectionQueryModel(this.mode);\n\n this.screenBoundsChangedDisposable = this.model.onScreenBoundsChanged(\n this.handleScreenBoundsChanged\n );\n\n this.handleViewerChanged(this.viewer);\n this.handleControllerChange(this.controller);\n this.handleDefaultOperationChange(this.operationType);\n }\n\n public disconnectedCallback(): void {\n this.model?.reset();\n this.screenBoundsChangedDisposable?.dispose();\n this.operationStartedDisposable?.dispose();\n this.operationCompleteDisposable?.dispose();\n this.deregisterInteractionHandler();\n }\n\n /**\n * @ignore\n */\n @Watch('viewer')\n protected handleViewerChanged(newViewer?: HTMLVertexViewerElement): void {\n this.deregisterInteractionHandler();\n\n if (this.model != null && newViewer != null) {\n this.controller = new VolumeIntersectionQueryController(\n this.model,\n newViewer\n );\n this.handleDefaultOperationChange(this.operationType);\n this.registerInteractionHandler(this.controller, newViewer);\n }\n }\n\n /**\n * @ignore\n */\n @Watch('operationType')\n protected handleDefaultOperationChange(\n updatedOperationType: VolumeIntersectionQueryType\n ): void {\n switch (updatedOperationType) {\n case 'clearAndSelect':\n this.setDefaultClearAndSelectOperation();\n break;\n case 'select':\n this.setDefaultSelectOperation();\n break;\n case 'deselect':\n this.setDefaultDeselectOperation();\n break;\n }\n }\n\n /**\n * @ignore\n */\n @Watch('mode')\n protected handleModeChange(updatedMode?: VolumeIntersectionQueryMode): void {\n this.model?.setMode(updatedMode);\n }\n\n /**\n * @ignore\n */\n @Watch('controller')\n protected handleControllerChange(\n controller?: VolumeIntersectionQueryController\n ): void {\n this.operationStartedDisposable?.dispose();\n this.operationCompleteDisposable?.dispose();\n\n this.operationStartedDisposable = controller?.onExecuteStarted(\n this.handleExecuteStarted\n );\n this.operationStartedDisposable = controller?.onExecuteComplete(\n this.handleExecuteComplete\n );\n\n this.controllerChanged.emit(this.controller);\n }\n\n /**\n * @ignore\n */\n protected render(): h.JSX.IntrinsicElements {\n return (\n <Host>\n <vertex-viewer-layer>\n {this.details != null && (\n <div\n class=\"bounds\"\n style={{\n left: `${this.details.screenBounds.x}px`,\n top: `${this.details.screenBounds.y}px`,\n width: `${this.details.screenBounds.width}px`,\n height: `${this.details.screenBounds.height}px`,\n }}\n >\n <slot name=\"bounds\">\n <div class=\"outline\"></div>\n <div class=\"fill\"></div>\n </slot>\n </div>\n )}\n </vertex-viewer-layer>\n </Host>\n );\n }\n\n private handleScreenBoundsChanged(\n details?: VolumeIntersectionQueryDetails\n ): void {\n this.details = details;\n\n this.updateTypeAttribute(details?.type);\n }\n\n private handleExecuteStarted(): void {\n this.interactionHandler?.disable();\n }\n\n private handleExecuteComplete(): void {\n this.interactionHandler?.enable();\n }\n\n private async registerInteractionHandler(\n controller: VolumeIntersectionQueryController,\n viewer: HTMLVertexViewerElement\n ): Promise<void> {\n this.interactionHandler = new VolumeIntersectionQueryInteractionHandler(\n controller\n );\n this.interactionHandlerDisposable = await viewer.registerInteractionHandler(\n this.interactionHandler\n );\n }\n\n private deregisterInteractionHandler(): void {\n this.interactionHandlerDisposable?.dispose();\n this.interactionHandler?.dispose();\n this.interactionHandler = undefined;\n }\n\n private updateTypeAttribute(type?: QueryType): void {\n this.hostEl.setAttribute('inclusive', `${type === 'inclusive'}`);\n this.hostEl.setAttribute('exclusive', `${type === 'exclusive'}`);\n }\n\n private setDefaultClearAndSelectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.select());\n this.controller?.setAdditionalTransforms([\n (op) => op.where((q) => q.withSelected()).deselect(),\n ]);\n }\n\n private setDefaultSelectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.select());\n this.controller?.setAdditionalTransforms([]);\n }\n\n private setDefaultDeselectOperation(): void {\n this.controller?.setOperationTransform((builder) => builder.deselect());\n this.controller?.setAdditionalTransforms([]);\n }\n}\n"],"version":3}
@@ -1490,7 +1490,15 @@ class MouseInteractionHandler extends BaseInteractionHandler {
1490
1490
  }
1491
1491
  }
1492
1492
 
1493
+ function requestAnimationFrame(callback) {
1494
+ window.requestAnimationFrame(callback);
1495
+ }
1496
+
1493
1497
  class MultiTouchInteractionHandler {
1498
+ constructor() {
1499
+ this.previousFirstPoints = [];
1500
+ this.previousSecondPoints = [];
1501
+ }
1494
1502
  initialize(element, api) {
1495
1503
  this.element = element;
1496
1504
  this.interactionApi = api;
@@ -1498,26 +1506,83 @@ class MultiTouchInteractionHandler {
1498
1506
  dispose() {
1499
1507
  this.element = undefined;
1500
1508
  }
1509
+ beginTwoPointTouch(point1, point2) {
1510
+ this.previousFirstPoints = [...this.previousFirstPoints, point1];
1511
+ this.previousSecondPoints = [...this.previousSecondPoints, point2];
1512
+ }
1501
1513
  handleTwoPointTouchMove(point1, point2) {
1502
- var _a, _b, _c, _d;
1503
- if (this.currentPosition1 != null && this.currentPosition2 != null) {
1504
- const delta = point.add(point.subtract(point1, this.currentPosition1), point.subtract(point2, this.currentPosition2));
1505
- const distance = point.distance(point1, point2) -
1506
- point.distance(this.currentPosition1, this.currentPosition2);
1507
- const zoom = distance * 0.5;
1508
- const previousToCurrent = matrix2.create(point.subtract(this.currentPosition1, this.currentPosition2), point.subtract(point1, point2));
1509
- const angle$1 = angle.toDegrees(Math.atan2(matrix2.determinant(previousToCurrent), matrix2.dot(previousToCurrent)));
1510
- const center = point.create((point1.x + point2.x) / 2, (point1.y + point2.y) / 2);
1511
- (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.beginInteraction();
1512
- (_b = this.interactionApi) === null || _b === void 0 ? void 0 : _b.zoomCameraToPoint(center, zoom);
1513
- (_c = this.interactionApi) === null || _c === void 0 ? void 0 : _c.panCameraByDelta(delta);
1514
- // Setting a minimum angle to prevent wobbling
1515
- if (Math.abs(angle$1) > 0.5) {
1516
- (_d = this.interactionApi) === null || _d === void 0 ? void 0 : _d.twistCamera(angle$1);
1514
+ this.previousFirstPoints = [...this.previousFirstPoints, point1];
1515
+ this.previousSecondPoints = [...this.previousSecondPoints, point2];
1516
+ // Process updates to touch points on animation frame callbacks to batch
1517
+ // the processing. Because each event can potentially only represent a single
1518
+ // touch point moving, two opposing angles can be computed sequentially. This
1519
+ // results in a wobbling effect if those angles are both sent, and this batched
1520
+ // processing helps to reduce that effect.
1521
+ requestAnimationFrame(() => {
1522
+ var _a, _b, _c, _d;
1523
+ if (this.previousFirstPoints.length > 1 &&
1524
+ this.previousSecondPoints.length > 1 &&
1525
+ this.previousFirstPoints.length === this.previousSecondPoints.length) {
1526
+ const previousFirstPoints = this.previousFirstPoints;
1527
+ const previousSecondPoints = this.previousSecondPoints;
1528
+ this.previousFirstPoints = this.previousFirstPoints.slice(-1);
1529
+ this.previousSecondPoints = this.previousSecondPoints.slice(-1);
1530
+ const changes = previousFirstPoints.reduce((result, previousFirstPoint, i) => {
1531
+ if (i < previousFirstPoints.length - 1) {
1532
+ const firstPoint = previousFirstPoints[i + 1];
1533
+ const previousSecondPoint = previousSecondPoints[i];
1534
+ const secondPoint = previousSecondPoints[i + 1];
1535
+ return {
1536
+ deltas: [
1537
+ ...result.deltas,
1538
+ this.computeDelta(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
1539
+ ],
1540
+ zooms: [
1541
+ ...result.zooms,
1542
+ this.computeZoom(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
1543
+ ],
1544
+ angles: [
1545
+ ...result.angles,
1546
+ this.computeAngle(previousFirstPoint, previousSecondPoint, firstPoint, secondPoint),
1547
+ ],
1548
+ };
1549
+ }
1550
+ return result;
1551
+ }, {
1552
+ deltas: [],
1553
+ zooms: [],
1554
+ angles: [],
1555
+ });
1556
+ const delta = changes.deltas.reduce((r, d) => point.add(r, d), point.create());
1557
+ const zoom = changes.zooms.reduce((z, d) => z + d, 0);
1558
+ const angle = changes.angles.reduce((a, d) => a + d, 0);
1559
+ const center = point.create((previousFirstPoints[previousFirstPoints.length - 1].x +
1560
+ previousSecondPoints[previousSecondPoints.length - 1].x) /
1561
+ 2, (previousFirstPoints[previousFirstPoints.length - 1].y +
1562
+ previousSecondPoints[previousSecondPoints.length - 1].y) /
1563
+ 2);
1564
+ (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.beginInteraction();
1565
+ (_b = this.interactionApi) === null || _b === void 0 ? void 0 : _b.zoomCameraToPoint(center, zoom);
1566
+ (_c = this.interactionApi) === null || _c === void 0 ? void 0 : _c.panCameraByDelta(delta);
1567
+ (_d = this.interactionApi) === null || _d === void 0 ? void 0 : _d.twistCamera(angle);
1517
1568
  }
1518
- }
1519
- this.currentPosition1 = point1;
1520
- this.currentPosition2 = point2;
1569
+ });
1570
+ }
1571
+ endTwoPointTouch() {
1572
+ this.previousFirstPoints = [];
1573
+ this.previousSecondPoints = [];
1574
+ }
1575
+ computeDelta(previousPoint1, previousPoint2, point1, point2) {
1576
+ return point.add(point.subtract(point1, previousPoint1), point.subtract(point2, previousPoint2));
1577
+ }
1578
+ computeZoom(previousPoint1, previousPoint2, point1, point2) {
1579
+ const distance = point.distance(point1, point2) -
1580
+ point.distance(previousPoint1, previousPoint2);
1581
+ return distance * 0.5;
1582
+ }
1583
+ computeAngle(previousPoint1, previousPoint2, point1, point2) {
1584
+ const previousToCurrent = matrix2.create(point.subtract(previousPoint1, previousPoint2), point.subtract(point1, point2));
1585
+ return angle.toDegrees(Math.atan2(matrix2.determinant(previousToCurrent), matrix2.dot(previousToCurrent)));
1521
1586
  }
1522
1587
  }
1523
1588
 
@@ -1546,6 +1611,9 @@ class MultiPointerInteractionHandler extends MultiTouchInteractionHandler {
1546
1611
  window.addEventListener('pointermove', this.handlePointerMove);
1547
1612
  window.addEventListener('pointerup', this.handlePointerUp);
1548
1613
  }
1614
+ else if (keys.length === 2) {
1615
+ this.beginTwoPointTouch(this.touchPoints[0], this.touchPoints[1]);
1616
+ }
1549
1617
  }
1550
1618
  handlePointerMove(event) {
1551
1619
  if (this.touchPoints[event.pointerId] != null) {
@@ -1564,13 +1632,12 @@ class MultiPointerInteractionHandler extends MultiTouchInteractionHandler {
1564
1632
  const keys = Object.keys(this.touchPoints);
1565
1633
  if (keys.length === 1) {
1566
1634
  (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.endInteraction();
1567
- this.currentPosition1 = undefined;
1568
- this.currentPosition2 = undefined;
1569
1635
  }
1570
1636
  if (keys.length === 0) {
1571
1637
  window.removeEventListener('pointermove', this.handlePointerMove);
1572
1638
  window.removeEventListener('pointerup', this.handlePointerUp);
1573
1639
  }
1640
+ this.endTwoPointTouch();
1574
1641
  }
1575
1642
  }
1576
1643
 
@@ -1833,12 +1900,10 @@ class TouchInteractionHandler extends MultiTouchInteractionHandler {
1833
1900
  if (event.touches.length >= 1) {
1834
1901
  event.preventDefault();
1835
1902
  const touch1 = event.touches[0];
1836
- const touch2 = event.touches[1];
1837
1903
  this.currentPosition1 = point.create(touch1.screenX, touch1.screenY);
1838
- this.currentPosition2 =
1839
- touch2 != null
1840
- ? point.create(touch2.screenX, touch2.screenY)
1841
- : undefined;
1904
+ if (event.touches[1] != null) {
1905
+ this.beginTwoPointTouch(this.currentPosition1, point.create(event.touches[1].screenX, event.touches[1].screenY));
1906
+ }
1842
1907
  window.addEventListener('touchmove', this.handleTouchMove, {
1843
1908
  passive: false,
1844
1909
  });
@@ -1863,6 +1928,7 @@ class TouchInteractionHandler extends MultiTouchInteractionHandler {
1863
1928
  this.isInteracting = false;
1864
1929
  window.removeEventListener('touchmove', this.handleTouchMove);
1865
1930
  window.removeEventListener('touchend', this.handleTouchEnd);
1931
+ this.endTwoPointTouch();
1866
1932
  }
1867
1933
  handleOnePointTouchMove(touch) {
1868
1934
  var _a, _b, _c;