@deck.gl/widgets 9.4.0-beta.1 → 9.4.0-beta.4

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/index.cjs CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -61,3042 +60,7 @@ module.exports = __toCommonJS(index_exports);
61
60
 
62
61
  // dist/zoom-widget.js
63
62
  var import_jsx_runtime4 = require("preact/jsx-runtime");
64
-
65
- // ../core/src/utils/log.ts
66
- var import_log = require("@probe.gl/log");
67
- var defaultLogger = new import_log.Log({ id: "deck" });
68
- var log_default = defaultLogger;
69
-
70
- // ../core/src/lib/constants.ts
71
- var import_mjolnir = require("mjolnir.js");
72
- var COORDINATE_SYSTEM = {
73
- /**
74
- * `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise
75
- */
76
- DEFAULT: "default",
77
- /**
78
- * Positions are interpreted as [longitude, latitude, elevation]
79
- * longitude/latitude are in degrees, elevation is in meters.
80
- * Dimensions are in meters.
81
- */
82
- LNGLAT: "lnglat",
83
- /**
84
- * Positions are interpreted as [x, y, z] in meter offsets from the coordinate origin.
85
- * Dimensions are in meters.
86
- */
87
- METER_OFFSETS: "meter-offsets",
88
- /**
89
- * Positions are interpreted as [deltaLng, deltaLat, elevation] from the coordinate origin.
90
- * deltaLng/deltaLat are in degrees, elevation is in meters.
91
- * Dimensions are in meters.
92
- */
93
- LNGLAT_OFFSETS: "lnglat-offsets",
94
- /**
95
- * Positions and dimensions are in the common units of the viewport.
96
- */
97
- CARTESIAN: "cartesian"
98
- };
99
- Object.defineProperty(COORDINATE_SYSTEM, "IDENTITY", {
100
- get: () => {
101
- log_default.deprecated("COORDINATE_SYSTEM.IDENTITY", "COORDINATE_SYSTEM.CARTESIAN")();
102
- return COORDINATE_SYSTEM.CARTESIAN;
103
- }
104
- });
105
- var PROJECTION_MODE = {
106
- /**
107
- * Render geospatial data in Web Mercator projection
108
- */
109
- WEB_MERCATOR: 1,
110
- /**
111
- * Render geospatial data as a 3D globe
112
- */
113
- GLOBE: 2,
114
- /**
115
- * (Internal use only) Web Mercator projection at high zoom
116
- */
117
- WEB_MERCATOR_AUTO_OFFSET: 4,
118
- /**
119
- * No transformation
120
- */
121
- IDENTITY: 0
122
- };
123
-
124
- // ../core/src/utils/math-utils.ts
125
- var import_core = require("@math.gl/core");
126
- function createMat4() {
127
- return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
128
- }
129
- function getCameraPosition(viewMatrixInverse) {
130
- return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
131
- }
132
- function getFrustumPlanes(viewProjectionMatrix) {
133
- return {
134
- left: getFrustumPlane(
135
- viewProjectionMatrix[3] + viewProjectionMatrix[0],
136
- viewProjectionMatrix[7] + viewProjectionMatrix[4],
137
- viewProjectionMatrix[11] + viewProjectionMatrix[8],
138
- viewProjectionMatrix[15] + viewProjectionMatrix[12]
139
- ),
140
- right: getFrustumPlane(
141
- viewProjectionMatrix[3] - viewProjectionMatrix[0],
142
- viewProjectionMatrix[7] - viewProjectionMatrix[4],
143
- viewProjectionMatrix[11] - viewProjectionMatrix[8],
144
- viewProjectionMatrix[15] - viewProjectionMatrix[12]
145
- ),
146
- bottom: getFrustumPlane(
147
- viewProjectionMatrix[3] + viewProjectionMatrix[1],
148
- viewProjectionMatrix[7] + viewProjectionMatrix[5],
149
- viewProjectionMatrix[11] + viewProjectionMatrix[9],
150
- viewProjectionMatrix[15] + viewProjectionMatrix[13]
151
- ),
152
- top: getFrustumPlane(
153
- viewProjectionMatrix[3] - viewProjectionMatrix[1],
154
- viewProjectionMatrix[7] - viewProjectionMatrix[5],
155
- viewProjectionMatrix[11] - viewProjectionMatrix[9],
156
- viewProjectionMatrix[15] - viewProjectionMatrix[13]
157
- ),
158
- near: getFrustumPlane(
159
- viewProjectionMatrix[3] + viewProjectionMatrix[2],
160
- viewProjectionMatrix[7] + viewProjectionMatrix[6],
161
- viewProjectionMatrix[11] + viewProjectionMatrix[10],
162
- viewProjectionMatrix[15] + viewProjectionMatrix[14]
163
- ),
164
- far: getFrustumPlane(
165
- viewProjectionMatrix[3] - viewProjectionMatrix[2],
166
- viewProjectionMatrix[7] - viewProjectionMatrix[6],
167
- viewProjectionMatrix[11] - viewProjectionMatrix[10],
168
- viewProjectionMatrix[15] - viewProjectionMatrix[14]
169
- )
170
- };
171
- }
172
- var scratchVector = new import_core.Vector3();
173
- function getFrustumPlane(a, b, c, d) {
174
- scratchVector.set(a, b, c);
175
- const L = scratchVector.len();
176
- return { distance: d / L, normal: new import_core.Vector3(-a / L, -b / L, -c / L) };
177
- }
178
-
179
- // ../core/src/viewports/viewport.ts
180
- var import_core2 = require("@math.gl/core");
181
- var import_web_mercator = require("@math.gl/web-mercator");
182
- var DEGREES_TO_RADIANS = Math.PI / 180;
183
- var IDENTITY = createMat4();
184
- var ZERO_VECTOR = [0, 0, 0];
185
- var DEFAULT_DISTANCE_SCALES = {
186
- unitsPerMeter: [1, 1, 1],
187
- metersPerUnit: [1, 1, 1]
188
- };
189
- function createProjectionMatrix({
190
- width,
191
- height,
192
- orthographic,
193
- fovyRadians,
194
- focalDistance,
195
- padding,
196
- near,
197
- far
198
- }) {
199
- const aspect = width / height;
200
- const matrix = orthographic ? new import_core2.Matrix4().orthographic({ fovy: fovyRadians, aspect, focalDistance, near, far }) : new import_core2.Matrix4().perspective({ fovy: fovyRadians, aspect, near, far });
201
- if (padding) {
202
- const { left = 0, right = 0, top = 0, bottom = 0 } = padding;
203
- const offsetX = (0, import_core2.clamp)((left + width - right) / 2, 0, width) - width / 2;
204
- const offsetY = (0, import_core2.clamp)((top + height - bottom) / 2, 0, height) - height / 2;
205
- matrix[8] -= offsetX * 2 / width;
206
- matrix[9] += offsetY * 2 / height;
207
- }
208
- return matrix;
209
- }
210
- var _Viewport = class _Viewport {
211
- // eslint-disable-next-line complexity
212
- constructor(opts = {}) {
213
- this._frustumPlanes = {};
214
- this.id = opts.id || this.constructor.displayName || "viewport";
215
- this.x = opts.x || 0;
216
- this.y = opts.y || 0;
217
- this.width = opts.width || 1;
218
- this.height = opts.height || 1;
219
- this.zoom = opts.zoom || 0;
220
- this.padding = opts.padding;
221
- this.distanceScales = opts.distanceScales || DEFAULT_DISTANCE_SCALES;
222
- this.focalDistance = opts.focalDistance || 1;
223
- this.position = opts.position || ZERO_VECTOR;
224
- this.modelMatrix = opts.modelMatrix || null;
225
- const { longitude, latitude } = opts;
226
- this.isGeospatial = Number.isFinite(latitude) && Number.isFinite(longitude);
227
- this._initProps(opts);
228
- this._initMatrices(opts);
229
- this.equals = this.equals.bind(this);
230
- this.project = this.project.bind(this);
231
- this.unproject = this.unproject.bind(this);
232
- this.projectPosition = this.projectPosition.bind(this);
233
- this.unprojectPosition = this.unprojectPosition.bind(this);
234
- this.projectFlat = this.projectFlat.bind(this);
235
- this.unprojectFlat = this.unprojectFlat.bind(this);
236
- }
237
- get subViewports() {
238
- return null;
239
- }
240
- get metersPerPixel() {
241
- return this.distanceScales.metersPerUnit[2] / this.scale;
242
- }
243
- get projectionMode() {
244
- if (this.isGeospatial) {
245
- return this.zoom < 12 ? PROJECTION_MODE.WEB_MERCATOR : PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET;
246
- }
247
- return PROJECTION_MODE.IDENTITY;
248
- }
249
- // Two viewports are equal if width and height are identical, and if
250
- // their view and projection matrices are (approximately) equal.
251
- equals(viewport) {
252
- if (!(viewport instanceof _Viewport)) {
253
- return false;
254
- }
255
- if (this === viewport) {
256
- return true;
257
- }
258
- return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && (0, import_core2.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core2.equals)(viewport.viewMatrix, this.viewMatrix);
259
- }
260
- /**
261
- * Projects xyz (possibly latitude and longitude) to pixel coordinates in window
262
- * using viewport projection parameters
263
- * - [longitude, latitude] to [x, y]
264
- * - [longitude, latitude, Z] => [x, y, z]
265
- * Note: By default, returns top-left coordinates for canvas/SVG type render
266
- *
267
- * @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
268
- * @param {Object} opts - options
269
- * @param {Object} opts.topLeft=true - Whether projected coords are top left
270
- * @return {Array} - [x, y] or [x, y, z] in top left coords
271
- */
272
- project(xyz, { topLeft = true } = {}) {
273
- const worldPosition = this.projectPosition(xyz);
274
- const coord = (0, import_web_mercator.worldToPixels)(worldPosition, this.pixelProjectionMatrix);
275
- const [x, y] = coord;
276
- const y2 = topLeft ? y : this.height - y;
277
- return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]];
278
- }
279
- /**
280
- * Unproject pixel coordinates on screen onto world coordinates,
281
- * (possibly [lon, lat]) on map.
282
- * - [x, y] => [lng, lat]
283
- * - [x, y, z] => [lng, lat, Z]
284
- * @param {Array} xyz -
285
- * @param {Object} opts - options
286
- * @param {Object} opts.topLeft=true - Whether origin is top left
287
- * @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
288
- */
289
- unproject(xyz, { topLeft = true, targetZ } = {}) {
290
- const [x, y, z] = xyz;
291
- const y2 = topLeft ? y : this.height - y;
292
- const targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2];
293
- const coord = (0, import_web_mercator.pixelsToWorld)([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld);
294
- const [X, Y, Z] = this.unprojectPosition(coord);
295
- if (Number.isFinite(z)) {
296
- return [X, Y, Z];
297
- }
298
- return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
299
- }
300
- // NON_LINEAR PROJECTION HOOKS
301
- // Used for web meractor projection
302
- projectPosition(xyz) {
303
- const [X, Y] = this.projectFlat(xyz);
304
- const Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2];
305
- return [X, Y, Z];
306
- }
307
- unprojectPosition(xyz) {
308
- const [X, Y] = this.unprojectFlat(xyz);
309
- const Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2];
310
- return [X, Y, Z];
311
- }
312
- /**
313
- * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
314
- * Performs the nonlinear part of the web mercator projection.
315
- * Remaining projection is done with 4x4 matrices which also handles
316
- * perspective.
317
- * @param {Array} lngLat - [lng, lat] coordinates
318
- * Specifies a point on the sphere to project onto the map.
319
- * @return {Array} [x,y] coordinates.
320
- */
321
- projectFlat(xyz) {
322
- if (this.isGeospatial) {
323
- const result = (0, import_web_mercator.lngLatToWorld)(xyz);
324
- result[1] = (0, import_core2.clamp)(result[1], -318, 830);
325
- return result;
326
- }
327
- return xyz;
328
- }
329
- /**
330
- * Unproject world point [x,y] on map onto {lat, lon} on sphere
331
- * @param {object|Vector} xy - object with {x,y} members
332
- * representing point on projected map plane
333
- * @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
334
- * Has toArray method if you need a GeoJSON Array.
335
- * Per cartographic tradition, lat and lon are specified as degrees.
336
- */
337
- unprojectFlat(xyz) {
338
- if (this.isGeospatial) {
339
- return (0, import_web_mercator.worldToLngLat)(xyz);
340
- }
341
- return xyz;
342
- }
343
- /**
344
- * Get bounds of the current viewport
345
- * @return {Array} - [minX, minY, maxX, maxY]
346
- */
347
- getBounds(options = {}) {
348
- const unprojectOption = { targetZ: options.z || 0 };
349
- const topLeft = this.unproject([0, 0], unprojectOption);
350
- const topRight = this.unproject([this.width, 0], unprojectOption);
351
- const bottomLeft = this.unproject([0, this.height], unprojectOption);
352
- const bottomRight = this.unproject([this.width, this.height], unprojectOption);
353
- return [
354
- Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
355
- Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]),
356
- Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
357
- Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1])
358
- ];
359
- }
360
- getDistanceScales(coordinateOrigin) {
361
- if (coordinateOrigin && this.isGeospatial) {
362
- return (0, import_web_mercator.getDistanceScales)({
363
- longitude: coordinateOrigin[0],
364
- latitude: coordinateOrigin[1],
365
- highPrecision: true
366
- });
367
- }
368
- return this.distanceScales;
369
- }
370
- containsPixel({
371
- x,
372
- y,
373
- width = 1,
374
- height = 1
375
- }) {
376
- return x < this.x + this.width && this.x < x + width && y < this.y + this.height && this.y < y + height;
377
- }
378
- // Extract frustum planes in common space
379
- getFrustumPlanes() {
380
- if (this._frustumPlanes.near) {
381
- return this._frustumPlanes;
382
- }
383
- Object.assign(this._frustumPlanes, getFrustumPlanes(this.viewProjectionMatrix));
384
- return this._frustumPlanes;
385
- }
386
- // EXPERIMENTAL METHODS
387
- /**
388
- * Needed by panning and linear transition
389
- * Pan the viewport to place a given world coordinate at screen point [x, y]
390
- *
391
- * @param {Array} coords - world coordinates
392
- * @param {Array} pixel - [x,y] coordinates on screen
393
- * @param {Array} startPixel - [x,y] screen position where pan started (optional, for delta-based panning)
394
- * @return {Object} props of the new viewport
395
- */
396
- panByPosition(coords, pixel, startPixel) {
397
- return null;
398
- }
399
- // INTERNAL METHODS
400
- /* eslint-disable complexity, max-statements */
401
- _initProps(opts) {
402
- const longitude = opts.longitude;
403
- const latitude = opts.latitude;
404
- if (this.isGeospatial) {
405
- if (!Number.isFinite(opts.zoom)) {
406
- this.zoom = (0, import_web_mercator.getMeterZoom)({ latitude }) + Math.log2(this.focalDistance);
407
- }
408
- this.distanceScales = opts.distanceScales || (0, import_web_mercator.getDistanceScales)({ latitude, longitude });
409
- }
410
- const scale = Math.pow(2, this.zoom);
411
- this.scale = scale;
412
- const { position, modelMatrix } = opts;
413
- let meterOffset = ZERO_VECTOR;
414
- if (position) {
415
- meterOffset = modelMatrix ? new import_core2.Matrix4(modelMatrix).transformAsVector(position, []) : position;
416
- }
417
- if (this.isGeospatial) {
418
- const center = this.projectPosition([longitude, latitude, 0]);
419
- this.center = new import_core2.Vector3(meterOffset).scale(this.distanceScales.unitsPerMeter).add(center);
420
- } else {
421
- this.center = this.projectPosition(meterOffset);
422
- }
423
- }
424
- /* eslint-enable complexity, max-statements */
425
- _initMatrices(opts) {
426
- const {
427
- // View matrix
428
- viewMatrix: viewMatrix2 = IDENTITY,
429
- // Projection matrix
430
- projectionMatrix = null,
431
- // Projection matrix parameters, used if projectionMatrix not supplied
432
- orthographic = false,
433
- fovyRadians,
434
- fovy = 75,
435
- near = 0.1,
436
- // Distance of near clipping plane
437
- far = 1e3,
438
- // Distance of far clipping plane
439
- padding = null,
440
- // Center offset in pixels
441
- focalDistance = 1
442
- } = opts;
443
- this.viewMatrixUncentered = viewMatrix2;
444
- this.viewMatrix = new import_core2.Matrix4().multiplyRight(viewMatrix2).translate(new import_core2.Vector3(this.center).negate());
445
- this.projectionMatrix = projectionMatrix || createProjectionMatrix({
446
- width: this.width,
447
- height: this.height,
448
- orthographic,
449
- fovyRadians: fovyRadians || fovy * DEGREES_TO_RADIANS,
450
- focalDistance,
451
- padding,
452
- near,
453
- far
454
- });
455
- const vpm = createMat4();
456
- import_core2.mat4.multiply(vpm, vpm, this.projectionMatrix);
457
- import_core2.mat4.multiply(vpm, vpm, this.viewMatrix);
458
- this.viewProjectionMatrix = vpm;
459
- this.viewMatrixInverse = import_core2.mat4.invert([], this.viewMatrix) || this.viewMatrix;
460
- this.cameraPosition = getCameraPosition(this.viewMatrixInverse);
461
- const viewportMatrix = createMat4();
462
- const pixelProjectionMatrix = createMat4();
463
- import_core2.mat4.scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
464
- import_core2.mat4.translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
465
- import_core2.mat4.multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
466
- this.pixelProjectionMatrix = pixelProjectionMatrix;
467
- this.pixelUnprojectionMatrix = import_core2.mat4.invert(createMat4(), this.pixelProjectionMatrix);
468
- if (!this.pixelUnprojectionMatrix) {
469
- log_default.warn("Pixel project matrix not invertible")();
470
- }
471
- }
472
- };
473
- _Viewport.displayName = "Viewport";
474
- var Viewport = _Viewport;
475
-
476
- // ../core/src/viewports/web-mercator-viewport.ts
477
- var import_web_mercator2 = require("@math.gl/web-mercator");
478
- var import_core3 = require("@math.gl/core");
479
- var _WebMercatorViewport = class _WebMercatorViewport extends Viewport {
480
- /* eslint-disable complexity, max-statements */
481
- constructor(opts = {}) {
482
- const {
483
- latitude = 0,
484
- longitude = 0,
485
- zoom = 0,
486
- pitch = 0,
487
- bearing = 0,
488
- nearZMultiplier = 0.1,
489
- farZMultiplier = 1.01,
490
- nearZ,
491
- farZ,
492
- orthographic = false,
493
- projectionMatrix,
494
- repeat = false,
495
- worldOffset = 0,
496
- position,
497
- padding,
498
- // backward compatibility
499
- // TODO: remove in v9
500
- legacyMeterSizes = false
501
- } = opts;
502
- let { width, height, altitude = 1.5 } = opts;
503
- const scale = Math.pow(2, zoom);
504
- width = width || 1;
505
- height = height || 1;
506
- let fovy;
507
- let projectionParameters = null;
508
- if (projectionMatrix) {
509
- altitude = projectionMatrix[5] / 2;
510
- fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
511
- } else {
512
- if (opts.fovy) {
513
- fovy = opts.fovy;
514
- altitude = (0, import_web_mercator2.fovyToAltitude)(fovy);
515
- } else {
516
- fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
517
- }
518
- let offset3;
519
- if (padding) {
520
- const { top = 0, bottom = 0 } = padding;
521
- offset3 = [0, (0, import_core3.clamp)((top + height - bottom) / 2, 0, height) - height / 2];
522
- }
523
- projectionParameters = (0, import_web_mercator2.getProjectionParameters)({
524
- width,
525
- height,
526
- scale,
527
- center: position && [0, 0, position[2] * (0, import_web_mercator2.unitsPerMeter)(latitude)],
528
- offset: offset3,
529
- pitch,
530
- fovy,
531
- nearZMultiplier,
532
- farZMultiplier
533
- });
534
- if (Number.isFinite(nearZ)) {
535
- projectionParameters.near = nearZ;
536
- }
537
- if (Number.isFinite(farZ)) {
538
- projectionParameters.far = farZ;
539
- }
540
- }
541
- let viewMatrixUncentered = (0, import_web_mercator2.getViewMatrix)({
542
- height,
543
- pitch,
544
- bearing,
545
- scale,
546
- altitude
547
- });
548
- if (worldOffset) {
549
- const viewOffset = new import_core3.Matrix4().translate([512 * worldOffset, 0, 0]);
550
- viewMatrixUncentered = viewOffset.multiplyLeft(viewMatrixUncentered);
551
- }
552
- super({
553
- ...opts,
554
- // x, y,
555
- width,
556
- height,
557
- // view matrix
558
- viewMatrix: viewMatrixUncentered,
559
- longitude,
560
- latitude,
561
- zoom,
562
- // projection matrix parameters
563
- ...projectionParameters,
564
- fovy,
565
- focalDistance: altitude
566
- });
567
- this.latitude = latitude;
568
- this.longitude = longitude;
569
- this.zoom = zoom;
570
- this.pitch = pitch;
571
- this.bearing = bearing;
572
- this.altitude = altitude;
573
- this.fovy = fovy;
574
- this.orthographic = orthographic;
575
- this._subViewports = repeat ? [] : null;
576
- this._pseudoMeters = legacyMeterSizes;
577
- Object.freeze(this);
578
- }
579
- /* eslint-enable complexity, max-statements */
580
- get subViewports() {
581
- if (this._subViewports && !this._subViewports.length) {
582
- const bounds = this.getBounds();
583
- const minOffset = Math.floor((bounds[0] + 180) / 360);
584
- const maxOffset = Math.ceil((bounds[2] - 180) / 360);
585
- for (let x = minOffset; x <= maxOffset; x++) {
586
- const offsetViewport = x ? new _WebMercatorViewport({
587
- ...this,
588
- worldOffset: x
589
- }) : this;
590
- this._subViewports.push(offsetViewport);
591
- }
592
- }
593
- return this._subViewports;
594
- }
595
- projectPosition(xyz) {
596
- if (this._pseudoMeters) {
597
- return super.projectPosition(xyz);
598
- }
599
- const [X, Y] = this.projectFlat(xyz);
600
- const Z = (xyz[2] || 0) * (0, import_web_mercator2.unitsPerMeter)(xyz[1]);
601
- return [X, Y, Z];
602
- }
603
- unprojectPosition(xyz) {
604
- if (this._pseudoMeters) {
605
- return super.unprojectPosition(xyz);
606
- }
607
- const [X, Y] = this.unprojectFlat(xyz);
608
- const Z = (xyz[2] || 0) / (0, import_web_mercator2.unitsPerMeter)(Y);
609
- return [X, Y, Z];
610
- }
611
- /**
612
- * Add a meter delta to a base lnglat coordinate, returning a new lnglat array
613
- *
614
- * Note: Uses simple linear approximation around the viewport center
615
- * Error increases with size of offset (roughly 1% per 100km)
616
- *
617
- * @param {[Number,Number]|[Number,Number,Number]) lngLatZ - base coordinate
618
- * @param {[Number,Number]|[Number,Number,Number]) xyz - array of meter deltas
619
- * @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
620
- */
621
- addMetersToLngLat(lngLatZ, xyz) {
622
- return (0, import_web_mercator2.addMetersToLngLat)(lngLatZ, xyz);
623
- }
624
- panByPosition(coords, pixel, startPixel) {
625
- const fromLocation = (0, import_web_mercator2.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
626
- const toLocation = this.projectFlat(coords);
627
- const translate = import_core3.vec2.add([], toLocation, import_core3.vec2.negate([], fromLocation));
628
- const newCenter = import_core3.vec2.add([], this.center, translate);
629
- const [longitude, latitude] = this.unprojectFlat(newCenter);
630
- return { longitude, latitude };
631
- }
632
- /**
633
- * Returns a new longitude and latitude that keeps a 3D world coordinate at a given screen pixel
634
- * This version handles the z-component (altitude) properly for cameras positioned above ground
635
- */
636
- panByPosition3D(coords, pixel) {
637
- const targetZ = coords[2] || 0;
638
- const deltaLngLat = import_core3.vec2.sub([], coords, this.unproject(pixel, { targetZ }));
639
- return { longitude: this.longitude + deltaLngLat[0], latitude: this.latitude + deltaLngLat[1] };
640
- }
641
- getBounds(options = {}) {
642
- const corners = (0, import_web_mercator2.getBounds)(this, options.z || 0);
643
- return [
644
- Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
645
- Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]),
646
- Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
647
- Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])
648
- ];
649
- }
650
- /**
651
- * Returns a new viewport that fit around the given rectangle.
652
- * Only supports non-perspective mode.
653
- */
654
- fitBounds(bounds, options = {}) {
655
- const { width, height } = this;
656
- const { longitude, latitude, zoom } = (0, import_web_mercator2.fitBounds)({ width, height, bounds, ...options });
657
- return new _WebMercatorViewport({ width, height, longitude, latitude, zoom });
658
- }
659
- };
660
- _WebMercatorViewport.displayName = "WebMercatorViewport";
661
- var WebMercatorViewport = _WebMercatorViewport;
662
-
663
- // ../core/src/utils/deep-equal.ts
664
- function deepEqual(a, b, depth) {
665
- if (a === b) {
666
- return true;
667
- }
668
- if (!depth || !a || !b) {
669
- return false;
670
- }
671
- if (Array.isArray(a)) {
672
- if (!Array.isArray(b) || a.length !== b.length) {
673
- return false;
674
- }
675
- for (let i = 0; i < a.length; i++) {
676
- if (!deepEqual(a[i], b[i], depth - 1)) {
677
- return false;
678
- }
679
- }
680
- return true;
681
- }
682
- if (Array.isArray(b)) {
683
- return false;
684
- }
685
- if (typeof a === "object" && typeof b === "object") {
686
- const aKeys = Object.keys(a);
687
- const bKeys = Object.keys(b);
688
- if (aKeys.length !== bKeys.length) {
689
- return false;
690
- }
691
- for (const key of aKeys) {
692
- if (!b.hasOwnProperty(key)) {
693
- return false;
694
- }
695
- if (!deepEqual(a[key], b[key], depth - 1)) {
696
- return false;
697
- }
698
- }
699
- return true;
700
- }
701
- return false;
702
- }
703
-
704
- // ../core/src/utils/positions.ts
705
- var NUMBER_REGEX = /^(?:\d+\.?\d*|\.\d+)$/;
706
- function parsePosition(value) {
707
- switch (typeof value) {
708
- case "number":
709
- if (!Number.isFinite(value)) {
710
- throw new Error(`Could not parse position string ${value}`);
711
- }
712
- return { type: "literal", value };
713
- case "string":
714
- try {
715
- const tokens = tokenize(value);
716
- const parser = new LayoutExpressionParser(tokens);
717
- return parser.parseExpression();
718
- } catch (error) {
719
- const reason = error instanceof Error ? error.message : String(error);
720
- throw new Error(`Could not parse position string ${value}: ${reason}`);
721
- }
722
- default:
723
- throw new Error(`Could not parse position string ${value}`);
724
- }
725
- }
726
- function evaluateLayoutExpression(expression, extent) {
727
- switch (expression.type) {
728
- case "literal":
729
- return expression.value;
730
- case "percentage":
731
- return Math.round(expression.value * extent);
732
- case "binary":
733
- const left = evaluateLayoutExpression(expression.left, extent);
734
- const right = evaluateLayoutExpression(expression.right, extent);
735
- return expression.operator === "+" ? left + right : left - right;
736
- default:
737
- throw new Error("Unknown layout expression type");
738
- }
739
- }
740
- function getPosition(expression, extent) {
741
- return evaluateLayoutExpression(expression, extent);
742
- }
743
- function tokenize(input) {
744
- const tokens = [];
745
- let index = 0;
746
- while (index < input.length) {
747
- const char = input[index];
748
- if (/\s/.test(char)) {
749
- index++;
750
- continue;
751
- }
752
- if (char === "+" || char === "-" || char === "(" || char === ")" || char === "%") {
753
- tokens.push({ type: "symbol", value: char });
754
- index++;
755
- continue;
756
- }
757
- if (isDigit(char) || char === ".") {
758
- const start = index;
759
- let hasDecimal = char === ".";
760
- index++;
761
- while (index < input.length) {
762
- const next = input[index];
763
- if (isDigit(next)) {
764
- index++;
765
- continue;
766
- }
767
- if (next === "." && !hasDecimal) {
768
- hasDecimal = true;
769
- index++;
770
- continue;
771
- }
772
- break;
773
- }
774
- const numberString = input.slice(start, index);
775
- if (!NUMBER_REGEX.test(numberString)) {
776
- throw new Error("Invalid number token");
777
- }
778
- tokens.push({ type: "number", value: parseFloat(numberString) });
779
- continue;
780
- }
781
- if (isAlpha(char)) {
782
- const start = index;
783
- while (index < input.length && isAlpha(input[index])) {
784
- index++;
785
- }
786
- const word = input.slice(start, index).toLowerCase();
787
- tokens.push({ type: "word", value: word });
788
- continue;
789
- }
790
- throw new Error("Invalid token in position string");
791
- }
792
- return tokens;
793
- }
794
- var LayoutExpressionParser = class {
795
- constructor(tokens) {
796
- this.index = 0;
797
- this.tokens = tokens;
798
- }
799
- parseExpression() {
800
- const expression = this.parseBinaryExpression();
801
- if (this.index < this.tokens.length) {
802
- throw new Error("Unexpected token at end of expression");
803
- }
804
- return expression;
805
- }
806
- parseBinaryExpression() {
807
- let expression = this.parseFactor();
808
- let token = this.peek();
809
- while (isAddSubSymbol(token)) {
810
- this.index++;
811
- const right = this.parseFactor();
812
- expression = { type: "binary", operator: token.value, left: expression, right };
813
- token = this.peek();
814
- }
815
- return expression;
816
- }
817
- parseFactor() {
818
- const token = this.peek();
819
- if (!token) {
820
- throw new Error("Unexpected end of expression");
821
- }
822
- if (token.type === "symbol" && token.value === "+") {
823
- this.index++;
824
- return this.parseFactor();
825
- }
826
- if (token.type === "symbol" && token.value === "-") {
827
- this.index++;
828
- const factor = this.parseFactor();
829
- return { type: "binary", operator: "-", left: { type: "literal", value: 0 }, right: factor };
830
- }
831
- if (token.type === "symbol" && token.value === "(") {
832
- this.index++;
833
- const expression = this.parseBinaryExpression();
834
- if (!this.consumeSymbol(")")) {
835
- throw new Error("Missing closing parenthesis");
836
- }
837
- return expression;
838
- }
839
- if (token.type === "word" && token.value === "calc") {
840
- this.index++;
841
- if (!this.consumeSymbol("(")) {
842
- throw new Error("Missing opening parenthesis after calc");
843
- }
844
- const expression = this.parseBinaryExpression();
845
- if (!this.consumeSymbol(")")) {
846
- throw new Error("Missing closing parenthesis");
847
- }
848
- return expression;
849
- }
850
- if (token.type === "number") {
851
- this.index++;
852
- const numberValue = token.value;
853
- const nextToken = this.peek();
854
- if (nextToken && nextToken.type === "symbol" && nextToken.value === "%") {
855
- this.index++;
856
- return { type: "percentage", value: numberValue / 100 };
857
- }
858
- if (nextToken && nextToken.type === "word" && nextToken.value === "px") {
859
- this.index++;
860
- return { type: "literal", value: numberValue };
861
- }
862
- return { type: "literal", value: numberValue };
863
- }
864
- throw new Error("Unexpected token in expression");
865
- }
866
- consumeSymbol(value) {
867
- const token = this.peek();
868
- if (token && token.type === "symbol" && token.value === value) {
869
- this.index++;
870
- return true;
871
- }
872
- return false;
873
- }
874
- peek() {
875
- return this.tokens[this.index] || null;
876
- }
877
- };
878
- function isDigit(char) {
879
- return char >= "0" && char <= "9";
880
- }
881
- function isAlpha(char) {
882
- return char >= "a" && char <= "z" || char >= "A" && char <= "Z";
883
- }
884
- function isAddSubSymbol(token) {
885
- return Boolean(token && token.type === "symbol" && (token.value === "+" || token.value === "-"));
886
- }
887
-
888
- // ../core/src/utils/deep-merge.ts
889
- function deepMergeViewState(a, b) {
890
- const result = { ...a };
891
- for (const key in b) {
892
- if (key === "id") continue;
893
- if (Array.isArray(result[key]) && Array.isArray(b[key])) {
894
- result[key] = mergeNumericArray(result[key], b[key]);
895
- } else {
896
- result[key] = b[key];
897
- }
898
- }
899
- return result;
900
- }
901
- function mergeNumericArray(target, source) {
902
- target = target.slice();
903
- for (let i = 0; i < source.length; i++) {
904
- const v = source[i];
905
- if (Number.isFinite(v)) {
906
- target[i] = v;
907
- }
908
- }
909
- return target;
910
- }
911
-
912
- // ../core/src/views/view.ts
913
- var View = class {
914
- constructor(props) {
915
- const { id, x = 0, y = 0, width = "100%", height = "100%", padding = null } = props;
916
- this.id = id || this.constructor.displayName || "view";
917
- this.props = { ...props, id: this.id };
918
- this._x = parsePosition(x);
919
- this._y = parsePosition(y);
920
- this._width = parsePosition(width);
921
- this._height = parsePosition(height);
922
- this._padding = padding && {
923
- left: parsePosition(padding.left || 0),
924
- right: parsePosition(padding.right || 0),
925
- top: parsePosition(padding.top || 0),
926
- bottom: parsePosition(padding.bottom || 0)
927
- };
928
- this.equals = this.equals.bind(this);
929
- Object.seal(this);
930
- }
931
- equals(view) {
932
- if (this === view) {
933
- return true;
934
- }
935
- return this.constructor === view.constructor && deepEqual(this.props, view.props, 2);
936
- }
937
- /** Clone this view with modified props */
938
- clone(newProps) {
939
- const ViewConstructor = this.constructor;
940
- return new ViewConstructor({ ...this.props, ...newProps });
941
- }
942
- /** Make viewport from canvas dimensions and view state */
943
- makeViewport({ width, height, viewState }) {
944
- viewState = this.filterViewState(viewState);
945
- const viewportDimensions = this.getDimensions({ width, height });
946
- if (!viewportDimensions.height || !viewportDimensions.width) {
947
- return null;
948
- }
949
- const ViewportType = this.getViewportType(viewState);
950
- return new ViewportType({ ...viewState, ...this.props, ...viewportDimensions });
951
- }
952
- getViewStateId() {
953
- const { viewState } = this.props;
954
- if (typeof viewState === "string") {
955
- return viewState;
956
- }
957
- return (viewState == null ? void 0 : viewState.id) || this.id;
958
- }
959
- // Allows view to override (or completely define) viewState
960
- filterViewState(viewState) {
961
- if (this.props.viewState && typeof this.props.viewState === "object") {
962
- if (!this.props.viewState.id) {
963
- return this.props.viewState;
964
- }
965
- return deepMergeViewState(viewState, this.props.viewState);
966
- }
967
- return viewState;
968
- }
969
- /** Resolve the dimensions of the view from overall canvas dimensions */
970
- getDimensions({ width, height }) {
971
- const dimensions = {
972
- x: getPosition(this._x, width),
973
- y: getPosition(this._y, height),
974
- width: getPosition(this._width, width),
975
- height: getPosition(this._height, height)
976
- };
977
- if (this._padding) {
978
- dimensions.padding = {
979
- left: getPosition(this._padding.left, width),
980
- top: getPosition(this._padding.top, height),
981
- right: getPosition(this._padding.right, width),
982
- bottom: getPosition(this._padding.bottom, height)
983
- };
984
- }
985
- return dimensions;
986
- }
987
- // Used by sub classes to resolve controller props
988
- get controller() {
989
- const opts = this.props.controller;
990
- if (!opts) {
991
- return null;
992
- }
993
- if (opts === true) {
994
- return { type: this.ControllerType };
995
- }
996
- if (typeof opts === "function") {
997
- return { type: opts };
998
- }
999
- return { type: this.ControllerType, ...opts };
1000
- }
1001
- };
1002
-
1003
- // ../core/src/transitions/transition.ts
1004
- var Transition = class {
1005
- /**
1006
- * @params timeline {Timeline}
1007
- */
1008
- constructor(timeline) {
1009
- this._inProgress = false;
1010
- this._handle = null;
1011
- this.time = 0;
1012
- // @ts-expect-error
1013
- this.settings = {
1014
- duration: 0
1015
- };
1016
- this._timeline = timeline;
1017
- }
1018
- /* Public API */
1019
- get inProgress() {
1020
- return this._inProgress;
1021
- }
1022
- /**
1023
- * (re)start this transition.
1024
- * @params props {object} - optional overriding props. see constructor
1025
- */
1026
- start(settings) {
1027
- var _a, _b;
1028
- this.cancel();
1029
- this.settings = settings;
1030
- this._inProgress = true;
1031
- (_b = (_a = this.settings).onStart) == null ? void 0 : _b.call(_a, this);
1032
- }
1033
- /**
1034
- * end this transition if it is in progress.
1035
- */
1036
- end() {
1037
- var _a, _b;
1038
- if (this._inProgress) {
1039
- this._timeline.removeChannel(this._handle);
1040
- this._handle = null;
1041
- this._inProgress = false;
1042
- (_b = (_a = this.settings).onEnd) == null ? void 0 : _b.call(_a, this);
1043
- }
1044
- }
1045
- /**
1046
- * cancel this transition if it is in progress.
1047
- */
1048
- cancel() {
1049
- var _a, _b;
1050
- if (this._inProgress) {
1051
- (_b = (_a = this.settings).onInterrupt) == null ? void 0 : _b.call(_a, this);
1052
- this._timeline.removeChannel(this._handle);
1053
- this._handle = null;
1054
- this._inProgress = false;
1055
- }
1056
- }
1057
- /**
1058
- * update this transition. Returns `true` if updated.
1059
- */
1060
- update() {
1061
- var _a, _b;
1062
- if (!this._inProgress) {
1063
- return false;
1064
- }
1065
- if (this._handle === null) {
1066
- const { _timeline: timeline, settings } = this;
1067
- this._handle = timeline.addChannel({
1068
- delay: timeline.getTime(),
1069
- duration: settings.duration
1070
- });
1071
- }
1072
- this.time = this._timeline.getTime(this._handle);
1073
- this._onUpdate();
1074
- (_b = (_a = this.settings).onUpdate) == null ? void 0 : _b.call(_a, this);
1075
- if (this._timeline.isFinished(this._handle)) {
1076
- this.end();
1077
- }
1078
- return true;
1079
- }
1080
- /* Private API */
1081
- _onUpdate() {
1082
- }
1083
- };
1084
-
1085
- // ../core/src/controllers/transition-manager.ts
1086
- var noop = () => {
1087
- };
1088
- var PRESERVE_CONSTRAINT_CONTEXT = { mode: "preserve" };
1089
- var HARD_CONSTRAINT_CONTEXT = { mode: "hard" };
1090
- var TRANSITION_EVENTS = {
1091
- BREAK: 1,
1092
- SNAP_TO_END: 2,
1093
- IGNORE: 3
1094
- };
1095
- var DEFAULT_EASING = (t) => t;
1096
- var DEFAULT_INTERRUPTION = TRANSITION_EVENTS.BREAK;
1097
- var TransitionManager = class {
1098
- constructor(opts) {
1099
- this._onTransitionUpdate = (transition) => {
1100
- const {
1101
- time,
1102
- settings: { interpolator, startProps, endProps, duration, easing }
1103
- } = transition;
1104
- const t = easing(time / duration);
1105
- const viewport = interpolator.interpolateProps(startProps, endProps, t);
1106
- this.propsInTransition = this.getControllerState(
1107
- {
1108
- ...this.props,
1109
- ...viewport
1110
- },
1111
- PRESERVE_CONSTRAINT_CONTEXT
1112
- ).getViewportProps();
1113
- this.onViewStateChange({
1114
- viewState: this.propsInTransition,
1115
- oldViewState: this.props
1116
- });
1117
- };
1118
- this.getControllerState = opts.getControllerState;
1119
- this.propsInTransition = null;
1120
- this.transition = new Transition(opts.timeline);
1121
- this.onViewStateChange = opts.onViewStateChange || noop;
1122
- this.onStateChange = opts.onStateChange || noop;
1123
- }
1124
- finalize() {
1125
- this.transition.cancel();
1126
- }
1127
- // Returns current transitioned viewport.
1128
- getViewportInTransition() {
1129
- return this.propsInTransition;
1130
- }
1131
- // Process the vewiport change, either ignore or trigger a new transition.
1132
- // Return true if a new transition is triggered, false otherwise.
1133
- processViewStateChange(nextProps) {
1134
- let transitionTriggered = false;
1135
- const currentProps = this.props;
1136
- this.props = nextProps;
1137
- if (!currentProps || this._shouldIgnoreViewportChange(currentProps, nextProps)) {
1138
- return false;
1139
- }
1140
- if (this._isTransitionEnabled(nextProps)) {
1141
- let startProps = currentProps;
1142
- if (this.transition.inProgress) {
1143
- const { interruption, endProps } = this.transition.settings;
1144
- startProps = {
1145
- ...currentProps,
1146
- ...interruption === TRANSITION_EVENTS.SNAP_TO_END ? endProps : this.propsInTransition || currentProps
1147
- };
1148
- }
1149
- this._triggerTransition(startProps, nextProps);
1150
- transitionTriggered = true;
1151
- } else {
1152
- this.transition.cancel();
1153
- }
1154
- return transitionTriggered;
1155
- }
1156
- updateTransition() {
1157
- this.transition.update();
1158
- }
1159
- // Helper methods
1160
- _isTransitionEnabled(props) {
1161
- const { transitionDuration, transitionInterpolator } = props;
1162
- return (transitionDuration > 0 || transitionDuration === "auto") && Boolean(transitionInterpolator);
1163
- }
1164
- _isUpdateDueToCurrentTransition(props) {
1165
- if (this.transition.inProgress && this.propsInTransition) {
1166
- return this.transition.settings.interpolator.arePropsEqual(
1167
- props,
1168
- this.propsInTransition
1169
- );
1170
- }
1171
- return false;
1172
- }
1173
- _shouldIgnoreViewportChange(currentProps, nextProps) {
1174
- if (this.transition.inProgress) {
1175
- const transitionSettings = this.transition.settings;
1176
- return transitionSettings.interruption === TRANSITION_EVENTS.IGNORE || // Ignore update if it is due to current active transition.
1177
- this._isUpdateDueToCurrentTransition(nextProps);
1178
- }
1179
- if (this._isTransitionEnabled(nextProps)) {
1180
- return nextProps.transitionInterpolator.arePropsEqual(
1181
- currentProps,
1182
- nextProps
1183
- );
1184
- }
1185
- return true;
1186
- }
1187
- _triggerTransition(startProps, endProps) {
1188
- const startViewstate = this.getControllerState(startProps, PRESERVE_CONSTRAINT_CONTEXT);
1189
- const endViewStateProps = this.getControllerState(
1190
- endProps,
1191
- HARD_CONSTRAINT_CONTEXT
1192
- ).shortestPathFrom(startViewstate);
1193
- const transitionInterpolator = endProps.transitionInterpolator;
1194
- const duration = transitionInterpolator.getDuration ? transitionInterpolator.getDuration(startProps, endProps) : endProps.transitionDuration;
1195
- if (duration === 0) {
1196
- return;
1197
- }
1198
- const initialProps = transitionInterpolator.initializeProps(startProps, endViewStateProps);
1199
- this.propsInTransition = {};
1200
- const transitionSettings = {
1201
- duration,
1202
- easing: endProps.transitionEasing || DEFAULT_EASING,
1203
- interpolator: transitionInterpolator,
1204
- interruption: endProps.transitionInterruption || DEFAULT_INTERRUPTION,
1205
- startProps: initialProps.start,
1206
- endProps: initialProps.end,
1207
- onStart: endProps.onTransitionStart,
1208
- onUpdate: this._onTransitionUpdate,
1209
- onInterrupt: this._onTransitionEnd(endProps.onTransitionInterrupt),
1210
- onEnd: this._onTransitionEnd(endProps.onTransitionEnd)
1211
- };
1212
- this.transition.start(transitionSettings);
1213
- this.onStateChange({ inTransition: true });
1214
- this.updateTransition();
1215
- }
1216
- _onTransitionEnd(callback) {
1217
- return (transition) => {
1218
- this.propsInTransition = null;
1219
- this.onStateChange({
1220
- inTransition: false,
1221
- isZooming: false,
1222
- isPanning: false,
1223
- isRotating: false
1224
- });
1225
- callback == null ? void 0 : callback(transition);
1226
- };
1227
- }
1228
- };
1229
-
1230
- // ../core/src/transitions/transition-interpolator.ts
1231
- var import_core4 = require("@math.gl/core");
1232
-
1233
- // ../core/src/utils/assert.ts
1234
- function assert(condition, message) {
1235
- if (!condition) {
1236
- throw new Error(message || "deck.gl: assertion failed.");
1237
- }
1238
- }
1239
-
1240
- // ../core/src/transitions/transition-interpolator.ts
1241
- var TransitionInterpolator = class {
1242
- /**
1243
- * @param opts {array|object}
1244
- * @param opts.compare {array} - prop names used in equality check
1245
- * @param opts.extract {array} - prop names needed for interpolation
1246
- * @param opts.required {array} - prop names that must be supplied
1247
- * alternatively, supply one list of prop names as `opts` if all of the above are the same.
1248
- */
1249
- constructor(opts) {
1250
- const { compare, extract, required } = opts;
1251
- this._propsToCompare = compare;
1252
- this._propsToExtract = extract || compare;
1253
- this._requiredProps = required;
1254
- }
1255
- /**
1256
- * Checks if two sets of props need transition in between
1257
- * @param currentProps {object} - a list of viewport props
1258
- * @param nextProps {object} - a list of viewport props
1259
- * @returns {bool} - true if two props are equivalent
1260
- */
1261
- arePropsEqual(currentProps, nextProps) {
1262
- for (const key of this._propsToCompare) {
1263
- if (!(key in currentProps) || !(key in nextProps) || !(0, import_core4.equals)(currentProps[key], nextProps[key])) {
1264
- return false;
1265
- }
1266
- }
1267
- return true;
1268
- }
1269
- /**
1270
- * Called before transition starts to validate/pre-process start and end props
1271
- * @param startProps {object} - a list of starting viewport props
1272
- * @param endProps {object} - a list of target viewport props
1273
- * @returns {Object} {start, end} - start and end props to be passed
1274
- * to `interpolateProps`
1275
- */
1276
- initializeProps(startProps, endProps) {
1277
- const startViewStateProps = {};
1278
- const endViewStateProps = {};
1279
- for (const key of this._propsToExtract) {
1280
- if (key in startProps || key in endProps) {
1281
- startViewStateProps[key] = startProps[key];
1282
- endViewStateProps[key] = endProps[key];
1283
- }
1284
- }
1285
- this._checkRequiredProps(startViewStateProps);
1286
- this._checkRequiredProps(endViewStateProps);
1287
- return { start: startViewStateProps, end: endViewStateProps };
1288
- }
1289
- /**
1290
- * Returns transition duration
1291
- * @param startProps {object} - a list of starting viewport props
1292
- * @param endProps {object} - a list of target viewport props
1293
- * @returns {Number} - transition duration in milliseconds
1294
- */
1295
- getDuration(startProps, endProps) {
1296
- return endProps.transitionDuration;
1297
- }
1298
- _checkRequiredProps(props) {
1299
- if (!this._requiredProps) {
1300
- return;
1301
- }
1302
- this._requiredProps.forEach((propName) => {
1303
- const value = props[propName];
1304
- assert(
1305
- Number.isFinite(value) || Array.isArray(value),
1306
- `${propName} is required for transition`
1307
- );
1308
- });
1309
- }
1310
- };
1311
-
1312
- // ../core/src/transitions/linear-interpolator.ts
1313
- var import_core7 = require("@math.gl/core");
1314
-
1315
- // ../core/src/viewports/globe-viewport.ts
1316
- var import_core5 = require("@math.gl/core");
1317
- var import_web_mercator3 = require("@math.gl/web-mercator");
1318
- var import_core6 = require("@math.gl/core");
1319
- var import_web_mercator4 = require("@math.gl/web-mercator");
1320
- var DEGREES_TO_RADIANS2 = Math.PI / 180;
1321
- var RADIANS_TO_DEGREES = 180 / Math.PI;
1322
- var EARTH_RADIUS = 6370972;
1323
- var GLOBE_RADIUS = 256;
1324
- function getDistanceScales2() {
1325
- const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
1326
- const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
1327
- return {
1328
- unitsPerMeter: [unitsPerMeter2, unitsPerMeter2, unitsPerMeter2],
1329
- unitsPerMeter2: [0, 0, 0],
1330
- metersPerUnit: [1 / unitsPerMeter2, 1 / unitsPerMeter2, 1 / unitsPerMeter2],
1331
- unitsPerDegree: [unitsPerDegree, unitsPerDegree, unitsPerMeter2],
1332
- unitsPerDegree2: [0, 0, 0],
1333
- degreesPerUnit: [1 / unitsPerDegree, 1 / unitsPerDegree, 1 / unitsPerMeter2]
1334
- };
1335
- }
1336
- var GlobeViewport = class extends Viewport {
1337
- constructor(opts = {}) {
1338
- const {
1339
- longitude = 0,
1340
- bearing = 0,
1341
- pitch = 0,
1342
- zoom = 0,
1343
- // Matches Maplibre defaults
1344
- // https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
1345
- nearZMultiplier = 0.5,
1346
- farZMultiplier = 1,
1347
- resolution = 10
1348
- } = opts;
1349
- let { latitude = 0, height, altitude = 1.5, fovy } = opts;
1350
- latitude = Math.max(Math.min(latitude, 90), -90);
1351
- height = height || 1;
1352
- if (fovy) {
1353
- altitude = (0, import_web_mercator3.fovyToAltitude)(fovy);
1354
- } else {
1355
- fovy = (0, import_web_mercator3.altitudeToFovy)(altitude);
1356
- }
1357
- const scaleLatitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
1358
- const scale = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
1359
- const pitchRadians = pitch * DEGREES_TO_RADIANS2;
1360
- const nearZ = opts.nearZ ?? nearZMultiplier;
1361
- const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale / height / Math.max(Math.cos(pitchRadians), 0.1)) * farZMultiplier;
1362
- const viewMatrix2 = new import_core5.Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] }).rotateX(-pitchRadians).rotateY(-bearing * DEGREES_TO_RADIANS2).rotateX(latitude * DEGREES_TO_RADIANS2).rotateZ(-longitude * DEGREES_TO_RADIANS2).scale(scale / height);
1363
- super({
1364
- ...opts,
1365
- // x, y, width,
1366
- height,
1367
- // view matrix
1368
- viewMatrix: viewMatrix2,
1369
- longitude,
1370
- latitude,
1371
- zoom,
1372
- // projection matrix parameters
1373
- distanceScales: getDistanceScales2(),
1374
- fovy,
1375
- focalDistance: altitude,
1376
- near: nearZ,
1377
- far: farZ
1378
- });
1379
- this.scale = scale;
1380
- this.latitude = latitude;
1381
- this.longitude = longitude;
1382
- this.bearing = bearing;
1383
- this.pitch = pitch;
1384
- this.fovy = fovy;
1385
- this.resolution = resolution;
1386
- }
1387
- get projectionMode() {
1388
- return PROJECTION_MODE.GLOBE;
1389
- }
1390
- getDistanceScales() {
1391
- return this.distanceScales;
1392
- }
1393
- getBounds(options = {}) {
1394
- const unprojectOption = { targetZ: options.z || 0 };
1395
- const left = this.unproject([0, this.height / 2], unprojectOption);
1396
- const top = this.unproject([this.width / 2, 0], unprojectOption);
1397
- const right = this.unproject([this.width, this.height / 2], unprojectOption);
1398
- const bottom = this.unproject([this.width / 2, this.height], unprojectOption);
1399
- if (right[0] < this.longitude) right[0] += 360;
1400
- if (left[0] > this.longitude) left[0] -= 360;
1401
- return [
1402
- Math.min(left[0], right[0], top[0], bottom[0]),
1403
- Math.min(left[1], right[1], top[1], bottom[1]),
1404
- Math.max(left[0], right[0], top[0], bottom[0]),
1405
- Math.max(left[1], right[1], top[1], bottom[1])
1406
- ];
1407
- }
1408
- unproject(xyz, { topLeft = true, targetZ } = {}) {
1409
- const [x, y, z] = xyz;
1410
- const y2 = topLeft ? y : this.height - y;
1411
- const { pixelUnprojectionMatrix } = this;
1412
- let coord;
1413
- if (Number.isFinite(z)) {
1414
- coord = transformVector(pixelUnprojectionMatrix, [x, y2, z, 1]);
1415
- } else {
1416
- const coord0 = transformVector(pixelUnprojectionMatrix, [x, y2, -1, 1]);
1417
- const coord1 = transformVector(pixelUnprojectionMatrix, [x, y2, 1, 1]);
1418
- const lt = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
1419
- const lSqr = import_core6.vec3.sqrLen(import_core6.vec3.sub([], coord0, coord1));
1420
- const l0Sqr = import_core6.vec3.sqrLen(coord0);
1421
- const l1Sqr = import_core6.vec3.sqrLen(coord1);
1422
- const sSqr = (4 * l0Sqr * l1Sqr - (lSqr - l0Sqr - l1Sqr) ** 2) / 16;
1423
- const dSqr = 4 * sSqr / lSqr;
1424
- const r0 = Math.sqrt(l0Sqr - dSqr);
1425
- const dr = Math.sqrt(Math.max(0, lt * lt - dSqr));
1426
- const t = (r0 - dr) / Math.sqrt(lSqr);
1427
- coord = import_core6.vec3.lerp([], coord0, coord1, t);
1428
- }
1429
- const [X, Y, Z] = this.unprojectPosition(coord);
1430
- if (Number.isFinite(z)) {
1431
- return [X, Y, Z];
1432
- }
1433
- return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
1434
- }
1435
- projectPosition(xyz) {
1436
- const [lng, lat, Z = 0] = xyz;
1437
- const lambda = lng * DEGREES_TO_RADIANS2;
1438
- const phi = lat * DEGREES_TO_RADIANS2;
1439
- const cosPhi = Math.cos(phi);
1440
- const D = (Z / EARTH_RADIUS + 1) * GLOBE_RADIUS;
1441
- return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D];
1442
- }
1443
- unprojectPosition(xyz) {
1444
- const [x, y, z] = xyz;
1445
- const D = import_core6.vec3.len(xyz);
1446
- const phi = Math.asin(z / D);
1447
- const lambda = Math.atan2(x, -y);
1448
- const lng = lambda * RADIANS_TO_DEGREES;
1449
- const lat = phi * RADIANS_TO_DEGREES;
1450
- const Z = (D / GLOBE_RADIUS - 1) * EARTH_RADIUS;
1451
- return [lng, lat, Z];
1452
- }
1453
- projectFlat(xyz) {
1454
- return xyz;
1455
- }
1456
- unprojectFlat(xyz) {
1457
- return xyz;
1458
- }
1459
- /**
1460
- * Pan the globe using delta-based movement
1461
- * @param coords - the geographic coordinates where the pan started
1462
- * @param pixel - the current screen position
1463
- * @param startPixel - the screen position where the pan started
1464
- * @returns updated viewport options with new longitude/latitude
1465
- */
1466
- panByPosition([startLng, startLat, startZoom], pixel, startPixel) {
1467
- const scale = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
1468
- const rotationSpeed = 0.25 / scale;
1469
- const longitude = startLng + rotationSpeed * (startPixel[0] - pixel[0]);
1470
- let latitude = startLat - rotationSpeed * (startPixel[1] - pixel[1]);
1471
- latitude = Math.max(Math.min(latitude, 90), -90);
1472
- const out = { longitude, latitude, zoom: startZoom - zoomAdjust(startLat) };
1473
- out.zoom += zoomAdjust(out.latitude);
1474
- return out;
1475
- }
1476
- };
1477
- GlobeViewport.displayName = "GlobeViewport";
1478
- function zoomAdjust(latitude, clampToPoles) {
1479
- if (clampToPoles) {
1480
- latitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
1481
- }
1482
- const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
1483
- return Math.log2(scaleAdjust);
1484
- }
1485
- function transformVector(matrix, vector) {
1486
- const result = import_core6.vec4.transformMat4([], vector, matrix);
1487
- import_core6.vec4.scale(result, result, 1 / result[3]);
1488
- return result;
1489
- }
1490
-
1491
- // ../core/src/transitions/linear-interpolator.ts
1492
- var DEFAULT_PROPS = ["longitude", "latitude", "zoom", "bearing", "pitch"];
1493
- var DEFAULT_REQUIRED_PROPS = ["longitude", "latitude", "zoom"];
1494
- var LinearInterpolator = class extends TransitionInterpolator {
1495
- /**
1496
- * @param {Object} opts
1497
- * @param {Array} opts.transitionProps - list of props to apply linear transition to.
1498
- * @param {Array} opts.around - a screen point to zoom/rotate around.
1499
- * @param {Function} opts.makeViewport - construct a viewport instance with given props.
1500
- */
1501
- constructor(opts = {}) {
1502
- const transitionProps = Array.isArray(opts) ? opts : opts.transitionProps;
1503
- const normalizedOpts = Array.isArray(opts) ? {} : opts;
1504
- normalizedOpts.transitionProps = Array.isArray(transitionProps) ? {
1505
- compare: transitionProps,
1506
- required: transitionProps
1507
- } : transitionProps || {
1508
- compare: DEFAULT_PROPS,
1509
- required: DEFAULT_REQUIRED_PROPS
1510
- };
1511
- super(normalizedOpts.transitionProps);
1512
- this.opts = normalizedOpts;
1513
- }
1514
- initializeProps(startProps, endProps) {
1515
- const result = super.initializeProps(startProps, endProps);
1516
- const { makeViewport, around } = this.opts;
1517
- if (makeViewport && around) {
1518
- const TestViewport = makeViewport(startProps);
1519
- if (TestViewport instanceof GlobeViewport) {
1520
- log_default.warn("around not supported in GlobeView")();
1521
- } else {
1522
- const startViewport = makeViewport(startProps);
1523
- const endViewport = makeViewport(endProps);
1524
- const aroundPosition = startViewport.unproject(around);
1525
- result.start.around = around;
1526
- Object.assign(result.end, {
1527
- around: endViewport.project(aroundPosition),
1528
- aroundPosition,
1529
- width: endProps.width,
1530
- height: endProps.height
1531
- });
1532
- }
1533
- }
1534
- return result;
1535
- }
1536
- interpolateProps(startProps, endProps, t) {
1537
- const propsInTransition = {};
1538
- for (const key of this._propsToExtract) {
1539
- propsInTransition[key] = (0, import_core7.lerp)(startProps[key] || 0, endProps[key] || 0, t);
1540
- }
1541
- if (endProps.aroundPosition && this.opts.makeViewport) {
1542
- const viewport = this.opts.makeViewport({ ...endProps, ...propsInTransition });
1543
- Object.assign(
1544
- propsInTransition,
1545
- viewport.panByPosition(
1546
- endProps.aroundPosition,
1547
- // anchor point in current screen coordinates
1548
- (0, import_core7.lerp)(startProps.around, endProps.around, t)
1549
- )
1550
- );
1551
- }
1552
- return propsInTransition;
1553
- }
1554
- };
1555
-
1556
- // ../core/src/controllers/controller.ts
1557
- var NO_TRANSITION_PROPS = {
1558
- transitionDuration: 0
1559
- };
1560
- var DEFAULT_INERTIA = 300;
1561
- var REBOUND_DURATION = 300;
1562
- var INERTIA_EASING = (t) => 1 - (1 - t) * (1 - t);
1563
- var EASE_OUT_EXPONENTIAL = (t) => t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
1564
- var EVENT_TYPES = {
1565
- WHEEL: ["wheel"],
1566
- PAN: ["panstart", "panmove", "panend"],
1567
- PINCH: ["pinchstart", "pinchmove", "pinchend"],
1568
- MULTI_PAN: ["multipanstart", "multipanmove", "multipanend"],
1569
- DOUBLE_CLICK: ["dblclick"],
1570
- DOUBLE_CLICK_DRAG: [
1571
- "dblclickdragstart",
1572
- "dblclickdragmove",
1573
- "dblclickdragend",
1574
- "dblclickdragcancel"
1575
- ],
1576
- KEYBOARD: ["keydown"]
1577
- };
1578
- var pinchEventWorkaround = {};
1579
- var Controller = class {
1580
- constructor(opts) {
1581
- this.state = {};
1582
- this._events = {};
1583
- this._interactionState = {
1584
- isDragging: false
1585
- };
1586
- this._customEvents = [];
1587
- this._eventStartBlocked = null;
1588
- this._panMove = false;
1589
- this._multiPanMode = null;
1590
- this._multiPanStartCenter = null;
1591
- this._doubleClickDragAnchor = null;
1592
- this._suppressDoubleClickUntil = 0;
1593
- this.invertPan = false;
1594
- this.dragMode = "rotate";
1595
- this.inertia = 0;
1596
- this.scrollZoom = true;
1597
- this.dragPan = true;
1598
- this.dragRotate = true;
1599
- this.doubleClickZoom = true;
1600
- this.doubleClickDragZoom = true;
1601
- this.touchZoom = true;
1602
- this.touchRotate = false;
1603
- this.multiTouchDrag = null;
1604
- this.trackpadGesture = false;
1605
- this.keyboard = true;
1606
- this.transitionManager = new TransitionManager({
1607
- ...opts,
1608
- getControllerState: (props, constraintContext) => new this.ControllerState({
1609
- ...props,
1610
- constraintContext,
1611
- makeViewport: opts.makeViewport
1612
- }),
1613
- onViewStateChange: this._onTransition.bind(this),
1614
- onStateChange: this._setInteractionState.bind(this)
1615
- });
1616
- this.handleEvent = this.handleEvent.bind(this);
1617
- this.eventManager = opts.eventManager;
1618
- this.onViewStateChange = opts.onViewStateChange || (() => {
1619
- });
1620
- this.onStateChange = opts.onStateChange || (() => {
1621
- });
1622
- this.makeViewport = opts.makeViewport;
1623
- this.pickPosition = opts.pickPosition;
1624
- }
1625
- set events(customEvents) {
1626
- this.toggleEvents(this._customEvents, false);
1627
- this.toggleEvents(customEvents, true);
1628
- this._customEvents = customEvents;
1629
- if (this.props) {
1630
- this.setProps(this.props);
1631
- }
1632
- }
1633
- finalize() {
1634
- var _a;
1635
- for (const eventName in this._events) {
1636
- if (this._events[eventName]) {
1637
- (_a = this.eventManager) == null ? void 0 : _a.off(eventName, this.handleEvent);
1638
- }
1639
- }
1640
- this.transitionManager.finalize();
1641
- }
1642
- /**
1643
- * Callback for events
1644
- */
1645
- handleEvent(event) {
1646
- this._controllerState = void 0;
1647
- const eventStartBlocked = this._eventStartBlocked;
1648
- switch (event.type) {
1649
- case "panstart":
1650
- return eventStartBlocked ? false : this._onPanStart(event);
1651
- case "panmove":
1652
- return this._onPan(event);
1653
- case "panend":
1654
- return this._onPanEnd(event);
1655
- case "pinchstart":
1656
- return eventStartBlocked || !this._isTrackpadGestureAllowed(event) ? false : this._onPinchStart(event);
1657
- case "pinchmove":
1658
- return this._isTrackpadGestureAllowed(event) ? this._onPinch(event) : false;
1659
- case "pinchend":
1660
- return this._isTrackpadGestureAllowed(event) ? this._onPinchEnd(event) : false;
1661
- case "multipanstart":
1662
- return eventStartBlocked ? false : this._onMultiPanStart(event);
1663
- case "multipanmove":
1664
- return this._onMultiPan(event);
1665
- case "multipanend":
1666
- return this._onMultiPanEnd(event);
1667
- case "dblclick":
1668
- return this._onDoubleClick(event);
1669
- case "dblclickdragstart":
1670
- return eventStartBlocked ? false : this._onDoubleClickDragStart(event);
1671
- case "dblclickdragmove":
1672
- return this._onDoubleClickDrag(event);
1673
- case "dblclickdragend":
1674
- case "dblclickdragcancel":
1675
- return this._onDoubleClickDragEnd(event);
1676
- case "wheel":
1677
- return this._onWheel(event);
1678
- case "keydown":
1679
- return this._onKeyDown(event);
1680
- default:
1681
- return false;
1682
- }
1683
- }
1684
- /* Event utils */
1685
- // Event object: http://hammerjs.github.io/api/#event-object
1686
- get controllerState() {
1687
- this._controllerState = this._controllerState || new this.ControllerState({
1688
- makeViewport: this.makeViewport,
1689
- ...this.props,
1690
- ...this.state
1691
- });
1692
- return this._controllerState;
1693
- }
1694
- getCenter(event) {
1695
- const { x, y } = this.props;
1696
- const { offsetCenter } = event;
1697
- return [offsetCenter.x - x, offsetCenter.y - y];
1698
- }
1699
- isPointInBounds(pos, event) {
1700
- const { width, height } = this.props;
1701
- if (event && event.handled) {
1702
- return false;
1703
- }
1704
- const inside = pos[0] >= 0 && pos[0] <= width && pos[1] >= 0 && pos[1] <= height;
1705
- if (inside && event) {
1706
- event.stopPropagation();
1707
- }
1708
- return inside;
1709
- }
1710
- isFunctionKeyPressed(event) {
1711
- const { srcEvent } = event;
1712
- return Boolean(srcEvent.metaKey || srcEvent.altKey || srcEvent.ctrlKey || srcEvent.shiftKey);
1713
- }
1714
- isDragging() {
1715
- return this._interactionState.isDragging || false;
1716
- }
1717
- // When a multi-touch event ends, e.g. pinch, not all pointers are lifted at the same time.
1718
- // This triggers a brief `pan` event.
1719
- // Calling this method will temporarily disable *start events to avoid conflicting transitions.
1720
- blockEvents(timeout) {
1721
- const timer = setTimeout(() => {
1722
- if (this._eventStartBlocked === timer) {
1723
- this._eventStartBlocked = null;
1724
- }
1725
- }, timeout);
1726
- this._eventStartBlocked = timer;
1727
- }
1728
- /**
1729
- * Extract interactivity options
1730
- */
1731
- setProps(props) {
1732
- if (props.maxBoundsPadding === void 0) {
1733
- props.maxBoundsPadding = null;
1734
- }
1735
- if (props.dragMode) {
1736
- this.dragMode = props.dragMode;
1737
- }
1738
- const oldProps = this.props;
1739
- this.props = props;
1740
- if (!("transitionInterpolator" in props)) {
1741
- props.transitionInterpolator = this._getTransitionProps().transitionInterpolator;
1742
- }
1743
- this.transitionManager.processViewStateChange(props);
1744
- const { inertia } = props;
1745
- this.inertia = Number.isFinite(inertia) ? inertia : inertia === true ? DEFAULT_INERTIA : 0;
1746
- const {
1747
- scrollZoom = true,
1748
- dragPan = true,
1749
- dragRotate = true,
1750
- doubleClickZoom = true,
1751
- doubleClickDragZoom = false,
1752
- touchZoom = true,
1753
- touchRotate = false,
1754
- multiTouchDrag = touchRotate ? "rotate" : null,
1755
- trackpadGesture = false,
1756
- keyboard = true
1757
- } = props;
1758
- const isInteractive = Boolean(this.onViewStateChange);
1759
- this.toggleEvents(EVENT_TYPES.WHEEL, isInteractive && scrollZoom);
1760
- this.toggleEvents(EVENT_TYPES.PAN, isInteractive);
1761
- this.toggleEvents(
1762
- EVENT_TYPES.PINCH,
1763
- isInteractive && (touchZoom || multiTouchDrag === "rotate")
1764
- );
1765
- this.toggleEvents(EVENT_TYPES.MULTI_PAN, isInteractive && Boolean(multiTouchDrag));
1766
- this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK, isInteractive && doubleClickZoom);
1767
- this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK_DRAG, isInteractive && doubleClickDragZoom);
1768
- this.toggleEvents(EVENT_TYPES.KEYBOARD, isInteractive && keyboard);
1769
- this.scrollZoom = scrollZoom;
1770
- this.dragPan = dragPan;
1771
- this.dragRotate = dragRotate;
1772
- this.doubleClickZoom = doubleClickZoom;
1773
- this.doubleClickDragZoom = doubleClickDragZoom;
1774
- this.touchZoom = touchZoom;
1775
- this.touchRotate = multiTouchDrag === "rotate";
1776
- this.multiTouchDrag = multiTouchDrag;
1777
- this.trackpadGesture = trackpadGesture;
1778
- this.keyboard = keyboard;
1779
- const constraintChanged = !oldProps || oldProps.height !== props.height || oldProps.width !== props.width || oldProps.maxBounds !== props.maxBounds || oldProps.maxBoundsPadding !== props.maxBoundsPadding;
1780
- if (constraintChanged && props.maxBounds) {
1781
- const controllerState = new this.ControllerState({ ...props, makeViewport: this.makeViewport });
1782
- const normalizedProps = controllerState.getViewportProps();
1783
- const changed = Object.keys(normalizedProps).some(
1784
- (key) => !deepEqual(normalizedProps[key], props[key], 1)
1785
- );
1786
- if (changed) {
1787
- this.updateViewport(controllerState);
1788
- }
1789
- }
1790
- }
1791
- updateTransition() {
1792
- this.transitionManager.updateTransition();
1793
- }
1794
- toggleEvents(eventNames, enabled) {
1795
- if (this.eventManager) {
1796
- eventNames.forEach((eventName) => {
1797
- if (this._events[eventName] !== enabled) {
1798
- this._events[eventName] = enabled;
1799
- if (enabled) {
1800
- this.eventManager.on(eventName, this.handleEvent);
1801
- } else {
1802
- this.eventManager.off(eventName, this.handleEvent);
1803
- }
1804
- }
1805
- });
1806
- }
1807
- }
1808
- // Private Methods
1809
- /* Callback util */
1810
- // formats map state and invokes callback function
1811
- updateViewport(newControllerState, extraProps = null, interactionState = {}) {
1812
- const viewState = { ...newControllerState.getViewportProps(), ...extraProps };
1813
- const changed = this.controllerState !== newControllerState;
1814
- this.state = newControllerState.getState();
1815
- this._setInteractionState(interactionState);
1816
- if (changed) {
1817
- const oldViewState = this.controllerState && this.controllerState.getViewportProps();
1818
- if (this.onViewStateChange) {
1819
- this.onViewStateChange({
1820
- viewState,
1821
- interactionState: this._interactionState,
1822
- oldViewState,
1823
- viewId: this.props.id
1824
- });
1825
- }
1826
- }
1827
- }
1828
- _onTransition(params) {
1829
- this.onViewStateChange({
1830
- ...params,
1831
- interactionState: this._interactionState,
1832
- viewId: this.props.id
1833
- });
1834
- }
1835
- _setInteractionState(newStates) {
1836
- Object.assign(this._interactionState, newStates);
1837
- this.onStateChange(this._interactionState);
1838
- }
1839
- /** Maps a semantic input lifecycle to the constraint policy seen by controller state. */
1840
- _getConstraintContext(_action, phase) {
1841
- if (!this.props.rubberBand) {
1842
- return { mode: "hard" };
1843
- }
1844
- return { mode: phase === "update" ? "elastic" : phase === "end" ? "rebound" : "hard" };
1845
- }
1846
- /** Returns a rebound transition when hard resolution changed the displayed viewport props. */
1847
- _getReboundTransition(constraintContext, nextControllerState) {
1848
- if (constraintContext.mode !== "rebound") {
1849
- return null;
1850
- }
1851
- const nextViewportProps = nextControllerState.getViewportProps();
1852
- const shouldRebound = Object.keys(nextViewportProps).some(
1853
- (key) => !deepEqual(this.props[key], nextViewportProps[key], 1)
1854
- );
1855
- return shouldRebound ? {
1856
- ...this._getTransitionProps(),
1857
- transitionDuration: REBOUND_DURATION,
1858
- transitionEasing: EASE_OUT_EXPONENTIAL
1859
- } : null;
1860
- }
1861
- /* Event handlers */
1862
- // Default handler for the `panstart` event.
1863
- _onPanStart(event) {
1864
- const pos = this.getCenter(event);
1865
- if (!this.isPointInBounds(pos, event)) {
1866
- return false;
1867
- }
1868
- let alternateMode = this.isFunctionKeyPressed(event) || event.rightButton || false;
1869
- if (this.invertPan || this.dragMode === "pan") {
1870
- alternateMode = !alternateMode;
1871
- }
1872
- const action = alternateMode ? "pan" : "rotate";
1873
- const constraintContext = this._getConstraintContext(action, "start");
1874
- const newControllerState = alternateMode ? this.controllerState.panStart({ pos }, constraintContext) : this.controllerState.rotateStart({ pos }, constraintContext);
1875
- this._panMove = alternateMode;
1876
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
1877
- return true;
1878
- }
1879
- // Default handler for the `panmove` and `panend` event.
1880
- _onPan(event) {
1881
- if (!this.isDragging()) {
1882
- return false;
1883
- }
1884
- return this._panMove ? this._onPanMove(event) : this._onPanRotate(event);
1885
- }
1886
- _onPanEnd(event) {
1887
- if (!this.isDragging()) {
1888
- return false;
1889
- }
1890
- return this._panMove ? this._onPanMoveEnd(event) : this._onPanRotateEnd(event);
1891
- }
1892
- // Default handler for panning to move.
1893
- // Called by `_onPan` when panning without function key pressed.
1894
- _onPanMove(event) {
1895
- if (!this.dragPan) {
1896
- return false;
1897
- }
1898
- const pos = this.getCenter(event);
1899
- const newControllerState = this.controllerState.pan(
1900
- { pos },
1901
- this._getConstraintContext("pan", "update")
1902
- );
1903
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
1904
- isDragging: true,
1905
- isPanning: true
1906
- });
1907
- return true;
1908
- }
1909
- _onPanMoveEnd(event) {
1910
- const { inertia } = this;
1911
- if (this.dragPan && inertia && event.velocity) {
1912
- const pos = this.getCenter(event);
1913
- const endPos = [
1914
- pos[0] + event.velocityX * inertia / 2,
1915
- pos[1] + event.velocityY * inertia / 2
1916
- ];
1917
- const newControllerState = this.controllerState.pan({ pos: endPos }).panEnd();
1918
- this.updateViewport(
1919
- newControllerState,
1920
- {
1921
- ...this._getTransitionProps(),
1922
- transitionDuration: inertia,
1923
- transitionEasing: INERTIA_EASING
1924
- },
1925
- {
1926
- isDragging: false,
1927
- isPanning: true
1928
- }
1929
- );
1930
- } else {
1931
- const currentControllerState = this.controllerState;
1932
- const constraintContext = this._getConstraintContext("pan", "end");
1933
- const newControllerState = currentControllerState.panEnd(constraintContext);
1934
- const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
1935
- this.updateViewport(newControllerState, reboundTransition, {
1936
- isDragging: false,
1937
- isPanning: Boolean(reboundTransition)
1938
- });
1939
- }
1940
- return true;
1941
- }
1942
- // Default handler for panning to rotate.
1943
- // Called by `_onPan` when panning with function key pressed.
1944
- _onPanRotate(event) {
1945
- if (!this.dragRotate) {
1946
- return false;
1947
- }
1948
- const pos = this.getCenter(event);
1949
- const newControllerState = this.controllerState.rotate(
1950
- { pos },
1951
- this._getConstraintContext("rotate", "update")
1952
- );
1953
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
1954
- isDragging: true,
1955
- isRotating: true
1956
- });
1957
- return true;
1958
- }
1959
- _onPanRotateEnd(event) {
1960
- const { inertia } = this;
1961
- if (this.dragRotate && inertia && event.velocity) {
1962
- const pos = this.getCenter(event);
1963
- const endPos = [
1964
- pos[0] + event.velocityX * inertia / 2,
1965
- pos[1] + event.velocityY * inertia / 2
1966
- ];
1967
- const newControllerState = this.controllerState.rotate({ pos: endPos }).rotateEnd();
1968
- this.updateViewport(
1969
- newControllerState,
1970
- {
1971
- ...this._getTransitionProps(),
1972
- transitionDuration: inertia,
1973
- transitionEasing: INERTIA_EASING
1974
- },
1975
- {
1976
- isDragging: false,
1977
- isRotating: true
1978
- }
1979
- );
1980
- } else {
1981
- const currentControllerState = this.controllerState;
1982
- const constraintContext = this._getConstraintContext("rotate", "end");
1983
- const newControllerState = currentControllerState.rotateEnd(constraintContext);
1984
- const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
1985
- this.updateViewport(newControllerState, reboundTransition, {
1986
- isDragging: false,
1987
- isRotating: Boolean(reboundTransition)
1988
- });
1989
- }
1990
- return true;
1991
- }
1992
- // Default handler for the `wheel` event.
1993
- _onWheel(event) {
1994
- if (!this.scrollZoom) {
1995
- return false;
1996
- }
1997
- if (this.trackpadGesture && event.device !== "mouse") {
1998
- return false;
1999
- }
2000
- const pos = this.getCenter(event);
2001
- if (!this.isPointInBounds(pos, event)) {
2002
- return false;
2003
- }
2004
- event.srcEvent.preventDefault();
2005
- const { speed = 0.01, smooth = false } = this.scrollZoom === true ? {} : this.scrollZoom;
2006
- const { delta } = event;
2007
- let scale = 2 / (1 + Math.exp(-Math.abs(delta * speed)));
2008
- if (delta < 0 && scale !== 0) {
2009
- scale = 1 / scale;
2010
- }
2011
- const transitionProps = smooth ? { ...this._getTransitionProps({ around: pos }), transitionDuration: 250 } : NO_TRANSITION_PROPS;
2012
- const newControllerState = this.controllerState.zoom({ pos, scale });
2013
- this.updateViewport(newControllerState, transitionProps, {
2014
- isZooming: true,
2015
- isPanning: true
2016
- });
2017
- if (!smooth) {
2018
- this._setInteractionState({ isZooming: false, isPanning: false });
2019
- }
2020
- return true;
2021
- }
2022
- _onMultiPanStart(event) {
2023
- const { multiTouchDrag } = this;
2024
- if (!multiTouchDrag || !this._isMultiPanEventAllowed(event, multiTouchDrag)) {
2025
- return false;
2026
- }
2027
- const currentCenter = event.offsetCenter;
2028
- if (!this.isPointInBounds(this.getCenter(event), event)) {
2029
- return false;
2030
- }
2031
- const isTrackpad = event.pointerType === "trackpad";
2032
- const startCenter = {
2033
- x: currentCenter.x - (isTrackpad ? 0 : event.deltaX),
2034
- y: currentCenter.y - (isTrackpad ? 0 : event.deltaY)
2035
- };
2036
- const startEvent = { ...event, offsetCenter: startCenter };
2037
- const pos = this.getCenter(startEvent);
2038
- const newControllerState = multiTouchDrag === "pan" ? this.controllerState.panStart({ pos }, this._getConstraintContext("pan", "start")) : this.controllerState.rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
2039
- this._multiPanMode = multiTouchDrag;
2040
- this._multiPanStartCenter = startCenter;
2041
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
2042
- return true;
2043
- }
2044
- _onMultiPan(event) {
2045
- const { mode, event: panEvent } = this._getMultiPanEvent(event);
2046
- if (!mode || !panEvent || !this.isDragging()) {
2047
- return false;
2048
- }
2049
- return mode === "pan" ? this._onPanMove(panEvent) : this._onPanRotate(panEvent);
2050
- }
2051
- _onMultiPanEnd(event) {
2052
- const { mode, event: panEvent } = this._getMultiPanEvent(event);
2053
- if (!mode || !panEvent || !this.isDragging()) {
2054
- this._resetMultiPan();
2055
- return false;
2056
- }
2057
- const handled = mode === "pan" ? this._onPanMoveEnd(panEvent) : this._onPanRotateEnd(panEvent);
2058
- this._resetMultiPan();
2059
- return handled;
2060
- }
2061
- _isTrackpadGestureAllowed(event) {
2062
- return event.pointerType !== "trackpad" || this.trackpadGesture;
2063
- }
2064
- _isMultiPanEventAllowed(event, mode) {
2065
- if (event.pointerType === "trackpad") {
2066
- return this.trackpadGesture && (mode === "pan" ? this.dragPan : this.dragRotate);
2067
- }
2068
- return event.pointerType === "touch" && (mode === "pan" ? this.dragPan : this.dragRotate);
2069
- }
2070
- _getMultiPanEvent(event) {
2071
- const mode = this._multiPanMode;
2072
- const startCenter = this._multiPanStartCenter;
2073
- if (!mode || !startCenter) {
2074
- return { mode: null, event: null };
2075
- }
2076
- return {
2077
- mode,
2078
- event: {
2079
- ...event,
2080
- offsetCenter: {
2081
- x: startCenter.x + event.deltaX,
2082
- y: startCenter.y + event.deltaY
2083
- }
2084
- }
2085
- };
2086
- }
2087
- _resetMultiPan() {
2088
- this._multiPanMode = null;
2089
- this._multiPanStartCenter = null;
2090
- }
2091
- // Default handler for the `pinchstart` event.
2092
- _onPinchStart(event) {
2093
- this._doubleClickDragAnchor = null;
2094
- const pos = this.getCenter(event);
2095
- if (!this.isPointInBounds(pos, event)) {
2096
- return false;
2097
- }
2098
- const newControllerState = this.controllerState.zoomStart({ pos }, this._getConstraintContext("zoom", "start")).rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
2099
- pinchEventWorkaround._startPinchRotation = event.rotation;
2100
- pinchEventWorkaround._lastPinchEvent = event;
2101
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
2102
- return true;
2103
- }
2104
- // Default handler for the `pinchmove` and `pinchend` events.
2105
- _onPinch(event) {
2106
- if (!this.touchZoom && !this.touchRotate) {
2107
- return false;
2108
- }
2109
- if (!this.isDragging()) {
2110
- return false;
2111
- }
2112
- let newControllerState = this.controllerState;
2113
- if (this.touchZoom) {
2114
- const { scale } = event;
2115
- const pos = this.getCenter(event);
2116
- newControllerState = newControllerState.zoom(
2117
- { pos, scale },
2118
- this._getConstraintContext("zoom", "update")
2119
- );
2120
- }
2121
- if (this.touchRotate) {
2122
- const { rotation } = event;
2123
- newControllerState = newControllerState.rotate(
2124
- { deltaAngleX: pinchEventWorkaround._startPinchRotation - rotation },
2125
- this._getConstraintContext("rotate", "update")
2126
- );
2127
- }
2128
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
2129
- isDragging: true,
2130
- isPanning: this.touchZoom,
2131
- isZooming: this.touchZoom,
2132
- isRotating: this.touchRotate
2133
- });
2134
- pinchEventWorkaround._lastPinchEvent = event;
2135
- return true;
2136
- }
2137
- _onPinchEnd(event) {
2138
- if (!this.isDragging()) {
2139
- return false;
2140
- }
2141
- const { inertia } = this;
2142
- const { _lastPinchEvent } = pinchEventWorkaround;
2143
- if (this.touchZoom && inertia && _lastPinchEvent && event.scale !== _lastPinchEvent.scale) {
2144
- const pos = this.getCenter(event);
2145
- let newControllerState = this.controllerState.rotateEnd();
2146
- const z = Math.log2(event.scale);
2147
- const velocityZ = (z - Math.log2(_lastPinchEvent.scale)) / (event.deltaTime - _lastPinchEvent.deltaTime);
2148
- const endScale = Math.pow(2, z + velocityZ * inertia / 2);
2149
- newControllerState = newControllerState.zoom({ pos, scale: endScale }).zoomEnd();
2150
- this.updateViewport(
2151
- newControllerState,
2152
- {
2153
- ...this._getTransitionProps({ around: pos }),
2154
- transitionDuration: inertia,
2155
- transitionEasing: INERTIA_EASING
2156
- },
2157
- {
2158
- isDragging: false,
2159
- isPanning: this.touchZoom,
2160
- isZooming: this.touchZoom,
2161
- isRotating: false
2162
- }
2163
- );
2164
- this.blockEvents(inertia);
2165
- } else {
2166
- const currentControllerState = this.controllerState;
2167
- const zoomConstraintContext = this._getConstraintContext("zoom", "end");
2168
- const rotateConstraintContext = this._getConstraintContext("rotate", "end");
2169
- const newControllerState = currentControllerState.zoomEnd(zoomConstraintContext).rotateEnd(rotateConstraintContext);
2170
- const reboundTransition = this._getReboundTransition(
2171
- this.touchZoom ? zoomConstraintContext : rotateConstraintContext,
2172
- newControllerState
2173
- );
2174
- this.updateViewport(newControllerState, reboundTransition, {
2175
- isDragging: false,
2176
- isPanning: Boolean(reboundTransition) && this.touchZoom,
2177
- isZooming: Boolean(reboundTransition) && this.touchZoom,
2178
- isRotating: Boolean(reboundTransition) && this.touchRotate
2179
- });
2180
- }
2181
- pinchEventWorkaround._startPinchRotation = null;
2182
- pinchEventWorkaround._lastPinchEvent = null;
2183
- return true;
2184
- }
2185
- // Default handler for the `dblclick` event.
2186
- _onDoubleClick(event) {
2187
- if (!this.doubleClickZoom) {
2188
- return false;
2189
- }
2190
- if (Date.now() < this._suppressDoubleClickUntil) {
2191
- return false;
2192
- }
2193
- const pos = this.getCenter(event);
2194
- if (!this.isPointInBounds(pos, event)) {
2195
- return false;
2196
- }
2197
- const isZoomOut = this.isFunctionKeyPressed(event);
2198
- const newControllerState = this.controllerState.zoom({ pos, scale: isZoomOut ? 0.5 : 2 });
2199
- this.updateViewport(newControllerState, this._getTransitionProps({ around: pos }), {
2200
- isZooming: true,
2201
- isPanning: true
2202
- });
2203
- this.blockEvents(100);
2204
- return true;
2205
- }
2206
- _onDoubleClickDragStart(event) {
2207
- if (!this.doubleClickDragZoom) {
2208
- this._doubleClickDragAnchor = null;
2209
- return false;
2210
- }
2211
- const pos = this.getCenter(event);
2212
- if (!this.isPointInBounds(pos, event)) {
2213
- this._doubleClickDragAnchor = null;
2214
- return false;
2215
- }
2216
- this._doubleClickDragAnchor = pos;
2217
- let newControllerState = this.controllerState.zoomStart(
2218
- { pos },
2219
- this._getConstraintContext("zoom", "start")
2220
- );
2221
- if (event.scale !== 1) {
2222
- newControllerState = newControllerState.zoom(
2223
- { pos, scale: event.scale },
2224
- this._getConstraintContext("zoom", "update")
2225
- );
2226
- }
2227
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
2228
- isDragging: true,
2229
- isPanning: true,
2230
- isZooming: true
2231
- });
2232
- return true;
2233
- }
2234
- _onDoubleClickDrag(event) {
2235
- const pos = this._doubleClickDragAnchor;
2236
- if (!pos) {
2237
- return false;
2238
- }
2239
- const newControllerState = this.controllerState.zoom(
2240
- { pos, scale: event.scale },
2241
- this._getConstraintContext("zoom", "update")
2242
- );
2243
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
2244
- isDragging: true,
2245
- isPanning: true,
2246
- isZooming: true
2247
- });
2248
- return true;
2249
- }
2250
- _onDoubleClickDragEnd(_event) {
2251
- const pos = this._doubleClickDragAnchor;
2252
- if (!pos) {
2253
- return false;
2254
- }
2255
- this._doubleClickDragAnchor = null;
2256
- const currentControllerState = this.controllerState;
2257
- const constraintContext = this._getConstraintContext("zoom", "end");
2258
- const newControllerState = currentControllerState.zoomEnd(constraintContext);
2259
- const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
2260
- this.updateViewport(newControllerState, reboundTransition, {
2261
- isDragging: false,
2262
- isPanning: Boolean(reboundTransition),
2263
- isZooming: Boolean(reboundTransition)
2264
- });
2265
- this._suppressDoubleClickUntil = Date.now() + 100;
2266
- this.blockEvents(100);
2267
- return true;
2268
- }
2269
- // Default handler for the `keydown` event
2270
- _onKeyDown(event) {
2271
- if (!this.keyboard) {
2272
- return false;
2273
- }
2274
- const funcKey = this.isFunctionKeyPressed(event);
2275
- const { zoomSpeed, moveSpeed, rotateSpeedX, rotateSpeedY } = this.keyboard === true ? {} : this.keyboard;
2276
- const { controllerState } = this;
2277
- let newControllerState;
2278
- const interactionState = {};
2279
- switch (event.srcEvent.code) {
2280
- case "Minus":
2281
- newControllerState = funcKey ? controllerState.zoomOut(zoomSpeed).zoomOut(zoomSpeed) : controllerState.zoomOut(zoomSpeed);
2282
- interactionState.isZooming = true;
2283
- break;
2284
- case "Equal":
2285
- newControllerState = funcKey ? controllerState.zoomIn(zoomSpeed).zoomIn(zoomSpeed) : controllerState.zoomIn(zoomSpeed);
2286
- interactionState.isZooming = true;
2287
- break;
2288
- case "ArrowLeft":
2289
- if (funcKey) {
2290
- newControllerState = controllerState.rotateLeft(rotateSpeedX);
2291
- interactionState.isRotating = true;
2292
- } else {
2293
- newControllerState = controllerState.moveLeft(moveSpeed);
2294
- interactionState.isPanning = true;
2295
- }
2296
- break;
2297
- case "ArrowRight":
2298
- if (funcKey) {
2299
- newControllerState = controllerState.rotateRight(rotateSpeedX);
2300
- interactionState.isRotating = true;
2301
- } else {
2302
- newControllerState = controllerState.moveRight(moveSpeed);
2303
- interactionState.isPanning = true;
2304
- }
2305
- break;
2306
- case "ArrowUp":
2307
- if (funcKey) {
2308
- newControllerState = controllerState.rotateUp(rotateSpeedY);
2309
- interactionState.isRotating = true;
2310
- } else {
2311
- newControllerState = controllerState.moveUp(moveSpeed);
2312
- interactionState.isPanning = true;
2313
- }
2314
- break;
2315
- case "ArrowDown":
2316
- if (funcKey) {
2317
- newControllerState = controllerState.rotateDown(rotateSpeedY);
2318
- interactionState.isRotating = true;
2319
- } else {
2320
- newControllerState = controllerState.moveDown(moveSpeed);
2321
- interactionState.isPanning = true;
2322
- }
2323
- break;
2324
- default:
2325
- return false;
2326
- }
2327
- this.updateViewport(newControllerState, this._getTransitionProps(), interactionState);
2328
- return true;
2329
- }
2330
- _getTransitionProps(opts) {
2331
- const { transition } = this;
2332
- if (!transition || !transition.transitionInterpolator) {
2333
- return NO_TRANSITION_PROPS;
2334
- }
2335
- return opts ? {
2336
- ...transition,
2337
- transitionInterpolator: new LinearInterpolator({
2338
- ...opts,
2339
- ...transition.transitionInterpolator.opts,
2340
- makeViewport: this.controllerState.makeViewport
2341
- })
2342
- } : transition;
2343
- }
2344
- };
2345
-
2346
- // ../core/src/controllers/view-state.ts
2347
- var CONSTRAINT_AROUND = /* @__PURE__ */ Symbol("constraintAround");
2348
- var ViewState = class {
2349
- constructor(props, state, makeViewport, constraintContext) {
2350
- this.makeViewport = makeViewport;
2351
- this._viewportProps = this.applyConstraints(props, constraintContext);
2352
- this._state = state;
2353
- }
2354
- getViewportProps() {
2355
- return this._viewportProps;
2356
- }
2357
- getState() {
2358
- return this._state;
2359
- }
2360
- };
2361
-
2362
- // ../core/src/controllers/utils.ts
2363
- function applyRubberBand(value, constrainedValue, range) {
2364
- const overshoot = value - constrainedValue;
2365
- return overshoot && Number.isFinite(overshoot) ? constrainedValue + overshoot * range / (range + Math.abs(overshoot)) : constrainedValue;
2366
- }
2367
- function getMaxBoundsRect(width, height, padding) {
2368
- const left = getPosition(parsePosition((padding == null ? void 0 : padding.left) ?? 0), width);
2369
- const right = getPosition(parsePosition((padding == null ? void 0 : padding.right) ?? 0), width);
2370
- const top = getPosition(parsePosition((padding == null ? void 0 : padding.top) ?? 0), height);
2371
- const bottom = getPosition(parsePosition((padding == null ? void 0 : padding.bottom) ?? 0), height);
2372
- return {
2373
- x: left,
2374
- y: top,
2375
- width: width - left - right,
2376
- height: height - top - bottom
2377
- };
2378
- }
2379
- function getMaxBoundsExtents(viewport, target, rect) {
2380
- let [x, y] = viewport.project(target);
2381
- x = Number.isFinite(x) ? x : viewport.width / 2;
2382
- y = Number.isFinite(y) ? y : viewport.height / 2;
2383
- return {
2384
- left: x - rect.x,
2385
- right: rect.x + rect.width - x,
2386
- top: y - rect.y,
2387
- bottom: rect.y + rect.height - y
2388
- };
2389
- }
2390
-
2391
- // ../core/src/utils/apply-styles.ts
2392
- function applyStyles(element, style) {
2393
- if (style) {
2394
- Object.entries(style).map(([key, value]) => {
2395
- if (key.startsWith("--")) {
2396
- element.style.setProperty(key, value);
2397
- } else {
2398
- element.style[key] = value;
2399
- }
2400
- });
2401
- }
2402
- }
2403
- function removeStyles(element, style) {
2404
- if (style) {
2405
- Object.keys(style).map((key) => {
2406
- if (key.startsWith("--")) {
2407
- element.style.removeProperty(key);
2408
- } else {
2409
- element.style[key] = "";
2410
- }
2411
- });
2412
- }
2413
- }
2414
-
2415
- // ../core/src/lib/widget.ts
2416
- var Widget = class {
2417
- constructor(props) {
2418
- /**
2419
- * The view id that this widget controls and is positioned relative to. Default `null`.
2420
- * If assigned, this widget only responds to events inside the matching view. In multi-canvas
2421
- * mode, the view's `canvasId` determines the positioning offset, but the widget DOM remains
2422
- * under the shared widget root.
2423
- */
2424
- this.viewId = null;
2425
- this.props = {
2426
- // @ts-expect-error `defaultProps` may not exist on constructor
2427
- ...this.constructor.defaultProps,
2428
- ...props
2429
- };
2430
- this.id = this.props.id;
2431
- }
2432
- /** Called to update widget options */
2433
- setProps(props) {
2434
- const oldProps = this.props;
2435
- const el = this.rootElement;
2436
- if (el && oldProps.className !== props.className) {
2437
- if (oldProps.className) el.classList.remove(oldProps.className);
2438
- if (props.className) el.classList.add(props.className);
2439
- }
2440
- if (el && !deepEqual(oldProps.style, props.style, 1)) {
2441
- removeStyles(el, oldProps.style);
2442
- applyStyles(el, props.style);
2443
- }
2444
- Object.assign(this.props, props);
2445
- this.updateHTML();
2446
- }
2447
- /** Update the HTML to reflect latest props and state */
2448
- updateHTML() {
2449
- if (this.rootElement) {
2450
- this.onRenderHTML(this.rootElement);
2451
- }
2452
- }
2453
- // VIEW STATE HELPERS
2454
- get viewIds() {
2455
- var _a;
2456
- return this.viewId ? [this.viewId] : ((_a = this.deck) == null ? void 0 : _a.getViews().map((v) => v.id)) ?? [];
2457
- }
2458
- /** Returns the current view state for the given view */
2459
- getViewState(viewId) {
2460
- var _a, _b;
2461
- return ((_b = (_a = this.deck) == null ? void 0 : _a.viewManager) == null ? void 0 : _b.getViewState(viewId)) || {};
2462
- }
2463
- /** Updates the view state for the given view */
2464
- setViewState(viewId, viewState) {
2465
- var _a;
2466
- (_a = this.deck) == null ? void 0 : _a._onViewStateChange({ viewId, viewState, interactionState: {} });
2467
- }
2468
- // @note empty method calls have an overhead in V8 but it is very low, ~1ns
2469
- /**
2470
- * Common utility to create the root DOM element for this widget
2471
- * Configures the top-level styles and adds basic class names for theming
2472
- * @returns an UI element that should be appended to the Deck container
2473
- */
2474
- onCreateRootElement() {
2475
- const CLASS_NAMES = [
2476
- // Add class names for theming
2477
- "deck-widget",
2478
- this.className,
2479
- // plus any app-supplied class name
2480
- this.props.className
2481
- ];
2482
- const element = document.createElement("div");
2483
- CLASS_NAMES.filter((cls) => typeof cls === "string" && cls.length > 0).forEach(
2484
- (className) => element.classList.add(className)
2485
- );
2486
- applyStyles(element, this.props.style);
2487
- return element;
2488
- }
2489
- /** Internal API called by Deck when the widget is first added to a Deck instance */
2490
- _onAdd(params) {
2491
- return this.onAdd(params) ?? this.onCreateRootElement();
2492
- }
2493
- /** Overridable by subclass - called when the widget is first added to a Deck instance
2494
- * @returns an optional UI element that should be appended to the Deck container
2495
- */
2496
- onAdd(params) {
2497
- }
2498
- /** Called when the widget is removed */
2499
- onRemove() {
2500
- }
2501
- // deck integration - Event hooks
2502
- /** Called when the containing view is changed */
2503
- onViewportChange(viewport) {
2504
- }
2505
- /** Called when the containing view is redrawn */
2506
- onRedraw(params) {
2507
- }
2508
- /** Called when a hover event occurs */
2509
- onHover(info, event) {
2510
- }
2511
- /** Called when a click event occurs */
2512
- onClick(info, event) {
2513
- }
2514
- /** Called when a drag event occurs */
2515
- onDrag(info, event) {
2516
- }
2517
- /** Called when a dragstart event occurs */
2518
- onDragStart(info, event) {
2519
- }
2520
- /** Called when a dragend event occurs */
2521
- onDragEnd(info, event) {
2522
- }
2523
- };
2524
- Widget.defaultProps = {
2525
- id: "widget",
2526
- style: {},
2527
- _container: null,
2528
- className: ""
2529
- };
2530
-
2531
- // ../core/src/viewports/orthographic-viewport.ts
2532
- var import_core8 = require("@math.gl/core");
2533
- var import_web_mercator5 = require("@math.gl/web-mercator");
2534
- var viewMatrix = new import_core8.Matrix4().lookAt({ eye: [0, 0, 1] });
2535
- function getProjectionMatrix({
2536
- width,
2537
- height,
2538
- near,
2539
- far,
2540
- padding
2541
- }) {
2542
- let left = -width / 2;
2543
- let right = width / 2;
2544
- let bottom = -height / 2;
2545
- let top = height / 2;
2546
- if (padding) {
2547
- const { left: l = 0, right: r = 0, top: t = 0, bottom: b = 0 } = padding;
2548
- const offsetX = (0, import_core8.clamp)((l + width - r) / 2, 0, width) - width / 2;
2549
- const offsetY = (0, import_core8.clamp)((t + height - b) / 2, 0, height) - height / 2;
2550
- left -= offsetX;
2551
- right -= offsetX;
2552
- bottom += offsetY;
2553
- top += offsetY;
2554
- }
2555
- return new import_core8.Matrix4().ortho({
2556
- left,
2557
- right,
2558
- bottom,
2559
- top,
2560
- near,
2561
- far
2562
- });
2563
- }
2564
- var OrthographicViewport = class extends Viewport {
2565
- constructor(props) {
2566
- const {
2567
- width,
2568
- height,
2569
- near = 0.1,
2570
- far = 1e3,
2571
- zoom = 0,
2572
- target = [0, 0, 0],
2573
- padding = null,
2574
- flipY = true
2575
- } = props;
2576
- const zoomX = props.zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
2577
- const zoomY = props.zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
2578
- const zoom_ = Number.isFinite(props.zoom) ? props.zoom : Math.min(zoomX, zoomY);
2579
- const scale = Math.pow(2, zoom_);
2580
- let distanceScales;
2581
- if (zoomX !== zoom_ || zoomY !== zoom_) {
2582
- const scaleX = Math.pow(2, zoomX);
2583
- const scaleY = Math.pow(2, zoomY);
2584
- distanceScales = {
2585
- unitsPerMeter: [scaleX / scale, scaleY / scale, 1],
2586
- metersPerUnit: [scale / scaleX, scale / scaleY, 1]
2587
- };
2588
- }
2589
- super({
2590
- ...props,
2591
- // in case viewState contains longitude/latitude values,
2592
- // make sure that the base Viewport class does not treat this as a geospatial viewport
2593
- longitude: void 0,
2594
- position: target,
2595
- viewMatrix: viewMatrix.clone().scale([scale, scale * (flipY ? -1 : 1), scale]),
2596
- projectionMatrix: getProjectionMatrix({
2597
- width: width || 1,
2598
- height: height || 1,
2599
- padding,
2600
- near,
2601
- far
2602
- }),
2603
- zoom: zoom_,
2604
- distanceScales
2605
- });
2606
- this.target = target;
2607
- this.zoomX = zoomX;
2608
- this.zoomY = zoomY;
2609
- this.flipY = flipY;
2610
- }
2611
- projectFlat([X, Y]) {
2612
- const { unitsPerMeter: unitsPerMeter2 } = this.distanceScales;
2613
- return [X * unitsPerMeter2[0], Y * unitsPerMeter2[1]];
2614
- }
2615
- unprojectFlat([x, y]) {
2616
- const { metersPerUnit } = this.distanceScales;
2617
- return [x * metersPerUnit[0], y * metersPerUnit[1]];
2618
- }
2619
- /* Needed by LinearInterpolator */
2620
- panByPosition(coords, pixel, startPixel) {
2621
- const fromLocation = (0, import_web_mercator5.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
2622
- const toLocation = this.projectFlat(coords);
2623
- const translate = import_core8.vec2.add([], toLocation, import_core8.vec2.negate([], fromLocation));
2624
- const newCenter = import_core8.vec2.add([], this.center, translate);
2625
- return { target: this.unprojectFlat(newCenter) };
2626
- }
2627
- };
2628
- OrthographicViewport.displayName = "OrthographicViewport";
2629
-
2630
- // ../core/src/controllers/orthographic-controller.ts
2631
- var import_core9 = require("@math.gl/core");
2632
- var ZOOM_RUBBER_BAND_RANGE = 1;
2633
- function normalizeZoom({
2634
- zoom = 0,
2635
- zoomX,
2636
- zoomY
2637
- }) {
2638
- zoomX = zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
2639
- zoomY = zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
2640
- return { zoomX, zoomY };
2641
- }
2642
- function getAxisBounds(maxBounds, index, negativeExtent, positiveExtent, target) {
2643
- const minimum = maxBounds[0][index] + negativeExtent;
2644
- const maximum = maxBounds[1][index] - positiveExtent;
2645
- const midpoint = (minimum + maximum) / 2;
2646
- return {
2647
- minimum,
2648
- maximum,
2649
- midpoint,
2650
- settledTarget: Number.isFinite(negativeExtent) && Number.isFinite(positiveExtent) && minimum <= maximum ? (0, import_core9.clamp)(target, minimum, maximum) : midpoint
2651
- };
2652
- }
2653
- var OrthographicState = class extends ViewState {
2654
- constructor(options) {
2655
- const {
2656
- /* Viewport arguments */
2657
- width,
2658
- // Width of viewport
2659
- height,
2660
- // Height of viewport
2661
- target = [0, 0, 0],
2662
- zoom = 0,
2663
- zoomAxis = "all",
2664
- /* Viewport constraints */
2665
- minZoom = -Infinity,
2666
- maxZoom = Infinity,
2667
- minZoomX = minZoom,
2668
- maxZoomX = maxZoom,
2669
- minZoomY = minZoom,
2670
- maxZoomY = maxZoom,
2671
- maxBounds = null,
2672
- maxBoundsPadding = null,
2673
- rubberBand = false,
2674
- /** Interaction states, required to calculate change during transform */
2675
- // Model state when the pan operation first started
2676
- startPanPosition,
2677
- // Model state when the zoom operation first started
2678
- startZoomPosition,
2679
- startZoom
2680
- } = options;
2681
- const { [CONSTRAINT_AROUND]: constraintAround } = options;
2682
- const { zoomX, zoomY } = normalizeZoom(options);
2683
- super(
2684
- {
2685
- width,
2686
- height,
2687
- target,
2688
- zoom,
2689
- zoomX,
2690
- zoomY,
2691
- zoomAxis,
2692
- minZoomX,
2693
- maxZoomX,
2694
- minZoomY,
2695
- maxZoomY,
2696
- maxBounds,
2697
- maxBoundsPadding,
2698
- rubberBand,
2699
- ...{ [CONSTRAINT_AROUND]: constraintAround }
2700
- },
2701
- {
2702
- startPanPosition,
2703
- startZoomPosition,
2704
- startZoom
2705
- },
2706
- options.makeViewport,
2707
- options.constraintContext
2708
- );
2709
- }
2710
- /**
2711
- * Start panning
2712
- * @param {[Number, Number]} pos - position on screen where the pointer grabs
2713
- */
2714
- panStart({ pos }, constraintContext) {
2715
- return this._getUpdatedState({ startPanPosition: this._unproject(pos) }, constraintContext);
2716
- }
2717
- /**
2718
- * Pan
2719
- * @param {[Number, Number]} pos - position on screen where the pointer is
2720
- */
2721
- pan({ pos, startPosition }, constraintContext) {
2722
- const startPanPosition = this.getState().startPanPosition || startPosition;
2723
- if (!startPanPosition) {
2724
- return this;
2725
- }
2726
- const viewport = this.makeViewport(this.getViewportProps());
2727
- const newProps = viewport.panByPosition(startPanPosition, pos);
2728
- return this._getUpdatedState(newProps, constraintContext);
2729
- }
2730
- /**
2731
- * End panning
2732
- * Must call if `panStart()` was called
2733
- */
2734
- panEnd(constraintContext) {
2735
- return this._getUpdatedState({ startPanPosition: null }, constraintContext);
2736
- }
2737
- /**
2738
- * Start rotating
2739
- */
2740
- rotateStart() {
2741
- return this;
2742
- }
2743
- /**
2744
- * Rotate
2745
- */
2746
- rotate() {
2747
- return this;
2748
- }
2749
- /**
2750
- * End rotating
2751
- */
2752
- rotateEnd() {
2753
- return this;
2754
- }
2755
- // shortest path between two view states
2756
- shortestPathFrom(viewState) {
2757
- const fromProps = viewState.getViewportProps();
2758
- const props = { ...this.getViewportProps() };
2759
- return props;
2760
- }
2761
- /**
2762
- * Start zooming
2763
- * @param {[Number, Number]} pos - position on screen where the pointer grabs
2764
- */
2765
- zoomStart({ pos }, constraintContext) {
2766
- const { zoomX, zoomY } = this.getViewportProps();
2767
- return this._getUpdatedState(
2768
- {
2769
- startZoomPosition: this._unproject(pos),
2770
- startZoom: [zoomX, zoomY]
2771
- },
2772
- constraintContext
2773
- );
2774
- }
2775
- /**
2776
- * Zoom
2777
- * @param {[Number, Number]} pos - position on screen where the current target is
2778
- * @param {[Number, Number]} startPos - the target position at
2779
- * the start of the operation. Must be supplied of `zoomStart()` was not called
2780
- * @param {Number} scale - a number between [0, 1] specifying the accumulated
2781
- * relative scale.
2782
- */
2783
- zoom({
2784
- pos,
2785
- startPos,
2786
- scale
2787
- }, constraintContext) {
2788
- let { startZoom, startZoomPosition } = this.getState();
2789
- if (!startZoomPosition) {
2790
- const { zoomX, zoomY } = this.getViewportProps();
2791
- startZoom = [zoomX, zoomY];
2792
- startZoomPosition = this._unproject(startPos || pos);
2793
- }
2794
- if (!startZoomPosition) {
2795
- return this;
2796
- }
2797
- const newZoomProps = this._calculateNewZoom({ scale, startZoom });
2798
- return this._getUpdatedState(
2799
- {
2800
- ...newZoomProps,
2801
- [CONSTRAINT_AROUND]: { position: startZoomPosition, screenPosition: pos }
2802
- },
2803
- constraintContext
2804
- );
2805
- }
2806
- /**
2807
- * End zooming
2808
- * Must call if `zoomStart()` was called
2809
- */
2810
- zoomEnd(constraintContext) {
2811
- return this._getUpdatedState(
2812
- {
2813
- startZoomPosition: null,
2814
- startZoom: null
2815
- },
2816
- constraintContext
2817
- );
2818
- }
2819
- zoomIn(speed = 2, constraintContext) {
2820
- return this._getUpdatedState(this._calculateNewZoom({ scale: speed }), constraintContext);
2821
- }
2822
- zoomOut(speed = 2, constraintContext) {
2823
- return this._getUpdatedState(this._calculateNewZoom({ scale: 1 / speed }), constraintContext);
2824
- }
2825
- moveLeft(speed = 50, constraintContext) {
2826
- return this._panFromCenter([-speed, 0], constraintContext);
2827
- }
2828
- moveRight(speed = 50, constraintContext) {
2829
- return this._panFromCenter([speed, 0], constraintContext);
2830
- }
2831
- moveUp(speed = 50, constraintContext) {
2832
- return this._panFromCenter([0, -speed], constraintContext);
2833
- }
2834
- moveDown(speed = 50, constraintContext) {
2835
- return this._panFromCenter([0, speed], constraintContext);
2836
- }
2837
- rotateLeft(speed = 15) {
2838
- return this;
2839
- }
2840
- rotateRight(speed = 15) {
2841
- return this;
2842
- }
2843
- rotateUp(speed = 10) {
2844
- return this;
2845
- }
2846
- rotateDown(speed = 10) {
2847
- return this;
2848
- }
2849
- /* Private methods */
2850
- _project(pos) {
2851
- const viewport = this.makeViewport(this.getViewportProps());
2852
- return viewport.project(pos);
2853
- }
2854
- _unproject(pos) {
2855
- const viewport = this.makeViewport(this.getViewportProps());
2856
- const [x, y] = viewport.unproject(pos);
2857
- return [x, y];
2858
- }
2859
- // Calculates new zoom
2860
- _calculateNewZoom({ scale, startZoom }) {
2861
- const { zoomX, zoomY, zoomAxis } = this.getViewportProps();
2862
- if (startZoom === void 0) {
2863
- startZoom = [zoomX, zoomY];
2864
- }
2865
- const deltaZoom = Math.log2(scale);
2866
- let [newZoomX, newZoomY] = startZoom;
2867
- switch (zoomAxis) {
2868
- case "X":
2869
- newZoomX += deltaZoom;
2870
- break;
2871
- case "Y":
2872
- newZoomY += deltaZoom;
2873
- break;
2874
- default:
2875
- newZoomX += deltaZoom;
2876
- newZoomY += deltaZoom;
2877
- }
2878
- return {
2879
- zoomX: newZoomX,
2880
- zoomY: newZoomY
2881
- };
2882
- }
2883
- _panFromCenter(offset3, constraintContext) {
2884
- const { target } = this.getViewportProps();
2885
- const center = this._project(target);
2886
- return this.pan(
2887
- {
2888
- startPosition: target,
2889
- pos: [center[0] + offset3[0], center[1] + offset3[1]]
2890
- },
2891
- constraintContext
2892
- );
2893
- }
2894
- _getUpdatedState(newProps, constraintContext) {
2895
- return new this.constructor({
2896
- makeViewport: this.makeViewport,
2897
- ...this.getViewportProps(),
2898
- ...this.getState(),
2899
- ...newProps,
2900
- constraintContext
2901
- });
2902
- }
2903
- // Apply any constraints (mathematical or defined by _viewportProps) to map state
2904
- applyConstraints(props, constraintContext) {
2905
- const internalProps = props;
2906
- const constraintAround = internalProps[CONSTRAINT_AROUND];
2907
- delete internalProps[CONSTRAINT_AROUND];
2908
- const normalizedZoom = normalizeZoom(props);
2909
- const constrainedZoom = this._constrainZoom(normalizedZoom, props);
2910
- const shouldRubberBand = props.rubberBand && (constraintContext == null ? void 0 : constraintContext.mode) === "elastic";
2911
- const { zoomX, zoomY } = (constraintContext == null ? void 0 : constraintContext.mode) === "preserve" ? normalizedZoom : shouldRubberBand ? {
2912
- zoomX: applyRubberBand(
2913
- normalizedZoom.zoomX,
2914
- constrainedZoom.zoomX,
2915
- ZOOM_RUBBER_BAND_RANGE
2916
- ),
2917
- zoomY: applyRubberBand(
2918
- normalizedZoom.zoomY,
2919
- constrainedZoom.zoomY,
2920
- ZOOM_RUBBER_BAND_RANGE
2921
- )
2922
- } : constrainedZoom;
2923
- props.zoomX = zoomX;
2924
- props.zoomY = zoomY;
2925
- if (constraintAround) {
2926
- const viewport = this.makeViewport({ ...props, zoomX, zoomY });
2927
- Object.assign(
2928
- props,
2929
- viewport.panByPosition(constraintAround.position, constraintAround.screenPosition)
2930
- );
2931
- }
2932
- props.zoom = Array.isArray(props.zoom) || props.zoomX !== props.zoomY ? [props.zoomX, props.zoomY] : props.zoomX;
2933
- const { maxBounds, rubberBand, target } = props;
2934
- if (maxBounds) {
2935
- const maxBoundsRect = getMaxBoundsRect(props.width, props.height, props.maxBoundsPadding);
2936
- const viewport = this.makeViewport(props);
2937
- const screenExtents = getMaxBoundsExtents(viewport, target, maxBoundsRect);
2938
- const projectedTarget = viewport.project(target);
2939
- const pixelsPerUnit = [0, 1].map((index) => {
2940
- const sampleTarget = target.slice();
2941
- sampleTarget[index] += 1;
2942
- const projectedDelta = viewport.project(sampleTarget)[index] - projectedTarget[index];
2943
- return Number.isFinite(projectedDelta) ? projectedDelta : 2 ** (index === 0 ? zoomX : zoomY) * (index === 0 ? 1 : -1);
2944
- });
2945
- const worldExtents = pixelsPerUnit.map((projectedDelta, index) => {
2946
- const negativeScreenExtent = index === 0 ? screenExtents.left : screenExtents.top;
2947
- const positiveScreenExtent = index === 0 ? screenExtents.right : screenExtents.bottom;
2948
- const scale = Math.abs(projectedDelta);
2949
- return projectedDelta >= 0 ? [negativeScreenExtent / scale, positiveScreenExtent / scale] : [positiveScreenExtent / scale, negativeScreenExtent / scale];
2950
- });
2951
- const constrainedTarget = target.slice();
2952
- const targetDimensions = [maxBoundsRect.width, maxBoundsRect.height];
2953
- for (const [index, [negativeExtent, positiveExtent]] of worldExtents.entries()) {
2954
- if (targetDimensions[index] < 0) {
2955
- continue;
2956
- }
2957
- const { minimum, maximum, midpoint, settledTarget } = getAxisBounds(
2958
- maxBounds,
2959
- index,
2960
- negativeExtent,
2961
- positiveExtent,
2962
- target[index]
2963
- );
2964
- if ((constraintContext == null ? void 0 : constraintContext.mode) !== "preserve" && rubberBand && (!Number.isFinite(negativeExtent) || !Number.isFinite(positiveExtent))) {
2965
- constrainedTarget[index] = midpoint;
2966
- continue;
2967
- }
2968
- const constrained = rubberBand ? settledTarget : (0, import_core9.clamp)(target[index], minimum, maximum);
2969
- constrainedTarget[index] = (constraintContext == null ? void 0 : constraintContext.mode) === "preserve" ? target[index] : shouldRubberBand ? applyRubberBand(
2970
- target[index],
2971
- constrained,
2972
- (index === 0 ? maxBoundsRect.width : maxBoundsRect.height) / 2 / Math.abs(pixelsPerUnit[index])
2973
- ) : constrained;
2974
- }
2975
- if (constrainedTarget[0] !== target[0] || constrainedTarget[1] !== target[1]) {
2976
- props.target = constrainedTarget;
2977
- }
2978
- }
2979
- return props;
2980
- }
2981
- _constrainZoom({ zoomX, zoomY }, props) {
2982
- props ||= this.getViewportProps();
2983
- const { zoomAxis, maxZoomX, maxZoomY, maxBounds } = props;
2984
- let { minZoomX, minZoomY } = props;
2985
- const shouldApplyMaxBounds = maxBounds !== null && props.width > 0 && props.height > 0;
2986
- if (shouldApplyMaxBounds) {
2987
- const maxBoundsRect = getMaxBoundsRect(props.width, props.height, props.maxBoundsPadding);
2988
- const bl = maxBounds[0];
2989
- const tr = maxBounds[1];
2990
- const w = tr[0] - bl[0];
2991
- const h = tr[1] - bl[1];
2992
- if (maxBoundsRect.width > 0 && Number.isFinite(w) && w > 0) {
2993
- minZoomX = Math.max(minZoomX, Math.log2(maxBoundsRect.width / w));
2994
- if (minZoomX > maxZoomX) minZoomX = maxZoomX;
2995
- }
2996
- if (maxBoundsRect.height > 0 && Number.isFinite(h) && h > 0) {
2997
- minZoomY = Math.max(minZoomY, Math.log2(maxBoundsRect.height / h));
2998
- if (minZoomY > maxZoomY) minZoomY = maxZoomY;
2999
- }
3000
- }
3001
- switch (zoomAxis) {
3002
- case "X":
3003
- zoomX = (0, import_core9.clamp)(zoomX, minZoomX, maxZoomX);
3004
- break;
3005
- case "Y":
3006
- zoomY = (0, import_core9.clamp)(zoomY, minZoomY, maxZoomY);
3007
- break;
3008
- default:
3009
- let delta = Math.min(maxZoomX - zoomX, maxZoomY - zoomY, 0);
3010
- if (delta === 0) {
3011
- delta = Math.max(minZoomX - zoomX, minZoomY - zoomY, 0);
3012
- }
3013
- if (delta !== 0) {
3014
- zoomX += delta;
3015
- zoomY += delta;
3016
- }
3017
- }
3018
- return { zoomX, zoomY };
3019
- }
3020
- };
3021
- var OrthographicController = class extends Controller {
3022
- constructor() {
3023
- super(...arguments);
3024
- this.ControllerState = OrthographicState;
3025
- this.transition = {
3026
- transitionDuration: 300,
3027
- transitionInterpolator: new LinearInterpolator(["target", "zoomX", "zoomY"])
3028
- };
3029
- this.dragMode = "pan";
3030
- }
3031
- setProps(props) {
3032
- Object.assign(props, normalizeZoom(props));
3033
- super.setProps(props);
3034
- }
3035
- _onMultiPanStart(event) {
3036
- return this.multiTouchDrag === "pan" && super._onMultiPanStart(event);
3037
- }
3038
- _onPanRotate() {
3039
- return false;
3040
- }
3041
- };
3042
-
3043
- // ../core/src/views/orthographic-view.ts
3044
- var OrthographicView = class extends View {
3045
- constructor(props = {}) {
3046
- super(props);
3047
- }
3048
- getViewportType() {
3049
- return OrthographicViewport;
3050
- }
3051
- get ControllerType() {
3052
- return OrthographicController;
3053
- }
3054
- };
3055
- OrthographicView.displayName = "OrthographicView";
3056
-
3057
- // ../core/src/transitions/fly-to-interpolator.ts
3058
- var import_core10 = require("@math.gl/core");
3059
- var import_web_mercator6 = require("@math.gl/web-mercator");
3060
- var LINEARLY_INTERPOLATED_PROPS = {
3061
- bearing: 0,
3062
- pitch: 0,
3063
- position: [0, 0, 0]
3064
- };
3065
- var DEFAULT_OPTS = {
3066
- speed: 1.2,
3067
- curve: 1.414
3068
- };
3069
- var FlyToInterpolator = class extends TransitionInterpolator {
3070
- constructor(opts = {}) {
3071
- super({
3072
- compare: ["longitude", "latitude", "zoom", "bearing", "pitch", "position"],
3073
- extract: ["width", "height", "longitude", "latitude", "zoom", "bearing", "pitch", "position"],
3074
- required: ["width", "height", "latitude", "longitude", "zoom"]
3075
- });
3076
- this.opts = { ...DEFAULT_OPTS, ...opts };
3077
- }
3078
- interpolateProps(startProps, endProps, t) {
3079
- const viewport = (0, import_web_mercator6.flyToViewport)(startProps, endProps, t, this.opts);
3080
- for (const key in LINEARLY_INTERPOLATED_PROPS) {
3081
- viewport[key] = (0, import_core10.lerp)(
3082
- startProps[key] || LINEARLY_INTERPOLATED_PROPS[key],
3083
- endProps[key] || LINEARLY_INTERPOLATED_PROPS[key],
3084
- t
3085
- );
3086
- }
3087
- return viewport;
3088
- }
3089
- // computes the transition duration
3090
- getDuration(startProps, endProps) {
3091
- let { transitionDuration } = endProps;
3092
- if (transitionDuration === "auto") {
3093
- transitionDuration = (0, import_web_mercator6.getFlyToDuration)(startProps, endProps, this.opts);
3094
- }
3095
- return transitionDuration;
3096
- }
3097
- };
3098
-
3099
- // dist/zoom-widget.js
63
+ var import_core = require("@deck.gl/core");
3100
64
  var import_preact = require("preact");
3101
65
 
3102
66
  // dist/lib/components/button-group.js
@@ -3198,7 +162,7 @@ var IconButton = (props) => {
3198
162
  };
3199
163
 
3200
164
  // dist/zoom-widget.js
3201
- var ZoomWidget = class extends Widget {
165
+ var ZoomWidget = class extends import_core.Widget {
3202
166
  constructor(props = {}) {
3203
167
  super(props);
3204
168
  this.className = "deck-widget-zoom";
@@ -3217,7 +181,7 @@ var ZoomWidget = class extends Widget {
3217
181
  isOrthographicView(viewId) {
3218
182
  const deck = this.deck;
3219
183
  const view = (deck == null ? void 0 : deck.isInitialized) && deck.getView(viewId);
3220
- return view instanceof OrthographicView;
184
+ return view instanceof import_core.OrthographicView;
3221
185
  }
3222
186
  handleZoom(viewId, delta) {
3223
187
  var _a, _b, _c, _d;
@@ -3229,13 +193,13 @@ var ZoomWidget = class extends Widget {
3229
193
  let nextZoom;
3230
194
  let nextZoomY;
3231
195
  if (zoomAxis === "X") {
3232
- nextZoom = clamp5(zoomX + delta, minZoomX, maxZoomX);
196
+ nextZoom = clamp(zoomX + delta, minZoomX, maxZoomX);
3233
197
  nextZoomY = zoomY;
3234
198
  } else if (zoomAxis === "Y") {
3235
199
  nextZoom = zoomX;
3236
- nextZoomY = clamp5(zoomY + delta, minZoomY, maxZoomY);
200
+ nextZoomY = clamp(zoomY + delta, minZoomY, maxZoomY);
3237
201
  } else {
3238
- const clampedDelta = clamp5(delta, Math.max(minZoomX - zoomX, minZoomY - zoomY), Math.min(maxZoomX - zoomX, maxZoomY - zoomY));
202
+ const clampedDelta = clamp(delta, Math.max(minZoomX - zoomX, minZoomY - zoomY), Math.min(maxZoomX - zoomX, maxZoomY - zoomY));
3239
203
  nextZoom = zoomX + clampedDelta;
3240
204
  nextZoomY = zoomY + clampedDelta;
3241
205
  }
@@ -3252,7 +216,7 @@ var ZoomWidget = class extends Widget {
3252
216
  });
3253
217
  } else {
3254
218
  const { zoom = 0, minZoom, maxZoom } = viewState;
3255
- const nextZoom = clamp5(zoom + delta, minZoom, maxZoom);
219
+ const nextZoom = clamp(zoom + delta, minZoom, maxZoom);
3256
220
  newViewState.zoom = nextZoom;
3257
221
  (_d = (_c = this.props).onZoom) == null ? void 0 : _d.call(_c, {
3258
222
  viewId,
@@ -3266,7 +230,7 @@ var ZoomWidget = class extends Widget {
3266
230
  };
3267
231
  if (this.props.transitionDuration > 0) {
3268
232
  nextViewState.transitionDuration = this.props.transitionDuration;
3269
- nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator({
233
+ nextViewState.transitionInterpolator = "latitude" in nextViewState ? new import_core.FlyToInterpolator() : new import_core.LinearInterpolator({
3270
234
  transitionProps: "zoomX" in newViewState ? ["zoomX", "zoomY"] : ["zoom"]
3271
235
  });
3272
236
  }
@@ -3284,7 +248,7 @@ var ZoomWidget = class extends Widget {
3284
248
  }
3285
249
  };
3286
250
  ZoomWidget.defaultProps = {
3287
- ...Widget.defaultProps,
251
+ ...import_core.Widget.defaultProps,
3288
252
  id: "zoom",
3289
253
  placement: "top-left",
3290
254
  orientation: "vertical",
@@ -3299,7 +263,7 @@ ZoomWidget.defaultProps = {
3299
263
  onZoom: () => {
3300
264
  }
3301
265
  };
3302
- function clamp5(zoom, minZoom, maxZoom) {
266
+ function clamp(zoom, minZoom, maxZoom) {
3303
267
  return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
3304
268
  }
3305
269
  function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Infinity, maxZoom = Infinity, minZoomX = minZoom, maxZoomX = maxZoom, minZoomY = minZoom, maxZoomY = maxZoom }) {
@@ -3311,7 +275,8 @@ function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Inf
3311
275
  // dist/reset-view-widget.js
3312
276
  var import_jsx_runtime5 = require("preact/jsx-runtime");
3313
277
  var import_preact2 = require("preact");
3314
- var ResetViewWidget = class extends Widget {
278
+ var import_core2 = require("@deck.gl/core");
279
+ var ResetViewWidget = class extends import_core2.Widget {
3315
280
  constructor(props = {}) {
3316
281
  super(props);
3317
282
  this.className = "deck-widget-reset-view";
@@ -3346,7 +311,7 @@ var ResetViewWidget = class extends Widget {
3346
311
  }
3347
312
  };
3348
313
  ResetViewWidget.defaultProps = {
3349
- ...Widget.defaultProps,
314
+ ...import_core2.Widget.defaultProps,
3350
315
  id: "reset-view",
3351
316
  placement: "top-left",
3352
317
  label: "Reset View",
@@ -3359,8 +324,9 @@ ResetViewWidget.defaultProps = {
3359
324
 
3360
325
  // dist/gimbal-widget.js
3361
326
  var import_jsx_runtime6 = require("preact/jsx-runtime");
327
+ var import_core3 = require("@deck.gl/core");
3362
328
  var import_preact3 = require("preact");
3363
- var GimbalWidget = class extends Widget {
329
+ var GimbalWidget = class extends import_core3.Widget {
3364
330
  constructor(props = {}) {
3365
331
  super(props);
3366
332
  this.className = "deck-widget-gimbal";
@@ -3411,7 +377,7 @@ var GimbalWidget = class extends Widget {
3411
377
  rotationOrbit: 0,
3412
378
  rotationX: 0,
3413
379
  transitionDuration: this.props.transitionDuration,
3414
- transitionInterpolator: new LinearInterpolator({
380
+ transitionInterpolator: new import_core3.LinearInterpolator({
3415
381
  transitionProps: ["rotationOrbit", "rotationX"]
3416
382
  })
3417
383
  };
@@ -3434,7 +400,7 @@ var GimbalWidget = class extends Widget {
3434
400
  }
3435
401
  };
3436
402
  GimbalWidget.defaultProps = {
3437
- ...Widget.defaultProps,
403
+ ...import_core3.Widget.defaultProps,
3438
404
  id: "gimbal",
3439
405
  placement: "top-left",
3440
406
  viewId: null,
@@ -3461,8 +427,9 @@ function normalizeAndClampAngle(angle) {
3461
427
 
3462
428
  // dist/compass-widget.js
3463
429
  var import_jsx_runtime7 = require("preact/jsx-runtime");
430
+ var import_core4 = require("@deck.gl/core");
3464
431
  var import_preact4 = require("preact");
3465
- var CompassWidget = class extends Widget {
432
+ var CompassWidget = class extends import_core4.Widget {
3466
433
  constructor(props = {}) {
3467
434
  super(props);
3468
435
  this.className = "deck-widget-compass";
@@ -3495,9 +462,9 @@ var CompassWidget = class extends Widget {
3495
462
  }
3496
463
  }
3497
464
  getRotation(viewport) {
3498
- if (viewport instanceof WebMercatorViewport) {
465
+ if (viewport instanceof import_core4.WebMercatorViewport) {
3499
466
  return [-viewport.bearing, viewport.pitch];
3500
- } else if (viewport instanceof GlobeViewport) {
467
+ } else if (viewport instanceof import_core4._GlobeViewport) {
3501
468
  return [0, Math.max(-80, Math.min(80, viewport.latitude))];
3502
469
  }
3503
470
  return [0, 0];
@@ -3505,7 +472,7 @@ var CompassWidget = class extends Widget {
3505
472
  handleCompassReset(viewport) {
3506
473
  var _a, _b;
3507
474
  const viewId = this.viewId || viewport.id;
3508
- if (viewport instanceof WebMercatorViewport) {
475
+ if (viewport instanceof import_core4.WebMercatorViewport) {
3509
476
  const viewState = this.getViewState(viewId);
3510
477
  const resetPitch = this.getRotation(viewport)[0] === 0;
3511
478
  const nextBearing = 0;
@@ -3516,14 +483,14 @@ var CompassWidget = class extends Widget {
3516
483
  bearing: nextBearing,
3517
484
  ...resetPitch ? { pitch: nextPitch } : {},
3518
485
  transitionDuration: this.props.transitionDuration,
3519
- transitionInterpolator: new FlyToInterpolator()
486
+ transitionInterpolator: new import_core4.FlyToInterpolator()
3520
487
  };
3521
488
  this.setViewState(viewId, nextViewState);
3522
489
  }
3523
490
  }
3524
491
  };
3525
492
  CompassWidget.defaultProps = {
3526
- ...Widget.defaultProps,
493
+ ...import_core4.Widget.defaultProps,
3527
494
  id: "compass",
3528
495
  placement: "top-left",
3529
496
  viewId: null,
@@ -3537,7 +504,8 @@ CompassWidget.defaultProps = {
3537
504
  // dist/scale-widget.js
3538
505
  var import_jsx_runtime8 = require("preact/jsx-runtime");
3539
506
  var import_preact5 = require("preact");
3540
- var ScaleWidget = class extends Widget {
507
+ var import_core5 = require("@deck.gl/core");
508
+ var ScaleWidget = class extends import_core5.Widget {
3541
509
  constructor(props = {}) {
3542
510
  super(props);
3543
511
  this.className = "deck-widget-scale";
@@ -3577,7 +545,7 @@ var ScaleWidget = class extends Widget {
3577
545
  }
3578
546
  };
3579
547
  ScaleWidget.defaultProps = {
3580
- ...Widget.defaultProps,
548
+ ...import_core5.Widget.defaultProps,
3581
549
  id: "scale",
3582
550
  placement: "bottom-left",
3583
551
  label: "Scale",
@@ -3620,6 +588,8 @@ function computeScaleCandidate(metersPerPixel) {
3620
588
 
3621
589
  // dist/geocoder-widget.js
3622
590
  var import_jsx_runtime10 = require("preact/jsx-runtime");
591
+ var import_core6 = require("@deck.gl/core");
592
+ var import_core7 = require("@deck.gl/core");
3623
593
  var import_preact6 = require("preact");
3624
594
 
3625
595
  // dist/lib/components/dropdown-menu.js
@@ -3874,7 +844,7 @@ var CURRENT_LOCATION_ITEM = {
3874
844
  value: CURRENT_LOCATION2,
3875
845
  icon: LOCATION_ICON
3876
846
  };
3877
- var GeocoderWidget = class extends Widget {
847
+ var GeocoderWidget = class extends import_core6.Widget {
3878
848
  constructor(props = {}) {
3879
849
  super(props);
3880
850
  this.className = "deck-widget-geocoder";
@@ -3976,14 +946,14 @@ var GeocoderWidget = class extends Widget {
3976
946
  };
3977
947
  if (this.props.transitionDuration > 0) {
3978
948
  nextViewState.transitionDuration = this.props.transitionDuration;
3979
- nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator();
949
+ nextViewState.transitionInterpolator = "latitude" in nextViewState ? new import_core7.FlyToInterpolator() : new import_core7.LinearInterpolator();
3980
950
  }
3981
951
  this.setViewState(viewId, nextViewState);
3982
952
  }
3983
953
  }
3984
954
  };
3985
955
  GeocoderWidget.defaultProps = {
3986
- ...Widget.defaultProps,
956
+ ...import_core6.Widget.defaultProps,
3987
957
  id: "geocoder",
3988
958
  viewId: null,
3989
959
  placement: "top-left",
@@ -4018,8 +988,9 @@ function getGeocoder(props) {
4018
988
 
4019
989
  // dist/fullscreen-widget.js
4020
990
  var import_jsx_runtime11 = require("preact/jsx-runtime");
991
+ var import_core8 = require("@deck.gl/core");
4021
992
  var import_preact7 = require("preact");
4022
- var FullscreenWidget = class extends Widget {
993
+ var FullscreenWidget = class extends import_core8.Widget {
4023
994
  constructor(props = {}) {
4024
995
  super(props);
4025
996
  this.className = "deck-widget-fullscreen";
@@ -4036,7 +1007,7 @@ var FullscreenWidget = class extends Widget {
4036
1007
  onRenderHTML(rootElement) {
4037
1008
  const isFullscreen = this.getFullscreen();
4038
1009
  (0, import_preact7.render)((0, import_jsx_runtime11.jsx)(IconButton, { onClick: () => {
4039
- this.handleClick().catch((err) => log_default.error(err)());
1010
+ this.handleClick().catch((err) => import_core8.log.error(err)());
4040
1011
  }, label: isFullscreen ? this.props.exitLabel : this.props.enterLabel, tooltip: isFullscreen ? this.props.exitTooltip : this.props.enterTooltip, className: isFullscreen ? "deck-widget-fullscreen-exit" : "deck-widget-fullscreen-enter" }), rootElement);
4041
1012
  }
4042
1013
  setProps(props) {
@@ -4092,7 +1063,7 @@ var FullscreenWidget = class extends Widget {
4092
1063
  }
4093
1064
  };
4094
1065
  FullscreenWidget.defaultProps = {
4095
- ...Widget.defaultProps,
1066
+ ...import_core8.Widget.defaultProps,
4096
1067
  id: "fullscreen",
4097
1068
  placement: "top-left",
4098
1069
  viewId: null,
@@ -4109,12 +1080,14 @@ FullscreenWidget.defaultProps = {
4109
1080
  var import_jsx_runtime12 = require("preact/jsx-runtime");
4110
1081
  var import_preact8 = require("preact");
4111
1082
  var import_hooks4 = require("preact/hooks");
1083
+ var import_core10 = require("@deck.gl/core");
4112
1084
 
4113
1085
  // dist/view-layout/view-layout.js
1086
+ var import_core9 = require("@deck.gl/core");
4114
1087
  var VIEW_LAYOUT_TYPES = /* @__PURE__ */ new Set(["row", "column", "overlay", "spacer"]);
4115
1088
  var VIEW_LAYOUT_ORIENTATIONS = /* @__PURE__ */ new Set(["horizontal", "vertical"]);
4116
1089
  function isViewLayout(child) {
4117
- return Boolean(child && typeof child === "object" && !(child instanceof View) && ("type" in child && VIEW_LAYOUT_TYPES.has(String(child.type)) || "orientation" in child && VIEW_LAYOUT_ORIENTATIONS.has(String(child.orientation))));
1090
+ return Boolean(child && typeof child === "object" && !(child instanceof import_core9.View) && ("type" in child && VIEW_LAYOUT_TYPES.has(String(child.type)) || "orientation" in child && VIEW_LAYOUT_ORIENTATIONS.has(String(child.orientation))));
4118
1091
  }
4119
1092
  function getViewLayoutType(item) {
4120
1093
  if ("orientation" in item) {
@@ -4164,7 +1137,7 @@ function assertViewLayoutChild(child) {
4164
1137
  assertViewLayout(child);
4165
1138
  return;
4166
1139
  }
4167
- if (child instanceof View) {
1140
+ if (child instanceof import_core9.View) {
4168
1141
  return;
4169
1142
  }
4170
1143
  throw new Error("ViewLayout children must be deck.gl View instances or layout objects.");
@@ -4666,7 +1639,7 @@ function evaluateViews(layout, viewLayouts, splitValues) {
4666
1639
  height: `${view.props.height}%`
4667
1640
  }));
4668
1641
  }
4669
- var SplitterWidget = class extends Widget {
1642
+ var SplitterWidget = class extends import_core10.Widget {
4670
1643
  constructor(props) {
4671
1644
  super(props);
4672
1645
  this.className = "deck-widget-splitter";
@@ -4676,7 +1649,7 @@ var SplitterWidget = class extends Widget {
4676
1649
  this.updateViewLayout(this.props.viewLayout);
4677
1650
  }
4678
1651
  setProps(props) {
4679
- if (props.viewLayout && !deepEqual(props.viewLayout, this.props.viewLayout, -1)) {
1652
+ if (props.viewLayout && !(0, import_core10._deepEqual)(props.viewLayout, this.props.viewLayout, -1)) {
4680
1653
  this.updateViewLayout(props.viewLayout);
4681
1654
  this.views = void 0;
4682
1655
  }
@@ -4728,7 +1701,7 @@ var SplitterWidget = class extends Widget {
4728
1701
  }
4729
1702
  };
4730
1703
  SplitterWidget.defaultProps = {
4731
- ...Widget.defaultProps,
1704
+ ...import_core10.Widget.defaultProps,
4732
1705
  id: "splitter-widget",
4733
1706
  viewLayout: void 0,
4734
1707
  onChange: () => {
@@ -4789,6 +1762,7 @@ function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit,
4789
1762
 
4790
1763
  // dist/info-widget.js
4791
1764
  var import_jsx_runtime15 = require("preact/jsx-runtime");
1765
+ var import_core11 = require("@deck.gl/core");
4792
1766
  var import_preact9 = require("preact");
4793
1767
 
4794
1768
  // dist/lib/components/popover.js
@@ -4903,7 +1877,7 @@ var UserContent = ({ text, html, element, ...props }) => {
4903
1877
  };
4904
1878
 
4905
1879
  // dist/info-widget.js
4906
- var InfoWidget = class extends Widget {
1880
+ var InfoWidget = class extends import_core11.Widget {
4907
1881
  constructor(props) {
4908
1882
  super(props);
4909
1883
  this.className = "deck-widget-info";
@@ -4974,7 +1948,7 @@ var InfoWidget = class extends Widget {
4974
1948
  }
4975
1949
  };
4976
1950
  InfoWidget.defaultProps = {
4977
- ...Widget.defaultProps,
1951
+ ...import_core11.Widget.defaultProps,
4978
1952
  id: "info",
4979
1953
  viewId: null,
4980
1954
  mode: "hover",
@@ -4986,8 +1960,9 @@ InfoWidget.defaultProps = {
4986
1960
 
4987
1961
  // dist/popup-widget.js
4988
1962
  var import_jsx_runtime16 = require("preact/jsx-runtime");
1963
+ var import_core12 = require("@deck.gl/core");
4989
1964
  var import_preact10 = require("preact");
4990
- var PopupWidget = class extends Widget {
1965
+ var PopupWidget = class extends import_core12.Widget {
4991
1966
  constructor(props) {
4992
1967
  super(props);
4993
1968
  this.className = "deck-widget-popup";
@@ -5036,7 +2011,7 @@ var PopupWidget = class extends Widget {
5036
2011
  }
5037
2012
  };
5038
2013
  PopupWidget.defaultProps = {
5039
- ...Widget.defaultProps,
2014
+ ...import_core12.Widget.defaultProps,
5040
2015
  id: "info",
5041
2016
  viewId: null,
5042
2017
  position: [0, 0],
@@ -5054,8 +2029,9 @@ PopupWidget.defaultProps = {
5054
2029
 
5055
2030
  // dist/context-menu-widget.js
5056
2031
  var import_jsx_runtime17 = require("preact/jsx-runtime");
2032
+ var import_core13 = require("@deck.gl/core");
5057
2033
  var import_preact11 = require("preact");
5058
- var ContextMenuWidget = class extends Widget {
2034
+ var ContextMenuWidget = class extends import_core13.Widget {
5059
2035
  constructor(props) {
5060
2036
  super(props);
5061
2037
  this.className = "deck-widget-context-menu";
@@ -5109,7 +2085,7 @@ var ContextMenuWidget = class extends Widget {
5109
2085
  }
5110
2086
  };
5111
2087
  ContextMenuWidget.defaultProps = {
5112
- ...Widget.defaultProps,
2088
+ ...import_core13.Widget.defaultProps,
5113
2089
  id: "context",
5114
2090
  viewId: null,
5115
2091
  menuItems: [],
@@ -5123,13 +2099,14 @@ ContextMenuWidget.defaultProps = {
5123
2099
 
5124
2100
  // dist/scrollbar-widget.js
5125
2101
  var import_jsx_runtime19 = require("preact/jsx-runtime");
2102
+ var import_core14 = require("@deck.gl/core");
5126
2103
  var import_preact12 = require("preact");
5127
2104
 
5128
2105
  // dist/lib/components/range-input.js
5129
2106
  var import_jsx_runtime18 = require("preact/jsx-runtime");
5130
2107
  var import_hooks7 = require("preact/hooks");
5131
2108
  var wheelListenerOptions = { passive: false };
5132
- var clamp6 = (value, min, max) => {
2109
+ var clamp2 = (value, min, max) => {
5133
2110
  if (value < min) {
5134
2111
  return min;
5135
2112
  }
@@ -5171,7 +2148,7 @@ function RangeInput(props) {
5171
2148
  const range = max - min;
5172
2149
  const rangeSize = Math.max(0, value[1] - value[0]);
5173
2150
  const maxStart = Math.max(0, range - rangeSize);
5174
- const clampedStart = clamp6(value[0], min, min + maxStart);
2151
+ const clampedStart = clamp2(value[0], min, min + maxStart);
5175
2152
  const { thumbLength, thumbOffset } = (0, import_hooks7.useMemo)(() => {
5176
2153
  if (trackLength <= 0 || range <= 0) {
5177
2154
  return { thumbLength: 0, thumbOffset: 0 };
@@ -5181,7 +2158,7 @@ function RangeInput(props) {
5181
2158
  }
5182
2159
  const nextThumbLength = rangeSize / range;
5183
2160
  const travel = Math.max(0, 1 - nextThumbLength);
5184
- const ratio = maxStart <= 0 ? 0 : clamp6((clampedStart - min) / maxStart, 0, 1);
2161
+ const ratio = maxStart <= 0 ? 0 : clamp2((clampedStart - min) / maxStart, 0, 1);
5185
2162
  return {
5186
2163
  thumbLength: Math.max(0, Math.min(nextThumbLength, 1)),
5187
2164
  thumbOffset: travel * ratio
@@ -5191,7 +2168,7 @@ function RangeInput(props) {
5191
2168
  if (!onChange) {
5192
2169
  return;
5193
2170
  }
5194
- const clamped = clamp6(nextStart, min, min + maxStart);
2171
+ const clamped = clamp2(nextStart, min, min + maxStart);
5195
2172
  onChange([clamped, clamped + rangeSize]);
5196
2173
  }, [onChange, min, maxStart, rangeSize]);
5197
2174
  const handleStepNegative = (0, import_hooks7.useCallback)((event) => {
@@ -5220,7 +2197,7 @@ function RangeInput(props) {
5220
2197
  const coordinate = vertical ? event.clientY - trackStart : event.clientX - trackStart;
5221
2198
  const span = Math.max(1, 1 - thumbLength) * trackLength;
5222
2199
  const thumbCenter = thumbLength / 2 * trackLength;
5223
- const ratio = span <= 0 ? 0 : clamp6((coordinate - thumbCenter) / span, 0, 1);
2200
+ const ratio = span <= 0 ? 0 : clamp2((coordinate - thumbCenter) / span, 0, 1);
5224
2201
  emitRange(min + ratio * maxStart);
5225
2202
  }, [vertical, trackLength, thumbLength, emitRange, min, maxStart]);
5226
2203
  const handleThumbPointerDown = (event) => {
@@ -5252,7 +2229,7 @@ function RangeInput(props) {
5252
2229
  const coordinate = vertical ? event.clientY : event.clientX;
5253
2230
  const delta = coordinate - state.startCoord;
5254
2231
  const ratio = state.startRatio + delta / trackLength2;
5255
- const nextStart = clamp6(ratio * (state.max - state.min), 0, state.maxStart) + state.min;
2232
+ const nextStart = clamp2(ratio * (state.max - state.min), 0, state.maxStart) + state.min;
5256
2233
  emitRange(nextStart);
5257
2234
  event.preventDefault();
5258
2235
  }, [emitRange, vertical]);
@@ -5383,7 +2360,7 @@ function RangeInput(props) {
5383
2360
  }
5384
2361
 
5385
2362
  // dist/scrollbar-widget.js
5386
- var clamp7 = (value, min, max) => {
2363
+ var clamp3 = (value, min, max) => {
5387
2364
  if (value < min) {
5388
2365
  return min;
5389
2366
  }
@@ -5392,7 +2369,7 @@ var clamp7 = (value, min, max) => {
5392
2369
  }
5393
2370
  return value;
5394
2371
  };
5395
- var ScrollbarWidget = class _ScrollbarWidget extends Widget {
2372
+ var ScrollbarWidget = class _ScrollbarWidget extends import_core14.Widget {
5396
2373
  constructor(props) {
5397
2374
  const resolved = {
5398
2375
  ..._ScrollbarWidget.defaultProps,
@@ -5454,7 +2431,7 @@ var ScrollbarWidget = class _ScrollbarWidget extends Widget {
5454
2431
  const contentBounds = this.getContentBounds(viewport.id);
5455
2432
  const isVertical = this.isVertical();
5456
2433
  const projectedBounds = contentBounds ? projectBounds(contentBounds, viewport, isVertical) : [0, 0];
5457
- const contentRect = getMaxBoundsRect(viewport.width, viewport.height, this.getContentBoundsPadding(viewport.id));
2434
+ const contentRect = (0, import_core14._getMaxBoundsRect)(viewport.width, viewport.height, this.getContentBoundsPadding(viewport.id));
5458
2435
  const contentStart = isVertical ? contentRect.y : contentRect.x;
5459
2436
  const viewportSize = isVertical ? contentRect.height : contentRect.width;
5460
2437
  this.contentSize = projectedBounds[1] - projectedBounds[0];
@@ -5506,7 +2483,7 @@ var ScrollbarWidget = class _ScrollbarWidget extends Widget {
5506
2483
  }
5507
2484
  getClampedOffset() {
5508
2485
  const maxScroll = this.getMaxScroll();
5509
- return clamp7(this.scrollOffset, 0, maxScroll);
2486
+ return clamp3(this.scrollOffset, 0, maxScroll);
5510
2487
  }
5511
2488
  isVertical() {
5512
2489
  return this.props.orientation !== "horizontal";
@@ -5525,7 +2502,7 @@ var ScrollbarWidget = class _ScrollbarWidget extends Widget {
5525
2502
  }
5526
2503
  emitScroll(next) {
5527
2504
  const maxScroll = this.getMaxScroll();
5528
- const target = clamp7(Math.round(next), 0, maxScroll);
2505
+ const target = clamp3(Math.round(next), 0, maxScroll);
5529
2506
  const viewport = this.viewport;
5530
2507
  if (viewport && target !== this.getClampedOffset()) {
5531
2508
  const pixel = viewport.project(viewport.position);
@@ -5547,7 +2524,7 @@ var ScrollbarWidget = class _ScrollbarWidget extends Widget {
5547
2524
  }
5548
2525
  };
5549
2526
  ScrollbarWidget.defaultProps = {
5550
- ...Widget.defaultProps,
2527
+ ...import_core14.Widget.defaultProps,
5551
2528
  contentBounds: null,
5552
2529
  contentBoundsPadding: null,
5553
2530
  placement: "top-right",
@@ -5572,7 +2549,8 @@ function projectBounds(bounds, viewport, isVertical) {
5572
2549
  // dist/icon-widget.js
5573
2550
  var import_jsx_runtime20 = require("preact/jsx-runtime");
5574
2551
  var import_preact13 = require("preact");
5575
- var IconWidget = class extends Widget {
2552
+ var import_core15 = require("@deck.gl/core");
2553
+ var IconWidget = class extends import_core15.Widget {
5576
2554
  constructor(props) {
5577
2555
  super(props);
5578
2556
  this.className = "";
@@ -5590,7 +2568,7 @@ var IconWidget = class extends Widget {
5590
2568
  }
5591
2569
  };
5592
2570
  IconWidget.defaultProps = {
5593
- ...Widget.defaultProps,
2571
+ ...import_core15.Widget.defaultProps,
5594
2572
  id: "icon",
5595
2573
  placement: "top-left",
5596
2574
  viewId: null,
@@ -5604,7 +2582,8 @@ IconWidget.defaultProps = {
5604
2582
  // dist/toggle-widget.js
5605
2583
  var import_jsx_runtime21 = require("preact/jsx-runtime");
5606
2584
  var import_preact14 = require("preact");
5607
- var ToggleWidget = class extends Widget {
2585
+ var import_core16 = require("@deck.gl/core");
2586
+ var ToggleWidget = class extends import_core16.Widget {
5608
2587
  constructor(props) {
5609
2588
  super(props);
5610
2589
  this.className = "deck-widget-toggle";
@@ -5631,7 +2610,7 @@ var ToggleWidget = class extends Widget {
5631
2610
  }
5632
2611
  };
5633
2612
  ToggleWidget.defaultProps = {
5634
- ...Widget.defaultProps,
2613
+ ...import_core16.Widget.defaultProps,
5635
2614
  id: "icon",
5636
2615
  placement: "top-left",
5637
2616
  viewId: null,
@@ -5650,7 +2629,8 @@ ToggleWidget.defaultProps = {
5650
2629
  // dist/selector-widget.js
5651
2630
  var import_jsx_runtime22 = require("preact/jsx-runtime");
5652
2631
  var import_preact15 = require("preact");
5653
- var SelectorWidget = class extends Widget {
2632
+ var import_core17 = require("@deck.gl/core");
2633
+ var SelectorWidget = class extends import_core17.Widget {
5654
2634
  constructor(props) {
5655
2635
  super(props);
5656
2636
  this.className = "deck-widget-selector";
@@ -5687,7 +2667,7 @@ var SelectorWidget = class extends Widget {
5687
2667
  }
5688
2668
  };
5689
2669
  SelectorWidget.defaultProps = {
5690
- ...Widget.defaultProps,
2670
+ ...import_core17.Widget.defaultProps,
5691
2671
  id: "view-selector",
5692
2672
  placement: "top-left",
5693
2673
  viewId: null,
@@ -5700,8 +2680,9 @@ SelectorWidget.defaultProps = {
5700
2680
 
5701
2681
  // dist/timeline-widget.js
5702
2682
  var import_jsx_runtime23 = require("preact/jsx-runtime");
2683
+ var import_core18 = require("@deck.gl/core");
5703
2684
  var import_preact16 = require("preact");
5704
- var TimelineWidget = class extends Widget {
2685
+ var TimelineWidget = class extends import_core18.Widget {
5705
2686
  /**
5706
2687
  * Returns the current time value.
5707
2688
  * In controlled mode, returns the time prop.
@@ -5857,7 +2838,7 @@ var TimelineWidget = class extends Widget {
5857
2838
  }
5858
2839
  };
5859
2840
  TimelineWidget.defaultProps = {
5860
- ...Widget.defaultProps,
2841
+ ...import_core18.Widget.defaultProps,
5861
2842
  id: "timeline",
5862
2843
  placement: "bottom-left",
5863
2844
  viewId: null,
@@ -5882,7 +2863,8 @@ TimelineWidget.defaultProps = {
5882
2863
  // dist/screenshot-widget.js
5883
2864
  var import_jsx_runtime24 = require("preact/jsx-runtime");
5884
2865
  var import_preact17 = require("preact");
5885
- var ScreenshotWidget = class extends Widget {
2866
+ var import_core19 = require("@deck.gl/core");
2867
+ var ScreenshotWidget = class extends import_core19.Widget {
5886
2868
  constructor(props = {}) {
5887
2869
  super(props);
5888
2870
  this.className = "deck-widget-screenshot";
@@ -5922,7 +2904,7 @@ var ScreenshotWidget = class extends Widget {
5922
2904
  }
5923
2905
  };
5924
2906
  ScreenshotWidget.defaultProps = {
5925
- ...Widget.defaultProps,
2907
+ ...import_core19.Widget.defaultProps,
5926
2908
  id: "screenshot",
5927
2909
  placement: "top-left",
5928
2910
  viewId: null,
@@ -5935,6 +2917,8 @@ ScreenshotWidget.defaultProps = {
5935
2917
 
5936
2918
  // dist/theme-widget.js
5937
2919
  var import_jsx_runtime25 = require("preact/jsx-runtime");
2920
+ var import_core20 = require("@deck.gl/core");
2921
+ var import_core21 = require("@deck.gl/core");
5938
2922
  var import_preact18 = require("preact");
5939
2923
 
5940
2924
  // dist/themes.js
@@ -6056,7 +3040,7 @@ var DarkGlassTheme = {
6056
3040
  };
6057
3041
 
6058
3042
  // dist/theme-widget.js
6059
- var ThemeWidget = class extends Widget {
3043
+ var ThemeWidget = class extends import_core21.Widget {
6060
3044
  constructor(props = {}) {
6061
3045
  super(props);
6062
3046
  this.className = "deck-widget-theme";
@@ -6099,16 +3083,16 @@ var ThemeWidget = class extends Widget {
6099
3083
  /** Apply theme styling without changing internal state */
6100
3084
  _applyTheme(themeMode, rootElement) {
6101
3085
  const themeStyle = themeMode === "dark" ? this.props.darkModeTheme : this.props.lightModeTheme;
6102
- if (deepEqual(themeStyle, this.appliedTheme, 1)) {
3086
+ if ((0, import_core20._deepEqual)(themeStyle, this.appliedTheme, 1)) {
6103
3087
  return;
6104
3088
  }
6105
3089
  const container = rootElement.closest(".deck-widget-container");
6106
3090
  if (!container)
6107
3091
  return;
6108
- applyStyles(container, themeStyle);
3092
+ (0, import_core20._applyStyles)(container, themeStyle);
6109
3093
  this.appliedTheme = themeStyle;
6110
3094
  const label = themeMode === "dark" ? this.props.darkModeLabel : this.props.lightModeLabel;
6111
- log_default.log(1, `Switched theme to ${label}`, themeStyle)();
3095
+ import_core20.log.log(1, `Switched theme to ${label}`, themeStyle)();
6112
3096
  }
6113
3097
  /** Read browser preference */
6114
3098
  _getInitialThemeMode() {
@@ -6123,7 +3107,7 @@ var ThemeWidget = class extends Widget {
6123
3107
  }
6124
3108
  };
6125
3109
  ThemeWidget.defaultProps = {
6126
- ...Widget.defaultProps,
3110
+ ...import_core21.Widget.defaultProps,
6127
3111
  id: "theme",
6128
3112
  placement: "top-left",
6129
3113
  viewId: null,
@@ -6142,7 +3126,8 @@ ThemeWidget.defaultProps = {
6142
3126
  // dist/loading-widget.js
6143
3127
  var import_jsx_runtime26 = require("preact/jsx-runtime");
6144
3128
  var import_preact19 = require("preact");
6145
- var LoadingWidget = class extends Widget {
3129
+ var import_core22 = require("@deck.gl/core");
3130
+ var LoadingWidget = class extends import_core22.Widget {
6146
3131
  constructor(props = {}) {
6147
3132
  super(props);
6148
3133
  this.className = "deck-widget-loading";
@@ -6176,7 +3161,7 @@ var LoadingWidget = class extends Widget {
6176
3161
  }
6177
3162
  };
6178
3163
  LoadingWidget.defaultProps = {
6179
- ...Widget.defaultProps,
3164
+ ...import_core22.Widget.defaultProps,
6180
3165
  id: "loading",
6181
3166
  placement: "top-left",
6182
3167
  viewId: null,
@@ -6188,7 +3173,8 @@ LoadingWidget.defaultProps = {
6188
3173
 
6189
3174
  // dist/stats-widget.js
6190
3175
  var import_jsx_runtime27 = require("preact/jsx-runtime");
6191
- var import_core34 = require("@luma.gl/core");
3176
+ var import_core23 = require("@deck.gl/core");
3177
+ var import_core24 = require("@luma.gl/core");
6192
3178
  var import_preact20 = require("preact");
6193
3179
  var import_hooks8 = require("preact/hooks");
6194
3180
  var DEFAULT_COUNT_FORMATTER = (stat) => `${stat.name}: ${stat.count}`;
@@ -6206,7 +3192,7 @@ var DEFAULT_FORMATTERS = {
6206
3192
  fps: (stat) => `${stat.name}: ${Math.round(stat.getHz())}fps`,
6207
3193
  memory: (stat) => `${stat.name}: ${formatMemory(stat.count)}`
6208
3194
  };
6209
- var StatsWidget = class extends Widget {
3195
+ var StatsWidget = class extends import_core23.Widget {
6210
3196
  /**
6211
3197
  * Returns the current expanded state.
6212
3198
  * In controlled mode, returns the expanded prop.
@@ -6296,7 +3282,7 @@ var StatsWidget = class extends Widget {
6296
3282
  const metrics = ((_a = this.deck) == null ? void 0 : _a.metrics) ?? {};
6297
3283
  return Object.entries(metrics);
6298
3284
  case "luma":
6299
- return Array.from(import_core34.luma.stats.stats.values())[0];
3285
+ return Array.from(import_core24.luma.stats.stats.values())[0];
6300
3286
  case "device":
6301
3287
  const device = (_b = this.deck) == null ? void 0 : _b.device;
6302
3288
  const stats = device == null ? void 0 : device.statsManager.stats.values();
@@ -6333,7 +3319,7 @@ var StatsWidget = class extends Widget {
6333
3319
  }
6334
3320
  };
6335
3321
  StatsWidget.defaultProps = {
6336
- ...Widget.defaultProps,
3322
+ ...import_core23.Widget.defaultProps,
6337
3323
  type: "deck",
6338
3324
  placement: "top-left",
6339
3325
  viewId: null,